@tscircuit/cli 0.1.1392 → 0.1.1393
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/cli/main.js +1239 -627
- package/dist/lib/index.js +2 -2
- package/package.json +2 -2
package/dist/cli/main.js
CHANGED
|
@@ -100616,7 +100616,7 @@ var import_perfect_cli = __toESM2(require_dist2(), 1);
|
|
|
100616
100616
|
// lib/getVersion.ts
|
|
100617
100617
|
import { createRequire as createRequire2 } from "node:module";
|
|
100618
100618
|
// package.json
|
|
100619
|
-
var version = "0.1.
|
|
100619
|
+
var version = "0.1.1392";
|
|
100620
100620
|
var package_default = {
|
|
100621
100621
|
name: "@tscircuit/cli",
|
|
100622
100622
|
version,
|
|
@@ -100630,7 +100630,7 @@ var package_default = {
|
|
|
100630
100630
|
"@biomejs/biome": "^1.9.4",
|
|
100631
100631
|
"@tscircuit/circuit-json-placement-analysis": "^0.0.6",
|
|
100632
100632
|
"@tscircuit/circuit-json-routing-analysis": "^0.0.1",
|
|
100633
|
-
"@tscircuit/circuit-json-schematic-placement-analysis": "github:tscircuit/circuit-json-schematic-placement-analysis#
|
|
100633
|
+
"@tscircuit/circuit-json-schematic-placement-analysis": "github:tscircuit/circuit-json-schematic-placement-analysis#700017d79a608295cc275dcb9c2e1d160809ef9e",
|
|
100634
100634
|
"@tscircuit/eval": "^0.0.835",
|
|
100635
100635
|
"@tscircuit/fake-snippets": "^0.0.182",
|
|
100636
100636
|
"@tscircuit/file-server": "^0.0.32",
|
|
@@ -244242,647 +244242,1254 @@ var registerCheckRoutingDifficulty = (program2) => {
|
|
|
244242
244242
|
});
|
|
244243
244243
|
};
|
|
244244
244244
|
|
|
244245
|
-
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/
|
|
244246
|
-
import {
|
|
244245
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/SchematicPlacementPipeline/SchematicPlacementPipeline.ts
|
|
244246
|
+
import {
|
|
244247
|
+
BasePipelineSolver as BasePipelineSolver2,
|
|
244248
|
+
definePipelineStep as definePipelineStep3
|
|
244249
|
+
} from "@tscircuit/solver-utils";
|
|
244247
244250
|
|
|
244248
|
-
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/
|
|
244249
|
-
|
|
244250
|
-
|
|
244251
|
-
|
|
244252
|
-
|
|
244253
|
-
var isSchematicComponent = (element) => element.type === "schematic_component";
|
|
244254
|
-
var isSourceCapacitor = (circuitJson, sourceComponentId) => {
|
|
244251
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/utils/placements.ts
|
|
244252
|
+
import { cju as cju7 } from "@tscircuit/circuit-json-util";
|
|
244253
|
+
var isSchematicBox = (el3) => el3.type === "schematic_box";
|
|
244254
|
+
var isSchematicComponent = (el3) => el3.type === "schematic_component";
|
|
244255
|
+
var getSourceComponentName = (circuitJson, sourceComponentId) => {
|
|
244255
244256
|
if (!sourceComponentId)
|
|
244256
|
-
return
|
|
244257
|
-
return circuitJson
|
|
244258
|
-
};
|
|
244259
|
-
var generateCapacitorOrientationIssues = (componentPlacements, circuitJson) => {
|
|
244260
|
-
const placementBySchematicComponentId = new Map(componentPlacements.filter((placement) => placement.schematicComponentId).map((placement) => [placement.schematicComponentId, placement]));
|
|
244261
|
-
return circuitJson.filter(isSchematicComponent).filter((schematicComponent) => isSourceCapacitor(circuitJson, schematicComponent.source_component_id) && HORIZONTAL_CAPACITOR_SYMBOL_NAMES.has(schematicComponent.symbol_name ?? "")).flatMap((schematicComponent) => {
|
|
244262
|
-
const schematicBox = placementBySchematicComponentId.get(schematicComponent.schematic_component_id);
|
|
244263
|
-
if (!schematicBox)
|
|
244264
|
-
return [];
|
|
244265
|
-
return [
|
|
244266
|
-
{
|
|
244267
|
-
lineItemType: "CapacitorSymbolHorizontal",
|
|
244268
|
-
schematicBox
|
|
244269
|
-
}
|
|
244270
|
-
];
|
|
244271
|
-
});
|
|
244257
|
+
return;
|
|
244258
|
+
return cju7(circuitJson).source_component.get(sourceComponentId)?.name;
|
|
244272
244259
|
};
|
|
244273
|
-
|
|
244274
|
-
|
|
244275
|
-
|
|
244276
|
-
|
|
244277
|
-
|
|
244278
|
-
|
|
244279
|
-
|
|
244280
|
-
|
|
244281
|
-
var FALLBACK_CHARACTER_WIDTH = 0.13;
|
|
244282
|
-
var GAP_COMPARISON_EPSILON = 0.000000001;
|
|
244283
|
-
var isSchematicPort = (element) => element.type === "schematic_port";
|
|
244284
|
-
var isSourcePort = (element) => element.type === "source_port";
|
|
244285
|
-
var isSchematicComponent2 = (element) => element.type === "schematic_component";
|
|
244286
|
-
var getSourceComponentWithFtype = (element) => {
|
|
244287
|
-
if (element.type !== "source_component" || !("source_component_id" in element) || typeof element.source_component_id !== "string") {
|
|
244288
|
-
return null;
|
|
244289
|
-
}
|
|
244260
|
+
var getSourceComponentMetadata = (schematicBox, circuitJson) => {
|
|
244261
|
+
if (!schematicBox.schematic_component_id)
|
|
244262
|
+
return {};
|
|
244263
|
+
const util2 = cju7(circuitJson);
|
|
244264
|
+
const sc2 = util2.schematic_component.get(schematicBox.schematic_component_id);
|
|
244265
|
+
if (!sc2?.source_component_id)
|
|
244266
|
+
return {};
|
|
244267
|
+
const sourceComponent = util2.source_component.get(sc2.source_component_id);
|
|
244290
244268
|
return {
|
|
244291
|
-
|
|
244292
|
-
|
|
244293
|
-
ftype: "ftype" in element && typeof element.ftype === "string" ? element.ftype : undefined
|
|
244269
|
+
sourceComponentId: sc2.source_component_id,
|
|
244270
|
+
sourceComponentName: sourceComponent?.name
|
|
244294
244271
|
};
|
|
244295
244272
|
};
|
|
244296
|
-
var
|
|
244297
|
-
|
|
244298
|
-
|
|
244299
|
-
|
|
244300
|
-
|
|
244273
|
+
var schematicComponentToPlacement = (schematicComponent, circuitJson, schematicBox) => ({
|
|
244274
|
+
lineItemType: "SchematicBoxPlacement",
|
|
244275
|
+
positionAnchor: "center",
|
|
244276
|
+
schX: schematicComponent.center.x,
|
|
244277
|
+
schY: schematicComponent.center.y,
|
|
244278
|
+
width: schematicBox?.width ?? schematicComponent.size.width,
|
|
244279
|
+
height: schematicBox?.height ?? schematicComponent.size.height,
|
|
244280
|
+
sourceComponentId: schematicComponent.source_component_id,
|
|
244281
|
+
sourceComponentName: getSourceComponentName(circuitJson, schematicComponent.source_component_id),
|
|
244282
|
+
schematicComponentId: schematicComponent.schematic_component_id,
|
|
244283
|
+
schematicSymbolId: schematicBox?.schematic_symbol_id ?? schematicComponent.schematic_symbol_id,
|
|
244284
|
+
subcircuitId: schematicComponent.subcircuit_id ?? schematicBox?.subcircuit_id
|
|
244285
|
+
});
|
|
244286
|
+
var schematicBoxToPlacement = (schematicBox, circuitJson) => ({
|
|
244287
|
+
lineItemType: "SchematicBoxPlacement",
|
|
244288
|
+
positionAnchor: "center",
|
|
244289
|
+
schX: schematicBox.x,
|
|
244290
|
+
schY: schematicBox.y,
|
|
244291
|
+
width: schematicBox.width,
|
|
244292
|
+
height: schematicBox.height,
|
|
244293
|
+
...getSourceComponentMetadata(schematicBox, circuitJson),
|
|
244294
|
+
schematicComponentId: schematicBox.schematic_component_id,
|
|
244295
|
+
schematicSymbolId: schematicBox.schematic_symbol_id,
|
|
244296
|
+
subcircuitId: schematicBox.subcircuit_id
|
|
244297
|
+
});
|
|
244298
|
+
var buildSolverContext = (circuitJson) => {
|
|
244299
|
+
const schematicBoxes = circuitJson.filter(isSchematicBox);
|
|
244300
|
+
const schematicComponentIds = new Set(circuitJson.filter(isSchematicComponent).map((sc2) => sc2.schematic_component_id));
|
|
244301
|
+
const componentPlacements = [
|
|
244302
|
+
...circuitJson.filter(isSchematicComponent).map((sc2) => schematicComponentToPlacement(sc2, circuitJson, schematicBoxes.find((sb2) => sb2.schematic_component_id === sc2.schematic_component_id))),
|
|
244303
|
+
...schematicBoxes.filter((sb2) => !sb2.schematic_component_id || !schematicComponentIds.has(sb2.schematic_component_id)).map((sb2) => schematicBoxToPlacement(sb2, circuitJson))
|
|
244304
|
+
];
|
|
244305
|
+
return { circuitJson, componentPlacements };
|
|
244306
|
+
};
|
|
244307
|
+
|
|
244308
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/CapacitorOrientationSolver/CapacitorOrientationSolver.ts
|
|
244309
|
+
import { BaseSolver as BaseSolver6 } from "@tscircuit/solver-utils";
|
|
244310
|
+
|
|
244311
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/utils/graphics.ts
|
|
244312
|
+
import { mergeGraphics as mergeGraphics2 } from "graphics-debug";
|
|
244313
|
+
function mergeGraphicsObjects2(objects) {
|
|
244314
|
+
return objects.filter((o3) => o3 !== undefined).reduce((acc, o3) => mergeGraphics2(acc, o3), {});
|
|
244315
|
+
}
|
|
244316
|
+
function highlightPlacement(placement, color, label) {
|
|
244301
244317
|
return {
|
|
244302
|
-
|
|
244303
|
-
|
|
244304
|
-
|
|
244305
|
-
|
|
244318
|
+
rects: [
|
|
244319
|
+
{
|
|
244320
|
+
center: { x: placement.schX, y: placement.schY },
|
|
244321
|
+
width: placement.width,
|
|
244322
|
+
height: placement.height,
|
|
244323
|
+
stroke: color,
|
|
244324
|
+
fill: color.replace("0.95", "0.15"),
|
|
244325
|
+
label
|
|
244326
|
+
}
|
|
244327
|
+
]
|
|
244306
244328
|
};
|
|
244329
|
+
}
|
|
244330
|
+
function visualizeCircuitJson(circuitJson) {
|
|
244331
|
+
const rects = circuitJson.filter((el3) => el3.type === "schematic_box").map((el3) => {
|
|
244332
|
+
const box2 = el3;
|
|
244333
|
+
return {
|
|
244334
|
+
center: { x: box2.x, y: box2.y },
|
|
244335
|
+
width: box2.width,
|
|
244336
|
+
height: box2.height,
|
|
244337
|
+
stroke: "hsl(0,0%,60%)"
|
|
244338
|
+
};
|
|
244339
|
+
});
|
|
244340
|
+
return { rects };
|
|
244341
|
+
}
|
|
244342
|
+
|
|
244343
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/utils/format.ts
|
|
244344
|
+
var fmtNumber5 = (value) => {
|
|
244345
|
+
if (Number.isInteger(value))
|
|
244346
|
+
return String(value);
|
|
244347
|
+
return value.toFixed(3).replace(/\.0+$/, "").replace(/(\.\d*?)0+$/, "$1");
|
|
244307
244348
|
};
|
|
244308
|
-
var
|
|
244309
|
-
|
|
244310
|
-
|
|
244311
|
-
|
|
244312
|
-
|
|
244313
|
-
var
|
|
244314
|
-
|
|
244315
|
-
|
|
244316
|
-
|
|
244317
|
-
|
|
244318
|
-
|
|
244319
|
-
|
|
244320
|
-
|
|
244321
|
-
|
|
244322
|
-
|
|
244323
|
-
|
|
244324
|
-
|
|
244325
|
-
|
|
244326
|
-
|
|
244327
|
-
|
|
244328
|
-
|
|
244329
|
-
|
|
244330
|
-
|
|
244331
|
-
|
|
244332
|
-
|
|
244333
|
-
|
|
244334
|
-
|
|
244335
|
-
|
|
244336
|
-
|
|
244337
|
-
|
|
244338
|
-
|
|
244339
|
-
|
|
244340
|
-
|
|
244341
|
-
|
|
244342
|
-
|
|
244349
|
+
var fmtDelta = (value) => {
|
|
244350
|
+
const formatted = fmtNumber5(value);
|
|
244351
|
+
return value > 0 ? `+${formatted}` : formatted;
|
|
244352
|
+
};
|
|
244353
|
+
var escapeAttr3 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">");
|
|
244354
|
+
var addAttr = (attrs, key, value, options) => {
|
|
244355
|
+
if (value === undefined)
|
|
244356
|
+
return;
|
|
244357
|
+
const stringValue = typeof value === "number" ? options?.formatDelta ? fmtDelta(value) : fmtNumber5(value) : options?.escape === false ? value : escapeAttr3(value);
|
|
244358
|
+
attrs.push(`${key}="${stringValue}"`);
|
|
244359
|
+
};
|
|
244360
|
+
|
|
244361
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/CapacitorOrientationSolver/CapacitorOrientationSolver.ts
|
|
244362
|
+
class CapacitorOrientationSolver extends BaseSolver6 {
|
|
244363
|
+
ctx;
|
|
244364
|
+
out;
|
|
244365
|
+
schematicComponentById;
|
|
244366
|
+
sourceComponentById;
|
|
244367
|
+
capacitorPlacements;
|
|
244368
|
+
currentPlacementIndex = 0;
|
|
244369
|
+
horizontalSymbolNames = new Set([
|
|
244370
|
+
"capacitor_left",
|
|
244371
|
+
"capacitor_right"
|
|
244372
|
+
]);
|
|
244373
|
+
constructor({
|
|
244374
|
+
ctx,
|
|
244375
|
+
issues: out
|
|
244376
|
+
}) {
|
|
244377
|
+
super();
|
|
244378
|
+
this.ctx = ctx;
|
|
244379
|
+
this.out = out;
|
|
244380
|
+
this.schematicComponentById = this.buildSchematicComponentById(ctx.circuitJson);
|
|
244381
|
+
this.sourceComponentById = this.buildSourceComponentById(ctx.circuitJson);
|
|
244382
|
+
this.capacitorPlacements = this.getCapacitorPlacements();
|
|
244383
|
+
this.solved = this.capacitorPlacements.length === 0;
|
|
244384
|
+
}
|
|
244385
|
+
getCapacitorPlacements() {
|
|
244386
|
+
return this.ctx.componentPlacements.filter((p3) => p3.sourceComponentId !== undefined && this.sourceComponentById.get(p3.sourceComponentId)?.ftype === "simple_capacitor").map((p3) => ({
|
|
244387
|
+
schX: p3.schX,
|
|
244388
|
+
schY: p3.schY,
|
|
244389
|
+
width: p3.width,
|
|
244390
|
+
height: p3.height,
|
|
244391
|
+
sourceComponentId: p3.sourceComponentId,
|
|
244392
|
+
sourceComponentName: p3.sourceComponentName,
|
|
244393
|
+
schematicComponentId: p3.schematicComponentId
|
|
244394
|
+
}));
|
|
244395
|
+
}
|
|
244396
|
+
_step() {
|
|
244397
|
+
const currentPlacement = this.capacitorPlacements[this.currentPlacementIndex];
|
|
244398
|
+
if (!currentPlacement) {
|
|
244399
|
+
this.solved = true;
|
|
244400
|
+
return;
|
|
244343
244401
|
}
|
|
244402
|
+
this.currentPlacementIndex += 1;
|
|
244403
|
+
this.solved = this.currentPlacementIndex >= this.capacitorPlacements.length;
|
|
244404
|
+
const issue = this.getIssueForPlacement(currentPlacement);
|
|
244405
|
+
if (issue)
|
|
244406
|
+
this.out.push(issue);
|
|
244344
244407
|
}
|
|
244345
|
-
|
|
244346
|
-
|
|
244347
|
-
|
|
244408
|
+
visualize() {
|
|
244409
|
+
const focusedPlacement = this.getFocusedPlacement();
|
|
244410
|
+
return mergeGraphicsObjects2([
|
|
244411
|
+
visualizeCircuitJson(this.ctx.circuitJson),
|
|
244412
|
+
focusedPlacement ? highlightPlacement(focusedPlacement, "hsl(210, 100%, 50%, 0.95)", "capacitorOrientation") : undefined
|
|
244413
|
+
]);
|
|
244414
|
+
}
|
|
244415
|
+
getFocusedPlacement() {
|
|
244416
|
+
if (this.capacitorPlacements.length === 0)
|
|
244417
|
+
return;
|
|
244418
|
+
const index = this.iterations === 0 ? this.currentPlacementIndex : Math.max(0, this.currentPlacementIndex - 1);
|
|
244419
|
+
return this.capacitorPlacements[index];
|
|
244420
|
+
}
|
|
244421
|
+
buildSchematicComponentById(circuitJson) {
|
|
244422
|
+
return new Map(circuitJson.filter((el3) => el3.type === "schematic_component").map((sc2) => [sc2.schematic_component_id, sc2]));
|
|
244423
|
+
}
|
|
244424
|
+
buildSourceComponentById(circuitJson) {
|
|
244425
|
+
return new Map(circuitJson.flatMap((el3) => {
|
|
244426
|
+
if (el3.type !== "source_component" || !("source_component_id" in el3) || typeof el3.source_component_id !== "string")
|
|
244427
|
+
return [];
|
|
244428
|
+
return [
|
|
244429
|
+
{
|
|
244430
|
+
type: "source_component",
|
|
244431
|
+
source_component_id: el3.source_component_id,
|
|
244432
|
+
ftype: "ftype" in el3 && typeof el3.ftype === "string" ? el3.ftype : undefined
|
|
244433
|
+
}
|
|
244434
|
+
];
|
|
244435
|
+
}).map((sc2) => [sc2.source_component_id, sc2]));
|
|
244436
|
+
}
|
|
244437
|
+
createIssuePlacement(placement) {
|
|
244438
|
+
return {
|
|
244439
|
+
positionAnchor: "center",
|
|
244440
|
+
schX: placement.schX,
|
|
244441
|
+
schY: placement.schY,
|
|
244442
|
+
width: placement.width,
|
|
244443
|
+
height: placement.height,
|
|
244444
|
+
sourceComponentId: placement.sourceComponentId,
|
|
244445
|
+
sourceComponentName: placement.sourceComponentName,
|
|
244446
|
+
schematicComponentId: placement.schematicComponentId
|
|
244447
|
+
};
|
|
244448
|
+
}
|
|
244449
|
+
getIssueForPlacement(placement) {
|
|
244450
|
+
if (!placement.schematicComponentId || !placement.sourceComponentId)
|
|
244451
|
+
return;
|
|
244452
|
+
const schematicComponent = this.schematicComponentById.get(placement.schematicComponentId);
|
|
244453
|
+
if (!schematicComponent)
|
|
244454
|
+
return;
|
|
244455
|
+
if (!this.horizontalSymbolNames.has(schematicComponent.symbol_name ?? ""))
|
|
244456
|
+
return;
|
|
244457
|
+
return {
|
|
244458
|
+
lineItemType: "CapacitorSymbolHorizontal",
|
|
244459
|
+
schematicBox: this.createIssuePlacement(placement)
|
|
244460
|
+
};
|
|
244461
|
+
}
|
|
244462
|
+
static issueToString(issue) {
|
|
244463
|
+
const attrs = [];
|
|
244464
|
+
addAttr(attrs, "componentName", issue.schematicBox.sourceComponentName);
|
|
244465
|
+
addAttr(attrs, "schX", issue.schematicBox.schX);
|
|
244466
|
+
addAttr(attrs, "schY", issue.schematicBox.schY);
|
|
244467
|
+
addAttr(attrs, "width", issue.schematicBox.width);
|
|
244468
|
+
addAttr(attrs, "height", issue.schematicBox.height);
|
|
244469
|
+
return `<CapacitorSymbolHorizontal ${attrs.join(" ")} />`;
|
|
244470
|
+
}
|
|
244471
|
+
}
|
|
244348
244472
|
|
|
244349
|
-
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/
|
|
244350
|
-
|
|
244351
|
-
|
|
244352
|
-
|
|
244353
|
-
|
|
244354
|
-
|
|
244355
|
-
|
|
244356
|
-
|
|
244357
|
-
|
|
244358
|
-
|
|
244359
|
-
|
|
244360
|
-
|
|
244361
|
-
if (port.display_pin_label)
|
|
244362
|
-
return port.display_pin_label;
|
|
244363
|
-
if (sourcePort?.pin_number !== undefined)
|
|
244364
|
-
return String(sourcePort.pin_number);
|
|
244365
|
-
return;
|
|
244366
|
-
};
|
|
244367
|
-
var getMaxLabelLengthBySide = (ports, sourcePortById) => {
|
|
244368
|
-
const maxLabelLengthBySide = {
|
|
244369
|
-
left: 0,
|
|
244370
|
-
right: 0,
|
|
244371
|
-
top: 0,
|
|
244372
|
-
bottom: 0
|
|
244373
|
-
};
|
|
244374
|
-
for (const port of ports) {
|
|
244375
|
-
if (!isSchematicSide(port.side_of_component))
|
|
244376
|
-
continue;
|
|
244377
|
-
if (!port.display_pin_label)
|
|
244378
|
-
continue;
|
|
244379
|
-
maxLabelLengthBySide[port.side_of_component] = Math.max(maxLabelLengthBySide[port.side_of_component], estimateLabelWidth(port.display_pin_label, sourcePortById.get(port.source_port_id)));
|
|
244473
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/SchematicBoxOverlapSolver/SchematicBoxOverlapSolver.ts
|
|
244474
|
+
import { BaseSolver as BaseSolver8 } from "@tscircuit/solver-utils";
|
|
244475
|
+
class SchematicBoxOverlapSolver extends BaseSolver8 {
|
|
244476
|
+
params;
|
|
244477
|
+
placements;
|
|
244478
|
+
firstIndex = 0;
|
|
244479
|
+
secondIndex = 1;
|
|
244480
|
+
constructor(params2) {
|
|
244481
|
+
super();
|
|
244482
|
+
this.params = params2;
|
|
244483
|
+
this.placements = params2.ctx.componentPlacements;
|
|
244484
|
+
this.solved = this.placements.length < 2;
|
|
244380
244485
|
}
|
|
244381
|
-
|
|
244382
|
-
|
|
244383
|
-
|
|
244384
|
-
|
|
244385
|
-
|
|
244386
|
-
|
|
244387
|
-
|
|
244388
|
-
|
|
244389
|
-
|
|
244390
|
-
|
|
244391
|
-
|
|
244392
|
-
|
|
244393
|
-
|
|
244394
|
-
|
|
244486
|
+
_step() {
|
|
244487
|
+
if (this.firstIndex >= this.placements.length - 1) {
|
|
244488
|
+
this.solved = true;
|
|
244489
|
+
return;
|
|
244490
|
+
}
|
|
244491
|
+
const overlap = this.getComponentOverlap(this.placements[this.firstIndex], this.placements[this.secondIndex]);
|
|
244492
|
+
if (overlap)
|
|
244493
|
+
this.params.issues.push(overlap);
|
|
244494
|
+
this.secondIndex++;
|
|
244495
|
+
if (this.secondIndex >= this.placements.length) {
|
|
244496
|
+
this.firstIndex++;
|
|
244497
|
+
this.secondIndex = this.firstIndex + 1;
|
|
244498
|
+
}
|
|
244499
|
+
this.solved = this.firstIndex >= this.placements.length - 1;
|
|
244395
244500
|
}
|
|
244396
|
-
|
|
244397
|
-
|
|
244398
|
-
|
|
244399
|
-
|
|
244400
|
-
|
|
244401
|
-
|
|
244402
|
-
|
|
244403
|
-
return Math.max(0, input.port.center.y - bounds.bottom);
|
|
244404
|
-
case "left":
|
|
244405
|
-
return Math.max(0, input.port.center.x - bounds.left);
|
|
244406
|
-
case "right":
|
|
244407
|
-
return Math.max(0, bounds.right - input.port.center.x);
|
|
244501
|
+
getCenteredRectBounds(box2) {
|
|
244502
|
+
return {
|
|
244503
|
+
left: box2.schX - box2.width / 2,
|
|
244504
|
+
right: box2.schX + box2.width / 2,
|
|
244505
|
+
top: box2.schY - box2.height / 2,
|
|
244506
|
+
bottom: box2.schY + box2.height / 2
|
|
244507
|
+
};
|
|
244408
244508
|
}
|
|
244409
|
-
|
|
244410
|
-
|
|
244411
|
-
|
|
244412
|
-
|
|
244413
|
-
|
|
244414
|
-
|
|
244415
|
-
|
|
244416
|
-
|
|
244417
|
-
|
|
244418
|
-
|
|
244419
|
-
|
|
244420
|
-
|
|
244421
|
-
|
|
244422
|
-
|
|
244423
|
-
|
|
244424
|
-
|
|
244425
|
-
|
|
244426
|
-
|
|
244427
|
-
|
|
244428
|
-
|
|
244429
|
-
|
|
244430
|
-
|
|
244431
|
-
|
|
244432
|
-
|
|
244433
|
-
|
|
244434
|
-
|
|
244435
|
-
|
|
244436
|
-
|
|
244437
|
-
|
|
244438
|
-
|
|
244439
|
-
|
|
244440
|
-
|
|
244441
|
-
|
|
244509
|
+
getOverlapCorrectionSuggestions({
|
|
244510
|
+
firstComponent,
|
|
244511
|
+
secondComponent,
|
|
244512
|
+
overlapWidth,
|
|
244513
|
+
overlapHeight
|
|
244514
|
+
}) {
|
|
244515
|
+
const firstArea = firstComponent.width * firstComponent.height;
|
|
244516
|
+
const secondArea = secondComponent.width * secondComponent.height;
|
|
244517
|
+
const target = firstArea <= secondArea ? firstComponent : secondComponent;
|
|
244518
|
+
const other = target === firstComponent ? secondComponent : firstComponent;
|
|
244519
|
+
const deltaSchX = target.schX <= other.schX ? -overlapWidth : overlapWidth;
|
|
244520
|
+
const deltaSchY = target.schY <= other.schY ? -overlapHeight : overlapHeight;
|
|
244521
|
+
return [
|
|
244522
|
+
{
|
|
244523
|
+
targetComponentName: target.sourceComponentName,
|
|
244524
|
+
deltaSchX,
|
|
244525
|
+
deltaSchY: 0,
|
|
244526
|
+
newSchX: target.schX + deltaSchX,
|
|
244527
|
+
newSchY: target.schY
|
|
244528
|
+
},
|
|
244529
|
+
{
|
|
244530
|
+
targetComponentName: target.sourceComponentName,
|
|
244531
|
+
deltaSchX: 0,
|
|
244532
|
+
deltaSchY,
|
|
244533
|
+
newSchX: target.schX,
|
|
244534
|
+
newSchY: target.schY + deltaSchY
|
|
244535
|
+
}
|
|
244536
|
+
];
|
|
244537
|
+
}
|
|
244538
|
+
static issueToString(issue) {
|
|
244539
|
+
const attrs = [];
|
|
244540
|
+
addAttr(attrs, "component1Name", issue.firstComponent.sourceComponentName);
|
|
244541
|
+
addAttr(attrs, "component2Name", issue.secondComponent.sourceComponentName);
|
|
244542
|
+
addAttr(attrs, "component1SchX", issue.firstComponent.schX);
|
|
244543
|
+
addAttr(attrs, "component1SchY", issue.firstComponent.schY);
|
|
244544
|
+
addAttr(attrs, "component2SchX", issue.secondComponent.schX);
|
|
244545
|
+
addAttr(attrs, "component2SchY", issue.secondComponent.schY);
|
|
244546
|
+
addAttr(attrs, "overlapWidth", issue.overlapWidth);
|
|
244547
|
+
addAttr(attrs, "overlapHeight", issue.overlapHeight);
|
|
244548
|
+
return [
|
|
244549
|
+
`<ComponentOverlap ${attrs.join(" ")}>`,
|
|
244550
|
+
...issue.correctionSuggestions.map(SchematicBoxOverlapSolver.correctionSuggestionToString),
|
|
244551
|
+
"</ComponentOverlap>"
|
|
244552
|
+
].join(`
|
|
244553
|
+
`);
|
|
244554
|
+
}
|
|
244555
|
+
static correctionSuggestionToString(suggestion) {
|
|
244556
|
+
const attrs = [];
|
|
244557
|
+
addAttr(attrs, "target", suggestion.targetComponentName);
|
|
244558
|
+
if (suggestion.deltaSchX !== 0) {
|
|
244559
|
+
addAttr(attrs, "newSchX", suggestion.newSchX);
|
|
244560
|
+
addAttr(attrs, "deltaSchX", suggestion.deltaSchX, { formatDelta: true });
|
|
244561
|
+
}
|
|
244562
|
+
if (suggestion.deltaSchY !== 0) {
|
|
244563
|
+
addAttr(attrs, "newSchY", suggestion.newSchY);
|
|
244564
|
+
addAttr(attrs, "deltaSchY", suggestion.deltaSchY, { formatDelta: true });
|
|
244565
|
+
}
|
|
244566
|
+
return `<OverlapCorrectionSuggestion ${attrs.join(" ")} />`;
|
|
244567
|
+
}
|
|
244568
|
+
getComponentOverlap(firstComponent, secondComponent) {
|
|
244569
|
+
const a2 = this.getCenteredRectBounds(firstComponent);
|
|
244570
|
+
const b = this.getCenteredRectBounds(secondComponent);
|
|
244571
|
+
const overlapWidth = Math.min(a2.right, b.right) - Math.max(a2.left, b.left);
|
|
244572
|
+
const overlapHeight = Math.min(a2.bottom, b.bottom) - Math.max(a2.top, b.top);
|
|
244573
|
+
if (overlapWidth <= 0 || overlapHeight <= 0)
|
|
244574
|
+
return null;
|
|
244575
|
+
return {
|
|
244576
|
+
lineItemType: "ComponentOverlap",
|
|
244577
|
+
firstComponent,
|
|
244578
|
+
secondComponent,
|
|
244579
|
+
overlapWidth,
|
|
244580
|
+
overlapHeight,
|
|
244581
|
+
correctionSuggestions: this.getOverlapCorrectionSuggestions({
|
|
244582
|
+
firstComponent,
|
|
244583
|
+
secondComponent,
|
|
244584
|
+
overlapWidth,
|
|
244585
|
+
overlapHeight
|
|
244586
|
+
})
|
|
244587
|
+
};
|
|
244588
|
+
}
|
|
244589
|
+
}
|
|
244590
|
+
|
|
244591
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/SchematicBoxInnerLabelCollisionSolver/SchematicBoxInnerLabelCollisionSolver.ts
|
|
244592
|
+
import { BaseSolver as BaseSolver9 } from "@tscircuit/solver-utils";
|
|
244593
|
+
class SchematicBoxInnerLabelCollisionSolver extends BaseSolver9 {
|
|
244594
|
+
params;
|
|
244595
|
+
MESSAGE = "Inner labels are colliding. Increase the schWidth or schHeight.";
|
|
244596
|
+
PIN_LABEL_EDGE_PADDING = 0.1;
|
|
244597
|
+
PIN_LABEL_TEXT_HEIGHT = 0.15;
|
|
244598
|
+
PIN_NAME_CHARACTER_WIDTH = 0.095;
|
|
244599
|
+
FALLBACK_CHARACTER_WIDTH = 0.13;
|
|
244600
|
+
INNER_LABEL_COLLISION_PADDING = 0.02;
|
|
244601
|
+
COLLISION_COMPARISON_EPSILON = 0.000000001;
|
|
244602
|
+
entries;
|
|
244603
|
+
placementById;
|
|
244604
|
+
sourcePortById;
|
|
244605
|
+
currentIndex = 0;
|
|
244606
|
+
constructor(params2) {
|
|
244607
|
+
super();
|
|
244608
|
+
this.params = params2;
|
|
244609
|
+
const { circuitJson, componentPlacements } = params2.ctx;
|
|
244610
|
+
this.placementById = this.getPlacementBySchematicComponentId(componentPlacements);
|
|
244611
|
+
this.sourcePortById = this.getSourcePortById(circuitJson);
|
|
244612
|
+
this.entries = Array.from(this.getPortsBySchematicComponentId(circuitJson));
|
|
244613
|
+
this.solved = this.entries.length === 0;
|
|
244614
|
+
}
|
|
244615
|
+
_step() {
|
|
244616
|
+
const entry = this.entries[this.currentIndex++];
|
|
244617
|
+
if (!entry) {
|
|
244618
|
+
this.solved = true;
|
|
244619
|
+
return;
|
|
244620
|
+
}
|
|
244621
|
+
this.solved = this.currentIndex >= this.entries.length;
|
|
244622
|
+
const [schematicComponentId, ports] = entry;
|
|
244623
|
+
const schematicBox = this.placementById.get(schematicComponentId);
|
|
244442
244624
|
if (!schematicBox)
|
|
244443
|
-
|
|
244444
|
-
const
|
|
244625
|
+
return;
|
|
244626
|
+
const bounds = this.getCenteredRectBounds(schematicBox);
|
|
244627
|
+
const labelRects = this.getLabelRects(bounds, ports, this.sourcePortById);
|
|
244628
|
+
if (labelRects.length === 0)
|
|
244629
|
+
return;
|
|
244630
|
+
const collisionSummary = this.getCollisionSummary(labelRects);
|
|
244631
|
+
if (collisionSummary.overlappingSides.length === 0)
|
|
244632
|
+
return;
|
|
244633
|
+
this.params.issues.push({
|
|
244634
|
+
lineItemType: "SchematicBoxInnerLabelCollision",
|
|
244635
|
+
schematicBox,
|
|
244636
|
+
overlappingSides: collisionSummary.overlappingSides,
|
|
244637
|
+
message: this.MESSAGE
|
|
244638
|
+
});
|
|
244639
|
+
}
|
|
244640
|
+
static issueToString(issue) {
|
|
244641
|
+
const attrs = [];
|
|
244642
|
+
addAttr(attrs, "message", issue.message, { escape: false });
|
|
244643
|
+
addAttr(attrs, "componentName", issue.schematicBox.sourceComponentName);
|
|
244644
|
+
addAttr(attrs, "currentSchWidth", issue.schematicBox.width);
|
|
244645
|
+
addAttr(attrs, "currentSchHeight", issue.schematicBox.height);
|
|
244646
|
+
addAttr(attrs, "overlappingSides", issue.overlappingSides.join(","));
|
|
244647
|
+
return `<SchematicBoxInnerLabelCollision ${attrs.join(" ")} />`;
|
|
244648
|
+
}
|
|
244649
|
+
isSchematicPort(el3) {
|
|
244650
|
+
return el3.type === "schematic_port";
|
|
244651
|
+
}
|
|
244652
|
+
isSourcePort(el3) {
|
|
244653
|
+
return el3.type === "source_port";
|
|
244654
|
+
}
|
|
244655
|
+
isSchematicSide(side) {
|
|
244656
|
+
return side === "left" || side === "right" || side === "top" || side === "bottom";
|
|
244657
|
+
}
|
|
244658
|
+
isPinNameLabel(label, sourcePort) {
|
|
244659
|
+
if (!sourcePort)
|
|
244660
|
+
return false;
|
|
244661
|
+
return label === sourcePort.name || label === String(sourcePort.pin_number) || (sourcePort.port_hints ?? []).includes(label);
|
|
244662
|
+
}
|
|
244663
|
+
estimateLabelLength(label, sourcePort) {
|
|
244664
|
+
return Array.from(label).length * (this.isPinNameLabel(label, sourcePort) ? this.PIN_NAME_CHARACTER_WIDTH : this.FALLBACK_CHARACTER_WIDTH);
|
|
244665
|
+
}
|
|
244666
|
+
hasCollision(requiredGrowth) {
|
|
244667
|
+
return requiredGrowth > this.COLLISION_COMPARISON_EPSILON;
|
|
244668
|
+
}
|
|
244669
|
+
getCenteredRectBounds(box2) {
|
|
244670
|
+
return {
|
|
244671
|
+
left: box2.schX - box2.width / 2,
|
|
244672
|
+
right: box2.schX + box2.width / 2,
|
|
244673
|
+
top: box2.schY + box2.height / 2,
|
|
244674
|
+
bottom: box2.schY - box2.height / 2
|
|
244675
|
+
};
|
|
244676
|
+
}
|
|
244677
|
+
getSourcePortById(circuitJson) {
|
|
244678
|
+
return new Map(circuitJson.filter((el3) => this.isSourcePort(el3)).map((sp3) => [sp3.source_port_id, sp3]));
|
|
244679
|
+
}
|
|
244680
|
+
getPlacementBySchematicComponentId(componentPlacements) {
|
|
244681
|
+
return new Map(componentPlacements.filter((p3) => p3.schematicComponentId).map((p3) => [p3.schematicComponentId, p3]));
|
|
244682
|
+
}
|
|
244683
|
+
getPortsBySchematicComponentId(circuitJson) {
|
|
244684
|
+
const map = new Map;
|
|
244685
|
+
for (const port of circuitJson.filter((el3) => this.isSchematicPort(el3))) {
|
|
244686
|
+
if (!port.schematic_component_id)
|
|
244687
|
+
continue;
|
|
244688
|
+
if (!this.isSchematicSide(port.side_of_component))
|
|
244689
|
+
continue;
|
|
244690
|
+
const ports = map.get(port.schematic_component_id);
|
|
244691
|
+
if (ports)
|
|
244692
|
+
ports.push(port);
|
|
244693
|
+
else
|
|
244694
|
+
map.set(port.schematic_component_id, [port]);
|
|
244695
|
+
}
|
|
244696
|
+
return map;
|
|
244697
|
+
}
|
|
244698
|
+
getLabelRects(bounds, ports, sourcePortById) {
|
|
244699
|
+
const rects = [];
|
|
244700
|
+
for (const port of ports) {
|
|
244701
|
+
if (!this.isSchematicSide(port.side_of_component))
|
|
244702
|
+
continue;
|
|
244703
|
+
if (!port.display_pin_label)
|
|
244704
|
+
continue;
|
|
244705
|
+
const labelLength = this.estimateLabelLength(port.display_pin_label, sourcePortById.get(port.source_port_id));
|
|
244706
|
+
const halfTextHeight = this.PIN_LABEL_TEXT_HEIGHT / 2;
|
|
244707
|
+
switch (port.side_of_component) {
|
|
244708
|
+
case "left": {
|
|
244709
|
+
const xMin = bounds.left + this.PIN_LABEL_EDGE_PADDING;
|
|
244710
|
+
rects.push({
|
|
244711
|
+
side: port.side_of_component,
|
|
244712
|
+
xMin,
|
|
244713
|
+
xMax: xMin + labelLength,
|
|
244714
|
+
yMin: port.center.y - halfTextHeight,
|
|
244715
|
+
yMax: port.center.y + halfTextHeight
|
|
244716
|
+
});
|
|
244717
|
+
break;
|
|
244718
|
+
}
|
|
244719
|
+
case "right": {
|
|
244720
|
+
const xMax = bounds.right - this.PIN_LABEL_EDGE_PADDING;
|
|
244721
|
+
rects.push({
|
|
244722
|
+
side: port.side_of_component,
|
|
244723
|
+
xMin: xMax - labelLength,
|
|
244724
|
+
xMax,
|
|
244725
|
+
yMin: port.center.y - halfTextHeight,
|
|
244726
|
+
yMax: port.center.y + halfTextHeight
|
|
244727
|
+
});
|
|
244728
|
+
break;
|
|
244729
|
+
}
|
|
244730
|
+
case "top": {
|
|
244731
|
+
const yMax = bounds.top - this.PIN_LABEL_EDGE_PADDING;
|
|
244732
|
+
rects.push({
|
|
244733
|
+
side: port.side_of_component,
|
|
244734
|
+
xMin: port.center.x - halfTextHeight,
|
|
244735
|
+
xMax: port.center.x + halfTextHeight,
|
|
244736
|
+
yMin: yMax - labelLength,
|
|
244737
|
+
yMax
|
|
244738
|
+
});
|
|
244739
|
+
break;
|
|
244740
|
+
}
|
|
244741
|
+
case "bottom": {
|
|
244742
|
+
const yMin = bounds.bottom + this.PIN_LABEL_EDGE_PADDING;
|
|
244743
|
+
rects.push({
|
|
244744
|
+
side: port.side_of_component,
|
|
244745
|
+
xMin: port.center.x - halfTextHeight,
|
|
244746
|
+
xMax: port.center.x + halfTextHeight,
|
|
244747
|
+
yMin,
|
|
244748
|
+
yMax: yMin + labelLength
|
|
244749
|
+
});
|
|
244750
|
+
break;
|
|
244751
|
+
}
|
|
244752
|
+
}
|
|
244753
|
+
}
|
|
244754
|
+
return rects;
|
|
244755
|
+
}
|
|
244756
|
+
getCollisionSummary(rects) {
|
|
244757
|
+
const overlappingSides = new Set;
|
|
244758
|
+
for (let i2 = 0;i2 < rects.length; i2++) {
|
|
244759
|
+
for (let j4 = i2 + 1;j4 < rects.length; j4++) {
|
|
244760
|
+
const a2 = rects[i2];
|
|
244761
|
+
const b = rects[j4];
|
|
244762
|
+
if (a2.side === b.side)
|
|
244763
|
+
continue;
|
|
244764
|
+
if (!this.rectsOverlap(a2, b))
|
|
244765
|
+
continue;
|
|
244766
|
+
overlappingSides.add(a2.side);
|
|
244767
|
+
overlappingSides.add(b.side);
|
|
244768
|
+
}
|
|
244769
|
+
}
|
|
244770
|
+
return {
|
|
244771
|
+
overlappingSides: this.sortSides(Array.from(overlappingSides))
|
|
244772
|
+
};
|
|
244773
|
+
}
|
|
244774
|
+
rectsOverlap(a2, b) {
|
|
244775
|
+
return this.hasCollision(Math.min(a2.xMax, b.xMax) - Math.max(a2.xMin, b.xMin) + this.INNER_LABEL_COLLISION_PADDING) && this.hasCollision(Math.min(a2.yMax, b.yMax) - Math.max(a2.yMin, b.yMin) + this.INNER_LABEL_COLLISION_PADDING);
|
|
244776
|
+
}
|
|
244777
|
+
sortSides(sides) {
|
|
244778
|
+
const order = {
|
|
244779
|
+
left: 0,
|
|
244780
|
+
right: 1,
|
|
244781
|
+
top: 2,
|
|
244782
|
+
bottom: 3
|
|
244783
|
+
};
|
|
244784
|
+
return sides.sort((a2, b) => order[a2] - order[b]);
|
|
244785
|
+
}
|
|
244786
|
+
}
|
|
244787
|
+
|
|
244788
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/SchematicBoxTooWideSolver/SchematicBoxTooWideSolver.ts
|
|
244789
|
+
import { BaseSolver as BaseSolver10 } from "@tscircuit/solver-utils";
|
|
244790
|
+
class SchematicBoxTooWideSolver extends BaseSolver10 {
|
|
244791
|
+
params;
|
|
244792
|
+
SCHEMATIC_BOX_TOO_WIDE_MESSAGE = "Shrink schematic box width";
|
|
244793
|
+
PIN_HEADER_MAX_ALLOWED_GAP = 0.1;
|
|
244794
|
+
GENERIC_MAX_ALLOWED_GAP = 1;
|
|
244795
|
+
PIN_LABEL_EDGE_PADDING = 0.1;
|
|
244796
|
+
PIN_NAME_CHARACTER_WIDTH = 0.095;
|
|
244797
|
+
FALLBACK_CHARACTER_WIDTH = 0.13;
|
|
244798
|
+
GAP_COMPARISON_EPSILON = 0.000000001;
|
|
244799
|
+
entries;
|
|
244800
|
+
placementById;
|
|
244801
|
+
sourcePortById;
|
|
244802
|
+
sourceComponentById;
|
|
244803
|
+
currentIndex = 0;
|
|
244804
|
+
constructor(params2) {
|
|
244805
|
+
super();
|
|
244806
|
+
this.params = params2;
|
|
244807
|
+
const { circuitJson, componentPlacements } = params2.ctx;
|
|
244808
|
+
this.placementById = this.getPlacementBySchematicComponentId(componentPlacements);
|
|
244809
|
+
this.sourcePortById = this.getSourcePortById(circuitJson);
|
|
244810
|
+
this.sourceComponentById = this.getSourceComponentById(circuitJson);
|
|
244811
|
+
this.entries = Array.from(this.getPortsBySchematicComponentId(circuitJson));
|
|
244812
|
+
this.solved = this.entries.length === 0;
|
|
244813
|
+
}
|
|
244814
|
+
_step() {
|
|
244815
|
+
const entry = this.entries[this.currentIndex++];
|
|
244816
|
+
if (!entry) {
|
|
244817
|
+
this.solved = true;
|
|
244818
|
+
return;
|
|
244819
|
+
}
|
|
244820
|
+
this.solved = this.currentIndex >= this.entries.length;
|
|
244821
|
+
const [schematicComponentId, ports] = entry;
|
|
244822
|
+
const schematicBox = this.placementById.get(schematicComponentId);
|
|
244823
|
+
if (!schematicBox)
|
|
244824
|
+
return;
|
|
244825
|
+
const bounds = this.getCenteredRectBounds(schematicBox);
|
|
244826
|
+
const leftCol = this.getLabelColumn("left", ports, this.sourcePortById);
|
|
244827
|
+
const rightCol = this.getLabelColumn("right", ports, this.sourcePortById);
|
|
244828
|
+
const ftype = this.getSourceComponentFtype(schematicBox, this.sourceComponentById);
|
|
244829
|
+
let measuredSpace;
|
|
244830
|
+
if (leftCol && rightCol) {
|
|
244831
|
+
measuredSpace = this.getInnerLabelEdge(bounds, rightCol) - this.getInnerLabelEdge(bounds, leftCol);
|
|
244832
|
+
} else if (leftCol && leftCol.labelCount >= 4) {
|
|
244833
|
+
measuredSpace = bounds.right - this.getInnerLabelEdge(bounds, leftCol);
|
|
244834
|
+
} else if (rightCol && rightCol.labelCount >= 4) {
|
|
244835
|
+
measuredSpace = this.getInnerLabelEdge(bounds, rightCol) - bounds.left;
|
|
244836
|
+
}
|
|
244837
|
+
if (measuredSpace === undefined)
|
|
244838
|
+
return;
|
|
244839
|
+
const maxAllowed = ftype === "simple_pin_header" ? this.PIN_HEADER_MAX_ALLOWED_GAP : this.GENERIC_MAX_ALLOWED_GAP;
|
|
244840
|
+
if (!this.exceedsMaxAllowedGap(measuredSpace, maxAllowed))
|
|
244841
|
+
return;
|
|
244842
|
+
const suggestedSchWidth = this.getSuggestedWidth({
|
|
244843
|
+
measuredInnerLabelHorizontalEmptySpace: measuredSpace,
|
|
244844
|
+
maxAllowedInnerLabelHorizontalEmptySpace: maxAllowed,
|
|
244845
|
+
currentWidth: schematicBox.width
|
|
244846
|
+
});
|
|
244847
|
+
if (ftype === "simple_pin_header") {
|
|
244848
|
+
this.params.issues.push({
|
|
244849
|
+
lineItemType: "PinHeaderSchematicBoxTooWide",
|
|
244850
|
+
schematicBox,
|
|
244851
|
+
measuredInnerLabelHorizontalEmptySpace: measuredSpace,
|
|
244852
|
+
maxAllowedInnerLabelHorizontalEmptySpace: maxAllowed,
|
|
244853
|
+
suggestedSchWidth,
|
|
244854
|
+
message: this.SCHEMATIC_BOX_TOO_WIDE_MESSAGE
|
|
244855
|
+
});
|
|
244856
|
+
} else {
|
|
244857
|
+
this.params.issues.push({
|
|
244858
|
+
lineItemType: "GenericSchematicBoxTooWide",
|
|
244859
|
+
schematicBox,
|
|
244860
|
+
measuredInnerLabelHorizontalEmptySpace: measuredSpace,
|
|
244861
|
+
maxAllowedInnerLabelHorizontalEmptySpace: maxAllowed,
|
|
244862
|
+
suggestedSchWidth,
|
|
244863
|
+
message: this.SCHEMATIC_BOX_TOO_WIDE_MESSAGE
|
|
244864
|
+
});
|
|
244865
|
+
}
|
|
244866
|
+
}
|
|
244867
|
+
static issueToString(issue) {
|
|
244868
|
+
const attrs = [];
|
|
244869
|
+
addAttr(attrs, "message", issue.message, { escape: false });
|
|
244870
|
+
addAttr(attrs, "componentName", issue.schematicBox.sourceComponentName);
|
|
244871
|
+
addAttr(attrs, "currentSchWidth", issue.schematicBox.width);
|
|
244872
|
+
addAttr(attrs, "measuredInnerLabelHorizontalEmptySpace", issue.measuredInnerLabelHorizontalEmptySpace);
|
|
244873
|
+
addAttr(attrs, "maxAllowedInnerLabelHorizontalEmptySpace", issue.maxAllowedInnerLabelHorizontalEmptySpace);
|
|
244874
|
+
addAttr(attrs, "suggestedSchWidth", issue.suggestedSchWidth);
|
|
244875
|
+
return `<${issue.lineItemType} ${attrs.join(" ")} />`;
|
|
244876
|
+
}
|
|
244877
|
+
isSchematicPort(el3) {
|
|
244878
|
+
return el3.type === "schematic_port";
|
|
244879
|
+
}
|
|
244880
|
+
isSourcePort(el3) {
|
|
244881
|
+
return el3.type === "source_port";
|
|
244882
|
+
}
|
|
244883
|
+
isHorizontalSide(side) {
|
|
244884
|
+
return side === "left" || side === "right";
|
|
244885
|
+
}
|
|
244886
|
+
getSourceComponentWithFtype(el3) {
|
|
244887
|
+
if (el3.type !== "source_component" || !("source_component_id" in el3) || typeof el3.source_component_id !== "string")
|
|
244888
|
+
return null;
|
|
244889
|
+
return {
|
|
244890
|
+
type: "source_component",
|
|
244891
|
+
source_component_id: el3.source_component_id,
|
|
244892
|
+
ftype: "ftype" in el3 && typeof el3.ftype === "string" ? el3.ftype : undefined
|
|
244893
|
+
};
|
|
244894
|
+
}
|
|
244895
|
+
isPinNameLabel(label, sourcePort) {
|
|
244896
|
+
if (!sourcePort)
|
|
244897
|
+
return false;
|
|
244898
|
+
return label === sourcePort.name || label === String(sourcePort.pin_number) || (sourcePort.port_hints ?? []).includes(label);
|
|
244899
|
+
}
|
|
244900
|
+
estimateLabelWidth(label, sourcePort) {
|
|
244901
|
+
return Array.from(label).length * (this.isPinNameLabel(label, sourcePort) ? this.PIN_NAME_CHARACTER_WIDTH : this.FALLBACK_CHARACTER_WIDTH);
|
|
244902
|
+
}
|
|
244903
|
+
exceedsMaxAllowedGap(measured, maxAllowed) {
|
|
244904
|
+
return measured - maxAllowed > this.GAP_COMPARISON_EPSILON;
|
|
244905
|
+
}
|
|
244906
|
+
getCenteredRectBounds(box2) {
|
|
244907
|
+
return {
|
|
244908
|
+
left: box2.schX - box2.width / 2,
|
|
244909
|
+
right: box2.schX + box2.width / 2,
|
|
244910
|
+
top: box2.schY + box2.height / 2,
|
|
244911
|
+
bottom: box2.schY - box2.height / 2
|
|
244912
|
+
};
|
|
244913
|
+
}
|
|
244914
|
+
getSourcePortById(circuitJson) {
|
|
244915
|
+
return new Map(circuitJson.filter((el3) => this.isSourcePort(el3)).map((sp3) => [sp3.source_port_id, sp3]));
|
|
244916
|
+
}
|
|
244917
|
+
getSourceComponentById(circuitJson) {
|
|
244918
|
+
return new Map(circuitJson.flatMap((el3) => {
|
|
244919
|
+
const sc2 = this.getSourceComponentWithFtype(el3);
|
|
244920
|
+
return sc2 ? [sc2] : [];
|
|
244921
|
+
}).map((sc2) => [sc2.source_component_id, sc2]));
|
|
244922
|
+
}
|
|
244923
|
+
getPlacementBySchematicComponentId(componentPlacements) {
|
|
244924
|
+
return new Map(componentPlacements.filter((p3) => p3.schematicComponentId).map((p3) => [p3.schematicComponentId, p3]));
|
|
244925
|
+
}
|
|
244926
|
+
getPortsBySchematicComponentId(circuitJson) {
|
|
244927
|
+
const map = new Map;
|
|
244928
|
+
for (const port of circuitJson.filter((el3) => this.isSchematicPort(el3))) {
|
|
244929
|
+
if (!port.schematic_component_id)
|
|
244930
|
+
continue;
|
|
244931
|
+
if (!this.isHorizontalSide(port.side_of_component))
|
|
244932
|
+
continue;
|
|
244933
|
+
const ports = map.get(port.schematic_component_id);
|
|
244934
|
+
if (ports)
|
|
244935
|
+
ports.push(port);
|
|
244936
|
+
else
|
|
244937
|
+
map.set(port.schematic_component_id, [port]);
|
|
244938
|
+
}
|
|
244939
|
+
return map;
|
|
244940
|
+
}
|
|
244941
|
+
getSourceComponentFtype(schematicBox, sourceComponentById) {
|
|
244942
|
+
return schematicBox.sourceComponentId ? sourceComponentById.get(schematicBox.sourceComponentId)?.ftype : undefined;
|
|
244943
|
+
}
|
|
244944
|
+
getLabelColumn(side, ports, sourcePortById) {
|
|
244945
|
+
const widths = ports.filter((p3) => p3.side_of_component === side).flatMap((p3) => p3.display_pin_label ? [
|
|
244946
|
+
this.estimateLabelWidth(p3.display_pin_label, sourcePortById.get(p3.source_port_id))
|
|
244947
|
+
] : []);
|
|
244948
|
+
if (widths.length === 0)
|
|
244949
|
+
return null;
|
|
244950
|
+
return {
|
|
244951
|
+
side,
|
|
244952
|
+
labelCount: widths.length,
|
|
244953
|
+
maxLabelWidth: Math.max(...widths)
|
|
244954
|
+
};
|
|
244955
|
+
}
|
|
244956
|
+
getInnerLabelEdge(bounds, col) {
|
|
244957
|
+
return col.side === "left" ? bounds.left + this.PIN_LABEL_EDGE_PADDING + col.maxLabelWidth : bounds.right - this.PIN_LABEL_EDGE_PADDING - col.maxLabelWidth;
|
|
244958
|
+
}
|
|
244959
|
+
getSuggestedWidth(input) {
|
|
244960
|
+
return input.currentWidth - input.measuredInnerLabelHorizontalEmptySpace + input.maxAllowedInnerLabelHorizontalEmptySpace;
|
|
244961
|
+
}
|
|
244962
|
+
}
|
|
244963
|
+
|
|
244964
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/SchematicPinPaddingToEdgeSolver/SchematicPinPaddingToEdgeSolver.ts
|
|
244965
|
+
import { BaseSolver as BaseSolver11 } from "@tscircuit/solver-utils";
|
|
244966
|
+
class SchematicPinPaddingToEdgeSolver extends BaseSolver11 {
|
|
244967
|
+
params;
|
|
244968
|
+
MESSAGE = "Move schematic pins closer to the box edge or change the schematic box";
|
|
244969
|
+
PIN_NAME_CHARACTER_WIDTH = 0.095;
|
|
244970
|
+
FALLBACK_CHARACTER_WIDTH = 0.13;
|
|
244971
|
+
GAP_COMPARISON_EPSILON = 0.000000001;
|
|
244972
|
+
entries;
|
|
244973
|
+
placementById;
|
|
244974
|
+
schematicComponentById;
|
|
244975
|
+
sourcePortById;
|
|
244976
|
+
currentIndex = 0;
|
|
244977
|
+
constructor(params2) {
|
|
244978
|
+
super();
|
|
244979
|
+
this.params = params2;
|
|
244980
|
+
const { circuitJson, componentPlacements } = params2.ctx;
|
|
244981
|
+
this.placementById = this.getPlacementBySchematicComponentId(componentPlacements);
|
|
244982
|
+
this.schematicComponentById = this.getSchematicComponentById(circuitJson);
|
|
244983
|
+
this.sourcePortById = this.getSourcePortById(circuitJson);
|
|
244984
|
+
this.entries = Array.from(this.getPortsBySchematicComponentId(circuitJson));
|
|
244985
|
+
this.solved = this.entries.length === 0;
|
|
244986
|
+
}
|
|
244987
|
+
_step() {
|
|
244988
|
+
const entry = this.entries[this.currentIndex++];
|
|
244989
|
+
if (!entry) {
|
|
244990
|
+
this.solved = true;
|
|
244991
|
+
return;
|
|
244992
|
+
}
|
|
244993
|
+
this.solved = this.currentIndex >= this.entries.length;
|
|
244994
|
+
const [schematicComponentId, ports] = entry;
|
|
244995
|
+
const schematicBox = this.placementById.get(schematicComponentId);
|
|
244996
|
+
if (!schematicBox)
|
|
244997
|
+
return;
|
|
244998
|
+
const pinSpacing = this.getPinSpacing(schematicBox, this.schematicComponentById);
|
|
244445
244999
|
if (pinSpacing === null)
|
|
244446
|
-
|
|
244447
|
-
const maxLabelLengthBySide = getMaxLabelLengthBySide(ports, sourcePortById);
|
|
245000
|
+
return;
|
|
245001
|
+
const maxLabelLengthBySide = this.getMaxLabelLengthBySide(ports, this.sourcePortById);
|
|
244448
245002
|
const portsBySide = new Map;
|
|
244449
245003
|
for (const port of ports) {
|
|
244450
|
-
if (!isSchematicSide(port.side_of_component))
|
|
245004
|
+
if (!this.isSchematicSide(port.side_of_component))
|
|
244451
245005
|
continue;
|
|
244452
245006
|
const sidePorts = portsBySide.get(port.side_of_component) ?? [];
|
|
244453
245007
|
sidePorts.push(port);
|
|
244454
245008
|
portsBySide.set(port.side_of_component, sidePorts);
|
|
244455
245009
|
}
|
|
244456
|
-
const useLabelAwareMaxPadding = hasPinsOnAllSides(portsBySide);
|
|
245010
|
+
const useLabelAwareMaxPadding = this.hasPinsOnAllSides(portsBySide);
|
|
244457
245011
|
for (const [pinSide, sidePorts] of portsBySide) {
|
|
244458
|
-
for (const edgeSide of getBoxEdgeSidesForPinSide(pinSide)) {
|
|
244459
|
-
const outerPin = getOuterPinBySide(edgeSide, sidePorts);
|
|
245012
|
+
for (const edgeSide of this.getBoxEdgeSidesForPinSide(pinSide)) {
|
|
245013
|
+
const outerPin = this.getOuterPinBySide(edgeSide, sidePorts);
|
|
244460
245014
|
if (!outerPin)
|
|
244461
245015
|
continue;
|
|
244462
|
-
const
|
|
244463
|
-
|
|
244464
|
-
|
|
244465
|
-
|
|
244466
|
-
|
|
244467
|
-
edgeSide
|
|
244468
|
-
})
|
|
244469
|
-
};
|
|
244470
|
-
candidates.push({
|
|
245016
|
+
const measuredPadding = this.getPinPaddingToEdge(schematicBox, outerPin, edgeSide);
|
|
245017
|
+
const maxAllowedPadding = useLabelAwareMaxPadding ? this.getMaxAllowedPinPadding(pinSpacing, edgeSide, maxLabelLengthBySide) : pinSpacing;
|
|
245018
|
+
if (!this.exceedsMaxAllowedGap(measuredPadding, maxAllowedPadding))
|
|
245019
|
+
continue;
|
|
245020
|
+
this.params.issues.push(this.createIssue({
|
|
244471
245021
|
schematicBox,
|
|
244472
245022
|
pinSide,
|
|
244473
245023
|
edgeSide,
|
|
244474
|
-
pinName:
|
|
244475
|
-
measuredPadding
|
|
244476
|
-
maxAllowedPadding
|
|
244477
|
-
|
|
244478
|
-
edgeSide,
|
|
244479
|
-
maxLabelLengthBySide
|
|
244480
|
-
}) : pinSpacing
|
|
244481
|
-
});
|
|
245024
|
+
pinName: this.getPinName(outerPin, this.sourcePortById),
|
|
245025
|
+
measuredPadding,
|
|
245026
|
+
maxAllowedPadding
|
|
245027
|
+
}));
|
|
244482
245028
|
}
|
|
244483
245029
|
}
|
|
244484
245030
|
}
|
|
244485
|
-
|
|
244486
|
-
|
|
244487
|
-
|
|
244488
|
-
|
|
244489
|
-
|
|
244490
|
-
|
|
244491
|
-
|
|
244492
|
-
|
|
244493
|
-
|
|
244494
|
-
|
|
244495
|
-
|
|
244496
|
-
|
|
244497
|
-
|
|
244498
|
-
|
|
244499
|
-
|
|
244500
|
-
|
|
244501
|
-
}
|
|
244502
|
-
|
|
244503
|
-
|
|
244504
|
-
|
|
244505
|
-
|
|
244506
|
-
|
|
244507
|
-
|
|
244508
|
-
|
|
244509
|
-
|
|
244510
|
-
|
|
244511
|
-
|
|
244512
|
-
|
|
244513
|
-
|
|
244514
|
-
|
|
244515
|
-
|
|
244516
|
-
|
|
244517
|
-
|
|
244518
|
-
|
|
244519
|
-
|
|
244520
|
-
|
|
244521
|
-
|
|
244522
|
-
|
|
244523
|
-
|
|
244524
|
-
|
|
244525
|
-
|
|
244526
|
-
|
|
244527
|
-
|
|
244528
|
-
|
|
244529
|
-
|
|
244530
|
-
|
|
244531
|
-
|
|
244532
|
-
|
|
244533
|
-
|
|
244534
|
-
|
|
244535
|
-
|
|
244536
|
-
|
|
244537
|
-
|
|
244538
|
-
|
|
244539
|
-
|
|
244540
|
-
|
|
244541
|
-
|
|
244542
|
-
|
|
244543
|
-
|
|
244544
|
-
|
|
244545
|
-
|
|
244546
|
-
|
|
244547
|
-
|
|
245031
|
+
static issueToString(issue) {
|
|
245032
|
+
const attrs = [];
|
|
245033
|
+
addAttr(attrs, "message", issue.message, { escape: false });
|
|
245034
|
+
addAttr(attrs, "componentName", issue.schematicBox.sourceComponentName);
|
|
245035
|
+
addAttr(attrs, "pinSide", issue.pinSide);
|
|
245036
|
+
addAttr(attrs, "edgeSide", issue.edgeSide);
|
|
245037
|
+
addAttr(attrs, "pinName", issue.pinName);
|
|
245038
|
+
addAttr(attrs, "measuredPadding", issue.measuredPadding);
|
|
245039
|
+
addAttr(attrs, "maxAllowedPadding", issue.maxAllowedPadding);
|
|
245040
|
+
addAttr(attrs, "excessPadding", issue.excessPadding);
|
|
245041
|
+
addAttr(attrs, "suggestedSchWidth", issue.suggestedSchWidth);
|
|
245042
|
+
addAttr(attrs, "suggestedSchHeight", issue.suggestedSchHeight);
|
|
245043
|
+
return `<SchematicPinPaddingToEdgeTooLarge ${attrs.join(" ")} />`;
|
|
245044
|
+
}
|
|
245045
|
+
isSchematicPort(el3) {
|
|
245046
|
+
return el3.type === "schematic_port";
|
|
245047
|
+
}
|
|
245048
|
+
isSourcePort(el3) {
|
|
245049
|
+
return el3.type === "source_port";
|
|
245050
|
+
}
|
|
245051
|
+
isSchematicComponent(el3) {
|
|
245052
|
+
return el3.type === "schematic_component";
|
|
245053
|
+
}
|
|
245054
|
+
isHorizontalSide(side) {
|
|
245055
|
+
return side === "left" || side === "right";
|
|
245056
|
+
}
|
|
245057
|
+
isVerticalSide(side) {
|
|
245058
|
+
return side === "top" || side === "bottom";
|
|
245059
|
+
}
|
|
245060
|
+
isSchematicSide(side) {
|
|
245061
|
+
return this.isHorizontalSide(side) || this.isVerticalSide(side);
|
|
245062
|
+
}
|
|
245063
|
+
isPinNameLabel(label, sourcePort) {
|
|
245064
|
+
if (!sourcePort)
|
|
245065
|
+
return false;
|
|
245066
|
+
return label === sourcePort.name || label === String(sourcePort.pin_number) || (sourcePort.port_hints ?? []).includes(label);
|
|
245067
|
+
}
|
|
245068
|
+
estimateLabelWidth(label, sourcePort) {
|
|
245069
|
+
return Array.from(label).length * (this.isPinNameLabel(label, sourcePort) ? this.PIN_NAME_CHARACTER_WIDTH : this.FALLBACK_CHARACTER_WIDTH);
|
|
245070
|
+
}
|
|
245071
|
+
exceedsMaxAllowedGap(measured, maxAllowed) {
|
|
245072
|
+
return measured - maxAllowed > this.GAP_COMPARISON_EPSILON;
|
|
245073
|
+
}
|
|
245074
|
+
getCenteredRectBounds(box2) {
|
|
245075
|
+
return {
|
|
245076
|
+
left: box2.schX - box2.width / 2,
|
|
245077
|
+
right: box2.schX + box2.width / 2,
|
|
245078
|
+
top: box2.schY + box2.height / 2,
|
|
245079
|
+
bottom: box2.schY - box2.height / 2
|
|
245080
|
+
};
|
|
245081
|
+
}
|
|
245082
|
+
getSourcePortById(circuitJson) {
|
|
245083
|
+
return new Map(circuitJson.filter((el3) => this.isSourcePort(el3)).map((sp3) => [sp3.source_port_id, sp3]));
|
|
245084
|
+
}
|
|
245085
|
+
getSchematicComponentById(circuitJson) {
|
|
245086
|
+
return new Map(circuitJson.filter((el3) => this.isSchematicComponent(el3)).map((sc2) => [sc2.schematic_component_id, sc2]));
|
|
245087
|
+
}
|
|
245088
|
+
getPlacementBySchematicComponentId(componentPlacements) {
|
|
245089
|
+
return new Map(componentPlacements.filter((p3) => p3.schematicComponentId).map((p3) => [p3.schematicComponentId, p3]));
|
|
245090
|
+
}
|
|
245091
|
+
getPortsBySchematicComponentId(circuitJson) {
|
|
245092
|
+
const map = new Map;
|
|
245093
|
+
for (const port of circuitJson.filter((el3) => this.isSchematicPort(el3))) {
|
|
245094
|
+
if (!port.schematic_component_id)
|
|
245095
|
+
continue;
|
|
245096
|
+
if (!this.isSchematicSide(port.side_of_component))
|
|
245097
|
+
continue;
|
|
245098
|
+
const ports = map.get(port.schematic_component_id);
|
|
245099
|
+
if (ports)
|
|
245100
|
+
ports.push(port);
|
|
245101
|
+
else
|
|
245102
|
+
map.set(port.schematic_component_id, [port]);
|
|
244548
245103
|
}
|
|
244549
|
-
|
|
244550
|
-
|
|
244551
|
-
|
|
244552
|
-
|
|
244553
|
-
|
|
244554
|
-
|
|
244555
|
-
|
|
245104
|
+
return map;
|
|
245105
|
+
}
|
|
245106
|
+
getPinSpacing(schematicBox, schematicComponentById) {
|
|
245107
|
+
if (!schematicBox.schematicComponentId)
|
|
245108
|
+
return null;
|
|
245109
|
+
const sc2 = schematicComponentById.get(schematicBox.schematicComponentId);
|
|
245110
|
+
return typeof sc2?.pin_spacing === "number" ? sc2.pin_spacing : null;
|
|
245111
|
+
}
|
|
245112
|
+
getPinName(port, sourcePortById) {
|
|
245113
|
+
const sp3 = sourcePortById.get(port.source_port_id);
|
|
245114
|
+
if (sp3?.name)
|
|
245115
|
+
return sp3.name;
|
|
245116
|
+
if (port.display_pin_label)
|
|
245117
|
+
return port.display_pin_label;
|
|
245118
|
+
if (sp3?.pin_number !== undefined)
|
|
245119
|
+
return String(sp3.pin_number);
|
|
245120
|
+
return;
|
|
245121
|
+
}
|
|
245122
|
+
getMaxLabelLengthBySide(ports, sourcePortById) {
|
|
245123
|
+
const result = {
|
|
245124
|
+
left: 0,
|
|
245125
|
+
right: 0,
|
|
245126
|
+
top: 0,
|
|
245127
|
+
bottom: 0
|
|
245128
|
+
};
|
|
245129
|
+
for (const port of ports) {
|
|
245130
|
+
if (!this.isSchematicSide(port.side_of_component))
|
|
245131
|
+
continue;
|
|
245132
|
+
if (!port.display_pin_label)
|
|
245133
|
+
continue;
|
|
245134
|
+
result[port.side_of_component] = Math.max(result[port.side_of_component], this.estimateLabelWidth(port.display_pin_label, sourcePortById.get(port.source_port_id)));
|
|
244556
245135
|
}
|
|
244557
|
-
|
|
244558
|
-
|
|
244559
|
-
|
|
244560
|
-
|
|
244561
|
-
|
|
244562
|
-
|
|
244563
|
-
|
|
245136
|
+
return result;
|
|
245137
|
+
}
|
|
245138
|
+
getOuterPinBySide(edgeSide, ports) {
|
|
245139
|
+
if (ports.length === 0)
|
|
245140
|
+
return null;
|
|
245141
|
+
switch (edgeSide) {
|
|
245142
|
+
case "top":
|
|
245143
|
+
return ports.reduce((a2, b) => b.center.y > a2.center.y ? b : a2);
|
|
245144
|
+
case "bottom":
|
|
245145
|
+
return ports.reduce((a2, b) => b.center.y < a2.center.y ? b : a2);
|
|
245146
|
+
case "left":
|
|
245147
|
+
return ports.reduce((a2, b) => b.center.x < a2.center.x ? b : a2);
|
|
245148
|
+
case "right":
|
|
245149
|
+
return ports.reduce((a2, b) => b.center.x > a2.center.x ? b : a2);
|
|
244564
245150
|
}
|
|
244565
245151
|
}
|
|
244566
|
-
|
|
244567
|
-
|
|
244568
|
-
|
|
244569
|
-
|
|
244570
|
-
|
|
244571
|
-
|
|
244572
|
-
|
|
244573
|
-
|
|
244574
|
-
|
|
244575
|
-
|
|
244576
|
-
|
|
244577
|
-
|
|
244578
|
-
schematicBox: candidate.schematicBox,
|
|
244579
|
-
measuredInnerLabelHorizontalEmptySpace: candidate.measuredInnerLabelHorizontalEmptySpace,
|
|
244580
|
-
suggestedSchWidth: getSuggestedWidth({
|
|
244581
|
-
measuredInnerLabelHorizontalEmptySpace: candidate.measuredInnerLabelHorizontalEmptySpace,
|
|
244582
|
-
maxAllowedInnerLabelHorizontalEmptySpace: GENERIC_SCHEMATIC_BOX_SIZING_MAX_ALLOWED_GAP,
|
|
244583
|
-
currentWidth: candidate.schematicBox.width
|
|
244584
|
-
})
|
|
244585
|
-
}));
|
|
244586
|
-
var generatePinHeaderSchematicBoxTooWideIssues = (componentPlacements, circuitJson) => getPinHeaderSchematicBoxTooWideIssues(generateSchematicBoxWidthSizingCandidates(componentPlacements, circuitJson));
|
|
244587
|
-
var generateGenericSchematicBoxTooWideIssues = (componentPlacements, circuitJson) => getGenericSchematicBoxTooWideIssues(generateSchematicBoxWidthSizingCandidates(componentPlacements, circuitJson));
|
|
244588
|
-
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/analyzers/schematic-box-overlap.ts
|
|
244589
|
-
var getCenteredRectBounds2 = (box2) => {
|
|
244590
|
-
const halfWidth = box2.width / 2;
|
|
244591
|
-
const halfHeight = box2.height / 2;
|
|
244592
|
-
return {
|
|
244593
|
-
left: box2.schX - halfWidth,
|
|
244594
|
-
right: box2.schX + halfWidth,
|
|
244595
|
-
top: box2.schY - halfHeight,
|
|
244596
|
-
bottom: box2.schY + halfHeight
|
|
244597
|
-
};
|
|
244598
|
-
};
|
|
244599
|
-
var getComponentOverlap = (firstComponent, secondComponent) => {
|
|
244600
|
-
const firstBounds = getCenteredRectBounds2(firstComponent);
|
|
244601
|
-
const secondBounds = getCenteredRectBounds2(secondComponent);
|
|
244602
|
-
const left = Math.max(firstBounds.left, secondBounds.left);
|
|
244603
|
-
const right = Math.min(firstBounds.right, secondBounds.right);
|
|
244604
|
-
const top = Math.max(firstBounds.top, secondBounds.top);
|
|
244605
|
-
const bottom = Math.min(firstBounds.bottom, secondBounds.bottom);
|
|
244606
|
-
const overlapWidth = right - left;
|
|
244607
|
-
const overlapHeight = bottom - top;
|
|
244608
|
-
if (overlapWidth <= 0 || overlapHeight <= 0) {
|
|
244609
|
-
return null;
|
|
245152
|
+
getPinPaddingToEdge(schematicBox, port, edgeSide) {
|
|
245153
|
+
const bounds = this.getCenteredRectBounds(schematicBox);
|
|
245154
|
+
switch (edgeSide) {
|
|
245155
|
+
case "top":
|
|
245156
|
+
return Math.max(0, bounds.top - port.center.y);
|
|
245157
|
+
case "bottom":
|
|
245158
|
+
return Math.max(0, port.center.y - bounds.bottom);
|
|
245159
|
+
case "left":
|
|
245160
|
+
return Math.max(0, port.center.x - bounds.left);
|
|
245161
|
+
case "right":
|
|
245162
|
+
return Math.max(0, bounds.right - port.center.x);
|
|
245163
|
+
}
|
|
244610
245164
|
}
|
|
244611
|
-
|
|
244612
|
-
|
|
244613
|
-
|
|
244614
|
-
|
|
244615
|
-
|
|
244616
|
-
|
|
244617
|
-
|
|
244618
|
-
|
|
244619
|
-
|
|
244620
|
-
|
|
244621
|
-
|
|
244622
|
-
|
|
244623
|
-
|
|
244624
|
-
|
|
244625
|
-
|
|
244626
|
-
|
|
244627
|
-
|
|
244628
|
-
|
|
244629
|
-
|
|
244630
|
-
|
|
244631
|
-
|
|
244632
|
-
|
|
244633
|
-
|
|
244634
|
-
|
|
244635
|
-
|
|
244636
|
-
|
|
244637
|
-
|
|
244638
|
-
|
|
244639
|
-
|
|
244640
|
-
|
|
244641
|
-
|
|
244642
|
-
|
|
244643
|
-
|
|
244644
|
-
|
|
244645
|
-
|
|
244646
|
-
|
|
244647
|
-
|
|
244648
|
-
|
|
244649
|
-
|
|
244650
|
-
|
|
245165
|
+
getBoxEdgeSidesForPinSide(pinSide) {
|
|
245166
|
+
return this.isHorizontalSide(pinSide) ? ["top", "bottom"] : ["left", "right"];
|
|
245167
|
+
}
|
|
245168
|
+
hasPinsOnAllSides(portsBySide) {
|
|
245169
|
+
return portsBySide.has("left") && portsBySide.has("right") && portsBySide.has("top") && portsBySide.has("bottom");
|
|
245170
|
+
}
|
|
245171
|
+
getMaxAllowedPinPadding(spacing, edgeSide, maxLabelLengthBySide) {
|
|
245172
|
+
const sides = this.isHorizontalSide(edgeSide) ? ["left", "right"] : ["top", "bottom"];
|
|
245173
|
+
return (maxLabelLengthBySide[sides[0]] + maxLabelLengthBySide[sides[1]] + spacing) / 2;
|
|
245174
|
+
}
|
|
245175
|
+
createIssue(candidate) {
|
|
245176
|
+
const excessPadding = Math.max(0, candidate.measuredPadding - candidate.maxAllowedPadding);
|
|
245177
|
+
const reduction = excessPadding * 2;
|
|
245178
|
+
return {
|
|
245179
|
+
lineItemType: "SchematicPinPaddingToEdgeTooLarge",
|
|
245180
|
+
pinSide: candidate.pinSide,
|
|
245181
|
+
edgeSide: candidate.edgeSide,
|
|
245182
|
+
pinName: candidate.pinName,
|
|
245183
|
+
schematicBox: candidate.schematicBox,
|
|
245184
|
+
measuredPadding: candidate.measuredPadding,
|
|
245185
|
+
maxAllowedPadding: candidate.maxAllowedPadding,
|
|
245186
|
+
excessPadding,
|
|
245187
|
+
suggestedSchWidth: this.isHorizontalSide(candidate.pinSide) ? undefined : Math.max(0, candidate.schematicBox.width - reduction),
|
|
245188
|
+
suggestedSchHeight: this.isHorizontalSide(candidate.pinSide) ? Math.max(0, candidate.schematicBox.height - reduction) : undefined,
|
|
245189
|
+
message: this.isHorizontalSide(candidate.pinSide) ? `${this.MESSAGE} height` : `${this.MESSAGE} width`
|
|
245190
|
+
};
|
|
245191
|
+
}
|
|
245192
|
+
}
|
|
245193
|
+
|
|
245194
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/VerboseNetLabelSolver/VerboseNetLabelSolver.ts
|
|
245195
|
+
import { BaseSolver as BaseSolver12 } from "@tscircuit/solver-utils";
|
|
245196
|
+
class VerboseNetLabelSolver extends BaseSolver12 {
|
|
245197
|
+
params;
|
|
245198
|
+
VERBOSE_NET_LABEL_MESSAGE = "Create trace with schDisplayLabel";
|
|
245199
|
+
netLabels;
|
|
245200
|
+
tokenToInvolvedPin;
|
|
245201
|
+
currentIndex = 0;
|
|
245202
|
+
seen = new Set;
|
|
245203
|
+
constructor(params2) {
|
|
245204
|
+
super();
|
|
245205
|
+
this.params = params2;
|
|
245206
|
+
const { circuitJson } = params2.ctx;
|
|
245207
|
+
this.netLabels = circuitJson.filter((el3) => this.isSchematicNetLabel(el3));
|
|
245208
|
+
this.tokenToInvolvedPin = this.buildTokenToInvolvedPinMap(circuitJson);
|
|
245209
|
+
this.solved = this.netLabels.length === 0;
|
|
245210
|
+
}
|
|
245211
|
+
_step() {
|
|
245212
|
+
const label = this.netLabels[this.currentIndex++];
|
|
245213
|
+
if (!label) {
|
|
245214
|
+
this.solved = true;
|
|
245215
|
+
return;
|
|
244651
245216
|
}
|
|
244652
|
-
|
|
244653
|
-
|
|
244654
|
-
|
|
244655
|
-
|
|
244656
|
-
|
|
244657
|
-
|
|
244658
|
-
|
|
244659
|
-
|
|
244660
|
-
|
|
245217
|
+
this.solved = this.currentIndex >= this.netLabels.length;
|
|
245218
|
+
if (!label.text.includes("/") || this.seen.has(label.text))
|
|
245219
|
+
return;
|
|
245220
|
+
this.seen.add(label.text);
|
|
245221
|
+
const issue = {
|
|
245222
|
+
lineItemType: "VerboseSchematicNetLabel",
|
|
245223
|
+
schematicNetLabelId: label.schematic_net_label_id,
|
|
245224
|
+
sourceNetId: label.source_net_id,
|
|
245225
|
+
text: label.text,
|
|
245226
|
+
involvedPins: this.getInvolvedPins(label.text, this.tokenToInvolvedPin),
|
|
245227
|
+
schX: label.center.x,
|
|
245228
|
+
schY: label.center.y,
|
|
245229
|
+
message: this.VERBOSE_NET_LABEL_MESSAGE
|
|
245230
|
+
};
|
|
245231
|
+
this.params.issues.push(issue);
|
|
245232
|
+
}
|
|
245233
|
+
static issueToString(issue) {
|
|
245234
|
+
const attrs = [];
|
|
245235
|
+
addAttr(attrs, "message", issue.message, { escape: false });
|
|
245236
|
+
addAttr(attrs, "text", issue.text);
|
|
245237
|
+
addAttr(attrs, "involvedPins", issue.involvedPins.join(","));
|
|
245238
|
+
addAttr(attrs, "schX", issue.schX);
|
|
245239
|
+
addAttr(attrs, "schY", issue.schY);
|
|
245240
|
+
return `<VerboseSchematicNetLabel ${attrs.join(" ")} />`;
|
|
245241
|
+
}
|
|
245242
|
+
isSchematicNetLabel(el3) {
|
|
245243
|
+
return el3.type === "schematic_net_label";
|
|
245244
|
+
}
|
|
245245
|
+
isSourcePort(el3) {
|
|
245246
|
+
return el3.type === "source_port";
|
|
245247
|
+
}
|
|
245248
|
+
getSourceComponentWithName(el3) {
|
|
245249
|
+
if (el3.type !== "source_component" || !("source_component_id" in el3) || !("name" in el3) || typeof el3.source_component_id !== "string" || typeof el3.name !== "string")
|
|
245250
|
+
return null;
|
|
245251
|
+
return { source_component_id: el3.source_component_id, name: el3.name };
|
|
245252
|
+
}
|
|
245253
|
+
getSourcePortNameCandidates(port) {
|
|
245254
|
+
return [
|
|
245255
|
+
port.most_frequently_referenced_by_name,
|
|
245256
|
+
port.name,
|
|
245257
|
+
...port.port_hints ?? [],
|
|
245258
|
+
port.pin_number === undefined ? undefined : String(port.pin_number)
|
|
245259
|
+
].filter((n3) => Boolean(n3));
|
|
245260
|
+
}
|
|
245261
|
+
getBestSourcePortName(port) {
|
|
245262
|
+
return port.most_frequently_referenced_by_name ?? port.name ?? (port.pin_number === undefined ? "" : `pin${port.pin_number}`);
|
|
245263
|
+
}
|
|
245264
|
+
buildTokenToInvolvedPinMap(circuitJson) {
|
|
245265
|
+
const sourceComponentById = new Map(circuitJson.flatMap((el3) => {
|
|
245266
|
+
const sc2 = this.getSourceComponentWithName(el3);
|
|
245267
|
+
return sc2 ? [sc2] : [];
|
|
245268
|
+
}).map((sc2) => [sc2.source_component_id, sc2]));
|
|
245269
|
+
const map = new Map;
|
|
245270
|
+
for (const port of circuitJson.filter((el3) => this.isSourcePort(el3))) {
|
|
245271
|
+
if (!port.source_component_id)
|
|
245272
|
+
continue;
|
|
245273
|
+
const sc2 = sourceComponentById.get(port.source_component_id);
|
|
245274
|
+
if (!sc2?.name)
|
|
245275
|
+
continue;
|
|
245276
|
+
const involvedPin = `${sc2.name}.${this.getBestSourcePortName(port)}`;
|
|
245277
|
+
for (const name of this.getSourcePortNameCandidates(port)) {
|
|
245278
|
+
map.set(`${sc2.name}_${name}`, involvedPin);
|
|
244661
245279
|
}
|
|
244662
245280
|
}
|
|
245281
|
+
return map;
|
|
245282
|
+
}
|
|
245283
|
+
getInvolvedPins(text, tokenToInvolvedPin) {
|
|
245284
|
+
const pins = new Set;
|
|
245285
|
+
for (const token of text.split("/")) {
|
|
245286
|
+
const pin = tokenToInvolvedPin.get(token);
|
|
245287
|
+
if (pin)
|
|
245288
|
+
pins.add(pin);
|
|
245289
|
+
}
|
|
245290
|
+
return Array.from(pins);
|
|
244663
245291
|
}
|
|
244664
|
-
|
|
244665
|
-
};
|
|
245292
|
+
}
|
|
244666
245293
|
|
|
244667
|
-
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/
|
|
244668
|
-
|
|
244669
|
-
|
|
244670
|
-
|
|
244671
|
-
|
|
244672
|
-
|
|
244673
|
-
|
|
245294
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/DiodeResistorAlignmentSolver/DiodeResistorAlignmentSolver.ts
|
|
245295
|
+
import { BaseSolver as BaseSolver13 } from "@tscircuit/solver-utils";
|
|
245296
|
+
class DiodeResistorAlignmentSolver extends BaseSolver13 {
|
|
245297
|
+
static DIODE_FTYPES = new Set(["simple_led", "simple_diode"]);
|
|
245298
|
+
ctx;
|
|
245299
|
+
out;
|
|
245300
|
+
schematicTraces;
|
|
245301
|
+
currentIndex = 0;
|
|
245302
|
+
sourceComponentFtypeById;
|
|
245303
|
+
sourceComponentIdBySourcePortId;
|
|
245304
|
+
schematicPorts;
|
|
245305
|
+
schematicBoxBySourceComponentId;
|
|
245306
|
+
constructor({
|
|
245307
|
+
ctx,
|
|
245308
|
+
issues
|
|
245309
|
+
}) {
|
|
245310
|
+
super();
|
|
245311
|
+
this.ctx = ctx;
|
|
245312
|
+
this.out = issues;
|
|
245313
|
+
const { circuitJson } = ctx;
|
|
245314
|
+
this.sourceComponentFtypeById = this.buildSourceComponentFtypeById(circuitJson);
|
|
245315
|
+
this.sourceComponentIdBySourcePortId = this.buildSourceComponentIdBySourcePortId(circuitJson);
|
|
245316
|
+
this.schematicPorts = circuitJson.filter((el3) => el3.type === "schematic_port");
|
|
245317
|
+
this.schematicBoxBySourceComponentId = this.buildSchematicBoxBySourceComponentId();
|
|
245318
|
+
this.schematicTraces = circuitJson.filter((el3) => el3.type === "schematic_trace");
|
|
245319
|
+
this.solved = this.schematicTraces.length === 0;
|
|
244674
245320
|
}
|
|
244675
|
-
|
|
244676
|
-
|
|
244677
|
-
|
|
244678
|
-
|
|
244679
|
-
|
|
244680
|
-
}
|
|
244681
|
-
|
|
244682
|
-
|
|
244683
|
-
|
|
244684
|
-
|
|
244685
|
-
|
|
244686
|
-
|
|
244687
|
-
|
|
244688
|
-
|
|
244689
|
-
|
|
244690
|
-
const
|
|
244691
|
-
|
|
244692
|
-
|
|
244693
|
-
|
|
244694
|
-
|
|
244695
|
-
|
|
244696
|
-
|
|
244697
|
-
|
|
244698
|
-
|
|
244699
|
-
|
|
244700
|
-
|
|
244701
|
-
|
|
244702
|
-
|
|
244703
|
-
const
|
|
244704
|
-
|
|
244705
|
-
|
|
245321
|
+
_step() {
|
|
245322
|
+
const trace = this.schematicTraces[this.currentIndex];
|
|
245323
|
+
if (!trace) {
|
|
245324
|
+
this.solved = true;
|
|
245325
|
+
return;
|
|
245326
|
+
}
|
|
245327
|
+
this.currentIndex++;
|
|
245328
|
+
this.solved = this.currentIndex >= this.schematicTraces.length;
|
|
245329
|
+
if (!trace.edges || trace.edges.length === 0)
|
|
245330
|
+
return;
|
|
245331
|
+
const firstEdge = trace.edges[0];
|
|
245332
|
+
const lastEdge = trace.edges[trace.edges.length - 1];
|
|
245333
|
+
if (!firstEdge || !lastEdge)
|
|
245334
|
+
return;
|
|
245335
|
+
const start = firstEdge.from;
|
|
245336
|
+
const end = lastEdge.to;
|
|
245337
|
+
const startSourceCompId = this.findSourceComponentIdNearPoint(start);
|
|
245338
|
+
const endSourceCompId = this.findSourceComponentIdNearPoint(end);
|
|
245339
|
+
if (!startSourceCompId || !endSourceCompId)
|
|
245340
|
+
return;
|
|
245341
|
+
const startFtype = this.sourceComponentFtypeById.get(startSourceCompId);
|
|
245342
|
+
const endFtype = this.sourceComponentFtypeById.get(endSourceCompId);
|
|
245343
|
+
const { DIODE_FTYPES } = DiodeResistorAlignmentSolver;
|
|
245344
|
+
const isDiodeResistorPair = DIODE_FTYPES.has(startFtype) && endFtype === "simple_resistor" || startFtype === "simple_resistor" && DIODE_FTYPES.has(endFtype);
|
|
245345
|
+
if (!isDiodeResistorPair)
|
|
245346
|
+
return;
|
|
245347
|
+
const diodeCompId = DIODE_FTYPES.has(startFtype) ? startSourceCompId : endSourceCompId;
|
|
245348
|
+
const resistorCompId = startFtype === "simple_resistor" ? startSourceCompId : endSourceCompId;
|
|
245349
|
+
const diodeBox = this.schematicBoxBySourceComponentId.get(diodeCompId);
|
|
245350
|
+
const resistorBox = this.schematicBoxBySourceComponentId.get(resistorCompId);
|
|
245351
|
+
if (!diodeBox || !resistorBox)
|
|
245352
|
+
return;
|
|
245353
|
+
const diodePort = this.findNearestPort(DIODE_FTYPES.has(startFtype) ? start : end);
|
|
245354
|
+
const resistorPort = this.findNearestPort(startFtype === "simple_resistor" ? start : end);
|
|
245355
|
+
if (!diodePort?.center || !resistorPort?.center)
|
|
245356
|
+
return;
|
|
245357
|
+
const diodeName = diodeBox.sourceComponentName ?? diodeCompId;
|
|
245358
|
+
const resistorName = resistorBox.sourceComponentName ?? resistorCompId;
|
|
245359
|
+
const diodePin = diodePort?.display_pin_label ?? diodePort?.pin_number?.toString();
|
|
245360
|
+
const resistorPin = resistorPort?.display_pin_label ?? resistorPort?.pin_number?.toString();
|
|
245361
|
+
const diodeFacing = diodePort?.facing_direction;
|
|
245362
|
+
const resistorFacing = resistorPort?.facing_direction;
|
|
245363
|
+
const diodePinDesc = diodePin ? `${diodeName}.${diodePin}` : diodeName;
|
|
245364
|
+
const resistorPinDesc = resistorPin ? `${resistorName}.${resistorPin}` : resistorName;
|
|
245365
|
+
const makeIssue2 = (message) => ({
|
|
245366
|
+
lineItemType: "DiodeResistorNotAligned",
|
|
245367
|
+
diodeSchematicBox: diodeBox,
|
|
245368
|
+
resistorSchematicBox: resistorBox,
|
|
245369
|
+
diodePin,
|
|
245370
|
+
resistorPin,
|
|
245371
|
+
diodePinFacingDirection: diodeFacing,
|
|
245372
|
+
resistorPinFacingDirection: resistorFacing,
|
|
245373
|
+
message
|
|
245374
|
+
});
|
|
245375
|
+
if (!DiodeResistorAlignmentSolver.isCoLinear(diodePort.center, resistorPort.center)) {
|
|
245376
|
+
this.out.push(makeIssue2(`trace has corners — align ${diodeName} and ${resistorName} on same axis and rotate so ${diodePinDesc} faces ${resistorPinDesc}`));
|
|
245377
|
+
return;
|
|
245378
|
+
}
|
|
245379
|
+
if (diodeFacing && resistorFacing && !DiodeResistorAlignmentSolver.pinsFacingEachOther(diodePort.center, diodeFacing, resistorPort.center, resistorFacing)) {
|
|
245380
|
+
this.out.push(makeIssue2(`${diodePinDesc} and ${resistorPinDesc} face away from each other — rotate ${diodeName} so ${diodePinDesc} faces ${resistorPinDesc}`));
|
|
244706
245381
|
}
|
|
244707
245382
|
}
|
|
244708
|
-
|
|
244709
|
-
|
|
244710
|
-
var getInvolvedPins = (netLabelText, tokenToInvolvedPin) => {
|
|
244711
|
-
const involvedPins = new Set;
|
|
244712
|
-
for (const token of netLabelText.split("/")) {
|
|
244713
|
-
const involvedPin = tokenToInvolvedPin.get(token);
|
|
244714
|
-
if (involvedPin)
|
|
244715
|
-
involvedPins.add(involvedPin);
|
|
245383
|
+
static isCoLinear(a2, b, epsilon = 0.01) {
|
|
245384
|
+
return Math.abs(a2.x - b.x) < epsilon || Math.abs(a2.y - b.y) < epsilon;
|
|
244716
245385
|
}
|
|
244717
|
-
|
|
244718
|
-
|
|
244719
|
-
|
|
244720
|
-
|
|
244721
|
-
|
|
244722
|
-
|
|
244723
|
-
if (!netLabel.text.includes("/"))
|
|
244724
|
-
continue;
|
|
244725
|
-
if (issuesByText.has(netLabel.text))
|
|
244726
|
-
continue;
|
|
244727
|
-
issuesByText.set(netLabel.text, {
|
|
244728
|
-
lineItemType: "VerboseSchematicNetLabel",
|
|
244729
|
-
schematicNetLabelId: netLabel.schematic_net_label_id,
|
|
244730
|
-
sourceNetId: netLabel.source_net_id,
|
|
244731
|
-
text: netLabel.text,
|
|
244732
|
-
involvedPins: getInvolvedPins(netLabel.text, tokenToInvolvedPin),
|
|
244733
|
-
schX: netLabel.center.x,
|
|
244734
|
-
schY: netLabel.center.y,
|
|
244735
|
-
message: VERBOSE_NET_LABEL_MESSAGE
|
|
244736
|
-
});
|
|
245386
|
+
static pinsFacingEachOther(aCenter, aFacing, bCenter, bFacing) {
|
|
245387
|
+
const dx2 = bCenter.x - aCenter.x;
|
|
245388
|
+
const dy2 = bCenter.y - aCenter.y;
|
|
245389
|
+
const aToward = aFacing === "right" && dx2 > 0 || aFacing === "left" && dx2 < 0 || aFacing === "up" && dy2 > 0 || aFacing === "down" && dy2 < 0;
|
|
245390
|
+
const bToward = bFacing === "right" && dx2 < 0 || bFacing === "left" && dx2 > 0 || bFacing === "up" && dy2 < 0 || bFacing === "down" && dy2 > 0;
|
|
245391
|
+
return aToward && bToward;
|
|
244737
245392
|
}
|
|
244738
|
-
|
|
244739
|
-
|
|
245393
|
+
static dist(a2, b) {
|
|
245394
|
+
return Math.sqrt((a2.x - b.x) ** 2 + (a2.y - b.y) ** 2);
|
|
245395
|
+
}
|
|
245396
|
+
findNearestPort(point5) {
|
|
245397
|
+
let nearest;
|
|
245398
|
+
let minDist = Infinity;
|
|
245399
|
+
for (const port of this.schematicPorts) {
|
|
245400
|
+
if (!port.center)
|
|
245401
|
+
continue;
|
|
245402
|
+
const d3 = DiodeResistorAlignmentSolver.dist(point5, port.center);
|
|
245403
|
+
if (d3 < minDist) {
|
|
245404
|
+
minDist = d3;
|
|
245405
|
+
nearest = port;
|
|
245406
|
+
}
|
|
245407
|
+
}
|
|
245408
|
+
return nearest;
|
|
245409
|
+
}
|
|
245410
|
+
findSourceComponentIdNearPoint(point5) {
|
|
245411
|
+
const nearest = this.findNearestPort(point5);
|
|
245412
|
+
if (!nearest || !nearest.source_port_id)
|
|
245413
|
+
return;
|
|
245414
|
+
return this.sourceComponentIdBySourcePortId.get(nearest.source_port_id);
|
|
245415
|
+
}
|
|
245416
|
+
buildSourceComponentFtypeById(circuitJson) {
|
|
245417
|
+
const map = new Map;
|
|
245418
|
+
for (const el3 of circuitJson) {
|
|
245419
|
+
if (el3.type === "source_component" && "source_component_id" in el3 && "ftype" in el3 && typeof el3.ftype === "string") {
|
|
245420
|
+
map.set(el3.source_component_id, el3.ftype);
|
|
245421
|
+
}
|
|
245422
|
+
}
|
|
245423
|
+
return map;
|
|
245424
|
+
}
|
|
245425
|
+
buildSourceComponentIdBySourcePortId(circuitJson) {
|
|
245426
|
+
const map = new Map;
|
|
245427
|
+
for (const el3 of circuitJson) {
|
|
245428
|
+
if (el3.type === "source_port" && "source_port_id" in el3 && "source_component_id" in el3 && typeof el3.source_port_id === "string" && typeof el3.source_component_id === "string") {
|
|
245429
|
+
map.set(el3.source_port_id, el3.source_component_id);
|
|
245430
|
+
}
|
|
245431
|
+
}
|
|
245432
|
+
return map;
|
|
245433
|
+
}
|
|
245434
|
+
buildSchematicBoxBySourceComponentId() {
|
|
245435
|
+
const map = new Map;
|
|
245436
|
+
for (const placement of this.ctx.componentPlacements) {
|
|
245437
|
+
if (placement.sourceComponentId) {
|
|
245438
|
+
map.set(placement.sourceComponentId, placement);
|
|
245439
|
+
}
|
|
245440
|
+
}
|
|
245441
|
+
return map;
|
|
245442
|
+
}
|
|
245443
|
+
static issueToString(issue) {
|
|
245444
|
+
const attrs = [];
|
|
245445
|
+
addAttr(attrs, "diodeComponentName", issue.diodeSchematicBox.sourceComponentName);
|
|
245446
|
+
addAttr(attrs, "diodePin", issue.diodePin);
|
|
245447
|
+
addAttr(attrs, "resistorComponentName", issue.resistorSchematicBox.sourceComponentName);
|
|
245448
|
+
addAttr(attrs, "resistorPin", issue.resistorPin);
|
|
245449
|
+
addAttr(attrs, "message", issue.message);
|
|
245450
|
+
return `<DiodeResistorNotAligned ${attrs.join(" ")} />`;
|
|
245451
|
+
}
|
|
245452
|
+
}
|
|
244740
245453
|
|
|
244741
|
-
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/
|
|
244742
|
-
|
|
244743
|
-
|
|
244744
|
-
|
|
244745
|
-
|
|
244746
|
-
|
|
244747
|
-
|
|
244748
|
-
|
|
244749
|
-
|
|
244750
|
-
}
|
|
244751
|
-
|
|
244752
|
-
|
|
244753
|
-
|
|
244754
|
-
|
|
244755
|
-
|
|
244756
|
-
|
|
244757
|
-
|
|
244758
|
-
|
|
244759
|
-
|
|
244760
|
-
|
|
244761
|
-
|
|
244762
|
-
|
|
244763
|
-
|
|
244764
|
-
|
|
244765
|
-
|
|
244766
|
-
|
|
244767
|
-
|
|
244768
|
-
|
|
244769
|
-
|
|
244770
|
-
}
|
|
244771
|
-
|
|
244772
|
-
|
|
244773
|
-
|
|
244774
|
-
|
|
244775
|
-
|
|
244776
|
-
|
|
244777
|
-
|
|
244778
|
-
...getSourceComponentMetadata(schematicBox, circuitJson),
|
|
244779
|
-
schematicComponentId: schematicBox.schematic_component_id,
|
|
244780
|
-
schematicSymbolId: schematicBox.schematic_symbol_id,
|
|
244781
|
-
subcircuitId: schematicBox.subcircuit_id
|
|
244782
|
-
});
|
|
244783
|
-
var getSourceComponentMetadata = (schematicBox, circuitJson) => {
|
|
244784
|
-
if (!schematicBox.schematic_component_id)
|
|
244785
|
-
return {};
|
|
244786
|
-
const circuitJsonUtil = cju7(circuitJson);
|
|
244787
|
-
const schematicComponent = circuitJsonUtil.schematic_component.get(schematicBox.schematic_component_id);
|
|
244788
|
-
if (!schematicComponent?.source_component_id)
|
|
244789
|
-
return {};
|
|
244790
|
-
const sourceComponent = circuitJsonUtil.source_component.get(schematicComponent.source_component_id);
|
|
244791
|
-
return {
|
|
244792
|
-
sourceComponentId: schematicComponent.source_component_id,
|
|
244793
|
-
sourceComponentName: sourceComponent?.name
|
|
244794
|
-
};
|
|
244795
|
-
};
|
|
244796
|
-
var addAttr = (attrs, key, value, options) => {
|
|
244797
|
-
if (value === undefined)
|
|
244798
|
-
return;
|
|
244799
|
-
const stringValue = typeof value === "number" ? options?.formatDelta ? fmtDelta(value) : fmtNumber5(value) : options?.escape === false ? value : escapeAttr3(value);
|
|
244800
|
-
attrs.push(`${key}="${stringValue}"`);
|
|
244801
|
-
};
|
|
244802
|
-
var lineItemToString3 = (lineItem) => {
|
|
244803
|
-
const attrs = [];
|
|
244804
|
-
addAttr(attrs, "componentName", lineItem.sourceComponentName);
|
|
244805
|
-
addAttr(attrs, "positionAnchor", lineItem.positionAnchor);
|
|
244806
|
-
addAttr(attrs, "schX", lineItem.schX);
|
|
244807
|
-
addAttr(attrs, "schY", lineItem.schY);
|
|
244808
|
-
addAttr(attrs, "width", lineItem.width);
|
|
244809
|
-
addAttr(attrs, "height", lineItem.height);
|
|
244810
|
-
return `<SchematicBoxPlacement ${attrs.join(" ")} />`;
|
|
244811
|
-
};
|
|
244812
|
-
var overlapIssueToString = (issue) => {
|
|
244813
|
-
const attrs = [];
|
|
244814
|
-
addAttr(attrs, "component1Name", issue.firstComponent.sourceComponentName);
|
|
244815
|
-
addAttr(attrs, "component2Name", issue.secondComponent.sourceComponentName);
|
|
244816
|
-
addAttr(attrs, "component1SchX", issue.firstComponent.schX);
|
|
244817
|
-
addAttr(attrs, "component1SchY", issue.firstComponent.schY);
|
|
244818
|
-
addAttr(attrs, "component2SchX", issue.secondComponent.schX);
|
|
244819
|
-
addAttr(attrs, "component2SchY", issue.secondComponent.schY);
|
|
244820
|
-
addAttr(attrs, "overlapWidth", issue.overlapWidth);
|
|
244821
|
-
addAttr(attrs, "overlapHeight", issue.overlapHeight);
|
|
244822
|
-
return [
|
|
244823
|
-
`<ComponentOverlap ${attrs.join(" ")}>`,
|
|
244824
|
-
...issue.correctionSuggestions.map(correctionSuggestionToString),
|
|
244825
|
-
"</ComponentOverlap>"
|
|
244826
|
-
].join(`
|
|
244827
|
-
`);
|
|
244828
|
-
};
|
|
244829
|
-
var capacitorSymbolHorizontalIssueToString = (issue) => {
|
|
244830
|
-
const attrs = [];
|
|
244831
|
-
addAttr(attrs, "componentName", issue.schematicBox.sourceComponentName);
|
|
244832
|
-
addAttr(attrs, "schX", issue.schematicBox.schX);
|
|
244833
|
-
addAttr(attrs, "schY", issue.schematicBox.schY);
|
|
244834
|
-
addAttr(attrs, "width", issue.schematicBox.width);
|
|
244835
|
-
addAttr(attrs, "height", issue.schematicBox.height);
|
|
244836
|
-
return `<CapacitorSymbolHorizontal ${attrs.join(" ")} />`;
|
|
244837
|
-
};
|
|
244838
|
-
var verboseSchematicNetLabelIssueToString = (issue) => {
|
|
244839
|
-
const attrs = [];
|
|
244840
|
-
addAttr(attrs, "message", issue.message, { escape: false });
|
|
244841
|
-
addAttr(attrs, "text", issue.text);
|
|
244842
|
-
addAttr(attrs, "involvedPins", issue.involvedPins.join(","));
|
|
244843
|
-
addAttr(attrs, "schX", issue.schX);
|
|
244844
|
-
addAttr(attrs, "schY", issue.schY);
|
|
244845
|
-
return `<VerboseSchematicNetLabel ${attrs.join(" ")} />`;
|
|
244846
|
-
};
|
|
244847
|
-
var schematicBoxTooWideIssueToString = (issue) => {
|
|
244848
|
-
const attrs = [];
|
|
244849
|
-
addAttr(attrs, "message", issue.message, { escape: false });
|
|
244850
|
-
addAttr(attrs, "componentName", issue.schematicBox.sourceComponentName);
|
|
244851
|
-
addAttr(attrs, "currentSchWidth", issue.schematicBox.width);
|
|
244852
|
-
addAttr(attrs, "measuredInnerLabelHorizontalEmptySpace", issue.measuredInnerLabelHorizontalEmptySpace);
|
|
244853
|
-
addAttr(attrs, "maxAllowedInnerLabelHorizontalEmptySpace", issue.maxAllowedInnerLabelHorizontalEmptySpace);
|
|
244854
|
-
addAttr(attrs, "suggestedSchWidth", issue.suggestedSchWidth);
|
|
244855
|
-
return `<${issue.lineItemType} ${attrs.join(" ")} />`;
|
|
244856
|
-
};
|
|
244857
|
-
var schematicPinPaddingToEdgeTooLargeIssueToString = (issue) => {
|
|
244858
|
-
const attrs = [];
|
|
244859
|
-
addAttr(attrs, "message", issue.message, { escape: false });
|
|
244860
|
-
addAttr(attrs, "componentName", issue.schematicBox.sourceComponentName);
|
|
244861
|
-
addAttr(attrs, "pinSide", issue.pinSide);
|
|
244862
|
-
addAttr(attrs, "edgeSide", issue.edgeSide);
|
|
244863
|
-
addAttr(attrs, "pinName", issue.pinName);
|
|
244864
|
-
addAttr(attrs, "measuredPadding", issue.measuredPadding);
|
|
244865
|
-
addAttr(attrs, "maxAllowedPadding", issue.maxAllowedPadding);
|
|
244866
|
-
addAttr(attrs, "excessPadding", issue.excessPadding);
|
|
244867
|
-
addAttr(attrs, "suggestedSchWidth", issue.suggestedSchWidth);
|
|
244868
|
-
addAttr(attrs, "suggestedSchHeight", issue.suggestedSchHeight);
|
|
244869
|
-
return `<SchematicPinPaddingToEdgeTooLarge ${attrs.join(" ")} />`;
|
|
244870
|
-
};
|
|
244871
|
-
var correctionSuggestionToString = (suggestion) => {
|
|
244872
|
-
const attrs = [];
|
|
244873
|
-
addAttr(attrs, "target", suggestion.targetComponentName);
|
|
244874
|
-
if (suggestion.deltaSchX !== 0) {
|
|
244875
|
-
addAttr(attrs, "newSchX", suggestion.newSchX);
|
|
244876
|
-
addAttr(attrs, "deltaSchX", suggestion.deltaSchX, { formatDelta: true });
|
|
244877
|
-
}
|
|
244878
|
-
if (suggestion.deltaSchY !== 0) {
|
|
244879
|
-
addAttr(attrs, "newSchY", suggestion.newSchY);
|
|
244880
|
-
addAttr(attrs, "deltaSchY", suggestion.deltaSchY, { formatDelta: true });
|
|
244881
|
-
}
|
|
244882
|
-
return `<OverlapCorrectionSuggestion ${attrs.join(" ")} />`;
|
|
244883
|
-
};
|
|
244884
|
-
var escapeAttr3 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">");
|
|
245454
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/solvers/SchematicPlacementPipeline/SchematicPlacementPipeline.ts
|
|
245455
|
+
class SchematicPlacementPipeline extends BasePipelineSolver2 {
|
|
245456
|
+
ctx;
|
|
245457
|
+
issues = [];
|
|
245458
|
+
pipelineDef = [
|
|
245459
|
+
definePipelineStep3("SchematicBoxOverlapSolver", SchematicBoxOverlapSolver, (p3) => [
|
|
245460
|
+
{ ctx: p3.ctx, issues: p3.issues }
|
|
245461
|
+
]),
|
|
245462
|
+
definePipelineStep3("CapacitorOrientationSolver", CapacitorOrientationSolver, (p3) => [
|
|
245463
|
+
{ ctx: p3.ctx, issues: p3.issues }
|
|
245464
|
+
]),
|
|
245465
|
+
definePipelineStep3("VerboseNetLabelSolver", VerboseNetLabelSolver, (p3) => [
|
|
245466
|
+
{ ctx: p3.ctx, issues: p3.issues }
|
|
245467
|
+
]),
|
|
245468
|
+
definePipelineStep3("SchematicBoxTooWideSolver", SchematicBoxTooWideSolver, (p3) => [
|
|
245469
|
+
{ ctx: p3.ctx, issues: p3.issues }
|
|
245470
|
+
]),
|
|
245471
|
+
definePipelineStep3("SchematicPinPaddingToEdgeSolver", SchematicPinPaddingToEdgeSolver, (p3) => [
|
|
245472
|
+
{ ctx: p3.ctx, issues: p3.issues }
|
|
245473
|
+
]),
|
|
245474
|
+
definePipelineStep3("SchematicBoxInnerLabelCollisionSolver", SchematicBoxInnerLabelCollisionSolver, (p3) => [
|
|
245475
|
+
{ ctx: p3.ctx, issues: p3.issues }
|
|
245476
|
+
]),
|
|
245477
|
+
definePipelineStep3("DiodeResistorAlignmentSolver", DiodeResistorAlignmentSolver, (p3) => [
|
|
245478
|
+
{ ctx: p3.ctx, issues: p3.issues }
|
|
245479
|
+
])
|
|
245480
|
+
];
|
|
245481
|
+
_setup() {
|
|
245482
|
+
this.ctx = buildSolverContext(this.inputProblem);
|
|
245483
|
+
}
|
|
245484
|
+
getOutput() {
|
|
245485
|
+
return {
|
|
245486
|
+
issues: this.issues,
|
|
245487
|
+
componentPlacements: this.ctx.componentPlacements
|
|
245488
|
+
};
|
|
245489
|
+
}
|
|
245490
|
+
}
|
|
244885
245491
|
|
|
245492
|
+
// node_modules/@tscircuit/circuit-json-schematic-placement-analysis/lib/analyze-schematic-placement.ts
|
|
244886
245493
|
class SchematicPlacementAnalysis {
|
|
244887
245494
|
lineItems;
|
|
244888
245495
|
constructor(lineItems) {
|
|
@@ -244894,32 +245501,47 @@ class SchematicPlacementAnalysis {
|
|
|
244894
245501
|
getString() {
|
|
244895
245502
|
return this.toString();
|
|
244896
245503
|
}
|
|
245504
|
+
schematicBoxPlacementsToString(lineItem) {
|
|
245505
|
+
const attrs = [];
|
|
245506
|
+
addAttr(attrs, "componentName", lineItem.sourceComponentName);
|
|
245507
|
+
addAttr(attrs, "positionAnchor", lineItem.positionAnchor);
|
|
245508
|
+
addAttr(attrs, "schX", lineItem.schX);
|
|
245509
|
+
addAttr(attrs, "schY", lineItem.schY);
|
|
245510
|
+
addAttr(attrs, "width", lineItem.width);
|
|
245511
|
+
addAttr(attrs, "height", lineItem.height);
|
|
245512
|
+
return `<SchematicBoxPlacement ${attrs.join(" ")} />`;
|
|
245513
|
+
}
|
|
245514
|
+
schematicIssuesToString(issue) {
|
|
245515
|
+
switch (issue.lineItemType) {
|
|
245516
|
+
case "ComponentOverlap":
|
|
245517
|
+
return SchematicBoxOverlapSolver.issueToString(issue);
|
|
245518
|
+
case "CapacitorSymbolHorizontal":
|
|
245519
|
+
return CapacitorOrientationSolver.issueToString(issue);
|
|
245520
|
+
case "VerboseSchematicNetLabel":
|
|
245521
|
+
return VerboseNetLabelSolver.issueToString(issue);
|
|
245522
|
+
case "PinHeaderSchematicBoxTooWide":
|
|
245523
|
+
case "GenericSchematicBoxTooWide":
|
|
245524
|
+
return SchematicBoxTooWideSolver.issueToString(issue);
|
|
245525
|
+
case "SchematicBoxInnerLabelCollision":
|
|
245526
|
+
return SchematicBoxInnerLabelCollisionSolver.issueToString(issue);
|
|
245527
|
+
case "SchematicPinPaddingToEdgeTooLarge":
|
|
245528
|
+
return SchematicPinPaddingToEdgeSolver.issueToString(issue);
|
|
245529
|
+
case "DiodeResistorNotAligned":
|
|
245530
|
+
return DiodeResistorAlignmentSolver.issueToString(issue);
|
|
245531
|
+
default:
|
|
245532
|
+
return "";
|
|
245533
|
+
}
|
|
245534
|
+
}
|
|
244897
245535
|
toString() {
|
|
244898
245536
|
const schematicBoxPlacements = this.lineItems.filter((lineItem) => lineItem.lineItemType === "SchematicBoxPlacement");
|
|
244899
245537
|
const issues = this.lineItems.flatMap((lineItem) => lineItem.lineItemType === "SchematicPlacementIssues" ? lineItem.issues : []);
|
|
244900
245538
|
return [
|
|
244901
245539
|
"<SchematicBoxPositions>",
|
|
244902
|
-
...schematicBoxPlacements.map(
|
|
245540
|
+
...schematicBoxPlacements.map(this.schematicBoxPlacementsToString),
|
|
244903
245541
|
"</SchematicBoxPositions>",
|
|
244904
245542
|
...issues.length > 0 ? [
|
|
244905
245543
|
"<SchematicPlacementIssues>",
|
|
244906
|
-
...issues.map(
|
|
244907
|
-
switch (issue.lineItemType) {
|
|
244908
|
-
case "ComponentOverlap":
|
|
244909
|
-
return overlapIssueToString(issue);
|
|
244910
|
-
case "CapacitorSymbolHorizontal":
|
|
244911
|
-
return capacitorSymbolHorizontalIssueToString(issue);
|
|
244912
|
-
case "VerboseSchematicNetLabel":
|
|
244913
|
-
return verboseSchematicNetLabelIssueToString(issue);
|
|
244914
|
-
case "PinHeaderSchematicBoxTooWide":
|
|
244915
|
-
case "GenericSchematicBoxTooWide":
|
|
244916
|
-
return schematicBoxTooWideIssueToString(issue);
|
|
244917
|
-
case "SchematicPinPaddingToEdgeTooLarge":
|
|
244918
|
-
return schematicPinPaddingToEdgeTooLargeIssueToString(issue);
|
|
244919
|
-
default:
|
|
244920
|
-
return "";
|
|
244921
|
-
}
|
|
244922
|
-
}),
|
|
245544
|
+
...issues.map(this.schematicIssuesToString),
|
|
244923
245545
|
"</SchematicPlacementIssues>"
|
|
244924
245546
|
] : []
|
|
244925
245547
|
].join(`
|
|
@@ -244927,24 +245549,14 @@ class SchematicPlacementAnalysis {
|
|
|
244927
245549
|
}
|
|
244928
245550
|
}
|
|
244929
245551
|
var analyzeSchematicPlacement = (circuitJson) => {
|
|
244930
|
-
const
|
|
244931
|
-
|
|
245552
|
+
const pipeline = new SchematicPlacementPipeline(circuitJson);
|
|
245553
|
+
pipeline.solve();
|
|
245554
|
+
const { issues, componentPlacements } = pipeline.getOutput();
|
|
244932
245555
|
const lineItems = [
|
|
244933
|
-
...
|
|
244934
|
-
...schematicBoxes.filter((schematicBox) => !schematicBox.schematic_component_id || !schematicComponentIds.has(schematicBox.schematic_component_id)).map((schematicBox) => schematicBoxToLineItem(schematicBox, circuitJson))
|
|
244935
|
-
];
|
|
244936
|
-
const issues = [
|
|
244937
|
-
...generateSchematicPlacementIssues(lineItems),
|
|
244938
|
-
...generateCapacitorOrientationIssues(lineItems, circuitJson),
|
|
244939
|
-
...generateVerboseNetLabelIssues(circuitJson),
|
|
244940
|
-
...generatePinHeaderSchematicBoxTooWideIssues(lineItems, circuitJson),
|
|
244941
|
-
...generateGenericSchematicBoxTooWideIssues(lineItems, circuitJson),
|
|
244942
|
-
...generateSchematicPinPaddingToEdgeTooLargeIssues(lineItems, circuitJson)
|
|
244943
|
-
];
|
|
244944
|
-
return new SchematicPlacementAnalysis([
|
|
244945
|
-
...lineItems,
|
|
245556
|
+
...componentPlacements,
|
|
244946
245557
|
...issues.length > 0 ? [{ lineItemType: "SchematicPlacementIssues", issues }] : []
|
|
244947
|
-
]
|
|
245558
|
+
];
|
|
245559
|
+
return new SchematicPlacementAnalysis(lineItems);
|
|
244948
245560
|
};
|
|
244949
245561
|
// cli/check/schematic-placement/register.ts
|
|
244950
245562
|
var checkSchematicPlacement = async (file) => {
|