@tscircuit/core 0.0.331 → 0.0.333
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 +524 -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" | "renderComplete";
|
|
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,80 @@ 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.on("progress", (event) => {
|
|
5840
|
+
this.root?.emit("autorouting:progress", {
|
|
5841
|
+
subcircuit_id: this.subcircuit_id,
|
|
5842
|
+
componentDisplayName: this.getString(),
|
|
5843
|
+
...event
|
|
5844
|
+
});
|
|
5845
|
+
});
|
|
5846
|
+
autorouter.start();
|
|
5847
|
+
try {
|
|
5848
|
+
const traces = await routingPromise;
|
|
5849
|
+
this._asyncAutoroutingResult = {
|
|
5850
|
+
output_pcb_traces: traces
|
|
5851
|
+
};
|
|
5852
|
+
this._markDirty("PcbTraceRender");
|
|
5853
|
+
} catch (error) {
|
|
5854
|
+
const { db: db2 } = this.root;
|
|
5855
|
+
db2.pcb_autorouting_error.insert({
|
|
5856
|
+
pcb_error_id: `local_${this.subcircuit_id}`,
|
|
5857
|
+
message: error instanceof Error ? error.message : String(error)
|
|
5858
|
+
});
|
|
5859
|
+
throw error;
|
|
5860
|
+
} finally {
|
|
5861
|
+
autorouter.stop();
|
|
5862
|
+
}
|
|
5863
|
+
}
|
|
5484
5864
|
_startAsyncAutorouting() {
|
|
5485
5865
|
this._hasStartedAsyncAutorouting = true;
|
|
5486
|
-
this.
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5866
|
+
if (this._getAutorouterConfig().local) {
|
|
5867
|
+
this._queueAsyncEffect(
|
|
5868
|
+
"capacity-mesh-autorouting",
|
|
5869
|
+
async () => this._runLocalCapacityMeshAutorouting()
|
|
5870
|
+
);
|
|
5871
|
+
} else {
|
|
5872
|
+
this._queueAsyncEffect(
|
|
5873
|
+
"make-http-autorouting-request",
|
|
5874
|
+
async () => this._runEffectMakeHttpAutoroutingRequest()
|
|
5875
|
+
);
|
|
5876
|
+
}
|
|
5490
5877
|
}
|
|
5491
5878
|
doInitialPcbTraceRender() {
|
|
5492
5879
|
const debug4 = Debug5("tscircuit:core:doInitialPcbTraceRender");
|
|
@@ -5508,6 +5895,7 @@ var Group = class extends NormalComponent {
|
|
|
5508
5895
|
}
|
|
5509
5896
|
updatePcbTraceRender() {
|
|
5510
5897
|
const debug4 = Debug5("tscircuit:core:updatePcbTraceRender");
|
|
5898
|
+
debug4(`[${this.getString()}] updating...`);
|
|
5511
5899
|
if (!this.isSubcircuit) return;
|
|
5512
5900
|
if (this._shouldRouteAsync() && this._hasTracesToRoute() && !this._hasStartedAsyncAutorouting) {
|
|
5513
5901
|
if (this._areChildSubcircuitsRouted()) {
|
|
@@ -5522,10 +5910,16 @@ var Group = class extends NormalComponent {
|
|
|
5522
5910
|
if (this._shouldUseTraceByTraceRouting()) return;
|
|
5523
5911
|
const { db } = this.root;
|
|
5524
5912
|
if (this._asyncAutoroutingResult.output_simple_route_json) {
|
|
5913
|
+
debug4(
|
|
5914
|
+
`[${this.getString()}] updating PCB traces from simple route json (${this._asyncAutoroutingResult.output_simple_route_json.traces?.length} traces)`
|
|
5915
|
+
);
|
|
5525
5916
|
this._updatePcbTraceRenderFromSimpleRouteJson();
|
|
5526
5917
|
return;
|
|
5527
5918
|
}
|
|
5528
5919
|
if (this._asyncAutoroutingResult.output_pcb_traces) {
|
|
5920
|
+
debug4(
|
|
5921
|
+
`[${this.getString()}] updating PCB traces from ${this._asyncAutoroutingResult.output_pcb_traces.length} traces`
|
|
5922
|
+
);
|
|
5529
5923
|
this._updatePcbTraceRenderFromPcbTraces();
|
|
5530
5924
|
return;
|
|
5531
5925
|
}
|
|
@@ -5534,9 +5928,9 @@ var Group = class extends NormalComponent {
|
|
|
5534
5928
|
const { db } = this.root;
|
|
5535
5929
|
const { traces: routedTraces } = this._asyncAutoroutingResult.output_simple_route_json;
|
|
5536
5930
|
if (!routedTraces) return;
|
|
5537
|
-
const circuitTraces = this.selectAll("trace");
|
|
5538
5931
|
for (const routedTrace of routedTraces) {
|
|
5539
5932
|
const pcb_trace = db.pcb_trace.insert({
|
|
5933
|
+
subcircuit_id: this.subcircuit_id,
|
|
5540
5934
|
route: routedTrace.route
|
|
5541
5935
|
// source_trace_id: circuitTrace.source_trace_id!,
|
|
5542
5936
|
});
|
|
@@ -5550,6 +5944,22 @@ var Group = class extends NormalComponent {
|
|
|
5550
5944
|
pcb_trace.subcircuit_id = this.subcircuit_id;
|
|
5551
5945
|
db.pcb_trace.insert(pcb_trace);
|
|
5552
5946
|
}
|
|
5947
|
+
for (const pcb_trace of output_pcb_traces) {
|
|
5948
|
+
for (const point of pcb_trace.route) {
|
|
5949
|
+
if (point.route_type === "via") {
|
|
5950
|
+
db.pcb_via.insert({
|
|
5951
|
+
pcb_trace_id: pcb_trace.pcb_trace_id,
|
|
5952
|
+
x: point.x,
|
|
5953
|
+
y: point.y,
|
|
5954
|
+
hole_diameter: 0.3,
|
|
5955
|
+
outer_diameter: 0.6,
|
|
5956
|
+
layers: [point.from_layer, point.to_layer],
|
|
5957
|
+
from_layer: point.from_layer,
|
|
5958
|
+
to_layer: point.to_layer
|
|
5959
|
+
});
|
|
5960
|
+
}
|
|
5961
|
+
}
|
|
5962
|
+
}
|
|
5553
5963
|
}
|
|
5554
5964
|
doInitialSchematicLayout() {
|
|
5555
5965
|
if (!this.isSubcircuit) return;
|
|
@@ -5581,7 +5991,7 @@ var Group = class extends NormalComponent {
|
|
|
5581
5991
|
const defaults = {
|
|
5582
5992
|
serverUrl: "https://registry-api.tscircuit.com",
|
|
5583
5993
|
serverMode: "job",
|
|
5584
|
-
serverCacheEnabled:
|
|
5994
|
+
serverCacheEnabled: true
|
|
5585
5995
|
};
|
|
5586
5996
|
const autorouter = this._parsedProps.autorouter ?? this.getInheritedProperty("autorouter");
|
|
5587
5997
|
if (typeof autorouter === "object") {
|
|
@@ -5593,13 +6003,27 @@ var Group = class extends NormalComponent {
|
|
|
5593
6003
|
}
|
|
5594
6004
|
if (autorouter === "auto-local")
|
|
5595
6005
|
return {
|
|
5596
|
-
local: true
|
|
6006
|
+
local: true,
|
|
6007
|
+
groupMode: "subcircuit"
|
|
5597
6008
|
};
|
|
5598
6009
|
if (autorouter === "sequential-trace")
|
|
5599
6010
|
return {
|
|
5600
6011
|
local: true,
|
|
5601
6012
|
groupMode: "sequential-trace"
|
|
5602
6013
|
};
|
|
6014
|
+
if (autorouter === "subcircuit")
|
|
6015
|
+
return {
|
|
6016
|
+
local: true,
|
|
6017
|
+
groupMode: "subcircuit"
|
|
6018
|
+
};
|
|
6019
|
+
if (autorouter === "auto-cloud")
|
|
6020
|
+
return {
|
|
6021
|
+
local: false,
|
|
6022
|
+
groupMode: "subcircuit",
|
|
6023
|
+
serverUrl: defaults.serverUrl,
|
|
6024
|
+
serverMode: defaults.serverMode,
|
|
6025
|
+
serverCacheEnabled: true
|
|
6026
|
+
};
|
|
5603
6027
|
return {
|
|
5604
6028
|
local: true,
|
|
5605
6029
|
groupMode: "sequential-trace"
|
|
@@ -6457,7 +6881,9 @@ var PinHeader = class extends NormalComponent {
|
|
|
6457
6881
|
new Port({
|
|
6458
6882
|
name: `pin${i}`,
|
|
6459
6883
|
pinNumber: i,
|
|
6460
|
-
aliases: []
|
|
6884
|
+
aliases: [this._parsedProps.pinLabels?.[i - 1]].filter(
|
|
6885
|
+
Boolean
|
|
6886
|
+
)
|
|
6461
6887
|
})
|
|
6462
6888
|
);
|
|
6463
6889
|
}
|
|
@@ -6778,7 +7204,7 @@ var Switch = class extends NormalComponent {
|
|
|
6778
7204
|
};
|
|
6779
7205
|
|
|
6780
7206
|
// lib/RootCircuit.ts
|
|
6781
|
-
import { su } from "@tscircuit/soup-util";
|
|
7207
|
+
import { su as su3 } from "@tscircuit/soup-util";
|
|
6782
7208
|
import { isValidElement as isValidElement2 } from "react";
|
|
6783
7209
|
import { identity as identity4 } from "transformation-matrix";
|
|
6784
7210
|
var RootCircuit = class {
|
|
@@ -6799,7 +7225,7 @@ var RootCircuit = class {
|
|
|
6799
7225
|
_hasRenderedAtleastOnce = false;
|
|
6800
7226
|
constructor() {
|
|
6801
7227
|
this.children = [];
|
|
6802
|
-
this.db =
|
|
7228
|
+
this.db = su3([]);
|
|
6803
7229
|
this.root = this;
|
|
6804
7230
|
}
|
|
6805
7231
|
add(componentOrElm) {
|
|
@@ -6857,6 +7283,7 @@ var RootCircuit = class {
|
|
|
6857
7283
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
6858
7284
|
this.render();
|
|
6859
7285
|
}
|
|
7286
|
+
this.emit("renderComplete");
|
|
6860
7287
|
}
|
|
6861
7288
|
_hasIncompleteAsyncEffects() {
|
|
6862
7289
|
return this.children.some((child) => {
|
|
@@ -7043,137 +7470,6 @@ var useResistor = createUseComponent(
|
|
|
7043
7470
|
resistorPins2
|
|
7044
7471
|
);
|
|
7045
7472
|
|
|
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
7473
|
// lib/sel/sel.ts
|
|
7178
7474
|
var sel = new Proxy(
|
|
7179
7475
|
{},
|
|
@@ -7186,6 +7482,23 @@ var sel = new Proxy(
|
|
|
7186
7482
|
if (prop1 === "net") {
|
|
7187
7483
|
return `net.${prop2}`;
|
|
7188
7484
|
}
|
|
7485
|
+
if (prop1 === "subcircuit") {
|
|
7486
|
+
return new Proxy(
|
|
7487
|
+
{},
|
|
7488
|
+
{
|
|
7489
|
+
get: (_3, prop3) => {
|
|
7490
|
+
return new Proxy(
|
|
7491
|
+
{},
|
|
7492
|
+
{
|
|
7493
|
+
get: (_4, prop4) => {
|
|
7494
|
+
return `subcircuit.${prop2} > .${prop3} > .${prop4}`;
|
|
7495
|
+
}
|
|
7496
|
+
}
|
|
7497
|
+
);
|
|
7498
|
+
}
|
|
7499
|
+
}
|
|
7500
|
+
);
|
|
7501
|
+
}
|
|
7189
7502
|
return `.${prop1} > .${prop2}`;
|
|
7190
7503
|
}
|
|
7191
7504
|
}
|
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.333",
|
|
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",
|