@tscircuit/core 0.0.331 → 0.0.332
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 +27 -10
- package/dist/index.js +516 -211
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _tscircuit_props from '@tscircuit/props';
|
|
2
|
-
import { subcircuitGroupProps, traceProps, SupplierPartNumbers, SchematicPortArrangement, groupProps,
|
|
2
|
+
import { subcircuitGroupProps, AutorouterConfig, traceProps, SupplierPartNumbers, SchematicPortArrangement, groupProps, boardProps, capacitorProps, chipProps, diodeProps, jumperProps, ledProps, powerSourceProps, resistorProps, constraintProps, fabricationNotePathProps, fabricationNoteTextProps, footprintProps, subcircuitProps, holeProps, pcbKeepoutProps, netAliasProps, platedHoleProps, silkscreenCircleProps, silkscreenPathProps, silkscreenRectProps, silkscreenTextProps, silkscreenLineProps, smtPadProps, traceHintProps, viaProps, batteryProps, pinHeaderProps, resonatorProps, inductorProps, potentiometerProps, pushButtonProps, crystalProps, transistorProps, mosfetProps, switchProps, CapacitorProps, ChipProps, ResistorProps, ManualEditEvent, manual_edits_file } from '@tscircuit/props';
|
|
3
3
|
import React, { ReactElement, DetailedHTMLProps, SVGProps } from 'react';
|
|
4
4
|
export { createElement } from 'react';
|
|
5
5
|
import * as zod from 'zod';
|
|
@@ -9,6 +9,7 @@ import { PcbTraceError, PcbPlacementError, PcbManualEditConflictError, LayerRef,
|
|
|
9
9
|
import { Matrix } from 'transformation-matrix';
|
|
10
10
|
import { SoupUtilObjects } from '@tscircuit/soup-util';
|
|
11
11
|
import * as _tscircuit_layout from '@tscircuit/layout';
|
|
12
|
+
import { ConnectivityMap } from 'circuit-json-to-connectivity-map';
|
|
12
13
|
|
|
13
14
|
declare const orderedRenderPhases: readonly ["ReactSubtreesRender", "InitializePortsFromChildren", "CreateNetsFromProps", "CreateTracesFromProps", "CreateTraceHintsFromProps", "SourceRender", "SourceParentAttachment", "PortMatching", "SourceTraceRender", "SourceAddConnectivityMapKey", "SchematicComponentRender", "SchematicPortRender", "SchematicLayout", "SchematicTraceRender", "PcbComponentRender", "PcbPrimitiveRender", "PcbFootprintLayout", "PcbPortRender", "PcbPortAttachment", "PcbLayout", "PcbComponentSizeCalculation", "PcbBoardAutoSize", "PcbTraceRender", "PcbTraceHintRender", "PcbRouteNetIslands", "CadModelRender", "PartsEngineRender"];
|
|
14
15
|
type RenderPhase = (typeof orderedRenderPhases)[number];
|
|
@@ -103,7 +104,7 @@ interface SchematicBoxDimensions {
|
|
|
103
104
|
};
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
type RootCircuitEventName = "asyncEffect:start" | "asyncEffect:end" | "renderable:renderLifecycle:anyEvent" | `renderable:renderLifecycle:${RenderPhase}:start` | `renderable:renderLifecycle:${RenderPhase}:end` | "external:evalError";
|
|
107
|
+
type RootCircuitEventName = "asyncEffect:start" | "asyncEffect:end" | "renderable:renderLifecycle:anyEvent" | `renderable:renderLifecycle:${RenderPhase}:start` | `renderable:renderLifecycle:${RenderPhase}:end` | "external:evalError" | "autorouting:start" | "autorouting:end" | "autorouting:progress";
|
|
107
108
|
declare class RootCircuit {
|
|
108
109
|
firstChild: PrimitiveComponent | null;
|
|
109
110
|
children: PrimitiveComponent[];
|
|
@@ -169,6 +170,7 @@ declare const Circuit: typeof RootCircuit;
|
|
|
169
170
|
interface ISubcircuit extends PrimitiveComponent {
|
|
170
171
|
_shouldUseTraceByTraceRouting(): boolean;
|
|
171
172
|
_parsedProps: z.infer<typeof subcircuitGroupProps>;
|
|
173
|
+
_getAutorouterConfig(): AutorouterConfig;
|
|
172
174
|
subcircuit_id: string | null;
|
|
173
175
|
}
|
|
174
176
|
|
|
@@ -391,6 +393,7 @@ declare class Net extends PrimitiveComponent<typeof netProps> {
|
|
|
391
393
|
};
|
|
392
394
|
getPortSelector(): string;
|
|
393
395
|
doInitialSourceRender(): void;
|
|
396
|
+
doInitialSourceParentAttachment(): void;
|
|
394
397
|
/**
|
|
395
398
|
* Get all ports connected to this net.
|
|
396
399
|
*
|
|
@@ -412,6 +415,8 @@ declare class Net extends PrimitiveComponent<typeof netProps> {
|
|
|
412
415
|
* Sometimes this phase doesn't find any net islands if the autorouter did
|
|
413
416
|
* a good job and connected the islands. In some sense this is a "backup"
|
|
414
417
|
* routing phase for autorouters that don't care about connecting nets.
|
|
418
|
+
*
|
|
419
|
+
* This should only run if the autorouter is sequential-trace
|
|
415
420
|
*/
|
|
416
421
|
doInitialPcbRouteNetIslands(): void;
|
|
417
422
|
renderError(message: Parameters<typeof PrimitiveComponent.prototype.renderError>[0]): void;
|
|
@@ -903,6 +908,7 @@ declare class NormalComponent<ZodProps extends ZodType = any, PortNames extends
|
|
|
903
908
|
type SimplifiedPcbTrace = {
|
|
904
909
|
type: "pcb_trace";
|
|
905
910
|
pcb_trace_id: string;
|
|
911
|
+
connection_name?: string;
|
|
906
912
|
route: Array<{
|
|
907
913
|
route_type: "wire";
|
|
908
914
|
x: number;
|
|
@@ -966,12 +972,15 @@ declare class Group<Props extends z.ZodType<any, any, any> = typeof groupProps>
|
|
|
966
972
|
doInitialSourceParentAttachment(): void;
|
|
967
973
|
doInitialPcbComponentRender(): void;
|
|
968
974
|
doInitialCreateTraceHintsFromProps(): void;
|
|
969
|
-
_getSimpleRouteJsonFromPcbTraces(): SimpleRouteJson;
|
|
970
975
|
doInitialSourceAddConnectivityMapKey(): void;
|
|
971
976
|
_areChildSubcircuitsRouted(): boolean;
|
|
972
977
|
_shouldRouteAsync(): boolean;
|
|
973
978
|
_hasTracesToRoute(): boolean;
|
|
974
979
|
_runEffectMakeHttpAutoroutingRequest(): Promise<void>;
|
|
980
|
+
/**
|
|
981
|
+
* Run local autorouting using the CapacityMeshAutorouter
|
|
982
|
+
*/
|
|
983
|
+
_runLocalCapacityMeshAutorouting(): Promise<void>;
|
|
975
984
|
_startAsyncAutorouting(): void;
|
|
976
985
|
doInitialPcbTraceRender(): void;
|
|
977
986
|
updatePcbTraceRender(): void;
|
|
@@ -10715,10 +10724,15 @@ declare const applyEditEventsToManualEditsFile: ({ circuitJson, editEvents, manu
|
|
|
10715
10724
|
/**
|
|
10716
10725
|
* This function can only be called in the PcbTraceRender phase or later
|
|
10717
10726
|
*/
|
|
10718
|
-
declare const getSimpleRouteJsonFromCircuitJson: ({ circuitJson, minTraceWidth, }: {
|
|
10719
|
-
|
|
10727
|
+
declare const getSimpleRouteJsonFromCircuitJson: ({ db, circuitJson, subcircuit_id, minTraceWidth, }: {
|
|
10728
|
+
db?: SoupUtilObjects;
|
|
10729
|
+
circuitJson?: AnyCircuitElement[];
|
|
10730
|
+
subcircuit_id?: string | null;
|
|
10720
10731
|
minTraceWidth?: number;
|
|
10721
|
-
}) =>
|
|
10732
|
+
}) => {
|
|
10733
|
+
simpleRouteJson: SimpleRouteJson;
|
|
10734
|
+
connMap: ConnectivityMap;
|
|
10735
|
+
};
|
|
10722
10736
|
|
|
10723
10737
|
type RenderEvent = {
|
|
10724
10738
|
type: string;
|
|
@@ -10737,7 +10751,7 @@ declare const getPhaseTimingsFromRenderEvents: (renderEvents: RenderEvent[]) =>
|
|
|
10737
10751
|
type Nums16 = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "10" | "11" | "12" | "13" | "14" | "15" | "16";
|
|
10738
10752
|
type Nums40 = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "10" | "11" | "12" | "13" | "14" | "15" | "16" | "17" | "18" | "19" | "20" | "21" | "22" | "23" | "24" | "25" | "26" | "27" | "28" | "29" | "30" | "31" | "32" | "33" | "34" | "35" | "36" | "37" | "38" | "39" | "40";
|
|
10739
10753
|
type PinNumbers100 = "pin1" | "pin2" | "pin3" | "pin4" | "pin5" | "pin6" | "pin7" | "pin8" | "pin9" | "pin10" | "pin11" | "pin12" | "pin13" | "pin14" | "pin15" | "pin16" | "pin17" | "pin18" | "pin19" | "pin20" | "pin21" | "pin22" | "pin23" | "pin24" | "pin25" | "pin26" | "pin27" | "pin28" | "pin29" | "pin30" | "pin31" | "pin32" | "pin33" | "pin34" | "pin35" | "pin36" | "pin37" | "pin38" | "pin39" | "pin40" | "pin41" | "pin42" | "pin43" | "pin44" | "pin45" | "pin46" | "pin47" | "pin48" | "pin49" | "pin50" | "pin51" | "pin52" | "pin53" | "pin54" | "pin55" | "pin56" | "pin57" | "pin58" | "pin59" | "pin60" | "pin61" | "pin62" | "pin63" | "pin64" | "pin65" | "pin66" | "pin67" | "pin68" | "pin69" | "pin70" | "pin71" | "pin72" | "pin73" | "pin74" | "pin75" | "pin76" | "pin77" | "pin78" | "pin79" | "pin80" | "pin81" | "pin82" | "pin83" | "pin84" | "pin85" | "pin86" | "pin87" | "pin88" | "pin89" | "pin90" | "pin91" | "pin92" | "pin93" | "pin94" | "pin95" | "pin96" | "pin97" | "pin98" | "pin99" | "pin100";
|
|
10740
|
-
type CommonPinNames = "pos" | "neg" | "V5" | "V3_3" | "VCC" | "VDD" | "GND" | `D${Nums40}` | `GP${Nums40}` | `GPIO${Nums40}` | "DP" | "DN" | "VIN" | "VOUT" | "VREF" | "VIN" | "VOUT" | "VREF" | "VIN" | "VOUT" | "VREF" | "OUT" | "DISCH" | "EN" | "IN" | "CLK" | "DATA" | "THRES" | "TRIG" | "RESET" | `A${Nums40}` | `B${Nums40}` | PinNumbers100;
|
|
10754
|
+
type CommonPinNames = "pos" | "neg" | "V5" | "V3_3" | "PWR" | "VCC" | "VDD" | "GND" | `D${Nums40}` | `GP${Nums40}` | `GPIO${Nums40}` | "DP" | "DN" | "VIN" | "VOUT" | "VREF" | "VIN" | "VOUT" | "VREF" | "VIN" | "VOUT" | "VREF" | "OUT" | "DISCH" | "EN" | "IN" | "CLK" | "DATA" | "THRES" | "TRIG" | "RESET" | `A${Nums40}` | `B${Nums40}` | PinNumbers100;
|
|
10741
10755
|
type TransistorPinNames = "base" | "collector" | "emitter";
|
|
10742
10756
|
|
|
10743
10757
|
type NonPolarizedSel = Record<`R${Nums40}`, {
|
|
@@ -10762,12 +10776,15 @@ type PolarizedSel = Record<`C${Nums40}` | `L${Nums40}` | `LED${Nums40}` | `D${Nu
|
|
|
10762
10776
|
pos: string;
|
|
10763
10777
|
neg: string;
|
|
10764
10778
|
}>;
|
|
10779
|
+
type CommonNetNames = "VCC" | "GND" | "VDD" | "PWR" | "V5" | "V3_3";
|
|
10765
10780
|
type TransistorSel = Record<`Q${Nums40}`, Record<TransistorPinNames, string>>;
|
|
10766
|
-
type JumperSel = Record<`J${Nums40}`, Record<PinNumbers100, string>>;
|
|
10781
|
+
type JumperSel = Record<`J${Nums40}`, Record<PinNumbers100 | CommonPinNames, string>>;
|
|
10767
10782
|
type ChipSel = Record<`U${Nums40}`, Record<CommonPinNames, string>>;
|
|
10768
|
-
type NetSel = Record<"net", Record<
|
|
10783
|
+
type NetSel = Record<"net", Record<CommonNetNames, string>>;
|
|
10769
10784
|
type ConnectionSel = Record<`CN${Nums40}`, Record<CommonPinNames, string>>;
|
|
10770
|
-
type
|
|
10785
|
+
type SubcircuitSel = Record<"subcircuit", Record<`S${Nums40}`, SelWithoutSubcircuit>>;
|
|
10786
|
+
type SelWithoutSubcircuit = NonPolarizedSel & PolarizedSel & TransistorSel & JumperSel & ChipSel & SwSel & NetSel & ConnectionSel;
|
|
10787
|
+
type Sel = SubcircuitSel & SelWithoutSubcircuit;
|
|
10771
10788
|
declare const sel: Sel;
|
|
10772
10789
|
|
|
10773
10790
|
interface TscircuitElements {
|
package/dist/index.js
CHANGED
|
@@ -1192,6 +1192,14 @@ var Net = class extends PrimitiveComponent {
|
|
|
1192
1192
|
});
|
|
1193
1193
|
this.source_net_id = net.source_net_id;
|
|
1194
1194
|
}
|
|
1195
|
+
doInitialSourceParentAttachment() {
|
|
1196
|
+
const subcircuit = this.getSubcircuit();
|
|
1197
|
+
if (!subcircuit) return;
|
|
1198
|
+
const { db } = this.root;
|
|
1199
|
+
db.source_net.update(this.source_net_id, {
|
|
1200
|
+
subcircuit_id: subcircuit.subcircuit_id
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1195
1203
|
/**
|
|
1196
1204
|
* Get all ports connected to this net.
|
|
1197
1205
|
*
|
|
@@ -1235,10 +1243,14 @@ var Net = class extends PrimitiveComponent {
|
|
|
1235
1243
|
* Sometimes this phase doesn't find any net islands if the autorouter did
|
|
1236
1244
|
* a good job and connected the islands. In some sense this is a "backup"
|
|
1237
1245
|
* routing phase for autorouters that don't care about connecting nets.
|
|
1246
|
+
*
|
|
1247
|
+
* This should only run if the autorouter is sequential-trace
|
|
1238
1248
|
*/
|
|
1239
1249
|
doInitialPcbRouteNetIslands() {
|
|
1240
1250
|
if (this.root?.pcbDisabled) return;
|
|
1241
1251
|
if (this.getSubcircuit()._parsedProps.routingDisabled) return;
|
|
1252
|
+
if (this.getSubcircuit()._getAutorouterConfig().groupMode !== "sequential-trace")
|
|
1253
|
+
return;
|
|
1242
1254
|
const { db } = this.root;
|
|
1243
1255
|
const { _parsedProps: props } = this;
|
|
1244
1256
|
const traces = this._getAllDirectlyConnectedTraces().filter(
|
|
@@ -1335,8 +1347,12 @@ var Net = class extends PrimitiveComponent {
|
|
|
1335
1347
|
var createNetsFromProps = (component, props) => {
|
|
1336
1348
|
for (const prop of props) {
|
|
1337
1349
|
if (typeof prop === "string" && prop.startsWith("net.")) {
|
|
1338
|
-
|
|
1339
|
-
|
|
1350
|
+
const subcircuit = component.getSubcircuit();
|
|
1351
|
+
if (!subcircuit.selectOne(prop)) {
|
|
1352
|
+
const net = new Net({
|
|
1353
|
+
name: prop.split("net.")[1]
|
|
1354
|
+
});
|
|
1355
|
+
subcircuit.add(net);
|
|
1340
1356
|
}
|
|
1341
1357
|
}
|
|
1342
1358
|
}
|
|
@@ -2284,7 +2300,8 @@ var Port = class extends PrimitiveComponent {
|
|
|
2284
2300
|
);
|
|
2285
2301
|
}
|
|
2286
2302
|
db.source_port.update(this.source_port_id, {
|
|
2287
|
-
source_component_id: this.parent?.source_component_id
|
|
2303
|
+
source_component_id: this.parent?.source_component_id,
|
|
2304
|
+
subcircuit_id: this.getSubcircuit()?.subcircuit_id
|
|
2288
2305
|
});
|
|
2289
2306
|
this.source_component_id = this.parent?.source_component_id;
|
|
2290
2307
|
}
|
|
@@ -2967,6 +2984,7 @@ var DirectLineRouter = class {
|
|
|
2967
2984
|
const trace = {
|
|
2968
2985
|
type: "pcb_trace",
|
|
2969
2986
|
pcb_trace_id: "",
|
|
2987
|
+
connection_name: connection.name,
|
|
2970
2988
|
route: [
|
|
2971
2989
|
{
|
|
2972
2990
|
route_type: "wire",
|
|
@@ -4689,7 +4707,6 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
4689
4707
|
if (symbol) {
|
|
4690
4708
|
const schematic_component2 = db.schematic_component.insert({
|
|
4691
4709
|
center,
|
|
4692
|
-
rotation: props.schRotation ?? 0,
|
|
4693
4710
|
size: symbol.size,
|
|
4694
4711
|
source_component_id: this.source_component_id,
|
|
4695
4712
|
symbol_name,
|
|
@@ -5133,64 +5150,156 @@ import {
|
|
|
5133
5150
|
groupProps
|
|
5134
5151
|
} from "@tscircuit/props";
|
|
5135
5152
|
import * as SAL from "@tscircuit/schematic-autolayout";
|
|
5136
|
-
import "circuit-json";
|
|
5137
|
-
import { ConnectivityMap } from "circuit-json-to-connectivity-map";
|
|
5138
|
-
import Debug5 from "debug";
|
|
5139
5153
|
|
|
5140
|
-
// lib/utils/autorouting/
|
|
5141
|
-
import {
|
|
5142
|
-
var
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
...db.pcb_plated_hole.list()
|
|
5151
|
-
]);
|
|
5152
|
-
const allPoints = obstacles.flatMap((o) => [
|
|
5153
|
-
{
|
|
5154
|
-
x: o.center.x - o.width / 2,
|
|
5155
|
-
y: o.center.y - o.height / 2
|
|
5156
|
-
},
|
|
5157
|
-
{
|
|
5158
|
-
x: o.center.x + o.width / 2,
|
|
5159
|
-
y: o.center.y + o.height / 2
|
|
5160
|
-
}
|
|
5161
|
-
]);
|
|
5162
|
-
const bounds = {
|
|
5163
|
-
minX: Math.min(...allPoints.map((p) => p.x)) - 1,
|
|
5164
|
-
maxX: Math.max(...allPoints.map((p) => p.x)) + 1,
|
|
5165
|
-
minY: Math.min(...allPoints.map((p) => p.y)) - 1,
|
|
5166
|
-
maxY: Math.max(...allPoints.map((p) => p.y)) + 1
|
|
5167
|
-
};
|
|
5168
|
-
const connections = traces.map((trace) => {
|
|
5169
|
-
const connectedPorts = trace._findConnectedPorts();
|
|
5170
|
-
if (!connectedPorts.allPortsFound || connectedPorts.ports.length < 2)
|
|
5171
|
-
return null;
|
|
5172
|
-
return {
|
|
5173
|
-
name: trace.source_trace_id ?? "",
|
|
5174
|
-
pointsToConnect: connectedPorts.ports.map((port) => {
|
|
5175
|
-
const pos = port._getGlobalPcbPositionBeforeLayout();
|
|
5176
|
-
return {
|
|
5177
|
-
x: pos.x,
|
|
5178
|
-
y: pos.y,
|
|
5179
|
-
layer: port.getAvailablePcbLayers()[0] ?? "top"
|
|
5180
|
-
};
|
|
5181
|
-
})
|
|
5182
|
-
};
|
|
5183
|
-
}).filter((c) => c !== null);
|
|
5184
|
-
return {
|
|
5185
|
-
bounds,
|
|
5186
|
-
obstacles: [],
|
|
5187
|
-
connections,
|
|
5188
|
-
layerCount: 2,
|
|
5189
|
-
minTraceWidth
|
|
5154
|
+
// lib/utils/autorouting/CapacityMeshAutorouter.ts
|
|
5155
|
+
import { CapacityMeshSolver } from "@tscircuit/capacity-autorouter";
|
|
5156
|
+
var CapacityMeshAutorouter = class {
|
|
5157
|
+
input;
|
|
5158
|
+
isRouting = false;
|
|
5159
|
+
solver;
|
|
5160
|
+
eventHandlers = {
|
|
5161
|
+
complete: [],
|
|
5162
|
+
error: [],
|
|
5163
|
+
progress: []
|
|
5190
5164
|
};
|
|
5165
|
+
cycleCount = 0;
|
|
5166
|
+
stepDelay;
|
|
5167
|
+
timeoutId;
|
|
5168
|
+
constructor(input, options = {}) {
|
|
5169
|
+
this.input = input;
|
|
5170
|
+
const { capacityDepth, targetMinCapacity, stepDelay = 0 } = options;
|
|
5171
|
+
this.solver = new CapacityMeshSolver(input, {
|
|
5172
|
+
capacityDepth,
|
|
5173
|
+
targetMinCapacity
|
|
5174
|
+
});
|
|
5175
|
+
this.stepDelay = stepDelay;
|
|
5176
|
+
}
|
|
5177
|
+
/**
|
|
5178
|
+
* Start the autorouting process asynchronously
|
|
5179
|
+
* This will emit progress events during routing and a complete event when done
|
|
5180
|
+
*/
|
|
5181
|
+
start() {
|
|
5182
|
+
if (this.isRouting) return;
|
|
5183
|
+
this.isRouting = true;
|
|
5184
|
+
this.cycleCount = 0;
|
|
5185
|
+
this.runCycleAndQueueNextCycle();
|
|
5186
|
+
}
|
|
5187
|
+
/**
|
|
5188
|
+
* Execute the next routing step and schedule the following one if needed
|
|
5189
|
+
*/
|
|
5190
|
+
runCycleAndQueueNextCycle() {
|
|
5191
|
+
if (!this.isRouting) return;
|
|
5192
|
+
try {
|
|
5193
|
+
if (this.solver.solved || this.solver.failed) {
|
|
5194
|
+
if (this.solver.failed) {
|
|
5195
|
+
this.emitEvent({
|
|
5196
|
+
type: "error",
|
|
5197
|
+
error: new Error(this.solver.error || "Routing failed")
|
|
5198
|
+
});
|
|
5199
|
+
} else {
|
|
5200
|
+
this.emitEvent({
|
|
5201
|
+
type: "complete",
|
|
5202
|
+
traces: this.solver.getOutputSimpleRouteJson().traces || []
|
|
5203
|
+
});
|
|
5204
|
+
}
|
|
5205
|
+
this.isRouting = false;
|
|
5206
|
+
return;
|
|
5207
|
+
}
|
|
5208
|
+
const startTime = performance.now();
|
|
5209
|
+
const startIterations = this.solver.iterations;
|
|
5210
|
+
while (performance.now() - startTime < 10 && !this.solver.failed && !this.solver.solved) {
|
|
5211
|
+
this.solver.step();
|
|
5212
|
+
}
|
|
5213
|
+
this.cycleCount++;
|
|
5214
|
+
const debugGraphics = this.solver.activeSolver?.visualize() || void 0;
|
|
5215
|
+
const progress = this.solver.progress;
|
|
5216
|
+
this.emitEvent({
|
|
5217
|
+
type: "progress",
|
|
5218
|
+
steps: this.cycleCount,
|
|
5219
|
+
progress,
|
|
5220
|
+
phase: this.solver.getCurrentPhase(),
|
|
5221
|
+
debugGraphics
|
|
5222
|
+
});
|
|
5223
|
+
if (this.stepDelay > 0) {
|
|
5224
|
+
this.timeoutId = setTimeout(
|
|
5225
|
+
() => this.runCycleAndQueueNextCycle(),
|
|
5226
|
+
this.stepDelay
|
|
5227
|
+
);
|
|
5228
|
+
} else {
|
|
5229
|
+
this.timeoutId = setTimeout(
|
|
5230
|
+
() => this.runCycleAndQueueNextCycle(),
|
|
5231
|
+
0
|
|
5232
|
+
);
|
|
5233
|
+
}
|
|
5234
|
+
} catch (error) {
|
|
5235
|
+
this.emitEvent({
|
|
5236
|
+
type: "error",
|
|
5237
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
5238
|
+
});
|
|
5239
|
+
this.isRouting = false;
|
|
5240
|
+
}
|
|
5241
|
+
}
|
|
5242
|
+
/**
|
|
5243
|
+
* Stop the routing process if it's in progress
|
|
5244
|
+
*/
|
|
5245
|
+
stop() {
|
|
5246
|
+
if (!this.isRouting) return;
|
|
5247
|
+
this.isRouting = false;
|
|
5248
|
+
if (this.timeoutId !== void 0) {
|
|
5249
|
+
clearTimeout(this.timeoutId);
|
|
5250
|
+
this.timeoutId = void 0;
|
|
5251
|
+
}
|
|
5252
|
+
}
|
|
5253
|
+
on(event, callback) {
|
|
5254
|
+
if (event === "complete") {
|
|
5255
|
+
this.eventHandlers.complete.push(
|
|
5256
|
+
callback
|
|
5257
|
+
);
|
|
5258
|
+
} else if (event === "error") {
|
|
5259
|
+
this.eventHandlers.error.push(
|
|
5260
|
+
callback
|
|
5261
|
+
);
|
|
5262
|
+
} else if (event === "progress") {
|
|
5263
|
+
this.eventHandlers.progress.push(
|
|
5264
|
+
callback
|
|
5265
|
+
);
|
|
5266
|
+
}
|
|
5267
|
+
}
|
|
5268
|
+
/**
|
|
5269
|
+
* Emit an event to all registered handlers
|
|
5270
|
+
*/
|
|
5271
|
+
emitEvent(event) {
|
|
5272
|
+
if (event.type === "complete") {
|
|
5273
|
+
for (const handler of this.eventHandlers.complete) {
|
|
5274
|
+
handler(event);
|
|
5275
|
+
}
|
|
5276
|
+
} else if (event.type === "error") {
|
|
5277
|
+
for (const handler of this.eventHandlers.error) {
|
|
5278
|
+
handler(event);
|
|
5279
|
+
}
|
|
5280
|
+
} else if (event.type === "progress") {
|
|
5281
|
+
for (const handler of this.eventHandlers.progress) {
|
|
5282
|
+
handler(event);
|
|
5283
|
+
}
|
|
5284
|
+
}
|
|
5285
|
+
}
|
|
5286
|
+
/**
|
|
5287
|
+
* Solve the routing problem synchronously
|
|
5288
|
+
* @returns Array of routed traces
|
|
5289
|
+
*/
|
|
5290
|
+
solveSync() {
|
|
5291
|
+
this.solver.solve();
|
|
5292
|
+
if (this.solver.failed) {
|
|
5293
|
+
throw new Error(this.solver.error || "Routing failed");
|
|
5294
|
+
}
|
|
5295
|
+
return this.solver.getOutputSimpleRouteJson().traces || [];
|
|
5296
|
+
}
|
|
5191
5297
|
};
|
|
5192
5298
|
|
|
5193
5299
|
// lib/components/primitive-components/Group/Group.ts
|
|
5300
|
+
import "circuit-json";
|
|
5301
|
+
import { ConnectivityMap as ConnectivityMap2 } from "circuit-json-to-connectivity-map";
|
|
5302
|
+
import Debug5 from "debug";
|
|
5194
5303
|
import "zod";
|
|
5195
5304
|
|
|
5196
5305
|
// lib/components/primitive-components/TraceHint.ts
|
|
@@ -5254,6 +5363,220 @@ var TraceHint = class extends PrimitiveComponent {
|
|
|
5254
5363
|
}
|
|
5255
5364
|
};
|
|
5256
5365
|
|
|
5366
|
+
// lib/utils/edit-events/apply-edit-events-to-manual-edits-file.ts
|
|
5367
|
+
import "zod";
|
|
5368
|
+
import { su } from "@tscircuit/soup-util";
|
|
5369
|
+
var applyEditEventsToManualEditsFile = ({
|
|
5370
|
+
circuitJson,
|
|
5371
|
+
editEvents,
|
|
5372
|
+
manualEditsFile
|
|
5373
|
+
}) => {
|
|
5374
|
+
const updatedManualEditsFile = {
|
|
5375
|
+
...manualEditsFile,
|
|
5376
|
+
schematic_placements: [...manualEditsFile.schematic_placements ?? []]
|
|
5377
|
+
};
|
|
5378
|
+
for (const editEvent of editEvents) {
|
|
5379
|
+
if (editEvent.edit_event_type === "edit_schematic_component_location") {
|
|
5380
|
+
const { schematic_component_id, new_center } = editEvent;
|
|
5381
|
+
const schematic_component2 = su(circuitJson).schematic_component.get(
|
|
5382
|
+
schematic_component_id
|
|
5383
|
+
);
|
|
5384
|
+
if (!schematic_component2) continue;
|
|
5385
|
+
const source_component = su(circuitJson).source_component.get(
|
|
5386
|
+
schematic_component2.source_component_id
|
|
5387
|
+
);
|
|
5388
|
+
if (!source_component) continue;
|
|
5389
|
+
const existingPlacementIndex = updatedManualEditsFile.schematic_placements?.findIndex(
|
|
5390
|
+
(p) => p.selector === source_component.name
|
|
5391
|
+
);
|
|
5392
|
+
const newPlacement = {
|
|
5393
|
+
selector: source_component.name,
|
|
5394
|
+
center: new_center,
|
|
5395
|
+
relative_to: "group_center"
|
|
5396
|
+
};
|
|
5397
|
+
if (existingPlacementIndex >= 0) {
|
|
5398
|
+
updatedManualEditsFile.schematic_placements[existingPlacementIndex] = newPlacement;
|
|
5399
|
+
} else {
|
|
5400
|
+
updatedManualEditsFile.schematic_placements.push(newPlacement);
|
|
5401
|
+
}
|
|
5402
|
+
}
|
|
5403
|
+
}
|
|
5404
|
+
return updatedManualEditsFile;
|
|
5405
|
+
};
|
|
5406
|
+
|
|
5407
|
+
// lib/utils/autorouting/getSimpleRouteJsonFromCircuitJson.ts
|
|
5408
|
+
import { getObstaclesFromSoup as getObstaclesFromSoup2 } from "@tscircuit/infgrid-ijump-astar";
|
|
5409
|
+
import { su as su2 } from "@tscircuit/soup-util";
|
|
5410
|
+
import {
|
|
5411
|
+
getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson2
|
|
5412
|
+
} from "circuit-json-to-connectivity-map";
|
|
5413
|
+
|
|
5414
|
+
// lib/utils/autorouting/getAncestorSubcircuitIds.ts
|
|
5415
|
+
var getDescendantSubcircuitIds = (db, root_subcircuit_id) => {
|
|
5416
|
+
const groups = db.source_group.list();
|
|
5417
|
+
const result = [];
|
|
5418
|
+
const findDescendants = (parentId) => {
|
|
5419
|
+
const children = groups.filter(
|
|
5420
|
+
(group) => group.parent_subcircuit_id === parentId
|
|
5421
|
+
);
|
|
5422
|
+
for (const child of children) {
|
|
5423
|
+
if (child.subcircuit_id) {
|
|
5424
|
+
result.push(child.subcircuit_id);
|
|
5425
|
+
findDescendants(child.subcircuit_id);
|
|
5426
|
+
}
|
|
5427
|
+
}
|
|
5428
|
+
};
|
|
5429
|
+
findDescendants(root_subcircuit_id);
|
|
5430
|
+
return result;
|
|
5431
|
+
};
|
|
5432
|
+
|
|
5433
|
+
// lib/utils/autorouting/getSimpleRouteJsonFromCircuitJson.ts
|
|
5434
|
+
var getSimpleRouteJsonFromCircuitJson = ({
|
|
5435
|
+
db,
|
|
5436
|
+
circuitJson,
|
|
5437
|
+
subcircuit_id,
|
|
5438
|
+
minTraceWidth = 0.1
|
|
5439
|
+
}) => {
|
|
5440
|
+
if (!db && circuitJson) {
|
|
5441
|
+
db = su2(circuitJson);
|
|
5442
|
+
}
|
|
5443
|
+
if (!db) {
|
|
5444
|
+
throw new Error("db or circuitJson is required");
|
|
5445
|
+
}
|
|
5446
|
+
const relevantSubcircuitIds = subcircuit_id ? /* @__PURE__ */ new Set([subcircuit_id]) : null;
|
|
5447
|
+
if (subcircuit_id) {
|
|
5448
|
+
const descendantSubcircuitIds = getDescendantSubcircuitIds(
|
|
5449
|
+
db,
|
|
5450
|
+
subcircuit_id
|
|
5451
|
+
);
|
|
5452
|
+
for (const id of descendantSubcircuitIds) {
|
|
5453
|
+
relevantSubcircuitIds.add(id);
|
|
5454
|
+
}
|
|
5455
|
+
}
|
|
5456
|
+
const subcircuitElements = (circuitJson ?? db.toArray()).filter(
|
|
5457
|
+
(e) => !subcircuit_id || "subcircuit_id" in e && relevantSubcircuitIds.has(e.subcircuit_id)
|
|
5458
|
+
);
|
|
5459
|
+
const board = db.pcb_board.list()[0];
|
|
5460
|
+
db = su2(subcircuitElements);
|
|
5461
|
+
const connMap = getFullConnectivityMapFromCircuitJson2(subcircuitElements);
|
|
5462
|
+
const obstacles = getObstaclesFromSoup2(
|
|
5463
|
+
[
|
|
5464
|
+
...db.pcb_component.list(),
|
|
5465
|
+
...db.pcb_smtpad.list(),
|
|
5466
|
+
...db.pcb_plated_hole.list()
|
|
5467
|
+
].filter(
|
|
5468
|
+
(e) => !subcircuit_id || relevantSubcircuitIds?.has(e.subcircuit_id)
|
|
5469
|
+
),
|
|
5470
|
+
connMap
|
|
5471
|
+
);
|
|
5472
|
+
const allPoints = obstacles.flatMap((o) => [
|
|
5473
|
+
{
|
|
5474
|
+
x: o.center.x - o.width / 2,
|
|
5475
|
+
y: o.center.y - o.height / 2
|
|
5476
|
+
},
|
|
5477
|
+
{
|
|
5478
|
+
x: o.center.x + o.width / 2,
|
|
5479
|
+
y: o.center.y + o.height / 2
|
|
5480
|
+
}
|
|
5481
|
+
]);
|
|
5482
|
+
let bounds;
|
|
5483
|
+
if (board) {
|
|
5484
|
+
bounds = {
|
|
5485
|
+
minX: board.center.x - board.width / 2,
|
|
5486
|
+
maxX: board.center.x + board.width / 2,
|
|
5487
|
+
minY: board.center.y - board.height / 2,
|
|
5488
|
+
maxY: board.center.y + board.height / 2
|
|
5489
|
+
};
|
|
5490
|
+
} else {
|
|
5491
|
+
bounds = {
|
|
5492
|
+
minX: Math.min(...allPoints.map((p) => p.x)) - 1,
|
|
5493
|
+
maxX: Math.max(...allPoints.map((p) => p.x)) + 1,
|
|
5494
|
+
minY: Math.min(...allPoints.map((p) => p.y)) - 1,
|
|
5495
|
+
maxY: Math.max(...allPoints.map((p) => p.y)) + 1
|
|
5496
|
+
};
|
|
5497
|
+
}
|
|
5498
|
+
const directTraceConnections = db.source_trace.list().map((trace) => {
|
|
5499
|
+
const connectedPorts = trace.connected_source_port_ids.map((id) => {
|
|
5500
|
+
const source_port = db.source_port.get(id);
|
|
5501
|
+
const pcb_port = db.pcb_port.getWhere({ source_port_id: id });
|
|
5502
|
+
return {
|
|
5503
|
+
...source_port,
|
|
5504
|
+
...pcb_port
|
|
5505
|
+
};
|
|
5506
|
+
});
|
|
5507
|
+
if (connectedPorts.length < 2) return null;
|
|
5508
|
+
return {
|
|
5509
|
+
name: connMap.getNetConnectedToId(trace.source_trace_id) ?? trace.source_trace_id ?? "",
|
|
5510
|
+
source_trace_id: trace.source_trace_id,
|
|
5511
|
+
pointsToConnect: connectedPorts.map((port) => {
|
|
5512
|
+
return {
|
|
5513
|
+
x: port.x,
|
|
5514
|
+
y: port.y,
|
|
5515
|
+
layer: port.layers?.[0] ?? "top"
|
|
5516
|
+
};
|
|
5517
|
+
})
|
|
5518
|
+
};
|
|
5519
|
+
}).filter((c) => c !== null);
|
|
5520
|
+
const source_nets = db.source_net.list().filter(
|
|
5521
|
+
(e) => !subcircuit_id || relevantSubcircuitIds?.has(e.subcircuit_id)
|
|
5522
|
+
);
|
|
5523
|
+
const connectionsFromNets = [];
|
|
5524
|
+
for (const net of source_nets) {
|
|
5525
|
+
const connectedSourceTraces = db.source_trace.list().filter((st) => st.connected_source_net_ids?.includes(net.source_net_id));
|
|
5526
|
+
connectionsFromNets.push({
|
|
5527
|
+
name: connMap.getNetConnectedToId(net.source_net_id) ?? net.source_net_id,
|
|
5528
|
+
pointsToConnect: connectedSourceTraces.flatMap((st) => {
|
|
5529
|
+
const pcb_ports = db.pcb_port.list().filter(
|
|
5530
|
+
(p) => st.connected_source_port_ids.includes(p.source_port_id)
|
|
5531
|
+
);
|
|
5532
|
+
return pcb_ports.map((p) => ({
|
|
5533
|
+
x: p.x,
|
|
5534
|
+
y: p.y,
|
|
5535
|
+
layer: p.layers?.[0] ?? "top",
|
|
5536
|
+
pcb_port_id: p.pcb_port_id
|
|
5537
|
+
}));
|
|
5538
|
+
})
|
|
5539
|
+
});
|
|
5540
|
+
}
|
|
5541
|
+
return {
|
|
5542
|
+
simpleRouteJson: {
|
|
5543
|
+
bounds,
|
|
5544
|
+
obstacles,
|
|
5545
|
+
connections: [...directTraceConnections, ...connectionsFromNets],
|
|
5546
|
+
// TODO add traces so that we don't run into things routed by another
|
|
5547
|
+
// subcircuit
|
|
5548
|
+
layerCount: 2,
|
|
5549
|
+
minTraceWidth
|
|
5550
|
+
},
|
|
5551
|
+
connMap
|
|
5552
|
+
};
|
|
5553
|
+
};
|
|
5554
|
+
|
|
5555
|
+
// lib/utils/render-events/getPhaseTimingsFromRenderEvents.ts
|
|
5556
|
+
var getPhaseTimingsFromRenderEvents = (renderEvents) => {
|
|
5557
|
+
const phaseTimings = {};
|
|
5558
|
+
if (!renderEvents) return phaseTimings;
|
|
5559
|
+
for (const renderPhase of orderedRenderPhases) {
|
|
5560
|
+
phaseTimings[renderPhase] = 0;
|
|
5561
|
+
}
|
|
5562
|
+
const startEvents = /* @__PURE__ */ new Map();
|
|
5563
|
+
for (const event of renderEvents) {
|
|
5564
|
+
const [, , phase, eventType] = event.type.split(":");
|
|
5565
|
+
if (eventType === "start") {
|
|
5566
|
+
startEvents.set(`${phase}:${event.renderId}`, event);
|
|
5567
|
+
continue;
|
|
5568
|
+
}
|
|
5569
|
+
if (eventType === "end") {
|
|
5570
|
+
const startEvent = startEvents.get(`${phase}:${event.renderId}`);
|
|
5571
|
+
if (startEvent) {
|
|
5572
|
+
const duration = event.createdAt - startEvent.createdAt;
|
|
5573
|
+
phaseTimings[phase] = (phaseTimings[phase] || 0) + duration;
|
|
5574
|
+
}
|
|
5575
|
+
}
|
|
5576
|
+
}
|
|
5577
|
+
return phaseTimings;
|
|
5578
|
+
};
|
|
5579
|
+
|
|
5257
5580
|
// lib/components/primitive-components/Group/Group.ts
|
|
5258
5581
|
var Group = class extends NormalComponent {
|
|
5259
5582
|
pcb_group_id = null;
|
|
@@ -5319,20 +5642,11 @@ var Group = class extends NormalComponent {
|
|
|
5319
5642
|
);
|
|
5320
5643
|
}
|
|
5321
5644
|
}
|
|
5322
|
-
_getSimpleRouteJsonFromPcbTraces() {
|
|
5323
|
-
const traces = this.selectAll("trace");
|
|
5324
|
-
const { db } = this.root;
|
|
5325
|
-
return getSimpleRouteJsonFromTracesAndDb({
|
|
5326
|
-
db,
|
|
5327
|
-
traces,
|
|
5328
|
-
minTraceWidth: this._parsedProps.minTraceWidth ?? 0.1
|
|
5329
|
-
});
|
|
5330
|
-
}
|
|
5331
5645
|
doInitialSourceAddConnectivityMapKey() {
|
|
5332
5646
|
if (!this.isSubcircuit) return;
|
|
5333
5647
|
const { db } = this.root;
|
|
5334
5648
|
const traces = this.selectAll("trace");
|
|
5335
|
-
const connMap = new
|
|
5649
|
+
const connMap = new ConnectivityMap2({});
|
|
5336
5650
|
connMap.addConnections(
|
|
5337
5651
|
traces.map((t) => {
|
|
5338
5652
|
const source_trace = db.source_trace.get(
|
|
@@ -5370,9 +5684,10 @@ var Group = class extends NormalComponent {
|
|
|
5370
5684
|
}
|
|
5371
5685
|
_shouldRouteAsync() {
|
|
5372
5686
|
const autorouter = this._getAutorouterConfig();
|
|
5373
|
-
if (autorouter.local) return false;
|
|
5374
5687
|
if (autorouter.groupMode === "sequential-trace") return false;
|
|
5375
|
-
return true;
|
|
5688
|
+
if (autorouter.local && autorouter.groupMode === "subcircuit") return true;
|
|
5689
|
+
if (!autorouter.local) return true;
|
|
5690
|
+
return false;
|
|
5376
5691
|
}
|
|
5377
5692
|
_hasTracesToRoute() {
|
|
5378
5693
|
const debug4 = Debug5("tscircuit:core:_hasTracesToRoute");
|
|
@@ -5403,7 +5718,11 @@ var Group = class extends NormalComponent {
|
|
|
5403
5718
|
{
|
|
5404
5719
|
method: "POST",
|
|
5405
5720
|
body: JSON.stringify({
|
|
5406
|
-
input_simple_route_json:
|
|
5721
|
+
input_simple_route_json: getSimpleRouteJsonFromCircuitJson({
|
|
5722
|
+
db,
|
|
5723
|
+
minTraceWidth: this.props.autorouter?.minTraceWidth ?? 0.15,
|
|
5724
|
+
subcircuit_id: this.subcircuit_id
|
|
5725
|
+
}).simpleRouteJson,
|
|
5407
5726
|
subcircuit_id: this.subcircuit_id
|
|
5408
5727
|
}),
|
|
5409
5728
|
headers: { "Content-Type": "application/json" }
|
|
@@ -5481,12 +5800,73 @@ var Group = class extends NormalComponent {
|
|
|
5481
5800
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
5482
5801
|
}
|
|
5483
5802
|
}
|
|
5803
|
+
/**
|
|
5804
|
+
* Run local autorouting using the CapacityMeshAutorouter
|
|
5805
|
+
*/
|
|
5806
|
+
async _runLocalCapacityMeshAutorouting() {
|
|
5807
|
+
const { db } = this.root;
|
|
5808
|
+
const debug4 = Debug5("tscircuit:core:_runLocalCapacityMeshAutorouting");
|
|
5809
|
+
debug4(`[${this.getString()}] starting local capacity mesh autorouting`);
|
|
5810
|
+
const { simpleRouteJson, connMap } = getSimpleRouteJsonFromCircuitJson({
|
|
5811
|
+
db,
|
|
5812
|
+
minTraceWidth: this.props.autorouter?.minTraceWidth ?? 0.15,
|
|
5813
|
+
subcircuit_id: this.subcircuit_id
|
|
5814
|
+
});
|
|
5815
|
+
this.root?.emit("autorouting:start", {
|
|
5816
|
+
subcircuit_id: this.subcircuit_id,
|
|
5817
|
+
componentDisplayName: this.getString(),
|
|
5818
|
+
simpleRouteJson
|
|
5819
|
+
});
|
|
5820
|
+
const autorouter = new CapacityMeshAutorouter(simpleRouteJson, {
|
|
5821
|
+
// Optional configuration parameters
|
|
5822
|
+
capacityDepth: this.props.autorouter?.capacityDepth,
|
|
5823
|
+
targetMinCapacity: this.props.autorouter?.targetMinCapacity
|
|
5824
|
+
});
|
|
5825
|
+
const routingPromise = new Promise(
|
|
5826
|
+
(resolve, reject) => {
|
|
5827
|
+
autorouter.on("complete", (event) => {
|
|
5828
|
+
debug4(`[${this.getString()}] local autorouting complete`);
|
|
5829
|
+
resolve(event.traces);
|
|
5830
|
+
});
|
|
5831
|
+
autorouter.on("error", (event) => {
|
|
5832
|
+
debug4(
|
|
5833
|
+
`[${this.getString()}] local autorouting error: ${event.error.message}`
|
|
5834
|
+
);
|
|
5835
|
+
reject(event.error);
|
|
5836
|
+
});
|
|
5837
|
+
}
|
|
5838
|
+
);
|
|
5839
|
+
autorouter.start();
|
|
5840
|
+
try {
|
|
5841
|
+
const traces = await routingPromise;
|
|
5842
|
+
this._asyncAutoroutingResult = {
|
|
5843
|
+
output_pcb_traces: traces
|
|
5844
|
+
};
|
|
5845
|
+
this._markDirty("PcbTraceRender");
|
|
5846
|
+
} catch (error) {
|
|
5847
|
+
const { db: db2 } = this.root;
|
|
5848
|
+
db2.pcb_autorouting_error.insert({
|
|
5849
|
+
pcb_error_id: `local_${this.subcircuit_id}`,
|
|
5850
|
+
message: error instanceof Error ? error.message : String(error)
|
|
5851
|
+
});
|
|
5852
|
+
throw error;
|
|
5853
|
+
} finally {
|
|
5854
|
+
autorouter.stop();
|
|
5855
|
+
}
|
|
5856
|
+
}
|
|
5484
5857
|
_startAsyncAutorouting() {
|
|
5485
5858
|
this._hasStartedAsyncAutorouting = true;
|
|
5486
|
-
this.
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5859
|
+
if (this._getAutorouterConfig().local) {
|
|
5860
|
+
this._queueAsyncEffect(
|
|
5861
|
+
"capacity-mesh-autorouting",
|
|
5862
|
+
async () => this._runLocalCapacityMeshAutorouting()
|
|
5863
|
+
);
|
|
5864
|
+
} else {
|
|
5865
|
+
this._queueAsyncEffect(
|
|
5866
|
+
"make-http-autorouting-request",
|
|
5867
|
+
async () => this._runEffectMakeHttpAutoroutingRequest()
|
|
5868
|
+
);
|
|
5869
|
+
}
|
|
5490
5870
|
}
|
|
5491
5871
|
doInitialPcbTraceRender() {
|
|
5492
5872
|
const debug4 = Debug5("tscircuit:core:doInitialPcbTraceRender");
|
|
@@ -5508,6 +5888,7 @@ var Group = class extends NormalComponent {
|
|
|
5508
5888
|
}
|
|
5509
5889
|
updatePcbTraceRender() {
|
|
5510
5890
|
const debug4 = Debug5("tscircuit:core:updatePcbTraceRender");
|
|
5891
|
+
debug4(`[${this.getString()}] updating...`);
|
|
5511
5892
|
if (!this.isSubcircuit) return;
|
|
5512
5893
|
if (this._shouldRouteAsync() && this._hasTracesToRoute() && !this._hasStartedAsyncAutorouting) {
|
|
5513
5894
|
if (this._areChildSubcircuitsRouted()) {
|
|
@@ -5522,10 +5903,16 @@ var Group = class extends NormalComponent {
|
|
|
5522
5903
|
if (this._shouldUseTraceByTraceRouting()) return;
|
|
5523
5904
|
const { db } = this.root;
|
|
5524
5905
|
if (this._asyncAutoroutingResult.output_simple_route_json) {
|
|
5906
|
+
debug4(
|
|
5907
|
+
`[${this.getString()}] updating PCB traces from simple route json (${this._asyncAutoroutingResult.output_simple_route_json.traces?.length} traces)`
|
|
5908
|
+
);
|
|
5525
5909
|
this._updatePcbTraceRenderFromSimpleRouteJson();
|
|
5526
5910
|
return;
|
|
5527
5911
|
}
|
|
5528
5912
|
if (this._asyncAutoroutingResult.output_pcb_traces) {
|
|
5913
|
+
debug4(
|
|
5914
|
+
`[${this.getString()}] updating PCB traces from ${this._asyncAutoroutingResult.output_pcb_traces.length} traces`
|
|
5915
|
+
);
|
|
5529
5916
|
this._updatePcbTraceRenderFromPcbTraces();
|
|
5530
5917
|
return;
|
|
5531
5918
|
}
|
|
@@ -5534,9 +5921,9 @@ var Group = class extends NormalComponent {
|
|
|
5534
5921
|
const { db } = this.root;
|
|
5535
5922
|
const { traces: routedTraces } = this._asyncAutoroutingResult.output_simple_route_json;
|
|
5536
5923
|
if (!routedTraces) return;
|
|
5537
|
-
const circuitTraces = this.selectAll("trace");
|
|
5538
5924
|
for (const routedTrace of routedTraces) {
|
|
5539
5925
|
const pcb_trace = db.pcb_trace.insert({
|
|
5926
|
+
subcircuit_id: this.subcircuit_id,
|
|
5540
5927
|
route: routedTrace.route
|
|
5541
5928
|
// source_trace_id: circuitTrace.source_trace_id!,
|
|
5542
5929
|
});
|
|
@@ -5550,6 +5937,22 @@ var Group = class extends NormalComponent {
|
|
|
5550
5937
|
pcb_trace.subcircuit_id = this.subcircuit_id;
|
|
5551
5938
|
db.pcb_trace.insert(pcb_trace);
|
|
5552
5939
|
}
|
|
5940
|
+
for (const pcb_trace of output_pcb_traces) {
|
|
5941
|
+
for (const point of pcb_trace.route) {
|
|
5942
|
+
if (point.route_type === "via") {
|
|
5943
|
+
db.pcb_via.insert({
|
|
5944
|
+
pcb_trace_id: pcb_trace.pcb_trace_id,
|
|
5945
|
+
x: point.x,
|
|
5946
|
+
y: point.y,
|
|
5947
|
+
hole_diameter: 0.3,
|
|
5948
|
+
outer_diameter: 0.6,
|
|
5949
|
+
layers: [point.from_layer, point.to_layer],
|
|
5950
|
+
from_layer: point.from_layer,
|
|
5951
|
+
to_layer: point.to_layer
|
|
5952
|
+
});
|
|
5953
|
+
}
|
|
5954
|
+
}
|
|
5955
|
+
}
|
|
5553
5956
|
}
|
|
5554
5957
|
doInitialSchematicLayout() {
|
|
5555
5958
|
if (!this.isSubcircuit) return;
|
|
@@ -5581,7 +5984,7 @@ var Group = class extends NormalComponent {
|
|
|
5581
5984
|
const defaults = {
|
|
5582
5985
|
serverUrl: "https://registry-api.tscircuit.com",
|
|
5583
5986
|
serverMode: "job",
|
|
5584
|
-
serverCacheEnabled:
|
|
5987
|
+
serverCacheEnabled: true
|
|
5585
5988
|
};
|
|
5586
5989
|
const autorouter = this._parsedProps.autorouter ?? this.getInheritedProperty("autorouter");
|
|
5587
5990
|
if (typeof autorouter === "object") {
|
|
@@ -5593,13 +5996,27 @@ var Group = class extends NormalComponent {
|
|
|
5593
5996
|
}
|
|
5594
5997
|
if (autorouter === "auto-local")
|
|
5595
5998
|
return {
|
|
5596
|
-
local: true
|
|
5999
|
+
local: true,
|
|
6000
|
+
groupMode: "subcircuit"
|
|
5597
6001
|
};
|
|
5598
6002
|
if (autorouter === "sequential-trace")
|
|
5599
6003
|
return {
|
|
5600
6004
|
local: true,
|
|
5601
6005
|
groupMode: "sequential-trace"
|
|
5602
6006
|
};
|
|
6007
|
+
if (autorouter === "subcircuit")
|
|
6008
|
+
return {
|
|
6009
|
+
local: true,
|
|
6010
|
+
groupMode: "subcircuit"
|
|
6011
|
+
};
|
|
6012
|
+
if (autorouter === "auto-cloud")
|
|
6013
|
+
return {
|
|
6014
|
+
local: false,
|
|
6015
|
+
groupMode: "subcircuit",
|
|
6016
|
+
serverUrl: defaults.serverUrl,
|
|
6017
|
+
serverMode: defaults.serverMode,
|
|
6018
|
+
serverCacheEnabled: true
|
|
6019
|
+
};
|
|
5603
6020
|
return {
|
|
5604
6021
|
local: true,
|
|
5605
6022
|
groupMode: "sequential-trace"
|
|
@@ -6457,7 +6874,9 @@ var PinHeader = class extends NormalComponent {
|
|
|
6457
6874
|
new Port({
|
|
6458
6875
|
name: `pin${i}`,
|
|
6459
6876
|
pinNumber: i,
|
|
6460
|
-
aliases: []
|
|
6877
|
+
aliases: [this._parsedProps.pinLabels?.[i - 1]].filter(
|
|
6878
|
+
Boolean
|
|
6879
|
+
)
|
|
6461
6880
|
})
|
|
6462
6881
|
);
|
|
6463
6882
|
}
|
|
@@ -6778,7 +7197,7 @@ var Switch = class extends NormalComponent {
|
|
|
6778
7197
|
};
|
|
6779
7198
|
|
|
6780
7199
|
// lib/RootCircuit.ts
|
|
6781
|
-
import { su } from "@tscircuit/soup-util";
|
|
7200
|
+
import { su as su3 } from "@tscircuit/soup-util";
|
|
6782
7201
|
import { isValidElement as isValidElement2 } from "react";
|
|
6783
7202
|
import { identity as identity4 } from "transformation-matrix";
|
|
6784
7203
|
var RootCircuit = class {
|
|
@@ -6799,7 +7218,7 @@ var RootCircuit = class {
|
|
|
6799
7218
|
_hasRenderedAtleastOnce = false;
|
|
6800
7219
|
constructor() {
|
|
6801
7220
|
this.children = [];
|
|
6802
|
-
this.db =
|
|
7221
|
+
this.db = su3([]);
|
|
6803
7222
|
this.root = this;
|
|
6804
7223
|
}
|
|
6805
7224
|
add(componentOrElm) {
|
|
@@ -7043,137 +7462,6 @@ var useResistor = createUseComponent(
|
|
|
7043
7462
|
resistorPins2
|
|
7044
7463
|
);
|
|
7045
7464
|
|
|
7046
|
-
// lib/utils/edit-events/apply-edit-events-to-manual-edits-file.ts
|
|
7047
|
-
import "zod";
|
|
7048
|
-
import { su as su2 } from "@tscircuit/soup-util";
|
|
7049
|
-
var applyEditEventsToManualEditsFile = ({
|
|
7050
|
-
circuitJson,
|
|
7051
|
-
editEvents,
|
|
7052
|
-
manualEditsFile
|
|
7053
|
-
}) => {
|
|
7054
|
-
const updatedManualEditsFile = {
|
|
7055
|
-
...manualEditsFile,
|
|
7056
|
-
schematic_placements: [...manualEditsFile.schematic_placements ?? []]
|
|
7057
|
-
};
|
|
7058
|
-
for (const editEvent of editEvents) {
|
|
7059
|
-
if (editEvent.edit_event_type === "edit_schematic_component_location") {
|
|
7060
|
-
const { schematic_component_id, new_center } = editEvent;
|
|
7061
|
-
const schematic_component2 = su2(circuitJson).schematic_component.get(
|
|
7062
|
-
schematic_component_id
|
|
7063
|
-
);
|
|
7064
|
-
if (!schematic_component2) continue;
|
|
7065
|
-
const source_component = su2(circuitJson).source_component.get(
|
|
7066
|
-
schematic_component2.source_component_id
|
|
7067
|
-
);
|
|
7068
|
-
if (!source_component) continue;
|
|
7069
|
-
const existingPlacementIndex = updatedManualEditsFile.schematic_placements?.findIndex(
|
|
7070
|
-
(p) => p.selector === source_component.name
|
|
7071
|
-
);
|
|
7072
|
-
const newPlacement = {
|
|
7073
|
-
selector: source_component.name,
|
|
7074
|
-
center: new_center,
|
|
7075
|
-
relative_to: "group_center"
|
|
7076
|
-
};
|
|
7077
|
-
if (existingPlacementIndex >= 0) {
|
|
7078
|
-
updatedManualEditsFile.schematic_placements[existingPlacementIndex] = newPlacement;
|
|
7079
|
-
} else {
|
|
7080
|
-
updatedManualEditsFile.schematic_placements.push(newPlacement);
|
|
7081
|
-
}
|
|
7082
|
-
}
|
|
7083
|
-
}
|
|
7084
|
-
return updatedManualEditsFile;
|
|
7085
|
-
};
|
|
7086
|
-
|
|
7087
|
-
// lib/utils/autorouting/getSimpleRouteJsonFromCircuitJson.ts
|
|
7088
|
-
import { getObstaclesFromSoup as getObstaclesFromSoup3 } from "@tscircuit/infgrid-ijump-astar";
|
|
7089
|
-
import { su as su3 } from "@tscircuit/soup-util";
|
|
7090
|
-
import { getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson2 } from "circuit-json-to-connectivity-map";
|
|
7091
|
-
var getSimpleRouteJsonFromCircuitJson = ({
|
|
7092
|
-
circuitJson,
|
|
7093
|
-
minTraceWidth = 0.1
|
|
7094
|
-
}) => {
|
|
7095
|
-
const db = su3(circuitJson);
|
|
7096
|
-
const connMap = getFullConnectivityMapFromCircuitJson2(circuitJson);
|
|
7097
|
-
const obstacles = getObstaclesFromSoup3(
|
|
7098
|
-
[
|
|
7099
|
-
...db.pcb_component.list(),
|
|
7100
|
-
...db.pcb_smtpad.list(),
|
|
7101
|
-
...db.pcb_plated_hole.list()
|
|
7102
|
-
],
|
|
7103
|
-
connMap
|
|
7104
|
-
);
|
|
7105
|
-
const allPoints = obstacles.flatMap((o) => [
|
|
7106
|
-
{
|
|
7107
|
-
x: o.center.x - o.width / 2,
|
|
7108
|
-
y: o.center.y - o.height / 2
|
|
7109
|
-
},
|
|
7110
|
-
{
|
|
7111
|
-
x: o.center.x + o.width / 2,
|
|
7112
|
-
y: o.center.y + o.height / 2
|
|
7113
|
-
}
|
|
7114
|
-
]);
|
|
7115
|
-
const bounds = {
|
|
7116
|
-
minX: Math.min(...allPoints.map((p) => p.x)) - 1,
|
|
7117
|
-
maxX: Math.max(...allPoints.map((p) => p.x)) + 1,
|
|
7118
|
-
minY: Math.min(...allPoints.map((p) => p.y)) - 1,
|
|
7119
|
-
maxY: Math.max(...allPoints.map((p) => p.y)) + 1
|
|
7120
|
-
};
|
|
7121
|
-
const connections = db.source_trace.list().map((trace) => {
|
|
7122
|
-
const connectedPorts = trace.connected_source_port_ids.map((id) => {
|
|
7123
|
-
const source_port = db.source_port.get(id);
|
|
7124
|
-
const pcb_port = db.pcb_port.getWhere({ source_port_id: id });
|
|
7125
|
-
return {
|
|
7126
|
-
...source_port,
|
|
7127
|
-
...pcb_port
|
|
7128
|
-
};
|
|
7129
|
-
});
|
|
7130
|
-
if (connectedPorts.length < 2) return null;
|
|
7131
|
-
return {
|
|
7132
|
-
name: connMap.getNetConnectedToId(trace.source_trace_id) ?? trace.source_trace_id ?? "",
|
|
7133
|
-
source_trace_id: trace.source_trace_id,
|
|
7134
|
-
pointsToConnect: connectedPorts.map((port) => {
|
|
7135
|
-
return {
|
|
7136
|
-
x: port.x,
|
|
7137
|
-
y: port.y,
|
|
7138
|
-
layer: port.layers?.[0] ?? "top"
|
|
7139
|
-
};
|
|
7140
|
-
})
|
|
7141
|
-
};
|
|
7142
|
-
}).filter((c) => c !== null);
|
|
7143
|
-
return {
|
|
7144
|
-
bounds,
|
|
7145
|
-
obstacles,
|
|
7146
|
-
connections,
|
|
7147
|
-
layerCount: 2,
|
|
7148
|
-
minTraceWidth
|
|
7149
|
-
};
|
|
7150
|
-
};
|
|
7151
|
-
|
|
7152
|
-
// lib/utils/render-events/getPhaseTimingsFromRenderEvents.ts
|
|
7153
|
-
var getPhaseTimingsFromRenderEvents = (renderEvents) => {
|
|
7154
|
-
const phaseTimings = {};
|
|
7155
|
-
if (!renderEvents) return phaseTimings;
|
|
7156
|
-
for (const renderPhase of orderedRenderPhases) {
|
|
7157
|
-
phaseTimings[renderPhase] = 0;
|
|
7158
|
-
}
|
|
7159
|
-
const startEvents = /* @__PURE__ */ new Map();
|
|
7160
|
-
for (const event of renderEvents) {
|
|
7161
|
-
const [, , phase, eventType] = event.type.split(":");
|
|
7162
|
-
if (eventType === "start") {
|
|
7163
|
-
startEvents.set(`${phase}:${event.renderId}`, event);
|
|
7164
|
-
continue;
|
|
7165
|
-
}
|
|
7166
|
-
if (eventType === "end") {
|
|
7167
|
-
const startEvent = startEvents.get(`${phase}:${event.renderId}`);
|
|
7168
|
-
if (startEvent) {
|
|
7169
|
-
const duration = event.createdAt - startEvent.createdAt;
|
|
7170
|
-
phaseTimings[phase] = (phaseTimings[phase] || 0) + duration;
|
|
7171
|
-
}
|
|
7172
|
-
}
|
|
7173
|
-
}
|
|
7174
|
-
return phaseTimings;
|
|
7175
|
-
};
|
|
7176
|
-
|
|
7177
7465
|
// lib/sel/sel.ts
|
|
7178
7466
|
var sel = new Proxy(
|
|
7179
7467
|
{},
|
|
@@ -7186,6 +7474,23 @@ var sel = new Proxy(
|
|
|
7186
7474
|
if (prop1 === "net") {
|
|
7187
7475
|
return `net.${prop2}`;
|
|
7188
7476
|
}
|
|
7477
|
+
if (prop1 === "subcircuit") {
|
|
7478
|
+
return new Proxy(
|
|
7479
|
+
{},
|
|
7480
|
+
{
|
|
7481
|
+
get: (_3, prop3) => {
|
|
7482
|
+
return new Proxy(
|
|
7483
|
+
{},
|
|
7484
|
+
{
|
|
7485
|
+
get: (_4, prop4) => {
|
|
7486
|
+
return `subcircuit.${prop2} > .${prop3} > .${prop4}`;
|
|
7487
|
+
}
|
|
7488
|
+
}
|
|
7489
|
+
);
|
|
7490
|
+
}
|
|
7491
|
+
}
|
|
7492
|
+
);
|
|
7493
|
+
}
|
|
7189
7494
|
return `.${prop1} > .${prop2}`;
|
|
7190
7495
|
}
|
|
7191
7496
|
}
|
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.332",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -53,12 +53,13 @@
|
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@lume/kiwi": "^0.4.3",
|
|
56
|
+
"@tscircuit/capacity-autorouter": "^0.0.12",
|
|
56
57
|
"@tscircuit/infgrid-ijump-astar": "^0.0.33",
|
|
57
58
|
"@tscircuit/math-utils": "^0.0.9",
|
|
58
59
|
"@tscircuit/props": "^0.0.152",
|
|
59
60
|
"@tscircuit/schematic-autolayout": "^0.0.6",
|
|
60
61
|
"@tscircuit/soup-util": "^0.0.41",
|
|
61
|
-
"circuit-json": "^0.0.
|
|
62
|
+
"circuit-json": "^0.0.144",
|
|
62
63
|
"circuit-json-to-connectivity-map": "^0.0.17",
|
|
63
64
|
"format-si-unit": "^0.0.3",
|
|
64
65
|
"nanoid": "^5.0.7",
|