@tscircuit/core 0.0.330 → 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 +29 -11
- package/dist/index.js +547 -211
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
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';
|
|
6
6
|
import { z, ZodType } from 'zod';
|
|
7
7
|
import { symbols, SchSymbol, BaseSymbolName } from 'schematic-symbols';
|
|
8
|
-
import { PcbTraceError, PcbPlacementError, PcbManualEditConflictError, LayerRef, AnyCircuitElement, AnySourceComponent, PcbTrace, RouteHintPoint, CircuitJson } from 'circuit-json';
|
|
8
|
+
import { PcbTraceError, PcbPlacementError, PcbManualEditConflictError, LayerRef, AnyCircuitElement, AnySourceComponent, PcbTraceRoutePoint, PcbTrace, RouteHintPoint, CircuitJson } from 'circuit-json';
|
|
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;
|
|
@@ -662,6 +667,7 @@ declare class Trace extends PrimitiveComponent<typeof traceProps> implements Tra
|
|
|
662
667
|
_isExplicitlyConnectedToNet(net: Net): boolean;
|
|
663
668
|
doInitialCreateNetsFromProps(): void;
|
|
664
669
|
doInitialSourceTraceRender(): void;
|
|
670
|
+
_insertErrorIfTraceIsOutsideBoard(mergedRoute: PcbTraceRoutePoint[], ports: Port[]): void;
|
|
665
671
|
doInitialPcbTraceRender(): void;
|
|
666
672
|
_doInitialSchematicTraceRenderWithDisplayLabel(): void;
|
|
667
673
|
private _isSymbolToChipConnection;
|
|
@@ -902,6 +908,7 @@ declare class NormalComponent<ZodProps extends ZodType = any, PortNames extends
|
|
|
902
908
|
type SimplifiedPcbTrace = {
|
|
903
909
|
type: "pcb_trace";
|
|
904
910
|
pcb_trace_id: string;
|
|
911
|
+
connection_name?: string;
|
|
905
912
|
route: Array<{
|
|
906
913
|
route_type: "wire";
|
|
907
914
|
x: number;
|
|
@@ -965,12 +972,15 @@ declare class Group<Props extends z.ZodType<any, any, any> = typeof groupProps>
|
|
|
965
972
|
doInitialSourceParentAttachment(): void;
|
|
966
973
|
doInitialPcbComponentRender(): void;
|
|
967
974
|
doInitialCreateTraceHintsFromProps(): void;
|
|
968
|
-
_getSimpleRouteJsonFromPcbTraces(): SimpleRouteJson;
|
|
969
975
|
doInitialSourceAddConnectivityMapKey(): void;
|
|
970
976
|
_areChildSubcircuitsRouted(): boolean;
|
|
971
977
|
_shouldRouteAsync(): boolean;
|
|
972
978
|
_hasTracesToRoute(): boolean;
|
|
973
979
|
_runEffectMakeHttpAutoroutingRequest(): Promise<void>;
|
|
980
|
+
/**
|
|
981
|
+
* Run local autorouting using the CapacityMeshAutorouter
|
|
982
|
+
*/
|
|
983
|
+
_runLocalCapacityMeshAutorouting(): Promise<void>;
|
|
974
984
|
_startAsyncAutorouting(): void;
|
|
975
985
|
doInitialPcbTraceRender(): void;
|
|
976
986
|
updatePcbTraceRender(): void;
|
|
@@ -10714,10 +10724,15 @@ declare const applyEditEventsToManualEditsFile: ({ circuitJson, editEvents, manu
|
|
|
10714
10724
|
/**
|
|
10715
10725
|
* This function can only be called in the PcbTraceRender phase or later
|
|
10716
10726
|
*/
|
|
10717
|
-
declare const getSimpleRouteJsonFromCircuitJson: ({ circuitJson, minTraceWidth, }: {
|
|
10718
|
-
|
|
10727
|
+
declare const getSimpleRouteJsonFromCircuitJson: ({ db, circuitJson, subcircuit_id, minTraceWidth, }: {
|
|
10728
|
+
db?: SoupUtilObjects;
|
|
10729
|
+
circuitJson?: AnyCircuitElement[];
|
|
10730
|
+
subcircuit_id?: string | null;
|
|
10719
10731
|
minTraceWidth?: number;
|
|
10720
|
-
}) =>
|
|
10732
|
+
}) => {
|
|
10733
|
+
simpleRouteJson: SimpleRouteJson;
|
|
10734
|
+
connMap: ConnectivityMap;
|
|
10735
|
+
};
|
|
10721
10736
|
|
|
10722
10737
|
type RenderEvent = {
|
|
10723
10738
|
type: string;
|
|
@@ -10736,7 +10751,7 @@ declare const getPhaseTimingsFromRenderEvents: (renderEvents: RenderEvent[]) =>
|
|
|
10736
10751
|
type Nums16 = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "10" | "11" | "12" | "13" | "14" | "15" | "16";
|
|
10737
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";
|
|
10738
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";
|
|
10739
|
-
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;
|
|
10740
10755
|
type TransistorPinNames = "base" | "collector" | "emitter";
|
|
10741
10756
|
|
|
10742
10757
|
type NonPolarizedSel = Record<`R${Nums40}`, {
|
|
@@ -10761,12 +10776,15 @@ type PolarizedSel = Record<`C${Nums40}` | `L${Nums40}` | `LED${Nums40}` | `D${Nu
|
|
|
10761
10776
|
pos: string;
|
|
10762
10777
|
neg: string;
|
|
10763
10778
|
}>;
|
|
10779
|
+
type CommonNetNames = "VCC" | "GND" | "VDD" | "PWR" | "V5" | "V3_3";
|
|
10764
10780
|
type TransistorSel = Record<`Q${Nums40}`, Record<TransistorPinNames, string>>;
|
|
10765
|
-
type JumperSel = Record<`J${Nums40}`, Record<PinNumbers100, string>>;
|
|
10781
|
+
type JumperSel = Record<`J${Nums40}`, Record<PinNumbers100 | CommonPinNames, string>>;
|
|
10766
10782
|
type ChipSel = Record<`U${Nums40}`, Record<CommonPinNames, string>>;
|
|
10767
|
-
type NetSel = Record<"net", Record<
|
|
10783
|
+
type NetSel = Record<"net", Record<CommonNetNames, string>>;
|
|
10768
10784
|
type ConnectionSel = Record<`CN${Nums40}`, Record<CommonPinNames, string>>;
|
|
10769
|
-
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;
|
|
10770
10788
|
declare const sel: Sel;
|
|
10771
10789
|
|
|
10772
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",
|
|
@@ -3634,6 +3652,22 @@ var pushEdgesOfSchematicTraceToPreventOverlap = ({
|
|
|
3634
3652
|
}
|
|
3635
3653
|
};
|
|
3636
3654
|
|
|
3655
|
+
// lib/utils/is-route-outside-board.ts
|
|
3656
|
+
var isRouteOutsideBoard = (mergedRoute, { db }) => {
|
|
3657
|
+
const pcbBoard = db.pcb_board.list()[0];
|
|
3658
|
+
if (pcbBoard.outline) {
|
|
3659
|
+
return true;
|
|
3660
|
+
}
|
|
3661
|
+
const boardWidth = pcbBoard.width;
|
|
3662
|
+
const boardHeight = pcbBoard.height;
|
|
3663
|
+
const boardCenterX = pcbBoard.center.x;
|
|
3664
|
+
const boardCenterY = pcbBoard.center.y;
|
|
3665
|
+
const outsideBoard = mergedRoute.some((point) => {
|
|
3666
|
+
return point.x < boardCenterX - boardWidth / 2 || point.y < boardCenterY - boardHeight / 2 || point.x > boardCenterX + boardWidth / 2 || point.y > boardCenterY + boardHeight / 2;
|
|
3667
|
+
});
|
|
3668
|
+
return outsideBoard;
|
|
3669
|
+
};
|
|
3670
|
+
|
|
3637
3671
|
// lib/components/primitive-components/Trace/Trace.ts
|
|
3638
3672
|
var portToObjective = (port) => {
|
|
3639
3673
|
const portPosition = port._getGlobalPcbPositionAfterLayout();
|
|
@@ -3790,6 +3824,20 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
3790
3824
|
});
|
|
3791
3825
|
this.source_trace_id = trace.source_trace_id;
|
|
3792
3826
|
}
|
|
3827
|
+
_insertErrorIfTraceIsOutsideBoard(mergedRoute, ports) {
|
|
3828
|
+
const { db } = this.root;
|
|
3829
|
+
const isOutsideBoard = isRouteOutsideBoard(mergedRoute, { db });
|
|
3830
|
+
if (isOutsideBoard) {
|
|
3831
|
+
db.pcb_trace_error.insert({
|
|
3832
|
+
error_type: "pcb_trace_error",
|
|
3833
|
+
source_trace_id: this.source_trace_id,
|
|
3834
|
+
message: `Trace ${this.getString()} routed outside the board boundaries.`,
|
|
3835
|
+
pcb_trace_id: this.pcb_trace_id,
|
|
3836
|
+
pcb_component_ids: [],
|
|
3837
|
+
pcb_port_ids: ports.map((p) => p.pcb_port_id)
|
|
3838
|
+
});
|
|
3839
|
+
}
|
|
3840
|
+
}
|
|
3793
3841
|
doInitialPcbTraceRender() {
|
|
3794
3842
|
if (this.root?.pcbDisabled) return;
|
|
3795
3843
|
const { db } = this.root;
|
|
@@ -4061,6 +4109,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
4061
4109
|
});
|
|
4062
4110
|
}
|
|
4063
4111
|
}
|
|
4112
|
+
this._insertErrorIfTraceIsOutsideBoard(mergedRoute, ports);
|
|
4064
4113
|
}
|
|
4065
4114
|
_doInitialSchematicTraceRenderWithDisplayLabel() {
|
|
4066
4115
|
if (this.root?.schematicDisabled) return;
|
|
@@ -4658,7 +4707,6 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
4658
4707
|
if (symbol) {
|
|
4659
4708
|
const schematic_component2 = db.schematic_component.insert({
|
|
4660
4709
|
center,
|
|
4661
|
-
rotation: props.schRotation ?? 0,
|
|
4662
4710
|
size: symbol.size,
|
|
4663
4711
|
source_component_id: this.source_component_id,
|
|
4664
4712
|
symbol_name,
|
|
@@ -5102,64 +5150,156 @@ import {
|
|
|
5102
5150
|
groupProps
|
|
5103
5151
|
} from "@tscircuit/props";
|
|
5104
5152
|
import * as SAL from "@tscircuit/schematic-autolayout";
|
|
5105
|
-
import "circuit-json";
|
|
5106
|
-
import { ConnectivityMap } from "circuit-json-to-connectivity-map";
|
|
5107
|
-
import Debug5 from "debug";
|
|
5108
5153
|
|
|
5109
|
-
// lib/utils/autorouting/
|
|
5110
|
-
import {
|
|
5111
|
-
var
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
...db.pcb_plated_hole.list()
|
|
5120
|
-
]);
|
|
5121
|
-
const allPoints = obstacles.flatMap((o) => [
|
|
5122
|
-
{
|
|
5123
|
-
x: o.center.x - o.width / 2,
|
|
5124
|
-
y: o.center.y - o.height / 2
|
|
5125
|
-
},
|
|
5126
|
-
{
|
|
5127
|
-
x: o.center.x + o.width / 2,
|
|
5128
|
-
y: o.center.y + o.height / 2
|
|
5129
|
-
}
|
|
5130
|
-
]);
|
|
5131
|
-
const bounds = {
|
|
5132
|
-
minX: Math.min(...allPoints.map((p) => p.x)) - 1,
|
|
5133
|
-
maxX: Math.max(...allPoints.map((p) => p.x)) + 1,
|
|
5134
|
-
minY: Math.min(...allPoints.map((p) => p.y)) - 1,
|
|
5135
|
-
maxY: Math.max(...allPoints.map((p) => p.y)) + 1
|
|
5136
|
-
};
|
|
5137
|
-
const connections = traces.map((trace) => {
|
|
5138
|
-
const connectedPorts = trace._findConnectedPorts();
|
|
5139
|
-
if (!connectedPorts.allPortsFound || connectedPorts.ports.length < 2)
|
|
5140
|
-
return null;
|
|
5141
|
-
return {
|
|
5142
|
-
name: trace.source_trace_id ?? "",
|
|
5143
|
-
pointsToConnect: connectedPorts.ports.map((port) => {
|
|
5144
|
-
const pos = port._getGlobalPcbPositionBeforeLayout();
|
|
5145
|
-
return {
|
|
5146
|
-
x: pos.x,
|
|
5147
|
-
y: pos.y,
|
|
5148
|
-
layer: port.getAvailablePcbLayers()[0] ?? "top"
|
|
5149
|
-
};
|
|
5150
|
-
})
|
|
5151
|
-
};
|
|
5152
|
-
}).filter((c) => c !== null);
|
|
5153
|
-
return {
|
|
5154
|
-
bounds,
|
|
5155
|
-
obstacles: [],
|
|
5156
|
-
connections,
|
|
5157
|
-
layerCount: 2,
|
|
5158
|
-
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: []
|
|
5159
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
|
+
}
|
|
5160
5297
|
};
|
|
5161
5298
|
|
|
5162
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";
|
|
5163
5303
|
import "zod";
|
|
5164
5304
|
|
|
5165
5305
|
// lib/components/primitive-components/TraceHint.ts
|
|
@@ -5223,6 +5363,220 @@ var TraceHint = class extends PrimitiveComponent {
|
|
|
5223
5363
|
}
|
|
5224
5364
|
};
|
|
5225
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
|
+
|
|
5226
5580
|
// lib/components/primitive-components/Group/Group.ts
|
|
5227
5581
|
var Group = class extends NormalComponent {
|
|
5228
5582
|
pcb_group_id = null;
|
|
@@ -5288,20 +5642,11 @@ var Group = class extends NormalComponent {
|
|
|
5288
5642
|
);
|
|
5289
5643
|
}
|
|
5290
5644
|
}
|
|
5291
|
-
_getSimpleRouteJsonFromPcbTraces() {
|
|
5292
|
-
const traces = this.selectAll("trace");
|
|
5293
|
-
const { db } = this.root;
|
|
5294
|
-
return getSimpleRouteJsonFromTracesAndDb({
|
|
5295
|
-
db,
|
|
5296
|
-
traces,
|
|
5297
|
-
minTraceWidth: this._parsedProps.minTraceWidth ?? 0.1
|
|
5298
|
-
});
|
|
5299
|
-
}
|
|
5300
5645
|
doInitialSourceAddConnectivityMapKey() {
|
|
5301
5646
|
if (!this.isSubcircuit) return;
|
|
5302
5647
|
const { db } = this.root;
|
|
5303
5648
|
const traces = this.selectAll("trace");
|
|
5304
|
-
const connMap = new
|
|
5649
|
+
const connMap = new ConnectivityMap2({});
|
|
5305
5650
|
connMap.addConnections(
|
|
5306
5651
|
traces.map((t) => {
|
|
5307
5652
|
const source_trace = db.source_trace.get(
|
|
@@ -5339,9 +5684,10 @@ var Group = class extends NormalComponent {
|
|
|
5339
5684
|
}
|
|
5340
5685
|
_shouldRouteAsync() {
|
|
5341
5686
|
const autorouter = this._getAutorouterConfig();
|
|
5342
|
-
if (autorouter.local) return false;
|
|
5343
5687
|
if (autorouter.groupMode === "sequential-trace") return false;
|
|
5344
|
-
return true;
|
|
5688
|
+
if (autorouter.local && autorouter.groupMode === "subcircuit") return true;
|
|
5689
|
+
if (!autorouter.local) return true;
|
|
5690
|
+
return false;
|
|
5345
5691
|
}
|
|
5346
5692
|
_hasTracesToRoute() {
|
|
5347
5693
|
const debug4 = Debug5("tscircuit:core:_hasTracesToRoute");
|
|
@@ -5372,7 +5718,11 @@ var Group = class extends NormalComponent {
|
|
|
5372
5718
|
{
|
|
5373
5719
|
method: "POST",
|
|
5374
5720
|
body: JSON.stringify({
|
|
5375
|
-
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,
|
|
5376
5726
|
subcircuit_id: this.subcircuit_id
|
|
5377
5727
|
}),
|
|
5378
5728
|
headers: { "Content-Type": "application/json" }
|
|
@@ -5450,12 +5800,73 @@ var Group = class extends NormalComponent {
|
|
|
5450
5800
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
5451
5801
|
}
|
|
5452
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
|
+
}
|
|
5453
5857
|
_startAsyncAutorouting() {
|
|
5454
5858
|
this._hasStartedAsyncAutorouting = true;
|
|
5455
|
-
this.
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
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
|
+
}
|
|
5459
5870
|
}
|
|
5460
5871
|
doInitialPcbTraceRender() {
|
|
5461
5872
|
const debug4 = Debug5("tscircuit:core:doInitialPcbTraceRender");
|
|
@@ -5477,6 +5888,7 @@ var Group = class extends NormalComponent {
|
|
|
5477
5888
|
}
|
|
5478
5889
|
updatePcbTraceRender() {
|
|
5479
5890
|
const debug4 = Debug5("tscircuit:core:updatePcbTraceRender");
|
|
5891
|
+
debug4(`[${this.getString()}] updating...`);
|
|
5480
5892
|
if (!this.isSubcircuit) return;
|
|
5481
5893
|
if (this._shouldRouteAsync() && this._hasTracesToRoute() && !this._hasStartedAsyncAutorouting) {
|
|
5482
5894
|
if (this._areChildSubcircuitsRouted()) {
|
|
@@ -5491,10 +5903,16 @@ var Group = class extends NormalComponent {
|
|
|
5491
5903
|
if (this._shouldUseTraceByTraceRouting()) return;
|
|
5492
5904
|
const { db } = this.root;
|
|
5493
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
|
+
);
|
|
5494
5909
|
this._updatePcbTraceRenderFromSimpleRouteJson();
|
|
5495
5910
|
return;
|
|
5496
5911
|
}
|
|
5497
5912
|
if (this._asyncAutoroutingResult.output_pcb_traces) {
|
|
5913
|
+
debug4(
|
|
5914
|
+
`[${this.getString()}] updating PCB traces from ${this._asyncAutoroutingResult.output_pcb_traces.length} traces`
|
|
5915
|
+
);
|
|
5498
5916
|
this._updatePcbTraceRenderFromPcbTraces();
|
|
5499
5917
|
return;
|
|
5500
5918
|
}
|
|
@@ -5503,9 +5921,9 @@ var Group = class extends NormalComponent {
|
|
|
5503
5921
|
const { db } = this.root;
|
|
5504
5922
|
const { traces: routedTraces } = this._asyncAutoroutingResult.output_simple_route_json;
|
|
5505
5923
|
if (!routedTraces) return;
|
|
5506
|
-
const circuitTraces = this.selectAll("trace");
|
|
5507
5924
|
for (const routedTrace of routedTraces) {
|
|
5508
5925
|
const pcb_trace = db.pcb_trace.insert({
|
|
5926
|
+
subcircuit_id: this.subcircuit_id,
|
|
5509
5927
|
route: routedTrace.route
|
|
5510
5928
|
// source_trace_id: circuitTrace.source_trace_id!,
|
|
5511
5929
|
});
|
|
@@ -5519,6 +5937,22 @@ var Group = class extends NormalComponent {
|
|
|
5519
5937
|
pcb_trace.subcircuit_id = this.subcircuit_id;
|
|
5520
5938
|
db.pcb_trace.insert(pcb_trace);
|
|
5521
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
|
+
}
|
|
5522
5956
|
}
|
|
5523
5957
|
doInitialSchematicLayout() {
|
|
5524
5958
|
if (!this.isSubcircuit) return;
|
|
@@ -5550,7 +5984,7 @@ var Group = class extends NormalComponent {
|
|
|
5550
5984
|
const defaults = {
|
|
5551
5985
|
serverUrl: "https://registry-api.tscircuit.com",
|
|
5552
5986
|
serverMode: "job",
|
|
5553
|
-
serverCacheEnabled:
|
|
5987
|
+
serverCacheEnabled: true
|
|
5554
5988
|
};
|
|
5555
5989
|
const autorouter = this._parsedProps.autorouter ?? this.getInheritedProperty("autorouter");
|
|
5556
5990
|
if (typeof autorouter === "object") {
|
|
@@ -5562,13 +5996,27 @@ var Group = class extends NormalComponent {
|
|
|
5562
5996
|
}
|
|
5563
5997
|
if (autorouter === "auto-local")
|
|
5564
5998
|
return {
|
|
5565
|
-
local: true
|
|
5999
|
+
local: true,
|
|
6000
|
+
groupMode: "subcircuit"
|
|
5566
6001
|
};
|
|
5567
6002
|
if (autorouter === "sequential-trace")
|
|
5568
6003
|
return {
|
|
5569
6004
|
local: true,
|
|
5570
6005
|
groupMode: "sequential-trace"
|
|
5571
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
|
+
};
|
|
5572
6020
|
return {
|
|
5573
6021
|
local: true,
|
|
5574
6022
|
groupMode: "sequential-trace"
|
|
@@ -6426,7 +6874,9 @@ var PinHeader = class extends NormalComponent {
|
|
|
6426
6874
|
new Port({
|
|
6427
6875
|
name: `pin${i}`,
|
|
6428
6876
|
pinNumber: i,
|
|
6429
|
-
aliases: []
|
|
6877
|
+
aliases: [this._parsedProps.pinLabels?.[i - 1]].filter(
|
|
6878
|
+
Boolean
|
|
6879
|
+
)
|
|
6430
6880
|
})
|
|
6431
6881
|
);
|
|
6432
6882
|
}
|
|
@@ -6747,7 +7197,7 @@ var Switch = class extends NormalComponent {
|
|
|
6747
7197
|
};
|
|
6748
7198
|
|
|
6749
7199
|
// lib/RootCircuit.ts
|
|
6750
|
-
import { su } from "@tscircuit/soup-util";
|
|
7200
|
+
import { su as su3 } from "@tscircuit/soup-util";
|
|
6751
7201
|
import { isValidElement as isValidElement2 } from "react";
|
|
6752
7202
|
import { identity as identity4 } from "transformation-matrix";
|
|
6753
7203
|
var RootCircuit = class {
|
|
@@ -6768,7 +7218,7 @@ var RootCircuit = class {
|
|
|
6768
7218
|
_hasRenderedAtleastOnce = false;
|
|
6769
7219
|
constructor() {
|
|
6770
7220
|
this.children = [];
|
|
6771
|
-
this.db =
|
|
7221
|
+
this.db = su3([]);
|
|
6772
7222
|
this.root = this;
|
|
6773
7223
|
}
|
|
6774
7224
|
add(componentOrElm) {
|
|
@@ -7012,137 +7462,6 @@ var useResistor = createUseComponent(
|
|
|
7012
7462
|
resistorPins2
|
|
7013
7463
|
);
|
|
7014
7464
|
|
|
7015
|
-
// lib/utils/edit-events/apply-edit-events-to-manual-edits-file.ts
|
|
7016
|
-
import "zod";
|
|
7017
|
-
import { su as su2 } from "@tscircuit/soup-util";
|
|
7018
|
-
var applyEditEventsToManualEditsFile = ({
|
|
7019
|
-
circuitJson,
|
|
7020
|
-
editEvents,
|
|
7021
|
-
manualEditsFile
|
|
7022
|
-
}) => {
|
|
7023
|
-
const updatedManualEditsFile = {
|
|
7024
|
-
...manualEditsFile,
|
|
7025
|
-
schematic_placements: [...manualEditsFile.schematic_placements ?? []]
|
|
7026
|
-
};
|
|
7027
|
-
for (const editEvent of editEvents) {
|
|
7028
|
-
if (editEvent.edit_event_type === "edit_schematic_component_location") {
|
|
7029
|
-
const { schematic_component_id, new_center } = editEvent;
|
|
7030
|
-
const schematic_component2 = su2(circuitJson).schematic_component.get(
|
|
7031
|
-
schematic_component_id
|
|
7032
|
-
);
|
|
7033
|
-
if (!schematic_component2) continue;
|
|
7034
|
-
const source_component = su2(circuitJson).source_component.get(
|
|
7035
|
-
schematic_component2.source_component_id
|
|
7036
|
-
);
|
|
7037
|
-
if (!source_component) continue;
|
|
7038
|
-
const existingPlacementIndex = updatedManualEditsFile.schematic_placements?.findIndex(
|
|
7039
|
-
(p) => p.selector === source_component.name
|
|
7040
|
-
);
|
|
7041
|
-
const newPlacement = {
|
|
7042
|
-
selector: source_component.name,
|
|
7043
|
-
center: new_center,
|
|
7044
|
-
relative_to: "group_center"
|
|
7045
|
-
};
|
|
7046
|
-
if (existingPlacementIndex >= 0) {
|
|
7047
|
-
updatedManualEditsFile.schematic_placements[existingPlacementIndex] = newPlacement;
|
|
7048
|
-
} else {
|
|
7049
|
-
updatedManualEditsFile.schematic_placements.push(newPlacement);
|
|
7050
|
-
}
|
|
7051
|
-
}
|
|
7052
|
-
}
|
|
7053
|
-
return updatedManualEditsFile;
|
|
7054
|
-
};
|
|
7055
|
-
|
|
7056
|
-
// lib/utils/autorouting/getSimpleRouteJsonFromCircuitJson.ts
|
|
7057
|
-
import { getObstaclesFromSoup as getObstaclesFromSoup3 } from "@tscircuit/infgrid-ijump-astar";
|
|
7058
|
-
import { su as su3 } from "@tscircuit/soup-util";
|
|
7059
|
-
import { getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson2 } from "circuit-json-to-connectivity-map";
|
|
7060
|
-
var getSimpleRouteJsonFromCircuitJson = ({
|
|
7061
|
-
circuitJson,
|
|
7062
|
-
minTraceWidth = 0.1
|
|
7063
|
-
}) => {
|
|
7064
|
-
const db = su3(circuitJson);
|
|
7065
|
-
const connMap = getFullConnectivityMapFromCircuitJson2(circuitJson);
|
|
7066
|
-
const obstacles = getObstaclesFromSoup3(
|
|
7067
|
-
[
|
|
7068
|
-
...db.pcb_component.list(),
|
|
7069
|
-
...db.pcb_smtpad.list(),
|
|
7070
|
-
...db.pcb_plated_hole.list()
|
|
7071
|
-
],
|
|
7072
|
-
connMap
|
|
7073
|
-
);
|
|
7074
|
-
const allPoints = obstacles.flatMap((o) => [
|
|
7075
|
-
{
|
|
7076
|
-
x: o.center.x - o.width / 2,
|
|
7077
|
-
y: o.center.y - o.height / 2
|
|
7078
|
-
},
|
|
7079
|
-
{
|
|
7080
|
-
x: o.center.x + o.width / 2,
|
|
7081
|
-
y: o.center.y + o.height / 2
|
|
7082
|
-
}
|
|
7083
|
-
]);
|
|
7084
|
-
const bounds = {
|
|
7085
|
-
minX: Math.min(...allPoints.map((p) => p.x)) - 1,
|
|
7086
|
-
maxX: Math.max(...allPoints.map((p) => p.x)) + 1,
|
|
7087
|
-
minY: Math.min(...allPoints.map((p) => p.y)) - 1,
|
|
7088
|
-
maxY: Math.max(...allPoints.map((p) => p.y)) + 1
|
|
7089
|
-
};
|
|
7090
|
-
const connections = db.source_trace.list().map((trace) => {
|
|
7091
|
-
const connectedPorts = trace.connected_source_port_ids.map((id) => {
|
|
7092
|
-
const source_port = db.source_port.get(id);
|
|
7093
|
-
const pcb_port = db.pcb_port.getWhere({ source_port_id: id });
|
|
7094
|
-
return {
|
|
7095
|
-
...source_port,
|
|
7096
|
-
...pcb_port
|
|
7097
|
-
};
|
|
7098
|
-
});
|
|
7099
|
-
if (connectedPorts.length < 2) return null;
|
|
7100
|
-
return {
|
|
7101
|
-
name: connMap.getNetConnectedToId(trace.source_trace_id) ?? trace.source_trace_id ?? "",
|
|
7102
|
-
source_trace_id: trace.source_trace_id,
|
|
7103
|
-
pointsToConnect: connectedPorts.map((port) => {
|
|
7104
|
-
return {
|
|
7105
|
-
x: port.x,
|
|
7106
|
-
y: port.y,
|
|
7107
|
-
layer: port.layers?.[0] ?? "top"
|
|
7108
|
-
};
|
|
7109
|
-
})
|
|
7110
|
-
};
|
|
7111
|
-
}).filter((c) => c !== null);
|
|
7112
|
-
return {
|
|
7113
|
-
bounds,
|
|
7114
|
-
obstacles,
|
|
7115
|
-
connections,
|
|
7116
|
-
layerCount: 2,
|
|
7117
|
-
minTraceWidth
|
|
7118
|
-
};
|
|
7119
|
-
};
|
|
7120
|
-
|
|
7121
|
-
// lib/utils/render-events/getPhaseTimingsFromRenderEvents.ts
|
|
7122
|
-
var getPhaseTimingsFromRenderEvents = (renderEvents) => {
|
|
7123
|
-
const phaseTimings = {};
|
|
7124
|
-
if (!renderEvents) return phaseTimings;
|
|
7125
|
-
for (const renderPhase of orderedRenderPhases) {
|
|
7126
|
-
phaseTimings[renderPhase] = 0;
|
|
7127
|
-
}
|
|
7128
|
-
const startEvents = /* @__PURE__ */ new Map();
|
|
7129
|
-
for (const event of renderEvents) {
|
|
7130
|
-
const [, , phase, eventType] = event.type.split(":");
|
|
7131
|
-
if (eventType === "start") {
|
|
7132
|
-
startEvents.set(`${phase}:${event.renderId}`, event);
|
|
7133
|
-
continue;
|
|
7134
|
-
}
|
|
7135
|
-
if (eventType === "end") {
|
|
7136
|
-
const startEvent = startEvents.get(`${phase}:${event.renderId}`);
|
|
7137
|
-
if (startEvent) {
|
|
7138
|
-
const duration = event.createdAt - startEvent.createdAt;
|
|
7139
|
-
phaseTimings[phase] = (phaseTimings[phase] || 0) + duration;
|
|
7140
|
-
}
|
|
7141
|
-
}
|
|
7142
|
-
}
|
|
7143
|
-
return phaseTimings;
|
|
7144
|
-
};
|
|
7145
|
-
|
|
7146
7465
|
// lib/sel/sel.ts
|
|
7147
7466
|
var sel = new Proxy(
|
|
7148
7467
|
{},
|
|
@@ -7155,6 +7474,23 @@ var sel = new Proxy(
|
|
|
7155
7474
|
if (prop1 === "net") {
|
|
7156
7475
|
return `net.${prop2}`;
|
|
7157
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
|
+
}
|
|
7158
7494
|
return `.${prop1} > .${prop2}`;
|
|
7159
7495
|
}
|
|
7160
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",
|