@tscircuit/cli 0.1.1289 → 0.1.1291
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/build/build.worker.js +5 -2
- package/dist/cli/main.js +874 -597
- package/dist/lib/index.js +2 -1
- package/package.json +2 -1
package/dist/cli/main.js
CHANGED
|
@@ -60611,6 +60611,616 @@ var init_dist_VYXUNJDT = __esm(() => {
|
|
|
60611
60611
|
];
|
|
60612
60612
|
});
|
|
60613
60613
|
|
|
60614
|
+
// node_modules/circuit-json-trace-length-analysis/lib/analyze-circuit-json-trace-length.ts
|
|
60615
|
+
class Trace {
|
|
60616
|
+
id;
|
|
60617
|
+
label;
|
|
60618
|
+
connectionType;
|
|
60619
|
+
connectionTarget;
|
|
60620
|
+
connectionTargetPosition;
|
|
60621
|
+
connectedPins;
|
|
60622
|
+
pinPositions;
|
|
60623
|
+
requirements;
|
|
60624
|
+
points;
|
|
60625
|
+
lengthMm;
|
|
60626
|
+
straightLineDistanceMm;
|
|
60627
|
+
sourceTraceId;
|
|
60628
|
+
displayName;
|
|
60629
|
+
constructor(model) {
|
|
60630
|
+
this.id = model.id;
|
|
60631
|
+
this.label = model.label;
|
|
60632
|
+
this.connectionType = model.connectionType;
|
|
60633
|
+
this.connectionTarget = model.connectionTarget;
|
|
60634
|
+
this.connectionTargetPosition = model.connectionTargetPosition;
|
|
60635
|
+
this.connectedPins = model.connectedPins;
|
|
60636
|
+
this.pinPositions = model.pinPositions;
|
|
60637
|
+
this.requirements = model.requirements;
|
|
60638
|
+
this.points = model.points;
|
|
60639
|
+
this.lengthMm = model.lengthMm;
|
|
60640
|
+
this.straightLineDistanceMm = model.straightLineDistanceMm;
|
|
60641
|
+
this.sourceTraceId = model.sourceTraceId;
|
|
60642
|
+
this.displayName = model.displayName;
|
|
60643
|
+
}
|
|
60644
|
+
toString() {
|
|
60645
|
+
const lines = [
|
|
60646
|
+
`<Trace id="${escapeXml(this.id)}" label="${escapeXml(this.label)}" connectionType="${escapeXml(this.connectionType)}" lengthMm="${formatNumber3(this.lengthMm)}" straightLineDistanceMm="${formatNumber3(this.straightLineDistanceMm)}">`,
|
|
60647
|
+
` <ConnectedPins>`,
|
|
60648
|
+
...this.connectedPins.map((pin) => ` <Pin ref="${escapeXml(pin.ref)}" />`),
|
|
60649
|
+
` </ConnectedPins>`,
|
|
60650
|
+
` <PinPositions>`,
|
|
60651
|
+
...this.pinPositions.map((pin) => renderPinPosition(pin, " ")),
|
|
60652
|
+
` </PinPositions>`,
|
|
60653
|
+
renderConnection(this),
|
|
60654
|
+
renderRequirements(this.requirements, " "),
|
|
60655
|
+
`</Trace>`
|
|
60656
|
+
];
|
|
60657
|
+
if (this.points.length > 0) {
|
|
60658
|
+
lines.splice(lines.length - 1, 0, ` <Path>`, ...this.points.map((point5) => ` <Point x="${formatNumber3(point5.x)}" y="${formatNumber3(point5.y)}" layer="${escapeXml(point5.layer)}" kind="${escapeXml(point5.kind)}" />`), ` </Path>`);
|
|
60659
|
+
}
|
|
60660
|
+
return lines.join(`
|
|
60661
|
+
`);
|
|
60662
|
+
}
|
|
60663
|
+
}
|
|
60664
|
+
|
|
60665
|
+
class TraceLengthAnalysis {
|
|
60666
|
+
requestedTarget;
|
|
60667
|
+
resolvedTarget;
|
|
60668
|
+
targetKind;
|
|
60669
|
+
totalLengthMm;
|
|
60670
|
+
totalStraightLineDistanceMm;
|
|
60671
|
+
traceCount;
|
|
60672
|
+
#traces;
|
|
60673
|
+
constructor(args) {
|
|
60674
|
+
this.requestedTarget = args.requestedTarget;
|
|
60675
|
+
this.resolvedTarget = args.resolvedTarget;
|
|
60676
|
+
this.targetKind = args.targetKind;
|
|
60677
|
+
this.#traces = [...args.traces];
|
|
60678
|
+
this.totalLengthMm = this.#traces.reduce((sum, trace) => sum + trace.lengthMm, 0);
|
|
60679
|
+
this.totalStraightLineDistanceMm = this.#traces.reduce((sum, trace) => sum + trace.straightLineDistanceMm, 0);
|
|
60680
|
+
this.traceCount = this.#traces.length;
|
|
60681
|
+
}
|
|
60682
|
+
listTraces() {
|
|
60683
|
+
return [...this.#traces];
|
|
60684
|
+
}
|
|
60685
|
+
toString() {
|
|
60686
|
+
const lines = [
|
|
60687
|
+
`<TraceLengthAnalysis requestedTarget="${escapeXml(this.requestedTarget)}" resolvedTarget="${escapeXml(this.resolvedTarget)}" targetKind="${escapeXml(this.targetKind)}" traceCount="${this.traceCount}" totalLengthMm="${formatNumber3(this.totalLengthMm)}" totalStraightLineDistanceMm="${formatNumber3(this.totalStraightLineDistanceMm)}">`,
|
|
60688
|
+
...this.#traces.flatMap((trace) => trace.toString().split(`
|
|
60689
|
+
`).map((line2) => ` ${line2}`)),
|
|
60690
|
+
`</TraceLengthAnalysis>`
|
|
60691
|
+
];
|
|
60692
|
+
return lines.join(`
|
|
60693
|
+
`);
|
|
60694
|
+
}
|
|
60695
|
+
}
|
|
60696
|
+
function analyzeCircuitJsonTraceLength(circuitJson, options) {
|
|
60697
|
+
const index = new CircuitJsonIndex(circuitJson);
|
|
60698
|
+
const target = resolveTarget(index, options.targetPinOrNet);
|
|
60699
|
+
const traces = target.kind === "pin" ? collectPinTraces(index, target) : collectNetTraces(index, target);
|
|
60700
|
+
return new TraceLengthAnalysis({
|
|
60701
|
+
requestedTarget: target.requestedTarget,
|
|
60702
|
+
resolvedTarget: target.resolvedTarget,
|
|
60703
|
+
targetKind: target.kind,
|
|
60704
|
+
traces
|
|
60705
|
+
});
|
|
60706
|
+
}
|
|
60707
|
+
|
|
60708
|
+
class CircuitJsonIndex {
|
|
60709
|
+
componentsById = new Map;
|
|
60710
|
+
componentsByName = new Map;
|
|
60711
|
+
portsById = new Map;
|
|
60712
|
+
portsByComponentId = new Map;
|
|
60713
|
+
netsById = new Map;
|
|
60714
|
+
netsByName = new Map;
|
|
60715
|
+
pcbPortsBySourcePortId = new Map;
|
|
60716
|
+
pcbTracesBySourceTraceId = new Map;
|
|
60717
|
+
pcbTracesByConnectionName = new Map;
|
|
60718
|
+
tracesById = new Map;
|
|
60719
|
+
tracesByPortId = new Map;
|
|
60720
|
+
tracesByNetId = new Map;
|
|
60721
|
+
constructor(circuitJson) {
|
|
60722
|
+
for (const item of circuitJson) {
|
|
60723
|
+
switch (item.type) {
|
|
60724
|
+
case "source_component":
|
|
60725
|
+
this.addComponent(item);
|
|
60726
|
+
break;
|
|
60727
|
+
case "source_port":
|
|
60728
|
+
this.addPort(item);
|
|
60729
|
+
break;
|
|
60730
|
+
case "source_net":
|
|
60731
|
+
this.addNet(item);
|
|
60732
|
+
break;
|
|
60733
|
+
case "pcb_port":
|
|
60734
|
+
this.addPcbPort(item);
|
|
60735
|
+
break;
|
|
60736
|
+
case "pcb_trace":
|
|
60737
|
+
this.addPcbTrace(item);
|
|
60738
|
+
break;
|
|
60739
|
+
case "source_trace":
|
|
60740
|
+
this.addTrace(item);
|
|
60741
|
+
break;
|
|
60742
|
+
default:
|
|
60743
|
+
break;
|
|
60744
|
+
}
|
|
60745
|
+
}
|
|
60746
|
+
}
|
|
60747
|
+
getComponentByName(name) {
|
|
60748
|
+
return this.lookupWithCaseFallback(this.componentsByName, name);
|
|
60749
|
+
}
|
|
60750
|
+
getNetByName(name) {
|
|
60751
|
+
return this.lookupWithCaseFallback(this.netsByName, name);
|
|
60752
|
+
}
|
|
60753
|
+
getPcbPort(sourcePortId) {
|
|
60754
|
+
return this.pcbPortsBySourcePortId.get(sourcePortId)?.[0];
|
|
60755
|
+
}
|
|
60756
|
+
getPortPosition(sourcePortId) {
|
|
60757
|
+
const pcbPort = this.getPcbPort(sourcePortId);
|
|
60758
|
+
if (!pcbPort || typeof pcbPort.x !== "number" || typeof pcbPort.y !== "number") {
|
|
60759
|
+
return null;
|
|
60760
|
+
}
|
|
60761
|
+
const layers = normalizeLayers(pcbPort.layers);
|
|
60762
|
+
return {
|
|
60763
|
+
x: pcbPort.x,
|
|
60764
|
+
y: pcbPort.y,
|
|
60765
|
+
layers
|
|
60766
|
+
};
|
|
60767
|
+
}
|
|
60768
|
+
getPortReference(sourcePortId) {
|
|
60769
|
+
const port = this.portsById.get(sourcePortId);
|
|
60770
|
+
if (!port) {
|
|
60771
|
+
return sourcePortId;
|
|
60772
|
+
}
|
|
60773
|
+
const component = this.componentsById.get(port.source_component_id);
|
|
60774
|
+
const componentName = component?.name ?? port.source_component_id;
|
|
60775
|
+
const portName = port.name ?? String(port.pin_number ?? port.source_port_id);
|
|
60776
|
+
return `${componentName}.${portName}`;
|
|
60777
|
+
}
|
|
60778
|
+
getPcbPathPoints(sourceTraceId) {
|
|
60779
|
+
const candidates = dedupePcbTraces([
|
|
60780
|
+
...this.pcbTracesBySourceTraceId.get(sourceTraceId) ?? [],
|
|
60781
|
+
...this.pcbTracesByConnectionName.get(sourceTraceId) ?? []
|
|
60782
|
+
]);
|
|
60783
|
+
const pcbTraceIds = new Set(candidates.map((trace) => trace.pcb_trace_id));
|
|
60784
|
+
if (candidates.length === 0 || pcbTraceIds.size > 1) {
|
|
60785
|
+
return [];
|
|
60786
|
+
}
|
|
60787
|
+
const routePoints = candidates.flatMap((trace) => normalizePcbTraceRoute(trace));
|
|
60788
|
+
return convertPcbTraceRouteToPath(routePoints);
|
|
60789
|
+
}
|
|
60790
|
+
getConnectedPinsForNet(sourceNetId) {
|
|
60791
|
+
const traces = this.tracesByNetId.get(sourceNetId) ?? [];
|
|
60792
|
+
const sourcePortIds = new Set;
|
|
60793
|
+
for (const trace of traces) {
|
|
60794
|
+
for (const sourcePortId of trace.connected_source_port_ids ?? []) {
|
|
60795
|
+
sourcePortIds.add(sourcePortId);
|
|
60796
|
+
}
|
|
60797
|
+
}
|
|
60798
|
+
return [...sourcePortIds].map((sourcePortId) => this.toConnectedPin(sourcePortId));
|
|
60799
|
+
}
|
|
60800
|
+
toConnectedPin(sourcePortId) {
|
|
60801
|
+
const position2 = this.getPortPosition(sourcePortId);
|
|
60802
|
+
return {
|
|
60803
|
+
ref: this.getPortReference(sourcePortId),
|
|
60804
|
+
x: position2?.x ?? null,
|
|
60805
|
+
y: position2?.y ?? null,
|
|
60806
|
+
layers: position2?.layers ?? []
|
|
60807
|
+
};
|
|
60808
|
+
}
|
|
60809
|
+
addComponent(component) {
|
|
60810
|
+
this.componentsById.set(component.source_component_id, component);
|
|
60811
|
+
const name = component.name;
|
|
60812
|
+
if (!name) {
|
|
60813
|
+
return;
|
|
60814
|
+
}
|
|
60815
|
+
this.addLookup(this.componentsByName, name, component);
|
|
60816
|
+
}
|
|
60817
|
+
addPort(port) {
|
|
60818
|
+
this.portsById.set(port.source_port_id, port);
|
|
60819
|
+
this.addLookup(this.portsByComponentId, port.source_component_id, port);
|
|
60820
|
+
}
|
|
60821
|
+
addNet(net) {
|
|
60822
|
+
this.netsById.set(net.source_net_id, net);
|
|
60823
|
+
const name = net.name;
|
|
60824
|
+
if (!name) {
|
|
60825
|
+
return;
|
|
60826
|
+
}
|
|
60827
|
+
this.addLookup(this.netsByName, name, net);
|
|
60828
|
+
}
|
|
60829
|
+
addPcbPort(pcbPort) {
|
|
60830
|
+
this.addLookup(this.pcbPortsBySourcePortId, pcbPort.source_port_id, pcbPort);
|
|
60831
|
+
}
|
|
60832
|
+
addPcbTrace(pcbTrace) {
|
|
60833
|
+
if (pcbTrace.source_trace_id) {
|
|
60834
|
+
this.addLookup(this.pcbTracesBySourceTraceId, pcbTrace.source_trace_id, pcbTrace);
|
|
60835
|
+
}
|
|
60836
|
+
if (pcbTrace.connection_name) {
|
|
60837
|
+
this.addLookup(this.pcbTracesByConnectionName, pcbTrace.connection_name, pcbTrace);
|
|
60838
|
+
}
|
|
60839
|
+
}
|
|
60840
|
+
addTrace(trace) {
|
|
60841
|
+
this.tracesById.set(trace.source_trace_id, trace);
|
|
60842
|
+
for (const sourcePortId of trace.connected_source_port_ids ?? []) {
|
|
60843
|
+
this.addLookup(this.tracesByPortId, sourcePortId, trace);
|
|
60844
|
+
}
|
|
60845
|
+
for (const sourceNetId of trace.connected_source_net_ids ?? []) {
|
|
60846
|
+
this.addLookup(this.tracesByNetId, sourceNetId, trace);
|
|
60847
|
+
}
|
|
60848
|
+
}
|
|
60849
|
+
addLookup(map, key, value) {
|
|
60850
|
+
const existing = map.get(key) ?? [];
|
|
60851
|
+
existing.push(value);
|
|
60852
|
+
map.set(key, existing);
|
|
60853
|
+
}
|
|
60854
|
+
lookupWithCaseFallback(map, key) {
|
|
60855
|
+
const exactMatch = map.get(key);
|
|
60856
|
+
if (exactMatch?.length) {
|
|
60857
|
+
return exactMatch;
|
|
60858
|
+
}
|
|
60859
|
+
const loweredKey = key.toLowerCase();
|
|
60860
|
+
const fuzzyMatches = [];
|
|
60861
|
+
for (const [candidateKey, values] of map.entries()) {
|
|
60862
|
+
if (candidateKey.toLowerCase() === loweredKey) {
|
|
60863
|
+
fuzzyMatches.push(...values);
|
|
60864
|
+
}
|
|
60865
|
+
}
|
|
60866
|
+
return fuzzyMatches;
|
|
60867
|
+
}
|
|
60868
|
+
}
|
|
60869
|
+
function resolveTarget(index, targetPinOrNet) {
|
|
60870
|
+
if (targetPinOrNet.includes(".")) {
|
|
60871
|
+
if (targetPinOrNet.startsWith("net.")) {
|
|
60872
|
+
const netName = targetPinOrNet.slice("net.".length);
|
|
60873
|
+
const net = resolveNetByName(index, netName);
|
|
60874
|
+
return {
|
|
60875
|
+
kind: "net",
|
|
60876
|
+
requestedTarget: targetPinOrNet,
|
|
60877
|
+
resolvedTarget: `net.${net.name ?? net.source_net_id}`,
|
|
60878
|
+
net
|
|
60879
|
+
};
|
|
60880
|
+
}
|
|
60881
|
+
return resolvePinTarget(index, targetPinOrNet);
|
|
60882
|
+
}
|
|
60883
|
+
const matchingNet = resolveOptionalNetByName(index, targetPinOrNet);
|
|
60884
|
+
if (matchingNet) {
|
|
60885
|
+
const resolvedTarget = `net.${matchingNet.name ?? matchingNet.source_net_id}`;
|
|
60886
|
+
console.log(`inferring ${resolvedTarget}`);
|
|
60887
|
+
return {
|
|
60888
|
+
kind: "net",
|
|
60889
|
+
requestedTarget: targetPinOrNet,
|
|
60890
|
+
resolvedTarget,
|
|
60891
|
+
net: matchingNet
|
|
60892
|
+
};
|
|
60893
|
+
}
|
|
60894
|
+
const matchingPin = resolveOptionalPinByLabel(index, targetPinOrNet);
|
|
60895
|
+
if (matchingPin) {
|
|
60896
|
+
const resolvedTarget = index.getPortReference(matchingPin.source_port_id);
|
|
60897
|
+
console.log(`inferring ${resolvedTarget}`);
|
|
60898
|
+
return {
|
|
60899
|
+
kind: "pin",
|
|
60900
|
+
requestedTarget: targetPinOrNet,
|
|
60901
|
+
resolvedTarget,
|
|
60902
|
+
port: matchingPin
|
|
60903
|
+
};
|
|
60904
|
+
}
|
|
60905
|
+
throw new Error(`Unable to resolve target "${targetPinOrNet}" to a pin or net`);
|
|
60906
|
+
}
|
|
60907
|
+
function resolvePinTarget(index, targetPinOrNet) {
|
|
60908
|
+
const [componentName, ...pinParts] = targetPinOrNet.split(".");
|
|
60909
|
+
const pinLabelOrNumber = pinParts.join(".");
|
|
60910
|
+
if (!componentName || !pinLabelOrNumber) {
|
|
60911
|
+
throw new Error(`Invalid pin target "${targetPinOrNet}"`);
|
|
60912
|
+
}
|
|
60913
|
+
const components = index.getComponentByName(componentName);
|
|
60914
|
+
if (components.length !== 1) {
|
|
60915
|
+
throw new Error(components.length === 0 ? `Unable to find component "${componentName}"` : `Component "${componentName}" is ambiguous`);
|
|
60916
|
+
}
|
|
60917
|
+
const component = components[0];
|
|
60918
|
+
if (!component) {
|
|
60919
|
+
throw new Error(`Unable to find component "${componentName}"`);
|
|
60920
|
+
}
|
|
60921
|
+
const ports = index.portsByComponentId.get(component.source_component_id) ?? [];
|
|
60922
|
+
const matchingPorts = ports.filter((port2) => portMatchesLabel(port2, pinLabelOrNumber));
|
|
60923
|
+
if (matchingPorts.length !== 1) {
|
|
60924
|
+
throw new Error(matchingPorts.length === 0 ? `Unable to find pin "${pinLabelOrNumber}" on ${componentName}` : `Pin "${pinLabelOrNumber}" on ${componentName} is ambiguous`);
|
|
60925
|
+
}
|
|
60926
|
+
const port = matchingPorts[0];
|
|
60927
|
+
if (!port) {
|
|
60928
|
+
throw new Error(`Unable to find pin "${pinLabelOrNumber}" on ${componentName}`);
|
|
60929
|
+
}
|
|
60930
|
+
return {
|
|
60931
|
+
kind: "pin",
|
|
60932
|
+
requestedTarget: targetPinOrNet,
|
|
60933
|
+
resolvedTarget: index.getPortReference(port.source_port_id),
|
|
60934
|
+
port
|
|
60935
|
+
};
|
|
60936
|
+
}
|
|
60937
|
+
function resolveOptionalPinByLabel(index, pinLabelOrNumber) {
|
|
60938
|
+
const matchingPorts = [...index.portsById.values()].filter((port) => portMatchesLabel(port, pinLabelOrNumber));
|
|
60939
|
+
if (matchingPorts.length !== 1) {
|
|
60940
|
+
return null;
|
|
60941
|
+
}
|
|
60942
|
+
return matchingPorts[0] ?? null;
|
|
60943
|
+
}
|
|
60944
|
+
function resolveNetByName(index, netName) {
|
|
60945
|
+
const matchingNets = index.getNetByName(netName);
|
|
60946
|
+
if (matchingNets.length !== 1) {
|
|
60947
|
+
throw new Error(matchingNets.length === 0 ? `Unable to find net "${netName}"` : `Net "${netName}" is ambiguous`);
|
|
60948
|
+
}
|
|
60949
|
+
const net = matchingNets[0];
|
|
60950
|
+
if (!net) {
|
|
60951
|
+
throw new Error(`Unable to find net "${netName}"`);
|
|
60952
|
+
}
|
|
60953
|
+
return net;
|
|
60954
|
+
}
|
|
60955
|
+
function resolveOptionalNetByName(index, netName) {
|
|
60956
|
+
const matchingNets = index.getNetByName(netName);
|
|
60957
|
+
if (matchingNets.length !== 1) {
|
|
60958
|
+
return null;
|
|
60959
|
+
}
|
|
60960
|
+
return matchingNets[0] ?? null;
|
|
60961
|
+
}
|
|
60962
|
+
function collectPinTraces(index, target) {
|
|
60963
|
+
const traces = index.tracesByPortId.get(target.port.source_port_id) ?? [];
|
|
60964
|
+
return traces.flatMap((trace) => {
|
|
60965
|
+
const netIds = trace.connected_source_net_ids ?? [];
|
|
60966
|
+
if (netIds.length > 0) {
|
|
60967
|
+
return netIds.map((sourceNetId) => createNetTraceModel(index, {
|
|
60968
|
+
trace,
|
|
60969
|
+
sourceNetId,
|
|
60970
|
+
focusSourcePortId: target.port.source_port_id
|
|
60971
|
+
}));
|
|
60972
|
+
}
|
|
60973
|
+
return [
|
|
60974
|
+
createDirectTraceModel(index, {
|
|
60975
|
+
trace,
|
|
60976
|
+
focusSourcePortId: target.port.source_port_id
|
|
60977
|
+
})
|
|
60978
|
+
];
|
|
60979
|
+
}).sort(compareTraceModels).map((model) => new Trace(model));
|
|
60980
|
+
}
|
|
60981
|
+
function collectNetTraces(index, target) {
|
|
60982
|
+
const traces = index.tracesByNetId.get(target.net.source_net_id) ?? [];
|
|
60983
|
+
return traces.flatMap((trace) => {
|
|
60984
|
+
const connectedSourcePortIds = trace.connected_source_port_ids ?? [];
|
|
60985
|
+
if (connectedSourcePortIds.length === 0) {
|
|
60986
|
+
return [];
|
|
60987
|
+
}
|
|
60988
|
+
return connectedSourcePortIds.map((focusSourcePortId) => createNetTraceModel(index, {
|
|
60989
|
+
trace,
|
|
60990
|
+
sourceNetId: target.net.source_net_id,
|
|
60991
|
+
focusSourcePortId
|
|
60992
|
+
}));
|
|
60993
|
+
}).sort(compareTraceModels).map((model) => new Trace(model));
|
|
60994
|
+
}
|
|
60995
|
+
function createDirectTraceModel(index, args) {
|
|
60996
|
+
const connectedSourcePortIds = args.trace.connected_source_port_ids ?? [];
|
|
60997
|
+
if (connectedSourcePortIds.length === 0) {
|
|
60998
|
+
throw new Error(`Trace ${args.trace.source_trace_id} has no connected ports`);
|
|
60999
|
+
}
|
|
61000
|
+
const orderedPortIds = prioritizeFocus(connectedSourcePortIds, args.focusSourcePortId);
|
|
61001
|
+
const firstPortId = orderedPortIds[0];
|
|
61002
|
+
const secondPortId = orderedPortIds[1] ?? orderedPortIds[0];
|
|
61003
|
+
if (!firstPortId || !secondPortId) {
|
|
61004
|
+
throw new Error(`Trace ${args.trace.source_trace_id} is missing connected ports`);
|
|
61005
|
+
}
|
|
61006
|
+
const firstPosition = requirePortPosition(index, firstPortId);
|
|
61007
|
+
const secondPosition = requirePortPosition(index, secondPortId);
|
|
61008
|
+
const secondLayer = primaryLayer(secondPosition.layers);
|
|
61009
|
+
const connectedPins = orderedPortIds.map((sourcePortId) => index.toConnectedPin(sourcePortId));
|
|
61010
|
+
const connectionTarget4 = index.getPortReference(secondPortId);
|
|
61011
|
+
const straightLineDistanceMm = distanceBetween(firstPosition, secondPosition);
|
|
61012
|
+
const points = index.getPcbPathPoints(args.trace.source_trace_id);
|
|
61013
|
+
const lengthMm = points.length > 1 ? measurePathLength(points) : straightLineDistanceMm;
|
|
61014
|
+
return {
|
|
61015
|
+
id: args.trace.source_trace_id,
|
|
61016
|
+
label: `${index.getPortReference(firstPortId)} -> ${connectionTarget4}`,
|
|
61017
|
+
connectionType: "direct connection",
|
|
61018
|
+
connectionTarget: connectionTarget4,
|
|
61019
|
+
connectionTargetPosition: {
|
|
61020
|
+
x: secondPosition.x,
|
|
61021
|
+
y: secondPosition.y,
|
|
61022
|
+
layer: secondLayer
|
|
61023
|
+
},
|
|
61024
|
+
connectedPins,
|
|
61025
|
+
pinPositions: connectedPins,
|
|
61026
|
+
requirements: {
|
|
61027
|
+
maxLengthMm: typeof args.trace.max_length === "number" ? args.trace.max_length : null
|
|
61028
|
+
},
|
|
61029
|
+
points,
|
|
61030
|
+
lengthMm,
|
|
61031
|
+
straightLineDistanceMm,
|
|
61032
|
+
sourceTraceId: args.trace.source_trace_id,
|
|
61033
|
+
displayName: args.trace.display_name ?? null
|
|
61034
|
+
};
|
|
61035
|
+
}
|
|
61036
|
+
function createNetTraceModel(index, args) {
|
|
61037
|
+
const net = index.netsById.get(args.sourceNetId);
|
|
61038
|
+
if (!net) {
|
|
61039
|
+
throw new Error(`Unable to find net ${args.sourceNetId}`);
|
|
61040
|
+
}
|
|
61041
|
+
const focusPosition = requirePortPosition(index, args.focusSourcePortId);
|
|
61042
|
+
const focusLayer = primaryLayer(focusPosition.layers);
|
|
61043
|
+
const connectedPins = index.getConnectedPinsForNet(args.sourceNetId).sort((a2, b) => a2.ref.localeCompare(b.ref));
|
|
61044
|
+
const hub = inferNetHub(connectedPins, focusLayer);
|
|
61045
|
+
const focusPin = index.toConnectedPin(args.focusSourcePortId);
|
|
61046
|
+
const points = index.getPcbPathPoints(args.trace.source_trace_id);
|
|
61047
|
+
const straightLineDistanceMm = distanceBetween(focusPosition, hub);
|
|
61048
|
+
const lengthMm = points.length > 1 ? measurePathLength(points) : straightLineDistanceMm;
|
|
61049
|
+
return {
|
|
61050
|
+
id: `${args.trace.source_trace_id}:${args.focusSourcePortId}`,
|
|
61051
|
+
label: `${focusPin.ref} -> net.${net.name ?? net.source_net_id}`,
|
|
61052
|
+
connectionType: "via net",
|
|
61053
|
+
connectionTarget: `net.${net.name ?? net.source_net_id}`,
|
|
61054
|
+
connectionTargetPosition: hub,
|
|
61055
|
+
connectedPins: prioritizePin(focusPin, connectedPins),
|
|
61056
|
+
pinPositions: prioritizePin(focusPin, connectedPins),
|
|
61057
|
+
requirements: {
|
|
61058
|
+
maxLengthMm: typeof args.trace.max_length === "number" ? args.trace.max_length : null
|
|
61059
|
+
},
|
|
61060
|
+
points,
|
|
61061
|
+
lengthMm,
|
|
61062
|
+
straightLineDistanceMm,
|
|
61063
|
+
sourceTraceId: args.trace.source_trace_id,
|
|
61064
|
+
displayName: args.trace.display_name ?? null
|
|
61065
|
+
};
|
|
61066
|
+
}
|
|
61067
|
+
function requirePortPosition(index, sourcePortId) {
|
|
61068
|
+
const position2 = index.getPortPosition(sourcePortId);
|
|
61069
|
+
if (!position2) {
|
|
61070
|
+
throw new Error(`Unable to analyze ${index.getPortReference(sourcePortId)} because it has no pcb_port position`);
|
|
61071
|
+
}
|
|
61072
|
+
return position2;
|
|
61073
|
+
}
|
|
61074
|
+
function inferNetHub(connectedPins, fallbackLayer) {
|
|
61075
|
+
const positionedPins = connectedPins.filter((pin) => typeof pin.x === "number" && typeof pin.y === "number");
|
|
61076
|
+
if (positionedPins.length === 0) {
|
|
61077
|
+
return {
|
|
61078
|
+
x: 0,
|
|
61079
|
+
y: 0,
|
|
61080
|
+
layer: fallbackLayer
|
|
61081
|
+
};
|
|
61082
|
+
}
|
|
61083
|
+
const x3 = positionedPins.reduce((sum, pin) => sum + pin.x, 0) / positionedPins.length;
|
|
61084
|
+
const y4 = positionedPins.reduce((sum, pin) => sum + pin.y, 0) / positionedPins.length;
|
|
61085
|
+
const layerCounts = new Map;
|
|
61086
|
+
for (const pin of positionedPins) {
|
|
61087
|
+
const layer2 = pin.layers[0] ?? fallbackLayer;
|
|
61088
|
+
layerCounts.set(layer2, (layerCounts.get(layer2) ?? 0) + 1);
|
|
61089
|
+
}
|
|
61090
|
+
const sortedLayers = [...layerCounts.entries()].sort((left, right) => {
|
|
61091
|
+
if (right[1] !== left[1]) {
|
|
61092
|
+
return right[1] - left[1];
|
|
61093
|
+
}
|
|
61094
|
+
return left[0].localeCompare(right[0]);
|
|
61095
|
+
});
|
|
61096
|
+
const layer = sortedLayers[0]?.[0] ?? fallbackLayer;
|
|
61097
|
+
return { x: x3, y: y4, layer };
|
|
61098
|
+
}
|
|
61099
|
+
function measurePathLength(points) {
|
|
61100
|
+
let lengthMm = 0;
|
|
61101
|
+
for (let index = 1;index < points.length; index += 1) {
|
|
61102
|
+
const previous = points[index - 1];
|
|
61103
|
+
const current2 = points[index];
|
|
61104
|
+
if (!previous || !current2) {
|
|
61105
|
+
continue;
|
|
61106
|
+
}
|
|
61107
|
+
lengthMm += distanceBetween(previous, current2);
|
|
61108
|
+
}
|
|
61109
|
+
return lengthMm;
|
|
61110
|
+
}
|
|
61111
|
+
function dedupePcbTraces(pcbTraces) {
|
|
61112
|
+
const seen = new Set;
|
|
61113
|
+
const deduped = [];
|
|
61114
|
+
for (const pcbTrace of pcbTraces) {
|
|
61115
|
+
if (seen.has(pcbTrace)) {
|
|
61116
|
+
continue;
|
|
61117
|
+
}
|
|
61118
|
+
seen.add(pcbTrace);
|
|
61119
|
+
deduped.push(pcbTrace);
|
|
61120
|
+
}
|
|
61121
|
+
return deduped;
|
|
61122
|
+
}
|
|
61123
|
+
function normalizePcbTraceRoute(pcbTrace) {
|
|
61124
|
+
if (!Array.isArray(pcbTrace.route)) {
|
|
61125
|
+
return [];
|
|
61126
|
+
}
|
|
61127
|
+
return pcbTrace.route.filter((point5) => typeof point5.x === "number" && typeof point5.y === "number").map((point5) => ({
|
|
61128
|
+
...point5,
|
|
61129
|
+
layer: typeof point5.layer === "string" && point5.layer.length > 0 ? point5.layer : typeof pcbTrace.layer === "string" && pcbTrace.layer.length > 0 ? pcbTrace.layer : "top"
|
|
61130
|
+
}));
|
|
61131
|
+
}
|
|
61132
|
+
function convertPcbTraceRouteToPath(routePoints) {
|
|
61133
|
+
const deduped = routePoints.filter((point5, index) => {
|
|
61134
|
+
const previous = routePoints[index - 1];
|
|
61135
|
+
return !previous || previous.x !== point5.x || previous.y !== point5.y || previous.layer !== point5.layer;
|
|
61136
|
+
});
|
|
61137
|
+
return deduped.map((point5, index) => ({
|
|
61138
|
+
x: point5.x,
|
|
61139
|
+
y: point5.y,
|
|
61140
|
+
layer: point5.layer,
|
|
61141
|
+
kind: classifyPcbTracePoint(point5, index, deduped.length)
|
|
61142
|
+
}));
|
|
61143
|
+
}
|
|
61144
|
+
function classifyPcbTracePoint(point5, index, pointCount) {
|
|
61145
|
+
if (point5.route_type === "via") {
|
|
61146
|
+
return "via";
|
|
61147
|
+
}
|
|
61148
|
+
if (index === 0 || index === pointCount - 1 || point5.start_pcb_port_id || point5.end_pcb_port_id) {
|
|
61149
|
+
return "endpoint";
|
|
61150
|
+
}
|
|
61151
|
+
return "track";
|
|
61152
|
+
}
|
|
61153
|
+
function renderPinPosition(pin, indent) {
|
|
61154
|
+
if (typeof pin.x !== "number" || typeof pin.y !== "number") {
|
|
61155
|
+
return `${indent}<Pin ref="${escapeXml(pin.ref)}" position="unavailable" />`;
|
|
61156
|
+
}
|
|
61157
|
+
const layers = pin.layers.length > 0 ? pin.layers.join(",") : "unknown";
|
|
61158
|
+
return `${indent}<Pin ref="${escapeXml(pin.ref)}" x="${formatNumber3(pin.x)}" y="${formatNumber3(pin.y)}" layers="${escapeXml(layers)}" />`;
|
|
61159
|
+
}
|
|
61160
|
+
function renderConnection(trace) {
|
|
61161
|
+
if (trace.connectionTargetPosition) {
|
|
61162
|
+
return ` <Connection kind="${escapeXml(trace.connectionType)}" target="${escapeXml(trace.connectionTarget)}" x="${formatNumber3(trace.connectionTargetPosition.x)}" y="${formatNumber3(trace.connectionTargetPosition.y)}" layer="${escapeXml(trace.connectionTargetPosition.layer)}" />`;
|
|
61163
|
+
}
|
|
61164
|
+
return ` <Connection kind="${escapeXml(trace.connectionType)}" target="${escapeXml(trace.connectionTarget)}" />`;
|
|
61165
|
+
}
|
|
61166
|
+
function renderRequirements(requirements, indent) {
|
|
61167
|
+
if (typeof requirements.maxLengthMm === "number") {
|
|
61168
|
+
return [
|
|
61169
|
+
`${indent}<TraceRequirements>`,
|
|
61170
|
+
`${indent} <MaxLengthMm>${formatNumber3(requirements.maxLengthMm)}</MaxLengthMm>`,
|
|
61171
|
+
`${indent}</TraceRequirements>`
|
|
61172
|
+
].join(`
|
|
61173
|
+
`);
|
|
61174
|
+
}
|
|
61175
|
+
return `${indent}<TraceRequirements none />`;
|
|
61176
|
+
}
|
|
61177
|
+
function portMatchesLabel(port, label) {
|
|
61178
|
+
const loweredLabel = label.toLowerCase();
|
|
61179
|
+
const portName = port.name?.toLowerCase();
|
|
61180
|
+
const pinNumber = String(port.pin_number ?? "").toLowerCase();
|
|
61181
|
+
const portHints2 = (port.port_hints ?? []).map((hint) => hint.toLowerCase());
|
|
61182
|
+
return portName === loweredLabel || pinNumber === loweredLabel || portHints2.includes(loweredLabel);
|
|
61183
|
+
}
|
|
61184
|
+
function prioritizeFocus(portIds, focusSourcePortId) {
|
|
61185
|
+
const remainder = portIds.filter((portId) => portId !== focusSourcePortId);
|
|
61186
|
+
return [focusSourcePortId, ...remainder];
|
|
61187
|
+
}
|
|
61188
|
+
function prioritizePin(focusPin, pins) {
|
|
61189
|
+
const remainder = pins.filter((pin) => pin.ref !== focusPin.ref);
|
|
61190
|
+
return [focusPin, ...remainder];
|
|
61191
|
+
}
|
|
61192
|
+
function compareTraceModels(left, right) {
|
|
61193
|
+
return left.label.localeCompare(right.label);
|
|
61194
|
+
}
|
|
61195
|
+
function normalizeLayers(layers) {
|
|
61196
|
+
if (!Array.isArray(layers)) {
|
|
61197
|
+
return ["top"];
|
|
61198
|
+
}
|
|
61199
|
+
const normalizedLayers = layers.filter((layer) => typeof layer === "string" && layer.length > 0);
|
|
61200
|
+
return normalizedLayers.length > 0 ? normalizedLayers : ["top"];
|
|
61201
|
+
}
|
|
61202
|
+
function primaryLayer(layers) {
|
|
61203
|
+
return layers[0] ?? "top";
|
|
61204
|
+
}
|
|
61205
|
+
function distanceBetween(left, right) {
|
|
61206
|
+
return Math.hypot(right.x - left.x, right.y - left.y);
|
|
61207
|
+
}
|
|
61208
|
+
function formatNumber3(value) {
|
|
61209
|
+
return value.toFixed(2);
|
|
61210
|
+
}
|
|
61211
|
+
function escapeXml(value) {
|
|
61212
|
+
return value.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">");
|
|
61213
|
+
}
|
|
61214
|
+
|
|
61215
|
+
// node_modules/circuit-json-trace-length-analysis/lib/index.ts
|
|
61216
|
+
var exports_lib = {};
|
|
61217
|
+
__export2(exports_lib, {
|
|
61218
|
+
analyzeCircuitJsonTraceLength: () => analyzeCircuitJsonTraceLength,
|
|
61219
|
+
TraceLengthAnalysis: () => TraceLengthAnalysis,
|
|
61220
|
+
Trace: () => Trace
|
|
61221
|
+
});
|
|
61222
|
+
var init_lib = () => {};
|
|
61223
|
+
|
|
60614
61224
|
// node_modules/@edge-runtime/node-utils/dist/index.js
|
|
60615
61225
|
var require_dist5 = __commonJS((exports2, module2) => {
|
|
60616
61226
|
var __filename = "/home/runner/work/cli/cli/node_modules/@edge-runtime/node-utils/dist/index.js";
|
|
@@ -99964,7 +100574,7 @@ var import_perfect_cli = __toESM2(require_dist2(), 1);
|
|
|
99964
100574
|
// lib/getVersion.ts
|
|
99965
100575
|
import { createRequire as createRequire2 } from "node:module";
|
|
99966
100576
|
// package.json
|
|
99967
|
-
var version = "0.1.
|
|
100577
|
+
var version = "0.1.1290";
|
|
99968
100578
|
var package_default = {
|
|
99969
100579
|
name: "@tscircuit/cli",
|
|
99970
100580
|
version,
|
|
@@ -99978,6 +100588,7 @@ var package_default = {
|
|
|
99978
100588
|
"@biomejs/biome": "^1.9.4",
|
|
99979
100589
|
"@tscircuit/circuit-json-placement-analysis": "^0.0.6",
|
|
99980
100590
|
"@tscircuit/circuit-json-routing-analysis": "^0.0.1",
|
|
100591
|
+
"@tscircuit/circuit-json-schematic-placement-analysis": "github:tscircuit/circuit-json-schematic-placement-analysis#d09c8d74f3085b29744bb0f1c9864c1154c69436",
|
|
99981
100592
|
"@tscircuit/fake-snippets": "^0.0.182",
|
|
99982
100593
|
"@tscircuit/file-server": "^0.0.32",
|
|
99983
100594
|
"@tscircuit/image-utils": "^0.0.3",
|
|
@@ -109908,7 +110519,10 @@ var buildPreviewGltf = async ({
|
|
|
109908
110519
|
// cli/build/build-preview-images.ts
|
|
109909
110520
|
import fs30 from "node:fs";
|
|
109910
110521
|
import path32 from "node:path";
|
|
109911
|
-
import {
|
|
110522
|
+
import {
|
|
110523
|
+
convertCircuitJsonToGltf as convertCircuitJsonToGltf3,
|
|
110524
|
+
getBestCameraPosition
|
|
110525
|
+
} from "circuit-json-to-gltf";
|
|
109912
110526
|
import {
|
|
109913
110527
|
convertCircuitJsonToPcbSvg,
|
|
109914
110528
|
convertCircuitJsonToSchematicSvg
|
|
@@ -110015,7 +110629,7 @@ var generatePreviewAssets = async ({
|
|
|
110015
110629
|
const glbBuffer = await convertCircuitJsonToGltf3(circuitJsonWithFileUrls, getCircuitJsonToGltfOptions({ format: "glb" }));
|
|
110016
110630
|
console.log(`${prefix}Rendering GLB to PNG buffer...`);
|
|
110017
110631
|
const glbArrayBuffer = await normalizeToArrayBuffer(glbBuffer);
|
|
110018
|
-
const pngBuffer = await renderGLTFToPNGBufferFromGLBBuffer(glbArrayBuffer);
|
|
110632
|
+
const pngBuffer = await renderGLTFToPNGBufferFromGLBBuffer(glbArrayBuffer, getBestCameraPosition(circuitJson));
|
|
110019
110633
|
fs30.writeFileSync(path32.join(outputDir, "3d.png"), Buffer.from(normalizeToUint8Array2(pngBuffer)));
|
|
110020
110634
|
console.log(`${prefix}Written 3d.png`);
|
|
110021
110635
|
} catch (error) {
|
|
@@ -240617,607 +241231,268 @@ var registerCheckRouting = (program2) => {
|
|
|
240617
241231
|
});
|
|
240618
241232
|
};
|
|
240619
241233
|
|
|
240620
|
-
// node_modules/circuit-json-
|
|
240621
|
-
|
|
240622
|
-
id;
|
|
240623
|
-
label;
|
|
240624
|
-
connectionType;
|
|
240625
|
-
connectionTarget;
|
|
240626
|
-
connectionTargetPosition;
|
|
240627
|
-
connectedPins;
|
|
240628
|
-
pinPositions;
|
|
240629
|
-
requirements;
|
|
240630
|
-
points;
|
|
240631
|
-
lengthMm;
|
|
240632
|
-
straightLineDistanceMm;
|
|
240633
|
-
sourceTraceId;
|
|
240634
|
-
displayName;
|
|
240635
|
-
constructor(model) {
|
|
240636
|
-
this.id = model.id;
|
|
240637
|
-
this.label = model.label;
|
|
240638
|
-
this.connectionType = model.connectionType;
|
|
240639
|
-
this.connectionTarget = model.connectionTarget;
|
|
240640
|
-
this.connectionTargetPosition = model.connectionTargetPosition;
|
|
240641
|
-
this.connectedPins = model.connectedPins;
|
|
240642
|
-
this.pinPositions = model.pinPositions;
|
|
240643
|
-
this.requirements = model.requirements;
|
|
240644
|
-
this.points = model.points;
|
|
240645
|
-
this.lengthMm = model.lengthMm;
|
|
240646
|
-
this.straightLineDistanceMm = model.straightLineDistanceMm;
|
|
240647
|
-
this.sourceTraceId = model.sourceTraceId;
|
|
240648
|
-
this.displayName = model.displayName;
|
|
240649
|
-
}
|
|
240650
|
-
toString() {
|
|
240651
|
-
const lines = [
|
|
240652
|
-
`<Trace id="${escapeXml(this.id)}" label="${escapeXml(this.label)}" connectionType="${escapeXml(this.connectionType)}" lengthMm="${formatNumber3(this.lengthMm)}" straightLineDistanceMm="${formatNumber3(this.straightLineDistanceMm)}">`,
|
|
240653
|
-
` <ConnectedPins>`,
|
|
240654
|
-
...this.connectedPins.map((pin) => ` <Pin ref="${escapeXml(pin.ref)}" />`),
|
|
240655
|
-
` </ConnectedPins>`,
|
|
240656
|
-
` <PinPositions>`,
|
|
240657
|
-
...this.pinPositions.map((pin) => renderPinPosition(pin, " ")),
|
|
240658
|
-
` </PinPositions>`,
|
|
240659
|
-
renderConnection(this),
|
|
240660
|
-
renderRequirements(this.requirements, " "),
|
|
240661
|
-
`</Trace>`
|
|
240662
|
-
];
|
|
240663
|
-
if (this.points.length > 0) {
|
|
240664
|
-
lines.splice(lines.length - 1, 0, ` <Path>`, ...this.points.map((point5) => ` <Point x="${formatNumber3(point5.x)}" y="${formatNumber3(point5.y)}" layer="${escapeXml(point5.layer)}" kind="${escapeXml(point5.kind)}" />`), ` </Path>`);
|
|
240665
|
-
}
|
|
240666
|
-
return lines.join(`
|
|
240667
|
-
`);
|
|
240668
|
-
}
|
|
240669
|
-
}
|
|
241234
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/analyze-schematic-placement.ts
|
|
241235
|
+
import { cju as cju7 } from "@tscircuit/circuit-json-util";
|
|
240670
241236
|
|
|
240671
|
-
|
|
240672
|
-
|
|
240673
|
-
|
|
240674
|
-
|
|
240675
|
-
totalLengthMm;
|
|
240676
|
-
totalStraightLineDistanceMm;
|
|
240677
|
-
traceCount;
|
|
240678
|
-
#traces;
|
|
240679
|
-
constructor(args) {
|
|
240680
|
-
this.requestedTarget = args.requestedTarget;
|
|
240681
|
-
this.resolvedTarget = args.resolvedTarget;
|
|
240682
|
-
this.targetKind = args.targetKind;
|
|
240683
|
-
this.#traces = [...args.traces];
|
|
240684
|
-
this.totalLengthMm = this.#traces.reduce((sum, trace) => sum + trace.lengthMm, 0);
|
|
240685
|
-
this.totalStraightLineDistanceMm = this.#traces.reduce((sum, trace) => sum + trace.straightLineDistanceMm, 0);
|
|
240686
|
-
this.traceCount = this.#traces.length;
|
|
240687
|
-
}
|
|
240688
|
-
listTraces() {
|
|
240689
|
-
return [...this.#traces];
|
|
240690
|
-
}
|
|
240691
|
-
toString() {
|
|
240692
|
-
const lines = [
|
|
240693
|
-
`<TraceLengthAnalysis requestedTarget="${escapeXml(this.requestedTarget)}" resolvedTarget="${escapeXml(this.resolvedTarget)}" targetKind="${escapeXml(this.targetKind)}" traceCount="${this.traceCount}" totalLengthMm="${formatNumber3(this.totalLengthMm)}" totalStraightLineDistanceMm="${formatNumber3(this.totalStraightLineDistanceMm)}">`,
|
|
240694
|
-
...this.#traces.flatMap((trace) => trace.toString().split(`
|
|
240695
|
-
`).map((line2) => ` ${line2}`)),
|
|
240696
|
-
`</TraceLengthAnalysis>`
|
|
240697
|
-
];
|
|
240698
|
-
return lines.join(`
|
|
240699
|
-
`);
|
|
240700
|
-
}
|
|
240701
|
-
}
|
|
240702
|
-
function analyzeCircuitJsonTraceLength(circuitJson, options) {
|
|
240703
|
-
const index = new CircuitJsonIndex(circuitJson);
|
|
240704
|
-
const target = resolveTarget(index, options.targetPinOrNet);
|
|
240705
|
-
const traces = target.kind === "pin" ? collectPinTraces(index, target) : collectNetTraces(index, target);
|
|
240706
|
-
return new TraceLengthAnalysis({
|
|
240707
|
-
requestedTarget: target.requestedTarget,
|
|
240708
|
-
resolvedTarget: target.resolvedTarget,
|
|
240709
|
-
targetKind: target.kind,
|
|
240710
|
-
traces
|
|
240711
|
-
});
|
|
240712
|
-
}
|
|
240713
|
-
|
|
240714
|
-
class CircuitJsonIndex {
|
|
240715
|
-
componentsById = new Map;
|
|
240716
|
-
componentsByName = new Map;
|
|
240717
|
-
portsById = new Map;
|
|
240718
|
-
portsByComponentId = new Map;
|
|
240719
|
-
netsById = new Map;
|
|
240720
|
-
netsByName = new Map;
|
|
240721
|
-
pcbPortsBySourcePortId = new Map;
|
|
240722
|
-
pcbTracesBySourceTraceId = new Map;
|
|
240723
|
-
pcbTracesByConnectionName = new Map;
|
|
240724
|
-
tracesById = new Map;
|
|
240725
|
-
tracesByPortId = new Map;
|
|
240726
|
-
tracesByNetId = new Map;
|
|
240727
|
-
constructor(circuitJson) {
|
|
240728
|
-
for (const item of circuitJson) {
|
|
240729
|
-
switch (item.type) {
|
|
240730
|
-
case "source_component":
|
|
240731
|
-
this.addComponent(item);
|
|
240732
|
-
break;
|
|
240733
|
-
case "source_port":
|
|
240734
|
-
this.addPort(item);
|
|
240735
|
-
break;
|
|
240736
|
-
case "source_net":
|
|
240737
|
-
this.addNet(item);
|
|
240738
|
-
break;
|
|
240739
|
-
case "pcb_port":
|
|
240740
|
-
this.addPcbPort(item);
|
|
240741
|
-
break;
|
|
240742
|
-
case "pcb_trace":
|
|
240743
|
-
this.addPcbTrace(item);
|
|
240744
|
-
break;
|
|
240745
|
-
case "source_trace":
|
|
240746
|
-
this.addTrace(item);
|
|
240747
|
-
break;
|
|
240748
|
-
default:
|
|
240749
|
-
break;
|
|
240750
|
-
}
|
|
240751
|
-
}
|
|
240752
|
-
}
|
|
240753
|
-
getComponentByName(name) {
|
|
240754
|
-
return this.lookupWithCaseFallback(this.componentsByName, name);
|
|
240755
|
-
}
|
|
240756
|
-
getNetByName(name) {
|
|
240757
|
-
return this.lookupWithCaseFallback(this.netsByName, name);
|
|
240758
|
-
}
|
|
240759
|
-
getPcbPort(sourcePortId) {
|
|
240760
|
-
return this.pcbPortsBySourcePortId.get(sourcePortId)?.[0];
|
|
240761
|
-
}
|
|
240762
|
-
getPortPosition(sourcePortId) {
|
|
240763
|
-
const pcbPort = this.getPcbPort(sourcePortId);
|
|
240764
|
-
if (!pcbPort || typeof pcbPort.x !== "number" || typeof pcbPort.y !== "number") {
|
|
240765
|
-
return null;
|
|
240766
|
-
}
|
|
240767
|
-
const layers = normalizeLayers(pcbPort.layers);
|
|
240768
|
-
return {
|
|
240769
|
-
x: pcbPort.x,
|
|
240770
|
-
y: pcbPort.y,
|
|
240771
|
-
layers
|
|
240772
|
-
};
|
|
240773
|
-
}
|
|
240774
|
-
getPortReference(sourcePortId) {
|
|
240775
|
-
const port = this.portsById.get(sourcePortId);
|
|
240776
|
-
if (!port) {
|
|
240777
|
-
return sourcePortId;
|
|
240778
|
-
}
|
|
240779
|
-
const component = this.componentsById.get(port.source_component_id);
|
|
240780
|
-
const componentName = component?.name ?? port.source_component_id;
|
|
240781
|
-
const portName = port.name ?? String(port.pin_number ?? port.source_port_id);
|
|
240782
|
-
return `${componentName}.${portName}`;
|
|
240783
|
-
}
|
|
240784
|
-
getPcbPathPoints(sourceTraceId) {
|
|
240785
|
-
const candidates = dedupePcbTraces([
|
|
240786
|
-
...this.pcbTracesBySourceTraceId.get(sourceTraceId) ?? [],
|
|
240787
|
-
...this.pcbTracesByConnectionName.get(sourceTraceId) ?? []
|
|
240788
|
-
]);
|
|
240789
|
-
const pcbTraceIds = new Set(candidates.map((trace) => trace.pcb_trace_id));
|
|
240790
|
-
if (candidates.length === 0 || pcbTraceIds.size > 1) {
|
|
240791
|
-
return [];
|
|
240792
|
-
}
|
|
240793
|
-
const routePoints = candidates.flatMap((trace) => normalizePcbTraceRoute(trace));
|
|
240794
|
-
return convertPcbTraceRouteToPath(routePoints);
|
|
240795
|
-
}
|
|
240796
|
-
getConnectedPinsForNet(sourceNetId) {
|
|
240797
|
-
const traces = this.tracesByNetId.get(sourceNetId) ?? [];
|
|
240798
|
-
const sourcePortIds = new Set;
|
|
240799
|
-
for (const trace of traces) {
|
|
240800
|
-
for (const sourcePortId of trace.connected_source_port_ids ?? []) {
|
|
240801
|
-
sourcePortIds.add(sourcePortId);
|
|
240802
|
-
}
|
|
240803
|
-
}
|
|
240804
|
-
return [...sourcePortIds].map((sourcePortId) => this.toConnectedPin(sourcePortId));
|
|
240805
|
-
}
|
|
240806
|
-
toConnectedPin(sourcePortId) {
|
|
240807
|
-
const position2 = this.getPortPosition(sourcePortId);
|
|
240808
|
-
return {
|
|
240809
|
-
ref: this.getPortReference(sourcePortId),
|
|
240810
|
-
x: position2?.x ?? null,
|
|
240811
|
-
y: position2?.y ?? null,
|
|
240812
|
-
layers: position2?.layers ?? []
|
|
240813
|
-
};
|
|
240814
|
-
}
|
|
240815
|
-
addComponent(component) {
|
|
240816
|
-
this.componentsById.set(component.source_component_id, component);
|
|
240817
|
-
const name = component.name;
|
|
240818
|
-
if (!name) {
|
|
240819
|
-
return;
|
|
240820
|
-
}
|
|
240821
|
-
this.addLookup(this.componentsByName, name, component);
|
|
240822
|
-
}
|
|
240823
|
-
addPort(port) {
|
|
240824
|
-
this.portsById.set(port.source_port_id, port);
|
|
240825
|
-
this.addLookup(this.portsByComponentId, port.source_component_id, port);
|
|
240826
|
-
}
|
|
240827
|
-
addNet(net) {
|
|
240828
|
-
this.netsById.set(net.source_net_id, net);
|
|
240829
|
-
const name = net.name;
|
|
240830
|
-
if (!name) {
|
|
240831
|
-
return;
|
|
240832
|
-
}
|
|
240833
|
-
this.addLookup(this.netsByName, name, net);
|
|
240834
|
-
}
|
|
240835
|
-
addPcbPort(pcbPort) {
|
|
240836
|
-
this.addLookup(this.pcbPortsBySourcePortId, pcbPort.source_port_id, pcbPort);
|
|
240837
|
-
}
|
|
240838
|
-
addPcbTrace(pcbTrace) {
|
|
240839
|
-
if (pcbTrace.source_trace_id) {
|
|
240840
|
-
this.addLookup(this.pcbTracesBySourceTraceId, pcbTrace.source_trace_id, pcbTrace);
|
|
240841
|
-
}
|
|
240842
|
-
if (pcbTrace.connection_name) {
|
|
240843
|
-
this.addLookup(this.pcbTracesByConnectionName, pcbTrace.connection_name, pcbTrace);
|
|
240844
|
-
}
|
|
240845
|
-
}
|
|
240846
|
-
addTrace(trace) {
|
|
240847
|
-
this.tracesById.set(trace.source_trace_id, trace);
|
|
240848
|
-
for (const sourcePortId of trace.connected_source_port_ids ?? []) {
|
|
240849
|
-
this.addLookup(this.tracesByPortId, sourcePortId, trace);
|
|
240850
|
-
}
|
|
240851
|
-
for (const sourceNetId of trace.connected_source_net_ids ?? []) {
|
|
240852
|
-
this.addLookup(this.tracesByNetId, sourceNetId, trace);
|
|
240853
|
-
}
|
|
240854
|
-
}
|
|
240855
|
-
addLookup(map, key, value) {
|
|
240856
|
-
const existing = map.get(key) ?? [];
|
|
240857
|
-
existing.push(value);
|
|
240858
|
-
map.set(key, existing);
|
|
240859
|
-
}
|
|
240860
|
-
lookupWithCaseFallback(map, key) {
|
|
240861
|
-
const exactMatch = map.get(key);
|
|
240862
|
-
if (exactMatch?.length) {
|
|
240863
|
-
return exactMatch;
|
|
240864
|
-
}
|
|
240865
|
-
const loweredKey = key.toLowerCase();
|
|
240866
|
-
const fuzzyMatches = [];
|
|
240867
|
-
for (const [candidateKey, values] of map.entries()) {
|
|
240868
|
-
if (candidateKey.toLowerCase() === loweredKey) {
|
|
240869
|
-
fuzzyMatches.push(...values);
|
|
240870
|
-
}
|
|
240871
|
-
}
|
|
240872
|
-
return fuzzyMatches;
|
|
240873
|
-
}
|
|
240874
|
-
}
|
|
240875
|
-
function resolveTarget(index, targetPinOrNet) {
|
|
240876
|
-
if (targetPinOrNet.includes(".")) {
|
|
240877
|
-
if (targetPinOrNet.startsWith("net.")) {
|
|
240878
|
-
const netName = targetPinOrNet.slice("net.".length);
|
|
240879
|
-
const net = resolveNetByName(index, netName);
|
|
240880
|
-
return {
|
|
240881
|
-
kind: "net",
|
|
240882
|
-
requestedTarget: targetPinOrNet,
|
|
240883
|
-
resolvedTarget: `net.${net.name ?? net.source_net_id}`,
|
|
240884
|
-
net
|
|
240885
|
-
};
|
|
240886
|
-
}
|
|
240887
|
-
return resolvePinTarget(index, targetPinOrNet);
|
|
240888
|
-
}
|
|
240889
|
-
const matchingNet = resolveOptionalNetByName(index, targetPinOrNet);
|
|
240890
|
-
if (matchingNet) {
|
|
240891
|
-
const resolvedTarget = `net.${matchingNet.name ?? matchingNet.source_net_id}`;
|
|
240892
|
-
console.log(`inferring ${resolvedTarget}`);
|
|
240893
|
-
return {
|
|
240894
|
-
kind: "net",
|
|
240895
|
-
requestedTarget: targetPinOrNet,
|
|
240896
|
-
resolvedTarget,
|
|
240897
|
-
net: matchingNet
|
|
240898
|
-
};
|
|
240899
|
-
}
|
|
240900
|
-
const matchingPin = resolveOptionalPinByLabel(index, targetPinOrNet);
|
|
240901
|
-
if (matchingPin) {
|
|
240902
|
-
const resolvedTarget = index.getPortReference(matchingPin.source_port_id);
|
|
240903
|
-
console.log(`inferring ${resolvedTarget}`);
|
|
240904
|
-
return {
|
|
240905
|
-
kind: "pin",
|
|
240906
|
-
requestedTarget: targetPinOrNet,
|
|
240907
|
-
resolvedTarget,
|
|
240908
|
-
port: matchingPin
|
|
240909
|
-
};
|
|
240910
|
-
}
|
|
240911
|
-
throw new Error(`Unable to resolve target "${targetPinOrNet}" to a pin or net`);
|
|
240912
|
-
}
|
|
240913
|
-
function resolvePinTarget(index, targetPinOrNet) {
|
|
240914
|
-
const [componentName, ...pinParts] = targetPinOrNet.split(".");
|
|
240915
|
-
const pinLabelOrNumber = pinParts.join(".");
|
|
240916
|
-
if (!componentName || !pinLabelOrNumber) {
|
|
240917
|
-
throw new Error(`Invalid pin target "${targetPinOrNet}"`);
|
|
240918
|
-
}
|
|
240919
|
-
const components = index.getComponentByName(componentName);
|
|
240920
|
-
if (components.length !== 1) {
|
|
240921
|
-
throw new Error(components.length === 0 ? `Unable to find component "${componentName}"` : `Component "${componentName}" is ambiguous`);
|
|
240922
|
-
}
|
|
240923
|
-
const component = components[0];
|
|
240924
|
-
if (!component) {
|
|
240925
|
-
throw new Error(`Unable to find component "${componentName}"`);
|
|
240926
|
-
}
|
|
240927
|
-
const ports = index.portsByComponentId.get(component.source_component_id) ?? [];
|
|
240928
|
-
const matchingPorts = ports.filter((port2) => portMatchesLabel(port2, pinLabelOrNumber));
|
|
240929
|
-
if (matchingPorts.length !== 1) {
|
|
240930
|
-
throw new Error(matchingPorts.length === 0 ? `Unable to find pin "${pinLabelOrNumber}" on ${componentName}` : `Pin "${pinLabelOrNumber}" on ${componentName} is ambiguous`);
|
|
240931
|
-
}
|
|
240932
|
-
const port = matchingPorts[0];
|
|
240933
|
-
if (!port) {
|
|
240934
|
-
throw new Error(`Unable to find pin "${pinLabelOrNumber}" on ${componentName}`);
|
|
240935
|
-
}
|
|
241237
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/schematic-box-overlap.ts
|
|
241238
|
+
var getCenteredRectBounds = (box2) => {
|
|
241239
|
+
const halfWidth = box2.width / 2;
|
|
241240
|
+
const halfHeight = box2.height / 2;
|
|
240936
241241
|
return {
|
|
240937
|
-
|
|
240938
|
-
|
|
240939
|
-
|
|
240940
|
-
|
|
240941
|
-
};
|
|
240942
|
-
}
|
|
240943
|
-
|
|
240944
|
-
const
|
|
240945
|
-
|
|
241242
|
+
left: box2.schX - halfWidth,
|
|
241243
|
+
right: box2.schX + halfWidth,
|
|
241244
|
+
top: box2.schY - halfHeight,
|
|
241245
|
+
bottom: box2.schY + halfHeight
|
|
241246
|
+
};
|
|
241247
|
+
};
|
|
241248
|
+
var getComponentOverlap = (firstComponent, secondComponent) => {
|
|
241249
|
+
const firstBounds = getCenteredRectBounds(firstComponent);
|
|
241250
|
+
const secondBounds = getCenteredRectBounds(secondComponent);
|
|
241251
|
+
const left = Math.max(firstBounds.left, secondBounds.left);
|
|
241252
|
+
const right = Math.min(firstBounds.right, secondBounds.right);
|
|
241253
|
+
const top = Math.max(firstBounds.top, secondBounds.top);
|
|
241254
|
+
const bottom = Math.min(firstBounds.bottom, secondBounds.bottom);
|
|
241255
|
+
const overlapWidth = right - left;
|
|
241256
|
+
const overlapHeight = bottom - top;
|
|
241257
|
+
if (overlapWidth <= 0 || overlapHeight <= 0) {
|
|
240946
241258
|
return null;
|
|
240947
241259
|
}
|
|
240948
|
-
return matchingPorts[0] ?? null;
|
|
240949
|
-
}
|
|
240950
|
-
function resolveNetByName(index, netName) {
|
|
240951
|
-
const matchingNets = index.getNetByName(netName);
|
|
240952
|
-
if (matchingNets.length !== 1) {
|
|
240953
|
-
throw new Error(matchingNets.length === 0 ? `Unable to find net "${netName}"` : `Net "${netName}" is ambiguous`);
|
|
240954
|
-
}
|
|
240955
|
-
const net = matchingNets[0];
|
|
240956
|
-
if (!net) {
|
|
240957
|
-
throw new Error(`Unable to find net "${netName}"`);
|
|
240958
|
-
}
|
|
240959
|
-
return net;
|
|
240960
|
-
}
|
|
240961
|
-
function resolveOptionalNetByName(index, netName) {
|
|
240962
|
-
const matchingNets = index.getNetByName(netName);
|
|
240963
|
-
if (matchingNets.length !== 1) {
|
|
240964
|
-
return null;
|
|
240965
|
-
}
|
|
240966
|
-
return matchingNets[0] ?? null;
|
|
240967
|
-
}
|
|
240968
|
-
function collectPinTraces(index, target) {
|
|
240969
|
-
const traces = index.tracesByPortId.get(target.port.source_port_id) ?? [];
|
|
240970
|
-
return traces.flatMap((trace) => {
|
|
240971
|
-
const netIds = trace.connected_source_net_ids ?? [];
|
|
240972
|
-
if (netIds.length > 0) {
|
|
240973
|
-
return netIds.map((sourceNetId) => createNetTraceModel(index, {
|
|
240974
|
-
trace,
|
|
240975
|
-
sourceNetId,
|
|
240976
|
-
focusSourcePortId: target.port.source_port_id
|
|
240977
|
-
}));
|
|
240978
|
-
}
|
|
240979
|
-
return [
|
|
240980
|
-
createDirectTraceModel(index, {
|
|
240981
|
-
trace,
|
|
240982
|
-
focusSourcePortId: target.port.source_port_id
|
|
240983
|
-
})
|
|
240984
|
-
];
|
|
240985
|
-
}).sort(compareTraceModels).map((model) => new Trace(model));
|
|
240986
|
-
}
|
|
240987
|
-
function collectNetTraces(index, target) {
|
|
240988
|
-
const traces = index.tracesByNetId.get(target.net.source_net_id) ?? [];
|
|
240989
|
-
return traces.flatMap((trace) => {
|
|
240990
|
-
const connectedSourcePortIds = trace.connected_source_port_ids ?? [];
|
|
240991
|
-
if (connectedSourcePortIds.length === 0) {
|
|
240992
|
-
return [];
|
|
240993
|
-
}
|
|
240994
|
-
return connectedSourcePortIds.map((focusSourcePortId) => createNetTraceModel(index, {
|
|
240995
|
-
trace,
|
|
240996
|
-
sourceNetId: target.net.source_net_id,
|
|
240997
|
-
focusSourcePortId
|
|
240998
|
-
}));
|
|
240999
|
-
}).sort(compareTraceModels).map((model) => new Trace(model));
|
|
241000
|
-
}
|
|
241001
|
-
function createDirectTraceModel(index, args) {
|
|
241002
|
-
const connectedSourcePortIds = args.trace.connected_source_port_ids ?? [];
|
|
241003
|
-
if (connectedSourcePortIds.length === 0) {
|
|
241004
|
-
throw new Error(`Trace ${args.trace.source_trace_id} has no connected ports`);
|
|
241005
|
-
}
|
|
241006
|
-
const orderedPortIds = prioritizeFocus(connectedSourcePortIds, args.focusSourcePortId);
|
|
241007
|
-
const firstPortId = orderedPortIds[0];
|
|
241008
|
-
const secondPortId = orderedPortIds[1] ?? orderedPortIds[0];
|
|
241009
|
-
if (!firstPortId || !secondPortId) {
|
|
241010
|
-
throw new Error(`Trace ${args.trace.source_trace_id} is missing connected ports`);
|
|
241011
|
-
}
|
|
241012
|
-
const firstPosition = requirePortPosition(index, firstPortId);
|
|
241013
|
-
const secondPosition = requirePortPosition(index, secondPortId);
|
|
241014
|
-
const secondLayer = primaryLayer(secondPosition.layers);
|
|
241015
|
-
const connectedPins = orderedPortIds.map((sourcePortId) => index.toConnectedPin(sourcePortId));
|
|
241016
|
-
const connectionTarget4 = index.getPortReference(secondPortId);
|
|
241017
|
-
const straightLineDistanceMm = distanceBetween(firstPosition, secondPosition);
|
|
241018
|
-
const points = index.getPcbPathPoints(args.trace.source_trace_id);
|
|
241019
|
-
const lengthMm = points.length > 1 ? measurePathLength(points) : straightLineDistanceMm;
|
|
241020
241260
|
return {
|
|
241021
|
-
|
|
241022
|
-
|
|
241023
|
-
|
|
241024
|
-
|
|
241025
|
-
|
|
241026
|
-
|
|
241027
|
-
|
|
241028
|
-
|
|
241029
|
-
|
|
241030
|
-
|
|
241031
|
-
|
|
241032
|
-
requirements: {
|
|
241033
|
-
maxLengthMm: typeof args.trace.max_length === "number" ? args.trace.max_length : null
|
|
241034
|
-
},
|
|
241035
|
-
points,
|
|
241036
|
-
lengthMm,
|
|
241037
|
-
straightLineDistanceMm,
|
|
241038
|
-
sourceTraceId: args.trace.source_trace_id,
|
|
241039
|
-
displayName: args.trace.display_name ?? null
|
|
241261
|
+
lineItemType: "ComponentOverlap",
|
|
241262
|
+
firstComponent,
|
|
241263
|
+
secondComponent,
|
|
241264
|
+
overlapWidth,
|
|
241265
|
+
overlapHeight,
|
|
241266
|
+
correctionSuggestions: getOverlapCorrectionSuggestions({
|
|
241267
|
+
firstComponent,
|
|
241268
|
+
secondComponent,
|
|
241269
|
+
overlapWidth,
|
|
241270
|
+
overlapHeight
|
|
241271
|
+
})
|
|
241040
241272
|
};
|
|
241041
|
-
}
|
|
241042
|
-
|
|
241043
|
-
|
|
241044
|
-
|
|
241045
|
-
|
|
241046
|
-
|
|
241047
|
-
|
|
241048
|
-
const
|
|
241049
|
-
const
|
|
241050
|
-
const
|
|
241051
|
-
const
|
|
241052
|
-
const
|
|
241053
|
-
const
|
|
241054
|
-
|
|
241055
|
-
|
|
241056
|
-
|
|
241057
|
-
|
|
241058
|
-
|
|
241059
|
-
|
|
241060
|
-
|
|
241061
|
-
connectedPins: prioritizePin(focusPin, connectedPins),
|
|
241062
|
-
pinPositions: prioritizePin(focusPin, connectedPins),
|
|
241063
|
-
requirements: {
|
|
241064
|
-
maxLengthMm: typeof args.trace.max_length === "number" ? args.trace.max_length : null
|
|
241273
|
+
};
|
|
241274
|
+
var getOverlapCorrectionSuggestions = ({
|
|
241275
|
+
firstComponent,
|
|
241276
|
+
secondComponent,
|
|
241277
|
+
overlapWidth,
|
|
241278
|
+
overlapHeight
|
|
241279
|
+
}) => {
|
|
241280
|
+
const firstArea = firstComponent.width * firstComponent.height;
|
|
241281
|
+
const secondArea = secondComponent.width * secondComponent.height;
|
|
241282
|
+
const targetComponent = firstArea <= secondArea ? firstComponent : secondComponent;
|
|
241283
|
+
const otherComponent = targetComponent === firstComponent ? secondComponent : firstComponent;
|
|
241284
|
+
const deltaSchX = targetComponent.schX <= otherComponent.schX ? -overlapWidth : overlapWidth;
|
|
241285
|
+
const deltaSchY = targetComponent.schY <= otherComponent.schY ? -overlapHeight : overlapHeight;
|
|
241286
|
+
return [
|
|
241287
|
+
{
|
|
241288
|
+
targetComponentName: targetComponent.sourceComponentName,
|
|
241289
|
+
deltaSchX,
|
|
241290
|
+
deltaSchY: 0,
|
|
241291
|
+
newSchX: targetComponent.schX + deltaSchX,
|
|
241292
|
+
newSchY: targetComponent.schY
|
|
241065
241293
|
},
|
|
241066
|
-
|
|
241067
|
-
|
|
241068
|
-
|
|
241069
|
-
|
|
241070
|
-
|
|
241071
|
-
|
|
241072
|
-
}
|
|
241073
|
-
function requirePortPosition(index, sourcePortId) {
|
|
241074
|
-
const position2 = index.getPortPosition(sourcePortId);
|
|
241075
|
-
if (!position2) {
|
|
241076
|
-
throw new Error(`Unable to analyze ${index.getPortReference(sourcePortId)} because it has no pcb_port position`);
|
|
241077
|
-
}
|
|
241078
|
-
return position2;
|
|
241079
|
-
}
|
|
241080
|
-
function inferNetHub(connectedPins, fallbackLayer) {
|
|
241081
|
-
const positionedPins = connectedPins.filter((pin) => typeof pin.x === "number" && typeof pin.y === "number");
|
|
241082
|
-
if (positionedPins.length === 0) {
|
|
241083
|
-
return {
|
|
241084
|
-
x: 0,
|
|
241085
|
-
y: 0,
|
|
241086
|
-
layer: fallbackLayer
|
|
241087
|
-
};
|
|
241088
|
-
}
|
|
241089
|
-
const x3 = positionedPins.reduce((sum, pin) => sum + pin.x, 0) / positionedPins.length;
|
|
241090
|
-
const y4 = positionedPins.reduce((sum, pin) => sum + pin.y, 0) / positionedPins.length;
|
|
241091
|
-
const layerCounts = new Map;
|
|
241092
|
-
for (const pin of positionedPins) {
|
|
241093
|
-
const layer2 = pin.layers[0] ?? fallbackLayer;
|
|
241094
|
-
layerCounts.set(layer2, (layerCounts.get(layer2) ?? 0) + 1);
|
|
241095
|
-
}
|
|
241096
|
-
const sortedLayers = [...layerCounts.entries()].sort((left, right) => {
|
|
241097
|
-
if (right[1] !== left[1]) {
|
|
241098
|
-
return right[1] - left[1];
|
|
241099
|
-
}
|
|
241100
|
-
return left[0].localeCompare(right[0]);
|
|
241101
|
-
});
|
|
241102
|
-
const layer = sortedLayers[0]?.[0] ?? fallbackLayer;
|
|
241103
|
-
return { x: x3, y: y4, layer };
|
|
241104
|
-
}
|
|
241105
|
-
function measurePathLength(points) {
|
|
241106
|
-
let lengthMm = 0;
|
|
241107
|
-
for (let index = 1;index < points.length; index += 1) {
|
|
241108
|
-
const previous = points[index - 1];
|
|
241109
|
-
const current2 = points[index];
|
|
241110
|
-
if (!previous || !current2) {
|
|
241111
|
-
continue;
|
|
241294
|
+
{
|
|
241295
|
+
targetComponentName: targetComponent.sourceComponentName,
|
|
241296
|
+
deltaSchX: 0,
|
|
241297
|
+
deltaSchY,
|
|
241298
|
+
newSchX: targetComponent.schX,
|
|
241299
|
+
newSchY: targetComponent.schY + deltaSchY
|
|
241112
241300
|
}
|
|
241113
|
-
|
|
241114
|
-
|
|
241115
|
-
|
|
241116
|
-
|
|
241117
|
-
|
|
241118
|
-
|
|
241119
|
-
|
|
241120
|
-
|
|
241121
|
-
|
|
241122
|
-
|
|
241301
|
+
];
|
|
241302
|
+
};
|
|
241303
|
+
var generateSchematicPlacementIssues = (componentPlacements) => {
|
|
241304
|
+
const issues = [];
|
|
241305
|
+
for (let firstIndex = 0;firstIndex < componentPlacements.length; firstIndex++) {
|
|
241306
|
+
for (let secondIndex = firstIndex + 1;secondIndex < componentPlacements.length; secondIndex++) {
|
|
241307
|
+
const overlap = getComponentOverlap(componentPlacements[firstIndex], componentPlacements[secondIndex]);
|
|
241308
|
+
if (overlap) {
|
|
241309
|
+
issues.push(overlap);
|
|
241310
|
+
}
|
|
241123
241311
|
}
|
|
241124
|
-
seen.add(pcbTrace);
|
|
241125
|
-
deduped.push(pcbTrace);
|
|
241126
241312
|
}
|
|
241127
|
-
return
|
|
241128
|
-
}
|
|
241129
|
-
|
|
241130
|
-
|
|
241131
|
-
|
|
241313
|
+
return issues;
|
|
241314
|
+
};
|
|
241315
|
+
|
|
241316
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/analyze-schematic-placement.ts
|
|
241317
|
+
var fmtNumber5 = (value) => {
|
|
241318
|
+
if (Number.isInteger(value))
|
|
241319
|
+
return String(value);
|
|
241320
|
+
return value.toFixed(3).replace(/\.0+$/, "").replace(/(\.\d*?)0+$/, "$1");
|
|
241321
|
+
};
|
|
241322
|
+
var fmtDelta = (value) => {
|
|
241323
|
+
const formattedValue = fmtNumber5(value);
|
|
241324
|
+
return value > 0 ? `+${formattedValue}` : formattedValue;
|
|
241325
|
+
};
|
|
241326
|
+
var isSchematicBox = (element) => element.type === "schematic_box";
|
|
241327
|
+
var isSchematicComponent = (element) => element.type === "schematic_component";
|
|
241328
|
+
var getSourceComponentName = (circuitJson, sourceComponentId) => {
|
|
241329
|
+
if (!sourceComponentId)
|
|
241330
|
+
return;
|
|
241331
|
+
return cju7(circuitJson).source_component.get(sourceComponentId)?.name;
|
|
241332
|
+
};
|
|
241333
|
+
var schematicComponentToLineItem = (schematicComponent, circuitJson, schematicBox) => ({
|
|
241334
|
+
lineItemType: "SchematicBoxPlacement",
|
|
241335
|
+
positionAnchor: "center",
|
|
241336
|
+
schX: schematicComponent.center.x,
|
|
241337
|
+
schY: schematicComponent.center.y,
|
|
241338
|
+
width: schematicBox?.width ?? schematicComponent.size.width,
|
|
241339
|
+
height: schematicBox?.height ?? schematicComponent.size.height,
|
|
241340
|
+
sourceComponentId: schematicComponent.source_component_id,
|
|
241341
|
+
sourceComponentName: getSourceComponentName(circuitJson, schematicComponent.source_component_id),
|
|
241342
|
+
schematicComponentId: schematicComponent.schematic_component_id,
|
|
241343
|
+
schematicSymbolId: schematicBox?.schematic_symbol_id ?? schematicComponent.schematic_symbol_id,
|
|
241344
|
+
subcircuitId: schematicComponent.subcircuit_id ?? schematicBox?.subcircuit_id
|
|
241345
|
+
});
|
|
241346
|
+
var schematicBoxToLineItem = (schematicBox, circuitJson) => ({
|
|
241347
|
+
lineItemType: "SchematicBoxPlacement",
|
|
241348
|
+
positionAnchor: "center",
|
|
241349
|
+
schX: schematicBox.x,
|
|
241350
|
+
schY: schematicBox.y,
|
|
241351
|
+
width: schematicBox.width,
|
|
241352
|
+
height: schematicBox.height,
|
|
241353
|
+
...getSourceComponentMetadata(schematicBox, circuitJson),
|
|
241354
|
+
schematicComponentId: schematicBox.schematic_component_id,
|
|
241355
|
+
schematicSymbolId: schematicBox.schematic_symbol_id,
|
|
241356
|
+
subcircuitId: schematicBox.subcircuit_id
|
|
241357
|
+
});
|
|
241358
|
+
var getSourceComponentMetadata = (schematicBox, circuitJson) => {
|
|
241359
|
+
if (!schematicBox.schematic_component_id)
|
|
241360
|
+
return {};
|
|
241361
|
+
const circuitJsonUtil = cju7(circuitJson);
|
|
241362
|
+
const schematicComponent = circuitJsonUtil.schematic_component.get(schematicBox.schematic_component_id);
|
|
241363
|
+
if (!schematicComponent?.source_component_id)
|
|
241364
|
+
return {};
|
|
241365
|
+
const sourceComponent = circuitJsonUtil.source_component.get(schematicComponent.source_component_id);
|
|
241366
|
+
return {
|
|
241367
|
+
sourceComponentId: schematicComponent.source_component_id,
|
|
241368
|
+
sourceComponentName: sourceComponent?.name
|
|
241369
|
+
};
|
|
241370
|
+
};
|
|
241371
|
+
var addAttr = (attrs, key, value, options) => {
|
|
241372
|
+
if (value === undefined)
|
|
241373
|
+
return;
|
|
241374
|
+
attrs.push(`${key}="${typeof value === "number" ? options?.formatDelta ? fmtDelta(value) : fmtNumber5(value) : escapeAttr3(value)}"`);
|
|
241375
|
+
};
|
|
241376
|
+
var lineItemToString3 = (lineItem) => {
|
|
241377
|
+
const attrs = [];
|
|
241378
|
+
addAttr(attrs, "componentName", lineItem.sourceComponentName);
|
|
241379
|
+
addAttr(attrs, "positionAnchor", lineItem.positionAnchor);
|
|
241380
|
+
addAttr(attrs, "schX", lineItem.schX);
|
|
241381
|
+
addAttr(attrs, "schY", lineItem.schY);
|
|
241382
|
+
addAttr(attrs, "width", lineItem.width);
|
|
241383
|
+
addAttr(attrs, "height", lineItem.height);
|
|
241384
|
+
return `<SchematicBoxPlacement ${attrs.join(" ")} />`;
|
|
241385
|
+
};
|
|
241386
|
+
var overlapIssueToString = (issue) => {
|
|
241387
|
+
const attrs = [];
|
|
241388
|
+
addAttr(attrs, "component1Name", issue.firstComponent.sourceComponentName);
|
|
241389
|
+
addAttr(attrs, "component2Name", issue.secondComponent.sourceComponentName);
|
|
241390
|
+
addAttr(attrs, "component1SchX", issue.firstComponent.schX);
|
|
241391
|
+
addAttr(attrs, "component1SchY", issue.firstComponent.schY);
|
|
241392
|
+
addAttr(attrs, "component2SchX", issue.secondComponent.schX);
|
|
241393
|
+
addAttr(attrs, "component2SchY", issue.secondComponent.schY);
|
|
241394
|
+
addAttr(attrs, "overlapWidth", issue.overlapWidth);
|
|
241395
|
+
addAttr(attrs, "overlapHeight", issue.overlapHeight);
|
|
241396
|
+
return [
|
|
241397
|
+
`<ComponentOverlap ${attrs.join(" ")}>`,
|
|
241398
|
+
...issue.correctionSuggestions.map(correctionSuggestionToString),
|
|
241399
|
+
"</ComponentOverlap>"
|
|
241400
|
+
].join(`
|
|
241401
|
+
`);
|
|
241402
|
+
};
|
|
241403
|
+
var correctionSuggestionToString = (suggestion) => {
|
|
241404
|
+
const attrs = [];
|
|
241405
|
+
addAttr(attrs, "target", suggestion.targetComponentName);
|
|
241406
|
+
if (suggestion.deltaSchX !== 0) {
|
|
241407
|
+
addAttr(attrs, "newSchX", suggestion.newSchX);
|
|
241408
|
+
addAttr(attrs, "deltaSchX", suggestion.deltaSchX, { formatDelta: true });
|
|
241132
241409
|
}
|
|
241133
|
-
|
|
241134
|
-
|
|
241135
|
-
|
|
241136
|
-
}));
|
|
241137
|
-
}
|
|
241138
|
-
function convertPcbTraceRouteToPath(routePoints) {
|
|
241139
|
-
const deduped = routePoints.filter((point5, index) => {
|
|
241140
|
-
const previous = routePoints[index - 1];
|
|
241141
|
-
return !previous || previous.x !== point5.x || previous.y !== point5.y || previous.layer !== point5.layer;
|
|
241142
|
-
});
|
|
241143
|
-
return deduped.map((point5, index) => ({
|
|
241144
|
-
x: point5.x,
|
|
241145
|
-
y: point5.y,
|
|
241146
|
-
layer: point5.layer,
|
|
241147
|
-
kind: classifyPcbTracePoint(point5, index, deduped.length)
|
|
241148
|
-
}));
|
|
241149
|
-
}
|
|
241150
|
-
function classifyPcbTracePoint(point5, index, pointCount) {
|
|
241151
|
-
if (point5.route_type === "via") {
|
|
241152
|
-
return "via";
|
|
241410
|
+
if (suggestion.deltaSchY !== 0) {
|
|
241411
|
+
addAttr(attrs, "newSchY", suggestion.newSchY);
|
|
241412
|
+
addAttr(attrs, "deltaSchY", suggestion.deltaSchY, { formatDelta: true });
|
|
241153
241413
|
}
|
|
241154
|
-
|
|
241155
|
-
|
|
241414
|
+
return `<OverlapCorrectionSuggestion ${attrs.join(" ")} />`;
|
|
241415
|
+
};
|
|
241416
|
+
var escapeAttr3 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">");
|
|
241417
|
+
|
|
241418
|
+
class SchematicPlacementAnalysis {
|
|
241419
|
+
lineItems;
|
|
241420
|
+
constructor(lineItems) {
|
|
241421
|
+
this.lineItems = lineItems;
|
|
241156
241422
|
}
|
|
241157
|
-
|
|
241158
|
-
|
|
241159
|
-
function renderPinPosition(pin, indent) {
|
|
241160
|
-
if (typeof pin.x !== "number" || typeof pin.y !== "number") {
|
|
241161
|
-
return `${indent}<Pin ref="${escapeXml(pin.ref)}" position="unavailable" />`;
|
|
241423
|
+
getLineItems() {
|
|
241424
|
+
return this.lineItems;
|
|
241162
241425
|
}
|
|
241163
|
-
|
|
241164
|
-
|
|
241165
|
-
}
|
|
241166
|
-
function renderConnection(trace) {
|
|
241167
|
-
if (trace.connectionTargetPosition) {
|
|
241168
|
-
return ` <Connection kind="${escapeXml(trace.connectionType)}" target="${escapeXml(trace.connectionTarget)}" x="${formatNumber3(trace.connectionTargetPosition.x)}" y="${formatNumber3(trace.connectionTargetPosition.y)}" layer="${escapeXml(trace.connectionTargetPosition.layer)}" />`;
|
|
241426
|
+
getString() {
|
|
241427
|
+
return this.toString();
|
|
241169
241428
|
}
|
|
241170
|
-
|
|
241171
|
-
|
|
241172
|
-
|
|
241173
|
-
if (typeof requirements.maxLengthMm === "number") {
|
|
241429
|
+
toString() {
|
|
241430
|
+
const schematicBoxPlacements = this.lineItems.filter((lineItem) => lineItem.lineItemType === "SchematicBoxPlacement");
|
|
241431
|
+
const issues = this.lineItems.flatMap((lineItem) => lineItem.lineItemType === "SchematicPlacementIssues" ? lineItem.issues : []);
|
|
241174
241432
|
return [
|
|
241175
|
-
|
|
241176
|
-
|
|
241177
|
-
|
|
241433
|
+
"<SchematicBoxPositions>",
|
|
241434
|
+
...schematicBoxPlacements.map(lineItemToString3),
|
|
241435
|
+
"</SchematicBoxPositions>",
|
|
241436
|
+
...issues.length > 0 ? [
|
|
241437
|
+
"<SchematicPlacementIssues>",
|
|
241438
|
+
...issues.map((issue) => {
|
|
241439
|
+
switch (issue.lineItemType) {
|
|
241440
|
+
case "ComponentOverlap":
|
|
241441
|
+
return overlapIssueToString(issue);
|
|
241442
|
+
default:
|
|
241443
|
+
return "";
|
|
241444
|
+
}
|
|
241445
|
+
}),
|
|
241446
|
+
"</SchematicPlacementIssues>"
|
|
241447
|
+
] : []
|
|
241178
241448
|
].join(`
|
|
241179
241449
|
`);
|
|
241180
241450
|
}
|
|
241181
|
-
return `${indent}<TraceRequirements none />`;
|
|
241182
|
-
}
|
|
241183
|
-
function portMatchesLabel(port, label) {
|
|
241184
|
-
const loweredLabel = label.toLowerCase();
|
|
241185
|
-
const portName = port.name?.toLowerCase();
|
|
241186
|
-
const pinNumber = String(port.pin_number ?? "").toLowerCase();
|
|
241187
|
-
const portHints2 = (port.port_hints ?? []).map((hint) => hint.toLowerCase());
|
|
241188
|
-
return portName === loweredLabel || pinNumber === loweredLabel || portHints2.includes(loweredLabel);
|
|
241189
|
-
}
|
|
241190
|
-
function prioritizeFocus(portIds, focusSourcePortId) {
|
|
241191
|
-
const remainder = portIds.filter((portId) => portId !== focusSourcePortId);
|
|
241192
|
-
return [focusSourcePortId, ...remainder];
|
|
241193
|
-
}
|
|
241194
|
-
function prioritizePin(focusPin, pins) {
|
|
241195
|
-
const remainder = pins.filter((pin) => pin.ref !== focusPin.ref);
|
|
241196
|
-
return [focusPin, ...remainder];
|
|
241197
|
-
}
|
|
241198
|
-
function compareTraceModels(left, right) {
|
|
241199
|
-
return left.label.localeCompare(right.label);
|
|
241200
|
-
}
|
|
241201
|
-
function normalizeLayers(layers) {
|
|
241202
|
-
if (!Array.isArray(layers)) {
|
|
241203
|
-
return ["top"];
|
|
241204
|
-
}
|
|
241205
|
-
const normalizedLayers = layers.filter((layer) => typeof layer === "string" && layer.length > 0);
|
|
241206
|
-
return normalizedLayers.length > 0 ? normalizedLayers : ["top"];
|
|
241207
|
-
}
|
|
241208
|
-
function primaryLayer(layers) {
|
|
241209
|
-
return layers[0] ?? "top";
|
|
241210
|
-
}
|
|
241211
|
-
function distanceBetween(left, right) {
|
|
241212
|
-
return Math.hypot(right.x - left.x, right.y - left.y);
|
|
241213
|
-
}
|
|
241214
|
-
function formatNumber3(value) {
|
|
241215
|
-
return value.toFixed(2);
|
|
241216
|
-
}
|
|
241217
|
-
function escapeXml(value) {
|
|
241218
|
-
return value.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">");
|
|
241219
241451
|
}
|
|
241452
|
+
var analyzeSchematicPlacement = (circuitJson) => {
|
|
241453
|
+
const schematicBoxes = circuitJson.filter(isSchematicBox);
|
|
241454
|
+
const schematicComponentIds = new Set(circuitJson.filter(isSchematicComponent).map((schematicComponent) => schematicComponent.schematic_component_id));
|
|
241455
|
+
const lineItems = [
|
|
241456
|
+
...circuitJson.filter(isSchematicComponent).map((schematicComponent) => schematicComponentToLineItem(schematicComponent, circuitJson, schematicBoxes.find((schematicBox) => schematicBox.schematic_component_id === schematicComponent.schematic_component_id))),
|
|
241457
|
+
...schematicBoxes.filter((schematicBox) => !schematicBox.schematic_component_id || !schematicComponentIds.has(schematicBox.schematic_component_id)).map((schematicBox) => schematicBoxToLineItem(schematicBox, circuitJson))
|
|
241458
|
+
];
|
|
241459
|
+
const issues = generateSchematicPlacementIssues(lineItems);
|
|
241460
|
+
return new SchematicPlacementAnalysis([
|
|
241461
|
+
...lineItems,
|
|
241462
|
+
...issues.length > 0 ? [{ lineItemType: "SchematicPlacementIssues", issues }] : []
|
|
241463
|
+
]);
|
|
241464
|
+
};
|
|
241465
|
+
// cli/check/schematic-placement/register.ts
|
|
241466
|
+
var checkSchematicPlacement = async (file) => {
|
|
241467
|
+
const resolvedInputFilePath = await resolveCheckInputFilePath(file);
|
|
241468
|
+
const circuitJson = await getCircuitJsonForCheck({
|
|
241469
|
+
filePath: resolvedInputFilePath,
|
|
241470
|
+
platformConfig: {
|
|
241471
|
+
pcbDisabled: true,
|
|
241472
|
+
routingDisabled: true,
|
|
241473
|
+
placementDrcChecksDisabled: true
|
|
241474
|
+
},
|
|
241475
|
+
allowPrebuiltCircuitJson: true
|
|
241476
|
+
});
|
|
241477
|
+
return analyzeSchematicPlacement(circuitJson).getString();
|
|
241478
|
+
};
|
|
241479
|
+
var registerCheckSchematicPlacement = (program2) => {
|
|
241480
|
+
program2.commands.find((c3) => c3.name() === "check").command("schematic-placement").description("Analyze schematic component placement").argument("[file]", "Path to the entry file").action(async (file) => {
|
|
241481
|
+
try {
|
|
241482
|
+
const output = await checkSchematicPlacement(file);
|
|
241483
|
+
console.log(output);
|
|
241484
|
+
} catch (error) {
|
|
241485
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
241486
|
+
process.exit(1);
|
|
241487
|
+
}
|
|
241488
|
+
});
|
|
241489
|
+
};
|
|
241490
|
+
|
|
241220
241491
|
// cli/check/trace-length/register.ts
|
|
241492
|
+
var loadTraceLengthAnalyzer = async () => {
|
|
241493
|
+
const mod = await Promise.resolve().then(() => (init_lib(), exports_lib));
|
|
241494
|
+
return mod.analyzeCircuitJsonTraceLength;
|
|
241495
|
+
};
|
|
241221
241496
|
var checkTraceLength = async (pinOrNetRef, file) => {
|
|
241222
241497
|
const resolvedInputFilePath = await resolveCheckInputFilePath(file);
|
|
241223
241498
|
const circuitJson = await getCircuitJsonForCheck({
|
|
@@ -241228,7 +241503,8 @@ var checkTraceLength = async (pinOrNetRef, file) => {
|
|
|
241228
241503
|
},
|
|
241229
241504
|
allowPrebuiltCircuitJson: true
|
|
241230
241505
|
});
|
|
241231
|
-
const
|
|
241506
|
+
const analyzeCircuitJsonTraceLength2 = await loadTraceLengthAnalyzer();
|
|
241507
|
+
const analysis = analyzeCircuitJsonTraceLength2(circuitJson, {
|
|
241232
241508
|
targetPinOrNet: pinOrNetRef
|
|
241233
241509
|
});
|
|
241234
241510
|
return analysis.toString();
|
|
@@ -246291,8 +246567,8 @@ var warnIfTsconfigMissingTscircuitType = (projectDir) => {
|
|
|
246291
246567
|
}
|
|
246292
246568
|
try {
|
|
246293
246569
|
const tsconfig = JSON.parse(fs51.readFileSync(tsconfigPath, "utf-8"));
|
|
246294
|
-
const
|
|
246295
|
-
if (!Array.isArray(
|
|
246570
|
+
const types2 = tsconfig?.compilerOptions?.types;
|
|
246571
|
+
if (!Array.isArray(types2) || !types2.includes("tscircuit")) {
|
|
246296
246572
|
console.warn(kleur_default.yellow('Warning: "tscircuit" is missing from tsconfig.json compilerOptions.types. Add it (e.g. "types": ["tscircuit"]) to ensure CLI-provided types work correctly.'));
|
|
246297
246573
|
}
|
|
246298
246574
|
} catch {}
|
|
@@ -255424,9 +255700,9 @@ var ZodUnion2 = class extends ZodType2 {
|
|
|
255424
255700
|
return this._def.options;
|
|
255425
255701
|
}
|
|
255426
255702
|
};
|
|
255427
|
-
ZodUnion2.create = (
|
|
255703
|
+
ZodUnion2.create = (types2, params2) => {
|
|
255428
255704
|
return new ZodUnion2({
|
|
255429
|
-
options:
|
|
255705
|
+
options: types2,
|
|
255430
255706
|
typeName: ZodFirstPartyTypeKind3.ZodUnion,
|
|
255431
255707
|
...processCreateParams2(params2)
|
|
255432
255708
|
});
|
|
@@ -260055,7 +260331,7 @@ function buildSubtree2(soup, opts) {
|
|
|
260055
260331
|
}
|
|
260056
260332
|
return soup.filter((e4) => included.has(e4));
|
|
260057
260333
|
}
|
|
260058
|
-
var
|
|
260334
|
+
var cju8 = (circuitJsonInput, options = {}) => {
|
|
260059
260335
|
const circuitJson = circuitJsonInput;
|
|
260060
260336
|
let internalStore = circuitJson._internal_store;
|
|
260061
260337
|
if (!internalStore) {
|
|
@@ -260087,7 +260363,7 @@ var cju7 = (circuitJsonInput, options = {}) => {
|
|
|
260087
260363
|
return internalStore.editCount;
|
|
260088
260364
|
}
|
|
260089
260365
|
if (prop === "subtree") {
|
|
260090
|
-
return (opts) =>
|
|
260366
|
+
return (opts) => cju8(buildSubtree2(circuitJson, opts), options);
|
|
260091
260367
|
}
|
|
260092
260368
|
if (prop === "insert") {
|
|
260093
260369
|
return (elm) => {
|
|
@@ -260197,8 +260473,8 @@ var cju7 = (circuitJsonInput, options = {}) => {
|
|
|
260197
260473
|
});
|
|
260198
260474
|
return su24;
|
|
260199
260475
|
};
|
|
260200
|
-
|
|
260201
|
-
var su9 =
|
|
260476
|
+
cju8.unparsed = cju8;
|
|
260477
|
+
var su9 = cju8;
|
|
260202
260478
|
function createIdKey2(element) {
|
|
260203
260479
|
const type = element.type;
|
|
260204
260480
|
return `${type}:${element[`${type}_id`]}`;
|
|
@@ -266614,7 +266890,7 @@ function buildSubtree3(soup, opts) {
|
|
|
266614
266890
|
}
|
|
266615
266891
|
return soup.filter((e4) => included.has(e4));
|
|
266616
266892
|
}
|
|
266617
|
-
var
|
|
266893
|
+
var cju9 = (circuitJsonInput, options = {}) => {
|
|
266618
266894
|
const circuitJson = circuitJsonInput;
|
|
266619
266895
|
let internalStore = circuitJson._internal_store;
|
|
266620
266896
|
if (!internalStore) {
|
|
@@ -266646,7 +266922,7 @@ var cju8 = (circuitJsonInput, options = {}) => {
|
|
|
266646
266922
|
return internalStore.editCount;
|
|
266647
266923
|
}
|
|
266648
266924
|
if (prop === "subtree") {
|
|
266649
|
-
return (opts) =>
|
|
266925
|
+
return (opts) => cju9(buildSubtree3(circuitJson, opts), options);
|
|
266650
266926
|
}
|
|
266651
266927
|
if (prop === "insert") {
|
|
266652
266928
|
return (elm) => {
|
|
@@ -266756,7 +267032,7 @@ var cju8 = (circuitJsonInput, options = {}) => {
|
|
|
266756
267032
|
});
|
|
266757
267033
|
return su24;
|
|
266758
267034
|
};
|
|
266759
|
-
|
|
267035
|
+
cju9.unparsed = cju9;
|
|
266760
267036
|
function createIdKey3(element) {
|
|
266761
267037
|
const type = element.type;
|
|
266762
267038
|
return `${type}:${element[`${type}_id`]}`;
|
|
@@ -272512,7 +272788,7 @@ import fs63 from "node:fs";
|
|
|
272512
272788
|
import path66 from "node:path";
|
|
272513
272789
|
import {
|
|
272514
272790
|
convertCircuitJsonToGltf as convertCircuitJsonToGltf5,
|
|
272515
|
-
getBestCameraPosition
|
|
272791
|
+
getBestCameraPosition as getBestCameraPosition2
|
|
272516
272792
|
} from "circuit-json-to-gltf";
|
|
272517
272793
|
import {
|
|
272518
272794
|
convertCircuitJsonToPcbSvg as convertCircuitJsonToPcbSvg4,
|
|
@@ -275323,7 +275599,7 @@ var processSnapshotFile = async ({
|
|
|
275323
275599
|
if (!(glbBuffer instanceof ArrayBuffer)) {
|
|
275324
275600
|
throw new Error("Expected ArrayBuffer from convertCircuitJsonToGltf with glb format");
|
|
275325
275601
|
}
|
|
275326
|
-
let cameraOptions =
|
|
275602
|
+
let cameraOptions = getBestCameraPosition2(circuitJson);
|
|
275327
275603
|
if (cameraPreset) {
|
|
275328
275604
|
cameraOptions = applyCameraPreset(cameraPreset, cameraOptions);
|
|
275329
275605
|
}
|
|
@@ -275748,6 +276024,7 @@ registerCheckPinSpecification(program2);
|
|
|
275748
276024
|
registerCheckPlacement(program2);
|
|
275749
276025
|
registerCheckRoutingDifficulty(program2);
|
|
275750
276026
|
registerCheckRouting(program2);
|
|
276027
|
+
registerCheckSchematicPlacement(program2);
|
|
275751
276028
|
registerCheckTraceLength(program2);
|
|
275752
276029
|
registerRegistry(program2);
|
|
275753
276030
|
registerRegistryPackages(program2);
|