@tscircuit/core 0.0.644 → 0.0.646
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/index.d.ts +2 -0
- package/dist/index.js +782 -30
- package/package.json +4 -2
package/dist/index.d.ts
CHANGED
|
@@ -202,6 +202,7 @@ declare class RootCircuit {
|
|
|
202
202
|
schematicDisabled: boolean;
|
|
203
203
|
pcbDisabled: boolean;
|
|
204
204
|
pcbRoutingDisabled: boolean;
|
|
205
|
+
_featureMspSchematicTraceRouting: boolean;
|
|
205
206
|
/**
|
|
206
207
|
* The RootCircuit name is usually set by the platform, it's not required but
|
|
207
208
|
* if supplied can identify the circuit in certain effects, e.g. it is passed
|
|
@@ -1125,6 +1126,7 @@ declare class Group<Props extends z.ZodType<any, any, any> = typeof groupProps>
|
|
|
1125
1126
|
_runLocalAutorouting(): Promise<void>;
|
|
1126
1127
|
_startAsyncAutorouting(): void;
|
|
1127
1128
|
doInitialPcbTraceRender(): void;
|
|
1129
|
+
doInitialSchematicTraceRender(): void;
|
|
1128
1130
|
updatePcbTraceRender(): void;
|
|
1129
1131
|
_updatePcbTraceRenderFromSimpleRouteJson(): void;
|
|
1130
1132
|
_updatePcbTraceRenderFromPcbTraces(): void;
|
package/dist/index.js
CHANGED
|
@@ -23,7 +23,7 @@ __export(components_exports, {
|
|
|
23
23
|
FabricationNoteText: () => FabricationNoteText,
|
|
24
24
|
Footprint: () => Footprint,
|
|
25
25
|
Fuse: () => Fuse,
|
|
26
|
-
Group: () =>
|
|
26
|
+
Group: () => Group6,
|
|
27
27
|
Hole: () => Hole,
|
|
28
28
|
Inductor: () => Inductor,
|
|
29
29
|
Jumper: () => Jumper,
|
|
@@ -4197,7 +4197,7 @@ var getMaxLengthFromConnectedCapacitors = (ports, { db }) => {
|
|
|
4197
4197
|
return sourceComponent.max_decoupling_trace_length;
|
|
4198
4198
|
}
|
|
4199
4199
|
return null;
|
|
4200
|
-
}).filter((
|
|
4200
|
+
}).filter((length7) => length7 !== null);
|
|
4201
4201
|
if (capacitorMaxLengths.length === 0) return void 0;
|
|
4202
4202
|
return Math.min(...capacitorMaxLengths);
|
|
4203
4203
|
};
|
|
@@ -5091,6 +5091,7 @@ var TraceConnectionError = class extends Error {
|
|
|
5091
5091
|
|
|
5092
5092
|
// lib/components/primitive-components/Trace/Trace_doInitialSchematicTraceRender.ts
|
|
5093
5093
|
var Trace_doInitialSchematicTraceRender = (trace) => {
|
|
5094
|
+
if (trace.root?._featureMspSchematicTraceRouting) return;
|
|
5094
5095
|
if (trace._couldNotFindPort) return;
|
|
5095
5096
|
if (trace.root?.schematicDisabled) return;
|
|
5096
5097
|
const { db } = trace.root;
|
|
@@ -7219,7 +7220,7 @@ var CapacityMeshAutorouter = class {
|
|
|
7219
7220
|
|
|
7220
7221
|
// lib/components/primitive-components/Group/Group.ts
|
|
7221
7222
|
import "circuit-json";
|
|
7222
|
-
import
|
|
7223
|
+
import Debug9 from "debug";
|
|
7223
7224
|
import "zod";
|
|
7224
7225
|
|
|
7225
7226
|
// lib/components/primitive-components/TraceHint.ts
|
|
@@ -8024,7 +8025,7 @@ function convertTreeToInputProblem(tree, db, group) {
|
|
|
8024
8025
|
netMap: {},
|
|
8025
8026
|
pinStrongConnMap: {},
|
|
8026
8027
|
netConnMap: {},
|
|
8027
|
-
chipGap: 0.
|
|
8028
|
+
chipGap: 0.6,
|
|
8028
8029
|
partitionGap: 1.2
|
|
8029
8030
|
};
|
|
8030
8031
|
debug5(
|
|
@@ -9210,6 +9211,7 @@ import {
|
|
|
9210
9211
|
} from "@tscircuit/circuit-json-util";
|
|
9211
9212
|
import { translate as translate5, rotate as rotate2, compose as compose4 } from "transformation-matrix";
|
|
9212
9213
|
import Debug7 from "debug";
|
|
9214
|
+
var DEFAULT_MIN_GAP = "1mm";
|
|
9213
9215
|
var debug6 = Debug7("Group_doInitialPcbLayoutPack");
|
|
9214
9216
|
var isDescendantGroup = (db, groupId, ancestorId) => {
|
|
9215
9217
|
if (groupId === ancestorId) return true;
|
|
@@ -9229,7 +9231,7 @@ var Group_doInitialPcbLayoutPack = (group) => {
|
|
|
9229
9231
|
pcbPackGap
|
|
9230
9232
|
} = props;
|
|
9231
9233
|
const gap = pcbPackGap ?? pcbGap ?? gapProp;
|
|
9232
|
-
const gapMm = length4.parse(gap ??
|
|
9234
|
+
const gapMm = length4.parse(gap ?? DEFAULT_MIN_GAP);
|
|
9233
9235
|
const packInput = {
|
|
9234
9236
|
...convertPackOutputToPackInput(
|
|
9235
9237
|
convertCircuitJsonToPackOutput(db.toArray(), {
|
|
@@ -9500,7 +9502,751 @@ var Group_doInitialPcbLayoutFlex = (group) => {
|
|
|
9500
9502
|
|
|
9501
9503
|
// lib/components/primitive-components/Group/Group.ts
|
|
9502
9504
|
import { convertSrjToGraphicsObject } from "@tscircuit/capacity-autorouter";
|
|
9503
|
-
|
|
9505
|
+
|
|
9506
|
+
// lib/components/primitive-components/Group/Group_doInitialSchematicTraceRender/Group_doInitialSchematicTraceRender.ts
|
|
9507
|
+
import { SchematicTracePipelineSolver as SchematicTracePipelineSolver4 } from "@tscircuit/schematic-trace-solver";
|
|
9508
|
+
import Debug8 from "debug";
|
|
9509
|
+
|
|
9510
|
+
// lib/components/primitive-components/Group/Group_doInitialSchematicTraceRender/createSchematicTraceSolverInputProblem.ts
|
|
9511
|
+
import "@tscircuit/schematic-trace-solver";
|
|
9512
|
+
function createSchematicTraceSolverInputProblem(group) {
|
|
9513
|
+
const { db } = group.root;
|
|
9514
|
+
const sckToSourceNet = /* @__PURE__ */ new Map();
|
|
9515
|
+
const sckToUserNetId = /* @__PURE__ */ new Map();
|
|
9516
|
+
const allScks = /* @__PURE__ */ new Set();
|
|
9517
|
+
const traces = group.selectAll("trace");
|
|
9518
|
+
const displayLabelTraces = traces.filter(
|
|
9519
|
+
(t) => t._parsedProps?.schDisplayLabel
|
|
9520
|
+
);
|
|
9521
|
+
const displayLabelSourceTraceIds = new Set(
|
|
9522
|
+
displayLabelTraces.map((t) => t.source_trace_id).filter((id) => Boolean(id))
|
|
9523
|
+
);
|
|
9524
|
+
const childGroups = group.selectAll("group");
|
|
9525
|
+
const allSchematicGroupIds = [
|
|
9526
|
+
group.schematic_group_id,
|
|
9527
|
+
...childGroups.map((a) => a.schematic_group_id)
|
|
9528
|
+
];
|
|
9529
|
+
const schematicComponents = db.schematic_component.list().filter((a) => allSchematicGroupIds.includes(a.schematic_group_id));
|
|
9530
|
+
const chips = [];
|
|
9531
|
+
const pinIdToSchematicPortId = /* @__PURE__ */ new Map();
|
|
9532
|
+
const schematicPortIdToPinId = /* @__PURE__ */ new Map();
|
|
9533
|
+
for (const schematicComponent of schematicComponents) {
|
|
9534
|
+
const chipId = schematicComponent.schematic_component_id;
|
|
9535
|
+
const pins = [];
|
|
9536
|
+
const sourceComponent = db.source_component.getWhere({
|
|
9537
|
+
source_component_id: schematicComponent.source_component_id
|
|
9538
|
+
});
|
|
9539
|
+
const schematicPorts = db.schematic_port.list({
|
|
9540
|
+
schematic_component_id: schematicComponent.schematic_component_id
|
|
9541
|
+
});
|
|
9542
|
+
for (const schematicPort of schematicPorts) {
|
|
9543
|
+
const pinId = `${sourceComponent?.name ?? schematicComponent.schematic_component_id}.${schematicPort.pin_number}`;
|
|
9544
|
+
pinIdToSchematicPortId.set(pinId, schematicPort.schematic_port_id);
|
|
9545
|
+
schematicPortIdToPinId.set(schematicPort.schematic_port_id, pinId);
|
|
9546
|
+
}
|
|
9547
|
+
for (const schematicPort of schematicPorts) {
|
|
9548
|
+
const pinId = schematicPortIdToPinId.get(schematicPort.schematic_port_id);
|
|
9549
|
+
pins.push({
|
|
9550
|
+
pinId,
|
|
9551
|
+
x: schematicPort.center.x,
|
|
9552
|
+
y: schematicPort.center.y
|
|
9553
|
+
});
|
|
9554
|
+
}
|
|
9555
|
+
chips.push({
|
|
9556
|
+
chipId,
|
|
9557
|
+
center: schematicComponent.center,
|
|
9558
|
+
width: schematicComponent.size.width,
|
|
9559
|
+
height: schematicComponent.size.height,
|
|
9560
|
+
pins
|
|
9561
|
+
});
|
|
9562
|
+
}
|
|
9563
|
+
const allSourceAndSchematicPortIdsInScope = /* @__PURE__ */ new Set();
|
|
9564
|
+
const schPortIdToSourcePortId = /* @__PURE__ */ new Map();
|
|
9565
|
+
const sourcePortIdToSchPortId = /* @__PURE__ */ new Map();
|
|
9566
|
+
const userNetIdToSck = /* @__PURE__ */ new Map();
|
|
9567
|
+
for (const sc of schematicComponents) {
|
|
9568
|
+
const ports = db.schematic_port.list({
|
|
9569
|
+
schematic_component_id: sc.schematic_component_id
|
|
9570
|
+
});
|
|
9571
|
+
for (const sp of ports) {
|
|
9572
|
+
allSourceAndSchematicPortIdsInScope.add(sp.schematic_port_id);
|
|
9573
|
+
if (sp.source_port_id) {
|
|
9574
|
+
schPortIdToSourcePortId.set(sp.schematic_port_id, sp.source_port_id);
|
|
9575
|
+
sourcePortIdToSchPortId.set(sp.source_port_id, sp.schematic_port_id);
|
|
9576
|
+
}
|
|
9577
|
+
}
|
|
9578
|
+
}
|
|
9579
|
+
const allowedSubcircuitIds = /* @__PURE__ */ new Set();
|
|
9580
|
+
if (group.subcircuit_id) allowedSubcircuitIds.add(group.subcircuit_id);
|
|
9581
|
+
for (const cg of childGroups) {
|
|
9582
|
+
if (cg.subcircuit_id) allowedSubcircuitIds.add(cg.subcircuit_id);
|
|
9583
|
+
}
|
|
9584
|
+
const directConnections = [];
|
|
9585
|
+
const pairKeyToSourceTraceId = /* @__PURE__ */ new Map();
|
|
9586
|
+
for (const st of db.source_trace.list()) {
|
|
9587
|
+
if (displayLabelSourceTraceIds.has(st.source_trace_id)) continue;
|
|
9588
|
+
if (st.subcircuit_id && !allowedSubcircuitIds.has(st.subcircuit_id)) {
|
|
9589
|
+
continue;
|
|
9590
|
+
}
|
|
9591
|
+
const connected = (st.connected_source_port_ids ?? []).map((srcId) => sourcePortIdToSchPortId.get(srcId)).filter(
|
|
9592
|
+
(sourcePortId) => Boolean(sourcePortId) && allSourceAndSchematicPortIdsInScope.has(sourcePortId)
|
|
9593
|
+
);
|
|
9594
|
+
if (connected.length >= 2) {
|
|
9595
|
+
const [a, b] = connected.slice(0, 2);
|
|
9596
|
+
const pairKey = [a, b].sort().join("::");
|
|
9597
|
+
if (!pairKeyToSourceTraceId.has(pairKey)) {
|
|
9598
|
+
pairKeyToSourceTraceId.set(pairKey, st.source_trace_id);
|
|
9599
|
+
const userNetId = st.display_name ?? st.source_trace_id;
|
|
9600
|
+
if (st.subcircuit_connectivity_map_key) {
|
|
9601
|
+
allScks.add(st.subcircuit_connectivity_map_key);
|
|
9602
|
+
userNetIdToSck.set(userNetId, st.subcircuit_connectivity_map_key);
|
|
9603
|
+
sckToUserNetId.set(st.subcircuit_connectivity_map_key, userNetId);
|
|
9604
|
+
}
|
|
9605
|
+
directConnections.push({
|
|
9606
|
+
pinIds: [a, b].map((id) => schematicPortIdToPinId.get(id)),
|
|
9607
|
+
netId: userNetId
|
|
9608
|
+
});
|
|
9609
|
+
}
|
|
9610
|
+
}
|
|
9611
|
+
}
|
|
9612
|
+
const netConnections = [];
|
|
9613
|
+
for (const net of db.source_net.list().filter((n) => allowedSubcircuitIds.has(n.subcircuit_id))) {
|
|
9614
|
+
if (net.subcircuit_connectivity_map_key) {
|
|
9615
|
+
allScks.add(net.subcircuit_connectivity_map_key);
|
|
9616
|
+
sckToSourceNet.set(net.subcircuit_connectivity_map_key, net);
|
|
9617
|
+
}
|
|
9618
|
+
}
|
|
9619
|
+
const sckToPinIds = /* @__PURE__ */ new Map();
|
|
9620
|
+
for (const [schId, srcPortId] of schPortIdToSourcePortId) {
|
|
9621
|
+
const sp = db.source_port.get(srcPortId);
|
|
9622
|
+
if (!sp?.subcircuit_connectivity_map_key) continue;
|
|
9623
|
+
const sck = sp.subcircuit_connectivity_map_key;
|
|
9624
|
+
allScks.add(sck);
|
|
9625
|
+
if (!sckToPinIds.has(sck)) sckToPinIds.set(sck, []);
|
|
9626
|
+
sckToPinIds.get(sck).push(schId);
|
|
9627
|
+
}
|
|
9628
|
+
for (const [subcircuitConnectivityKey, schematicPortIds] of sckToPinIds) {
|
|
9629
|
+
const sourceNet = sckToSourceNet.get(subcircuitConnectivityKey);
|
|
9630
|
+
if (sourceNet && schematicPortIds.length >= 2) {
|
|
9631
|
+
const userNetId = String(
|
|
9632
|
+
sourceNet.name || sourceNet.source_net_id || subcircuitConnectivityKey
|
|
9633
|
+
);
|
|
9634
|
+
userNetIdToSck.set(userNetId, subcircuitConnectivityKey);
|
|
9635
|
+
sckToUserNetId.set(subcircuitConnectivityKey, userNetId);
|
|
9636
|
+
netConnections.push({
|
|
9637
|
+
netId: userNetId,
|
|
9638
|
+
pinIds: schematicPortIds.map(
|
|
9639
|
+
(portId) => schematicPortIdToPinId.get(portId)
|
|
9640
|
+
)
|
|
9641
|
+
});
|
|
9642
|
+
}
|
|
9643
|
+
}
|
|
9644
|
+
const availableNetLabelOrientations = (() => {
|
|
9645
|
+
const netToAllowedOrientations = {};
|
|
9646
|
+
const presentNetIds = new Set(netConnections.map((nc) => nc.netId));
|
|
9647
|
+
for (const net of db.source_net.list().filter(
|
|
9648
|
+
(n) => !n.subcircuit_id || allowedSubcircuitIds.has(n.subcircuit_id)
|
|
9649
|
+
)) {
|
|
9650
|
+
if (!net.name) continue;
|
|
9651
|
+
if (!presentNetIds.has(net.name)) continue;
|
|
9652
|
+
if (net.name === "GND") {
|
|
9653
|
+
netToAllowedOrientations[net.name] = ["y-"];
|
|
9654
|
+
} else if (/^V/.test(net.name)) {
|
|
9655
|
+
netToAllowedOrientations[net.name] = ["y+"];
|
|
9656
|
+
}
|
|
9657
|
+
}
|
|
9658
|
+
return netToAllowedOrientations;
|
|
9659
|
+
})();
|
|
9660
|
+
const inputProblem = {
|
|
9661
|
+
chips,
|
|
9662
|
+
directConnections,
|
|
9663
|
+
netConnections,
|
|
9664
|
+
availableNetLabelOrientations,
|
|
9665
|
+
maxMspPairDistance: 2
|
|
9666
|
+
};
|
|
9667
|
+
return {
|
|
9668
|
+
inputProblem,
|
|
9669
|
+
pinIdToSchematicPortId,
|
|
9670
|
+
pairKeyToSourceTraceId,
|
|
9671
|
+
sckToSourceNet,
|
|
9672
|
+
sckToUserNetId,
|
|
9673
|
+
userNetIdToSck,
|
|
9674
|
+
allSourceAndSchematicPortIdsInScope,
|
|
9675
|
+
schPortIdToSourcePortId,
|
|
9676
|
+
displayLabelTraces,
|
|
9677
|
+
allScks
|
|
9678
|
+
};
|
|
9679
|
+
}
|
|
9680
|
+
|
|
9681
|
+
// lib/components/primitive-components/Group/Group_doInitialSchematicTraceRender/applyTracesFromSolverOutput.ts
|
|
9682
|
+
import "@tscircuit/schematic-trace-solver";
|
|
9683
|
+
|
|
9684
|
+
// lib/components/primitive-components/Group/Group_doInitialSchematicTraceRender/compute-crossings.ts
|
|
9685
|
+
var TOL = 1e-6;
|
|
9686
|
+
function isHorizontalEdge(edge) {
|
|
9687
|
+
const dx = Math.abs(edge.to.x - edge.from.x);
|
|
9688
|
+
const dy = Math.abs(edge.to.y - edge.from.y);
|
|
9689
|
+
return dx >= dy;
|
|
9690
|
+
}
|
|
9691
|
+
function length6(a, b) {
|
|
9692
|
+
return Math.hypot(b.x - a.x, b.y - a.y);
|
|
9693
|
+
}
|
|
9694
|
+
function pointAt(a, b, t) {
|
|
9695
|
+
return { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };
|
|
9696
|
+
}
|
|
9697
|
+
function paramAlong(a, b, p) {
|
|
9698
|
+
const L = length6(a, b);
|
|
9699
|
+
if (L < TOL) return 0;
|
|
9700
|
+
const t = ((p.x - a.x) * (b.x - a.x) + (p.y - a.y) * (b.y - a.y)) / ((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y));
|
|
9701
|
+
return Math.max(0, Math.min(1, t)) * L;
|
|
9702
|
+
}
|
|
9703
|
+
function cross(ax, ay, bx, by) {
|
|
9704
|
+
return ax * by - ay * bx;
|
|
9705
|
+
}
|
|
9706
|
+
function segmentIntersection(p1, p2, q1, q2) {
|
|
9707
|
+
const r = { x: p2.x - p1.x, y: p2.y - p1.y };
|
|
9708
|
+
const s = { x: q2.x - q1.x, y: q2.y - q1.y };
|
|
9709
|
+
const rxs = cross(r.x, r.y, s.x, s.y);
|
|
9710
|
+
const q_p = { x: q1.x - p1.x, y: q1.y - p1.y };
|
|
9711
|
+
const q_pxr = cross(q_p.x, q_p.y, r.x, r.y);
|
|
9712
|
+
if (Math.abs(rxs) < TOL && Math.abs(q_pxr) < TOL) {
|
|
9713
|
+
return null;
|
|
9714
|
+
}
|
|
9715
|
+
if (Math.abs(rxs) < TOL && Math.abs(q_pxr) >= TOL) {
|
|
9716
|
+
return null;
|
|
9717
|
+
}
|
|
9718
|
+
const t = cross(q_p.x, q_p.y, s.x, s.y) / rxs;
|
|
9719
|
+
const u = cross(q_p.x, q_p.y, r.x, r.y) / rxs;
|
|
9720
|
+
if (t < -TOL || t > 1 + TOL || u < -TOL || u > 1 + TOL) return null;
|
|
9721
|
+
const pt = { x: p1.x + t * r.x, y: p1.y + t * r.y };
|
|
9722
|
+
return pt;
|
|
9723
|
+
}
|
|
9724
|
+
function mergeIntervals(intervals, tol = TOL) {
|
|
9725
|
+
if (intervals.length === 0) return intervals;
|
|
9726
|
+
intervals.sort((a, b) => a.start - b.start);
|
|
9727
|
+
const merged = [];
|
|
9728
|
+
let cur = { ...intervals[0] };
|
|
9729
|
+
for (let i = 1; i < intervals.length; i++) {
|
|
9730
|
+
const nxt = intervals[i];
|
|
9731
|
+
if (nxt.start <= cur.end + tol) {
|
|
9732
|
+
cur.end = Math.max(cur.end, nxt.end);
|
|
9733
|
+
} else {
|
|
9734
|
+
merged.push(cur);
|
|
9735
|
+
cur = { ...nxt };
|
|
9736
|
+
}
|
|
9737
|
+
}
|
|
9738
|
+
merged.push(cur);
|
|
9739
|
+
return merged;
|
|
9740
|
+
}
|
|
9741
|
+
function splitEdgeByCrossings(edge, crossingDistances, crossLen) {
|
|
9742
|
+
const L = length6(edge.from, edge.to);
|
|
9743
|
+
if (L < TOL || crossingDistances.length === 0) return [edge];
|
|
9744
|
+
const half = crossLen / 2;
|
|
9745
|
+
const rawIntervals = crossingDistances.map((d) => ({
|
|
9746
|
+
start: Math.max(0, d - half),
|
|
9747
|
+
end: Math.min(L, d + half)
|
|
9748
|
+
})).filter((iv) => iv.end - iv.start > TOL);
|
|
9749
|
+
const intervals = mergeIntervals(rawIntervals);
|
|
9750
|
+
const result = [];
|
|
9751
|
+
let cursor = 0;
|
|
9752
|
+
const dir = { x: edge.to.x - edge.from.x, y: edge.to.y - edge.from.y };
|
|
9753
|
+
const addSeg = (d0, d1, isCrossing) => {
|
|
9754
|
+
if (d1 - d0 <= TOL) return;
|
|
9755
|
+
const t0 = d0 / L;
|
|
9756
|
+
const t1 = d1 / L;
|
|
9757
|
+
result.push({
|
|
9758
|
+
from: pointAt(edge.from, edge.to, t0),
|
|
9759
|
+
to: pointAt(edge.from, edge.to, t1),
|
|
9760
|
+
...isCrossing ? { is_crossing: true } : {}
|
|
9761
|
+
});
|
|
9762
|
+
};
|
|
9763
|
+
for (const iv of intervals) {
|
|
9764
|
+
if (iv.start - cursor > TOL) {
|
|
9765
|
+
addSeg(cursor, iv.start, false);
|
|
9766
|
+
}
|
|
9767
|
+
addSeg(iv.start, iv.end, true);
|
|
9768
|
+
cursor = iv.end;
|
|
9769
|
+
}
|
|
9770
|
+
if (L - cursor > TOL) {
|
|
9771
|
+
addSeg(cursor, L, false);
|
|
9772
|
+
}
|
|
9773
|
+
return result.length > 0 ? result : [edge];
|
|
9774
|
+
}
|
|
9775
|
+
function computeCrossings(traces, opts = {}) {
|
|
9776
|
+
const crossLen = opts.crossSegmentLength ?? 0.075;
|
|
9777
|
+
const tol = opts.tolerance ?? TOL;
|
|
9778
|
+
const crossingsByEdge = /* @__PURE__ */ new Map();
|
|
9779
|
+
const keyOf = (ref) => `${ref.traceIdx}:${ref.edgeIdx}`;
|
|
9780
|
+
const getEdge = (ref) => traces[ref.traceIdx].edges[ref.edgeIdx];
|
|
9781
|
+
for (let ti = 0; ti < traces.length; ti++) {
|
|
9782
|
+
const A = traces[ti];
|
|
9783
|
+
for (let ei = 0; ei < A.edges.length; ei++) {
|
|
9784
|
+
const eA = A.edges[ei];
|
|
9785
|
+
for (let tj = ti; tj < traces.length; tj++) {
|
|
9786
|
+
const B = traces[tj];
|
|
9787
|
+
for (let ej = tj === ti ? ei + 1 : 0; ej < B.edges.length; ej++) {
|
|
9788
|
+
const eB = B.edges[ej];
|
|
9789
|
+
const P = segmentIntersection(eA.from, eA.to, eB.from, eB.to);
|
|
9790
|
+
if (!P) continue;
|
|
9791
|
+
const LA = length6(eA.from, eA.to);
|
|
9792
|
+
const LB = length6(eB.from, eB.to);
|
|
9793
|
+
if (LA < tol || LB < tol) continue;
|
|
9794
|
+
const dA = paramAlong(eA.from, eA.to, P);
|
|
9795
|
+
const dB = paramAlong(eB.from, eB.to, P);
|
|
9796
|
+
const nearEndpointA = dA <= tol || Math.abs(LA - dA) <= tol || Number.isNaN(dA);
|
|
9797
|
+
const nearEndpointB = dB <= tol || Math.abs(LB - dB) <= tol || Number.isNaN(dB);
|
|
9798
|
+
if (!nearEndpointA && !nearEndpointB) {
|
|
9799
|
+
const aIsHorizontal = isHorizontalEdge(eA);
|
|
9800
|
+
const bIsHorizontal = isHorizontalEdge(eB);
|
|
9801
|
+
let assignToA;
|
|
9802
|
+
if (aIsHorizontal !== bIsHorizontal) {
|
|
9803
|
+
assignToA = aIsHorizontal;
|
|
9804
|
+
} else {
|
|
9805
|
+
const ax = Math.abs(eA.to.x - eA.from.x);
|
|
9806
|
+
const ay = Math.abs(eA.to.y - eA.from.y);
|
|
9807
|
+
const bx = Math.abs(eB.to.x - eB.from.x);
|
|
9808
|
+
const by = Math.abs(eB.to.y - eB.from.y);
|
|
9809
|
+
const aScore = ax - ay;
|
|
9810
|
+
const bScore = bx - by;
|
|
9811
|
+
assignToA = aScore === bScore ? true : aScore > bScore;
|
|
9812
|
+
}
|
|
9813
|
+
const chosenKey = keyOf({
|
|
9814
|
+
traceIdx: assignToA ? ti : tj,
|
|
9815
|
+
edgeIdx: assignToA ? ei : ej
|
|
9816
|
+
});
|
|
9817
|
+
const chosenList = crossingsByEdge.get(chosenKey) ?? [];
|
|
9818
|
+
chosenList.push(assignToA ? dA : dB);
|
|
9819
|
+
crossingsByEdge.set(chosenKey, chosenList);
|
|
9820
|
+
}
|
|
9821
|
+
}
|
|
9822
|
+
}
|
|
9823
|
+
}
|
|
9824
|
+
}
|
|
9825
|
+
const out = traces.map((t) => ({ id: t.id, edges: [] }));
|
|
9826
|
+
for (let ti = 0; ti < traces.length; ti++) {
|
|
9827
|
+
const trace = traces[ti];
|
|
9828
|
+
for (let ei = 0; ei < trace.edges.length; ei++) {
|
|
9829
|
+
const eRefKey = keyOf({ traceIdx: ti, edgeIdx: ei });
|
|
9830
|
+
const splittingDistances = crossingsByEdge.get(eRefKey) ?? [];
|
|
9831
|
+
if (splittingDistances.length === 0) {
|
|
9832
|
+
out[ti].edges.push(trace.edges[ei]);
|
|
9833
|
+
continue;
|
|
9834
|
+
}
|
|
9835
|
+
const uniqueSorted = Array.from(
|
|
9836
|
+
new Set(splittingDistances.map((d) => Number(d.toFixed(6))))
|
|
9837
|
+
).sort((a, b) => a - b);
|
|
9838
|
+
const split = splitEdgeByCrossings(
|
|
9839
|
+
trace.edges[ei],
|
|
9840
|
+
uniqueSorted,
|
|
9841
|
+
crossLen
|
|
9842
|
+
);
|
|
9843
|
+
out[ti].edges.push(...split);
|
|
9844
|
+
}
|
|
9845
|
+
}
|
|
9846
|
+
return out;
|
|
9847
|
+
}
|
|
9848
|
+
|
|
9849
|
+
// lib/components/primitive-components/Group/Group_doInitialSchematicTraceRender/compute-junctions.ts
|
|
9850
|
+
var TOL2 = 1e-6;
|
|
9851
|
+
function nearlyEqual(a, b, tol = TOL2) {
|
|
9852
|
+
return Math.abs(a - b) <= tol;
|
|
9853
|
+
}
|
|
9854
|
+
function pointEq(a, b, tol = TOL2) {
|
|
9855
|
+
return nearlyEqual(a.x, b.x, tol) && nearlyEqual(a.y, b.y, tol);
|
|
9856
|
+
}
|
|
9857
|
+
function onSegment(p, a, b, tol = TOL2) {
|
|
9858
|
+
const minX = Math.min(a.x, b.x) - tol;
|
|
9859
|
+
const maxX = Math.max(a.x, b.x) + tol;
|
|
9860
|
+
const minY = Math.min(a.y, b.y) - tol;
|
|
9861
|
+
const maxY = Math.max(a.y, b.y) + tol;
|
|
9862
|
+
if (p.x < minX || p.x > maxX || p.y < minY || p.y > maxY) return false;
|
|
9863
|
+
const area = Math.abs((b.x - a.x) * (p.y - a.y) - (b.y - a.y) * (p.x - a.x));
|
|
9864
|
+
return area <= tol;
|
|
9865
|
+
}
|
|
9866
|
+
function dedupePoints(points, tol = TOL2) {
|
|
9867
|
+
const map = /* @__PURE__ */ new Map();
|
|
9868
|
+
for (const p of points) {
|
|
9869
|
+
const key = `${p.x.toFixed(6)},${p.y.toFixed(6)}`;
|
|
9870
|
+
if (!map.has(key)) map.set(key, p);
|
|
9871
|
+
}
|
|
9872
|
+
return Array.from(map.values());
|
|
9873
|
+
}
|
|
9874
|
+
function edgeVec(e) {
|
|
9875
|
+
return { x: e.to.x - e.from.x, y: e.to.y - e.from.y };
|
|
9876
|
+
}
|
|
9877
|
+
function isParallel(e1, e2, tol = TOL2) {
|
|
9878
|
+
const v1 = edgeVec(e1);
|
|
9879
|
+
const v2 = edgeVec(e2);
|
|
9880
|
+
const L1 = Math.hypot(v1.x, v1.y);
|
|
9881
|
+
const L2 = Math.hypot(v2.x, v2.y);
|
|
9882
|
+
if (L1 < tol || L2 < tol) return true;
|
|
9883
|
+
const cross2 = v1.x * v2.y - v1.y * v2.x;
|
|
9884
|
+
return Math.abs(cross2) <= tol * L1 * L2;
|
|
9885
|
+
}
|
|
9886
|
+
function incidentEdgesAtPoint(trace, p, tol = TOL2) {
|
|
9887
|
+
return trace.edges.filter(
|
|
9888
|
+
(e) => pointEq(e.from, p, tol) || pointEq(e.to, p, tol)
|
|
9889
|
+
);
|
|
9890
|
+
}
|
|
9891
|
+
function nearestEndpointOnTrace(trace, p, tol = TOL2) {
|
|
9892
|
+
for (const e of trace.edges) {
|
|
9893
|
+
if (pointEq(e.from, p, tol)) return e.from;
|
|
9894
|
+
if (pointEq(e.to, p, tol)) return e.to;
|
|
9895
|
+
}
|
|
9896
|
+
return null;
|
|
9897
|
+
}
|
|
9898
|
+
function edgeDirectionFromPoint(e, p, tol = TOL2) {
|
|
9899
|
+
const other = pointEq(e.from, p, tol) || nearlyEqual(e.from.x, p.x, tol) && nearlyEqual(e.from.y, p.y, tol) ? e.to : e.from;
|
|
9900
|
+
const dx = other.x - p.x;
|
|
9901
|
+
const dy = other.y - p.y;
|
|
9902
|
+
if (Math.abs(dx) < tol && Math.abs(dy) < tol) return null;
|
|
9903
|
+
if (Math.abs(dx) >= Math.abs(dy)) {
|
|
9904
|
+
return dx >= 0 ? "right" : "left";
|
|
9905
|
+
}
|
|
9906
|
+
return dy >= 0 ? "up" : "down";
|
|
9907
|
+
}
|
|
9908
|
+
function getCornerOrientationAtPoint(trace, p, tol = TOL2) {
|
|
9909
|
+
const incident = incidentEdgesAtPoint(trace, p, tol);
|
|
9910
|
+
if (incident.length < 2) return null;
|
|
9911
|
+
const dirs = incident.map((e) => edgeDirectionFromPoint(e, p, tol));
|
|
9912
|
+
const hasUp = dirs.includes("up");
|
|
9913
|
+
const hasDown = dirs.includes("down");
|
|
9914
|
+
const hasLeft = dirs.includes("left");
|
|
9915
|
+
const hasRight = dirs.includes("right");
|
|
9916
|
+
const vertical = hasUp ? "up" : hasDown ? "down" : null;
|
|
9917
|
+
const horizontal = hasRight ? "right" : hasLeft ? "left" : null;
|
|
9918
|
+
if (vertical && horizontal) {
|
|
9919
|
+
return `${vertical}-${horizontal}`;
|
|
9920
|
+
}
|
|
9921
|
+
return null;
|
|
9922
|
+
}
|
|
9923
|
+
function computeJunctions(traces, opts = {}) {
|
|
9924
|
+
const tol = opts.tolerance ?? TOL2;
|
|
9925
|
+
const result = {};
|
|
9926
|
+
for (const t of traces) result[t.id] = [];
|
|
9927
|
+
const endpointsByTrace = traces.map((t) => {
|
|
9928
|
+
const pts = [];
|
|
9929
|
+
for (const e of t.edges) {
|
|
9930
|
+
pts.push(e.from, e.to);
|
|
9931
|
+
}
|
|
9932
|
+
return dedupePoints(pts, tol);
|
|
9933
|
+
});
|
|
9934
|
+
for (let i = 0; i < traces.length; i++) {
|
|
9935
|
+
const A = traces[i];
|
|
9936
|
+
const AEnds = endpointsByTrace[i];
|
|
9937
|
+
for (let j = i + 1; j < traces.length; j++) {
|
|
9938
|
+
const B = traces[j];
|
|
9939
|
+
const BEnds = endpointsByTrace[j];
|
|
9940
|
+
for (const pa of AEnds) {
|
|
9941
|
+
for (const pb of BEnds) {
|
|
9942
|
+
if (pointEq(pa, pb, tol)) {
|
|
9943
|
+
const aEdgesAtP = incidentEdgesAtPoint(A, pa, tol);
|
|
9944
|
+
const bEdgesAtP = incidentEdgesAtPoint(B, pb, tol);
|
|
9945
|
+
const hasCorner = aEdgesAtP.some(
|
|
9946
|
+
(eA) => bEdgesAtP.some((eB) => !isParallel(eA, eB, tol))
|
|
9947
|
+
);
|
|
9948
|
+
const aCorner = getCornerOrientationAtPoint(A, pa, tol);
|
|
9949
|
+
const bCorner = getCornerOrientationAtPoint(B, pb, tol);
|
|
9950
|
+
const sameCornerOrientation = aCorner !== null && bCorner !== null && aCorner === bCorner;
|
|
9951
|
+
if (hasCorner && !sameCornerOrientation) {
|
|
9952
|
+
result[A.id].push(pa);
|
|
9953
|
+
if (A.id !== B.id) result[B.id].push(pb);
|
|
9954
|
+
}
|
|
9955
|
+
}
|
|
9956
|
+
}
|
|
9957
|
+
}
|
|
9958
|
+
for (const pa of AEnds) {
|
|
9959
|
+
for (const eB of B.edges) {
|
|
9960
|
+
if (onSegment(pa, eB.from, eB.to, tol)) {
|
|
9961
|
+
const aEdgesAtP = incidentEdgesAtPoint(A, pa, tol);
|
|
9962
|
+
const hasCorner = aEdgesAtP.some((eA) => !isParallel(eA, eB, tol));
|
|
9963
|
+
const aCorner = getCornerOrientationAtPoint(A, pa, tol);
|
|
9964
|
+
const bEndpointNearPa = nearestEndpointOnTrace(B, pa, tol * 1e3);
|
|
9965
|
+
const bCorner = bEndpointNearPa ? getCornerOrientationAtPoint(B, bEndpointNearPa, tol) : null;
|
|
9966
|
+
const sameCornerOrientation = aCorner !== null && bCorner !== null && aCorner === bCorner;
|
|
9967
|
+
if (hasCorner && !sameCornerOrientation) {
|
|
9968
|
+
result[A.id].push(pa);
|
|
9969
|
+
if (A.id !== B.id) result[B.id].push(pa);
|
|
9970
|
+
}
|
|
9971
|
+
}
|
|
9972
|
+
}
|
|
9973
|
+
}
|
|
9974
|
+
for (const pb of BEnds) {
|
|
9975
|
+
for (const eA of A.edges) {
|
|
9976
|
+
if (onSegment(pb, eA.from, eA.to, tol)) {
|
|
9977
|
+
const bEdgesAtP = incidentEdgesAtPoint(B, pb, tol);
|
|
9978
|
+
const hasCorner = bEdgesAtP.some((eB) => !isParallel(eA, eB, tol));
|
|
9979
|
+
const bCorner = getCornerOrientationAtPoint(B, pb, tol);
|
|
9980
|
+
const aEndpointNearPb = nearestEndpointOnTrace(A, pb, tol * 1e3);
|
|
9981
|
+
const aCorner = aEndpointNearPb ? getCornerOrientationAtPoint(A, aEndpointNearPb, tol) : null;
|
|
9982
|
+
const sameCornerOrientation = aCorner !== null && bCorner !== null && aCorner === bCorner;
|
|
9983
|
+
if (hasCorner && !sameCornerOrientation) {
|
|
9984
|
+
result[B.id].push(pb);
|
|
9985
|
+
if (A.id !== B.id) result[A.id].push(pb);
|
|
9986
|
+
}
|
|
9987
|
+
}
|
|
9988
|
+
}
|
|
9989
|
+
}
|
|
9990
|
+
}
|
|
9991
|
+
}
|
|
9992
|
+
for (const id of Object.keys(result)) {
|
|
9993
|
+
result[id] = dedupePoints(result[id], tol);
|
|
9994
|
+
}
|
|
9995
|
+
return result;
|
|
9996
|
+
}
|
|
9997
|
+
|
|
9998
|
+
// lib/components/primitive-components/Group/Group_doInitialSchematicTraceRender/applyTracesFromSolverOutput.ts
|
|
9999
|
+
function applyTracesFromSolverOutput(args) {
|
|
10000
|
+
const { group, solver, pinIdToSchematicPortId, pairKeyToSourceTraceId } = args;
|
|
10001
|
+
const { db } = group.root;
|
|
10002
|
+
const correctedMap = solver.traceOverlapShiftSolver?.correctedTraceMap;
|
|
10003
|
+
const pendingTraces = [];
|
|
10004
|
+
for (const solved of Object.values(correctedMap ?? {})) {
|
|
10005
|
+
const points = solved?.tracePath;
|
|
10006
|
+
if (!Array.isArray(points) || points.length < 2) continue;
|
|
10007
|
+
const edges = [];
|
|
10008
|
+
for (let i = 0; i < points.length - 1; i++) {
|
|
10009
|
+
edges.push({
|
|
10010
|
+
from: { x: points[i].x, y: points[i].y },
|
|
10011
|
+
to: { x: points[i + 1].x, y: points[i + 1].y }
|
|
10012
|
+
});
|
|
10013
|
+
}
|
|
10014
|
+
let source_trace_id = null;
|
|
10015
|
+
if (Array.isArray(solved?.pins) && solved.pins.length === 2) {
|
|
10016
|
+
const pA = pinIdToSchematicPortId.get(solved.pins[0]?.pinId);
|
|
10017
|
+
const pB = pinIdToSchematicPortId.get(solved.pins[1]?.pinId);
|
|
10018
|
+
if (pA && pB) {
|
|
10019
|
+
const pairKey = [pA, pB].sort().join("::");
|
|
10020
|
+
source_trace_id = pairKeyToSourceTraceId.get(pairKey) || `solver_${solved.mspPairId || pairKey}`;
|
|
10021
|
+
for (const schPid of [pA, pB]) {
|
|
10022
|
+
const existing = db.schematic_port.get(schPid);
|
|
10023
|
+
if (existing) db.schematic_port.update(schPid, { is_connected: true });
|
|
10024
|
+
}
|
|
10025
|
+
}
|
|
10026
|
+
}
|
|
10027
|
+
if (!source_trace_id) {
|
|
10028
|
+
source_trace_id = `solver_${solved?.mspPairId}`;
|
|
10029
|
+
}
|
|
10030
|
+
pendingTraces.push({
|
|
10031
|
+
id: source_trace_id,
|
|
10032
|
+
edges
|
|
10033
|
+
});
|
|
10034
|
+
}
|
|
10035
|
+
const withCrossings = computeCrossings(
|
|
10036
|
+
pendingTraces.map((t) => ({ id: t.id, edges: t.edges }))
|
|
10037
|
+
);
|
|
10038
|
+
const junctionsById = computeJunctions(withCrossings);
|
|
10039
|
+
for (const t of withCrossings) {
|
|
10040
|
+
db.schematic_trace.insert({
|
|
10041
|
+
source_trace_id: t.id,
|
|
10042
|
+
edges: t.edges,
|
|
10043
|
+
junctions: junctionsById[t.id] ?? []
|
|
10044
|
+
});
|
|
10045
|
+
}
|
|
10046
|
+
}
|
|
10047
|
+
|
|
10048
|
+
// lib/components/primitive-components/Group/Group_doInitialSchematicTraceRender/applyNetLabelPlacements.ts
|
|
10049
|
+
import "@tscircuit/schematic-trace-solver";
|
|
10050
|
+
|
|
10051
|
+
// lib/components/primitive-components/Group/Group_doInitialSchematicTraceRender/oppositeSide.ts
|
|
10052
|
+
var oppositeSide = (input) => {
|
|
10053
|
+
switch (input) {
|
|
10054
|
+
case "x+":
|
|
10055
|
+
return "left";
|
|
10056
|
+
case "x-":
|
|
10057
|
+
return "right";
|
|
10058
|
+
case "y+":
|
|
10059
|
+
return "bottom";
|
|
10060
|
+
case "y-":
|
|
10061
|
+
return "top";
|
|
10062
|
+
case "left":
|
|
10063
|
+
return "right";
|
|
10064
|
+
case "top":
|
|
10065
|
+
return "bottom";
|
|
10066
|
+
case "right":
|
|
10067
|
+
return "left";
|
|
10068
|
+
case "bottom":
|
|
10069
|
+
return "top";
|
|
10070
|
+
}
|
|
10071
|
+
};
|
|
10072
|
+
|
|
10073
|
+
// lib/components/primitive-components/Group/Group_doInitialSchematicTraceRender/applyNetLabelPlacements.ts
|
|
10074
|
+
function applyNetLabelPlacements(args) {
|
|
10075
|
+
const {
|
|
10076
|
+
group,
|
|
10077
|
+
solver,
|
|
10078
|
+
sckToSourceNet,
|
|
10079
|
+
allScks,
|
|
10080
|
+
allSourceAndSchematicPortIdsInScope,
|
|
10081
|
+
schPortIdToSourcePortId,
|
|
10082
|
+
userNetIdToSck
|
|
10083
|
+
} = args;
|
|
10084
|
+
const { db } = group.root;
|
|
10085
|
+
const netLabelPlacements = solver.netLabelPlacementSolver?.netLabelPlacements ?? [];
|
|
10086
|
+
const globalConnMap = solver.mspConnectionPairSolver.globalConnMap;
|
|
10087
|
+
for (const placement of netLabelPlacements) {
|
|
10088
|
+
const placementUserNetId = globalConnMap.getIdsConnectedToNet(placement.globalConnNetId).find((id) => userNetIdToSck.get(id));
|
|
10089
|
+
const placementSck = userNetIdToSck.get(placementUserNetId);
|
|
10090
|
+
const anchor_position = placement.anchorPoint;
|
|
10091
|
+
const orientation = placement.orientation;
|
|
10092
|
+
const anchor_side = oppositeSide(orientation);
|
|
10093
|
+
const sourceNet = placementSck ? sckToSourceNet.get(placementSck) : void 0;
|
|
10094
|
+
if (!sourceNet) {
|
|
10095
|
+
continue;
|
|
10096
|
+
}
|
|
10097
|
+
const text = sourceNet.name;
|
|
10098
|
+
const center = placement.center ?? computeSchematicNetLabelCenter({
|
|
10099
|
+
anchor_position,
|
|
10100
|
+
anchor_side,
|
|
10101
|
+
text
|
|
10102
|
+
});
|
|
10103
|
+
db.schematic_net_label.insert({
|
|
10104
|
+
text,
|
|
10105
|
+
anchor_position,
|
|
10106
|
+
center,
|
|
10107
|
+
anchor_side,
|
|
10108
|
+
...sourceNet?.source_net_id ? { source_net_id: sourceNet.source_net_id } : {}
|
|
10109
|
+
});
|
|
10110
|
+
}
|
|
10111
|
+
}
|
|
10112
|
+
|
|
10113
|
+
// lib/components/primitive-components/Group/Group_doInitialSchematicTraceRender/insertNetLabelsForTracesExcludedFromRouting.ts
|
|
10114
|
+
import "@tscircuit/schematic-trace-solver";
|
|
10115
|
+
function insertNetLabelsForTracesExcludedFromRouting(args) {
|
|
10116
|
+
const { group, displayLabelTraces } = args;
|
|
10117
|
+
const { db } = group.root;
|
|
10118
|
+
for (const trace of displayLabelTraces) {
|
|
10119
|
+
const label = trace._parsedProps?.schDisplayLabel;
|
|
10120
|
+
if (!label) continue;
|
|
10121
|
+
try {
|
|
10122
|
+
const res = trace._findConnectedPorts?.();
|
|
10123
|
+
if (!res?.allPortsFound || !res.ports || res.ports.length < 1) continue;
|
|
10124
|
+
const ports = res.ports.slice(0, 2);
|
|
10125
|
+
for (const port of ports) {
|
|
10126
|
+
const anchor_position = port._getGlobalSchematicPositionAfterLayout();
|
|
10127
|
+
const side = getEnteringEdgeFromDirection(port.facingDirection || "right") || "right";
|
|
10128
|
+
const center = computeSchematicNetLabelCenter({
|
|
10129
|
+
anchor_position,
|
|
10130
|
+
anchor_side: side,
|
|
10131
|
+
text: label
|
|
10132
|
+
});
|
|
10133
|
+
db.schematic_net_label.insert({
|
|
10134
|
+
text: label,
|
|
10135
|
+
anchor_position,
|
|
10136
|
+
center,
|
|
10137
|
+
anchor_side: side,
|
|
10138
|
+
...trace.source_trace_id ? { source_trace_id: trace.source_trace_id } : {}
|
|
10139
|
+
});
|
|
10140
|
+
}
|
|
10141
|
+
} catch {
|
|
10142
|
+
}
|
|
10143
|
+
}
|
|
10144
|
+
}
|
|
10145
|
+
|
|
10146
|
+
// lib/components/primitive-components/Group/Group_doInitialSchematicTraceRender/insertNetLabelsForPortsMissingTrace.ts
|
|
10147
|
+
var insertNetLabelsForPortsMissingTrace = ({
|
|
10148
|
+
allSourceAndSchematicPortIdsInScope,
|
|
10149
|
+
group,
|
|
10150
|
+
schPortIdToSourcePortId,
|
|
10151
|
+
sckToSourceNet: connKeyToNet
|
|
10152
|
+
}) => {
|
|
10153
|
+
const { db } = group.root;
|
|
10154
|
+
for (const schOrSrcPortId of Array.from(
|
|
10155
|
+
allSourceAndSchematicPortIdsInScope
|
|
10156
|
+
)) {
|
|
10157
|
+
const sp = db.schematic_port.get(schOrSrcPortId);
|
|
10158
|
+
if (!sp) continue;
|
|
10159
|
+
if (sp.is_connected) continue;
|
|
10160
|
+
const srcPortId = schPortIdToSourcePortId.get(schOrSrcPortId);
|
|
10161
|
+
if (!srcPortId) continue;
|
|
10162
|
+
const sourcePort = db.source_port.get(srcPortId);
|
|
10163
|
+
const key = sourcePort?.subcircuit_connectivity_map_key;
|
|
10164
|
+
if (!key) continue;
|
|
10165
|
+
const sourceNet = connKeyToNet.get(key);
|
|
10166
|
+
if (!sourceNet) {
|
|
10167
|
+
continue;
|
|
10168
|
+
}
|
|
10169
|
+
const existingAtPort = db.schematic_net_label.list().some((nl) => {
|
|
10170
|
+
const samePos = Math.abs(nl.anchor_position.x - sp.center.x) < 1e-6 && Math.abs(nl.anchor_position.y - sp.center.y) < 1e-6;
|
|
10171
|
+
if (!samePos) return false;
|
|
10172
|
+
if (sourceNet.source_net_id && nl.source_net_id) {
|
|
10173
|
+
return nl.source_net_id === sourceNet.source_net_id;
|
|
10174
|
+
}
|
|
10175
|
+
return nl.text === (sourceNet.name || key);
|
|
10176
|
+
});
|
|
10177
|
+
if (existingAtPort) continue;
|
|
10178
|
+
const text = sourceNet.name || sourceNet.source_net_id || key;
|
|
10179
|
+
const side = getEnteringEdgeFromDirection(sp.facing_direction || "right") || "right";
|
|
10180
|
+
const center = computeSchematicNetLabelCenter({
|
|
10181
|
+
anchor_position: sp.center,
|
|
10182
|
+
anchor_side: side,
|
|
10183
|
+
text
|
|
10184
|
+
});
|
|
10185
|
+
db.schematic_net_label.insert({
|
|
10186
|
+
text,
|
|
10187
|
+
anchor_position: sp.center,
|
|
10188
|
+
center,
|
|
10189
|
+
anchor_side: side,
|
|
10190
|
+
...sourceNet.source_net_id ? { source_net_id: sourceNet.source_net_id } : {}
|
|
10191
|
+
});
|
|
10192
|
+
}
|
|
10193
|
+
};
|
|
10194
|
+
|
|
10195
|
+
// lib/components/primitive-components/Group/Group_doInitialSchematicTraceRender/Group_doInitialSchematicTraceRender.ts
|
|
10196
|
+
var debug7 = Debug8("Group_doInitialSchematicTraceRender");
|
|
10197
|
+
var Group_doInitialSchematicTraceRender = (group) => {
|
|
10198
|
+
if (!group.root?._featureMspSchematicTraceRouting) return;
|
|
10199
|
+
if (!group.isSubcircuit) return;
|
|
10200
|
+
if (group.root?.schematicDisabled) return;
|
|
10201
|
+
const {
|
|
10202
|
+
inputProblem,
|
|
10203
|
+
pinIdToSchematicPortId,
|
|
10204
|
+
pairKeyToSourceTraceId,
|
|
10205
|
+
sckToSourceNet,
|
|
10206
|
+
allSourceAndSchematicPortIdsInScope,
|
|
10207
|
+
schPortIdToSourcePortId,
|
|
10208
|
+
displayLabelTraces,
|
|
10209
|
+
allScks,
|
|
10210
|
+
userNetIdToSck
|
|
10211
|
+
} = createSchematicTraceSolverInputProblem(group);
|
|
10212
|
+
if (debug7.enabled) {
|
|
10213
|
+
globalThis.debugOutputs?.add(
|
|
10214
|
+
"group-trace-render-input-problem",
|
|
10215
|
+
JSON.stringify(inputProblem, null, 2)
|
|
10216
|
+
);
|
|
10217
|
+
}
|
|
10218
|
+
const solver = new SchematicTracePipelineSolver4(inputProblem);
|
|
10219
|
+
solver.solve();
|
|
10220
|
+
applyTracesFromSolverOutput({
|
|
10221
|
+
group,
|
|
10222
|
+
solver,
|
|
10223
|
+
pinIdToSchematicPortId,
|
|
10224
|
+
pairKeyToSourceTraceId
|
|
10225
|
+
});
|
|
10226
|
+
applyNetLabelPlacements({
|
|
10227
|
+
group,
|
|
10228
|
+
solver,
|
|
10229
|
+
sckToSourceNet,
|
|
10230
|
+
allSourceAndSchematicPortIdsInScope,
|
|
10231
|
+
schPortIdToSourcePortId,
|
|
10232
|
+
allScks,
|
|
10233
|
+
userNetIdToSck
|
|
10234
|
+
});
|
|
10235
|
+
insertNetLabelsForPortsMissingTrace({
|
|
10236
|
+
group,
|
|
10237
|
+
allSourceAndSchematicPortIdsInScope,
|
|
10238
|
+
schPortIdToSourcePortId,
|
|
10239
|
+
sckToSourceNet
|
|
10240
|
+
});
|
|
10241
|
+
insertNetLabelsForTracesExcludedFromRouting({
|
|
10242
|
+
group,
|
|
10243
|
+
solver,
|
|
10244
|
+
displayLabelTraces
|
|
10245
|
+
});
|
|
10246
|
+
};
|
|
10247
|
+
|
|
10248
|
+
// lib/components/primitive-components/Group/Group.ts
|
|
10249
|
+
var Group6 = class extends NormalComponent {
|
|
9504
10250
|
constructor() {
|
|
9505
10251
|
super(...arguments);
|
|
9506
10252
|
__publicField(this, "pcb_group_id", null);
|
|
@@ -9668,20 +10414,20 @@ var Group = class extends NormalComponent {
|
|
|
9668
10414
|
return false;
|
|
9669
10415
|
}
|
|
9670
10416
|
_hasTracesToRoute() {
|
|
9671
|
-
const
|
|
10417
|
+
const debug8 = Debug9("tscircuit:core:_hasTracesToRoute");
|
|
9672
10418
|
const traces = this.selectAll("trace");
|
|
9673
|
-
|
|
10419
|
+
debug8(`[${this.getString()}] has ${traces.length} traces to route`);
|
|
9674
10420
|
return traces.length > 0;
|
|
9675
10421
|
}
|
|
9676
10422
|
async _runEffectMakeHttpAutoroutingRequest() {
|
|
9677
10423
|
const { db } = this.root;
|
|
9678
|
-
const
|
|
10424
|
+
const debug8 = Debug9("tscircuit:core:_runEffectMakeHttpAutoroutingRequest");
|
|
9679
10425
|
const props = this._parsedProps;
|
|
9680
10426
|
const autorouterConfig = this._getAutorouterConfig();
|
|
9681
10427
|
const serverUrl = autorouterConfig.serverUrl;
|
|
9682
10428
|
const serverMode = autorouterConfig.serverMode;
|
|
9683
10429
|
const fetchWithDebug = (url, options) => {
|
|
9684
|
-
|
|
10430
|
+
debug8("fetching", url);
|
|
9685
10431
|
if (options.headers) {
|
|
9686
10432
|
options.headers["Tscircuit-Core-Version"] = this.root?.getCoreVersion();
|
|
9687
10433
|
}
|
|
@@ -9797,15 +10543,15 @@ var Group = class extends NormalComponent {
|
|
|
9797
10543
|
async _runLocalAutorouting() {
|
|
9798
10544
|
const { db } = this.root;
|
|
9799
10545
|
const props = this._parsedProps;
|
|
9800
|
-
const
|
|
9801
|
-
|
|
10546
|
+
const debug8 = Debug9("tscircuit:core:_runLocalAutorouting");
|
|
10547
|
+
debug8(`[${this.getString()}] starting local autorouting`);
|
|
9802
10548
|
const autorouterConfig = this._getAutorouterConfig();
|
|
9803
10549
|
const { simpleRouteJson } = getSimpleRouteJsonFromCircuitJson({
|
|
9804
10550
|
db,
|
|
9805
10551
|
minTraceWidth: this.props.autorouter?.minTraceWidth ?? 0.15,
|
|
9806
10552
|
subcircuit_id: this.subcircuit_id
|
|
9807
10553
|
});
|
|
9808
|
-
if (
|
|
10554
|
+
if (debug8.enabled) {
|
|
9809
10555
|
const graphicsObject = convertSrjToGraphicsObject(
|
|
9810
10556
|
simpleRouteJson
|
|
9811
10557
|
);
|
|
@@ -9830,11 +10576,11 @@ var Group = class extends NormalComponent {
|
|
|
9830
10576
|
const routingPromise = new Promise(
|
|
9831
10577
|
(resolve, reject) => {
|
|
9832
10578
|
autorouter.on("complete", (event) => {
|
|
9833
|
-
|
|
10579
|
+
debug8(`[${this.getString()}] local autorouting complete`);
|
|
9834
10580
|
resolve(event.traces);
|
|
9835
10581
|
});
|
|
9836
10582
|
autorouter.on("error", (event) => {
|
|
9837
|
-
|
|
10583
|
+
debug8(
|
|
9838
10584
|
`[${this.getString()}] local autorouting error: ${event.error.message}`
|
|
9839
10585
|
);
|
|
9840
10586
|
reject(event.error);
|
|
@@ -9891,30 +10637,33 @@ var Group = class extends NormalComponent {
|
|
|
9891
10637
|
}
|
|
9892
10638
|
}
|
|
9893
10639
|
doInitialPcbTraceRender() {
|
|
9894
|
-
const
|
|
10640
|
+
const debug8 = Debug9("tscircuit:core:doInitialPcbTraceRender");
|
|
9895
10641
|
if (!this.isSubcircuit) return;
|
|
9896
10642
|
if (this.root?.pcbDisabled) return;
|
|
9897
10643
|
if (this.getInheritedProperty("routingDisabled")) return;
|
|
9898
10644
|
if (this._shouldUseTraceByTraceRouting()) return;
|
|
9899
10645
|
if (!this._areChildSubcircuitsRouted()) {
|
|
9900
|
-
|
|
10646
|
+
debug8(
|
|
9901
10647
|
`[${this.getString()}] child subcircuits are not routed, skipping async autorouting until subcircuits routed`
|
|
9902
10648
|
);
|
|
9903
10649
|
return;
|
|
9904
10650
|
}
|
|
9905
|
-
|
|
10651
|
+
debug8(
|
|
9906
10652
|
`[${this.getString()}] no child subcircuits to wait for, initiating async routing`
|
|
9907
10653
|
);
|
|
9908
10654
|
if (!this._hasTracesToRoute()) return;
|
|
9909
10655
|
this._startAsyncAutorouting();
|
|
9910
10656
|
}
|
|
10657
|
+
doInitialSchematicTraceRender() {
|
|
10658
|
+
Group_doInitialSchematicTraceRender(this);
|
|
10659
|
+
}
|
|
9911
10660
|
updatePcbTraceRender() {
|
|
9912
|
-
const
|
|
9913
|
-
|
|
10661
|
+
const debug8 = Debug9("tscircuit:core:updatePcbTraceRender");
|
|
10662
|
+
debug8(`[${this.getString()}] updating...`);
|
|
9914
10663
|
if (!this.isSubcircuit) return;
|
|
9915
10664
|
if (this._shouldRouteAsync() && this._hasTracesToRoute() && !this._hasStartedAsyncAutorouting) {
|
|
9916
10665
|
if (this._areChildSubcircuitsRouted()) {
|
|
9917
|
-
|
|
10666
|
+
debug8(
|
|
9918
10667
|
`[${this.getString()}] child subcircuits are now routed, starting async autorouting`
|
|
9919
10668
|
);
|
|
9920
10669
|
this._startAsyncAutorouting();
|
|
@@ -9925,14 +10674,14 @@ var Group = class extends NormalComponent {
|
|
|
9925
10674
|
if (this._shouldUseTraceByTraceRouting()) return;
|
|
9926
10675
|
const { db } = this.root;
|
|
9927
10676
|
if (this._asyncAutoroutingResult.output_simple_route_json) {
|
|
9928
|
-
|
|
10677
|
+
debug8(
|
|
9929
10678
|
`[${this.getString()}] updating PCB traces from simple route json (${this._asyncAutoroutingResult.output_simple_route_json.traces?.length} traces)`
|
|
9930
10679
|
);
|
|
9931
10680
|
this._updatePcbTraceRenderFromSimpleRouteJson();
|
|
9932
10681
|
return;
|
|
9933
10682
|
}
|
|
9934
10683
|
if (this._asyncAutoroutingResult.output_pcb_traces) {
|
|
9935
|
-
|
|
10684
|
+
debug8(
|
|
9936
10685
|
`[${this.getString()}] updating PCB traces from ${this._asyncAutoroutingResult.output_pcb_traces.length} traces`
|
|
9937
10686
|
);
|
|
9938
10687
|
this._updatePcbTraceRenderFromPcbTraces();
|
|
@@ -10236,7 +10985,7 @@ import {
|
|
|
10236
10985
|
checkEachPcbPortConnectedToPcbTraces,
|
|
10237
10986
|
checkEachPcbTraceNonOverlapping
|
|
10238
10987
|
} from "@tscircuit/checks";
|
|
10239
|
-
var Board = class extends
|
|
10988
|
+
var Board = class extends Group6 {
|
|
10240
10989
|
constructor() {
|
|
10241
10990
|
super(...arguments);
|
|
10242
10991
|
__publicField(this, "pcb_board_id", null);
|
|
@@ -11412,7 +12161,7 @@ var FabricationNoteText = class extends PrimitiveComponent2 {
|
|
|
11412
12161
|
|
|
11413
12162
|
// lib/components/primitive-components/Group/Subcircuit.ts
|
|
11414
12163
|
import "@tscircuit/props";
|
|
11415
|
-
var Subcircuit = class extends
|
|
12164
|
+
var Subcircuit = class extends Group6 {
|
|
11416
12165
|
constructor(props) {
|
|
11417
12166
|
super({
|
|
11418
12167
|
...props,
|
|
@@ -11423,7 +12172,7 @@ var Subcircuit = class extends Group {
|
|
|
11423
12172
|
|
|
11424
12173
|
// lib/components/primitive-components/Breakout/Breakout.ts
|
|
11425
12174
|
import "@tscircuit/props";
|
|
11426
|
-
var Breakout = class extends
|
|
12175
|
+
var Breakout = class extends Group6 {
|
|
11427
12176
|
constructor(props) {
|
|
11428
12177
|
super({
|
|
11429
12178
|
...props,
|
|
@@ -12854,7 +13603,7 @@ import { identity as identity5 } from "transformation-matrix";
|
|
|
12854
13603
|
var package_default = {
|
|
12855
13604
|
name: "@tscircuit/core",
|
|
12856
13605
|
type: "module",
|
|
12857
|
-
version: "0.0.
|
|
13606
|
+
version: "0.0.645",
|
|
12858
13607
|
types: "dist/index.d.ts",
|
|
12859
13608
|
main: "dist/index.js",
|
|
12860
13609
|
module: "dist/index.js",
|
|
@@ -12884,8 +13633,8 @@ var package_default = {
|
|
|
12884
13633
|
devDependencies: {
|
|
12885
13634
|
"@biomejs/biome": "^1.8.3",
|
|
12886
13635
|
"@tscircuit/capacity-autorouter": "^0.0.100",
|
|
12887
|
-
"@tscircuit/circuit-json-util": "^0.0.65",
|
|
12888
13636
|
"@tscircuit/checks": "^0.0.71",
|
|
13637
|
+
"@tscircuit/circuit-json-util": "^0.0.65",
|
|
12889
13638
|
"@tscircuit/footprinter": "^0.0.208",
|
|
12890
13639
|
"@tscircuit/import-snippet": "^0.0.4",
|
|
12891
13640
|
"@tscircuit/infgrid-ijump-astar": "^0.0.33",
|
|
@@ -12897,6 +13646,7 @@ var package_default = {
|
|
|
12897
13646
|
"@tscircuit/schematic-autolayout": "^0.0.6",
|
|
12898
13647
|
"@tscircuit/schematic-corpus": "^0.0.110",
|
|
12899
13648
|
"@tscircuit/schematic-match-adapt": "^0.0.16",
|
|
13649
|
+
"@tscircuit/schematic-trace-solver": "^0.0.12",
|
|
12900
13650
|
"@tscircuit/simple-3d-svg": "^0.0.38",
|
|
12901
13651
|
"@types/bun": "^1.2.16",
|
|
12902
13652
|
"@types/debug": "^4.1.12",
|
|
@@ -12913,6 +13663,7 @@ var package_default = {
|
|
|
12913
13663
|
"circuit-json-to-simple-3d": "^0.0.6",
|
|
12914
13664
|
"circuit-to-svg": "^0.0.174",
|
|
12915
13665
|
concurrently: "^9.1.2",
|
|
13666
|
+
"connectivity-map": "^1.0.0",
|
|
12916
13667
|
debug: "^4.3.6",
|
|
12917
13668
|
"graphics-debug": "^0.0.60",
|
|
12918
13669
|
howfat: "^0.3.8",
|
|
@@ -12973,6 +13724,7 @@ var RootCircuit = class {
|
|
|
12973
13724
|
__publicField(this, "schematicDisabled", false);
|
|
12974
13725
|
__publicField(this, "pcbDisabled", false);
|
|
12975
13726
|
__publicField(this, "pcbRoutingDisabled", false);
|
|
13727
|
+
__publicField(this, "_featureMspSchematicTraceRouting", false);
|
|
12976
13728
|
/**
|
|
12977
13729
|
* The RootCircuit name is usually set by the platform, it's not required but
|
|
12978
13730
|
* if supplied can identify the circuit in certain effects, e.g. it is passed
|
|
@@ -13023,7 +13775,7 @@ var RootCircuit = class {
|
|
|
13023
13775
|
this.firstChild = this.children[0];
|
|
13024
13776
|
return;
|
|
13025
13777
|
}
|
|
13026
|
-
const group = new
|
|
13778
|
+
const group = new Group6({ subcircuit: true });
|
|
13027
13779
|
group.parent = this;
|
|
13028
13780
|
group.addAll(this.children);
|
|
13029
13781
|
this.children = [group];
|
|
@@ -13362,7 +14114,7 @@ export {
|
|
|
13362
14114
|
FabricationNoteText,
|
|
13363
14115
|
Footprint,
|
|
13364
14116
|
Fuse,
|
|
13365
|
-
Group,
|
|
14117
|
+
Group6 as Group,
|
|
13366
14118
|
Hole,
|
|
13367
14119
|
Inductor,
|
|
13368
14120
|
Jumper,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.646",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@biomejs/biome": "^1.8.3",
|
|
33
33
|
"@tscircuit/capacity-autorouter": "^0.0.100",
|
|
34
|
-
"@tscircuit/circuit-json-util": "^0.0.65",
|
|
35
34
|
"@tscircuit/checks": "^0.0.71",
|
|
35
|
+
"@tscircuit/circuit-json-util": "^0.0.65",
|
|
36
36
|
"@tscircuit/footprinter": "^0.0.208",
|
|
37
37
|
"@tscircuit/import-snippet": "^0.0.4",
|
|
38
38
|
"@tscircuit/infgrid-ijump-astar": "^0.0.33",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"@tscircuit/schematic-autolayout": "^0.0.6",
|
|
45
45
|
"@tscircuit/schematic-corpus": "^0.0.110",
|
|
46
46
|
"@tscircuit/schematic-match-adapt": "^0.0.16",
|
|
47
|
+
"@tscircuit/schematic-trace-solver": "^0.0.12",
|
|
47
48
|
"@tscircuit/simple-3d-svg": "^0.0.38",
|
|
48
49
|
"@types/bun": "^1.2.16",
|
|
49
50
|
"@types/debug": "^4.1.12",
|
|
@@ -60,6 +61,7 @@
|
|
|
60
61
|
"circuit-json-to-simple-3d": "^0.0.6",
|
|
61
62
|
"circuit-to-svg": "^0.0.174",
|
|
62
63
|
"concurrently": "^9.1.2",
|
|
64
|
+
"connectivity-map": "^1.0.0",
|
|
63
65
|
"debug": "^4.3.6",
|
|
64
66
|
"graphics-debug": "^0.0.60",
|
|
65
67
|
"howfat": "^0.3.8",
|