@tscircuit/core 0.0.1305 → 0.0.1307
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.js +1557 -1500
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9170,1590 +9170,1647 @@ var SmtPad = class extends PrimitiveComponent2 {
|
|
|
9170
9170
|
}
|
|
9171
9171
|
};
|
|
9172
9172
|
|
|
9173
|
-
// lib/
|
|
9174
|
-
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
|
|
9180
|
-
|
|
9173
|
+
// lib/utils/get-relative-direction.ts
|
|
9174
|
+
function getRelativeDirection(pointA, pointB) {
|
|
9175
|
+
const dx = pointB.x - pointA.x;
|
|
9176
|
+
const dy = pointB.y - pointA.y;
|
|
9177
|
+
if (Math.abs(dx) > Math.abs(dy)) {
|
|
9178
|
+
return dx >= 0 ? "right" : "left";
|
|
9179
|
+
}
|
|
9180
|
+
return dy >= 0 ? "up" : "down";
|
|
9181
|
+
}
|
|
9182
|
+
|
|
9183
|
+
// lib/components/primitive-components/Port/Port.ts
|
|
9184
|
+
import "schematic-symbols";
|
|
9185
|
+
import { applyToPoint as applyToPoint22, compose as compose3, translate as translate2 } from "transformation-matrix";
|
|
9186
|
+
import "zod";
|
|
9187
|
+
|
|
9188
|
+
// lib/components/primitive-components/Port/getCenterOfPcbPrimitives.ts
|
|
9189
|
+
var getCenterOfPcbPrimitives = (pcbPrimitives) => {
|
|
9190
|
+
if (pcbPrimitives.length === 0) {
|
|
9191
|
+
throw new Error("Cannot get center of empty PCB primitives array");
|
|
9192
|
+
}
|
|
9193
|
+
const positions = pcbPrimitives.map((p) => p._getPcbCircuitJsonBounds().center).filter(Boolean);
|
|
9194
|
+
const sumX = positions.reduce((sum, pos) => sum + pos.x, 0);
|
|
9195
|
+
const sumY = positions.reduce((sum, pos) => sum + pos.y, 0);
|
|
9196
|
+
return {
|
|
9197
|
+
x: sumX / positions.length,
|
|
9198
|
+
y: sumY / positions.length
|
|
9199
|
+
};
|
|
9200
|
+
};
|
|
9201
|
+
|
|
9202
|
+
// lib/components/primitive-components/Port/Port.ts
|
|
9203
|
+
import { portProps } from "@tscircuit/props";
|
|
9204
|
+
|
|
9205
|
+
// lib/components/primitive-components/Port/apply-pin-attributes-to-source-port.ts
|
|
9206
|
+
var applyPinAttributesToSourcePort = (sourcePortProps, attributes) => {
|
|
9207
|
+
if (attributes.mustBeConnected !== void 0) {
|
|
9208
|
+
sourcePortProps.must_be_connected = attributes.mustBeConnected;
|
|
9209
|
+
}
|
|
9210
|
+
if (attributes.providesPower !== void 0) {
|
|
9211
|
+
sourcePortProps.provides_power = attributes.providesPower;
|
|
9212
|
+
}
|
|
9213
|
+
if (attributes.requiresPower !== void 0) {
|
|
9214
|
+
sourcePortProps.requires_power = attributes.requiresPower;
|
|
9215
|
+
}
|
|
9216
|
+
if (attributes.providesGround !== void 0) {
|
|
9217
|
+
sourcePortProps.provides_ground = attributes.providesGround;
|
|
9218
|
+
}
|
|
9219
|
+
if (attributes.requiresGround !== void 0) {
|
|
9220
|
+
sourcePortProps.requires_ground = attributes.requiresGround;
|
|
9221
|
+
}
|
|
9222
|
+
if (attributes.providesVoltage !== void 0) {
|
|
9223
|
+
sourcePortProps.provides_voltage = attributes.providesVoltage;
|
|
9224
|
+
}
|
|
9225
|
+
if (attributes.requiresVoltage !== void 0) {
|
|
9226
|
+
sourcePortProps.requires_voltage = attributes.requiresVoltage;
|
|
9227
|
+
}
|
|
9228
|
+
if (attributes.doNotConnect !== void 0) {
|
|
9229
|
+
sourcePortProps.do_not_connect = attributes.doNotConnect;
|
|
9230
|
+
}
|
|
9231
|
+
if (attributes.includeInBoardPinout !== void 0) {
|
|
9232
|
+
sourcePortProps.include_in_board_pinout = attributes.includeInBoardPinout;
|
|
9233
|
+
}
|
|
9234
|
+
if (attributes.canUseInternalPullup !== void 0) {
|
|
9235
|
+
sourcePortProps.can_use_internal_pullup = attributes.canUseInternalPullup;
|
|
9236
|
+
}
|
|
9237
|
+
if (attributes.isUsingInternalPullup !== void 0) {
|
|
9238
|
+
sourcePortProps.is_using_internal_pullup = attributes.isUsingInternalPullup;
|
|
9239
|
+
}
|
|
9240
|
+
if (attributes.needsExternalPullup !== void 0) {
|
|
9241
|
+
sourcePortProps.needs_external_pullup = attributes.needsExternalPullup;
|
|
9242
|
+
}
|
|
9243
|
+
if (attributes.canUseInternalPulldown !== void 0) {
|
|
9244
|
+
sourcePortProps.can_use_internal_pulldown = attributes.canUseInternalPulldown;
|
|
9245
|
+
}
|
|
9246
|
+
if (attributes.isUsingInternalPulldown !== void 0) {
|
|
9247
|
+
sourcePortProps.is_using_internal_pulldown = attributes.isUsingInternalPulldown;
|
|
9248
|
+
}
|
|
9249
|
+
if (attributes.needsExternalPulldown !== void 0) {
|
|
9250
|
+
sourcePortProps.needs_external_pulldown = attributes.needsExternalPulldown;
|
|
9251
|
+
}
|
|
9252
|
+
if (attributes.canUseOpenDrain !== void 0) {
|
|
9253
|
+
sourcePortProps.can_use_open_drain = attributes.canUseOpenDrain;
|
|
9254
|
+
}
|
|
9255
|
+
if (attributes.isUsingOpenDrain !== void 0) {
|
|
9256
|
+
sourcePortProps.is_using_open_drain = attributes.isUsingOpenDrain;
|
|
9257
|
+
}
|
|
9258
|
+
if (attributes.canUsePushPull !== void 0) {
|
|
9259
|
+
sourcePortProps.can_use_push_pull = attributes.canUsePushPull;
|
|
9260
|
+
}
|
|
9261
|
+
if (attributes.isUsingPushPull !== void 0) {
|
|
9262
|
+
sourcePortProps.is_using_push_pull = attributes.isUsingPushPull;
|
|
9263
|
+
}
|
|
9264
|
+
if (attributes.shouldHaveDecouplingCapacitor !== void 0) {
|
|
9265
|
+
sourcePortProps.should_have_decoupling_capacitor = attributes.shouldHaveDecouplingCapacitor;
|
|
9266
|
+
}
|
|
9267
|
+
if (attributes.recommendedDecouplingCapacitorCapacitance !== void 0) {
|
|
9268
|
+
sourcePortProps.recommended_decoupling_capacitor_capacitance = attributes.recommendedDecouplingCapacitorCapacitance;
|
|
9269
|
+
}
|
|
9270
|
+
};
|
|
9271
|
+
|
|
9272
|
+
// lib/components/primitive-components/Port/Port.ts
|
|
9273
|
+
var Port = class extends PrimitiveComponent2 {
|
|
9274
|
+
source_port_id = null;
|
|
9275
|
+
pcb_port_id = null;
|
|
9276
|
+
schematic_port_id = null;
|
|
9277
|
+
schematic_stem_line_id = null;
|
|
9278
|
+
schematicSymbolPortDef = null;
|
|
9279
|
+
matchedComponents;
|
|
9280
|
+
_isPrimaryPort = true;
|
|
9281
|
+
_primaryPinNumber = null;
|
|
9282
|
+
facingDirection = null;
|
|
9283
|
+
originDescription = null;
|
|
9181
9284
|
get config() {
|
|
9182
9285
|
return {
|
|
9183
|
-
componentName: "
|
|
9184
|
-
zodProps:
|
|
9286
|
+
componentName: "Port",
|
|
9287
|
+
zodProps: portProps
|
|
9185
9288
|
};
|
|
9186
9289
|
}
|
|
9187
|
-
|
|
9188
|
-
|
|
9189
|
-
|
|
9290
|
+
constructor(props, opts = {}) {
|
|
9291
|
+
if (!props.name && props.pinNumber !== void 0)
|
|
9292
|
+
props.name = `pin${props.pinNumber}`;
|
|
9293
|
+
if (!props.name) {
|
|
9294
|
+
throw new Error("Port must have a name or a pinNumber");
|
|
9295
|
+
}
|
|
9296
|
+
super(props);
|
|
9297
|
+
if (opts.originDescription) {
|
|
9298
|
+
this.originDescription = opts.originDescription;
|
|
9299
|
+
}
|
|
9300
|
+
this.matchedComponents = [];
|
|
9190
9301
|
}
|
|
9191
|
-
|
|
9192
|
-
|
|
9193
|
-
|
|
9194
|
-
|
|
9195
|
-
|
|
9196
|
-
|
|
9197
|
-
|
|
9198
|
-
const { db } = this.root;
|
|
9302
|
+
isGroupPort() {
|
|
9303
|
+
return this.parent?.componentName === "Group";
|
|
9304
|
+
}
|
|
9305
|
+
isComponentPort() {
|
|
9306
|
+
return !this.isGroupPort();
|
|
9307
|
+
}
|
|
9308
|
+
_getConnectedPortsFromConnectsTo() {
|
|
9199
9309
|
const { _parsedProps: props } = this;
|
|
9200
|
-
const
|
|
9201
|
-
|
|
9202
|
-
const
|
|
9203
|
-
|
|
9204
|
-
|
|
9205
|
-
|
|
9206
|
-
|
|
9310
|
+
const connectsTo = props.connectsTo;
|
|
9311
|
+
if (!connectsTo) return [];
|
|
9312
|
+
const connectedPorts = [];
|
|
9313
|
+
const connectsToArray = Array.isArray(connectsTo) ? connectsTo : [connectsTo];
|
|
9314
|
+
for (const connection of connectsToArray) {
|
|
9315
|
+
const port = this.getSubcircuit().selectOne(connection, {
|
|
9316
|
+
type: "port"
|
|
9317
|
+
});
|
|
9318
|
+
if (port) {
|
|
9319
|
+
connectedPorts.push(port);
|
|
9320
|
+
}
|
|
9321
|
+
}
|
|
9322
|
+
return connectedPorts;
|
|
9207
9323
|
}
|
|
9208
|
-
|
|
9209
|
-
|
|
9210
|
-
|
|
9324
|
+
_isBoardPinoutFromAttributes() {
|
|
9325
|
+
const parent = this.parent;
|
|
9326
|
+
if (parent?._parsedProps?.pinAttributes) {
|
|
9327
|
+
const pinAttributes = parent._parsedProps.pinAttributes;
|
|
9328
|
+
for (const alias of this.getNameAndAliases()) {
|
|
9329
|
+
if (pinAttributes[alias]?.includeInBoardPinout) {
|
|
9330
|
+
return true;
|
|
9331
|
+
}
|
|
9332
|
+
}
|
|
9211
9333
|
}
|
|
9212
|
-
this._computeSchematicSymbolBounds();
|
|
9213
|
-
return this.schematicSymbolBoundsInUserCoordinates ?? null;
|
|
9214
9334
|
}
|
|
9215
|
-
|
|
9216
|
-
|
|
9217
|
-
|
|
9335
|
+
_getGlobalPcbPositionBeforeLayout() {
|
|
9336
|
+
const matchedPcbElm = this.matchedComponents.find((c) => c.isPcbPrimitive);
|
|
9337
|
+
const parentComponent = this.parent;
|
|
9338
|
+
if (parentComponent && !parentComponent.props.footprint) {
|
|
9339
|
+
throw new Error(
|
|
9340
|
+
`${parentComponent.componentName} "${parentComponent.props.name}" does not have a footprint. Add a footprint prop, e.g. <${parentComponent.componentName.toLowerCase()} footprint="..." />`
|
|
9341
|
+
);
|
|
9218
9342
|
}
|
|
9219
|
-
if (
|
|
9220
|
-
|
|
9343
|
+
if (!matchedPcbElm) {
|
|
9344
|
+
throw new Error(
|
|
9345
|
+
`Port ${this} has no matching PCB primitives. This often means the footprint's pads lack matching port hints.`
|
|
9346
|
+
);
|
|
9221
9347
|
}
|
|
9222
|
-
|
|
9223
|
-
return this.userCoordinateToResizedSymbolTransformMat ?? null;
|
|
9348
|
+
return matchedPcbElm?._getGlobalPcbPositionBeforeLayout() ?? { x: 0, y: 0 };
|
|
9224
9349
|
}
|
|
9225
|
-
|
|
9226
|
-
if (this.
|
|
9350
|
+
_getPcbCircuitJsonBounds() {
|
|
9351
|
+
if (!this.pcb_port_id) {
|
|
9352
|
+
return super._getPcbCircuitJsonBounds();
|
|
9353
|
+
}
|
|
9227
9354
|
const { db } = this.root;
|
|
9228
|
-
const
|
|
9229
|
-
|
|
9230
|
-
|
|
9231
|
-
|
|
9232
|
-
|
|
9233
|
-
|
|
9234
|
-
|
|
9235
|
-
|
|
9236
|
-
|
|
9355
|
+
const pcb_port = db.pcb_port.get(this.pcb_port_id);
|
|
9356
|
+
return {
|
|
9357
|
+
center: { x: pcb_port.x, y: pcb_port.y },
|
|
9358
|
+
bounds: { left: 0, top: 0, right: 0, bottom: 0 },
|
|
9359
|
+
width: 0,
|
|
9360
|
+
height: 0
|
|
9361
|
+
};
|
|
9362
|
+
}
|
|
9363
|
+
_getGlobalPcbPositionAfterLayout() {
|
|
9364
|
+
return this._getPcbCircuitJsonBounds().center;
|
|
9365
|
+
}
|
|
9366
|
+
_getPortsInternallyConnectedToThisPort() {
|
|
9367
|
+
const parent = this.parent;
|
|
9368
|
+
if (!parent || !parent._getInternallyConnectedPins) return [];
|
|
9369
|
+
const internallyConnectedPorts = parent._getInternallyConnectedPins();
|
|
9370
|
+
for (const ports of internallyConnectedPorts) {
|
|
9371
|
+
if (ports.some((port) => port === this)) {
|
|
9372
|
+
return ports;
|
|
9237
9373
|
}
|
|
9238
|
-
|
|
9239
|
-
|
|
9240
|
-
|
|
9241
|
-
|
|
9242
|
-
|
|
9243
|
-
|
|
9244
|
-
|
|
9245
|
-
|
|
9246
|
-
|
|
9247
|
-
|
|
9248
|
-
|
|
9249
|
-
|
|
9250
|
-
|
|
9251
|
-
|
|
9252
|
-
|
|
9253
|
-
|
|
9254
|
-
|
|
9255
|
-
|
|
9256
|
-
|
|
9257
|
-
|
|
9258
|
-
|
|
9259
|
-
|
|
9260
|
-
|
|
9261
|
-
|
|
9262
|
-
|
|
9374
|
+
}
|
|
9375
|
+
return [];
|
|
9376
|
+
}
|
|
9377
|
+
/**
|
|
9378
|
+
* Return true if this port has a schematic representation and can be rendered
|
|
9379
|
+
* to the schematic.
|
|
9380
|
+
*
|
|
9381
|
+
* Sometimes things like mounting holes don't have a schematic representation
|
|
9382
|
+
* and aren't rendered to the schematic.
|
|
9383
|
+
*
|
|
9384
|
+
* It's common for a schematic symbol to not have a representation for all of
|
|
9385
|
+
* the pins on a footprint, e.g. a pushbutton has 4 pins but is typically
|
|
9386
|
+
* represented by a two-pin symbol. In these cases, it's best to use
|
|
9387
|
+
* internallyConnectedPorts or externallyConnectedPorts to ensure the things
|
|
9388
|
+
* are rendered properly.
|
|
9389
|
+
*/
|
|
9390
|
+
_hasSchematicPort() {
|
|
9391
|
+
const { schX, schY } = this._parsedProps;
|
|
9392
|
+
if (schX !== void 0 && schY !== void 0) {
|
|
9393
|
+
return true;
|
|
9394
|
+
}
|
|
9395
|
+
const parentNormalComponent = this.getParentNormalComponent();
|
|
9396
|
+
const symbol = parentNormalComponent?.getSchematicSymbol();
|
|
9397
|
+
if (symbol) {
|
|
9398
|
+
if (this.schematicSymbolPortDef) return true;
|
|
9399
|
+
const portsInternallyConnectedToThisPort = this._getPortsInternallyConnectedToThisPort();
|
|
9400
|
+
if (portsInternallyConnectedToThisPort.some((p) => p.schematicSymbolPortDef))
|
|
9401
|
+
return true;
|
|
9402
|
+
return false;
|
|
9403
|
+
}
|
|
9404
|
+
const parentBoxDim = parentNormalComponent?._getSchematicBoxDimensions();
|
|
9405
|
+
if (parentBoxDim && this._parsedProps.pinNumber !== void 0) {
|
|
9406
|
+
const localPortPosition = parentBoxDim.getPortPositionByPinNumber(
|
|
9407
|
+
this._parsedProps.pinNumber
|
|
9408
|
+
);
|
|
9409
|
+
if (localPortPosition) return true;
|
|
9410
|
+
}
|
|
9411
|
+
return false;
|
|
9412
|
+
}
|
|
9413
|
+
_getGlobalSchematicPositionBeforeLayout() {
|
|
9414
|
+
const { schX, schY } = this._parsedProps;
|
|
9415
|
+
if (schX !== void 0 && schY !== void 0) {
|
|
9416
|
+
return { x: schX, y: schY };
|
|
9417
|
+
}
|
|
9418
|
+
const parentNormalComponent = this.getParentNormalComponent();
|
|
9419
|
+
const symbol = parentNormalComponent?.getSchematicSymbol();
|
|
9420
|
+
if (symbol) {
|
|
9421
|
+
let schematicSymbolPortDef = this.schematicSymbolPortDef;
|
|
9422
|
+
if (!schematicSymbolPortDef) {
|
|
9423
|
+
schematicSymbolPortDef = this._getPortsInternallyConnectedToThisPort().find(
|
|
9424
|
+
(p) => p.schematicSymbolPortDef
|
|
9425
|
+
)?.schematicSymbolPortDef ?? null;
|
|
9426
|
+
if (!schematicSymbolPortDef) {
|
|
9427
|
+
throw new Error(
|
|
9428
|
+
`Couldn't find schematicSymbolPortDef for port ${this.getString()}, searched internally connected ports and none had a schematicSymbolPortDef. Why are we trying to get the schematic position of this port?`
|
|
9429
|
+
);
|
|
9263
9430
|
}
|
|
9264
9431
|
}
|
|
9432
|
+
const transform = compose3(
|
|
9433
|
+
parentNormalComponent.computeSchematicGlobalTransform(),
|
|
9434
|
+
translate2(-symbol.center.x, -symbol.center.y)
|
|
9435
|
+
);
|
|
9436
|
+
return applyToPoint22(transform, schematicSymbolPortDef);
|
|
9437
|
+
}
|
|
9438
|
+
const parentBoxDim = parentNormalComponent?._getSchematicBoxDimensions();
|
|
9439
|
+
if (parentBoxDim && this._parsedProps.pinNumber !== void 0) {
|
|
9440
|
+
const localPortPosition = parentBoxDim.getPortPositionByPinNumber(
|
|
9441
|
+
this._parsedProps.pinNumber
|
|
9442
|
+
);
|
|
9443
|
+
if (!localPortPosition) {
|
|
9444
|
+
throw new Error(
|
|
9445
|
+
`Couldn't find position for schematic_port for port ${this.getString()} inside of the schematic box`
|
|
9446
|
+
);
|
|
9447
|
+
}
|
|
9448
|
+
return applyToPoint22(
|
|
9449
|
+
parentNormalComponent.computeSchematicGlobalTransform(),
|
|
9450
|
+
localPortPosition
|
|
9451
|
+
);
|
|
9265
9452
|
}
|
|
9266
|
-
|
|
9267
|
-
|
|
9268
|
-
|
|
9453
|
+
throw new Error(
|
|
9454
|
+
`Couldn't find position for schematic_port for port ${this.getString()}`
|
|
9455
|
+
);
|
|
9269
9456
|
}
|
|
9270
|
-
|
|
9271
|
-
const
|
|
9272
|
-
if (!
|
|
9457
|
+
_getGlobalSchematicPositionAfterLayout() {
|
|
9458
|
+
const { db } = this.root;
|
|
9459
|
+
if (!this.schematic_port_id) {
|
|
9460
|
+
throw new Error(
|
|
9461
|
+
`Can't get schematic port position after layout for "${this.getString()}", no schematic_port_id`
|
|
9462
|
+
);
|
|
9463
|
+
}
|
|
9464
|
+
const schematic_port = db.schematic_port.get(this.schematic_port_id);
|
|
9465
|
+
if (!schematic_port)
|
|
9466
|
+
throw new Error(
|
|
9467
|
+
`Schematic port not found when trying to get post-layout position: ${this.schematic_port_id}`
|
|
9468
|
+
);
|
|
9469
|
+
return schematic_port.center;
|
|
9470
|
+
}
|
|
9471
|
+
/**
|
|
9472
|
+
* Smtpads and platedholes call this method to register themselves as a match
|
|
9473
|
+
* for this port. All the matching is done by primitives other than the Port,
|
|
9474
|
+
* but everyone registers themselves as a match with their Port.
|
|
9475
|
+
*/
|
|
9476
|
+
registerMatch(component) {
|
|
9477
|
+
this.matchedComponents.push(component);
|
|
9478
|
+
}
|
|
9479
|
+
getNameAndAliases() {
|
|
9273
9480
|
const { _parsedProps: props } = this;
|
|
9274
|
-
|
|
9275
|
-
|
|
9276
|
-
|
|
9277
|
-
|
|
9278
|
-
|
|
9279
|
-
|
|
9280
|
-
|
|
9281
|
-
const currentCenterY = (bounds.minY + bounds.maxY) / 2;
|
|
9282
|
-
const scaleX = targetWidth !== void 0 && currentWidth > 0 ? targetWidth / currentWidth : 1;
|
|
9283
|
-
const scaleY = targetHeight !== void 0 && currentHeight > 0 ? targetHeight / currentHeight : 1;
|
|
9284
|
-
const globalPos = this._getGlobalSchematicPositionBeforeLayout();
|
|
9285
|
-
this.userCoordinateToResizedSymbolTransformMat = compose3(
|
|
9286
|
-
translate2(globalPos.x, globalPos.y),
|
|
9287
|
-
scale(scaleX, scaleY),
|
|
9288
|
-
translate2(-currentCenterX, -currentCenterY)
|
|
9481
|
+
return Array.from(
|
|
9482
|
+
/* @__PURE__ */ new Set([
|
|
9483
|
+
...props.name ? [props.name] : [],
|
|
9484
|
+
...props.aliases ?? [],
|
|
9485
|
+
...typeof props.pinNumber === "number" ? [`pin${props.pinNumber}`, props.pinNumber.toString()] : [],
|
|
9486
|
+
...this.externallyAddedAliases ?? []
|
|
9487
|
+
])
|
|
9289
9488
|
);
|
|
9290
9489
|
}
|
|
9291
|
-
|
|
9292
|
-
|
|
9293
|
-
|
|
9294
|
-
|
|
9295
|
-
|
|
9296
|
-
|
|
9297
|
-
|
|
9298
|
-
|
|
9299
|
-
|
|
9300
|
-
|
|
9301
|
-
|
|
9302
|
-
|
|
9303
|
-
|
|
9304
|
-
|
|
9305
|
-
|
|
9306
|
-
|
|
9307
|
-
|
|
9490
|
+
_getMatchingPinAttributes() {
|
|
9491
|
+
const parentProps = this.parent?._parsedProps;
|
|
9492
|
+
const pinAttributes = parentProps?.pinAttributes;
|
|
9493
|
+
const noConnect = parentProps?.noConnect;
|
|
9494
|
+
const matches = [];
|
|
9495
|
+
for (const alias of this.getNameAndAliases()) {
|
|
9496
|
+
if (pinAttributes) {
|
|
9497
|
+
const attributes = pinAttributes[alias];
|
|
9498
|
+
if (attributes) {
|
|
9499
|
+
matches.push(attributes);
|
|
9500
|
+
}
|
|
9501
|
+
}
|
|
9502
|
+
if (noConnect?.includes(alias)) {
|
|
9503
|
+
matches.push({ doNotConnect: true });
|
|
9504
|
+
}
|
|
9505
|
+
}
|
|
9506
|
+
if (matches.length === 0) {
|
|
9507
|
+
return [];
|
|
9508
|
+
}
|
|
9509
|
+
return matches;
|
|
9308
9510
|
}
|
|
9309
|
-
|
|
9310
|
-
|
|
9311
|
-
|
|
9312
|
-
|
|
9313
|
-
pcbX: isNaN(elm.anchor_position.x) ? 0 : elm.anchor_position.x,
|
|
9314
|
-
pcbY: elm.anchor_position.y,
|
|
9315
|
-
pcbRotation: readableRotation ?? 0
|
|
9316
|
-
});
|
|
9317
|
-
silkscreenText._footprinterFontSize = elm.font_size + 0.2;
|
|
9318
|
-
return silkscreenText;
|
|
9319
|
-
};
|
|
9320
|
-
|
|
9321
|
-
// lib/utils/createComponentsFromCircuitJson.ts
|
|
9322
|
-
var calculateCcwRotation = (componentRotationStr, elementCcwRotation) => {
|
|
9323
|
-
const componentAngle = parseInt(componentRotationStr || "0", 10);
|
|
9324
|
-
let totalRotation;
|
|
9325
|
-
if (elementCcwRotation !== void 0 && elementCcwRotation !== null) {
|
|
9326
|
-
totalRotation = elementCcwRotation - componentAngle;
|
|
9327
|
-
} else {
|
|
9328
|
-
totalRotation = componentAngle;
|
|
9511
|
+
_shouldIncludeInBoardPinout() {
|
|
9512
|
+
return this._getMatchingPinAttributes().some(
|
|
9513
|
+
(attributes) => attributes.includeInBoardPinout === true
|
|
9514
|
+
);
|
|
9329
9515
|
}
|
|
9330
|
-
|
|
9331
|
-
|
|
9332
|
-
};
|
|
9333
|
-
var optional = (value) => value ?? void 0;
|
|
9334
|
-
var getFacingDirectionFromSide = (side) => {
|
|
9335
|
-
switch (side) {
|
|
9336
|
-
case "left":
|
|
9337
|
-
case "right":
|
|
9338
|
-
return side;
|
|
9339
|
-
case "top":
|
|
9340
|
-
return "up";
|
|
9341
|
-
case "bottom":
|
|
9342
|
-
return "down";
|
|
9516
|
+
isMatchingPort(port) {
|
|
9517
|
+
return this.isMatchingAnyOf(port.getNameAndAliases());
|
|
9343
9518
|
}
|
|
9344
|
-
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
componentName,
|
|
9348
|
-
componentRotation,
|
|
9349
|
-
footprinterString,
|
|
9350
|
-
pinLabels,
|
|
9351
|
-
pcbPinLabels
|
|
9352
|
-
}, circuitJson) => {
|
|
9353
|
-
const components = [];
|
|
9354
|
-
const schematicSymbolsByImportedId = /* @__PURE__ */ new Map();
|
|
9355
|
-
const schematicComponentsByImportedId = /* @__PURE__ */ new Map();
|
|
9356
|
-
for (const elm of circuitJson) {
|
|
9357
|
-
if (elm.type !== "schematic_symbol") continue;
|
|
9358
|
-
const schematicSymbol = new SymbolComponent({
|
|
9359
|
-
name: elm.name
|
|
9360
|
-
});
|
|
9361
|
-
schematicSymbolsByImportedId.set(elm.schematic_symbol_id, schematicSymbol);
|
|
9362
|
-
components.push(schematicSymbol);
|
|
9519
|
+
getPortSelector() {
|
|
9520
|
+
const parentComponent = this.getParentNormalComponent() ?? this.parent;
|
|
9521
|
+
return `.${parentComponent?.props.name} > port.${this.props.name}`;
|
|
9363
9522
|
}
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
|
|
9523
|
+
getAvailablePcbLayers() {
|
|
9524
|
+
const { layer, layers } = this._parsedProps;
|
|
9525
|
+
if (layers) return layers;
|
|
9526
|
+
if (layer) return [layer];
|
|
9527
|
+
return Array.from(
|
|
9528
|
+
new Set(this.matchedComponents.flatMap((c) => c.getAvailablePcbLayers()))
|
|
9529
|
+
);
|
|
9367
9530
|
}
|
|
9368
|
-
|
|
9369
|
-
|
|
9370
|
-
|
|
9371
|
-
|
|
9372
|
-
|
|
9373
|
-
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
9377
|
-
|
|
9378
|
-
|
|
9379
|
-
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
|
|
9399
|
-
|
|
9400
|
-
|
|
9401
|
-
|
|
9402
|
-
|
|
9403
|
-
|
|
9404
|
-
|
|
9405
|
-
|
|
9406
|
-
|
|
9407
|
-
|
|
9408
|
-
|
|
9409
|
-
|
|
9410
|
-
|
|
9411
|
-
|
|
9412
|
-
|
|
9413
|
-
})
|
|
9414
|
-
);
|
|
9415
|
-
} else if (elm.type === "pcb_smtpad" && elm.shape === "polygon") {
|
|
9416
|
-
components.push(
|
|
9417
|
-
new SmtPad({
|
|
9418
|
-
shape: "polygon",
|
|
9419
|
-
points: elm.points,
|
|
9420
|
-
portHints: elm.port_hints,
|
|
9421
|
-
layer: elm.layer
|
|
9422
|
-
})
|
|
9423
|
-
);
|
|
9424
|
-
} else if (elm.type === "pcb_silkscreen_path") {
|
|
9425
|
-
components.push(
|
|
9426
|
-
new SilkscreenPath({
|
|
9427
|
-
layer: elm.layer,
|
|
9428
|
-
route: elm.route,
|
|
9429
|
-
strokeWidth: elm.stroke_width
|
|
9430
|
-
})
|
|
9531
|
+
/**
|
|
9532
|
+
* Return traces that are explicitly connected to this port (not via a net)
|
|
9533
|
+
*/
|
|
9534
|
+
_getDirectlyConnectedTraces() {
|
|
9535
|
+
const allSubcircuitTraces = this.getSubcircuit().selectAll(
|
|
9536
|
+
"trace"
|
|
9537
|
+
);
|
|
9538
|
+
const connectedTraces = allSubcircuitTraces.filter((trace) => !trace._couldNotFindPort).filter((trace) => trace._isExplicitlyConnectedToPort(this));
|
|
9539
|
+
return connectedTraces;
|
|
9540
|
+
}
|
|
9541
|
+
doInitialSourceRender() {
|
|
9542
|
+
const { db } = this.root;
|
|
9543
|
+
const { _parsedProps: props } = this;
|
|
9544
|
+
const port_hints = this.getNameAndAliases();
|
|
9545
|
+
const parentNormalComponent = this.getParentNormalComponent();
|
|
9546
|
+
const parentWithSourceId = this.parent?.source_component_id ? this.parent : parentNormalComponent;
|
|
9547
|
+
const source_component_id = parentWithSourceId?.source_component_id ?? null;
|
|
9548
|
+
const pinAttributes = this._getMatchingPinAttributes();
|
|
9549
|
+
const portAttributesFromParent = {};
|
|
9550
|
+
for (const attributes of pinAttributes) {
|
|
9551
|
+
applyPinAttributesToSourcePort(portAttributesFromParent, attributes);
|
|
9552
|
+
}
|
|
9553
|
+
const source_port = db.source_port.insert({
|
|
9554
|
+
name: props.name,
|
|
9555
|
+
pin_number: props.pinNumber,
|
|
9556
|
+
port_hints,
|
|
9557
|
+
source_component_id,
|
|
9558
|
+
subcircuit_id: this.getSubcircuit()?.subcircuit_id,
|
|
9559
|
+
...portAttributesFromParent
|
|
9560
|
+
});
|
|
9561
|
+
this.source_port_id = source_port.source_port_id;
|
|
9562
|
+
}
|
|
9563
|
+
doInitialSourceParentAttachment() {
|
|
9564
|
+
const { db } = this.root;
|
|
9565
|
+
const parentNormalComponent = this.getParentNormalComponent();
|
|
9566
|
+
const parentWithSourceId = this.parent?.source_component_id ? this.parent : parentNormalComponent;
|
|
9567
|
+
if (this.isGroupPort()) {
|
|
9568
|
+
db.source_port.update(this.source_port_id, {
|
|
9569
|
+
source_component_id: null,
|
|
9570
|
+
subcircuit_id: this.getSubcircuit()?.subcircuit_id
|
|
9571
|
+
});
|
|
9572
|
+
return;
|
|
9573
|
+
}
|
|
9574
|
+
if (!parentWithSourceId?.source_component_id) {
|
|
9575
|
+
throw new Error(
|
|
9576
|
+
`${this.getString()} has no parent source component (parent: ${this.parent?.getString()})`
|
|
9431
9577
|
);
|
|
9432
|
-
}
|
|
9433
|
-
|
|
9434
|
-
|
|
9435
|
-
|
|
9436
|
-
|
|
9437
|
-
|
|
9438
|
-
|
|
9439
|
-
|
|
9440
|
-
|
|
9441
|
-
|
|
9442
|
-
|
|
9443
|
-
|
|
9444
|
-
|
|
9578
|
+
}
|
|
9579
|
+
db.source_port.update(this.source_port_id, {
|
|
9580
|
+
source_component_id: parentWithSourceId.source_component_id,
|
|
9581
|
+
subcircuit_id: this.getSubcircuit()?.subcircuit_id
|
|
9582
|
+
});
|
|
9583
|
+
this.source_component_id = parentWithSourceId.source_component_id;
|
|
9584
|
+
}
|
|
9585
|
+
doInitialPcbPortRender() {
|
|
9586
|
+
if (this.root?.pcbDisabled) return;
|
|
9587
|
+
const { db } = this.root;
|
|
9588
|
+
const { matchedComponents } = this;
|
|
9589
|
+
if (this.isGroupPort()) {
|
|
9590
|
+
const connectedPorts = this._getConnectedPortsFromConnectsTo();
|
|
9591
|
+
if (connectedPorts.length === 0) {
|
|
9592
|
+
return;
|
|
9593
|
+
}
|
|
9594
|
+
const connectedPort = connectedPorts[0];
|
|
9595
|
+
if (!connectedPort.pcb_port_id) {
|
|
9596
|
+
return;
|
|
9597
|
+
}
|
|
9598
|
+
const connectedPcbPort = db.pcb_port.get(connectedPort.pcb_port_id);
|
|
9599
|
+
const matchCenter2 = { x: connectedPcbPort.x, y: connectedPcbPort.y };
|
|
9600
|
+
const subcircuit = this.getSubcircuit();
|
|
9601
|
+
const pcb_port = db.pcb_port.insert({
|
|
9602
|
+
pcb_component_id: void 0,
|
|
9603
|
+
layers: connectedPort.getAvailablePcbLayers(),
|
|
9604
|
+
subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
|
|
9605
|
+
pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0,
|
|
9606
|
+
...matchCenter2,
|
|
9607
|
+
source_port_id: this.source_port_id,
|
|
9608
|
+
is_board_pinout: false
|
|
9609
|
+
});
|
|
9610
|
+
this.pcb_port_id = pcb_port.pcb_port_id;
|
|
9611
|
+
return;
|
|
9612
|
+
}
|
|
9613
|
+
const parentNormalComponent = this.getParentNormalComponent();
|
|
9614
|
+
const parentWithPcbComponentId = this.parent?.pcb_component_id ? this.parent : parentNormalComponent;
|
|
9615
|
+
if (!parentWithPcbComponentId?.pcb_component_id) {
|
|
9616
|
+
throw new Error(
|
|
9617
|
+
`${this.getString()} has no parent pcb component, cannot render pcb_port (parent: ${this.parent?.getString()}, parentNormalComponent: ${parentNormalComponent?.getString()})`
|
|
9445
9618
|
);
|
|
9446
|
-
}
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
|
|
9450
|
-
|
|
9451
|
-
|
|
9452
|
-
|
|
9453
|
-
|
|
9454
|
-
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
)
|
|
9458
|
-
|
|
9459
|
-
components.push(
|
|
9460
|
-
new PlatedHole({
|
|
9461
|
-
pcbX: elm.x,
|
|
9462
|
-
pcbY: elm.y,
|
|
9463
|
-
shape: "circular_hole_with_rect_pad",
|
|
9464
|
-
holeDiameter: elm.hole_diameter,
|
|
9465
|
-
rectPadHeight: elm.rect_pad_height,
|
|
9466
|
-
rectPadWidth: elm.rect_pad_width,
|
|
9467
|
-
portHints: elm.port_hints,
|
|
9468
|
-
rectBorderRadius: elm.rect_border_radius,
|
|
9469
|
-
holeOffsetX: elm.hole_offset_x,
|
|
9470
|
-
holeOffsetY: elm.hole_offset_y
|
|
9471
|
-
})
|
|
9472
|
-
);
|
|
9473
|
-
} else if (elm.shape === "pill" || elm.shape === "oval") {
|
|
9474
|
-
components.push(
|
|
9475
|
-
new PlatedHole({
|
|
9476
|
-
pcbX: elm.x,
|
|
9477
|
-
pcbY: elm.y,
|
|
9478
|
-
shape: elm.shape,
|
|
9479
|
-
holeWidth: elm.hole_width,
|
|
9480
|
-
holeHeight: elm.hole_height,
|
|
9481
|
-
outerWidth: elm.outer_width,
|
|
9482
|
-
outerHeight: elm.outer_height,
|
|
9483
|
-
portHints: elm.port_hints
|
|
9484
|
-
})
|
|
9485
|
-
);
|
|
9486
|
-
} else if (elm.shape === "pill_hole_with_rect_pad") {
|
|
9487
|
-
components.push(
|
|
9488
|
-
new PlatedHole({
|
|
9489
|
-
pcbX: elm.x,
|
|
9490
|
-
pcbY: elm.y,
|
|
9491
|
-
shape: "pill_hole_with_rect_pad",
|
|
9492
|
-
holeShape: "pill",
|
|
9493
|
-
padShape: "rect",
|
|
9494
|
-
holeWidth: elm.hole_width,
|
|
9495
|
-
holeHeight: elm.hole_height,
|
|
9496
|
-
rectPadWidth: elm.rect_pad_width,
|
|
9497
|
-
rectPadHeight: elm.rect_pad_height,
|
|
9498
|
-
rectBorderRadius: elm.rect_border_radius,
|
|
9499
|
-
portHints: elm.port_hints,
|
|
9500
|
-
holeOffsetX: elm.hole_offset_x,
|
|
9501
|
-
holeOffsetY: elm.hole_offset_y
|
|
9502
|
-
})
|
|
9503
|
-
);
|
|
9504
|
-
} else if (elm.shape === "rotated_pill_hole_with_rect_pad") {
|
|
9505
|
-
components.push(
|
|
9506
|
-
new PlatedHole({
|
|
9507
|
-
pcbX: elm.x,
|
|
9508
|
-
pcbY: elm.y,
|
|
9509
|
-
shape: "pill_hole_with_rect_pad",
|
|
9510
|
-
holeShape: "pill",
|
|
9511
|
-
padShape: "rect",
|
|
9512
|
-
holeWidth: elm.hole_width,
|
|
9513
|
-
holeHeight: elm.hole_height,
|
|
9514
|
-
rectPadWidth: elm.rect_pad_width,
|
|
9515
|
-
rectPadHeight: elm.rect_pad_height,
|
|
9516
|
-
rectBorderRadius: elm.rect_border_radius,
|
|
9517
|
-
portHints: elm.port_hints,
|
|
9518
|
-
holeOffsetX: elm.hole_offset_x,
|
|
9519
|
-
holeOffsetY: elm.hole_offset_y,
|
|
9520
|
-
pcbRotation: elm.hole_ccw_rotation
|
|
9521
|
-
})
|
|
9522
|
-
);
|
|
9523
|
-
} else if (elm.shape === "hole_with_polygon_pad") {
|
|
9524
|
-
components.push(
|
|
9525
|
-
new PlatedHole({
|
|
9526
|
-
pcbX: elm.x,
|
|
9527
|
-
pcbY: elm.y,
|
|
9528
|
-
shape: "hole_with_polygon_pad",
|
|
9529
|
-
holeShape: elm.hole_shape || "circle",
|
|
9530
|
-
holeDiameter: elm.hole_diameter,
|
|
9531
|
-
holeWidth: elm.hole_width,
|
|
9532
|
-
holeHeight: elm.hole_height,
|
|
9533
|
-
padOutline: elm.pad_outline || [],
|
|
9534
|
-
holeOffsetX: elm.hole_offset_x,
|
|
9535
|
-
holeOffsetY: elm.hole_offset_y,
|
|
9536
|
-
portHints: elm.port_hints
|
|
9537
|
-
})
|
|
9619
|
+
}
|
|
9620
|
+
const pcbMatches = matchedComponents.filter((c) => c.isPcbPrimitive);
|
|
9621
|
+
if (pcbMatches.length === 0) return;
|
|
9622
|
+
let matchCenter = null;
|
|
9623
|
+
if (pcbMatches.length === 1) {
|
|
9624
|
+
matchCenter = pcbMatches[0]._getPcbCircuitJsonBounds().center;
|
|
9625
|
+
}
|
|
9626
|
+
if (pcbMatches.length > 1) {
|
|
9627
|
+
if (!areAllPcbPrimitivesOverlapping(pcbMatches)) {
|
|
9628
|
+
const portName = this.props.name;
|
|
9629
|
+
const componentName = this.getParentNormalComponent()?.props.name ?? "unknown";
|
|
9630
|
+
const altAliases = this.getNameAndAliases().filter(
|
|
9631
|
+
(h) => h !== portName
|
|
9538
9632
|
);
|
|
9633
|
+
const altMsg = altAliases.length > 0 ? ` (consider using alternate aliases: ${altAliases.join(", ")})` : "";
|
|
9634
|
+
db.source_ambiguous_port_reference.insert({
|
|
9635
|
+
error_type: "source_ambiguous_port_reference",
|
|
9636
|
+
message: `${componentName}.${portName} is ambiguous: ${componentName}.${portName} references multiple non-overlapping pads: ${pcbMatches.map((c) => c.getString()).join(", ")}${altMsg}`,
|
|
9637
|
+
source_port_id: this.source_port_id ?? void 0,
|
|
9638
|
+
source_component_id: this.getParentNormalComponent()?.source_component_id ?? void 0
|
|
9639
|
+
});
|
|
9640
|
+
return;
|
|
9539
9641
|
}
|
|
9540
|
-
|
|
9541
|
-
|
|
9542
|
-
|
|
9543
|
-
|
|
9544
|
-
|
|
9545
|
-
|
|
9546
|
-
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
|
|
9550
|
-
|
|
9551
|
-
|
|
9552
|
-
|
|
9553
|
-
|
|
9554
|
-
shape: "rect",
|
|
9555
|
-
width: elm.width,
|
|
9556
|
-
height: elm.height
|
|
9557
|
-
})
|
|
9558
|
-
);
|
|
9559
|
-
} else if (elm.type === "pcb_hole" && elm.hole_shape === "circle") {
|
|
9560
|
-
components.push(
|
|
9561
|
-
new Hole({
|
|
9562
|
-
pcbX: elm.x,
|
|
9563
|
-
pcbY: elm.y,
|
|
9564
|
-
diameter: elm.hole_diameter
|
|
9565
|
-
})
|
|
9566
|
-
);
|
|
9567
|
-
} else if (elm.type === "pcb_hole" && elm.hole_shape === "rect") {
|
|
9568
|
-
components.push(
|
|
9569
|
-
new Hole({
|
|
9570
|
-
pcbX: elm.x,
|
|
9571
|
-
pcbY: elm.y,
|
|
9572
|
-
shape: "rect",
|
|
9573
|
-
width: elm.hole_width,
|
|
9574
|
-
height: elm.hole_height
|
|
9575
|
-
})
|
|
9576
|
-
);
|
|
9577
|
-
} else if (elm.type === "pcb_hole" && elm.hole_shape === "pill") {
|
|
9578
|
-
components.push(
|
|
9579
|
-
new Hole({
|
|
9580
|
-
pcbX: elm.x,
|
|
9581
|
-
pcbY: elm.y,
|
|
9582
|
-
shape: "pill",
|
|
9583
|
-
width: elm.hole_width,
|
|
9584
|
-
height: elm.hole_height
|
|
9585
|
-
})
|
|
9586
|
-
);
|
|
9587
|
-
} else if (elm.type === "pcb_hole" && elm.hole_shape === "oval") {
|
|
9588
|
-
components.push(
|
|
9589
|
-
new Hole({
|
|
9590
|
-
pcbX: elm.x,
|
|
9591
|
-
pcbY: elm.y,
|
|
9592
|
-
shape: "oval",
|
|
9593
|
-
width: elm.hole_width,
|
|
9594
|
-
height: elm.hole_height
|
|
9595
|
-
})
|
|
9596
|
-
);
|
|
9597
|
-
} else if (elm.type === "pcb_hole" && elm.hole_shape === "rotated_pill") {
|
|
9598
|
-
components.push(
|
|
9599
|
-
new Hole({
|
|
9600
|
-
pcbX: elm.x,
|
|
9601
|
-
pcbY: elm.y,
|
|
9602
|
-
shape: "pill",
|
|
9603
|
-
width: elm.hole_width,
|
|
9604
|
-
height: elm.hole_height,
|
|
9605
|
-
pcbRotation: elm.ccw_rotation
|
|
9606
|
-
})
|
|
9607
|
-
);
|
|
9608
|
-
} else if (elm.type === "pcb_cutout") {
|
|
9609
|
-
if (elm.shape === "rect") {
|
|
9610
|
-
components.push(
|
|
9611
|
-
new Cutout({
|
|
9612
|
-
pcbX: elm.center.x,
|
|
9613
|
-
pcbY: elm.center.y,
|
|
9614
|
-
shape: "rect",
|
|
9615
|
-
width: elm.width,
|
|
9616
|
-
height: elm.height
|
|
9617
|
-
})
|
|
9618
|
-
);
|
|
9619
|
-
} else if (elm.shape === "circle") {
|
|
9620
|
-
components.push(
|
|
9621
|
-
new Cutout({
|
|
9622
|
-
pcbX: elm.center.x,
|
|
9623
|
-
pcbY: elm.center.y,
|
|
9624
|
-
shape: "circle",
|
|
9625
|
-
radius: elm.radius
|
|
9626
|
-
})
|
|
9627
|
-
);
|
|
9628
|
-
} else if (elm.shape === "polygon") {
|
|
9629
|
-
components.push(
|
|
9630
|
-
new Cutout({
|
|
9631
|
-
shape: "polygon",
|
|
9632
|
-
points: elm.points
|
|
9633
|
-
})
|
|
9634
|
-
);
|
|
9635
|
-
}
|
|
9636
|
-
} else if (elm.type === "pcb_silkscreen_text") {
|
|
9637
|
-
const ccwRotation = calculateCcwRotation(
|
|
9638
|
-
componentRotation,
|
|
9639
|
-
elm.ccw_rotation
|
|
9640
|
-
);
|
|
9641
|
-
if (footprinterString?.includes("pinrow") && elm.text.includes("PIN")) {
|
|
9642
|
-
components.push(
|
|
9643
|
-
createPinrowSilkscreenText({
|
|
9644
|
-
elm,
|
|
9645
|
-
pinLabels: pcbPinLabels ?? pinLabels ?? {},
|
|
9646
|
-
layer: elm.layer,
|
|
9647
|
-
readableRotation: ccwRotation,
|
|
9648
|
-
anchorAlignment: elm.anchor_alignment
|
|
9649
|
-
})
|
|
9650
|
-
);
|
|
9651
|
-
} else {
|
|
9652
|
-
const silkscreenText = new SilkscreenText({
|
|
9653
|
-
anchorAlignment: elm.anchor_alignment || "center",
|
|
9654
|
-
text: componentName || elm.text,
|
|
9655
|
-
pcbX: Number.isNaN(elm.anchor_position.x) ? 0 : elm.anchor_position.x,
|
|
9656
|
-
pcbY: elm.anchor_position.y,
|
|
9657
|
-
pcbRotation: ccwRotation ?? 0
|
|
9658
|
-
});
|
|
9659
|
-
silkscreenText._footprinterFontSize = elm.font_size + 0.2;
|
|
9660
|
-
components.push(silkscreenText);
|
|
9661
|
-
}
|
|
9662
|
-
} else if (elm.type === "pcb_trace") {
|
|
9663
|
-
components.push(
|
|
9664
|
-
new PcbTrace({
|
|
9665
|
-
route: elm.route
|
|
9666
|
-
})
|
|
9667
|
-
);
|
|
9668
|
-
} else if (elm.type === "pcb_via") {
|
|
9669
|
-
const layers = elm.layers ?? [];
|
|
9670
|
-
const pcbVia = new PcbVia({
|
|
9671
|
-
pcbX: elm.x,
|
|
9672
|
-
pcbY: elm.y,
|
|
9673
|
-
holeDiameter: elm.hole_diameter,
|
|
9674
|
-
outerDiameter: elm.outer_diameter,
|
|
9675
|
-
fromLayer: elm.from_layer ?? layers[0],
|
|
9676
|
-
toLayer: elm.to_layer ?? layers[layers.length - 1],
|
|
9677
|
-
layers,
|
|
9678
|
-
netIsAssignable: elm.net_is_assignable,
|
|
9679
|
-
isTented: elm.is_tented
|
|
9642
|
+
matchCenter = getCenterOfPcbPrimitives(pcbMatches);
|
|
9643
|
+
}
|
|
9644
|
+
if (matchCenter) {
|
|
9645
|
+
const subcircuit = this.getSubcircuit();
|
|
9646
|
+
const isBoardPinout = this._shouldIncludeInBoardPinout();
|
|
9647
|
+
const pcb_port = db.pcb_port.insert({
|
|
9648
|
+
pcb_component_id: parentWithPcbComponentId.pcb_component_id,
|
|
9649
|
+
layers: this.getAvailablePcbLayers(),
|
|
9650
|
+
subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
|
|
9651
|
+
pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0,
|
|
9652
|
+
...isBoardPinout ? { is_board_pinout: true } : {},
|
|
9653
|
+
...matchCenter,
|
|
9654
|
+
source_port_id: this.source_port_id,
|
|
9655
|
+
is_board_pinout: this._isBoardPinoutFromAttributes()
|
|
9680
9656
|
});
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9686
|
-
pcbX: elm.center.x,
|
|
9687
|
-
pcbY: elm.center.y,
|
|
9688
|
-
width: elm.width,
|
|
9689
|
-
height: elm.height,
|
|
9690
|
-
layer: elm.layer,
|
|
9691
|
-
strokeWidth: elm.stroke_width,
|
|
9692
|
-
filled: elm.is_filled,
|
|
9693
|
-
cornerRadius: elm.corner_radius
|
|
9694
|
-
})
|
|
9695
|
-
);
|
|
9696
|
-
} else if (elm.type === "pcb_silkscreen_circle") {
|
|
9697
|
-
components.push(
|
|
9698
|
-
new SilkscreenCircle({
|
|
9699
|
-
pcbX: elm.center.x,
|
|
9700
|
-
pcbY: elm.center.y,
|
|
9701
|
-
radius: elm.radius,
|
|
9702
|
-
layer: elm.layer,
|
|
9703
|
-
strokeWidth: elm.stroke_width
|
|
9704
|
-
})
|
|
9705
|
-
);
|
|
9706
|
-
} else if (elm.type === "pcb_silkscreen_line") {
|
|
9707
|
-
components.push(
|
|
9708
|
-
new SilkscreenLine({
|
|
9709
|
-
x1: elm.x1,
|
|
9710
|
-
y1: elm.y1,
|
|
9711
|
-
x2: elm.x2,
|
|
9712
|
-
y2: elm.y2,
|
|
9713
|
-
layer: elm.layer,
|
|
9714
|
-
strokeWidth: elm.stroke_width
|
|
9715
|
-
})
|
|
9716
|
-
);
|
|
9717
|
-
} else if (elm.type === "pcb_fabrication_note_text") {
|
|
9718
|
-
components.push(
|
|
9719
|
-
new FabricationNoteText({
|
|
9720
|
-
pcbX: elm.anchor_position.x,
|
|
9721
|
-
pcbY: elm.anchor_position.y,
|
|
9722
|
-
text: elm.text,
|
|
9723
|
-
fontSize: elm.font_size,
|
|
9724
|
-
anchorAlignment: elm.anchor_alignment,
|
|
9725
|
-
color: elm.color,
|
|
9726
|
-
font: elm.font
|
|
9727
|
-
})
|
|
9728
|
-
);
|
|
9729
|
-
} else if (elm.type === "pcb_fabrication_note_path") {
|
|
9730
|
-
components.push(
|
|
9731
|
-
new FabricationNotePath({
|
|
9732
|
-
route: elm.route,
|
|
9733
|
-
strokeWidth: elm.stroke_width,
|
|
9734
|
-
color: elm.color,
|
|
9735
|
-
layer: elm.layer
|
|
9736
|
-
})
|
|
9737
|
-
);
|
|
9738
|
-
} else if (elm.type === "pcb_fabrication_note_rect") {
|
|
9739
|
-
components.push(
|
|
9740
|
-
new FabricationNoteRect({
|
|
9741
|
-
pcbX: elm.center.x,
|
|
9742
|
-
pcbY: elm.center.y,
|
|
9743
|
-
width: elm.width,
|
|
9744
|
-
height: elm.height,
|
|
9745
|
-
strokeWidth: elm.stroke_width,
|
|
9746
|
-
isFilled: elm.is_filled,
|
|
9747
|
-
color: elm.color,
|
|
9748
|
-
layer: elm.layer,
|
|
9749
|
-
cornerRadius: elm.corner_radius,
|
|
9750
|
-
hasStroke: elm.has_stroke,
|
|
9751
|
-
isStrokeDashed: elm.is_stroke_dashed
|
|
9752
|
-
})
|
|
9753
|
-
);
|
|
9754
|
-
} else if (elm.type === "pcb_note_text") {
|
|
9755
|
-
components.push(
|
|
9756
|
-
new PcbNoteText({
|
|
9757
|
-
pcbX: elm.anchor_position.x,
|
|
9758
|
-
pcbY: elm.anchor_position.y,
|
|
9759
|
-
text: elm.text ?? "",
|
|
9760
|
-
fontSize: elm.font_size,
|
|
9761
|
-
anchorAlignment: elm.anchor_alignment,
|
|
9762
|
-
color: elm.color,
|
|
9763
|
-
font: elm.font
|
|
9764
|
-
})
|
|
9765
|
-
);
|
|
9766
|
-
} else if (elm.type === "pcb_note_rect") {
|
|
9767
|
-
components.push(
|
|
9768
|
-
new PcbNoteRect({
|
|
9769
|
-
pcbX: elm.center.x,
|
|
9770
|
-
pcbY: elm.center.y,
|
|
9771
|
-
width: elm.width,
|
|
9772
|
-
height: elm.height,
|
|
9773
|
-
strokeWidth: elm.stroke_width,
|
|
9774
|
-
isFilled: elm.is_filled,
|
|
9775
|
-
color: elm.color,
|
|
9776
|
-
cornerRadius: elm.corner_radius,
|
|
9777
|
-
hasStroke: elm.has_stroke,
|
|
9778
|
-
isStrokeDashed: elm.is_stroke_dashed
|
|
9779
|
-
})
|
|
9780
|
-
);
|
|
9781
|
-
} else if (elm.type === "pcb_note_path") {
|
|
9782
|
-
components.push(
|
|
9783
|
-
new PcbNotePath({
|
|
9784
|
-
route: elm.route,
|
|
9785
|
-
strokeWidth: elm.stroke_width,
|
|
9786
|
-
color: elm.color
|
|
9787
|
-
})
|
|
9788
|
-
);
|
|
9789
|
-
} else if (elm.type === "pcb_note_line") {
|
|
9790
|
-
components.push(
|
|
9791
|
-
new PcbNoteLine({
|
|
9792
|
-
x1: elm.x1,
|
|
9793
|
-
y1: elm.y1,
|
|
9794
|
-
x2: elm.x2,
|
|
9795
|
-
y2: elm.y2,
|
|
9796
|
-
strokeWidth: elm.stroke_width,
|
|
9797
|
-
color: elm.color,
|
|
9798
|
-
isDashed: elm.is_dashed
|
|
9799
|
-
})
|
|
9800
|
-
);
|
|
9801
|
-
} else if (elm.type === "pcb_courtyard_rect") {
|
|
9802
|
-
components.push(
|
|
9803
|
-
new CourtyardRect({
|
|
9804
|
-
pcbX: elm.center.x,
|
|
9805
|
-
pcbY: elm.center.y,
|
|
9806
|
-
width: elm.width,
|
|
9807
|
-
height: elm.height,
|
|
9808
|
-
layer: elm.layer
|
|
9809
|
-
})
|
|
9810
|
-
);
|
|
9811
|
-
} else if (elm.type === "pcb_courtyard_circle") {
|
|
9812
|
-
components.push(
|
|
9813
|
-
new CourtyardCircle({
|
|
9814
|
-
pcbX: elm.center.x,
|
|
9815
|
-
pcbY: elm.center.y,
|
|
9816
|
-
radius: elm.radius,
|
|
9817
|
-
layer: elm.layer
|
|
9818
|
-
})
|
|
9819
|
-
);
|
|
9820
|
-
} else if (elm.type === "pcb_courtyard_outline") {
|
|
9821
|
-
components.push(
|
|
9822
|
-
new CourtyardOutline({
|
|
9823
|
-
outline: elm.outline,
|
|
9824
|
-
layer: elm.layer
|
|
9825
|
-
})
|
|
9826
|
-
);
|
|
9827
|
-
} else if (elm.type === "schematic_line") {
|
|
9828
|
-
addSchematicPrimitive(
|
|
9829
|
-
elm,
|
|
9830
|
-
new SchematicLine({
|
|
9831
|
-
x1: elm.x1,
|
|
9832
|
-
y1: elm.y1,
|
|
9833
|
-
x2: elm.x2,
|
|
9834
|
-
y2: elm.y2,
|
|
9835
|
-
strokeWidth: optional(elm.stroke_width),
|
|
9836
|
-
color: elm.color,
|
|
9837
|
-
isDashed: elm.is_dashed
|
|
9838
|
-
})
|
|
9839
|
-
);
|
|
9840
|
-
} else if (elm.type === "schematic_rect") {
|
|
9841
|
-
addSchematicPrimitive(
|
|
9842
|
-
elm,
|
|
9843
|
-
new SchematicRect({
|
|
9844
|
-
schX: elm.center.x,
|
|
9845
|
-
schY: elm.center.y,
|
|
9846
|
-
width: elm.width,
|
|
9847
|
-
height: elm.height,
|
|
9848
|
-
rotation: elm.rotation,
|
|
9849
|
-
strokeWidth: optional(elm.stroke_width),
|
|
9850
|
-
color: elm.color,
|
|
9851
|
-
isFilled: elm.is_filled,
|
|
9852
|
-
fillColor: elm.fill_color,
|
|
9853
|
-
isDashed: elm.is_dashed
|
|
9854
|
-
})
|
|
9855
|
-
);
|
|
9856
|
-
} else if (elm.type === "schematic_circle") {
|
|
9857
|
-
addSchematicPrimitive(
|
|
9858
|
-
elm,
|
|
9859
|
-
new SchematicCircle({
|
|
9860
|
-
center: elm.center,
|
|
9861
|
-
radius: elm.radius,
|
|
9862
|
-
strokeWidth: optional(elm.stroke_width),
|
|
9863
|
-
color: elm.color,
|
|
9864
|
-
isFilled: elm.is_filled,
|
|
9865
|
-
fillColor: elm.fill_color,
|
|
9866
|
-
isDashed: elm.is_dashed
|
|
9867
|
-
})
|
|
9868
|
-
);
|
|
9869
|
-
} else if (elm.type === "schematic_arc") {
|
|
9870
|
-
addSchematicPrimitive(
|
|
9871
|
-
elm,
|
|
9872
|
-
new SchematicArc({
|
|
9873
|
-
center: elm.center,
|
|
9874
|
-
radius: elm.radius,
|
|
9875
|
-
startAngleDegrees: elm.start_angle_degrees,
|
|
9876
|
-
endAngleDegrees: elm.end_angle_degrees,
|
|
9877
|
-
direction: elm.direction,
|
|
9878
|
-
strokeWidth: optional(elm.stroke_width),
|
|
9879
|
-
color: elm.color,
|
|
9880
|
-
isDashed: elm.is_dashed
|
|
9881
|
-
})
|
|
9882
|
-
);
|
|
9883
|
-
} else if (elm.type === "schematic_text") {
|
|
9884
|
-
addSchematicPrimitive(
|
|
9885
|
-
elm,
|
|
9886
|
-
new SchematicText({
|
|
9887
|
-
schX: elm.position.x,
|
|
9888
|
-
schY: elm.position.y,
|
|
9889
|
-
text: elm.text,
|
|
9890
|
-
fontSize: elm.font_size,
|
|
9891
|
-
anchor: elm.anchor,
|
|
9892
|
-
color: elm.color,
|
|
9893
|
-
schRotation: elm.rotation
|
|
9894
|
-
})
|
|
9895
|
-
);
|
|
9896
|
-
} else if (elm.type === "schematic_path") {
|
|
9897
|
-
addSchematicPrimitive(
|
|
9898
|
-
elm,
|
|
9899
|
-
new SchematicPath({
|
|
9900
|
-
points: elm.points,
|
|
9901
|
-
strokeWidth: optional(elm.stroke_width),
|
|
9902
|
-
strokeColor: elm.stroke_color,
|
|
9903
|
-
dashLength: elm.dash_length,
|
|
9904
|
-
dashGap: elm.dash_gap,
|
|
9905
|
-
isFilled: elm.is_filled,
|
|
9906
|
-
fillColor: elm.fill_color
|
|
9907
|
-
})
|
|
9657
|
+
this.pcb_port_id = pcb_port.pcb_port_id;
|
|
9658
|
+
} else {
|
|
9659
|
+
const pcbMatch = pcbMatches[0];
|
|
9660
|
+
throw new Error(
|
|
9661
|
+
`${pcbMatch.getString()} does not have a center or _getGlobalPcbPositionBeforeLayout method (needed for pcb_port placement)`
|
|
9908
9662
|
);
|
|
9909
|
-
}
|
|
9910
|
-
|
|
9911
|
-
|
|
9912
|
-
|
|
9913
|
-
|
|
9914
|
-
|
|
9915
|
-
|
|
9916
|
-
|
|
9917
|
-
|
|
9918
|
-
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
|
|
9922
|
-
|
|
9923
|
-
|
|
9924
|
-
|
|
9925
|
-
|
|
9926
|
-
|
|
9927
|
-
|
|
9928
|
-
|
|
9929
|
-
|
|
9930
|
-
|
|
9931
|
-
|
|
9932
|
-
|
|
9933
|
-
|
|
9934
|
-
|
|
9935
|
-
|
|
9663
|
+
}
|
|
9664
|
+
}
|
|
9665
|
+
updatePcbPortRender() {
|
|
9666
|
+
if (this.root?.pcbDisabled) return;
|
|
9667
|
+
const { db } = this.root;
|
|
9668
|
+
if (this.pcb_port_id) return;
|
|
9669
|
+
if (this.isGroupPort()) {
|
|
9670
|
+
const connectedPorts = this._getConnectedPortsFromConnectsTo();
|
|
9671
|
+
if (connectedPorts.length === 0) return;
|
|
9672
|
+
const connectedPort = connectedPorts[0];
|
|
9673
|
+
if (!connectedPort.pcb_port_id) return;
|
|
9674
|
+
const connectedPcbPort = db.pcb_port.get(connectedPort.pcb_port_id);
|
|
9675
|
+
const matchCenter2 = { x: connectedPcbPort.x, y: connectedPcbPort.y };
|
|
9676
|
+
const subcircuit2 = this.getSubcircuit();
|
|
9677
|
+
const pcb_port2 = db.pcb_port.insert({
|
|
9678
|
+
pcb_component_id: void 0,
|
|
9679
|
+
layers: connectedPort.getAvailablePcbLayers(),
|
|
9680
|
+
subcircuit_id: subcircuit2?.subcircuit_id ?? void 0,
|
|
9681
|
+
pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0,
|
|
9682
|
+
...matchCenter2,
|
|
9683
|
+
source_port_id: this.source_port_id,
|
|
9684
|
+
is_board_pinout: false
|
|
9685
|
+
});
|
|
9686
|
+
this.pcb_port_id = pcb_port2.pcb_port_id;
|
|
9687
|
+
return;
|
|
9688
|
+
}
|
|
9689
|
+
const pcbMatches = this.matchedComponents.filter((c) => c.isPcbPrimitive);
|
|
9690
|
+
if (pcbMatches.length === 0) return;
|
|
9691
|
+
let matchCenter = null;
|
|
9692
|
+
if (pcbMatches.length === 1) {
|
|
9693
|
+
matchCenter = pcbMatches[0]._getPcbCircuitJsonBounds().center;
|
|
9694
|
+
}
|
|
9695
|
+
if (pcbMatches.length > 1) {
|
|
9696
|
+
try {
|
|
9697
|
+
if (areAllPcbPrimitivesOverlapping(pcbMatches)) {
|
|
9698
|
+
matchCenter = getCenterOfPcbPrimitives(pcbMatches);
|
|
9699
|
+
}
|
|
9700
|
+
} catch {
|
|
9936
9701
|
}
|
|
9937
9702
|
}
|
|
9703
|
+
if (!matchCenter) return;
|
|
9704
|
+
const parentNormalComponent = this.getParentNormalComponent();
|
|
9705
|
+
const parentWithPcbComponentId = this.parent?.pcb_component_id ? this.parent : parentNormalComponent;
|
|
9706
|
+
const subcircuit = this.getSubcircuit();
|
|
9707
|
+
const isBoardPinout = this._shouldIncludeInBoardPinout();
|
|
9708
|
+
const pcb_port = db.pcb_port.insert({
|
|
9709
|
+
pcb_component_id: parentWithPcbComponentId?.pcb_component_id,
|
|
9710
|
+
layers: this.getAvailablePcbLayers(),
|
|
9711
|
+
subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
|
|
9712
|
+
pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0,
|
|
9713
|
+
...isBoardPinout ? { is_board_pinout: true } : {},
|
|
9714
|
+
...matchCenter,
|
|
9715
|
+
source_port_id: this.source_port_id,
|
|
9716
|
+
is_board_pinout: this._isBoardPinoutFromAttributes()
|
|
9717
|
+
});
|
|
9718
|
+
this.pcb_port_id = pcb_port.pcb_port_id;
|
|
9938
9719
|
}
|
|
9939
|
-
|
|
9940
|
-
|
|
9941
|
-
|
|
9942
|
-
|
|
9943
|
-
|
|
9944
|
-
|
|
9945
|
-
|
|
9946
|
-
|
|
9947
|
-
|
|
9948
|
-
|
|
9949
|
-
|
|
9950
|
-
|
|
9951
|
-
|
|
9952
|
-
for (const [pin, labelOrLabels] of Object.entries(pinLabels)) {
|
|
9953
|
-
const labels = Array.isArray(labelOrLabels) ? labelOrLabels.slice() : [labelOrLabels];
|
|
9954
|
-
const validLabels = [];
|
|
9955
|
-
for (const label of labels) {
|
|
9956
|
-
if (isValidPinLabel(pin, label)) {
|
|
9957
|
-
validLabels.push(label);
|
|
9958
|
-
} else {
|
|
9959
|
-
invalidPinLabelsMessages.push(
|
|
9960
|
-
`Invalid pin label: ${pin} = '${label}' - excluding from component. Pin labels can only contain letters, numbers and underscores.`
|
|
9961
|
-
);
|
|
9962
|
-
}
|
|
9720
|
+
/**
|
|
9721
|
+
* Get the best display label for this port based on port_hints
|
|
9722
|
+
* Filters out generic patterns and applies showPinAliases logic
|
|
9723
|
+
*/
|
|
9724
|
+
_getBestDisplayPinLabel() {
|
|
9725
|
+
const { db } = this.root;
|
|
9726
|
+
const sourcePort = db.source_port.get(this.source_port_id);
|
|
9727
|
+
const labelHints = [];
|
|
9728
|
+
for (const portHint of sourcePort?.port_hints ?? []) {
|
|
9729
|
+
if (portHint.match(/^(pin)?\d+$/)) continue;
|
|
9730
|
+
if (portHint.match(/^(left|right)/) && !sourcePort?.name.match(/^(left|right)/))
|
|
9731
|
+
continue;
|
|
9732
|
+
labelHints.push(portHint);
|
|
9963
9733
|
}
|
|
9964
|
-
|
|
9965
|
-
|
|
9734
|
+
const parentNormalComponent = this.getParentNormalComponent();
|
|
9735
|
+
const showPinAliases = parentNormalComponent?.props?.showPinAliases;
|
|
9736
|
+
if (showPinAliases && labelHints.length > 0) {
|
|
9737
|
+
return labelHints.join("/");
|
|
9738
|
+
} else if (labelHints.length > 0) {
|
|
9739
|
+
return labelHints[0];
|
|
9966
9740
|
}
|
|
9741
|
+
return void 0;
|
|
9967
9742
|
}
|
|
9968
|
-
|
|
9969
|
-
|
|
9970
|
-
|
|
9971
|
-
|
|
9972
|
-
}
|
|
9973
|
-
|
|
9974
|
-
|
|
9975
|
-
|
|
9976
|
-
|
|
9977
|
-
|
|
9978
|
-
|
|
9979
|
-
|
|
9980
|
-
const
|
|
9981
|
-
|
|
9982
|
-
|
|
9983
|
-
|
|
9984
|
-
|
|
9985
|
-
|
|
9986
|
-
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
|
|
9990
|
-
|
|
9991
|
-
|
|
9992
|
-
|
|
9993
|
-
|
|
9994
|
-
|
|
9995
|
-
|
|
9996
|
-
|
|
9997
|
-
|
|
9998
|
-
|
|
9999
|
-
|
|
10000
|
-
|
|
10001
|
-
|
|
10002
|
-
|
|
10003
|
-
|
|
10004
|
-
|
|
10005
|
-
|
|
10006
|
-
|
|
10007
|
-
|
|
10008
|
-
|
|
10009
|
-
|
|
10010
|
-
|
|
10011
|
-
|
|
10012
|
-
|
|
10013
|
-
|
|
10014
|
-
|
|
10015
|
-
|
|
10016
|
-
|
|
10017
|
-
|
|
10018
|
-
|
|
10019
|
-
|
|
9743
|
+
doInitialSchematicPortRender() {
|
|
9744
|
+
const collapsedAncestor = this.getCollapsedSchematicBoxAncestor();
|
|
9745
|
+
if (collapsedAncestor && this.parent !== collapsedAncestor) return;
|
|
9746
|
+
const { db } = this.root;
|
|
9747
|
+
const { _parsedProps: props } = this;
|
|
9748
|
+
const { schX, schY } = props;
|
|
9749
|
+
const container = schX !== void 0 && schY !== void 0 ? this.getParentNormalComponent() : this.getPrimitiveContainer();
|
|
9750
|
+
if (!container) return;
|
|
9751
|
+
if (!this._hasSchematicPort()) return;
|
|
9752
|
+
const containerCenter = container._getGlobalSchematicPositionBeforeLayout();
|
|
9753
|
+
const portCenter = this._getGlobalSchematicPositionBeforeLayout();
|
|
9754
|
+
let localPortInfo = null;
|
|
9755
|
+
const containerDims = container._getSchematicBoxDimensions();
|
|
9756
|
+
if (containerDims && props.pinNumber !== void 0) {
|
|
9757
|
+
localPortInfo = containerDims.getPortPositionByPinNumber(props.pinNumber);
|
|
9758
|
+
}
|
|
9759
|
+
if (this.getSubcircuit().props._schDebugObjectsEnabled) {
|
|
9760
|
+
db.schematic_debug_object.insert({
|
|
9761
|
+
shape: "rect",
|
|
9762
|
+
center: portCenter,
|
|
9763
|
+
size: {
|
|
9764
|
+
width: 0.1,
|
|
9765
|
+
height: 0.1
|
|
9766
|
+
},
|
|
9767
|
+
label: "obstacle"
|
|
9768
|
+
});
|
|
9769
|
+
}
|
|
9770
|
+
if (!localPortInfo?.side) {
|
|
9771
|
+
this.facingDirection = getRelativeDirection(containerCenter, portCenter);
|
|
9772
|
+
} else {
|
|
9773
|
+
this.facingDirection = {
|
|
9774
|
+
left: "left",
|
|
9775
|
+
right: "right",
|
|
9776
|
+
top: "up",
|
|
9777
|
+
bottom: "down"
|
|
9778
|
+
}[localPortInfo.side];
|
|
9779
|
+
}
|
|
9780
|
+
const bestDisplayPinLabel = this._getBestDisplayPinLabel();
|
|
9781
|
+
const parentNormalComponent = this.getParentNormalComponent();
|
|
9782
|
+
const sideOfComponent = localPortInfo?.side ?? (props.direction === "up" ? "top" : props.direction === "down" ? "bottom" : props.direction);
|
|
9783
|
+
const schematicPortInsertProps = {
|
|
9784
|
+
type: "schematic_port",
|
|
9785
|
+
schematic_component_id: parentNormalComponent?.schematic_component_id,
|
|
9786
|
+
center: portCenter,
|
|
9787
|
+
source_port_id: this.source_port_id,
|
|
9788
|
+
facing_direction: this.facingDirection,
|
|
9789
|
+
distance_from_component_edge: props.schStemLength ?? 0.4,
|
|
9790
|
+
side_of_component: sideOfComponent,
|
|
9791
|
+
pin_number: props.pinNumber,
|
|
9792
|
+
true_ccw_index: localPortInfo?.trueIndex,
|
|
9793
|
+
display_pin_label: bestDisplayPinLabel,
|
|
9794
|
+
is_connected: false
|
|
9795
|
+
};
|
|
9796
|
+
for (const attributes of this._getMatchingPinAttributes()) {
|
|
9797
|
+
if (attributes.requiresPower) {
|
|
9798
|
+
schematicPortInsertProps.has_input_arrow = true;
|
|
9799
|
+
}
|
|
9800
|
+
if (attributes.providesPower) {
|
|
9801
|
+
schematicPortInsertProps.has_output_arrow = true;
|
|
9802
|
+
}
|
|
9803
|
+
}
|
|
9804
|
+
const schematic_port = db.schematic_port.insert(schematicPortInsertProps);
|
|
9805
|
+
this.schematic_port_id = schematic_port.schematic_port_id;
|
|
9806
|
+
if (props.schStemLength !== void 0 && props.schStemLength !== 0) {
|
|
9807
|
+
const { schStemLength, direction } = props;
|
|
9808
|
+
let x2 = portCenter.x;
|
|
9809
|
+
let y2 = portCenter.y;
|
|
9810
|
+
if (direction === "right") x2 -= schStemLength;
|
|
9811
|
+
else if (direction === "left") x2 += schStemLength;
|
|
9812
|
+
else if (direction === "up") y2 -= schStemLength;
|
|
9813
|
+
else if (direction === "down") y2 += schStemLength;
|
|
9814
|
+
const stemLine = db.schematic_line.insert({
|
|
9815
|
+
schematic_component_id: parentNormalComponent?.schematic_component_id,
|
|
9816
|
+
x1: portCenter.x,
|
|
9817
|
+
y1: portCenter.y,
|
|
9818
|
+
x2,
|
|
9819
|
+
y2,
|
|
9820
|
+
stroke_width: 0.02,
|
|
9821
|
+
color: SCHEMATIC_COMPONENT_OUTLINE_COLOR,
|
|
9822
|
+
is_dashed: false
|
|
9823
|
+
});
|
|
9824
|
+
this.schematic_stem_line_id = stemLine.schematic_line_id;
|
|
10020
9825
|
}
|
|
10021
9826
|
}
|
|
10022
|
-
|
|
10023
|
-
return
|
|
10024
|
-
|
|
10025
|
-
|
|
10026
|
-
|
|
10027
|
-
|
|
10028
|
-
|
|
10029
|
-
|
|
10030
|
-
|
|
10031
|
-
|
|
10032
|
-
|
|
10033
|
-
|
|
10034
|
-
|
|
10035
|
-
|
|
10036
|
-
|
|
10037
|
-
|
|
10038
|
-
|
|
10039
|
-
|
|
10040
|
-
|
|
10041
|
-
|
|
10042
|
-
|
|
10043
|
-
|
|
10044
|
-
|
|
10045
|
-
|
|
10046
|
-
|
|
10047
|
-
|
|
10048
|
-
|
|
10049
|
-
|
|
10050
|
-
|
|
10051
|
-
|
|
10052
|
-
|
|
10053
|
-
|
|
10054
|
-
}
|
|
10055
|
-
|
|
10056
|
-
// lib/components/primitive-components/Port/Port.ts
|
|
10057
|
-
import "schematic-symbols";
|
|
10058
|
-
import { applyToPoint as applyToPoint22, compose as compose4, translate as translate3 } from "transformation-matrix";
|
|
10059
|
-
import "zod";
|
|
10060
|
-
|
|
10061
|
-
// lib/components/primitive-components/Port/getCenterOfPcbPrimitives.ts
|
|
10062
|
-
var getCenterOfPcbPrimitives = (pcbPrimitives) => {
|
|
10063
|
-
if (pcbPrimitives.length === 0) {
|
|
10064
|
-
throw new Error("Cannot get center of empty PCB primitives array");
|
|
10065
|
-
}
|
|
10066
|
-
const positions = pcbPrimitives.map((p) => p._getPcbCircuitJsonBounds().center).filter(Boolean);
|
|
10067
|
-
const sumX = positions.reduce((sum, pos) => sum + pos.x, 0);
|
|
10068
|
-
const sumY = positions.reduce((sum, pos) => sum + pos.y, 0);
|
|
10069
|
-
return {
|
|
10070
|
-
x: sumX / positions.length,
|
|
10071
|
-
y: sumY / positions.length
|
|
10072
|
-
};
|
|
10073
|
-
};
|
|
10074
|
-
|
|
10075
|
-
// lib/components/primitive-components/Port/Port.ts
|
|
10076
|
-
import { portProps } from "@tscircuit/props";
|
|
10077
|
-
|
|
10078
|
-
// lib/components/primitive-components/Port/apply-pin-attributes-to-source-port.ts
|
|
10079
|
-
var applyPinAttributesToSourcePort = (sourcePortProps, attributes) => {
|
|
10080
|
-
if (attributes.mustBeConnected !== void 0) {
|
|
10081
|
-
sourcePortProps.must_be_connected = attributes.mustBeConnected;
|
|
10082
|
-
}
|
|
10083
|
-
if (attributes.providesPower !== void 0) {
|
|
10084
|
-
sourcePortProps.provides_power = attributes.providesPower;
|
|
10085
|
-
}
|
|
10086
|
-
if (attributes.requiresPower !== void 0) {
|
|
10087
|
-
sourcePortProps.requires_power = attributes.requiresPower;
|
|
10088
|
-
}
|
|
10089
|
-
if (attributes.providesGround !== void 0) {
|
|
10090
|
-
sourcePortProps.provides_ground = attributes.providesGround;
|
|
10091
|
-
}
|
|
10092
|
-
if (attributes.requiresGround !== void 0) {
|
|
10093
|
-
sourcePortProps.requires_ground = attributes.requiresGround;
|
|
10094
|
-
}
|
|
10095
|
-
if (attributes.providesVoltage !== void 0) {
|
|
10096
|
-
sourcePortProps.provides_voltage = attributes.providesVoltage;
|
|
10097
|
-
}
|
|
10098
|
-
if (attributes.requiresVoltage !== void 0) {
|
|
10099
|
-
sourcePortProps.requires_voltage = attributes.requiresVoltage;
|
|
10100
|
-
}
|
|
10101
|
-
if (attributes.doNotConnect !== void 0) {
|
|
10102
|
-
sourcePortProps.do_not_connect = attributes.doNotConnect;
|
|
9827
|
+
doInitialSchematicSymbolResize() {
|
|
9828
|
+
if (this.root?.schematicDisabled) return;
|
|
9829
|
+
if (!this.schematic_port_id) return;
|
|
9830
|
+
const symbol = this._getSymbolAncestor();
|
|
9831
|
+
const transform = symbol?.getUserCoordinateToResizedSymbolTransform();
|
|
9832
|
+
if (!transform) return;
|
|
9833
|
+
const { db } = this.root;
|
|
9834
|
+
const schPort = db.schematic_port.get(this.schematic_port_id);
|
|
9835
|
+
if (schPort) {
|
|
9836
|
+
const newCenter = applyToPoint22(transform, schPort.center);
|
|
9837
|
+
db.schematic_port.update(this.schematic_port_id, {
|
|
9838
|
+
center: newCenter
|
|
9839
|
+
});
|
|
9840
|
+
if (this.schematic_stem_line_id) {
|
|
9841
|
+
const line = db.schematic_line.get(this.schematic_stem_line_id);
|
|
9842
|
+
if (line) {
|
|
9843
|
+
const p1 = applyToPoint22(transform, { x: line.x1, y: line.y1 });
|
|
9844
|
+
const p2 = applyToPoint22(transform, { x: line.x2, y: line.y2 });
|
|
9845
|
+
db.schematic_line.update(this.schematic_stem_line_id, {
|
|
9846
|
+
x1: p1.x,
|
|
9847
|
+
y1: p1.y,
|
|
9848
|
+
x2: p2.x,
|
|
9849
|
+
y2: p2.y
|
|
9850
|
+
});
|
|
9851
|
+
const scaledStemLength = Math.sqrt(
|
|
9852
|
+
(p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2
|
|
9853
|
+
);
|
|
9854
|
+
db.schematic_port.update(this.schematic_port_id, {
|
|
9855
|
+
distance_from_component_edge: scaledStemLength
|
|
9856
|
+
});
|
|
9857
|
+
}
|
|
9858
|
+
}
|
|
9859
|
+
}
|
|
10103
9860
|
}
|
|
10104
|
-
|
|
10105
|
-
|
|
9861
|
+
_getSubcircuitConnectivityKey() {
|
|
9862
|
+
return this.root?.db.source_port.get(this.source_port_id)?.subcircuit_connectivity_map_key;
|
|
10106
9863
|
}
|
|
10107
|
-
|
|
10108
|
-
|
|
9864
|
+
_setPositionFromLayout(newCenter) {
|
|
9865
|
+
const { db } = this.root;
|
|
9866
|
+
if (!this.pcb_port_id) return;
|
|
9867
|
+
db.pcb_port.update(this.pcb_port_id, {
|
|
9868
|
+
x: newCenter.x,
|
|
9869
|
+
y: newCenter.y
|
|
9870
|
+
});
|
|
10109
9871
|
}
|
|
10110
|
-
|
|
10111
|
-
|
|
9872
|
+
_hasMatchedPcbPrimitive() {
|
|
9873
|
+
return this.matchedComponents.some((c) => c.isPcbPrimitive);
|
|
10112
9874
|
}
|
|
10113
|
-
|
|
10114
|
-
|
|
9875
|
+
/**
|
|
9876
|
+
* Return the text that should be used for the net label for this port if a
|
|
9877
|
+
* trace can't be drawn. This net label text usually doesn't appear at this
|
|
9878
|
+
* port, but appears at the port it connects to.
|
|
9879
|
+
*/
|
|
9880
|
+
_getNetLabelText() {
|
|
9881
|
+
return `${this.parent?.props.name}_${this.props.name}`;
|
|
10115
9882
|
}
|
|
10116
|
-
|
|
10117
|
-
|
|
9883
|
+
};
|
|
9884
|
+
|
|
9885
|
+
// lib/components/primitive-components/Symbol/Symbol.ts
|
|
9886
|
+
import { symbolProps } from "@tscircuit/props";
|
|
9887
|
+
import { compose as compose4, translate as translate3, scale } from "transformation-matrix";
|
|
9888
|
+
var SymbolComponent = class extends PrimitiveComponent2 {
|
|
9889
|
+
isPrimitiveContainer = true;
|
|
9890
|
+
schematic_symbol_id;
|
|
9891
|
+
userCoordinateToResizedSymbolTransformMat;
|
|
9892
|
+
schematicSymbolBoundsInUserCoordinates;
|
|
9893
|
+
get config() {
|
|
9894
|
+
return {
|
|
9895
|
+
componentName: "Symbol",
|
|
9896
|
+
zodProps: symbolProps
|
|
9897
|
+
};
|
|
10118
9898
|
}
|
|
10119
|
-
|
|
10120
|
-
|
|
9899
|
+
hasExplicitSize() {
|
|
9900
|
+
const { _parsedProps: props } = this;
|
|
9901
|
+
return props.width !== void 0 || props.height !== void 0;
|
|
10121
9902
|
}
|
|
10122
|
-
|
|
10123
|
-
|
|
9903
|
+
/**
|
|
9904
|
+
* Create the schematic_symbol element in SymbolContainerRender phase.
|
|
9905
|
+
* This runs before SchematicPrimitiveRender, ensuring children can
|
|
9906
|
+
* reference the schematic_symbol_id when they render.
|
|
9907
|
+
*/
|
|
9908
|
+
doInitialSymbolContainerRender() {
|
|
9909
|
+
if (this.root?.schematicDisabled) return;
|
|
9910
|
+
const { db } = this.root;
|
|
9911
|
+
const { _parsedProps: props } = this;
|
|
9912
|
+
const parentNormal = this.getParentNormalComponent();
|
|
9913
|
+
const kicadSymbolMetadata = parentNormal?._parsedProps?.kicadSymbolMetadata;
|
|
9914
|
+
const schematic_symbol = db.schematic_symbol.insert({
|
|
9915
|
+
name: props.name,
|
|
9916
|
+
metadata: kicadSymbolMetadata ? { kicad_symbol: kicadSymbolMetadata } : void 0
|
|
9917
|
+
});
|
|
9918
|
+
this.schematic_symbol_id = schematic_symbol.schematic_symbol_id;
|
|
10124
9919
|
}
|
|
10125
|
-
|
|
10126
|
-
|
|
9920
|
+
getSchematicSymbolBounds() {
|
|
9921
|
+
if (this.schematicSymbolBoundsInUserCoordinates) {
|
|
9922
|
+
return this.schematicSymbolBoundsInUserCoordinates;
|
|
9923
|
+
}
|
|
9924
|
+
this._computeSchematicSymbolBounds();
|
|
9925
|
+
return this.schematicSymbolBoundsInUserCoordinates ?? null;
|
|
10127
9926
|
}
|
|
10128
|
-
|
|
10129
|
-
|
|
9927
|
+
getUserCoordinateToResizedSymbolTransform() {
|
|
9928
|
+
if (!this.hasExplicitSize()) {
|
|
9929
|
+
return null;
|
|
9930
|
+
}
|
|
9931
|
+
if (this.userCoordinateToResizedSymbolTransformMat) {
|
|
9932
|
+
return this.userCoordinateToResizedSymbolTransformMat;
|
|
9933
|
+
}
|
|
9934
|
+
this._computeUserCoordinateToResizedSymbolTransform();
|
|
9935
|
+
return this.userCoordinateToResizedSymbolTransformMat ?? null;
|
|
10130
9936
|
}
|
|
10131
|
-
|
|
10132
|
-
|
|
9937
|
+
_computeSchematicSymbolBounds() {
|
|
9938
|
+
if (this.root?.schematicDisabled) return;
|
|
9939
|
+
const { db } = this.root;
|
|
9940
|
+
const schematicElements = [];
|
|
9941
|
+
for (const child of this.children) {
|
|
9942
|
+
if (child.componentName === "Port") {
|
|
9943
|
+
const portId = child.schematic_port_id;
|
|
9944
|
+
if (portId) {
|
|
9945
|
+
const port = db.schematic_port.get(portId);
|
|
9946
|
+
if (port) schematicElements.push(port);
|
|
9947
|
+
}
|
|
9948
|
+
continue;
|
|
9949
|
+
}
|
|
9950
|
+
if (!child.isSchematicPrimitive) continue;
|
|
9951
|
+
if (child.componentName === "SchematicLine") {
|
|
9952
|
+
const line = db.schematic_line.get(child.schematic_line_id);
|
|
9953
|
+
if (line) schematicElements.push(line);
|
|
9954
|
+
} else if (child.componentName === "SchematicRect") {
|
|
9955
|
+
const rect = db.schematic_rect.get(child.schematic_rect_id);
|
|
9956
|
+
if (rect) schematicElements.push(rect);
|
|
9957
|
+
} else if (child.componentName === "SchematicCircle") {
|
|
9958
|
+
const circle = db.schematic_circle.get(
|
|
9959
|
+
child.schematic_circle_id
|
|
9960
|
+
);
|
|
9961
|
+
if (circle) schematicElements.push(circle);
|
|
9962
|
+
} else if (child.componentName === "SchematicArc") {
|
|
9963
|
+
const arc = db.schematic_arc.get(child.schematic_arc_id);
|
|
9964
|
+
if (arc) schematicElements.push(arc);
|
|
9965
|
+
} else if (child.componentName === "SchematicText") {
|
|
9966
|
+
const text = db.schematic_text.get(child.schematic_text_id);
|
|
9967
|
+
if (text) schematicElements.push(text);
|
|
9968
|
+
} else if (child.componentName === "SchematicPath") {
|
|
9969
|
+
const pathIds = child.schematic_path_ids;
|
|
9970
|
+
if (pathIds) {
|
|
9971
|
+
for (const pathId of pathIds) {
|
|
9972
|
+
const path = db.schematic_path.get(pathId);
|
|
9973
|
+
if (path) schematicElements.push(path);
|
|
9974
|
+
}
|
|
9975
|
+
}
|
|
9976
|
+
}
|
|
9977
|
+
}
|
|
9978
|
+
if (schematicElements.length === 0) return;
|
|
9979
|
+
const bounds = getBoundsForSchematic(schematicElements);
|
|
9980
|
+
this.schematicSymbolBoundsInUserCoordinates = bounds;
|
|
10133
9981
|
}
|
|
10134
|
-
|
|
10135
|
-
|
|
9982
|
+
_computeUserCoordinateToResizedSymbolTransform() {
|
|
9983
|
+
const bounds = this.getSchematicSymbolBounds();
|
|
9984
|
+
if (!bounds) return;
|
|
9985
|
+
const { _parsedProps: props } = this;
|
|
9986
|
+
const targetWidth = props.width;
|
|
9987
|
+
const targetHeight = props.height;
|
|
9988
|
+
if (targetWidth === void 0 && targetHeight === void 0) return;
|
|
9989
|
+
const currentWidth = bounds.maxX - bounds.minX;
|
|
9990
|
+
const currentHeight = bounds.maxY - bounds.minY;
|
|
9991
|
+
if (currentWidth === 0 && currentHeight === 0) return;
|
|
9992
|
+
const currentCenterX = (bounds.minX + bounds.maxX) / 2;
|
|
9993
|
+
const currentCenterY = (bounds.minY + bounds.maxY) / 2;
|
|
9994
|
+
const scaleX = targetWidth !== void 0 && currentWidth > 0 ? targetWidth / currentWidth : 1;
|
|
9995
|
+
const scaleY = targetHeight !== void 0 && currentHeight > 0 ? targetHeight / currentHeight : 1;
|
|
9996
|
+
const globalPos = this._getGlobalSchematicPositionBeforeLayout();
|
|
9997
|
+
this.userCoordinateToResizedSymbolTransformMat = compose4(
|
|
9998
|
+
translate3(globalPos.x, globalPos.y),
|
|
9999
|
+
scale(scaleX, scaleY),
|
|
10000
|
+
translate3(-currentCenterX, -currentCenterY)
|
|
10001
|
+
);
|
|
10136
10002
|
}
|
|
10137
|
-
|
|
10138
|
-
|
|
10003
|
+
};
|
|
10004
|
+
|
|
10005
|
+
// lib/utils/createPinrowSilkscreenText.ts
|
|
10006
|
+
var createPinrowSilkscreenText = ({
|
|
10007
|
+
elm,
|
|
10008
|
+
pinLabels,
|
|
10009
|
+
layer,
|
|
10010
|
+
readableRotation,
|
|
10011
|
+
anchorAlignment
|
|
10012
|
+
}) => {
|
|
10013
|
+
const pinNum = elm.text.replace(/[{}]/g, "").toLowerCase();
|
|
10014
|
+
let label = pinNum;
|
|
10015
|
+
if (Array.isArray(pinLabels)) {
|
|
10016
|
+
const index = parseInt(pinNum.replace(/[^\d]/g, ""), 10) - 1;
|
|
10017
|
+
label = String(pinLabels[index] ?? pinNum);
|
|
10018
|
+
} else if (typeof pinLabels === "object") {
|
|
10019
|
+
label = String(pinLabels[pinNum] ?? pinNum);
|
|
10139
10020
|
}
|
|
10140
|
-
|
|
10141
|
-
|
|
10021
|
+
const silkscreenText = new SilkscreenText({
|
|
10022
|
+
anchorAlignment: anchorAlignment || "center",
|
|
10023
|
+
text: label ?? pinNum,
|
|
10024
|
+
layer: layer || "top",
|
|
10025
|
+
pcbX: isNaN(elm.anchor_position.x) ? 0 : elm.anchor_position.x,
|
|
10026
|
+
pcbY: elm.anchor_position.y,
|
|
10027
|
+
pcbRotation: readableRotation ?? 0
|
|
10028
|
+
});
|
|
10029
|
+
silkscreenText._footprinterFontSize = elm.font_size + 0.2;
|
|
10030
|
+
return silkscreenText;
|
|
10031
|
+
};
|
|
10032
|
+
|
|
10033
|
+
// lib/utils/createComponentsFromCircuitJson.ts
|
|
10034
|
+
var calculateCcwRotation = (componentRotationStr, elementCcwRotation) => {
|
|
10035
|
+
const componentAngle = parseInt(componentRotationStr || "0", 10);
|
|
10036
|
+
let totalRotation;
|
|
10037
|
+
if (elementCcwRotation !== void 0 && elementCcwRotation !== null) {
|
|
10038
|
+
totalRotation = elementCcwRotation - componentAngle;
|
|
10039
|
+
} else {
|
|
10040
|
+
totalRotation = componentAngle;
|
|
10142
10041
|
}
|
|
10042
|
+
const normalizedRotation = (totalRotation % 360 + 360) % 360;
|
|
10043
|
+
return normalizedRotation;
|
|
10143
10044
|
};
|
|
10144
|
-
|
|
10145
|
-
|
|
10146
|
-
|
|
10147
|
-
|
|
10148
|
-
|
|
10149
|
-
|
|
10150
|
-
|
|
10151
|
-
|
|
10152
|
-
|
|
10153
|
-
|
|
10154
|
-
_primaryPinNumber = null;
|
|
10155
|
-
facingDirection = null;
|
|
10156
|
-
originDescription = null;
|
|
10157
|
-
get config() {
|
|
10158
|
-
return {
|
|
10159
|
-
componentName: "Port",
|
|
10160
|
-
zodProps: portProps
|
|
10161
|
-
};
|
|
10045
|
+
var optional = (value) => value ?? void 0;
|
|
10046
|
+
var getFacingDirectionFromSide = (side) => {
|
|
10047
|
+
switch (side) {
|
|
10048
|
+
case "left":
|
|
10049
|
+
case "right":
|
|
10050
|
+
return side;
|
|
10051
|
+
case "top":
|
|
10052
|
+
return "up";
|
|
10053
|
+
case "bottom":
|
|
10054
|
+
return "down";
|
|
10162
10055
|
}
|
|
10163
|
-
|
|
10164
|
-
|
|
10165
|
-
|
|
10166
|
-
|
|
10167
|
-
|
|
10168
|
-
|
|
10169
|
-
|
|
10170
|
-
|
|
10171
|
-
|
|
10056
|
+
return null;
|
|
10057
|
+
};
|
|
10058
|
+
var schematicPrimitiveTypesWithStrokeWidth = [
|
|
10059
|
+
"schematic_line",
|
|
10060
|
+
"schematic_rect",
|
|
10061
|
+
"schematic_circle",
|
|
10062
|
+
"schematic_arc",
|
|
10063
|
+
"schematic_path"
|
|
10064
|
+
];
|
|
10065
|
+
var isSchematicPrimitiveWithStrokeWidth = (elm) => schematicPrimitiveTypesWithStrokeWidth.includes(
|
|
10066
|
+
elm.type
|
|
10067
|
+
);
|
|
10068
|
+
var getSchematicSymbolId = (elm) => {
|
|
10069
|
+
if (!("schematic_symbol_id" in elm)) return void 0;
|
|
10070
|
+
return typeof elm.schematic_symbol_id === "string" ? elm.schematic_symbol_id : void 0;
|
|
10071
|
+
};
|
|
10072
|
+
var createComponentsFromCircuitJson = ({
|
|
10073
|
+
componentName,
|
|
10074
|
+
componentRotation,
|
|
10075
|
+
footprinterString,
|
|
10076
|
+
pinLabels,
|
|
10077
|
+
pcbPinLabels
|
|
10078
|
+
}, circuitJson) => {
|
|
10079
|
+
const components = [];
|
|
10080
|
+
const schematicSymbolsByImportedId = /* @__PURE__ */ new Map();
|
|
10081
|
+
const schematicComponentsByImportedId = /* @__PURE__ */ new Map();
|
|
10082
|
+
const sourcePortsByImportedId = /* @__PURE__ */ new Map();
|
|
10083
|
+
const schematicStrokeWidthBySymbolId = /* @__PURE__ */ new Map();
|
|
10084
|
+
for (const elm of circuitJson) {
|
|
10085
|
+
if (elm.type === "source_port") {
|
|
10086
|
+
sourcePortsByImportedId.set(elm.source_port_id, elm);
|
|
10172
10087
|
}
|
|
10173
|
-
this.matchedComponents = [];
|
|
10174
10088
|
}
|
|
10175
|
-
|
|
10176
|
-
|
|
10177
|
-
|
|
10178
|
-
|
|
10179
|
-
|
|
10089
|
+
for (const elm of circuitJson) {
|
|
10090
|
+
if (elm.type !== "schematic_symbol") continue;
|
|
10091
|
+
const schematicSymbol = new SymbolComponent({
|
|
10092
|
+
name: elm.name
|
|
10093
|
+
});
|
|
10094
|
+
schematicSymbolsByImportedId.set(elm.schematic_symbol_id, schematicSymbol);
|
|
10095
|
+
components.push(schematicSymbol);
|
|
10180
10096
|
}
|
|
10181
|
-
|
|
10182
|
-
|
|
10183
|
-
const
|
|
10184
|
-
|
|
10185
|
-
|
|
10186
|
-
|
|
10187
|
-
for (const connection of connectsToArray) {
|
|
10188
|
-
const port = this.getSubcircuit().selectOne(connection, {
|
|
10189
|
-
type: "port"
|
|
10190
|
-
});
|
|
10191
|
-
if (port) {
|
|
10192
|
-
connectedPorts.push(port);
|
|
10193
|
-
}
|
|
10097
|
+
for (const elm of circuitJson) {
|
|
10098
|
+
if (!isSchematicPrimitiveWithStrokeWidth(elm)) continue;
|
|
10099
|
+
const schematicSymbolId = getSchematicSymbolId(elm);
|
|
10100
|
+
const strokeWidth = elm.stroke_width;
|
|
10101
|
+
if (!schematicSymbolId || typeof strokeWidth !== "number" || !Number.isFinite(strokeWidth) || schematicStrokeWidthBySymbolId.has(schematicSymbolId)) {
|
|
10102
|
+
continue;
|
|
10194
10103
|
}
|
|
10195
|
-
|
|
10104
|
+
schematicStrokeWidthBySymbolId.set(schematicSymbolId, strokeWidth);
|
|
10196
10105
|
}
|
|
10197
|
-
|
|
10198
|
-
|
|
10199
|
-
|
|
10200
|
-
|
|
10201
|
-
|
|
10202
|
-
|
|
10203
|
-
|
|
10204
|
-
|
|
10106
|
+
for (const elm of circuitJson) {
|
|
10107
|
+
if (elm.type !== "schematic_component") continue;
|
|
10108
|
+
schematicComponentsByImportedId.set(elm.schematic_component_id, elm);
|
|
10109
|
+
}
|
|
10110
|
+
const addSchematicPrimitive = (elm, primitive) => {
|
|
10111
|
+
const schematicSymbolId = getSchematicSymbolId(elm);
|
|
10112
|
+
const parentSymbol = schematicSymbolId ? schematicSymbolsByImportedId.get(schematicSymbolId) : void 0;
|
|
10113
|
+
if (parentSymbol) {
|
|
10114
|
+
parentSymbol.add(primitive);
|
|
10115
|
+
} else {
|
|
10116
|
+
components.push(primitive);
|
|
10117
|
+
}
|
|
10118
|
+
};
|
|
10119
|
+
for (const elm of circuitJson) {
|
|
10120
|
+
if (elm.type === "pcb_smtpad" && elm.shape === "rect") {
|
|
10121
|
+
components.push(
|
|
10122
|
+
new SmtPad({
|
|
10123
|
+
pcbX: elm.x,
|
|
10124
|
+
pcbY: elm.y,
|
|
10125
|
+
layer: elm.layer,
|
|
10126
|
+
shape: "rect",
|
|
10127
|
+
height: elm.height,
|
|
10128
|
+
width: elm.width,
|
|
10129
|
+
portHints: elm.port_hints,
|
|
10130
|
+
rectBorderRadius: elm.rect_border_radius
|
|
10131
|
+
})
|
|
10132
|
+
);
|
|
10133
|
+
} else if (elm.type === "pcb_smtpad" && elm.shape === "circle") {
|
|
10134
|
+
components.push(
|
|
10135
|
+
new SmtPad({
|
|
10136
|
+
pcbX: elm.x,
|
|
10137
|
+
pcbY: elm.y,
|
|
10138
|
+
layer: elm.layer,
|
|
10139
|
+
shape: "circle",
|
|
10140
|
+
radius: elm.radius,
|
|
10141
|
+
portHints: elm.port_hints
|
|
10142
|
+
})
|
|
10143
|
+
);
|
|
10144
|
+
} else if (elm.type === "pcb_smtpad" && elm.shape === "pill") {
|
|
10145
|
+
components.push(
|
|
10146
|
+
new SmtPad({
|
|
10147
|
+
shape: "pill",
|
|
10148
|
+
height: elm.height,
|
|
10149
|
+
width: elm.width,
|
|
10150
|
+
radius: elm.radius,
|
|
10151
|
+
portHints: elm.port_hints,
|
|
10152
|
+
pcbX: elm.x,
|
|
10153
|
+
pcbY: elm.y,
|
|
10154
|
+
layer: elm.layer
|
|
10155
|
+
})
|
|
10156
|
+
);
|
|
10157
|
+
} else if (elm.type === "pcb_smtpad" && elm.shape === "polygon") {
|
|
10158
|
+
components.push(
|
|
10159
|
+
new SmtPad({
|
|
10160
|
+
shape: "polygon",
|
|
10161
|
+
points: elm.points,
|
|
10162
|
+
portHints: elm.port_hints,
|
|
10163
|
+
layer: elm.layer
|
|
10164
|
+
})
|
|
10165
|
+
);
|
|
10166
|
+
} else if (elm.type === "pcb_silkscreen_path") {
|
|
10167
|
+
components.push(
|
|
10168
|
+
new SilkscreenPath({
|
|
10169
|
+
layer: elm.layer,
|
|
10170
|
+
route: elm.route,
|
|
10171
|
+
strokeWidth: elm.stroke_width
|
|
10172
|
+
})
|
|
10173
|
+
);
|
|
10174
|
+
} else if (elm.type === "pcb_copper_text") {
|
|
10175
|
+
components.push(
|
|
10176
|
+
new CopperText({
|
|
10177
|
+
text: elm.text,
|
|
10178
|
+
pcbX: elm.anchor_position.x,
|
|
10179
|
+
pcbY: elm.anchor_position.y,
|
|
10180
|
+
pcbRotation: elm.ccw_rotation,
|
|
10181
|
+
anchorAlignment: elm.anchor_alignment,
|
|
10182
|
+
fontSize: elm.font_size,
|
|
10183
|
+
layer: elm.layer,
|
|
10184
|
+
mirrored: elm.is_mirrored,
|
|
10185
|
+
knockout: elm.is_knockout
|
|
10186
|
+
})
|
|
10187
|
+
);
|
|
10188
|
+
} else if (elm.type === "pcb_plated_hole") {
|
|
10189
|
+
if (elm.shape === "circle") {
|
|
10190
|
+
components.push(
|
|
10191
|
+
new PlatedHole({
|
|
10192
|
+
pcbX: elm.x,
|
|
10193
|
+
pcbY: elm.y,
|
|
10194
|
+
shape: "circle",
|
|
10195
|
+
holeDiameter: elm.hole_diameter,
|
|
10196
|
+
outerDiameter: elm.outer_diameter,
|
|
10197
|
+
portHints: elm.port_hints
|
|
10198
|
+
})
|
|
10199
|
+
);
|
|
10200
|
+
} else if (elm.shape === "circular_hole_with_rect_pad") {
|
|
10201
|
+
components.push(
|
|
10202
|
+
new PlatedHole({
|
|
10203
|
+
pcbX: elm.x,
|
|
10204
|
+
pcbY: elm.y,
|
|
10205
|
+
shape: "circular_hole_with_rect_pad",
|
|
10206
|
+
holeDiameter: elm.hole_diameter,
|
|
10207
|
+
rectPadHeight: elm.rect_pad_height,
|
|
10208
|
+
rectPadWidth: elm.rect_pad_width,
|
|
10209
|
+
portHints: elm.port_hints,
|
|
10210
|
+
rectBorderRadius: elm.rect_border_radius,
|
|
10211
|
+
holeOffsetX: elm.hole_offset_x,
|
|
10212
|
+
holeOffsetY: elm.hole_offset_y
|
|
10213
|
+
})
|
|
10214
|
+
);
|
|
10215
|
+
} else if (elm.shape === "pill" || elm.shape === "oval") {
|
|
10216
|
+
components.push(
|
|
10217
|
+
new PlatedHole({
|
|
10218
|
+
pcbX: elm.x,
|
|
10219
|
+
pcbY: elm.y,
|
|
10220
|
+
shape: elm.shape,
|
|
10221
|
+
holeWidth: elm.hole_width,
|
|
10222
|
+
holeHeight: elm.hole_height,
|
|
10223
|
+
outerWidth: elm.outer_width,
|
|
10224
|
+
outerHeight: elm.outer_height,
|
|
10225
|
+
portHints: elm.port_hints
|
|
10226
|
+
})
|
|
10227
|
+
);
|
|
10228
|
+
} else if (elm.shape === "pill_hole_with_rect_pad") {
|
|
10229
|
+
components.push(
|
|
10230
|
+
new PlatedHole({
|
|
10231
|
+
pcbX: elm.x,
|
|
10232
|
+
pcbY: elm.y,
|
|
10233
|
+
shape: "pill_hole_with_rect_pad",
|
|
10234
|
+
holeShape: "pill",
|
|
10235
|
+
padShape: "rect",
|
|
10236
|
+
holeWidth: elm.hole_width,
|
|
10237
|
+
holeHeight: elm.hole_height,
|
|
10238
|
+
rectPadWidth: elm.rect_pad_width,
|
|
10239
|
+
rectPadHeight: elm.rect_pad_height,
|
|
10240
|
+
rectBorderRadius: elm.rect_border_radius,
|
|
10241
|
+
portHints: elm.port_hints,
|
|
10242
|
+
holeOffsetX: elm.hole_offset_x,
|
|
10243
|
+
holeOffsetY: elm.hole_offset_y
|
|
10244
|
+
})
|
|
10245
|
+
);
|
|
10246
|
+
} else if (elm.shape === "rotated_pill_hole_with_rect_pad") {
|
|
10247
|
+
components.push(
|
|
10248
|
+
new PlatedHole({
|
|
10249
|
+
pcbX: elm.x,
|
|
10250
|
+
pcbY: elm.y,
|
|
10251
|
+
shape: "pill_hole_with_rect_pad",
|
|
10252
|
+
holeShape: "pill",
|
|
10253
|
+
padShape: "rect",
|
|
10254
|
+
holeWidth: elm.hole_width,
|
|
10255
|
+
holeHeight: elm.hole_height,
|
|
10256
|
+
rectPadWidth: elm.rect_pad_width,
|
|
10257
|
+
rectPadHeight: elm.rect_pad_height,
|
|
10258
|
+
rectBorderRadius: elm.rect_border_radius,
|
|
10259
|
+
portHints: elm.port_hints,
|
|
10260
|
+
holeOffsetX: elm.hole_offset_x,
|
|
10261
|
+
holeOffsetY: elm.hole_offset_y,
|
|
10262
|
+
pcbRotation: elm.hole_ccw_rotation
|
|
10263
|
+
})
|
|
10264
|
+
);
|
|
10265
|
+
} else if (elm.shape === "hole_with_polygon_pad") {
|
|
10266
|
+
components.push(
|
|
10267
|
+
new PlatedHole({
|
|
10268
|
+
pcbX: elm.x,
|
|
10269
|
+
pcbY: elm.y,
|
|
10270
|
+
shape: "hole_with_polygon_pad",
|
|
10271
|
+
holeShape: elm.hole_shape || "circle",
|
|
10272
|
+
holeDiameter: elm.hole_diameter,
|
|
10273
|
+
holeWidth: elm.hole_width,
|
|
10274
|
+
holeHeight: elm.hole_height,
|
|
10275
|
+
padOutline: elm.pad_outline || [],
|
|
10276
|
+
holeOffsetX: elm.hole_offset_x,
|
|
10277
|
+
holeOffsetY: elm.hole_offset_y,
|
|
10278
|
+
portHints: elm.port_hints
|
|
10279
|
+
})
|
|
10280
|
+
);
|
|
10205
10281
|
}
|
|
10206
|
-
}
|
|
10207
|
-
|
|
10208
|
-
|
|
10209
|
-
|
|
10210
|
-
|
|
10211
|
-
|
|
10212
|
-
|
|
10213
|
-
|
|
10282
|
+
} else if (elm.type === "pcb_keepout" && elm.shape === "circle") {
|
|
10283
|
+
components.push(
|
|
10284
|
+
new Keepout({
|
|
10285
|
+
pcbX: elm.center.x,
|
|
10286
|
+
pcbY: elm.center.y,
|
|
10287
|
+
shape: "circle",
|
|
10288
|
+
radius: elm.radius
|
|
10289
|
+
})
|
|
10214
10290
|
);
|
|
10215
|
-
}
|
|
10216
|
-
|
|
10217
|
-
|
|
10218
|
-
|
|
10291
|
+
} else if (elm.type === "pcb_keepout" && elm.shape === "rect") {
|
|
10292
|
+
components.push(
|
|
10293
|
+
new Keepout({
|
|
10294
|
+
pcbX: elm.center.x,
|
|
10295
|
+
pcbY: elm.center.y,
|
|
10296
|
+
shape: "rect",
|
|
10297
|
+
width: elm.width,
|
|
10298
|
+
height: elm.height
|
|
10299
|
+
})
|
|
10219
10300
|
);
|
|
10220
|
-
}
|
|
10221
|
-
|
|
10222
|
-
|
|
10223
|
-
|
|
10224
|
-
|
|
10225
|
-
|
|
10226
|
-
|
|
10227
|
-
|
|
10228
|
-
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
|
|
10232
|
-
|
|
10233
|
-
|
|
10234
|
-
|
|
10235
|
-
|
|
10236
|
-
|
|
10237
|
-
|
|
10238
|
-
|
|
10239
|
-
|
|
10240
|
-
|
|
10241
|
-
|
|
10242
|
-
|
|
10243
|
-
|
|
10244
|
-
|
|
10245
|
-
|
|
10301
|
+
} else if (elm.type === "pcb_hole" && elm.hole_shape === "circle") {
|
|
10302
|
+
components.push(
|
|
10303
|
+
new Hole({
|
|
10304
|
+
pcbX: elm.x,
|
|
10305
|
+
pcbY: elm.y,
|
|
10306
|
+
diameter: elm.hole_diameter
|
|
10307
|
+
})
|
|
10308
|
+
);
|
|
10309
|
+
} else if (elm.type === "pcb_hole" && elm.hole_shape === "rect") {
|
|
10310
|
+
components.push(
|
|
10311
|
+
new Hole({
|
|
10312
|
+
pcbX: elm.x,
|
|
10313
|
+
pcbY: elm.y,
|
|
10314
|
+
shape: "rect",
|
|
10315
|
+
width: elm.hole_width,
|
|
10316
|
+
height: elm.hole_height
|
|
10317
|
+
})
|
|
10318
|
+
);
|
|
10319
|
+
} else if (elm.type === "pcb_hole" && elm.hole_shape === "pill") {
|
|
10320
|
+
components.push(
|
|
10321
|
+
new Hole({
|
|
10322
|
+
pcbX: elm.x,
|
|
10323
|
+
pcbY: elm.y,
|
|
10324
|
+
shape: "pill",
|
|
10325
|
+
width: elm.hole_width,
|
|
10326
|
+
height: elm.hole_height
|
|
10327
|
+
})
|
|
10328
|
+
);
|
|
10329
|
+
} else if (elm.type === "pcb_hole" && elm.hole_shape === "oval") {
|
|
10330
|
+
components.push(
|
|
10331
|
+
new Hole({
|
|
10332
|
+
pcbX: elm.x,
|
|
10333
|
+
pcbY: elm.y,
|
|
10334
|
+
shape: "oval",
|
|
10335
|
+
width: elm.hole_width,
|
|
10336
|
+
height: elm.hole_height
|
|
10337
|
+
})
|
|
10338
|
+
);
|
|
10339
|
+
} else if (elm.type === "pcb_hole" && elm.hole_shape === "rotated_pill") {
|
|
10340
|
+
components.push(
|
|
10341
|
+
new Hole({
|
|
10342
|
+
pcbX: elm.x,
|
|
10343
|
+
pcbY: elm.y,
|
|
10344
|
+
shape: "pill",
|
|
10345
|
+
width: elm.hole_width,
|
|
10346
|
+
height: elm.hole_height,
|
|
10347
|
+
pcbRotation: elm.ccw_rotation
|
|
10348
|
+
})
|
|
10349
|
+
);
|
|
10350
|
+
} else if (elm.type === "pcb_cutout") {
|
|
10351
|
+
if (elm.shape === "rect") {
|
|
10352
|
+
components.push(
|
|
10353
|
+
new Cutout({
|
|
10354
|
+
pcbX: elm.center.x,
|
|
10355
|
+
pcbY: elm.center.y,
|
|
10356
|
+
shape: "rect",
|
|
10357
|
+
width: elm.width,
|
|
10358
|
+
height: elm.height
|
|
10359
|
+
})
|
|
10360
|
+
);
|
|
10361
|
+
} else if (elm.shape === "circle") {
|
|
10362
|
+
components.push(
|
|
10363
|
+
new Cutout({
|
|
10364
|
+
pcbX: elm.center.x,
|
|
10365
|
+
pcbY: elm.center.y,
|
|
10366
|
+
shape: "circle",
|
|
10367
|
+
radius: elm.radius
|
|
10368
|
+
})
|
|
10369
|
+
);
|
|
10370
|
+
} else if (elm.shape === "polygon") {
|
|
10371
|
+
components.push(
|
|
10372
|
+
new Cutout({
|
|
10373
|
+
shape: "polygon",
|
|
10374
|
+
points: elm.points
|
|
10375
|
+
})
|
|
10376
|
+
);
|
|
10246
10377
|
}
|
|
10247
|
-
}
|
|
10248
|
-
|
|
10249
|
-
|
|
10250
|
-
|
|
10251
|
-
|
|
10252
|
-
|
|
10253
|
-
|
|
10254
|
-
|
|
10255
|
-
|
|
10256
|
-
|
|
10257
|
-
|
|
10258
|
-
|
|
10259
|
-
|
|
10260
|
-
|
|
10261
|
-
|
|
10262
|
-
|
|
10263
|
-
|
|
10264
|
-
|
|
10265
|
-
|
|
10266
|
-
|
|
10267
|
-
|
|
10268
|
-
|
|
10269
|
-
|
|
10270
|
-
|
|
10271
|
-
|
|
10272
|
-
|
|
10273
|
-
|
|
10274
|
-
|
|
10275
|
-
|
|
10276
|
-
|
|
10277
|
-
|
|
10278
|
-
|
|
10279
|
-
|
|
10280
|
-
|
|
10378
|
+
} else if (elm.type === "pcb_silkscreen_text") {
|
|
10379
|
+
const ccwRotation = calculateCcwRotation(
|
|
10380
|
+
componentRotation,
|
|
10381
|
+
elm.ccw_rotation
|
|
10382
|
+
);
|
|
10383
|
+
if (footprinterString?.includes("pinrow") && elm.text.includes("PIN")) {
|
|
10384
|
+
components.push(
|
|
10385
|
+
createPinrowSilkscreenText({
|
|
10386
|
+
elm,
|
|
10387
|
+
pinLabels: pcbPinLabels ?? pinLabels ?? {},
|
|
10388
|
+
layer: elm.layer,
|
|
10389
|
+
readableRotation: ccwRotation,
|
|
10390
|
+
anchorAlignment: elm.anchor_alignment
|
|
10391
|
+
})
|
|
10392
|
+
);
|
|
10393
|
+
} else {
|
|
10394
|
+
const silkscreenText = new SilkscreenText({
|
|
10395
|
+
anchorAlignment: elm.anchor_alignment || "center",
|
|
10396
|
+
text: componentName || elm.text,
|
|
10397
|
+
pcbX: Number.isNaN(elm.anchor_position.x) ? 0 : elm.anchor_position.x,
|
|
10398
|
+
pcbY: elm.anchor_position.y,
|
|
10399
|
+
pcbRotation: ccwRotation ?? 0
|
|
10400
|
+
});
|
|
10401
|
+
silkscreenText._footprinterFontSize = elm.font_size + 0.2;
|
|
10402
|
+
components.push(silkscreenText);
|
|
10403
|
+
}
|
|
10404
|
+
} else if (elm.type === "pcb_trace") {
|
|
10405
|
+
components.push(
|
|
10406
|
+
new PcbTrace({
|
|
10407
|
+
route: elm.route
|
|
10408
|
+
})
|
|
10409
|
+
);
|
|
10410
|
+
} else if (elm.type === "pcb_via") {
|
|
10411
|
+
const layers = elm.layers ?? [];
|
|
10412
|
+
const pcbVia = new PcbVia({
|
|
10413
|
+
pcbX: elm.x,
|
|
10414
|
+
pcbY: elm.y,
|
|
10415
|
+
holeDiameter: elm.hole_diameter,
|
|
10416
|
+
outerDiameter: elm.outer_diameter,
|
|
10417
|
+
fromLayer: elm.from_layer ?? layers[0],
|
|
10418
|
+
toLayer: elm.to_layer ?? layers[layers.length - 1],
|
|
10419
|
+
layers,
|
|
10420
|
+
netIsAssignable: elm.net_is_assignable,
|
|
10421
|
+
isTented: elm.is_tented
|
|
10422
|
+
});
|
|
10423
|
+
pcbVia._importedPcbTraceId = elm.pcb_trace_id;
|
|
10424
|
+
components.push(pcbVia);
|
|
10425
|
+
} else if (elm.type === "pcb_silkscreen_rect") {
|
|
10426
|
+
components.push(
|
|
10427
|
+
new SilkscreenRect({
|
|
10428
|
+
pcbX: elm.center.x,
|
|
10429
|
+
pcbY: elm.center.y,
|
|
10430
|
+
width: elm.width,
|
|
10431
|
+
height: elm.height,
|
|
10432
|
+
layer: elm.layer,
|
|
10433
|
+
strokeWidth: elm.stroke_width,
|
|
10434
|
+
filled: elm.is_filled,
|
|
10435
|
+
cornerRadius: elm.corner_radius
|
|
10436
|
+
})
|
|
10437
|
+
);
|
|
10438
|
+
} else if (elm.type === "pcb_silkscreen_circle") {
|
|
10439
|
+
components.push(
|
|
10440
|
+
new SilkscreenCircle({
|
|
10441
|
+
pcbX: elm.center.x,
|
|
10442
|
+
pcbY: elm.center.y,
|
|
10443
|
+
radius: elm.radius,
|
|
10444
|
+
layer: elm.layer,
|
|
10445
|
+
strokeWidth: elm.stroke_width
|
|
10446
|
+
})
|
|
10447
|
+
);
|
|
10448
|
+
} else if (elm.type === "pcb_silkscreen_line") {
|
|
10449
|
+
components.push(
|
|
10450
|
+
new SilkscreenLine({
|
|
10451
|
+
x1: elm.x1,
|
|
10452
|
+
y1: elm.y1,
|
|
10453
|
+
x2: elm.x2,
|
|
10454
|
+
y2: elm.y2,
|
|
10455
|
+
layer: elm.layer,
|
|
10456
|
+
strokeWidth: elm.stroke_width
|
|
10457
|
+
})
|
|
10458
|
+
);
|
|
10459
|
+
} else if (elm.type === "pcb_fabrication_note_text") {
|
|
10460
|
+
components.push(
|
|
10461
|
+
new FabricationNoteText({
|
|
10462
|
+
pcbX: elm.anchor_position.x,
|
|
10463
|
+
pcbY: elm.anchor_position.y,
|
|
10464
|
+
text: elm.text,
|
|
10465
|
+
fontSize: elm.font_size,
|
|
10466
|
+
anchorAlignment: elm.anchor_alignment,
|
|
10467
|
+
color: elm.color,
|
|
10468
|
+
font: elm.font
|
|
10469
|
+
})
|
|
10281
10470
|
);
|
|
10282
|
-
|
|
10283
|
-
|
|
10284
|
-
|
|
10285
|
-
|
|
10286
|
-
|
|
10287
|
-
|
|
10288
|
-
|
|
10289
|
-
|
|
10290
|
-
}
|
|
10291
|
-
const parentNormalComponent = this.getParentNormalComponent();
|
|
10292
|
-
const symbol = parentNormalComponent?.getSchematicSymbol();
|
|
10293
|
-
if (symbol) {
|
|
10294
|
-
let schematicSymbolPortDef = this.schematicSymbolPortDef;
|
|
10295
|
-
if (!schematicSymbolPortDef) {
|
|
10296
|
-
schematicSymbolPortDef = this._getPortsInternallyConnectedToThisPort().find(
|
|
10297
|
-
(p) => p.schematicSymbolPortDef
|
|
10298
|
-
)?.schematicSymbolPortDef ?? null;
|
|
10299
|
-
if (!schematicSymbolPortDef) {
|
|
10300
|
-
throw new Error(
|
|
10301
|
-
`Couldn't find schematicSymbolPortDef for port ${this.getString()}, searched internally connected ports and none had a schematicSymbolPortDef. Why are we trying to get the schematic position of this port?`
|
|
10302
|
-
);
|
|
10303
|
-
}
|
|
10304
|
-
}
|
|
10305
|
-
const transform = compose4(
|
|
10306
|
-
parentNormalComponent.computeSchematicGlobalTransform(),
|
|
10307
|
-
translate3(-symbol.center.x, -symbol.center.y)
|
|
10471
|
+
} else if (elm.type === "pcb_fabrication_note_path") {
|
|
10472
|
+
components.push(
|
|
10473
|
+
new FabricationNotePath({
|
|
10474
|
+
route: elm.route,
|
|
10475
|
+
strokeWidth: elm.stroke_width,
|
|
10476
|
+
color: elm.color,
|
|
10477
|
+
layer: elm.layer
|
|
10478
|
+
})
|
|
10308
10479
|
);
|
|
10309
|
-
|
|
10310
|
-
|
|
10311
|
-
|
|
10312
|
-
|
|
10313
|
-
|
|
10314
|
-
|
|
10480
|
+
} else if (elm.type === "pcb_fabrication_note_rect") {
|
|
10481
|
+
components.push(
|
|
10482
|
+
new FabricationNoteRect({
|
|
10483
|
+
pcbX: elm.center.x,
|
|
10484
|
+
pcbY: elm.center.y,
|
|
10485
|
+
width: elm.width,
|
|
10486
|
+
height: elm.height,
|
|
10487
|
+
strokeWidth: elm.stroke_width,
|
|
10488
|
+
isFilled: elm.is_filled,
|
|
10489
|
+
color: elm.color,
|
|
10490
|
+
layer: elm.layer,
|
|
10491
|
+
cornerRadius: elm.corner_radius,
|
|
10492
|
+
hasStroke: elm.has_stroke,
|
|
10493
|
+
isStrokeDashed: elm.is_stroke_dashed
|
|
10494
|
+
})
|
|
10315
10495
|
);
|
|
10316
|
-
|
|
10317
|
-
|
|
10318
|
-
|
|
10319
|
-
|
|
10320
|
-
|
|
10321
|
-
|
|
10322
|
-
|
|
10323
|
-
|
|
10496
|
+
} else if (elm.type === "pcb_note_text") {
|
|
10497
|
+
components.push(
|
|
10498
|
+
new PcbNoteText({
|
|
10499
|
+
pcbX: elm.anchor_position.x,
|
|
10500
|
+
pcbY: elm.anchor_position.y,
|
|
10501
|
+
text: elm.text ?? "",
|
|
10502
|
+
fontSize: elm.font_size,
|
|
10503
|
+
anchorAlignment: elm.anchor_alignment,
|
|
10504
|
+
color: elm.color,
|
|
10505
|
+
font: elm.font
|
|
10506
|
+
})
|
|
10324
10507
|
);
|
|
10325
|
-
}
|
|
10326
|
-
|
|
10327
|
-
|
|
10328
|
-
|
|
10329
|
-
|
|
10330
|
-
|
|
10331
|
-
|
|
10332
|
-
|
|
10333
|
-
|
|
10334
|
-
|
|
10508
|
+
} else if (elm.type === "pcb_note_rect") {
|
|
10509
|
+
components.push(
|
|
10510
|
+
new PcbNoteRect({
|
|
10511
|
+
pcbX: elm.center.x,
|
|
10512
|
+
pcbY: elm.center.y,
|
|
10513
|
+
width: elm.width,
|
|
10514
|
+
height: elm.height,
|
|
10515
|
+
strokeWidth: elm.stroke_width,
|
|
10516
|
+
isFilled: elm.is_filled,
|
|
10517
|
+
color: elm.color,
|
|
10518
|
+
cornerRadius: elm.corner_radius,
|
|
10519
|
+
hasStroke: elm.has_stroke,
|
|
10520
|
+
isStrokeDashed: elm.is_stroke_dashed
|
|
10521
|
+
})
|
|
10335
10522
|
);
|
|
10336
|
-
}
|
|
10337
|
-
|
|
10338
|
-
|
|
10339
|
-
|
|
10340
|
-
|
|
10523
|
+
} else if (elm.type === "pcb_note_path") {
|
|
10524
|
+
components.push(
|
|
10525
|
+
new PcbNotePath({
|
|
10526
|
+
route: elm.route,
|
|
10527
|
+
strokeWidth: elm.stroke_width,
|
|
10528
|
+
color: elm.color
|
|
10529
|
+
})
|
|
10341
10530
|
);
|
|
10342
|
-
|
|
10343
|
-
|
|
10344
|
-
|
|
10345
|
-
|
|
10346
|
-
|
|
10347
|
-
|
|
10348
|
-
|
|
10349
|
-
|
|
10350
|
-
|
|
10351
|
-
|
|
10352
|
-
|
|
10353
|
-
|
|
10354
|
-
|
|
10355
|
-
|
|
10356
|
-
|
|
10357
|
-
|
|
10358
|
-
|
|
10359
|
-
|
|
10360
|
-
|
|
10361
|
-
|
|
10362
|
-
|
|
10363
|
-
|
|
10364
|
-
|
|
10365
|
-
|
|
10366
|
-
|
|
10367
|
-
|
|
10368
|
-
|
|
10369
|
-
|
|
10370
|
-
|
|
10371
|
-
|
|
10372
|
-
matches.push(attributes);
|
|
10373
|
-
}
|
|
10374
|
-
}
|
|
10375
|
-
if (noConnect?.includes(alias)) {
|
|
10376
|
-
matches.push({ doNotConnect: true });
|
|
10377
|
-
}
|
|
10378
|
-
}
|
|
10379
|
-
if (matches.length === 0) {
|
|
10380
|
-
return [];
|
|
10381
|
-
}
|
|
10382
|
-
return matches;
|
|
10383
|
-
}
|
|
10384
|
-
_shouldIncludeInBoardPinout() {
|
|
10385
|
-
return this._getMatchingPinAttributes().some(
|
|
10386
|
-
(attributes) => attributes.includeInBoardPinout === true
|
|
10387
|
-
);
|
|
10388
|
-
}
|
|
10389
|
-
isMatchingPort(port) {
|
|
10390
|
-
return this.isMatchingAnyOf(port.getNameAndAliases());
|
|
10391
|
-
}
|
|
10392
|
-
getPortSelector() {
|
|
10393
|
-
const parentComponent = this.getParentNormalComponent() ?? this.parent;
|
|
10394
|
-
return `.${parentComponent?.props.name} > port.${this.props.name}`;
|
|
10395
|
-
}
|
|
10396
|
-
getAvailablePcbLayers() {
|
|
10397
|
-
const { layer, layers } = this._parsedProps;
|
|
10398
|
-
if (layers) return layers;
|
|
10399
|
-
if (layer) return [layer];
|
|
10400
|
-
return Array.from(
|
|
10401
|
-
new Set(this.matchedComponents.flatMap((c) => c.getAvailablePcbLayers()))
|
|
10402
|
-
);
|
|
10403
|
-
}
|
|
10404
|
-
/**
|
|
10405
|
-
* Return traces that are explicitly connected to this port (not via a net)
|
|
10406
|
-
*/
|
|
10407
|
-
_getDirectlyConnectedTraces() {
|
|
10408
|
-
const allSubcircuitTraces = this.getSubcircuit().selectAll(
|
|
10409
|
-
"trace"
|
|
10410
|
-
);
|
|
10411
|
-
const connectedTraces = allSubcircuitTraces.filter((trace) => !trace._couldNotFindPort).filter((trace) => trace._isExplicitlyConnectedToPort(this));
|
|
10412
|
-
return connectedTraces;
|
|
10413
|
-
}
|
|
10414
|
-
doInitialSourceRender() {
|
|
10415
|
-
const { db } = this.root;
|
|
10416
|
-
const { _parsedProps: props } = this;
|
|
10417
|
-
const port_hints = this.getNameAndAliases();
|
|
10418
|
-
const parentNormalComponent = this.getParentNormalComponent();
|
|
10419
|
-
const parentWithSourceId = this.parent?.source_component_id ? this.parent : parentNormalComponent;
|
|
10420
|
-
const source_component_id = parentWithSourceId?.source_component_id ?? null;
|
|
10421
|
-
const pinAttributes = this._getMatchingPinAttributes();
|
|
10422
|
-
const portAttributesFromParent = {};
|
|
10423
|
-
for (const attributes of pinAttributes) {
|
|
10424
|
-
applyPinAttributesToSourcePort(portAttributesFromParent, attributes);
|
|
10425
|
-
}
|
|
10426
|
-
const source_port = db.source_port.insert({
|
|
10427
|
-
name: props.name,
|
|
10428
|
-
pin_number: props.pinNumber,
|
|
10429
|
-
port_hints,
|
|
10430
|
-
source_component_id,
|
|
10431
|
-
subcircuit_id: this.getSubcircuit()?.subcircuit_id,
|
|
10432
|
-
...portAttributesFromParent
|
|
10433
|
-
});
|
|
10434
|
-
this.source_port_id = source_port.source_port_id;
|
|
10435
|
-
}
|
|
10436
|
-
doInitialSourceParentAttachment() {
|
|
10437
|
-
const { db } = this.root;
|
|
10438
|
-
const parentNormalComponent = this.getParentNormalComponent();
|
|
10439
|
-
const parentWithSourceId = this.parent?.source_component_id ? this.parent : parentNormalComponent;
|
|
10440
|
-
if (this.isGroupPort()) {
|
|
10441
|
-
db.source_port.update(this.source_port_id, {
|
|
10442
|
-
source_component_id: null,
|
|
10443
|
-
subcircuit_id: this.getSubcircuit()?.subcircuit_id
|
|
10444
|
-
});
|
|
10445
|
-
return;
|
|
10446
|
-
}
|
|
10447
|
-
if (!parentWithSourceId?.source_component_id) {
|
|
10448
|
-
throw new Error(
|
|
10449
|
-
`${this.getString()} has no parent source component (parent: ${this.parent?.getString()})`
|
|
10531
|
+
} else if (elm.type === "pcb_note_line") {
|
|
10532
|
+
components.push(
|
|
10533
|
+
new PcbNoteLine({
|
|
10534
|
+
x1: elm.x1,
|
|
10535
|
+
y1: elm.y1,
|
|
10536
|
+
x2: elm.x2,
|
|
10537
|
+
y2: elm.y2,
|
|
10538
|
+
strokeWidth: elm.stroke_width,
|
|
10539
|
+
color: elm.color,
|
|
10540
|
+
isDashed: elm.is_dashed
|
|
10541
|
+
})
|
|
10542
|
+
);
|
|
10543
|
+
} else if (elm.type === "pcb_courtyard_rect") {
|
|
10544
|
+
components.push(
|
|
10545
|
+
new CourtyardRect({
|
|
10546
|
+
pcbX: elm.center.x,
|
|
10547
|
+
pcbY: elm.center.y,
|
|
10548
|
+
width: elm.width,
|
|
10549
|
+
height: elm.height,
|
|
10550
|
+
layer: elm.layer
|
|
10551
|
+
})
|
|
10552
|
+
);
|
|
10553
|
+
} else if (elm.type === "pcb_courtyard_circle") {
|
|
10554
|
+
components.push(
|
|
10555
|
+
new CourtyardCircle({
|
|
10556
|
+
pcbX: elm.center.x,
|
|
10557
|
+
pcbY: elm.center.y,
|
|
10558
|
+
radius: elm.radius,
|
|
10559
|
+
layer: elm.layer
|
|
10560
|
+
})
|
|
10450
10561
|
);
|
|
10451
|
-
}
|
|
10452
|
-
|
|
10453
|
-
|
|
10454
|
-
|
|
10455
|
-
|
|
10456
|
-
|
|
10457
|
-
}
|
|
10458
|
-
doInitialPcbPortRender() {
|
|
10459
|
-
if (this.root?.pcbDisabled) return;
|
|
10460
|
-
const { db } = this.root;
|
|
10461
|
-
const { matchedComponents } = this;
|
|
10462
|
-
if (this.isGroupPort()) {
|
|
10463
|
-
const connectedPorts = this._getConnectedPortsFromConnectsTo();
|
|
10464
|
-
if (connectedPorts.length === 0) {
|
|
10465
|
-
return;
|
|
10466
|
-
}
|
|
10467
|
-
const connectedPort = connectedPorts[0];
|
|
10468
|
-
if (!connectedPort.pcb_port_id) {
|
|
10469
|
-
return;
|
|
10470
|
-
}
|
|
10471
|
-
const connectedPcbPort = db.pcb_port.get(connectedPort.pcb_port_id);
|
|
10472
|
-
const matchCenter2 = { x: connectedPcbPort.x, y: connectedPcbPort.y };
|
|
10473
|
-
const subcircuit = this.getSubcircuit();
|
|
10474
|
-
const pcb_port = db.pcb_port.insert({
|
|
10475
|
-
pcb_component_id: void 0,
|
|
10476
|
-
layers: connectedPort.getAvailablePcbLayers(),
|
|
10477
|
-
subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
|
|
10478
|
-
pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0,
|
|
10479
|
-
...matchCenter2,
|
|
10480
|
-
source_port_id: this.source_port_id,
|
|
10481
|
-
is_board_pinout: false
|
|
10482
|
-
});
|
|
10483
|
-
this.pcb_port_id = pcb_port.pcb_port_id;
|
|
10484
|
-
return;
|
|
10485
|
-
}
|
|
10486
|
-
const parentNormalComponent = this.getParentNormalComponent();
|
|
10487
|
-
const parentWithPcbComponentId = this.parent?.pcb_component_id ? this.parent : parentNormalComponent;
|
|
10488
|
-
if (!parentWithPcbComponentId?.pcb_component_id) {
|
|
10489
|
-
throw new Error(
|
|
10490
|
-
`${this.getString()} has no parent pcb component, cannot render pcb_port (parent: ${this.parent?.getString()}, parentNormalComponent: ${parentNormalComponent?.getString()})`
|
|
10562
|
+
} else if (elm.type === "pcb_courtyard_outline") {
|
|
10563
|
+
components.push(
|
|
10564
|
+
new CourtyardOutline({
|
|
10565
|
+
outline: elm.outline,
|
|
10566
|
+
layer: elm.layer
|
|
10567
|
+
})
|
|
10491
10568
|
);
|
|
10492
|
-
}
|
|
10493
|
-
|
|
10494
|
-
|
|
10495
|
-
|
|
10496
|
-
|
|
10497
|
-
|
|
10498
|
-
|
|
10499
|
-
|
|
10500
|
-
|
|
10501
|
-
|
|
10502
|
-
|
|
10503
|
-
|
|
10504
|
-
(h) => h !== portName
|
|
10505
|
-
);
|
|
10506
|
-
const altMsg = altAliases.length > 0 ? ` (consider using alternate aliases: ${altAliases.join(", ")})` : "";
|
|
10507
|
-
db.source_ambiguous_port_reference.insert({
|
|
10508
|
-
error_type: "source_ambiguous_port_reference",
|
|
10509
|
-
message: `${componentName}.${portName} is ambiguous: ${componentName}.${portName} references multiple non-overlapping pads: ${pcbMatches.map((c) => c.getString()).join(", ")}${altMsg}`,
|
|
10510
|
-
source_port_id: this.source_port_id ?? void 0,
|
|
10511
|
-
source_component_id: this.getParentNormalComponent()?.source_component_id ?? void 0
|
|
10512
|
-
});
|
|
10513
|
-
return;
|
|
10514
|
-
}
|
|
10515
|
-
matchCenter = getCenterOfPcbPrimitives(pcbMatches);
|
|
10516
|
-
}
|
|
10517
|
-
if (matchCenter) {
|
|
10518
|
-
const subcircuit = this.getSubcircuit();
|
|
10519
|
-
const isBoardPinout = this._shouldIncludeInBoardPinout();
|
|
10520
|
-
const pcb_port = db.pcb_port.insert({
|
|
10521
|
-
pcb_component_id: parentWithPcbComponentId.pcb_component_id,
|
|
10522
|
-
layers: this.getAvailablePcbLayers(),
|
|
10523
|
-
subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
|
|
10524
|
-
pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0,
|
|
10525
|
-
...isBoardPinout ? { is_board_pinout: true } : {},
|
|
10526
|
-
...matchCenter,
|
|
10527
|
-
source_port_id: this.source_port_id,
|
|
10528
|
-
is_board_pinout: this._isBoardPinoutFromAttributes()
|
|
10529
|
-
});
|
|
10530
|
-
this.pcb_port_id = pcb_port.pcb_port_id;
|
|
10531
|
-
} else {
|
|
10532
|
-
const pcbMatch = pcbMatches[0];
|
|
10533
|
-
throw new Error(
|
|
10534
|
-
`${pcbMatch.getString()} does not have a center or _getGlobalPcbPositionBeforeLayout method (needed for pcb_port placement)`
|
|
10569
|
+
} else if (elm.type === "schematic_line") {
|
|
10570
|
+
addSchematicPrimitive(
|
|
10571
|
+
elm,
|
|
10572
|
+
new SchematicLine({
|
|
10573
|
+
x1: elm.x1,
|
|
10574
|
+
y1: elm.y1,
|
|
10575
|
+
x2: elm.x2,
|
|
10576
|
+
y2: elm.y2,
|
|
10577
|
+
strokeWidth: optional(elm.stroke_width),
|
|
10578
|
+
color: elm.color,
|
|
10579
|
+
isDashed: elm.is_dashed
|
|
10580
|
+
})
|
|
10535
10581
|
);
|
|
10582
|
+
} else if (elm.type === "schematic_rect") {
|
|
10583
|
+
addSchematicPrimitive(
|
|
10584
|
+
elm,
|
|
10585
|
+
new SchematicRect({
|
|
10586
|
+
schX: elm.center.x,
|
|
10587
|
+
schY: elm.center.y,
|
|
10588
|
+
width: elm.width,
|
|
10589
|
+
height: elm.height,
|
|
10590
|
+
rotation: elm.rotation,
|
|
10591
|
+
strokeWidth: optional(elm.stroke_width),
|
|
10592
|
+
color: elm.color,
|
|
10593
|
+
isFilled: elm.is_filled,
|
|
10594
|
+
fillColor: elm.fill_color,
|
|
10595
|
+
isDashed: elm.is_dashed
|
|
10596
|
+
})
|
|
10597
|
+
);
|
|
10598
|
+
} else if (elm.type === "schematic_circle") {
|
|
10599
|
+
addSchematicPrimitive(
|
|
10600
|
+
elm,
|
|
10601
|
+
new SchematicCircle({
|
|
10602
|
+
center: elm.center,
|
|
10603
|
+
radius: elm.radius,
|
|
10604
|
+
strokeWidth: optional(elm.stroke_width),
|
|
10605
|
+
color: elm.color,
|
|
10606
|
+
isFilled: elm.is_filled,
|
|
10607
|
+
fillColor: elm.fill_color,
|
|
10608
|
+
isDashed: elm.is_dashed
|
|
10609
|
+
})
|
|
10610
|
+
);
|
|
10611
|
+
} else if (elm.type === "schematic_arc") {
|
|
10612
|
+
addSchematicPrimitive(
|
|
10613
|
+
elm,
|
|
10614
|
+
new SchematicArc({
|
|
10615
|
+
center: elm.center,
|
|
10616
|
+
radius: elm.radius,
|
|
10617
|
+
startAngleDegrees: elm.start_angle_degrees,
|
|
10618
|
+
endAngleDegrees: elm.end_angle_degrees,
|
|
10619
|
+
direction: elm.direction,
|
|
10620
|
+
strokeWidth: optional(elm.stroke_width),
|
|
10621
|
+
color: elm.color,
|
|
10622
|
+
isDashed: elm.is_dashed
|
|
10623
|
+
})
|
|
10624
|
+
);
|
|
10625
|
+
} else if (elm.type === "schematic_text") {
|
|
10626
|
+
addSchematicPrimitive(
|
|
10627
|
+
elm,
|
|
10628
|
+
new SchematicText({
|
|
10629
|
+
schX: elm.position.x,
|
|
10630
|
+
schY: elm.position.y,
|
|
10631
|
+
text: elm.text,
|
|
10632
|
+
fontSize: elm.font_size,
|
|
10633
|
+
anchor: elm.anchor,
|
|
10634
|
+
color: elm.color,
|
|
10635
|
+
schRotation: elm.rotation
|
|
10636
|
+
})
|
|
10637
|
+
);
|
|
10638
|
+
} else if (elm.type === "schematic_path") {
|
|
10639
|
+
addSchematicPrimitive(
|
|
10640
|
+
elm,
|
|
10641
|
+
new SchematicPath({
|
|
10642
|
+
points: elm.points,
|
|
10643
|
+
strokeWidth: optional(elm.stroke_width),
|
|
10644
|
+
strokeColor: elm.stroke_color,
|
|
10645
|
+
dashLength: elm.dash_length,
|
|
10646
|
+
dashGap: elm.dash_gap,
|
|
10647
|
+
isFilled: elm.is_filled,
|
|
10648
|
+
fillColor: elm.fill_color
|
|
10649
|
+
})
|
|
10650
|
+
);
|
|
10651
|
+
} else if (elm.type === "schematic_port") {
|
|
10652
|
+
const schematicComponentId = elm.schematic_component_id;
|
|
10653
|
+
if (typeof schematicComponentId !== "string") continue;
|
|
10654
|
+
const schematicComponent = schematicComponentsByImportedId.get(schematicComponentId);
|
|
10655
|
+
const schematicSymbolId = schematicComponent?.schematic_symbol_id;
|
|
10656
|
+
const parentSymbol = typeof schematicSymbolId === "string" ? schematicSymbolsByImportedId.get(schematicSymbolId) : void 0;
|
|
10657
|
+
if (parentSymbol && schematicComponent?.is_box_with_pins === true && elm.center && elm.side_of_component) {
|
|
10658
|
+
const distance19 = elm.distance_from_component_edge;
|
|
10659
|
+
const facingDirection = getFacingDirectionFromSide(
|
|
10660
|
+
elm.side_of_component
|
|
10661
|
+
);
|
|
10662
|
+
if (!facingDirection) continue;
|
|
10663
|
+
const directionVector = getUnitVectorFromDirection2(facingDirection);
|
|
10664
|
+
const stemDirection = elm.facing_direction === facingDirection ? 1 : -1;
|
|
10665
|
+
const portCenter = {
|
|
10666
|
+
x: elm.center.x + directionVector.x * distance19 * stemDirection,
|
|
10667
|
+
y: elm.center.y + directionVector.y * distance19 * stemDirection
|
|
10668
|
+
};
|
|
10669
|
+
const sourcePort = sourcePortsByImportedId.get(elm.source_port_id);
|
|
10670
|
+
const aliases = Array.from(
|
|
10671
|
+
new Set(
|
|
10672
|
+
[
|
|
10673
|
+
elm.display_pin_label,
|
|
10674
|
+
sourcePort?.name,
|
|
10675
|
+
...sourcePort?.port_hints ?? []
|
|
10676
|
+
].filter(
|
|
10677
|
+
(alias) => typeof alias === "string" && alias.length > 0
|
|
10678
|
+
)
|
|
10679
|
+
)
|
|
10680
|
+
);
|
|
10681
|
+
const fallbackPortName = elm.pin_number ? `pin${elm.pin_number}` : elm.schematic_port_id;
|
|
10682
|
+
const portName = aliases[0] ?? elm.source_port_id ?? fallbackPortName;
|
|
10683
|
+
parentSymbol.add(
|
|
10684
|
+
new Port({
|
|
10685
|
+
pinNumber: elm.pin_number,
|
|
10686
|
+
name: portName,
|
|
10687
|
+
aliases,
|
|
10688
|
+
schX: elm.center.x,
|
|
10689
|
+
schY: elm.center.y,
|
|
10690
|
+
direction: facingDirection
|
|
10691
|
+
})
|
|
10692
|
+
);
|
|
10693
|
+
parentSymbol.add(
|
|
10694
|
+
new SchematicLine({
|
|
10695
|
+
x1: elm.center.x,
|
|
10696
|
+
y1: elm.center.y,
|
|
10697
|
+
x2: portCenter.x,
|
|
10698
|
+
y2: portCenter.y,
|
|
10699
|
+
strokeWidth: typeof schematicSymbolId === "string" ? optional(
|
|
10700
|
+
schematicStrokeWidthBySymbolId.get(schematicSymbolId)
|
|
10701
|
+
) : void 0,
|
|
10702
|
+
isDashed: false
|
|
10703
|
+
})
|
|
10704
|
+
);
|
|
10705
|
+
}
|
|
10536
10706
|
}
|
|
10537
10707
|
}
|
|
10538
|
-
|
|
10539
|
-
|
|
10540
|
-
|
|
10541
|
-
|
|
10542
|
-
|
|
10543
|
-
|
|
10544
|
-
|
|
10545
|
-
|
|
10546
|
-
|
|
10547
|
-
|
|
10548
|
-
const matchCenter2 = { x: connectedPcbPort.x, y: connectedPcbPort.y };
|
|
10549
|
-
const subcircuit2 = this.getSubcircuit();
|
|
10550
|
-
const pcb_port2 = db.pcb_port.insert({
|
|
10551
|
-
pcb_component_id: void 0,
|
|
10552
|
-
layers: connectedPort.getAvailablePcbLayers(),
|
|
10553
|
-
subcircuit_id: subcircuit2?.subcircuit_id ?? void 0,
|
|
10554
|
-
pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0,
|
|
10555
|
-
...matchCenter2,
|
|
10556
|
-
source_port_id: this.source_port_id,
|
|
10557
|
-
is_board_pinout: false
|
|
10558
|
-
});
|
|
10559
|
-
this.pcb_port_id = pcb_port2.pcb_port_id;
|
|
10560
|
-
return;
|
|
10561
|
-
}
|
|
10562
|
-
const pcbMatches = this.matchedComponents.filter((c) => c.isPcbPrimitive);
|
|
10563
|
-
if (pcbMatches.length === 0) return;
|
|
10564
|
-
let matchCenter = null;
|
|
10565
|
-
if (pcbMatches.length === 1) {
|
|
10566
|
-
matchCenter = pcbMatches[0]._getPcbCircuitJsonBounds().center;
|
|
10567
|
-
}
|
|
10568
|
-
if (pcbMatches.length > 1) {
|
|
10569
|
-
try {
|
|
10570
|
-
if (areAllPcbPrimitivesOverlapping(pcbMatches)) {
|
|
10571
|
-
matchCenter = getCenterOfPcbPrimitives(pcbMatches);
|
|
10572
|
-
}
|
|
10573
|
-
} catch {
|
|
10574
|
-
}
|
|
10575
|
-
}
|
|
10576
|
-
if (!matchCenter) return;
|
|
10577
|
-
const parentNormalComponent = this.getParentNormalComponent();
|
|
10578
|
-
const parentWithPcbComponentId = this.parent?.pcb_component_id ? this.parent : parentNormalComponent;
|
|
10579
|
-
const subcircuit = this.getSubcircuit();
|
|
10580
|
-
const isBoardPinout = this._shouldIncludeInBoardPinout();
|
|
10581
|
-
const pcb_port = db.pcb_port.insert({
|
|
10582
|
-
pcb_component_id: parentWithPcbComponentId?.pcb_component_id,
|
|
10583
|
-
layers: this.getAvailablePcbLayers(),
|
|
10584
|
-
subcircuit_id: subcircuit?.subcircuit_id ?? void 0,
|
|
10585
|
-
pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0,
|
|
10586
|
-
...isBoardPinout ? { is_board_pinout: true } : {},
|
|
10587
|
-
...matchCenter,
|
|
10588
|
-
source_port_id: this.source_port_id,
|
|
10589
|
-
is_board_pinout: this._isBoardPinoutFromAttributes()
|
|
10590
|
-
});
|
|
10591
|
-
this.pcb_port_id = pcb_port.pcb_port_id;
|
|
10592
|
-
}
|
|
10593
|
-
/**
|
|
10594
|
-
* Get the best display label for this port based on port_hints
|
|
10595
|
-
* Filters out generic patterns and applies showPinAliases logic
|
|
10596
|
-
*/
|
|
10597
|
-
_getBestDisplayPinLabel() {
|
|
10598
|
-
const { db } = this.root;
|
|
10599
|
-
const sourcePort = db.source_port.get(this.source_port_id);
|
|
10600
|
-
const labelHints = [];
|
|
10601
|
-
for (const portHint of sourcePort?.port_hints ?? []) {
|
|
10602
|
-
if (portHint.match(/^(pin)?\d+$/)) continue;
|
|
10603
|
-
if (portHint.match(/^(left|right)/) && !sourcePort?.name.match(/^(left|right)/))
|
|
10604
|
-
continue;
|
|
10605
|
-
labelHints.push(portHint);
|
|
10606
|
-
}
|
|
10607
|
-
const parentNormalComponent = this.getParentNormalComponent();
|
|
10608
|
-
const showPinAliases = parentNormalComponent?.props?.showPinAliases;
|
|
10609
|
-
if (showPinAliases && labelHints.length > 0) {
|
|
10610
|
-
return labelHints.join("/");
|
|
10611
|
-
} else if (labelHints.length > 0) {
|
|
10612
|
-
return labelHints[0];
|
|
10613
|
-
}
|
|
10614
|
-
return void 0;
|
|
10615
|
-
}
|
|
10616
|
-
doInitialSchematicPortRender() {
|
|
10617
|
-
const collapsedAncestor = this.getCollapsedSchematicBoxAncestor();
|
|
10618
|
-
if (collapsedAncestor && this.parent !== collapsedAncestor) return;
|
|
10619
|
-
const { db } = this.root;
|
|
10620
|
-
const { _parsedProps: props } = this;
|
|
10621
|
-
const { schX, schY } = props;
|
|
10622
|
-
const container = schX !== void 0 && schY !== void 0 ? this.getParentNormalComponent() : this.getPrimitiveContainer();
|
|
10623
|
-
if (!container) return;
|
|
10624
|
-
if (!this._hasSchematicPort()) return;
|
|
10625
|
-
const containerCenter = container._getGlobalSchematicPositionBeforeLayout();
|
|
10626
|
-
const portCenter = this._getGlobalSchematicPositionBeforeLayout();
|
|
10627
|
-
let localPortInfo = null;
|
|
10628
|
-
const containerDims = container._getSchematicBoxDimensions();
|
|
10629
|
-
if (containerDims && props.pinNumber !== void 0) {
|
|
10630
|
-
localPortInfo = containerDims.getPortPositionByPinNumber(props.pinNumber);
|
|
10631
|
-
}
|
|
10632
|
-
if (this.getSubcircuit().props._schDebugObjectsEnabled) {
|
|
10633
|
-
db.schematic_debug_object.insert({
|
|
10634
|
-
shape: "rect",
|
|
10635
|
-
center: portCenter,
|
|
10636
|
-
size: {
|
|
10637
|
-
width: 0.1,
|
|
10638
|
-
height: 0.1
|
|
10639
|
-
},
|
|
10640
|
-
label: "obstacle"
|
|
10641
|
-
});
|
|
10642
|
-
}
|
|
10643
|
-
if (!localPortInfo?.side) {
|
|
10644
|
-
this.facingDirection = getRelativeDirection(containerCenter, portCenter);
|
|
10645
|
-
} else {
|
|
10646
|
-
this.facingDirection = {
|
|
10647
|
-
left: "left",
|
|
10648
|
-
right: "right",
|
|
10649
|
-
top: "up",
|
|
10650
|
-
bottom: "down"
|
|
10651
|
-
}[localPortInfo.side];
|
|
10652
|
-
}
|
|
10653
|
-
const bestDisplayPinLabel = this._getBestDisplayPinLabel();
|
|
10654
|
-
const parentNormalComponent = this.getParentNormalComponent();
|
|
10655
|
-
const sideOfComponent = localPortInfo?.side ?? (props.direction === "up" ? "top" : props.direction === "down" ? "bottom" : props.direction);
|
|
10656
|
-
const schematicPortInsertProps = {
|
|
10657
|
-
type: "schematic_port",
|
|
10658
|
-
schematic_component_id: parentNormalComponent?.schematic_component_id,
|
|
10659
|
-
center: portCenter,
|
|
10660
|
-
source_port_id: this.source_port_id,
|
|
10661
|
-
facing_direction: this.facingDirection,
|
|
10662
|
-
distance_from_component_edge: props.schStemLength ?? 0.4,
|
|
10663
|
-
side_of_component: sideOfComponent,
|
|
10664
|
-
pin_number: props.pinNumber,
|
|
10665
|
-
true_ccw_index: localPortInfo?.trueIndex,
|
|
10666
|
-
display_pin_label: bestDisplayPinLabel,
|
|
10667
|
-
is_connected: false
|
|
10708
|
+
return components;
|
|
10709
|
+
};
|
|
10710
|
+
|
|
10711
|
+
// lib/utils/filterPinLabels.ts
|
|
10712
|
+
import { chipProps } from "@tscircuit/props";
|
|
10713
|
+
function filterPinLabels(pinLabels) {
|
|
10714
|
+
if (!pinLabels)
|
|
10715
|
+
return {
|
|
10716
|
+
validPinLabels: pinLabels,
|
|
10717
|
+
invalidPinLabelsMessages: []
|
|
10668
10718
|
};
|
|
10669
|
-
|
|
10670
|
-
|
|
10671
|
-
|
|
10672
|
-
|
|
10673
|
-
|
|
10674
|
-
|
|
10719
|
+
const validPinLabels = {};
|
|
10720
|
+
const invalidPinLabelsMessages = [];
|
|
10721
|
+
for (const [pin, labelOrLabels] of Object.entries(pinLabels)) {
|
|
10722
|
+
const labels = Array.isArray(labelOrLabels) ? labelOrLabels.slice() : [labelOrLabels];
|
|
10723
|
+
const validLabels = [];
|
|
10724
|
+
for (const label of labels) {
|
|
10725
|
+
if (isValidPinLabel(pin, label)) {
|
|
10726
|
+
validLabels.push(label);
|
|
10727
|
+
} else {
|
|
10728
|
+
invalidPinLabelsMessages.push(
|
|
10729
|
+
`Invalid pin label: ${pin} = '${label}' - excluding from component. Pin labels can only contain letters, numbers and underscores.`
|
|
10730
|
+
);
|
|
10675
10731
|
}
|
|
10676
10732
|
}
|
|
10677
|
-
|
|
10678
|
-
|
|
10679
|
-
if (props.schStemLength !== void 0 && props.schStemLength !== 0) {
|
|
10680
|
-
const { schStemLength, direction } = props;
|
|
10681
|
-
let x2 = portCenter.x;
|
|
10682
|
-
let y2 = portCenter.y;
|
|
10683
|
-
if (direction === "right") x2 -= schStemLength;
|
|
10684
|
-
else if (direction === "left") x2 += schStemLength;
|
|
10685
|
-
else if (direction === "up") y2 -= schStemLength;
|
|
10686
|
-
else if (direction === "down") y2 += schStemLength;
|
|
10687
|
-
const stemLine = db.schematic_line.insert({
|
|
10688
|
-
schematic_component_id: parentNormalComponent?.schematic_component_id,
|
|
10689
|
-
x1: portCenter.x,
|
|
10690
|
-
y1: portCenter.y,
|
|
10691
|
-
x2,
|
|
10692
|
-
y2,
|
|
10693
|
-
stroke_width: 0.02,
|
|
10694
|
-
color: SCHEMATIC_COMPONENT_OUTLINE_COLOR,
|
|
10695
|
-
is_dashed: false
|
|
10696
|
-
});
|
|
10697
|
-
this.schematic_stem_line_id = stemLine.schematic_line_id;
|
|
10733
|
+
if (validLabels.length > 0) {
|
|
10734
|
+
validPinLabels[pin] = Array.isArray(labelOrLabels) ? validLabels : validLabels[0];
|
|
10698
10735
|
}
|
|
10699
10736
|
}
|
|
10700
|
-
|
|
10701
|
-
|
|
10702
|
-
|
|
10703
|
-
|
|
10704
|
-
|
|
10705
|
-
|
|
10706
|
-
|
|
10707
|
-
const
|
|
10708
|
-
|
|
10709
|
-
|
|
10710
|
-
|
|
10711
|
-
|
|
10712
|
-
|
|
10713
|
-
|
|
10714
|
-
|
|
10715
|
-
|
|
10716
|
-
|
|
10717
|
-
|
|
10718
|
-
|
|
10719
|
-
|
|
10720
|
-
|
|
10721
|
-
|
|
10722
|
-
|
|
10723
|
-
|
|
10724
|
-
|
|
10725
|
-
|
|
10726
|
-
|
|
10727
|
-
|
|
10728
|
-
|
|
10729
|
-
|
|
10730
|
-
|
|
10737
|
+
return {
|
|
10738
|
+
validPinLabels: Object.keys(validPinLabels).length > 0 ? validPinLabels : void 0,
|
|
10739
|
+
invalidPinLabelsMessages
|
|
10740
|
+
};
|
|
10741
|
+
}
|
|
10742
|
+
function isValidPinLabel(pin, label) {
|
|
10743
|
+
try {
|
|
10744
|
+
const testProps = {
|
|
10745
|
+
name: "test",
|
|
10746
|
+
footprint: "test",
|
|
10747
|
+
pinLabels: { [pin]: label }
|
|
10748
|
+
};
|
|
10749
|
+
const result = chipProps.safeParse(testProps);
|
|
10750
|
+
return result.success;
|
|
10751
|
+
} catch (error) {
|
|
10752
|
+
return false;
|
|
10753
|
+
}
|
|
10754
|
+
}
|
|
10755
|
+
|
|
10756
|
+
// lib/utils/get-bounds-of-pcb-components.ts
|
|
10757
|
+
var NON_PHYSICAL_PCB_PRIMITIVE_PREFIXES = [
|
|
10758
|
+
"Silkscreen",
|
|
10759
|
+
"PcbNote",
|
|
10760
|
+
"Courtyard",
|
|
10761
|
+
"FabricationNote"
|
|
10762
|
+
];
|
|
10763
|
+
function getBoundsOfPcbComponents(components) {
|
|
10764
|
+
let minX = Infinity;
|
|
10765
|
+
let minY = Infinity;
|
|
10766
|
+
let maxX = -Infinity;
|
|
10767
|
+
let maxY = -Infinity;
|
|
10768
|
+
let hasValidComponents = false;
|
|
10769
|
+
for (const child of components) {
|
|
10770
|
+
if (child.isPcbPrimitive && !NON_PHYSICAL_PCB_PRIMITIVE_PREFIXES.some(
|
|
10771
|
+
(prefix) => child.componentName.startsWith(prefix)
|
|
10772
|
+
)) {
|
|
10773
|
+
const { x, y } = child._getGlobalPcbPositionBeforeLayout();
|
|
10774
|
+
const { width: width2, height: height2 } = child.getPcbSize();
|
|
10775
|
+
minX = Math.min(minX, x - width2 / 2);
|
|
10776
|
+
minY = Math.min(minY, y - height2 / 2);
|
|
10777
|
+
maxX = Math.max(maxX, x + width2 / 2);
|
|
10778
|
+
maxY = Math.max(maxY, y + height2 / 2);
|
|
10779
|
+
hasValidComponents = true;
|
|
10780
|
+
} else if (child.children.length > 0) {
|
|
10781
|
+
const childBounds = getBoundsOfPcbComponents(child.children);
|
|
10782
|
+
if (childBounds.width > 0 || childBounds.height > 0) {
|
|
10783
|
+
minX = Math.min(minX, childBounds.minX);
|
|
10784
|
+
minY = Math.min(minY, childBounds.minY);
|
|
10785
|
+
maxX = Math.max(maxX, childBounds.maxX);
|
|
10786
|
+
maxY = Math.max(maxY, childBounds.maxY);
|
|
10787
|
+
hasValidComponents = true;
|
|
10731
10788
|
}
|
|
10732
10789
|
}
|
|
10733
10790
|
}
|
|
10734
|
-
|
|
10735
|
-
return
|
|
10736
|
-
|
|
10737
|
-
|
|
10738
|
-
|
|
10739
|
-
|
|
10740
|
-
|
|
10741
|
-
|
|
10742
|
-
|
|
10743
|
-
});
|
|
10744
|
-
}
|
|
10745
|
-
_hasMatchedPcbPrimitive() {
|
|
10746
|
-
return this.matchedComponents.some((c) => c.isPcbPrimitive);
|
|
10747
|
-
}
|
|
10748
|
-
/**
|
|
10749
|
-
* Return the text that should be used for the net label for this port if a
|
|
10750
|
-
* trace can't be drawn. This net label text usually doesn't appear at this
|
|
10751
|
-
* port, but appears at the port it connects to.
|
|
10752
|
-
*/
|
|
10753
|
-
_getNetLabelText() {
|
|
10754
|
-
return `${this.parent?.props.name}_${this.props.name}`;
|
|
10791
|
+
if (!hasValidComponents) {
|
|
10792
|
+
return {
|
|
10793
|
+
minX: 0,
|
|
10794
|
+
minY: 0,
|
|
10795
|
+
maxX: 0,
|
|
10796
|
+
maxY: 0,
|
|
10797
|
+
width: 0,
|
|
10798
|
+
height: 0
|
|
10799
|
+
};
|
|
10755
10800
|
}
|
|
10756
|
-
|
|
10801
|
+
let width = maxX - minX;
|
|
10802
|
+
let height = maxY - minY;
|
|
10803
|
+
if (width < 0) width = 0;
|
|
10804
|
+
if (height < 0) height = 0;
|
|
10805
|
+
return {
|
|
10806
|
+
minX,
|
|
10807
|
+
minY,
|
|
10808
|
+
maxX,
|
|
10809
|
+
maxY,
|
|
10810
|
+
width,
|
|
10811
|
+
height
|
|
10812
|
+
};
|
|
10813
|
+
}
|
|
10757
10814
|
|
|
10758
10815
|
// lib/utils/getPortFromHints.ts
|
|
10759
10816
|
var getPinNumberFromLabels = (labels) => {
|
|
@@ -23429,7 +23486,7 @@ import { identity as identity5 } from "transformation-matrix";
|
|
|
23429
23486
|
var package_default = {
|
|
23430
23487
|
name: "@tscircuit/core",
|
|
23431
23488
|
type: "module",
|
|
23432
|
-
version: "0.0.
|
|
23489
|
+
version: "0.0.1306",
|
|
23433
23490
|
types: "dist/index.d.ts",
|
|
23434
23491
|
main: "dist/index.js",
|
|
23435
23492
|
module: "dist/index.js",
|