@tscircuit/core 0.0.1067 → 0.0.1069
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 +1 -0
- package/dist/index.js +1135 -1134
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -11020,6 +11020,35 @@ var NormalComponent3 = class extends PrimitiveComponent2 {
|
|
|
11020
11020
|
}
|
|
11021
11021
|
};
|
|
11022
11022
|
|
|
11023
|
+
// lib/components/normal-components/Board.ts
|
|
11024
|
+
import {
|
|
11025
|
+
runAllNetlistChecks,
|
|
11026
|
+
runAllPlacementChecks,
|
|
11027
|
+
runAllRoutingChecks
|
|
11028
|
+
} from "@tscircuit/checks";
|
|
11029
|
+
import { getBoundsFromPoints as getBoundsFromPoints4 } from "@tscircuit/math-utils";
|
|
11030
|
+
import { boardProps } from "@tscircuit/props";
|
|
11031
|
+
import { compose as compose7, translate as translate7 } from "transformation-matrix";
|
|
11032
|
+
|
|
11033
|
+
// lib/utils/autorouting/getAncestorSubcircuitIds.ts
|
|
11034
|
+
var getDescendantSubcircuitIds = (db, root_subcircuit_id) => {
|
|
11035
|
+
const groups = db.source_group.list();
|
|
11036
|
+
const result = [];
|
|
11037
|
+
const findDescendants = (parentId) => {
|
|
11038
|
+
const children = groups.filter(
|
|
11039
|
+
(group) => group.parent_subcircuit_id === parentId
|
|
11040
|
+
);
|
|
11041
|
+
for (const child of children) {
|
|
11042
|
+
if (child.subcircuit_id) {
|
|
11043
|
+
result.push(child.subcircuit_id);
|
|
11044
|
+
findDescendants(child.subcircuit_id);
|
|
11045
|
+
}
|
|
11046
|
+
}
|
|
11047
|
+
};
|
|
11048
|
+
findDescendants(root_subcircuit_id);
|
|
11049
|
+
return result;
|
|
11050
|
+
};
|
|
11051
|
+
|
|
11023
11052
|
// lib/utils/boards/get-board-center-from-anchor.ts
|
|
11024
11053
|
var getBoardCenterFromAnchor = ({
|
|
11025
11054
|
boardAnchorPosition,
|
|
@@ -11070,311 +11099,817 @@ var getBoardCenterFromAnchor = ({
|
|
|
11070
11099
|
return { x: cx, y: cy };
|
|
11071
11100
|
};
|
|
11072
11101
|
|
|
11073
|
-
// lib/
|
|
11074
|
-
import {
|
|
11075
|
-
|
|
11076
|
-
// lib/components/primitive-components/Group/Group.ts
|
|
11077
|
-
import { convertSrjToGraphicsObject } from "@tscircuit/capacity-autorouter";
|
|
11078
|
-
import { getBoundsFromPoints as getBoundsFromPoints3 } from "@tscircuit/math-utils";
|
|
11079
|
-
import {
|
|
11080
|
-
groupProps
|
|
11081
|
-
} from "@tscircuit/props";
|
|
11082
|
-
import {
|
|
11083
|
-
distance as distance8
|
|
11084
|
-
} from "circuit-json";
|
|
11085
|
-
import Debug13 from "debug";
|
|
11086
|
-
|
|
11087
|
-
// lib/utils/autorouting/CapacityMeshAutorouter.ts
|
|
11088
|
-
import "@tscircuit/capacity-autorouter";
|
|
11089
|
-
|
|
11090
|
-
// lib/solvers.ts
|
|
11091
|
-
import { PackSolver2 } from "calculate-packing";
|
|
11092
|
-
import {
|
|
11093
|
-
AutoroutingPipelineSolver,
|
|
11094
|
-
AssignableAutoroutingPipeline2,
|
|
11095
|
-
AutoroutingPipeline1_OriginalUnravel,
|
|
11096
|
-
AssignableAutoroutingPipeline3
|
|
11097
|
-
} from "@tscircuit/capacity-autorouter";
|
|
11098
|
-
import { CopperPourPipelineSolver } from "@tscircuit/copper-pour-solver";
|
|
11099
|
-
var SOLVERS = {
|
|
11100
|
-
PackSolver2,
|
|
11101
|
-
AutoroutingPipelineSolver,
|
|
11102
|
-
AssignableAutoroutingPipeline2,
|
|
11103
|
-
AssignableAutoroutingPipeline3,
|
|
11104
|
-
AutoroutingPipeline1_OriginalUnravel,
|
|
11105
|
-
CopperPourPipelineSolver
|
|
11106
|
-
};
|
|
11102
|
+
// lib/utils/circuit-json/inflate-circuit-json.ts
|
|
11103
|
+
import { cju } from "@tscircuit/circuit-json-util";
|
|
11107
11104
|
|
|
11108
|
-
// lib/
|
|
11109
|
-
|
|
11110
|
-
|
|
11111
|
-
|
|
11112
|
-
|
|
11113
|
-
|
|
11114
|
-
|
|
11115
|
-
|
|
11116
|
-
|
|
11105
|
+
// lib/components/primitive-components/Group/Subcircuit/inflators/inflatePcbBoard.ts
|
|
11106
|
+
function inflatePcbBoard(pcbBoard, inflatorContext) {
|
|
11107
|
+
const { subcircuit } = inflatorContext;
|
|
11108
|
+
if (subcircuit.lowercaseComponentName === "board" || subcircuit.lowercaseComponentName === "mountedboard") {
|
|
11109
|
+
return;
|
|
11110
|
+
}
|
|
11111
|
+
if (subcircuit.parent?.lowercaseComponentName === "board") {
|
|
11112
|
+
return;
|
|
11113
|
+
}
|
|
11114
|
+
const boardProps2 = {
|
|
11115
|
+
name: "inflated_board"
|
|
11117
11116
|
};
|
|
11118
|
-
|
|
11119
|
-
|
|
11120
|
-
|
|
11121
|
-
|
|
11122
|
-
|
|
11123
|
-
const {
|
|
11124
|
-
capacityDepth,
|
|
11125
|
-
targetMinCapacity,
|
|
11126
|
-
stepDelay = 0,
|
|
11127
|
-
useAssignableSolver = false,
|
|
11128
|
-
useAutoJumperSolver = false,
|
|
11129
|
-
autorouterVersion: autorouterVersion2,
|
|
11130
|
-
effort,
|
|
11131
|
-
onSolverStarted
|
|
11132
|
-
} = options;
|
|
11133
|
-
let solverName;
|
|
11134
|
-
if (autorouterVersion2 === "v1") {
|
|
11135
|
-
solverName = "AutoroutingPipeline1_OriginalUnravel";
|
|
11136
|
-
} else if (useAutoJumperSolver) {
|
|
11137
|
-
solverName = "AssignableAutoroutingPipeline3";
|
|
11138
|
-
} else if (useAssignableSolver) {
|
|
11139
|
-
solverName = "AssignableAutoroutingPipeline2";
|
|
11140
|
-
} else {
|
|
11141
|
-
solverName = "AutoroutingPipelineSolver";
|
|
11142
|
-
}
|
|
11143
|
-
const SolverClass = SOLVERS[solverName];
|
|
11144
|
-
this.solver = new SolverClass(input, {
|
|
11145
|
-
capacityDepth,
|
|
11146
|
-
targetMinCapacity,
|
|
11147
|
-
cacheProvider: null,
|
|
11148
|
-
effort
|
|
11149
|
-
});
|
|
11150
|
-
onSolverStarted?.({
|
|
11151
|
-
solverName,
|
|
11152
|
-
solverParams: {
|
|
11153
|
-
input,
|
|
11154
|
-
options: {
|
|
11155
|
-
capacityDepth,
|
|
11156
|
-
targetMinCapacity,
|
|
11157
|
-
cacheProvider: null,
|
|
11158
|
-
effort
|
|
11159
|
-
}
|
|
11160
|
-
}
|
|
11161
|
-
});
|
|
11162
|
-
this.stepDelay = stepDelay;
|
|
11117
|
+
if (pcbBoard.width) boardProps2.width = pcbBoard.width;
|
|
11118
|
+
if (pcbBoard.height) boardProps2.height = pcbBoard.height;
|
|
11119
|
+
if (pcbBoard.center) {
|
|
11120
|
+
boardProps2.pcbX = pcbBoard.center.x;
|
|
11121
|
+
boardProps2.pcbY = pcbBoard.center.y;
|
|
11163
11122
|
}
|
|
11164
|
-
|
|
11165
|
-
|
|
11166
|
-
|
|
11167
|
-
|
|
11168
|
-
|
|
11169
|
-
|
|
11170
|
-
|
|
11171
|
-
|
|
11172
|
-
|
|
11123
|
+
if (pcbBoard.outline) boardProps2.outline = pcbBoard.outline;
|
|
11124
|
+
if (pcbBoard.thickness) boardProps2.thickness = pcbBoard.thickness;
|
|
11125
|
+
if (pcbBoard.material) boardProps2.material = pcbBoard.material;
|
|
11126
|
+
const board = new Board(boardProps2);
|
|
11127
|
+
board.pcb_board_id = pcbBoard.pcb_board_id;
|
|
11128
|
+
subcircuit.add(board);
|
|
11129
|
+
return board;
|
|
11130
|
+
}
|
|
11131
|
+
|
|
11132
|
+
// lib/components/normal-components/Capacitor.ts
|
|
11133
|
+
import { capacitorProps } from "@tscircuit/props";
|
|
11134
|
+
import { formatSiUnit } from "format-si-unit";
|
|
11135
|
+
var Capacitor = class extends NormalComponent3 {
|
|
11136
|
+
_adjustSilkscreenTextAutomatically = true;
|
|
11137
|
+
get config() {
|
|
11138
|
+
return {
|
|
11139
|
+
componentName: "Capacitor",
|
|
11140
|
+
schematicSymbolName: this.props.polarized ? "capacitor_polarized" : this.props.symbolName ?? "capacitor",
|
|
11141
|
+
zodProps: capacitorProps,
|
|
11142
|
+
sourceFtype: FTYPE.simple_capacitor
|
|
11143
|
+
};
|
|
11173
11144
|
}
|
|
11174
|
-
|
|
11175
|
-
|
|
11176
|
-
|
|
11177
|
-
|
|
11178
|
-
|
|
11179
|
-
|
|
11180
|
-
if (this.solver.solved || this.solver.failed) {
|
|
11181
|
-
if (this.solver.failed) {
|
|
11182
|
-
this.emitEvent({
|
|
11183
|
-
type: "error",
|
|
11184
|
-
error: new AutorouterError(this.solver.error || "Routing failed")
|
|
11185
|
-
});
|
|
11186
|
-
} else {
|
|
11187
|
-
this.emitEvent({
|
|
11188
|
-
type: "complete",
|
|
11189
|
-
traces: this.solver.getOutputSimpleRouteJson().traces || []
|
|
11190
|
-
});
|
|
11145
|
+
initPorts() {
|
|
11146
|
+
if (typeof this.props.footprint === "string") {
|
|
11147
|
+
super.initPorts({
|
|
11148
|
+
additionalAliases: {
|
|
11149
|
+
pin1: ["anode", "pos"],
|
|
11150
|
+
pin2: ["cathode", "neg"]
|
|
11191
11151
|
}
|
|
11192
|
-
this.isRouting = false;
|
|
11193
|
-
return;
|
|
11194
|
-
}
|
|
11195
|
-
const startTime = Date.now();
|
|
11196
|
-
const startIterations = this.solver.iterations;
|
|
11197
|
-
while (Date.now() - startTime < 250 && !this.solver.failed && !this.solver.solved) {
|
|
11198
|
-
this.solver.step();
|
|
11199
|
-
}
|
|
11200
|
-
const iterationsPerSecond = (this.solver.iterations - startIterations) / (Date.now() - startTime) * 1e3;
|
|
11201
|
-
this.cycleCount++;
|
|
11202
|
-
const debugGraphics = this.solver?.preview() || void 0;
|
|
11203
|
-
const progress = this.solver.progress;
|
|
11204
|
-
this.emitEvent({
|
|
11205
|
-
type: "progress",
|
|
11206
|
-
steps: this.cycleCount,
|
|
11207
|
-
iterationsPerSecond,
|
|
11208
|
-
progress,
|
|
11209
|
-
phase: this.solver.getCurrentPhase(),
|
|
11210
|
-
debugGraphics
|
|
11211
|
-
});
|
|
11212
|
-
if (this.stepDelay > 0) {
|
|
11213
|
-
this.timeoutId = setTimeout(
|
|
11214
|
-
() => this.runCycleAndQueueNextCycle(),
|
|
11215
|
-
this.stepDelay
|
|
11216
|
-
);
|
|
11217
|
-
} else {
|
|
11218
|
-
this.timeoutId = setTimeout(
|
|
11219
|
-
() => this.runCycleAndQueueNextCycle(),
|
|
11220
|
-
0
|
|
11221
|
-
);
|
|
11222
|
-
}
|
|
11223
|
-
} catch (error) {
|
|
11224
|
-
this.emitEvent({
|
|
11225
|
-
type: "error",
|
|
11226
|
-
error: error instanceof Error ? new AutorouterError(error.message) : new AutorouterError(String(error))
|
|
11227
11152
|
});
|
|
11228
|
-
|
|
11153
|
+
} else {
|
|
11154
|
+
super.initPorts();
|
|
11229
11155
|
}
|
|
11230
11156
|
}
|
|
11231
|
-
|
|
11232
|
-
|
|
11233
|
-
|
|
11234
|
-
|
|
11235
|
-
|
|
11236
|
-
this.isRouting = false;
|
|
11237
|
-
if (this.timeoutId !== void 0) {
|
|
11238
|
-
clearTimeout(this.timeoutId);
|
|
11239
|
-
this.timeoutId = void 0;
|
|
11157
|
+
_getSchematicSymbolDisplayValue() {
|
|
11158
|
+
const inputCapacitance = this.props.capacitance;
|
|
11159
|
+
const capacitanceDisplay = typeof inputCapacitance === "string" ? inputCapacitance : `${formatSiUnit(this._parsedProps.capacitance)}F`;
|
|
11160
|
+
if (this._parsedProps.schShowRatings && this._parsedProps.maxVoltageRating) {
|
|
11161
|
+
return `${capacitanceDisplay}/${formatSiUnit(this._parsedProps.maxVoltageRating)}V`;
|
|
11240
11162
|
}
|
|
11163
|
+
return capacitanceDisplay;
|
|
11241
11164
|
}
|
|
11242
|
-
|
|
11243
|
-
|
|
11244
|
-
this.
|
|
11245
|
-
|
|
11165
|
+
doInitialCreateNetsFromProps() {
|
|
11166
|
+
this._createNetsFromProps([
|
|
11167
|
+
this.props.decouplingFor,
|
|
11168
|
+
this.props.decouplingTo,
|
|
11169
|
+
...this._getNetsFromConnectionsProp()
|
|
11170
|
+
]);
|
|
11171
|
+
}
|
|
11172
|
+
doInitialCreateTracesFromProps() {
|
|
11173
|
+
if (this.props.decouplingFor && this.props.decouplingTo) {
|
|
11174
|
+
this.add(
|
|
11175
|
+
new Trace3({
|
|
11176
|
+
from: `${this.getSubcircuitSelector()} > port.1`,
|
|
11177
|
+
to: this.props.decouplingFor
|
|
11178
|
+
})
|
|
11246
11179
|
);
|
|
11247
|
-
|
|
11248
|
-
|
|
11249
|
-
|
|
11250
|
-
|
|
11251
|
-
|
|
11252
|
-
this.eventHandlers.progress.push(
|
|
11253
|
-
callback
|
|
11180
|
+
this.add(
|
|
11181
|
+
new Trace3({
|
|
11182
|
+
from: `${this.getSubcircuitSelector()} > port.2`,
|
|
11183
|
+
to: this.props.decouplingTo
|
|
11184
|
+
})
|
|
11254
11185
|
);
|
|
11255
11186
|
}
|
|
11187
|
+
this._createTracesFromConnectionsProp();
|
|
11256
11188
|
}
|
|
11257
|
-
|
|
11258
|
-
|
|
11259
|
-
|
|
11260
|
-
|
|
11261
|
-
|
|
11262
|
-
|
|
11263
|
-
|
|
11264
|
-
|
|
11265
|
-
|
|
11266
|
-
|
|
11267
|
-
|
|
11268
|
-
|
|
11269
|
-
|
|
11270
|
-
|
|
11271
|
-
|
|
11272
|
-
|
|
11273
|
-
}
|
|
11274
|
-
}
|
|
11275
|
-
/**
|
|
11276
|
-
* Solve the routing problem synchronously
|
|
11277
|
-
* @returns Array of routed traces
|
|
11278
|
-
*/
|
|
11279
|
-
solveSync() {
|
|
11280
|
-
this.solver.solve();
|
|
11281
|
-
if (this.solver.failed) {
|
|
11282
|
-
throw new AutorouterError(this.solver.error || "Routing failed");
|
|
11283
|
-
}
|
|
11284
|
-
return this.solver.getOutputSimpleRouteJson().traces || [];
|
|
11285
|
-
}
|
|
11286
|
-
/**
|
|
11287
|
-
* Get the mapping of obstacle IDs to root connection names that were
|
|
11288
|
-
* connected via off-board paths (e.g., interconnects).
|
|
11289
|
-
* Only available when using AssignableAutoroutingPipeline2.
|
|
11290
|
-
*/
|
|
11291
|
-
getConnectedOffboardObstacles() {
|
|
11292
|
-
if ("getConnectedOffboardObstacles" in this.solver) {
|
|
11293
|
-
return this.solver.getConnectedOffboardObstacles();
|
|
11294
|
-
}
|
|
11295
|
-
return {};
|
|
11189
|
+
doInitialSourceRender() {
|
|
11190
|
+
const { db } = this.root;
|
|
11191
|
+
const { _parsedProps: props } = this;
|
|
11192
|
+
const source_component = db.source_component.insert({
|
|
11193
|
+
ftype: "simple_capacitor",
|
|
11194
|
+
name: this.name,
|
|
11195
|
+
manufacturer_part_number: props.manufacturerPartNumber ?? props.mfn,
|
|
11196
|
+
supplier_part_numbers: props.supplierPartNumbers,
|
|
11197
|
+
capacitance: props.capacitance,
|
|
11198
|
+
max_voltage_rating: props.maxVoltageRating,
|
|
11199
|
+
max_decoupling_trace_length: props.maxDecouplingTraceLength,
|
|
11200
|
+
display_capacitance: this._getSchematicSymbolDisplayValue(),
|
|
11201
|
+
are_pins_interchangeable: !props.polarized,
|
|
11202
|
+
display_name: props.displayName
|
|
11203
|
+
});
|
|
11204
|
+
this.source_component_id = source_component.source_component_id;
|
|
11296
11205
|
}
|
|
11297
11206
|
};
|
|
11298
11207
|
|
|
11299
|
-
// lib/utils/
|
|
11300
|
-
|
|
11208
|
+
// lib/utils/extractPcbPrimitivesFromCircuitJson.ts
|
|
11209
|
+
import { transformPCBElements } from "@tscircuit/circuit-json-util";
|
|
11210
|
+
import { compose as compose5, inverse, rotate as rotate2, translate as translate4 } from "transformation-matrix";
|
|
11211
|
+
var extractPcbPrimitivesFromCircuitJson = ({
|
|
11212
|
+
pcbComponent,
|
|
11301
11213
|
db,
|
|
11302
|
-
|
|
11303
|
-
simpleRouteJson,
|
|
11304
|
-
subcircuit_id
|
|
11214
|
+
componentName
|
|
11305
11215
|
}) => {
|
|
11306
|
-
|
|
11307
|
-
const
|
|
11308
|
-
|
|
11309
|
-
|
|
11310
|
-
|
|
11311
|
-
|
|
11312
|
-
|
|
11313
|
-
|
|
11314
|
-
|
|
11315
|
-
|
|
11316
|
-
|
|
11317
|
-
|
|
11318
|
-
|
|
11319
|
-
|
|
11320
|
-
|
|
11321
|
-
|
|
11322
|
-
|
|
11323
|
-
|
|
11324
|
-
|
|
11325
|
-
|
|
11326
|
-
|
|
11327
|
-
|
|
11216
|
+
const componentCenter = pcbComponent.center || { x: 0, y: 0 };
|
|
11217
|
+
const componentRotation = pcbComponent.rotation || 0;
|
|
11218
|
+
const absoluteToComponentRelativeTransform = inverse(
|
|
11219
|
+
compose5(
|
|
11220
|
+
translate4(componentCenter.x, componentCenter.y),
|
|
11221
|
+
rotate2(componentRotation * Math.PI / 180)
|
|
11222
|
+
)
|
|
11223
|
+
);
|
|
11224
|
+
const relativeElements = db.toArray().filter(
|
|
11225
|
+
(elm) => "pcb_component_id" in elm && elm.pcb_component_id === pcbComponent.pcb_component_id
|
|
11226
|
+
);
|
|
11227
|
+
const clonedRelativeElements = structuredClone(relativeElements);
|
|
11228
|
+
transformPCBElements(
|
|
11229
|
+
clonedRelativeElements,
|
|
11230
|
+
absoluteToComponentRelativeTransform
|
|
11231
|
+
);
|
|
11232
|
+
const components = createComponentsFromCircuitJson(
|
|
11233
|
+
{
|
|
11234
|
+
componentName,
|
|
11235
|
+
componentRotation: "0deg"
|
|
11236
|
+
},
|
|
11237
|
+
clonedRelativeElements
|
|
11238
|
+
);
|
|
11239
|
+
return components;
|
|
11240
|
+
};
|
|
11241
|
+
|
|
11242
|
+
// lib/components/primitive-components/Group/Subcircuit/inflators/inflateFootprintComponent.ts
|
|
11243
|
+
var inflateFootprintComponent = (pcbElm, inflatorContext) => {
|
|
11244
|
+
const { injectionDb, normalComponent } = inflatorContext;
|
|
11245
|
+
if (!normalComponent) return null;
|
|
11246
|
+
const primitives = extractPcbPrimitivesFromCircuitJson({
|
|
11247
|
+
pcbComponent: pcbElm,
|
|
11248
|
+
db: injectionDb,
|
|
11249
|
+
componentName: normalComponent.name
|
|
11250
|
+
});
|
|
11251
|
+
if (primitives.length === 0) return null;
|
|
11252
|
+
const footprint = new Footprint({});
|
|
11253
|
+
footprint.addAll(primitives);
|
|
11254
|
+
return footprint;
|
|
11255
|
+
};
|
|
11256
|
+
|
|
11257
|
+
// lib/components/primitive-components/Group/Subcircuit/inflators/inflateSourceCapacitor.ts
|
|
11258
|
+
function inflateSourceCapacitor(sourceElm, inflatorContext) {
|
|
11259
|
+
const { injectionDb, subcircuit, groupsMap } = inflatorContext;
|
|
11260
|
+
const pcbElm = injectionDb.pcb_component.getWhere({
|
|
11261
|
+
source_component_id: sourceElm.source_component_id
|
|
11262
|
+
});
|
|
11263
|
+
const cadElm = injectionDb.cad_component.getWhere({
|
|
11264
|
+
source_component_id: sourceElm.source_component_id
|
|
11265
|
+
});
|
|
11266
|
+
const capacitor = new Capacitor({
|
|
11267
|
+
name: sourceElm.name,
|
|
11268
|
+
capacitance: sourceElm.capacitance,
|
|
11269
|
+
layer: pcbElm?.layer,
|
|
11270
|
+
pcbX: pcbElm?.center?.x,
|
|
11271
|
+
pcbY: pcbElm?.center?.y,
|
|
11272
|
+
pcbRotation: pcbElm?.rotation,
|
|
11273
|
+
doNotPlace: pcbElm?.do_not_place,
|
|
11274
|
+
obstructsWithinBounds: pcbElm?.obstructs_within_bounds
|
|
11275
|
+
});
|
|
11276
|
+
if (pcbElm) {
|
|
11277
|
+
const footprint = inflateFootprintComponent(pcbElm, {
|
|
11278
|
+
...inflatorContext,
|
|
11279
|
+
normalComponent: capacitor
|
|
11280
|
+
});
|
|
11281
|
+
if (footprint) {
|
|
11282
|
+
capacitor.add(footprint);
|
|
11328
11283
|
}
|
|
11329
11284
|
}
|
|
11330
|
-
|
|
11331
|
-
|
|
11332
|
-
|
|
11333
|
-
|
|
11334
|
-
|
|
11285
|
+
if (sourceElm.source_group_id && groupsMap?.has(sourceElm.source_group_id)) {
|
|
11286
|
+
const group = groupsMap.get(sourceElm.source_group_id);
|
|
11287
|
+
group.add(capacitor);
|
|
11288
|
+
} else {
|
|
11289
|
+
subcircuit.add(capacitor);
|
|
11335
11290
|
}
|
|
11336
|
-
|
|
11337
|
-
|
|
11338
|
-
|
|
11339
|
-
|
|
11340
|
-
|
|
11341
|
-
|
|
11342
|
-
|
|
11343
|
-
|
|
11291
|
+
}
|
|
11292
|
+
|
|
11293
|
+
// lib/components/normal-components/Chip.ts
|
|
11294
|
+
import { chipProps as chipProps2 } from "@tscircuit/props";
|
|
11295
|
+
import { pcb_component_invalid_layer_error as pcb_component_invalid_layer_error2 } from "circuit-json";
|
|
11296
|
+
var Chip = class extends NormalComponent3 {
|
|
11297
|
+
schematicBoxDimensions = null;
|
|
11298
|
+
constructor(props) {
|
|
11299
|
+
super(props);
|
|
11344
11300
|
}
|
|
11345
|
-
|
|
11346
|
-
|
|
11347
|
-
|
|
11348
|
-
|
|
11349
|
-
|
|
11350
|
-
|
|
11351
|
-
|
|
11352
|
-
|
|
11353
|
-
|
|
11301
|
+
get config() {
|
|
11302
|
+
return {
|
|
11303
|
+
componentName: "Chip",
|
|
11304
|
+
zodProps: chipProps2,
|
|
11305
|
+
shouldRenderAsSchematicBox: true
|
|
11306
|
+
};
|
|
11307
|
+
}
|
|
11308
|
+
initPorts(opts = {}) {
|
|
11309
|
+
super.initPorts(opts);
|
|
11310
|
+
const { _parsedProps: props } = this;
|
|
11311
|
+
if (props.externallyConnectedPins) {
|
|
11312
|
+
const requiredPorts = /* @__PURE__ */ new Set();
|
|
11313
|
+
for (const [pin1, pin2] of props.externallyConnectedPins) {
|
|
11314
|
+
requiredPorts.add(pin1);
|
|
11315
|
+
requiredPorts.add(pin2);
|
|
11316
|
+
}
|
|
11317
|
+
for (const pinIdentifier of requiredPorts) {
|
|
11318
|
+
const existingPort = this.children.find(
|
|
11319
|
+
(child) => child instanceof Port && child.isMatchingAnyOf([pinIdentifier])
|
|
11320
|
+
);
|
|
11321
|
+
if (!existingPort) {
|
|
11322
|
+
const pinMatch = pinIdentifier.match(/^pin(\d+)$/);
|
|
11323
|
+
if (pinMatch) {
|
|
11324
|
+
const pinNumber = parseInt(pinMatch[1]);
|
|
11325
|
+
this.add(
|
|
11326
|
+
new Port({
|
|
11327
|
+
pinNumber,
|
|
11328
|
+
aliases: [pinIdentifier]
|
|
11329
|
+
})
|
|
11330
|
+
);
|
|
11331
|
+
} else {
|
|
11332
|
+
this.add(
|
|
11333
|
+
new Port({
|
|
11334
|
+
name: pinIdentifier,
|
|
11335
|
+
aliases: [pinIdentifier]
|
|
11336
|
+
})
|
|
11337
|
+
);
|
|
11338
|
+
}
|
|
11354
11339
|
}
|
|
11355
11340
|
}
|
|
11356
11341
|
}
|
|
11357
|
-
if (sourcePortIds.size < 2) continue;
|
|
11358
|
-
const sourcePortIdArray = Array.from(sourcePortIds);
|
|
11359
|
-
const existingTraces = db.source_trace.list();
|
|
11360
|
-
const alreadyConnected = existingTraces.some((trace) => {
|
|
11361
|
-
const tracePortIds = new Set(trace.connected_source_port_ids);
|
|
11362
|
-
return sourcePortIdArray.every((id) => tracePortIds.has(id));
|
|
11363
|
-
});
|
|
11364
|
-
if (alreadyConnected) continue;
|
|
11365
|
-
db.source_trace.insert({
|
|
11366
|
-
connected_source_port_ids: sourcePortIdArray,
|
|
11367
|
-
connected_source_net_ids: [],
|
|
11368
|
-
subcircuit_id: subcircuit_id ?? void 0,
|
|
11369
|
-
display_name: `offboard_${rootConnectionName}`
|
|
11370
|
-
});
|
|
11371
11342
|
}
|
|
11372
|
-
|
|
11373
|
-
|
|
11374
|
-
|
|
11375
|
-
|
|
11376
|
-
|
|
11377
|
-
|
|
11343
|
+
doInitialSchematicComponentRender() {
|
|
11344
|
+
const { _parsedProps: props } = this;
|
|
11345
|
+
if (props?.noSchematicRepresentation === true) return;
|
|
11346
|
+
super.doInitialSchematicComponentRender();
|
|
11347
|
+
}
|
|
11348
|
+
doInitialSourceRender() {
|
|
11349
|
+
const { db } = this.root;
|
|
11350
|
+
const { _parsedProps: props } = this;
|
|
11351
|
+
const source_component = db.source_component.insert({
|
|
11352
|
+
ftype: "simple_chip",
|
|
11353
|
+
name: this.name,
|
|
11354
|
+
manufacturer_part_number: props.manufacturerPartNumber,
|
|
11355
|
+
supplier_part_numbers: props.supplierPartNumbers,
|
|
11356
|
+
display_name: props.displayName
|
|
11357
|
+
});
|
|
11358
|
+
this.source_component_id = source_component.source_component_id;
|
|
11359
|
+
}
|
|
11360
|
+
doInitialPcbComponentRender() {
|
|
11361
|
+
if (this.root?.pcbDisabled) return;
|
|
11362
|
+
const { db } = this.root;
|
|
11363
|
+
const { _parsedProps: props } = this;
|
|
11364
|
+
const { pcbX, pcbY } = this.getResolvedPcbPositionProp();
|
|
11365
|
+
const componentLayer = props.layer ?? "top";
|
|
11366
|
+
if (componentLayer !== "top" && componentLayer !== "bottom") {
|
|
11367
|
+
const subcircuit = this.getSubcircuit();
|
|
11368
|
+
const error = pcb_component_invalid_layer_error2.parse({
|
|
11369
|
+
type: "pcb_component_invalid_layer_error",
|
|
11370
|
+
message: `Component cannot be placed on layer '${componentLayer}'. Components can only be placed on 'top' or 'bottom' layers.`,
|
|
11371
|
+
source_component_id: this.source_component_id,
|
|
11372
|
+
layer: componentLayer,
|
|
11373
|
+
subcircuit_id: subcircuit.subcircuit_id ?? void 0
|
|
11374
|
+
});
|
|
11375
|
+
db.pcb_component_invalid_layer_error.insert(error);
|
|
11376
|
+
}
|
|
11377
|
+
const pcb_component = db.pcb_component.insert({
|
|
11378
|
+
center: { x: pcbX, y: pcbY },
|
|
11379
|
+
width: 2,
|
|
11380
|
+
// Default width, adjust as needed
|
|
11381
|
+
height: 3,
|
|
11382
|
+
// Default height, adjust as needed
|
|
11383
|
+
layer: componentLayer === "top" || componentLayer === "bottom" ? componentLayer : "top",
|
|
11384
|
+
rotation: props.pcbRotation ?? 0,
|
|
11385
|
+
source_component_id: this.source_component_id,
|
|
11386
|
+
subcircuit_id: this.getSubcircuit().subcircuit_id ?? void 0,
|
|
11387
|
+
do_not_place: props.doNotPlace ?? false,
|
|
11388
|
+
obstructs_within_bounds: props.obstructsWithinBounds ?? true,
|
|
11389
|
+
is_allowed_to_be_off_board: props.allowOffBoard ?? false,
|
|
11390
|
+
metadata: props.kicadFootprintMetadata ? { kicad_footprint: props.kicadFootprintMetadata } : void 0
|
|
11391
|
+
});
|
|
11392
|
+
this.pcb_component_id = pcb_component.pcb_component_id;
|
|
11393
|
+
}
|
|
11394
|
+
doInitialCreateTracesFromProps() {
|
|
11395
|
+
const { _parsedProps: props } = this;
|
|
11396
|
+
if (props.externallyConnectedPins) {
|
|
11397
|
+
for (const [pin1, pin2] of props.externallyConnectedPins) {
|
|
11398
|
+
this.add(
|
|
11399
|
+
new Trace3({
|
|
11400
|
+
from: `${this.getSubcircuitSelector()} > port.${pin1}`,
|
|
11401
|
+
to: `${this.getSubcircuitSelector()} > port.${pin2}`
|
|
11402
|
+
})
|
|
11403
|
+
);
|
|
11404
|
+
}
|
|
11405
|
+
}
|
|
11406
|
+
this._createTracesFromConnectionsProp();
|
|
11407
|
+
}
|
|
11408
|
+
doInitialSimulationRender() {
|
|
11409
|
+
const { db } = this.root;
|
|
11410
|
+
const { pinAttributes } = this.props;
|
|
11411
|
+
if (!pinAttributes) return;
|
|
11412
|
+
let powerPort = null;
|
|
11413
|
+
let groundPort = null;
|
|
11414
|
+
let voltage;
|
|
11415
|
+
const ports = this.selectAll("port");
|
|
11416
|
+
for (const port of ports) {
|
|
11417
|
+
for (const alias of port.getNameAndAliases()) {
|
|
11418
|
+
if (pinAttributes[alias]) {
|
|
11419
|
+
const attributes = pinAttributes[alias];
|
|
11420
|
+
if (attributes.providesPower) {
|
|
11421
|
+
powerPort = port;
|
|
11422
|
+
voltage = attributes.providesVoltage;
|
|
11423
|
+
}
|
|
11424
|
+
if (attributes.providesGround) {
|
|
11425
|
+
groundPort = port;
|
|
11426
|
+
}
|
|
11427
|
+
}
|
|
11428
|
+
}
|
|
11429
|
+
}
|
|
11430
|
+
if (!powerPort || !groundPort || voltage === void 0) {
|
|
11431
|
+
return;
|
|
11432
|
+
}
|
|
11433
|
+
const powerSourcePort = db.source_port.get(powerPort.source_port_id);
|
|
11434
|
+
if (!powerSourcePort?.subcircuit_connectivity_map_key) return;
|
|
11435
|
+
const groundSourcePort = db.source_port.get(groundPort.source_port_id);
|
|
11436
|
+
if (!groundSourcePort?.subcircuit_connectivity_map_key) return;
|
|
11437
|
+
const powerNet = db.source_net.getWhere({
|
|
11438
|
+
subcircuit_connectivity_map_key: powerSourcePort.subcircuit_connectivity_map_key
|
|
11439
|
+
});
|
|
11440
|
+
const groundNet = db.source_net.getWhere({
|
|
11441
|
+
subcircuit_connectivity_map_key: groundSourcePort.subcircuit_connectivity_map_key
|
|
11442
|
+
});
|
|
11443
|
+
if (!powerNet || !groundNet) {
|
|
11444
|
+
return;
|
|
11445
|
+
}
|
|
11446
|
+
;
|
|
11447
|
+
db.simulation_voltage_source.insert({
|
|
11448
|
+
type: "simulation_voltage_source",
|
|
11449
|
+
positive_source_port_id: powerPort.source_port_id,
|
|
11450
|
+
positive_source_net_id: powerNet.source_net_id,
|
|
11451
|
+
negative_source_port_id: groundPort.source_port_id,
|
|
11452
|
+
negative_source_net_id: groundNet.source_net_id,
|
|
11453
|
+
voltage
|
|
11454
|
+
});
|
|
11455
|
+
}
|
|
11456
|
+
};
|
|
11457
|
+
|
|
11458
|
+
// lib/components/primitive-components/Group/Subcircuit/inflators/inflateSourceChip.ts
|
|
11459
|
+
var mapInternallyConnectedSourcePortIdsToPinLabels = (sourcePortIds, inflatorContext) => {
|
|
11460
|
+
if (!sourcePortIds || sourcePortIds.length === 0) return void 0;
|
|
11461
|
+
const { injectionDb } = inflatorContext;
|
|
11462
|
+
const mapped = sourcePortIds.map(
|
|
11463
|
+
(group) => group.map((sourcePortId) => {
|
|
11464
|
+
const port = injectionDb.source_port.get(
|
|
11465
|
+
sourcePortId
|
|
11466
|
+
);
|
|
11467
|
+
if (!port) return null;
|
|
11468
|
+
if (port.pin_number !== void 0 && port.pin_number !== null) {
|
|
11469
|
+
return `pin${port.pin_number}`;
|
|
11470
|
+
}
|
|
11471
|
+
return port.name;
|
|
11472
|
+
}).filter((value) => value !== null)
|
|
11473
|
+
).filter((group) => group.length > 0);
|
|
11474
|
+
return mapped.length > 0 ? mapped : void 0;
|
|
11475
|
+
};
|
|
11476
|
+
var inflateSourceChip = (sourceElm, inflatorContext) => {
|
|
11477
|
+
const { injectionDb, subcircuit, groupsMap } = inflatorContext;
|
|
11478
|
+
const pcbElm = injectionDb.pcb_component.getWhere({
|
|
11479
|
+
source_component_id: sourceElm.source_component_id
|
|
11480
|
+
});
|
|
11481
|
+
const schematicElm = injectionDb.schematic_component.getWhere({
|
|
11482
|
+
source_component_id: sourceElm.source_component_id
|
|
11483
|
+
});
|
|
11484
|
+
const cadElm = injectionDb.cad_component.getWhere({
|
|
11485
|
+
source_component_id: sourceElm.source_component_id
|
|
11486
|
+
});
|
|
11487
|
+
const internallyConnectedPins = mapInternallyConnectedSourcePortIdsToPinLabels(
|
|
11488
|
+
sourceElm.internally_connected_source_port_ids,
|
|
11489
|
+
inflatorContext
|
|
11490
|
+
);
|
|
11491
|
+
const footprinterString = cadElm?.footprinter_string ?? null;
|
|
11492
|
+
const chip = new Chip({
|
|
11493
|
+
name: sourceElm.name,
|
|
11494
|
+
manufacturerPartNumber: sourceElm.manufacturer_part_number,
|
|
11495
|
+
supplierPartNumbers: sourceElm.supplier_part_numbers ?? void 0,
|
|
11496
|
+
pinLabels: schematicElm?.port_labels ?? void 0,
|
|
11497
|
+
schWidth: schematicElm?.size?.width,
|
|
11498
|
+
schHeight: schematicElm?.size?.height,
|
|
11499
|
+
schPinSpacing: schematicElm?.pin_spacing,
|
|
11500
|
+
schX: schematicElm?.center?.x,
|
|
11501
|
+
schY: schematicElm?.center?.y,
|
|
11502
|
+
layer: pcbElm?.layer,
|
|
11503
|
+
pcbX: pcbElm?.center?.x,
|
|
11504
|
+
pcbY: pcbElm?.center?.y,
|
|
11505
|
+
pcbRotation: pcbElm?.rotation,
|
|
11506
|
+
doNotPlace: pcbElm?.do_not_place,
|
|
11507
|
+
obstructsWithinBounds: pcbElm?.obstructs_within_bounds,
|
|
11508
|
+
internallyConnectedPins
|
|
11509
|
+
});
|
|
11510
|
+
if (footprinterString) {
|
|
11511
|
+
Object.assign(chip.props, { footprint: footprinterString });
|
|
11512
|
+
Object.assign(chip._parsedProps, { footprint: footprinterString });
|
|
11513
|
+
}
|
|
11514
|
+
if (pcbElm) {
|
|
11515
|
+
const footprint = inflateFootprintComponent(pcbElm, {
|
|
11516
|
+
...inflatorContext,
|
|
11517
|
+
normalComponent: chip
|
|
11518
|
+
});
|
|
11519
|
+
if (footprint) {
|
|
11520
|
+
chip.add(footprint);
|
|
11521
|
+
}
|
|
11522
|
+
}
|
|
11523
|
+
if (sourceElm.source_group_id && groupsMap?.has(sourceElm.source_group_id)) {
|
|
11524
|
+
const group = groupsMap.get(sourceElm.source_group_id);
|
|
11525
|
+
group.add(chip);
|
|
11526
|
+
} else {
|
|
11527
|
+
subcircuit.add(chip);
|
|
11528
|
+
}
|
|
11529
|
+
};
|
|
11530
|
+
|
|
11531
|
+
// lib/components/normal-components/Diode.ts
|
|
11532
|
+
import { diodeProps } from "@tscircuit/props";
|
|
11533
|
+
var Diode = class extends NormalComponent3 {
|
|
11534
|
+
get config() {
|
|
11535
|
+
const symbolMap = {
|
|
11536
|
+
schottky: "schottky_diode",
|
|
11537
|
+
avalanche: "avalanche_diode",
|
|
11538
|
+
zener: "zener_diode",
|
|
11539
|
+
photodiode: "photodiode"
|
|
11540
|
+
};
|
|
11541
|
+
const variantSymbol = this.props.schottky ? "schottky" : this.props.avalanche ? "avalanche" : this.props.zener ? "zener" : this.props.photo ? "photodiode" : null;
|
|
11542
|
+
return {
|
|
11543
|
+
schematicSymbolName: variantSymbol ? symbolMap[variantSymbol] : this.props.symbolName ?? "diode",
|
|
11544
|
+
componentName: "Diode",
|
|
11545
|
+
zodProps: diodeProps,
|
|
11546
|
+
sourceFtype: "simple_diode"
|
|
11547
|
+
};
|
|
11548
|
+
}
|
|
11549
|
+
initPorts() {
|
|
11550
|
+
super.initPorts({
|
|
11551
|
+
additionalAliases: {
|
|
11552
|
+
pin1: ["anode", "pos", "left"],
|
|
11553
|
+
pin2: ["cathode", "neg", "right"]
|
|
11554
|
+
}
|
|
11555
|
+
});
|
|
11556
|
+
}
|
|
11557
|
+
doInitialSourceRender() {
|
|
11558
|
+
const { db } = this.root;
|
|
11559
|
+
const { _parsedProps: props } = this;
|
|
11560
|
+
const source_component = db.source_component.insert({
|
|
11561
|
+
ftype: "simple_diode",
|
|
11562
|
+
name: this.name,
|
|
11563
|
+
manufacturer_part_number: props.manufacturerPartNumber ?? props.mfn,
|
|
11564
|
+
supplier_part_numbers: props.supplierPartNumbers,
|
|
11565
|
+
are_pins_interchangeable: false,
|
|
11566
|
+
display_name: props.displayName
|
|
11567
|
+
});
|
|
11568
|
+
this.source_component_id = source_component.source_component_id;
|
|
11569
|
+
}
|
|
11570
|
+
pos = this.portMap.pin1;
|
|
11571
|
+
anode = this.portMap.pin1;
|
|
11572
|
+
neg = this.portMap.pin2;
|
|
11573
|
+
cathode = this.portMap.pin2;
|
|
11574
|
+
};
|
|
11575
|
+
|
|
11576
|
+
// lib/components/primitive-components/Group/Subcircuit/inflators/inflateSourceDiode.ts
|
|
11577
|
+
function inflateSourceDiode(sourceElm, inflatorContext) {
|
|
11578
|
+
const { injectionDb, subcircuit, groupsMap } = inflatorContext;
|
|
11579
|
+
const pcbElm = injectionDb.pcb_component.getWhere({
|
|
11580
|
+
source_component_id: sourceElm.source_component_id
|
|
11581
|
+
});
|
|
11582
|
+
const cadElm = injectionDb.cad_component.getWhere({
|
|
11583
|
+
source_component_id: sourceElm.source_component_id
|
|
11584
|
+
});
|
|
11585
|
+
const diode = new Diode({
|
|
11586
|
+
name: sourceElm.name,
|
|
11587
|
+
layer: pcbElm?.layer,
|
|
11588
|
+
pcbX: pcbElm?.center?.x,
|
|
11589
|
+
pcbY: pcbElm?.center?.y,
|
|
11590
|
+
pcbRotation: pcbElm?.rotation,
|
|
11591
|
+
doNotPlace: pcbElm?.do_not_place,
|
|
11592
|
+
obstructsWithinBounds: pcbElm?.obstructs_within_bounds
|
|
11593
|
+
});
|
|
11594
|
+
if (pcbElm) {
|
|
11595
|
+
const footprint = inflateFootprintComponent(pcbElm, {
|
|
11596
|
+
...inflatorContext,
|
|
11597
|
+
normalComponent: diode
|
|
11598
|
+
});
|
|
11599
|
+
if (footprint) {
|
|
11600
|
+
diode.add(footprint);
|
|
11601
|
+
}
|
|
11602
|
+
}
|
|
11603
|
+
if (sourceElm.source_group_id && groupsMap?.has(sourceElm.source_group_id)) {
|
|
11604
|
+
const group = groupsMap.get(sourceElm.source_group_id);
|
|
11605
|
+
group.add(diode);
|
|
11606
|
+
} else {
|
|
11607
|
+
subcircuit.add(diode);
|
|
11608
|
+
}
|
|
11609
|
+
}
|
|
11610
|
+
|
|
11611
|
+
// lib/components/primitive-components/Group/Group.ts
|
|
11612
|
+
import { convertSrjToGraphicsObject } from "@tscircuit/capacity-autorouter";
|
|
11613
|
+
import { getBoundsFromPoints as getBoundsFromPoints3 } from "@tscircuit/math-utils";
|
|
11614
|
+
import {
|
|
11615
|
+
groupProps
|
|
11616
|
+
} from "@tscircuit/props";
|
|
11617
|
+
import {
|
|
11618
|
+
distance as distance8
|
|
11619
|
+
} from "circuit-json";
|
|
11620
|
+
import Debug13 from "debug";
|
|
11621
|
+
|
|
11622
|
+
// lib/utils/autorouting/CapacityMeshAutorouter.ts
|
|
11623
|
+
import "@tscircuit/capacity-autorouter";
|
|
11624
|
+
|
|
11625
|
+
// lib/solvers.ts
|
|
11626
|
+
import { PackSolver2 } from "calculate-packing";
|
|
11627
|
+
import {
|
|
11628
|
+
AutoroutingPipelineSolver,
|
|
11629
|
+
AssignableAutoroutingPipeline2,
|
|
11630
|
+
AutoroutingPipeline1_OriginalUnravel,
|
|
11631
|
+
AssignableAutoroutingPipeline3
|
|
11632
|
+
} from "@tscircuit/capacity-autorouter";
|
|
11633
|
+
import { CopperPourPipelineSolver } from "@tscircuit/copper-pour-solver";
|
|
11634
|
+
var SOLVERS = {
|
|
11635
|
+
PackSolver2,
|
|
11636
|
+
AutoroutingPipelineSolver,
|
|
11637
|
+
AssignableAutoroutingPipeline2,
|
|
11638
|
+
AssignableAutoroutingPipeline3,
|
|
11639
|
+
AutoroutingPipeline1_OriginalUnravel,
|
|
11640
|
+
CopperPourPipelineSolver
|
|
11641
|
+
};
|
|
11642
|
+
|
|
11643
|
+
// lib/utils/autorouting/CapacityMeshAutorouter.ts
|
|
11644
|
+
var TscircuitAutorouter = class {
|
|
11645
|
+
input;
|
|
11646
|
+
isRouting = false;
|
|
11647
|
+
solver;
|
|
11648
|
+
eventHandlers = {
|
|
11649
|
+
complete: [],
|
|
11650
|
+
error: [],
|
|
11651
|
+
progress: []
|
|
11652
|
+
};
|
|
11653
|
+
cycleCount = 0;
|
|
11654
|
+
stepDelay;
|
|
11655
|
+
timeoutId;
|
|
11656
|
+
constructor(input, options = {}) {
|
|
11657
|
+
this.input = input;
|
|
11658
|
+
const {
|
|
11659
|
+
capacityDepth,
|
|
11660
|
+
targetMinCapacity,
|
|
11661
|
+
stepDelay = 0,
|
|
11662
|
+
useAssignableSolver = false,
|
|
11663
|
+
useAutoJumperSolver = false,
|
|
11664
|
+
autorouterVersion: autorouterVersion2,
|
|
11665
|
+
effort,
|
|
11666
|
+
onSolverStarted
|
|
11667
|
+
} = options;
|
|
11668
|
+
let solverName;
|
|
11669
|
+
if (autorouterVersion2 === "v1") {
|
|
11670
|
+
solverName = "AutoroutingPipeline1_OriginalUnravel";
|
|
11671
|
+
} else if (useAutoJumperSolver) {
|
|
11672
|
+
solverName = "AssignableAutoroutingPipeline3";
|
|
11673
|
+
} else if (useAssignableSolver) {
|
|
11674
|
+
solverName = "AssignableAutoroutingPipeline2";
|
|
11675
|
+
} else {
|
|
11676
|
+
solverName = "AutoroutingPipelineSolver";
|
|
11677
|
+
}
|
|
11678
|
+
const SolverClass = SOLVERS[solverName];
|
|
11679
|
+
this.solver = new SolverClass(input, {
|
|
11680
|
+
capacityDepth,
|
|
11681
|
+
targetMinCapacity,
|
|
11682
|
+
cacheProvider: null,
|
|
11683
|
+
effort
|
|
11684
|
+
});
|
|
11685
|
+
onSolverStarted?.({
|
|
11686
|
+
solverName,
|
|
11687
|
+
solverParams: {
|
|
11688
|
+
input,
|
|
11689
|
+
options: {
|
|
11690
|
+
capacityDepth,
|
|
11691
|
+
targetMinCapacity,
|
|
11692
|
+
cacheProvider: null,
|
|
11693
|
+
effort
|
|
11694
|
+
}
|
|
11695
|
+
}
|
|
11696
|
+
});
|
|
11697
|
+
this.stepDelay = stepDelay;
|
|
11698
|
+
}
|
|
11699
|
+
/**
|
|
11700
|
+
* Start the autorouting process asynchronously
|
|
11701
|
+
* This will emit progress events during routing and a complete event when done
|
|
11702
|
+
*/
|
|
11703
|
+
start() {
|
|
11704
|
+
if (this.isRouting) return;
|
|
11705
|
+
this.isRouting = true;
|
|
11706
|
+
this.cycleCount = 0;
|
|
11707
|
+
this.runCycleAndQueueNextCycle();
|
|
11708
|
+
}
|
|
11709
|
+
/**
|
|
11710
|
+
* Execute the next routing step and schedule the following one if needed
|
|
11711
|
+
*/
|
|
11712
|
+
runCycleAndQueueNextCycle() {
|
|
11713
|
+
if (!this.isRouting) return;
|
|
11714
|
+
try {
|
|
11715
|
+
if (this.solver.solved || this.solver.failed) {
|
|
11716
|
+
if (this.solver.failed) {
|
|
11717
|
+
this.emitEvent({
|
|
11718
|
+
type: "error",
|
|
11719
|
+
error: new AutorouterError(this.solver.error || "Routing failed")
|
|
11720
|
+
});
|
|
11721
|
+
} else {
|
|
11722
|
+
this.emitEvent({
|
|
11723
|
+
type: "complete",
|
|
11724
|
+
traces: this.solver.getOutputSimpleRouteJson().traces || []
|
|
11725
|
+
});
|
|
11726
|
+
}
|
|
11727
|
+
this.isRouting = false;
|
|
11728
|
+
return;
|
|
11729
|
+
}
|
|
11730
|
+
const startTime = Date.now();
|
|
11731
|
+
const startIterations = this.solver.iterations;
|
|
11732
|
+
while (Date.now() - startTime < 250 && !this.solver.failed && !this.solver.solved) {
|
|
11733
|
+
this.solver.step();
|
|
11734
|
+
}
|
|
11735
|
+
const iterationsPerSecond = (this.solver.iterations - startIterations) / (Date.now() - startTime) * 1e3;
|
|
11736
|
+
this.cycleCount++;
|
|
11737
|
+
const debugGraphics = this.solver?.preview() || void 0;
|
|
11738
|
+
const progress = this.solver.progress;
|
|
11739
|
+
this.emitEvent({
|
|
11740
|
+
type: "progress",
|
|
11741
|
+
steps: this.cycleCount,
|
|
11742
|
+
iterationsPerSecond,
|
|
11743
|
+
progress,
|
|
11744
|
+
phase: this.solver.getCurrentPhase(),
|
|
11745
|
+
debugGraphics
|
|
11746
|
+
});
|
|
11747
|
+
if (this.stepDelay > 0) {
|
|
11748
|
+
this.timeoutId = setTimeout(
|
|
11749
|
+
() => this.runCycleAndQueueNextCycle(),
|
|
11750
|
+
this.stepDelay
|
|
11751
|
+
);
|
|
11752
|
+
} else {
|
|
11753
|
+
this.timeoutId = setTimeout(
|
|
11754
|
+
() => this.runCycleAndQueueNextCycle(),
|
|
11755
|
+
0
|
|
11756
|
+
);
|
|
11757
|
+
}
|
|
11758
|
+
} catch (error) {
|
|
11759
|
+
this.emitEvent({
|
|
11760
|
+
type: "error",
|
|
11761
|
+
error: error instanceof Error ? new AutorouterError(error.message) : new AutorouterError(String(error))
|
|
11762
|
+
});
|
|
11763
|
+
this.isRouting = false;
|
|
11764
|
+
}
|
|
11765
|
+
}
|
|
11766
|
+
/**
|
|
11767
|
+
* Stop the routing process if it's in progress
|
|
11768
|
+
*/
|
|
11769
|
+
stop() {
|
|
11770
|
+
if (!this.isRouting) return;
|
|
11771
|
+
this.isRouting = false;
|
|
11772
|
+
if (this.timeoutId !== void 0) {
|
|
11773
|
+
clearTimeout(this.timeoutId);
|
|
11774
|
+
this.timeoutId = void 0;
|
|
11775
|
+
}
|
|
11776
|
+
}
|
|
11777
|
+
on(event, callback) {
|
|
11778
|
+
if (event === "complete") {
|
|
11779
|
+
this.eventHandlers.complete.push(
|
|
11780
|
+
callback
|
|
11781
|
+
);
|
|
11782
|
+
} else if (event === "error") {
|
|
11783
|
+
this.eventHandlers.error.push(
|
|
11784
|
+
callback
|
|
11785
|
+
);
|
|
11786
|
+
} else if (event === "progress") {
|
|
11787
|
+
this.eventHandlers.progress.push(
|
|
11788
|
+
callback
|
|
11789
|
+
);
|
|
11790
|
+
}
|
|
11791
|
+
}
|
|
11792
|
+
/**
|
|
11793
|
+
* Emit an event to all registered handlers
|
|
11794
|
+
*/
|
|
11795
|
+
emitEvent(event) {
|
|
11796
|
+
if (event.type === "complete") {
|
|
11797
|
+
for (const handler of this.eventHandlers.complete) {
|
|
11798
|
+
handler(event);
|
|
11799
|
+
}
|
|
11800
|
+
} else if (event.type === "error") {
|
|
11801
|
+
for (const handler of this.eventHandlers.error) {
|
|
11802
|
+
handler(event);
|
|
11803
|
+
}
|
|
11804
|
+
} else if (event.type === "progress") {
|
|
11805
|
+
for (const handler of this.eventHandlers.progress) {
|
|
11806
|
+
handler(event);
|
|
11807
|
+
}
|
|
11808
|
+
}
|
|
11809
|
+
}
|
|
11810
|
+
/**
|
|
11811
|
+
* Solve the routing problem synchronously
|
|
11812
|
+
* @returns Array of routed traces
|
|
11813
|
+
*/
|
|
11814
|
+
solveSync() {
|
|
11815
|
+
this.solver.solve();
|
|
11816
|
+
if (this.solver.failed) {
|
|
11817
|
+
throw new AutorouterError(this.solver.error || "Routing failed");
|
|
11818
|
+
}
|
|
11819
|
+
return this.solver.getOutputSimpleRouteJson().traces || [];
|
|
11820
|
+
}
|
|
11821
|
+
/**
|
|
11822
|
+
* Get the mapping of obstacle IDs to root connection names that were
|
|
11823
|
+
* connected via off-board paths (e.g., interconnects).
|
|
11824
|
+
* Only available when using AssignableAutoroutingPipeline2.
|
|
11825
|
+
*/
|
|
11826
|
+
getConnectedOffboardObstacles() {
|
|
11827
|
+
if ("getConnectedOffboardObstacles" in this.solver) {
|
|
11828
|
+
return this.solver.getConnectedOffboardObstacles();
|
|
11829
|
+
}
|
|
11830
|
+
return {};
|
|
11831
|
+
}
|
|
11832
|
+
};
|
|
11833
|
+
|
|
11834
|
+
// lib/utils/autorouting/createSourceTracesFromOffboardConnections.ts
|
|
11835
|
+
var createSourceTracesFromOffboardConnections = ({
|
|
11836
|
+
db,
|
|
11837
|
+
connectedOffboardObstacles,
|
|
11838
|
+
simpleRouteJson,
|
|
11839
|
+
subcircuit_id
|
|
11840
|
+
}) => {
|
|
11841
|
+
if (Object.keys(connectedOffboardObstacles).length === 0) return;
|
|
11842
|
+
const pcbElementIdToSourcePortId = /* @__PURE__ */ new Map();
|
|
11843
|
+
for (const pcbPort of db.pcb_port.list()) {
|
|
11844
|
+
if (pcbPort.source_port_id) {
|
|
11845
|
+
const smtpad = db.pcb_smtpad.getWhere({
|
|
11846
|
+
pcb_port_id: pcbPort.pcb_port_id
|
|
11847
|
+
});
|
|
11848
|
+
if (smtpad) {
|
|
11849
|
+
pcbElementIdToSourcePortId.set(
|
|
11850
|
+
smtpad.pcb_smtpad_id,
|
|
11851
|
+
pcbPort.source_port_id
|
|
11852
|
+
);
|
|
11853
|
+
}
|
|
11854
|
+
const platedHole = db.pcb_plated_hole.getWhere({
|
|
11855
|
+
pcb_port_id: pcbPort.pcb_port_id
|
|
11856
|
+
});
|
|
11857
|
+
if (platedHole) {
|
|
11858
|
+
pcbElementIdToSourcePortId.set(
|
|
11859
|
+
platedHole.pcb_plated_hole_id,
|
|
11860
|
+
pcbPort.source_port_id
|
|
11861
|
+
);
|
|
11862
|
+
}
|
|
11863
|
+
}
|
|
11864
|
+
}
|
|
11865
|
+
const obstacleById = /* @__PURE__ */ new Map();
|
|
11866
|
+
for (const obstacle of simpleRouteJson.obstacles) {
|
|
11867
|
+
if (obstacle.obstacleId) {
|
|
11868
|
+
obstacleById.set(obstacle.obstacleId, obstacle);
|
|
11869
|
+
}
|
|
11870
|
+
}
|
|
11871
|
+
const connectionGroups = /* @__PURE__ */ new Map();
|
|
11872
|
+
for (const [obstacleId, rootConnectionName] of Object.entries(
|
|
11873
|
+
connectedOffboardObstacles
|
|
11874
|
+
)) {
|
|
11875
|
+
if (!connectionGroups.has(rootConnectionName)) {
|
|
11876
|
+
connectionGroups.set(rootConnectionName, []);
|
|
11877
|
+
}
|
|
11878
|
+
connectionGroups.get(rootConnectionName).push(obstacleId);
|
|
11879
|
+
}
|
|
11880
|
+
for (const [rootConnectionName, obstacleIds] of connectionGroups) {
|
|
11881
|
+
const sourcePortIds = /* @__PURE__ */ new Set();
|
|
11882
|
+
for (const obstacleId of obstacleIds) {
|
|
11883
|
+
const obstacle = obstacleById.get(obstacleId);
|
|
11884
|
+
if (!obstacle) continue;
|
|
11885
|
+
for (const connectedId of obstacle.connectedTo) {
|
|
11886
|
+
const sourcePortId = pcbElementIdToSourcePortId.get(connectedId);
|
|
11887
|
+
if (sourcePortId) {
|
|
11888
|
+
sourcePortIds.add(sourcePortId);
|
|
11889
|
+
}
|
|
11890
|
+
}
|
|
11891
|
+
}
|
|
11892
|
+
if (sourcePortIds.size < 2) continue;
|
|
11893
|
+
const sourcePortIdArray = Array.from(sourcePortIds);
|
|
11894
|
+
const existingTraces = db.source_trace.list();
|
|
11895
|
+
const alreadyConnected = existingTraces.some((trace) => {
|
|
11896
|
+
const tracePortIds = new Set(trace.connected_source_port_ids);
|
|
11897
|
+
return sourcePortIdArray.every((id) => tracePortIds.has(id));
|
|
11898
|
+
});
|
|
11899
|
+
if (alreadyConnected) continue;
|
|
11900
|
+
db.source_trace.insert({
|
|
11901
|
+
connected_source_port_ids: sourcePortIdArray,
|
|
11902
|
+
connected_source_net_ids: [],
|
|
11903
|
+
subcircuit_id: subcircuit_id ?? void 0,
|
|
11904
|
+
display_name: `offboard_${rootConnectionName}`
|
|
11905
|
+
});
|
|
11906
|
+
}
|
|
11907
|
+
};
|
|
11908
|
+
|
|
11909
|
+
// lib/utils/autorouting/getPresetAutoroutingConfig.ts
|
|
11910
|
+
function getPresetAutoroutingConfig(autorouterConfig) {
|
|
11911
|
+
const defaults = {
|
|
11912
|
+
serverUrl: "https://registry-api.tscircuit.com",
|
|
11378
11913
|
serverMode: "job",
|
|
11379
11914
|
serverCacheEnabled: true
|
|
11380
11915
|
};
|
|
@@ -11567,7 +12102,7 @@ var applyEditEventsToManualEditsFile = ({
|
|
|
11567
12102
|
|
|
11568
12103
|
// lib/utils/edit-events/apply-edit-events-to-circuit-json.ts
|
|
11569
12104
|
import { transformPCBElement } from "@tscircuit/circuit-json-util";
|
|
11570
|
-
import { translate as
|
|
12105
|
+
import { translate as translate5 } from "transformation-matrix";
|
|
11571
12106
|
|
|
11572
12107
|
// lib/utils/edit-events/apply-trace-hint-edit-event.ts
|
|
11573
12108
|
import { su as su3 } from "@tscircuit/circuit-json-util";
|
|
@@ -11612,7 +12147,7 @@ var applyEditEvents = ({
|
|
|
11612
12147
|
);
|
|
11613
12148
|
const needsMovement = !component || component.center.x !== editEvent.new_center.x || component.center.y !== editEvent.new_center.y;
|
|
11614
12149
|
if (needsMovement && editEvent.original_center) {
|
|
11615
|
-
const mat =
|
|
12150
|
+
const mat = translate5(
|
|
11616
12151
|
editEvent.new_center.x - editEvent.original_center.x,
|
|
11617
12152
|
editEvent.new_center.y - editEvent.original_center.y
|
|
11618
12153
|
);
|
|
@@ -11642,27 +12177,6 @@ import { su as su4 } from "@tscircuit/circuit-json-util";
|
|
|
11642
12177
|
import {
|
|
11643
12178
|
getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson3
|
|
11644
12179
|
} from "circuit-json-to-connectivity-map";
|
|
11645
|
-
|
|
11646
|
-
// lib/utils/autorouting/getAncestorSubcircuitIds.ts
|
|
11647
|
-
var getDescendantSubcircuitIds = (db, root_subcircuit_id) => {
|
|
11648
|
-
const groups = db.source_group.list();
|
|
11649
|
-
const result = [];
|
|
11650
|
-
const findDescendants = (parentId) => {
|
|
11651
|
-
const children = groups.filter(
|
|
11652
|
-
(group) => group.parent_subcircuit_id === parentId
|
|
11653
|
-
);
|
|
11654
|
-
for (const child of children) {
|
|
11655
|
-
if (child.subcircuit_id) {
|
|
11656
|
-
result.push(child.subcircuit_id);
|
|
11657
|
-
findDescendants(child.subcircuit_id);
|
|
11658
|
-
}
|
|
11659
|
-
}
|
|
11660
|
-
};
|
|
11661
|
-
findDescendants(root_subcircuit_id);
|
|
11662
|
-
return result;
|
|
11663
|
-
};
|
|
11664
|
-
|
|
11665
|
-
// lib/utils/autorouting/getSimpleRouteJsonFromCircuitJson.ts
|
|
11666
12180
|
var getSimpleRouteJsonFromCircuitJson = ({
|
|
11667
12181
|
db,
|
|
11668
12182
|
circuitJson,
|
|
@@ -13175,9 +13689,9 @@ var applyComponentConstraintClusters = (group, packInput) => {
|
|
|
13175
13689
|
};
|
|
13176
13690
|
|
|
13177
13691
|
// lib/components/primitive-components/Group/Group_doInitialPcbLayoutPack/applyPackOutput.ts
|
|
13178
|
-
import { translate as
|
|
13692
|
+
import { translate as translate6, rotate as rotate3, compose as compose6 } from "transformation-matrix";
|
|
13179
13693
|
import {
|
|
13180
|
-
transformPCBElements
|
|
13694
|
+
transformPCBElements as transformPCBElements2
|
|
13181
13695
|
} from "@tscircuit/circuit-json-util";
|
|
13182
13696
|
import { normalizeDegrees as normalizeDegrees2 } from "@tscircuit/math-utils";
|
|
13183
13697
|
var updateCadRotation = ({
|
|
@@ -13230,16 +13744,16 @@ var applyPackOutput = (group, packOutput, clusterMap) => {
|
|
|
13230
13744
|
const member = db.pcb_component.get(memberId);
|
|
13231
13745
|
if (!member) continue;
|
|
13232
13746
|
const originalCenter2 = member.center;
|
|
13233
|
-
const transformMatrix2 =
|
|
13747
|
+
const transformMatrix2 = compose6(
|
|
13234
13748
|
group._computePcbGlobalTransformBeforeLayout(),
|
|
13235
|
-
|
|
13236
|
-
|
|
13237
|
-
|
|
13749
|
+
translate6(center.x + rotatedRel.x, center.y + rotatedRel.y),
|
|
13750
|
+
rotate3(angleRad),
|
|
13751
|
+
translate6(-originalCenter2.x, -originalCenter2.y)
|
|
13238
13752
|
);
|
|
13239
13753
|
const related = db.toArray().filter(
|
|
13240
13754
|
(elm) => "pcb_component_id" in elm && elm.pcb_component_id === memberId
|
|
13241
13755
|
);
|
|
13242
|
-
|
|
13756
|
+
transformPCBElements2(related, transformMatrix2);
|
|
13243
13757
|
updateCadRotation({
|
|
13244
13758
|
db,
|
|
13245
13759
|
pcbComponentId: memberId,
|
|
@@ -13264,16 +13778,16 @@ var applyPackOutput = (group, packOutput, clusterMap) => {
|
|
|
13264
13778
|
}
|
|
13265
13779
|
const originalCenter2 = pcbComponent.center;
|
|
13266
13780
|
const rotationDegrees2 = ccwRotationDegrees ?? ccwRotationOffset ?? 0;
|
|
13267
|
-
const transformMatrix2 =
|
|
13781
|
+
const transformMatrix2 = compose6(
|
|
13268
13782
|
group._computePcbGlobalTransformBeforeLayout(),
|
|
13269
|
-
|
|
13270
|
-
|
|
13271
|
-
|
|
13783
|
+
translate6(center.x, center.y),
|
|
13784
|
+
rotate3(rotationDegrees2 * Math.PI / 180),
|
|
13785
|
+
translate6(-originalCenter2.x, -originalCenter2.y)
|
|
13272
13786
|
);
|
|
13273
13787
|
const related = db.toArray().filter(
|
|
13274
13788
|
(elm) => "pcb_component_id" in elm && elm.pcb_component_id === componentId
|
|
13275
13789
|
);
|
|
13276
|
-
|
|
13790
|
+
transformPCBElements2(related, transformMatrix2);
|
|
13277
13791
|
updateCadRotation({
|
|
13278
13792
|
db,
|
|
13279
13793
|
pcbComponentId: componentId,
|
|
@@ -13286,11 +13800,11 @@ var applyPackOutput = (group, packOutput, clusterMap) => {
|
|
|
13286
13800
|
if (!pcbGroup) continue;
|
|
13287
13801
|
const originalCenter = pcbGroup.center;
|
|
13288
13802
|
const rotationDegrees = ccwRotationDegrees ?? ccwRotationOffset ?? 0;
|
|
13289
|
-
const transformMatrix =
|
|
13803
|
+
const transformMatrix = compose6(
|
|
13290
13804
|
group._computePcbGlobalTransformBeforeLayout(),
|
|
13291
|
-
|
|
13292
|
-
|
|
13293
|
-
|
|
13805
|
+
translate6(center.x, center.y),
|
|
13806
|
+
rotate3(rotationDegrees * Math.PI / 180),
|
|
13807
|
+
translate6(-originalCenter.x, -originalCenter.y)
|
|
13294
13808
|
);
|
|
13295
13809
|
const relatedElements = db.toArray().filter((elm) => {
|
|
13296
13810
|
if ("source_group_id" in elm && elm.source_group_id) {
|
|
@@ -13337,7 +13851,7 @@ var applyPackOutput = (group, packOutput, clusterMap) => {
|
|
|
13337
13851
|
});
|
|
13338
13852
|
}
|
|
13339
13853
|
}
|
|
13340
|
-
|
|
13854
|
+
transformPCBElements2(relatedElements, transformMatrix);
|
|
13341
13855
|
db.pcb_group.update(pcbGroup.pcb_group_id, { center });
|
|
13342
13856
|
}
|
|
13343
13857
|
};
|
|
@@ -16532,7 +17046,8 @@ var Group6 = class extends NormalComponent3 {
|
|
|
16532
17046
|
const debug11 = Debug13("tscircuit:core:doInitialPcbTraceRender");
|
|
16533
17047
|
if (!this.isSubcircuit) return;
|
|
16534
17048
|
if (this.root?.pcbDisabled) return;
|
|
16535
|
-
if (this.getInheritedProperty("routingDisabled"))
|
|
17049
|
+
if (this.root?.pcbRoutingDisabled || this.getInheritedProperty("routingDisabled"))
|
|
17050
|
+
return;
|
|
16536
17051
|
if (this._isInflatedFromCircuitJson) return;
|
|
16537
17052
|
if (this._shouldUseTraceByTraceRouting()) return;
|
|
16538
17053
|
if (!this._areChildSubcircuitsRouted()) {
|
|
@@ -16784,718 +17299,210 @@ var Group6 = class extends NormalComponent3 {
|
|
|
16784
17299
|
this._doInitialPcbLayoutGrid();
|
|
16785
17300
|
} else if (pcbLayoutMode === "pack") {
|
|
16786
17301
|
this._doInitialPcbLayoutPack();
|
|
16787
|
-
} else if (pcbLayoutMode === "flex") {
|
|
16788
|
-
this._doInitialPcbLayoutFlex();
|
|
16789
|
-
}
|
|
16790
|
-
}
|
|
16791
|
-
_doInitialPcbLayoutGrid() {
|
|
16792
|
-
Group_doInitialPcbLayoutGrid(this);
|
|
16793
|
-
}
|
|
16794
|
-
_doInitialPcbLayoutPack() {
|
|
16795
|
-
Group_doInitialPcbLayoutPack(this);
|
|
16796
|
-
}
|
|
16797
|
-
_doInitialPcbLayoutFlex() {
|
|
16798
|
-
Group_doInitialPcbLayoutFlex(this);
|
|
16799
|
-
}
|
|
16800
|
-
_insertSchematicBorder() {
|
|
16801
|
-
if (this.root?.schematicDisabled) return;
|
|
16802
|
-
const { db } = this.root;
|
|
16803
|
-
const props = this._parsedProps;
|
|
16804
|
-
if (!props.border) return;
|
|
16805
|
-
let width = typeof props.schWidth === "number" ? props.schWidth : void 0;
|
|
16806
|
-
let height = typeof props.schHeight === "number" ? props.schHeight : void 0;
|
|
16807
|
-
const paddingGeneral = typeof props.schPadding === "number" ? props.schPadding : 0;
|
|
16808
|
-
const paddingLeft = typeof props.schPaddingLeft === "number" ? props.schPaddingLeft : paddingGeneral;
|
|
16809
|
-
const paddingRight = typeof props.schPaddingRight === "number" ? props.schPaddingRight : paddingGeneral;
|
|
16810
|
-
const paddingTop = typeof props.schPaddingTop === "number" ? props.schPaddingTop : paddingGeneral;
|
|
16811
|
-
const paddingBottom = typeof props.schPaddingBottom === "number" ? props.schPaddingBottom : paddingGeneral;
|
|
16812
|
-
const schematicGroup = this.schematic_group_id ? db.schematic_group.get(this.schematic_group_id) : null;
|
|
16813
|
-
if (schematicGroup) {
|
|
16814
|
-
if (width === void 0 && typeof schematicGroup.width === "number") {
|
|
16815
|
-
width = schematicGroup.width;
|
|
16816
|
-
}
|
|
16817
|
-
if (height === void 0 && typeof schematicGroup.height === "number") {
|
|
16818
|
-
height = schematicGroup.height;
|
|
16819
|
-
}
|
|
16820
|
-
}
|
|
16821
|
-
if (width === void 0 || height === void 0) return;
|
|
16822
|
-
const center = schematicGroup?.center ?? this._getGlobalSchematicPositionBeforeLayout();
|
|
16823
|
-
const left = center.x - width / 2 - paddingLeft;
|
|
16824
|
-
const bottom = center.y - height / 2 - paddingBottom;
|
|
16825
|
-
const finalWidth = width + paddingLeft + paddingRight;
|
|
16826
|
-
const finalHeight = height + paddingTop + paddingBottom;
|
|
16827
|
-
db.schematic_box.insert({
|
|
16828
|
-
width: finalWidth,
|
|
16829
|
-
height: finalHeight,
|
|
16830
|
-
x: left,
|
|
16831
|
-
y: bottom,
|
|
16832
|
-
is_dashed: props.border?.dashed ?? false
|
|
16833
|
-
});
|
|
16834
|
-
}
|
|
16835
|
-
_determineSideFromPosition(port, component) {
|
|
16836
|
-
if (!port.center || !component.center) return "left";
|
|
16837
|
-
const dx = port.center.x - component.center.x;
|
|
16838
|
-
const dy = port.center.y - component.center.y;
|
|
16839
|
-
if (Math.abs(dx) > Math.abs(dy)) {
|
|
16840
|
-
return dx > 0 ? "right" : "left";
|
|
16841
|
-
}
|
|
16842
|
-
return dy > 0 ? "bottom" : "top";
|
|
16843
|
-
}
|
|
16844
|
-
_calculateSchematicBounds(boxes) {
|
|
16845
|
-
if (boxes.length === 0) {
|
|
16846
|
-
return { minX: 0, maxX: 0, minY: 0, maxY: 0 };
|
|
16847
|
-
}
|
|
16848
|
-
let minX = Infinity;
|
|
16849
|
-
let maxX = -Infinity;
|
|
16850
|
-
let minY = Infinity;
|
|
16851
|
-
let maxY = -Infinity;
|
|
16852
|
-
for (const box of boxes) {
|
|
16853
|
-
minX = Math.min(minX, box.centerX);
|
|
16854
|
-
maxX = Math.max(maxX, box.centerX);
|
|
16855
|
-
minY = Math.min(minY, box.centerY);
|
|
16856
|
-
maxY = Math.max(maxY, box.centerY);
|
|
16857
|
-
}
|
|
16858
|
-
const padding = 2;
|
|
16859
|
-
return {
|
|
16860
|
-
minX: minX - padding,
|
|
16861
|
-
maxX: maxX + padding,
|
|
16862
|
-
minY: minY - padding,
|
|
16863
|
-
maxY: maxY + padding
|
|
16864
|
-
};
|
|
16865
|
-
}
|
|
16866
|
-
_getAutorouterConfig() {
|
|
16867
|
-
const autorouter = this._parsedProps.autorouter || this.getInheritedProperty("autorouter");
|
|
16868
|
-
return getPresetAutoroutingConfig(autorouter);
|
|
16869
|
-
}
|
|
16870
|
-
_isLaserPrefabAutorouter(autorouterConfig = this._getAutorouterConfig()) {
|
|
16871
|
-
const autorouterProp = this.props.autorouter;
|
|
16872
|
-
const normalize = (value) => value?.replace(/-/g, "_") ?? value;
|
|
16873
|
-
if (autorouterConfig.preset === "laser_prefab") return true;
|
|
16874
|
-
if (typeof autorouterProp === "string") {
|
|
16875
|
-
return normalize(autorouterProp) === "laser_prefab";
|
|
16876
|
-
}
|
|
16877
|
-
if (typeof autorouterProp === "object" && autorouterProp) {
|
|
16878
|
-
return normalize(autorouterProp.preset) === "laser_prefab";
|
|
16879
|
-
}
|
|
16880
|
-
return false;
|
|
16881
|
-
}
|
|
16882
|
-
_isAutoJumperAutorouter(autorouterConfig = this._getAutorouterConfig()) {
|
|
16883
|
-
const autorouterProp = this.props.autorouter;
|
|
16884
|
-
const normalize = (value) => value?.replace(/-/g, "_") ?? value;
|
|
16885
|
-
if (autorouterConfig.preset === "auto_jumper") return true;
|
|
16886
|
-
if (typeof autorouterProp === "string") {
|
|
16887
|
-
return normalize(autorouterProp) === "auto_jumper";
|
|
16888
|
-
}
|
|
16889
|
-
if (typeof autorouterProp === "object" && autorouterProp) {
|
|
16890
|
-
return normalize(autorouterProp.preset) === "auto_jumper";
|
|
16891
|
-
}
|
|
16892
|
-
return false;
|
|
16893
|
-
}
|
|
16894
|
-
_getSubcircuitLayerCount() {
|
|
16895
|
-
const layers = this.getInheritedProperty("layers");
|
|
16896
|
-
return typeof layers === "number" ? layers : 2;
|
|
16897
|
-
}
|
|
16898
|
-
/**
|
|
16899
|
-
* Trace-by-trace autorouting is where each trace routes itself in a well-known
|
|
16900
|
-
* order. It's the most deterministic way to autoroute, because a new trace
|
|
16901
|
-
* is generally ordered last.
|
|
16902
|
-
*
|
|
16903
|
-
* This method will return false if using an external service for autorouting
|
|
16904
|
-
* or if using a "fullview" or "rip and replace" autorouting mode
|
|
16905
|
-
*/
|
|
16906
|
-
_shouldUseTraceByTraceRouting() {
|
|
16907
|
-
const autorouter = this._getAutorouterConfig();
|
|
16908
|
-
return autorouter.groupMode === "sequential-trace";
|
|
16909
|
-
}
|
|
16910
|
-
doInitialPcbDesignRuleChecks() {
|
|
16911
|
-
if (this.root?.pcbDisabled) return;
|
|
16912
|
-
if (this.getInheritedProperty("routingDisabled")) return;
|
|
16913
|
-
const { db } = this.root;
|
|
16914
|
-
if (this.isSubcircuit) {
|
|
16915
|
-
const subcircuitComponentsByName = /* @__PURE__ */ new Map();
|
|
16916
|
-
for (const child of this.children) {
|
|
16917
|
-
if (child.isSubcircuit) continue;
|
|
16918
|
-
if (child._parsedProps.name) {
|
|
16919
|
-
const components = subcircuitComponentsByName.get(child._parsedProps.name) || [];
|
|
16920
|
-
components.push(child);
|
|
16921
|
-
subcircuitComponentsByName.set(child._parsedProps.name, components);
|
|
16922
|
-
}
|
|
16923
|
-
}
|
|
16924
|
-
for (const [name, components] of subcircuitComponentsByName.entries()) {
|
|
16925
|
-
if (components.length > 1) {
|
|
16926
|
-
db.pcb_trace_error.insert({
|
|
16927
|
-
error_type: "pcb_trace_error",
|
|
16928
|
-
message: `Multiple components found with name "${name}" in subcircuit "${this.name || "unnamed"}". Component names must be unique within a subcircuit.`,
|
|
16929
|
-
source_trace_id: "",
|
|
16930
|
-
pcb_trace_id: "",
|
|
16931
|
-
pcb_component_ids: components.map((c) => c.pcb_component_id).filter(Boolean),
|
|
16932
|
-
pcb_port_ids: []
|
|
16933
|
-
});
|
|
16934
|
-
}
|
|
16935
|
-
}
|
|
16936
|
-
}
|
|
16937
|
-
}
|
|
16938
|
-
doInitialSchematicReplaceNetLabelsWithSymbols() {
|
|
16939
|
-
if (this.root?.schematicDisabled) return;
|
|
16940
|
-
if (!this.isSubcircuit) return;
|
|
16941
|
-
const { db } = this.root;
|
|
16942
|
-
const subtree = db;
|
|
16943
|
-
for (const nl of subtree.schematic_net_label.list()) {
|
|
16944
|
-
const net = subtree.source_net.get(nl.source_net_id);
|
|
16945
|
-
const text = nl.text || net?.name || "";
|
|
16946
|
-
if (nl.anchor_side === "top" && /^gnd/i.test(text)) {
|
|
16947
|
-
subtree.schematic_net_label.update(nl.schematic_net_label_id, {
|
|
16948
|
-
symbol_name: "rail_down"
|
|
16949
|
-
});
|
|
16950
|
-
continue;
|
|
16951
|
-
}
|
|
16952
|
-
if (nl.anchor_side === "bottom" && /^v/i.test(text)) {
|
|
16953
|
-
subtree.schematic_net_label.update(nl.schematic_net_label_id, {
|
|
16954
|
-
symbol_name: "rail_up"
|
|
16955
|
-
});
|
|
16956
|
-
}
|
|
16957
|
-
}
|
|
16958
|
-
}
|
|
16959
|
-
doInitialSimulationSpiceEngineRender() {
|
|
16960
|
-
Group_doInitialSimulationSpiceEngineRender(this);
|
|
16961
|
-
}
|
|
16962
|
-
/**
|
|
16963
|
-
* Override anchor alignment to handle group-specific logic
|
|
16964
|
-
*/
|
|
16965
|
-
doInitialPcbComponentAnchorAlignment() {
|
|
16966
|
-
Group_doInitialPcbComponentAnchorAlignment(this);
|
|
16967
|
-
}
|
|
16968
|
-
updatePcbComponentAnchorAlignment() {
|
|
16969
|
-
this.doInitialPcbComponentAnchorAlignment();
|
|
16970
|
-
}
|
|
16971
|
-
doInitialPcbCalcPlacementResolution() {
|
|
16972
|
-
Group_doInitialPcbCalcPlacementResolution(this);
|
|
16973
|
-
}
|
|
16974
|
-
updatePcbCalcPlacementResolution() {
|
|
16975
|
-
this.doInitialPcbCalcPlacementResolution();
|
|
16976
|
-
}
|
|
16977
|
-
/**
|
|
16978
|
-
* Get the minimum flex container size for this group on PCB
|
|
16979
|
-
*/
|
|
16980
|
-
_getMinimumFlexContainerSize() {
|
|
16981
|
-
return super._getMinimumFlexContainerSize();
|
|
16982
|
-
}
|
|
16983
|
-
/**
|
|
16984
|
-
* Reposition this group on the PCB to the specified coordinates
|
|
16985
|
-
*/
|
|
16986
|
-
_repositionOnPcb(position) {
|
|
16987
|
-
return super._repositionOnPcb(position);
|
|
16988
|
-
}
|
|
16989
|
-
};
|
|
16990
|
-
|
|
16991
|
-
// lib/utils/circuit-json/inflate-circuit-json.ts
|
|
16992
|
-
import { cju } from "@tscircuit/circuit-json-util";
|
|
16993
|
-
|
|
16994
|
-
// lib/components/primitive-components/Group/Subcircuit/inflators/inflatePcbBoard.ts
|
|
16995
|
-
function inflatePcbBoard(pcbBoard, inflatorContext) {
|
|
16996
|
-
const { subcircuit } = inflatorContext;
|
|
16997
|
-
if (subcircuit.lowercaseComponentName === "board" || subcircuit.lowercaseComponentName === "mountedboard") {
|
|
16998
|
-
return;
|
|
16999
|
-
}
|
|
17000
|
-
if (subcircuit.parent?.lowercaseComponentName === "board") {
|
|
17001
|
-
return;
|
|
17002
|
-
}
|
|
17003
|
-
const boardProps2 = {
|
|
17004
|
-
name: "inflated_board"
|
|
17005
|
-
};
|
|
17006
|
-
if (pcbBoard.width) boardProps2.width = pcbBoard.width;
|
|
17007
|
-
if (pcbBoard.height) boardProps2.height = pcbBoard.height;
|
|
17008
|
-
if (pcbBoard.center) {
|
|
17009
|
-
boardProps2.pcbX = pcbBoard.center.x;
|
|
17010
|
-
boardProps2.pcbY = pcbBoard.center.y;
|
|
17011
|
-
}
|
|
17012
|
-
if (pcbBoard.outline) boardProps2.outline = pcbBoard.outline;
|
|
17013
|
-
if (pcbBoard.thickness) boardProps2.thickness = pcbBoard.thickness;
|
|
17014
|
-
if (pcbBoard.material) boardProps2.material = pcbBoard.material;
|
|
17015
|
-
const board = new Board(boardProps2);
|
|
17016
|
-
board.pcb_board_id = pcbBoard.pcb_board_id;
|
|
17017
|
-
subcircuit.add(board);
|
|
17018
|
-
return board;
|
|
17019
|
-
}
|
|
17020
|
-
|
|
17021
|
-
// lib/components/normal-components/Capacitor.ts
|
|
17022
|
-
import { capacitorProps } from "@tscircuit/props";
|
|
17023
|
-
import { formatSiUnit } from "format-si-unit";
|
|
17024
|
-
var Capacitor = class extends NormalComponent3 {
|
|
17025
|
-
_adjustSilkscreenTextAutomatically = true;
|
|
17026
|
-
get config() {
|
|
17027
|
-
return {
|
|
17028
|
-
componentName: "Capacitor",
|
|
17029
|
-
schematicSymbolName: this.props.polarized ? "capacitor_polarized" : this.props.symbolName ?? "capacitor",
|
|
17030
|
-
zodProps: capacitorProps,
|
|
17031
|
-
sourceFtype: FTYPE.simple_capacitor
|
|
17032
|
-
};
|
|
17033
|
-
}
|
|
17034
|
-
initPorts() {
|
|
17035
|
-
if (typeof this.props.footprint === "string") {
|
|
17036
|
-
super.initPorts({
|
|
17037
|
-
additionalAliases: {
|
|
17038
|
-
pin1: ["anode", "pos"],
|
|
17039
|
-
pin2: ["cathode", "neg"]
|
|
17040
|
-
}
|
|
17041
|
-
});
|
|
17042
|
-
} else {
|
|
17043
|
-
super.initPorts();
|
|
17302
|
+
} else if (pcbLayoutMode === "flex") {
|
|
17303
|
+
this._doInitialPcbLayoutFlex();
|
|
17044
17304
|
}
|
|
17045
17305
|
}
|
|
17046
|
-
|
|
17047
|
-
|
|
17048
|
-
const capacitanceDisplay = typeof inputCapacitance === "string" ? inputCapacitance : `${formatSiUnit(this._parsedProps.capacitance)}F`;
|
|
17049
|
-
if (this._parsedProps.schShowRatings && this._parsedProps.maxVoltageRating) {
|
|
17050
|
-
return `${capacitanceDisplay}/${formatSiUnit(this._parsedProps.maxVoltageRating)}V`;
|
|
17051
|
-
}
|
|
17052
|
-
return capacitanceDisplay;
|
|
17306
|
+
_doInitialPcbLayoutGrid() {
|
|
17307
|
+
Group_doInitialPcbLayoutGrid(this);
|
|
17053
17308
|
}
|
|
17054
|
-
|
|
17055
|
-
this
|
|
17056
|
-
this.props.decouplingFor,
|
|
17057
|
-
this.props.decouplingTo,
|
|
17058
|
-
...this._getNetsFromConnectionsProp()
|
|
17059
|
-
]);
|
|
17309
|
+
_doInitialPcbLayoutPack() {
|
|
17310
|
+
Group_doInitialPcbLayoutPack(this);
|
|
17060
17311
|
}
|
|
17061
|
-
|
|
17062
|
-
|
|
17063
|
-
this.add(
|
|
17064
|
-
new Trace3({
|
|
17065
|
-
from: `${this.getSubcircuitSelector()} > port.1`,
|
|
17066
|
-
to: this.props.decouplingFor
|
|
17067
|
-
})
|
|
17068
|
-
);
|
|
17069
|
-
this.add(
|
|
17070
|
-
new Trace3({
|
|
17071
|
-
from: `${this.getSubcircuitSelector()} > port.2`,
|
|
17072
|
-
to: this.props.decouplingTo
|
|
17073
|
-
})
|
|
17074
|
-
);
|
|
17075
|
-
}
|
|
17076
|
-
this._createTracesFromConnectionsProp();
|
|
17312
|
+
_doInitialPcbLayoutFlex() {
|
|
17313
|
+
Group_doInitialPcbLayoutFlex(this);
|
|
17077
17314
|
}
|
|
17078
|
-
|
|
17315
|
+
_insertSchematicBorder() {
|
|
17316
|
+
if (this.root?.schematicDisabled) return;
|
|
17079
17317
|
const { db } = this.root;
|
|
17080
|
-
const
|
|
17081
|
-
|
|
17082
|
-
|
|
17083
|
-
|
|
17084
|
-
|
|
17085
|
-
|
|
17086
|
-
|
|
17087
|
-
|
|
17088
|
-
|
|
17089
|
-
|
|
17090
|
-
|
|
17091
|
-
|
|
17318
|
+
const props = this._parsedProps;
|
|
17319
|
+
if (!props.border) return;
|
|
17320
|
+
let width = typeof props.schWidth === "number" ? props.schWidth : void 0;
|
|
17321
|
+
let height = typeof props.schHeight === "number" ? props.schHeight : void 0;
|
|
17322
|
+
const paddingGeneral = typeof props.schPadding === "number" ? props.schPadding : 0;
|
|
17323
|
+
const paddingLeft = typeof props.schPaddingLeft === "number" ? props.schPaddingLeft : paddingGeneral;
|
|
17324
|
+
const paddingRight = typeof props.schPaddingRight === "number" ? props.schPaddingRight : paddingGeneral;
|
|
17325
|
+
const paddingTop = typeof props.schPaddingTop === "number" ? props.schPaddingTop : paddingGeneral;
|
|
17326
|
+
const paddingBottom = typeof props.schPaddingBottom === "number" ? props.schPaddingBottom : paddingGeneral;
|
|
17327
|
+
const schematicGroup = this.schematic_group_id ? db.schematic_group.get(this.schematic_group_id) : null;
|
|
17328
|
+
if (schematicGroup) {
|
|
17329
|
+
if (width === void 0 && typeof schematicGroup.width === "number") {
|
|
17330
|
+
width = schematicGroup.width;
|
|
17331
|
+
}
|
|
17332
|
+
if (height === void 0 && typeof schematicGroup.height === "number") {
|
|
17333
|
+
height = schematicGroup.height;
|
|
17334
|
+
}
|
|
17335
|
+
}
|
|
17336
|
+
if (width === void 0 || height === void 0) return;
|
|
17337
|
+
const center = schematicGroup?.center ?? this._getGlobalSchematicPositionBeforeLayout();
|
|
17338
|
+
const left = center.x - width / 2 - paddingLeft;
|
|
17339
|
+
const bottom = center.y - height / 2 - paddingBottom;
|
|
17340
|
+
const finalWidth = width + paddingLeft + paddingRight;
|
|
17341
|
+
const finalHeight = height + paddingTop + paddingBottom;
|
|
17342
|
+
db.schematic_box.insert({
|
|
17343
|
+
width: finalWidth,
|
|
17344
|
+
height: finalHeight,
|
|
17345
|
+
x: left,
|
|
17346
|
+
y: bottom,
|
|
17347
|
+
is_dashed: props.border?.dashed ?? false
|
|
17092
17348
|
});
|
|
17093
|
-
this.source_component_id = source_component.source_component_id;
|
|
17094
17349
|
}
|
|
17095
|
-
|
|
17096
|
-
|
|
17097
|
-
|
|
17098
|
-
|
|
17099
|
-
|
|
17100
|
-
|
|
17101
|
-
pcbComponent,
|
|
17102
|
-
db,
|
|
17103
|
-
componentName
|
|
17104
|
-
}) => {
|
|
17105
|
-
const componentCenter = pcbComponent.center || { x: 0, y: 0 };
|
|
17106
|
-
const componentRotation = pcbComponent.rotation || 0;
|
|
17107
|
-
const absoluteToComponentRelativeTransform = inverse(
|
|
17108
|
-
compose6(
|
|
17109
|
-
translate6(componentCenter.x, componentCenter.y),
|
|
17110
|
-
rotate3(componentRotation * Math.PI / 180)
|
|
17111
|
-
)
|
|
17112
|
-
);
|
|
17113
|
-
const relativeElements = db.toArray().filter(
|
|
17114
|
-
(elm) => "pcb_component_id" in elm && elm.pcb_component_id === pcbComponent.pcb_component_id
|
|
17115
|
-
);
|
|
17116
|
-
const clonedRelativeElements = structuredClone(relativeElements);
|
|
17117
|
-
transformPCBElements2(
|
|
17118
|
-
clonedRelativeElements,
|
|
17119
|
-
absoluteToComponentRelativeTransform
|
|
17120
|
-
);
|
|
17121
|
-
const components = createComponentsFromCircuitJson(
|
|
17122
|
-
{
|
|
17123
|
-
componentName,
|
|
17124
|
-
componentRotation: "0deg"
|
|
17125
|
-
},
|
|
17126
|
-
clonedRelativeElements
|
|
17127
|
-
);
|
|
17128
|
-
return components;
|
|
17129
|
-
};
|
|
17130
|
-
|
|
17131
|
-
// lib/components/primitive-components/Group/Subcircuit/inflators/inflateFootprintComponent.ts
|
|
17132
|
-
var inflateFootprintComponent = (pcbElm, inflatorContext) => {
|
|
17133
|
-
const { injectionDb, normalComponent } = inflatorContext;
|
|
17134
|
-
if (!normalComponent) return null;
|
|
17135
|
-
const primitives = extractPcbPrimitivesFromCircuitJson({
|
|
17136
|
-
pcbComponent: pcbElm,
|
|
17137
|
-
db: injectionDb,
|
|
17138
|
-
componentName: normalComponent.name
|
|
17139
|
-
});
|
|
17140
|
-
if (primitives.length === 0) return null;
|
|
17141
|
-
const footprint = new Footprint({});
|
|
17142
|
-
footprint.addAll(primitives);
|
|
17143
|
-
return footprint;
|
|
17144
|
-
};
|
|
17145
|
-
|
|
17146
|
-
// lib/components/primitive-components/Group/Subcircuit/inflators/inflateSourceCapacitor.ts
|
|
17147
|
-
function inflateSourceCapacitor(sourceElm, inflatorContext) {
|
|
17148
|
-
const { injectionDb, subcircuit, groupsMap } = inflatorContext;
|
|
17149
|
-
const pcbElm = injectionDb.pcb_component.getWhere({
|
|
17150
|
-
source_component_id: sourceElm.source_component_id
|
|
17151
|
-
});
|
|
17152
|
-
const cadElm = injectionDb.cad_component.getWhere({
|
|
17153
|
-
source_component_id: sourceElm.source_component_id
|
|
17154
|
-
});
|
|
17155
|
-
const capacitor = new Capacitor({
|
|
17156
|
-
name: sourceElm.name,
|
|
17157
|
-
capacitance: sourceElm.capacitance,
|
|
17158
|
-
layer: pcbElm?.layer,
|
|
17159
|
-
pcbX: pcbElm?.center?.x,
|
|
17160
|
-
pcbY: pcbElm?.center?.y,
|
|
17161
|
-
pcbRotation: pcbElm?.rotation,
|
|
17162
|
-
doNotPlace: pcbElm?.do_not_place,
|
|
17163
|
-
obstructsWithinBounds: pcbElm?.obstructs_within_bounds
|
|
17164
|
-
});
|
|
17165
|
-
if (pcbElm) {
|
|
17166
|
-
const footprint = inflateFootprintComponent(pcbElm, {
|
|
17167
|
-
...inflatorContext,
|
|
17168
|
-
normalComponent: capacitor
|
|
17169
|
-
});
|
|
17170
|
-
if (footprint) {
|
|
17171
|
-
capacitor.add(footprint);
|
|
17350
|
+
_determineSideFromPosition(port, component) {
|
|
17351
|
+
if (!port.center || !component.center) return "left";
|
|
17352
|
+
const dx = port.center.x - component.center.x;
|
|
17353
|
+
const dy = port.center.y - component.center.y;
|
|
17354
|
+
if (Math.abs(dx) > Math.abs(dy)) {
|
|
17355
|
+
return dx > 0 ? "right" : "left";
|
|
17172
17356
|
}
|
|
17357
|
+
return dy > 0 ? "bottom" : "top";
|
|
17173
17358
|
}
|
|
17174
|
-
|
|
17175
|
-
|
|
17176
|
-
|
|
17177
|
-
|
|
17178
|
-
|
|
17179
|
-
|
|
17180
|
-
|
|
17181
|
-
|
|
17182
|
-
|
|
17183
|
-
|
|
17184
|
-
|
|
17185
|
-
|
|
17186
|
-
|
|
17187
|
-
|
|
17188
|
-
|
|
17189
|
-
}
|
|
17190
|
-
get config() {
|
|
17359
|
+
_calculateSchematicBounds(boxes) {
|
|
17360
|
+
if (boxes.length === 0) {
|
|
17361
|
+
return { minX: 0, maxX: 0, minY: 0, maxY: 0 };
|
|
17362
|
+
}
|
|
17363
|
+
let minX = Infinity;
|
|
17364
|
+
let maxX = -Infinity;
|
|
17365
|
+
let minY = Infinity;
|
|
17366
|
+
let maxY = -Infinity;
|
|
17367
|
+
for (const box of boxes) {
|
|
17368
|
+
minX = Math.min(minX, box.centerX);
|
|
17369
|
+
maxX = Math.max(maxX, box.centerX);
|
|
17370
|
+
minY = Math.min(minY, box.centerY);
|
|
17371
|
+
maxY = Math.max(maxY, box.centerY);
|
|
17372
|
+
}
|
|
17373
|
+
const padding = 2;
|
|
17191
17374
|
return {
|
|
17192
|
-
|
|
17193
|
-
|
|
17194
|
-
|
|
17375
|
+
minX: minX - padding,
|
|
17376
|
+
maxX: maxX + padding,
|
|
17377
|
+
minY: minY - padding,
|
|
17378
|
+
maxY: maxY + padding
|
|
17195
17379
|
};
|
|
17196
17380
|
}
|
|
17197
|
-
|
|
17198
|
-
|
|
17199
|
-
|
|
17200
|
-
|
|
17201
|
-
|
|
17202
|
-
|
|
17203
|
-
|
|
17204
|
-
|
|
17205
|
-
|
|
17206
|
-
|
|
17207
|
-
|
|
17208
|
-
|
|
17209
|
-
|
|
17210
|
-
|
|
17211
|
-
|
|
17212
|
-
|
|
17213
|
-
|
|
17214
|
-
|
|
17215
|
-
|
|
17216
|
-
|
|
17217
|
-
|
|
17218
|
-
|
|
17219
|
-
|
|
17220
|
-
|
|
17221
|
-
|
|
17222
|
-
new Port({
|
|
17223
|
-
name: pinIdentifier,
|
|
17224
|
-
aliases: [pinIdentifier]
|
|
17225
|
-
})
|
|
17226
|
-
);
|
|
17227
|
-
}
|
|
17228
|
-
}
|
|
17229
|
-
}
|
|
17381
|
+
_getAutorouterConfig() {
|
|
17382
|
+
const autorouter = this._parsedProps.autorouter || this.getInheritedProperty("autorouter");
|
|
17383
|
+
return getPresetAutoroutingConfig(autorouter);
|
|
17384
|
+
}
|
|
17385
|
+
_isLaserPrefabAutorouter(autorouterConfig = this._getAutorouterConfig()) {
|
|
17386
|
+
const autorouterProp = this.props.autorouter;
|
|
17387
|
+
const normalize = (value) => value?.replace(/-/g, "_") ?? value;
|
|
17388
|
+
if (autorouterConfig.preset === "laser_prefab") return true;
|
|
17389
|
+
if (typeof autorouterProp === "string") {
|
|
17390
|
+
return normalize(autorouterProp) === "laser_prefab";
|
|
17391
|
+
}
|
|
17392
|
+
if (typeof autorouterProp === "object" && autorouterProp) {
|
|
17393
|
+
return normalize(autorouterProp.preset) === "laser_prefab";
|
|
17394
|
+
}
|
|
17395
|
+
return false;
|
|
17396
|
+
}
|
|
17397
|
+
_isAutoJumperAutorouter(autorouterConfig = this._getAutorouterConfig()) {
|
|
17398
|
+
const autorouterProp = this.props.autorouter;
|
|
17399
|
+
const normalize = (value) => value?.replace(/-/g, "_") ?? value;
|
|
17400
|
+
if (autorouterConfig.preset === "auto_jumper") return true;
|
|
17401
|
+
if (typeof autorouterProp === "string") {
|
|
17402
|
+
return normalize(autorouterProp) === "auto_jumper";
|
|
17403
|
+
}
|
|
17404
|
+
if (typeof autorouterProp === "object" && autorouterProp) {
|
|
17405
|
+
return normalize(autorouterProp.preset) === "auto_jumper";
|
|
17230
17406
|
}
|
|
17407
|
+
return false;
|
|
17231
17408
|
}
|
|
17232
|
-
|
|
17233
|
-
const
|
|
17234
|
-
|
|
17235
|
-
super.doInitialSchematicComponentRender();
|
|
17409
|
+
_getSubcircuitLayerCount() {
|
|
17410
|
+
const layers = this.getInheritedProperty("layers");
|
|
17411
|
+
return typeof layers === "number" ? layers : 2;
|
|
17236
17412
|
}
|
|
17237
|
-
|
|
17238
|
-
|
|
17239
|
-
|
|
17240
|
-
|
|
17241
|
-
|
|
17242
|
-
|
|
17243
|
-
|
|
17244
|
-
|
|
17245
|
-
|
|
17246
|
-
|
|
17247
|
-
|
|
17413
|
+
/**
|
|
17414
|
+
* Trace-by-trace autorouting is where each trace routes itself in a well-known
|
|
17415
|
+
* order. It's the most deterministic way to autoroute, because a new trace
|
|
17416
|
+
* is generally ordered last.
|
|
17417
|
+
*
|
|
17418
|
+
* This method will return false if using an external service for autorouting
|
|
17419
|
+
* or if using a "fullview" or "rip and replace" autorouting mode
|
|
17420
|
+
*/
|
|
17421
|
+
_shouldUseTraceByTraceRouting() {
|
|
17422
|
+
const autorouter = this._getAutorouterConfig();
|
|
17423
|
+
return autorouter.groupMode === "sequential-trace";
|
|
17248
17424
|
}
|
|
17249
|
-
|
|
17425
|
+
doInitialPcbDesignRuleChecks() {
|
|
17250
17426
|
if (this.root?.pcbDisabled) return;
|
|
17427
|
+
if (this.root?.pcbRoutingDisabled || this.getInheritedProperty("routingDisabled"))
|
|
17428
|
+
return;
|
|
17251
17429
|
const { db } = this.root;
|
|
17252
|
-
|
|
17253
|
-
|
|
17254
|
-
|
|
17255
|
-
|
|
17256
|
-
|
|
17257
|
-
|
|
17258
|
-
|
|
17259
|
-
|
|
17260
|
-
|
|
17261
|
-
layer: componentLayer,
|
|
17262
|
-
subcircuit_id: subcircuit.subcircuit_id ?? void 0
|
|
17263
|
-
});
|
|
17264
|
-
db.pcb_component_invalid_layer_error.insert(error);
|
|
17265
|
-
}
|
|
17266
|
-
const pcb_component = db.pcb_component.insert({
|
|
17267
|
-
center: { x: pcbX, y: pcbY },
|
|
17268
|
-
width: 2,
|
|
17269
|
-
// Default width, adjust as needed
|
|
17270
|
-
height: 3,
|
|
17271
|
-
// Default height, adjust as needed
|
|
17272
|
-
layer: componentLayer === "top" || componentLayer === "bottom" ? componentLayer : "top",
|
|
17273
|
-
rotation: props.pcbRotation ?? 0,
|
|
17274
|
-
source_component_id: this.source_component_id,
|
|
17275
|
-
subcircuit_id: this.getSubcircuit().subcircuit_id ?? void 0,
|
|
17276
|
-
do_not_place: props.doNotPlace ?? false,
|
|
17277
|
-
obstructs_within_bounds: props.obstructsWithinBounds ?? true,
|
|
17278
|
-
is_allowed_to_be_off_board: props.allowOffBoard ?? false,
|
|
17279
|
-
metadata: props.kicadFootprintMetadata ? { kicad_footprint: props.kicadFootprintMetadata } : void 0
|
|
17280
|
-
});
|
|
17281
|
-
this.pcb_component_id = pcb_component.pcb_component_id;
|
|
17282
|
-
}
|
|
17283
|
-
doInitialCreateTracesFromProps() {
|
|
17284
|
-
const { _parsedProps: props } = this;
|
|
17285
|
-
if (props.externallyConnectedPins) {
|
|
17286
|
-
for (const [pin1, pin2] of props.externallyConnectedPins) {
|
|
17287
|
-
this.add(
|
|
17288
|
-
new Trace3({
|
|
17289
|
-
from: `${this.getSubcircuitSelector()} > port.${pin1}`,
|
|
17290
|
-
to: `${this.getSubcircuitSelector()} > port.${pin2}`
|
|
17291
|
-
})
|
|
17292
|
-
);
|
|
17430
|
+
if (this.isSubcircuit) {
|
|
17431
|
+
const subcircuitComponentsByName = /* @__PURE__ */ new Map();
|
|
17432
|
+
for (const child of this.children) {
|
|
17433
|
+
if (child.isSubcircuit) continue;
|
|
17434
|
+
if (child._parsedProps.name) {
|
|
17435
|
+
const components = subcircuitComponentsByName.get(child._parsedProps.name) || [];
|
|
17436
|
+
components.push(child);
|
|
17437
|
+
subcircuitComponentsByName.set(child._parsedProps.name, components);
|
|
17438
|
+
}
|
|
17293
17439
|
}
|
|
17294
|
-
|
|
17295
|
-
|
|
17296
|
-
|
|
17297
|
-
|
|
17298
|
-
|
|
17299
|
-
|
|
17300
|
-
|
|
17301
|
-
|
|
17302
|
-
|
|
17303
|
-
|
|
17304
|
-
const ports = this.selectAll("port");
|
|
17305
|
-
for (const port of ports) {
|
|
17306
|
-
for (const alias of port.getNameAndAliases()) {
|
|
17307
|
-
if (pinAttributes[alias]) {
|
|
17308
|
-
const attributes = pinAttributes[alias];
|
|
17309
|
-
if (attributes.providesPower) {
|
|
17310
|
-
powerPort = port;
|
|
17311
|
-
voltage = attributes.providesVoltage;
|
|
17312
|
-
}
|
|
17313
|
-
if (attributes.providesGround) {
|
|
17314
|
-
groundPort = port;
|
|
17315
|
-
}
|
|
17440
|
+
for (const [name, components] of subcircuitComponentsByName.entries()) {
|
|
17441
|
+
if (components.length > 1) {
|
|
17442
|
+
db.pcb_trace_error.insert({
|
|
17443
|
+
error_type: "pcb_trace_error",
|
|
17444
|
+
message: `Multiple components found with name "${name}" in subcircuit "${this.name || "unnamed"}". Component names must be unique within a subcircuit.`,
|
|
17445
|
+
source_trace_id: "",
|
|
17446
|
+
pcb_trace_id: "",
|
|
17447
|
+
pcb_component_ids: components.map((c) => c.pcb_component_id).filter(Boolean),
|
|
17448
|
+
pcb_port_ids: []
|
|
17449
|
+
});
|
|
17316
17450
|
}
|
|
17317
17451
|
}
|
|
17318
17452
|
}
|
|
17319
|
-
if (!powerPort || !groundPort || voltage === void 0) {
|
|
17320
|
-
return;
|
|
17321
|
-
}
|
|
17322
|
-
const powerSourcePort = db.source_port.get(powerPort.source_port_id);
|
|
17323
|
-
if (!powerSourcePort?.subcircuit_connectivity_map_key) return;
|
|
17324
|
-
const groundSourcePort = db.source_port.get(groundPort.source_port_id);
|
|
17325
|
-
if (!groundSourcePort?.subcircuit_connectivity_map_key) return;
|
|
17326
|
-
const powerNet = db.source_net.getWhere({
|
|
17327
|
-
subcircuit_connectivity_map_key: powerSourcePort.subcircuit_connectivity_map_key
|
|
17328
|
-
});
|
|
17329
|
-
const groundNet = db.source_net.getWhere({
|
|
17330
|
-
subcircuit_connectivity_map_key: groundSourcePort.subcircuit_connectivity_map_key
|
|
17331
|
-
});
|
|
17332
|
-
if (!powerNet || !groundNet) {
|
|
17333
|
-
return;
|
|
17334
|
-
}
|
|
17335
|
-
;
|
|
17336
|
-
db.simulation_voltage_source.insert({
|
|
17337
|
-
type: "simulation_voltage_source",
|
|
17338
|
-
positive_source_port_id: powerPort.source_port_id,
|
|
17339
|
-
positive_source_net_id: powerNet.source_net_id,
|
|
17340
|
-
negative_source_port_id: groundPort.source_port_id,
|
|
17341
|
-
negative_source_net_id: groundNet.source_net_id,
|
|
17342
|
-
voltage
|
|
17343
|
-
});
|
|
17344
17453
|
}
|
|
17345
|
-
|
|
17346
|
-
|
|
17347
|
-
|
|
17348
|
-
|
|
17349
|
-
|
|
17350
|
-
|
|
17351
|
-
|
|
17352
|
-
|
|
17353
|
-
|
|
17354
|
-
|
|
17355
|
-
|
|
17356
|
-
|
|
17357
|
-
|
|
17358
|
-
|
|
17454
|
+
doInitialSchematicReplaceNetLabelsWithSymbols() {
|
|
17455
|
+
if (this.root?.schematicDisabled) return;
|
|
17456
|
+
if (!this.isSubcircuit) return;
|
|
17457
|
+
const { db } = this.root;
|
|
17458
|
+
const subtree = db;
|
|
17459
|
+
for (const nl of subtree.schematic_net_label.list()) {
|
|
17460
|
+
const net = subtree.source_net.get(nl.source_net_id);
|
|
17461
|
+
const text = nl.text || net?.name || "";
|
|
17462
|
+
if (nl.anchor_side === "top" && /^gnd/i.test(text)) {
|
|
17463
|
+
subtree.schematic_net_label.update(nl.schematic_net_label_id, {
|
|
17464
|
+
symbol_name: "rail_down"
|
|
17465
|
+
});
|
|
17466
|
+
continue;
|
|
17467
|
+
}
|
|
17468
|
+
if (nl.anchor_side === "bottom" && /^v/i.test(text)) {
|
|
17469
|
+
subtree.schematic_net_label.update(nl.schematic_net_label_id, {
|
|
17470
|
+
symbol_name: "rail_up"
|
|
17471
|
+
});
|
|
17359
17472
|
}
|
|
17360
|
-
return port.name;
|
|
17361
|
-
}).filter((value) => value !== null)
|
|
17362
|
-
).filter((group) => group.length > 0);
|
|
17363
|
-
return mapped.length > 0 ? mapped : void 0;
|
|
17364
|
-
};
|
|
17365
|
-
var inflateSourceChip = (sourceElm, inflatorContext) => {
|
|
17366
|
-
const { injectionDb, subcircuit, groupsMap } = inflatorContext;
|
|
17367
|
-
const pcbElm = injectionDb.pcb_component.getWhere({
|
|
17368
|
-
source_component_id: sourceElm.source_component_id
|
|
17369
|
-
});
|
|
17370
|
-
const schematicElm = injectionDb.schematic_component.getWhere({
|
|
17371
|
-
source_component_id: sourceElm.source_component_id
|
|
17372
|
-
});
|
|
17373
|
-
const cadElm = injectionDb.cad_component.getWhere({
|
|
17374
|
-
source_component_id: sourceElm.source_component_id
|
|
17375
|
-
});
|
|
17376
|
-
const internallyConnectedPins = mapInternallyConnectedSourcePortIdsToPinLabels(
|
|
17377
|
-
sourceElm.internally_connected_source_port_ids,
|
|
17378
|
-
inflatorContext
|
|
17379
|
-
);
|
|
17380
|
-
const footprinterString = cadElm?.footprinter_string ?? null;
|
|
17381
|
-
const chip = new Chip({
|
|
17382
|
-
name: sourceElm.name,
|
|
17383
|
-
manufacturerPartNumber: sourceElm.manufacturer_part_number,
|
|
17384
|
-
supplierPartNumbers: sourceElm.supplier_part_numbers ?? void 0,
|
|
17385
|
-
pinLabels: schematicElm?.port_labels ?? void 0,
|
|
17386
|
-
schWidth: schematicElm?.size?.width,
|
|
17387
|
-
schHeight: schematicElm?.size?.height,
|
|
17388
|
-
schPinSpacing: schematicElm?.pin_spacing,
|
|
17389
|
-
schX: schematicElm?.center?.x,
|
|
17390
|
-
schY: schematicElm?.center?.y,
|
|
17391
|
-
layer: pcbElm?.layer,
|
|
17392
|
-
pcbX: pcbElm?.center?.x,
|
|
17393
|
-
pcbY: pcbElm?.center?.y,
|
|
17394
|
-
pcbRotation: pcbElm?.rotation,
|
|
17395
|
-
doNotPlace: pcbElm?.do_not_place,
|
|
17396
|
-
obstructsWithinBounds: pcbElm?.obstructs_within_bounds,
|
|
17397
|
-
internallyConnectedPins
|
|
17398
|
-
});
|
|
17399
|
-
if (footprinterString) {
|
|
17400
|
-
Object.assign(chip.props, { footprint: footprinterString });
|
|
17401
|
-
Object.assign(chip._parsedProps, { footprint: footprinterString });
|
|
17402
|
-
}
|
|
17403
|
-
if (pcbElm) {
|
|
17404
|
-
const footprint = inflateFootprintComponent(pcbElm, {
|
|
17405
|
-
...inflatorContext,
|
|
17406
|
-
normalComponent: chip
|
|
17407
|
-
});
|
|
17408
|
-
if (footprint) {
|
|
17409
|
-
chip.add(footprint);
|
|
17410
17473
|
}
|
|
17411
17474
|
}
|
|
17412
|
-
|
|
17413
|
-
|
|
17414
|
-
group.add(chip);
|
|
17415
|
-
} else {
|
|
17416
|
-
subcircuit.add(chip);
|
|
17475
|
+
doInitialSimulationSpiceEngineRender() {
|
|
17476
|
+
Group_doInitialSimulationSpiceEngineRender(this);
|
|
17417
17477
|
}
|
|
17418
|
-
|
|
17419
|
-
|
|
17420
|
-
|
|
17421
|
-
|
|
17422
|
-
|
|
17423
|
-
|
|
17424
|
-
|
|
17425
|
-
|
|
17426
|
-
avalanche: "avalanche_diode",
|
|
17427
|
-
zener: "zener_diode",
|
|
17428
|
-
photodiode: "photodiode"
|
|
17429
|
-
};
|
|
17430
|
-
const variantSymbol = this.props.schottky ? "schottky" : this.props.avalanche ? "avalanche" : this.props.zener ? "zener" : this.props.photo ? "photodiode" : null;
|
|
17431
|
-
return {
|
|
17432
|
-
schematicSymbolName: variantSymbol ? symbolMap[variantSymbol] : this.props.symbolName ?? "diode",
|
|
17433
|
-
componentName: "Diode",
|
|
17434
|
-
zodProps: diodeProps,
|
|
17435
|
-
sourceFtype: "simple_diode"
|
|
17436
|
-
};
|
|
17478
|
+
/**
|
|
17479
|
+
* Override anchor alignment to handle group-specific logic
|
|
17480
|
+
*/
|
|
17481
|
+
doInitialPcbComponentAnchorAlignment() {
|
|
17482
|
+
Group_doInitialPcbComponentAnchorAlignment(this);
|
|
17483
|
+
}
|
|
17484
|
+
updatePcbComponentAnchorAlignment() {
|
|
17485
|
+
this.doInitialPcbComponentAnchorAlignment();
|
|
17437
17486
|
}
|
|
17438
|
-
|
|
17439
|
-
|
|
17440
|
-
additionalAliases: {
|
|
17441
|
-
pin1: ["anode", "pos", "left"],
|
|
17442
|
-
pin2: ["cathode", "neg", "right"]
|
|
17443
|
-
}
|
|
17444
|
-
});
|
|
17487
|
+
doInitialPcbCalcPlacementResolution() {
|
|
17488
|
+
Group_doInitialPcbCalcPlacementResolution(this);
|
|
17445
17489
|
}
|
|
17446
|
-
|
|
17447
|
-
|
|
17448
|
-
const { _parsedProps: props } = this;
|
|
17449
|
-
const source_component = db.source_component.insert({
|
|
17450
|
-
ftype: "simple_diode",
|
|
17451
|
-
name: this.name,
|
|
17452
|
-
manufacturer_part_number: props.manufacturerPartNumber ?? props.mfn,
|
|
17453
|
-
supplier_part_numbers: props.supplierPartNumbers,
|
|
17454
|
-
are_pins_interchangeable: false,
|
|
17455
|
-
display_name: props.displayName
|
|
17456
|
-
});
|
|
17457
|
-
this.source_component_id = source_component.source_component_id;
|
|
17490
|
+
updatePcbCalcPlacementResolution() {
|
|
17491
|
+
this.doInitialPcbCalcPlacementResolution();
|
|
17458
17492
|
}
|
|
17459
|
-
|
|
17460
|
-
|
|
17461
|
-
|
|
17462
|
-
|
|
17463
|
-
|
|
17464
|
-
|
|
17465
|
-
// lib/components/primitive-components/Group/Subcircuit/inflators/inflateSourceDiode.ts
|
|
17466
|
-
function inflateSourceDiode(sourceElm, inflatorContext) {
|
|
17467
|
-
const { injectionDb, subcircuit, groupsMap } = inflatorContext;
|
|
17468
|
-
const pcbElm = injectionDb.pcb_component.getWhere({
|
|
17469
|
-
source_component_id: sourceElm.source_component_id
|
|
17470
|
-
});
|
|
17471
|
-
const cadElm = injectionDb.cad_component.getWhere({
|
|
17472
|
-
source_component_id: sourceElm.source_component_id
|
|
17473
|
-
});
|
|
17474
|
-
const diode = new Diode({
|
|
17475
|
-
name: sourceElm.name,
|
|
17476
|
-
layer: pcbElm?.layer,
|
|
17477
|
-
pcbX: pcbElm?.center?.x,
|
|
17478
|
-
pcbY: pcbElm?.center?.y,
|
|
17479
|
-
pcbRotation: pcbElm?.rotation,
|
|
17480
|
-
doNotPlace: pcbElm?.do_not_place,
|
|
17481
|
-
obstructsWithinBounds: pcbElm?.obstructs_within_bounds
|
|
17482
|
-
});
|
|
17483
|
-
if (pcbElm) {
|
|
17484
|
-
const footprint = inflateFootprintComponent(pcbElm, {
|
|
17485
|
-
...inflatorContext,
|
|
17486
|
-
normalComponent: diode
|
|
17487
|
-
});
|
|
17488
|
-
if (footprint) {
|
|
17489
|
-
diode.add(footprint);
|
|
17490
|
-
}
|
|
17493
|
+
/**
|
|
17494
|
+
* Get the minimum flex container size for this group on PCB
|
|
17495
|
+
*/
|
|
17496
|
+
_getMinimumFlexContainerSize() {
|
|
17497
|
+
return super._getMinimumFlexContainerSize();
|
|
17491
17498
|
}
|
|
17492
|
-
|
|
17493
|
-
|
|
17494
|
-
|
|
17495
|
-
|
|
17496
|
-
|
|
17499
|
+
/**
|
|
17500
|
+
* Reposition this group on the PCB to the specified coordinates
|
|
17501
|
+
*/
|
|
17502
|
+
_repositionOnPcb(position) {
|
|
17503
|
+
return super._repositionOnPcb(position);
|
|
17497
17504
|
}
|
|
17498
|
-
}
|
|
17505
|
+
};
|
|
17499
17506
|
|
|
17500
17507
|
// lib/components/primitive-components/Group/Subcircuit/inflators/inflateSourceGroup.ts
|
|
17501
17508
|
function inflateSourceGroup(sourceGroup, inflatorContext) {
|
|
@@ -18039,100 +18046,6 @@ var inflateCircuitJson = (target, circuitJson, children) => {
|
|
|
18039
18046
|
inflateStandalonePcbPrimitives(inflationCtx);
|
|
18040
18047
|
};
|
|
18041
18048
|
|
|
18042
|
-
// lib/components/normal-components/Board.ts
|
|
18043
|
-
import {
|
|
18044
|
-
checkEachPcbPortConnectedToPcbTraces,
|
|
18045
|
-
checkEachPcbTraceNonOverlapping,
|
|
18046
|
-
checkPcbComponentsOutOfBoard,
|
|
18047
|
-
checkPcbTracesOutOfBoard,
|
|
18048
|
-
checkDifferentNetViaSpacing,
|
|
18049
|
-
checkSameNetViaSpacing,
|
|
18050
|
-
checkPcbComponentOverlap,
|
|
18051
|
-
checkPinMustBeConnected
|
|
18052
|
-
} from "@tscircuit/checks";
|
|
18053
|
-
import { getBoundsFromPoints as getBoundsFromPoints4 } from "@tscircuit/math-utils";
|
|
18054
|
-
import { compose as compose7, translate as translate7 } from "transformation-matrix";
|
|
18055
|
-
|
|
18056
|
-
// lib/components/primitive-components/Group/Subcircuit_getSubcircuitPropHash.ts
|
|
18057
|
-
var EXCLUDED_PROPS = /* @__PURE__ */ new Set([
|
|
18058
|
-
"name",
|
|
18059
|
-
"key",
|
|
18060
|
-
"pcbX",
|
|
18061
|
-
"pcbY",
|
|
18062
|
-
"schX",
|
|
18063
|
-
"schY",
|
|
18064
|
-
"pcbLeftEdgeX",
|
|
18065
|
-
"pcbRightEdgeX",
|
|
18066
|
-
"pcbTopEdgeY",
|
|
18067
|
-
"pcbBottomEdgeY",
|
|
18068
|
-
"pcbRotation",
|
|
18069
|
-
"schRotation"
|
|
18070
|
-
]);
|
|
18071
|
-
function safeSerialize(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
18072
|
-
if (value === null) return "null";
|
|
18073
|
-
if (value === void 0) return "undefined";
|
|
18074
|
-
const type = typeof value;
|
|
18075
|
-
if (type === "string") return `"${value}"`;
|
|
18076
|
-
if (type === "number" || type === "boolean") return String(value);
|
|
18077
|
-
if (type === "function") return "[function]";
|
|
18078
|
-
if (type === "symbol") return "[symbol]";
|
|
18079
|
-
if (type === "object") {
|
|
18080
|
-
if (seen.has(value)) return "[circular]";
|
|
18081
|
-
seen.add(value);
|
|
18082
|
-
if (value.$$typeof !== void 0) {
|
|
18083
|
-
const elementType = typeof value.type === "string" ? value.type : value.type?.name || "[component]";
|
|
18084
|
-
const propsStr = value.props ? safeSerialize(value.props, seen) : "{}";
|
|
18085
|
-
return `ReactElement(${elementType},${propsStr})`;
|
|
18086
|
-
}
|
|
18087
|
-
if (Array.isArray(value)) {
|
|
18088
|
-
const items = value.map((v) => safeSerialize(v, seen)).join(",");
|
|
18089
|
-
return `[${items}]`;
|
|
18090
|
-
}
|
|
18091
|
-
const keys = Object.keys(value).sort();
|
|
18092
|
-
const pairs3 = keys.map((k) => `${k}:${safeSerialize(value[k], seen)}`);
|
|
18093
|
-
return `{${pairs3.join(",")}}`;
|
|
18094
|
-
}
|
|
18095
|
-
return String(value);
|
|
18096
|
-
}
|
|
18097
|
-
function getHashableProps(props) {
|
|
18098
|
-
const result = {};
|
|
18099
|
-
const keys = Object.keys(props).sort();
|
|
18100
|
-
for (const key of keys) {
|
|
18101
|
-
if (!EXCLUDED_PROPS.has(key) && props[key] !== void 0) {
|
|
18102
|
-
result[key] = props[key];
|
|
18103
|
-
}
|
|
18104
|
-
}
|
|
18105
|
-
return result;
|
|
18106
|
-
}
|
|
18107
|
-
function getChildrenHashData(children) {
|
|
18108
|
-
return children.map((child) => ({
|
|
18109
|
-
componentName: child.componentName,
|
|
18110
|
-
props: getHashableProps(child.props ?? {}),
|
|
18111
|
-
children: getChildrenHashData(child.children)
|
|
18112
|
-
}));
|
|
18113
|
-
}
|
|
18114
|
-
function fnv1aHash(str) {
|
|
18115
|
-
let hash = 2166136261;
|
|
18116
|
-
for (let i = 0; i < str.length; i++) {
|
|
18117
|
-
hash ^= str.charCodeAt(i);
|
|
18118
|
-
hash = Math.imul(hash, 16777619);
|
|
18119
|
-
}
|
|
18120
|
-
return hash >>> 0;
|
|
18121
|
-
}
|
|
18122
|
-
function computeHash(data) {
|
|
18123
|
-
const serialized = safeSerialize(data);
|
|
18124
|
-
const hash1 = fnv1aHash(serialized);
|
|
18125
|
-
const hash2 = fnv1aHash(serialized + hash1.toString());
|
|
18126
|
-
return hash1.toString(16).padStart(8, "0") + hash2.toString(16).padStart(8, "0");
|
|
18127
|
-
}
|
|
18128
|
-
function Subcircuit_getSubcircuitPropHash(subcircuit) {
|
|
18129
|
-
const hashableData = {
|
|
18130
|
-
props: getHashableProps(subcircuit.props ?? {}),
|
|
18131
|
-
children: getChildrenHashData(subcircuit.children)
|
|
18132
|
-
};
|
|
18133
|
-
return computeHash(hashableData);
|
|
18134
|
-
}
|
|
18135
|
-
|
|
18136
18049
|
// lib/IsolatedCircuit.ts
|
|
18137
18050
|
import { su as su5 } from "@tscircuit/circuit-json-util";
|
|
18138
18051
|
import Debug14 from "debug";
|
|
@@ -18143,7 +18056,7 @@ import { identity as identity5 } from "transformation-matrix";
|
|
|
18143
18056
|
var package_default = {
|
|
18144
18057
|
name: "@tscircuit/core",
|
|
18145
18058
|
type: "module",
|
|
18146
|
-
version: "0.0.
|
|
18059
|
+
version: "0.0.1068",
|
|
18147
18060
|
types: "dist/index.d.ts",
|
|
18148
18061
|
main: "dist/index.js",
|
|
18149
18062
|
module: "dist/index.js",
|
|
@@ -18176,8 +18089,8 @@ var package_default = {
|
|
|
18176
18089
|
"@resvg/resvg-js": "^2.6.2",
|
|
18177
18090
|
"@tscircuit/alphabet": "0.0.18",
|
|
18178
18091
|
"@tscircuit/capacity-autorouter": "^0.0.299",
|
|
18179
|
-
"@tscircuit/checks": "
|
|
18180
|
-
"@tscircuit/circuit-json-util": "^0.0.
|
|
18092
|
+
"@tscircuit/checks": "0.0.95",
|
|
18093
|
+
"@tscircuit/circuit-json-util": "^0.0.80",
|
|
18181
18094
|
"@tscircuit/common": "^0.0.20",
|
|
18182
18095
|
"@tscircuit/copper-pour-solver": "^0.0.20",
|
|
18183
18096
|
"@tscircuit/footprinter": "^0.0.316",
|
|
@@ -18187,7 +18100,7 @@ var package_default = {
|
|
|
18187
18100
|
"@tscircuit/math-utils": "^0.0.29",
|
|
18188
18101
|
"@tscircuit/miniflex": "^0.0.4",
|
|
18189
18102
|
"@tscircuit/ngspice-spice-engine": "^0.0.8",
|
|
18190
|
-
"@tscircuit/props": "^0.0.
|
|
18103
|
+
"@tscircuit/props": "^0.0.485",
|
|
18191
18104
|
"@tscircuit/schematic-match-adapt": "^0.0.16",
|
|
18192
18105
|
"@tscircuit/schematic-trace-solver": "^v0.0.45",
|
|
18193
18106
|
"@tscircuit/solver-utils": "^0.0.3",
|
|
@@ -18207,7 +18120,7 @@ var package_default = {
|
|
|
18207
18120
|
"circuit-json-to-gltf": "^0.0.73",
|
|
18208
18121
|
"circuit-json-to-simple-3d": "^0.0.9",
|
|
18209
18122
|
"circuit-json-to-spice": "^0.0.34",
|
|
18210
|
-
"circuit-to-svg": "^0.0.
|
|
18123
|
+
"circuit-to-svg": "^0.0.333",
|
|
18211
18124
|
concurrently: "^9.1.2",
|
|
18212
18125
|
"connectivity-map": "^1.0.0",
|
|
18213
18126
|
debug: "^4.3.6",
|
|
@@ -18321,6 +18234,7 @@ var IsolatedCircuit = class {
|
|
|
18321
18234
|
this.platform = platform;
|
|
18322
18235
|
this.projectUrl = projectUrl;
|
|
18323
18236
|
this.pcbDisabled = platform?.pcbDisabled ?? false;
|
|
18237
|
+
this.pcbRoutingDisabled = platform?.routingDisabled ?? false;
|
|
18324
18238
|
this.cachedSubcircuits = cachedSubcircuits;
|
|
18325
18239
|
this.pendingSubcircuitRenders = pendingSubcircuitRenders;
|
|
18326
18240
|
this.root = this;
|
|
@@ -18339,6 +18253,12 @@ var IsolatedCircuit = class {
|
|
|
18339
18253
|
...this.platform,
|
|
18340
18254
|
...platform
|
|
18341
18255
|
};
|
|
18256
|
+
if (platform.pcbDisabled !== void 0) {
|
|
18257
|
+
this.pcbDisabled = platform.pcbDisabled;
|
|
18258
|
+
}
|
|
18259
|
+
if (platform.routingDisabled !== void 0) {
|
|
18260
|
+
this.pcbRoutingDisabled = platform.routingDisabled;
|
|
18261
|
+
}
|
|
18342
18262
|
}
|
|
18343
18263
|
/**
|
|
18344
18264
|
* Get the main board for this Circuit.
|
|
@@ -18593,6 +18513,86 @@ function Subcircuit_doInitialRenderIsolatedSubcircuits(subcircuit) {
|
|
|
18593
18513
|
});
|
|
18594
18514
|
}
|
|
18595
18515
|
|
|
18516
|
+
// lib/components/primitive-components/Group/Subcircuit_getSubcircuitPropHash.ts
|
|
18517
|
+
var EXCLUDED_PROPS = /* @__PURE__ */ new Set([
|
|
18518
|
+
"name",
|
|
18519
|
+
"key",
|
|
18520
|
+
"pcbX",
|
|
18521
|
+
"pcbY",
|
|
18522
|
+
"schX",
|
|
18523
|
+
"schY",
|
|
18524
|
+
"pcbLeftEdgeX",
|
|
18525
|
+
"pcbRightEdgeX",
|
|
18526
|
+
"pcbTopEdgeY",
|
|
18527
|
+
"pcbBottomEdgeY",
|
|
18528
|
+
"pcbRotation",
|
|
18529
|
+
"schRotation"
|
|
18530
|
+
]);
|
|
18531
|
+
function safeSerialize(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
18532
|
+
if (value === null) return "null";
|
|
18533
|
+
if (value === void 0) return "undefined";
|
|
18534
|
+
const type = typeof value;
|
|
18535
|
+
if (type === "string") return `"${value}"`;
|
|
18536
|
+
if (type === "number" || type === "boolean") return String(value);
|
|
18537
|
+
if (type === "function") return "[function]";
|
|
18538
|
+
if (type === "symbol") return "[symbol]";
|
|
18539
|
+
if (type === "object") {
|
|
18540
|
+
if (seen.has(value)) return "[circular]";
|
|
18541
|
+
seen.add(value);
|
|
18542
|
+
if (value.$$typeof !== void 0) {
|
|
18543
|
+
const elementType = typeof value.type === "string" ? value.type : value.type?.name || "[component]";
|
|
18544
|
+
const propsStr = value.props ? safeSerialize(value.props, seen) : "{}";
|
|
18545
|
+
return `ReactElement(${elementType},${propsStr})`;
|
|
18546
|
+
}
|
|
18547
|
+
if (Array.isArray(value)) {
|
|
18548
|
+
const items = value.map((v) => safeSerialize(v, seen)).join(",");
|
|
18549
|
+
return `[${items}]`;
|
|
18550
|
+
}
|
|
18551
|
+
const keys = Object.keys(value).sort();
|
|
18552
|
+
const pairs3 = keys.map((k) => `${k}:${safeSerialize(value[k], seen)}`);
|
|
18553
|
+
return `{${pairs3.join(",")}}`;
|
|
18554
|
+
}
|
|
18555
|
+
return String(value);
|
|
18556
|
+
}
|
|
18557
|
+
function getHashableProps(props) {
|
|
18558
|
+
const result = {};
|
|
18559
|
+
const keys = Object.keys(props).sort();
|
|
18560
|
+
for (const key of keys) {
|
|
18561
|
+
if (!EXCLUDED_PROPS.has(key) && props[key] !== void 0) {
|
|
18562
|
+
result[key] = props[key];
|
|
18563
|
+
}
|
|
18564
|
+
}
|
|
18565
|
+
return result;
|
|
18566
|
+
}
|
|
18567
|
+
function getChildrenHashData(children) {
|
|
18568
|
+
return children.map((child) => ({
|
|
18569
|
+
componentName: child.componentName,
|
|
18570
|
+
props: getHashableProps(child.props ?? {}),
|
|
18571
|
+
children: getChildrenHashData(child.children)
|
|
18572
|
+
}));
|
|
18573
|
+
}
|
|
18574
|
+
function fnv1aHash(str) {
|
|
18575
|
+
let hash = 2166136261;
|
|
18576
|
+
for (let i = 0; i < str.length; i++) {
|
|
18577
|
+
hash ^= str.charCodeAt(i);
|
|
18578
|
+
hash = Math.imul(hash, 16777619);
|
|
18579
|
+
}
|
|
18580
|
+
return hash >>> 0;
|
|
18581
|
+
}
|
|
18582
|
+
function computeHash(data) {
|
|
18583
|
+
const serialized = safeSerialize(data);
|
|
18584
|
+
const hash1 = fnv1aHash(serialized);
|
|
18585
|
+
const hash2 = fnv1aHash(serialized + hash1.toString());
|
|
18586
|
+
return hash1.toString(16).padStart(8, "0") + hash2.toString(16).padStart(8, "0");
|
|
18587
|
+
}
|
|
18588
|
+
function Subcircuit_getSubcircuitPropHash(subcircuit) {
|
|
18589
|
+
const hashableData = {
|
|
18590
|
+
props: getHashableProps(subcircuit.props ?? {}),
|
|
18591
|
+
children: getChildrenHashData(subcircuit.children)
|
|
18592
|
+
};
|
|
18593
|
+
return computeHash(hashableData);
|
|
18594
|
+
}
|
|
18595
|
+
|
|
18596
18596
|
// lib/components/normal-components/Board.ts
|
|
18597
18597
|
var MIN_EFFECTIVE_BORDER_RADIUS_MM = 0.01;
|
|
18598
18598
|
var getRoundedRectOutline = (width, height, radius) => {
|
|
@@ -18653,6 +18653,7 @@ var Board = class extends Group6 {
|
|
|
18653
18653
|
pcb_board_id = null;
|
|
18654
18654
|
source_board_id = null;
|
|
18655
18655
|
_drcChecksComplete = false;
|
|
18656
|
+
_drcChecksInProgress = false;
|
|
18656
18657
|
_connectedSchematicPortPairs = /* @__PURE__ */ new Set();
|
|
18657
18658
|
_panelPositionOffset = null;
|
|
18658
18659
|
get isSubcircuit() {
|
|
@@ -18967,53 +18968,53 @@ var Board = class extends Group6 {
|
|
|
18967
18968
|
}
|
|
18968
18969
|
doInitialPcbDesignRuleChecks() {
|
|
18969
18970
|
if (this.root?.pcbDisabled) return;
|
|
18970
|
-
if (this.getInheritedProperty("routingDisabled")) return;
|
|
18971
18971
|
super.doInitialPcbDesignRuleChecks();
|
|
18972
|
+
this.updatePcbDesignRuleChecks();
|
|
18972
18973
|
}
|
|
18973
18974
|
updatePcbDesignRuleChecks() {
|
|
18974
|
-
if (this.root?.pcbDisabled) return;
|
|
18975
|
-
if (this.getInheritedProperty("routingDisabled")) return;
|
|
18976
18975
|
const { db } = this.root;
|
|
18977
|
-
|
|
18978
|
-
|
|
18979
|
-
const
|
|
18980
|
-
|
|
18981
|
-
|
|
18982
|
-
|
|
18983
|
-
|
|
18984
|
-
|
|
18985
|
-
|
|
18986
|
-
|
|
18987
|
-
|
|
18988
|
-
|
|
18989
|
-
|
|
18990
|
-
|
|
18991
|
-
|
|
18992
|
-
|
|
18993
|
-
|
|
18994
|
-
db.pcb_trace_error.insert(error);
|
|
18995
|
-
}
|
|
18996
|
-
const differentNetViaErrors = checkDifferentNetViaSpacing(circuitJson);
|
|
18997
|
-
for (const error of differentNetViaErrors) {
|
|
18998
|
-
db.pcb_via_clearance_error.insert(error);
|
|
18999
|
-
}
|
|
19000
|
-
const sameNetViaErrors = checkSameNetViaSpacing(circuitJson);
|
|
19001
|
-
for (const error of sameNetViaErrors) {
|
|
19002
|
-
db.pcb_via_clearance_error.insert(error);
|
|
18976
|
+
const routingDisabled = this.root?.pcbRoutingDisabled || this.getInheritedProperty("routingDisabled");
|
|
18977
|
+
const pcbDisabled = this.root?.pcbDisabled;
|
|
18978
|
+
const shouldRunNetlistChecks = true;
|
|
18979
|
+
const shouldRunPlacementChecks = !pcbDisabled;
|
|
18980
|
+
const shouldRunRoutingChecks = !pcbDisabled && !routingDisabled;
|
|
18981
|
+
if (shouldRunRoutingChecks && this._hasIncompleteAsyncEffectsInSubtreeForPhase("PcbTraceRender"))
|
|
18982
|
+
return;
|
|
18983
|
+
const hasTracesToRoute = this._hasTracesToRoute();
|
|
18984
|
+
if (shouldRunRoutingChecks && hasTracesToRoute && !this._areChildSubcircuitsRouted())
|
|
18985
|
+
return;
|
|
18986
|
+
if (this._drcChecksComplete || this._drcChecksInProgress) return;
|
|
18987
|
+
const runDrcChecks = async (circuitJson) => {
|
|
18988
|
+
const checksToRun = [];
|
|
18989
|
+
if (shouldRunRoutingChecks) {
|
|
18990
|
+
checksToRun.push(
|
|
18991
|
+
runAllRoutingChecks(circuitJson)
|
|
18992
|
+
);
|
|
19003
18993
|
}
|
|
19004
|
-
|
|
19005
|
-
|
|
19006
|
-
|
|
18994
|
+
if (shouldRunPlacementChecks) {
|
|
18995
|
+
checksToRun.push(
|
|
18996
|
+
runAllPlacementChecks(circuitJson)
|
|
18997
|
+
);
|
|
19007
18998
|
}
|
|
19008
|
-
|
|
19009
|
-
|
|
19010
|
-
|
|
18999
|
+
if (shouldRunNetlistChecks) {
|
|
19000
|
+
checksToRun.push(
|
|
19001
|
+
runAllNetlistChecks(circuitJson)
|
|
19002
|
+
);
|
|
19011
19003
|
}
|
|
19004
|
+
const checkResults = await Promise.all(checksToRun);
|
|
19005
|
+
db.insertAll(checkResults.flat());
|
|
19012
19006
|
};
|
|
19013
19007
|
const subcircuit = db.subtree({ subcircuit_id: this.subcircuit_id });
|
|
19014
19008
|
const subcircuitCircuitJson = subcircuit.toArray();
|
|
19015
|
-
|
|
19016
|
-
this.
|
|
19009
|
+
this._drcChecksInProgress = true;
|
|
19010
|
+
this._queueAsyncEffect("board:drc-checks", async () => {
|
|
19011
|
+
try {
|
|
19012
|
+
await runDrcChecks(subcircuitCircuitJson);
|
|
19013
|
+
this._drcChecksComplete = true;
|
|
19014
|
+
} finally {
|
|
19015
|
+
this._drcChecksInProgress = false;
|
|
19016
|
+
}
|
|
19017
|
+
});
|
|
19017
19018
|
}
|
|
19018
19019
|
_emitRenderLifecycleEvent(phase, startOrEnd) {
|
|
19019
19020
|
super._emitRenderLifecycleEvent(phase, startOrEnd);
|