@tscircuit/cli 0.1.1322 → 0.1.1323

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/lib/index.js CHANGED
@@ -47885,7 +47885,7 @@ var require_utils2 = __commonJS((exports2) => {
47885
47885
  }
47886
47886
  }
47887
47887
  };
47888
- function identity5(input) {
47888
+ function identity6(input) {
47889
47889
  return input;
47890
47890
  }
47891
47891
  function stringToArrayLike(str, array) {
@@ -47961,7 +47961,7 @@ var require_utils2 = __commonJS((exports2) => {
47961
47961
  }
47962
47962
  var transform = {};
47963
47963
  transform["string"] = {
47964
- string: identity5,
47964
+ string: identity6,
47965
47965
  array: function(input) {
47966
47966
  return stringToArrayLike(input, new Array(input.length));
47967
47967
  },
@@ -47977,7 +47977,7 @@ var require_utils2 = __commonJS((exports2) => {
47977
47977
  };
47978
47978
  transform["array"] = {
47979
47979
  string: arrayLikeToString,
47980
- array: identity5,
47980
+ array: identity6,
47981
47981
  arraybuffer: function(input) {
47982
47982
  return new Uint8Array(input).buffer;
47983
47983
  },
@@ -47995,7 +47995,7 @@ var require_utils2 = __commonJS((exports2) => {
47995
47995
  array: function(input) {
47996
47996
  return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength));
47997
47997
  },
47998
- arraybuffer: identity5,
47998
+ arraybuffer: identity6,
47999
47999
  uint8array: function(input) {
48000
48000
  return new Uint8Array(input);
48001
48001
  },
@@ -48011,7 +48011,7 @@ var require_utils2 = __commonJS((exports2) => {
48011
48011
  arraybuffer: function(input) {
48012
48012
  return input.buffer;
48013
48013
  },
48014
- uint8array: identity5,
48014
+ uint8array: identity6,
48015
48015
  nodebuffer: function(input) {
48016
48016
  return nodejsUtils.newBufferFrom(input);
48017
48017
  }
@@ -48027,7 +48027,7 @@ var require_utils2 = __commonJS((exports2) => {
48027
48027
  uint8array: function(input) {
48028
48028
  return arrayLikeToArrayLike(input, new Uint8Array(input.length));
48029
48029
  },
48030
- nodebuffer: identity5
48030
+ nodebuffer: identity6
48031
48031
  };
48032
48032
  exports2.transformTo = function(outputType, input) {
48033
48033
  if (!input) {
@@ -65661,7 +65661,7 @@ var getNodeHandler = (winterSpec, { port, middleware = [] }) => {
65661
65661
  }));
65662
65662
  };
65663
65663
  // package.json
65664
- var version = "0.1.1321";
65664
+ var version = "0.1.1322";
65665
65665
  var package_default = {
65666
65666
  name: "@tscircuit/cli",
65667
65667
  version,
@@ -65696,7 +65696,7 @@ var package_default = {
65696
65696
  "circuit-json": "^0.0.403",
65697
65697
  "circuit-json-to-bom-csv": "^0.0.7",
65698
65698
  "circuit-json-to-gerber": "^0.0.49",
65699
- "circuit-json-to-kicad": "^0.0.114",
65699
+ "circuit-json-to-kicad": "^0.0.125",
65700
65700
  "circuit-json-to-pnp-csv": "^0.0.7",
65701
65701
  "circuit-json-to-readable-netlist": "^0.0.15",
65702
65702
  "circuit-json-to-spice": "^0.0.10",
@@ -68353,7 +68353,7 @@ import {
68353
68353
  TextEffects as TextEffects6,
68354
68354
  TextEffectsFont as TextEffectsFont6
68355
68355
  } from "kicadts";
68356
- import { applyToPoint as applyToPoint14 } from "transformation-matrix";
68356
+ import { applyToPoint as applyToPoint15 } from "transformation-matrix";
68357
68357
  import {
68358
68358
  Property as Property2,
68359
68359
  TextEffects as TextEffects7,
@@ -68378,8 +68378,10 @@ import {
68378
68378
  import"kicadts";
68379
68379
  import { FpText, TextEffects as TextEffects8, TextEffectsFont as TextEffectsFont8 } from "kicadts";
68380
68380
  import { applyToPoint as applyToPoint9, rotate as rotate2, identity } from "transformation-matrix";
68381
+ import { FpLine, Stroke as Stroke10 } from "kicadts";
68382
+ import { applyToPoint as applyToPoint10, identity as identity2, rotate as rotate3 } from "transformation-matrix";
68381
68383
  import { FpText as FpText3, TextEffects as TextEffects9, TextEffectsFont as TextEffectsFont9 } from "kicadts";
68382
- import { applyToPoint as applyToPoint10, rotate as rotate3, identity as identity2 } from "transformation-matrix";
68384
+ import { applyToPoint as applyToPoint11, rotate as rotate4, identity as identity3 } from "transformation-matrix";
68383
68385
  import { FootprintModel as FootprintModel3 } from "kicadts";
68384
68386
  import {
68385
68387
  FootprintPad,
@@ -68391,22 +68393,22 @@ import {
68391
68393
  PadNet
68392
68394
  } from "kicadts";
68393
68395
  import {
68394
- applyToPoint as applyToPoint11,
68396
+ applyToPoint as applyToPoint12,
68395
68397
  compose as compose4,
68396
68398
  translate as translate4,
68397
68399
  scale as scale3,
68398
- rotate as rotate4
68400
+ rotate as rotate5
68399
68401
  } from "transformation-matrix";
68400
68402
  import { FootprintPad as FootprintPad2, PadDrill, PadNet as PadNet2 } from "kicadts";
68401
- import { applyToPoint as applyToPoint12, rotate as rotate5, identity as identity3 } from "transformation-matrix";
68402
- import { FootprintPad as FootprintPad3, PadDrill as PadDrill2 } from "kicadts";
68403
68403
  import { applyToPoint as applyToPoint13, rotate as rotate6, identity as identity4 } from "transformation-matrix";
68404
+ import { FootprintPad as FootprintPad3, PadDrill as PadDrill2 } from "kicadts";
68405
+ import { applyToPoint as applyToPoint14, rotate as rotate7, identity as identity5 } from "transformation-matrix";
68404
68406
  import { Segment, SegmentNet } from "kicadts";
68405
- import { applyToPoint as applyToPoint15 } from "transformation-matrix";
68406
- import { Via, ViaNet } from "kicadts";
68407
68407
  import { applyToPoint as applyToPoint16 } from "transformation-matrix";
68408
- import { Footprint as Footprint4 } from "kicadts";
68408
+ import { Via, ViaNet } from "kicadts";
68409
68409
  import { applyToPoint as applyToPoint17 } from "transformation-matrix";
68410
+ import { Footprint as Footprint4 } from "kicadts";
68411
+ import { applyToPoint as applyToPoint18 } from "transformation-matrix";
68410
68412
  import { GrLine } from "kicadts";
68411
68413
  import {
68412
68414
  At as At2,
@@ -68415,8 +68417,8 @@ import {
68415
68417
  TextEffectsFont as TextEffectsFont10,
68416
68418
  TextEffectsJustify as TextEffectsJustify3
68417
68419
  } from "kicadts";
68418
- import { applyToPoint as applyToPoint18 } from "transformation-matrix";
68419
- import { applyToPoint as applyToPoint20 } from "transformation-matrix";
68420
+ import { applyToPoint as applyToPoint19 } from "transformation-matrix";
68421
+ import { applyToPoint as applyToPoint21 } from "transformation-matrix";
68420
68422
  import {
68421
68423
  GrText as GrText2,
68422
68424
  TextEffects as TextEffects11,
@@ -68424,7 +68426,7 @@ import {
68424
68426
  TextEffectsJustify as TextEffectsJustify4,
68425
68427
  At as At3
68426
68428
  } from "kicadts";
68427
- import { applyToPoint as applyToPoint19 } from "transformation-matrix";
68429
+ import { applyToPoint as applyToPoint20 } from "transformation-matrix";
68428
68430
  import { cju as cju3 } from "@tscircuit/circuit-json-util";
68429
68431
  import { cju as cju4 } from "@tscircuit/circuit-json-util";
68430
68432
  import { parseKicadSexpr as parseKicadSexpr2, KicadSch as KicadSch2 } from "kicadts";
@@ -68598,7 +68600,9 @@ function buildSymbolDataFromSchematicPrimitives(params2) {
68598
68600
  circuitJson,
68599
68601
  schematicSymbolId,
68600
68602
  schematicSymbol,
68601
- schematicComponentId
68603
+ schematicComponentId,
68604
+ schematicComponentCenter,
68605
+ schematicComponentSize
68602
68606
  } = params2;
68603
68607
  const circles = circuitJson.filter((el) => el.type === "schematic_circle" && el.schematic_symbol_id === schematicSymbolId);
68604
68608
  const symbolLines = circuitJson.filter((el) => el.type === "schematic_line" && el.schematic_symbol_id === schematicSymbolId);
@@ -68676,9 +68680,10 @@ function buildSymbolDataFromSchematicPrimitives(params2) {
68676
68680
  facingDirection: port.facing_direction
68677
68681
  }));
68678
68682
  symbolPorts.sort((a, b) => a.pinNumber - b.pinNumber);
68683
+ const symbolCenter = schematicSymbol.center || schematicComponentCenter || { x: 0, y: 0 };
68679
68684
  return {
68680
- center: schematicSymbol.center || { x: 0, y: 0 },
68681
- size: schematicSymbol.size || { width: 1, height: 1 },
68685
+ center: symbolCenter,
68686
+ size: schematicSymbol.size || schematicComponentSize || { width: 1, height: 1 },
68682
68687
  primitives: primitives2,
68683
68688
  texts: symbolTexts,
68684
68689
  ports: symbolPorts
@@ -69091,7 +69096,8 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
69091
69096
  keywords: this.getKeywords(sourceComp),
69092
69097
  fpFilters: this.getFpFilters(sourceComp),
69093
69098
  footprintRef: footprintName ? `tscircuit:${footprintName}` : "",
69094
- referencePrefix: getReferencePrefixForComponent(sourceComp)
69099
+ referencePrefix: getReferencePrefixForComponent(sourceComp),
69100
+ symbolScale: this.ctx.kicadSchematicScaleFactor
69095
69101
  });
69096
69102
  }
69097
69103
  createLibrarySymbolFromSchematicSymbol(schematicComponent, sourceComp, cadComponent, schematicSymbolId) {
@@ -69120,7 +69126,9 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
69120
69126
  circuitJson: this.ctx.circuitJson,
69121
69127
  schematicSymbolId,
69122
69128
  schematicSymbol,
69123
- schematicComponentId: schematicComponent.schematic_component_id
69129
+ schematicComponentId: schematicComponent.schematic_component_id,
69130
+ schematicComponentCenter: schematicComponent.center,
69131
+ schematicComponentSize: schematicComponent.size
69124
69132
  });
69125
69133
  const footprintName = getKicadCompatibleComponentName(sourceComp, cadComponent);
69126
69134
  return this.createLibrarySymbol({
@@ -69133,7 +69141,7 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
69133
69141
  fpFilters: this.getFpFilters(sourceComp, schematicSymbol.name),
69134
69142
  footprintRef: footprintName ? `tscircuit:${footprintName}` : "",
69135
69143
  referencePrefix: getReferencePrefixForComponent(sourceComp),
69136
- symbolScale: 1
69144
+ symbolScale: this.ctx.kicadSchematicScaleFactor
69137
69145
  });
69138
69146
  }
69139
69147
  createLibrarySymbolForNetLabel({
@@ -69156,7 +69164,8 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
69156
69164
  description: isPower ? "Power net label" : isGround ? "Ground net label" : "Net symbol",
69157
69165
  keywords: isPower ? "power net" : isGround ? "ground net" : "net",
69158
69166
  fpFilters: "",
69159
- referencePrefix: libId.split(":")[1]?.[0] || "U"
69167
+ referencePrefix: libId.split(":")[1]?.[0] || "U",
69168
+ symbolScale: this.ctx.kicadSchematicScaleFactor
69160
69169
  });
69161
69170
  }
69162
69171
  getSymbolData(symbolName, schematicComponent) {
@@ -69177,8 +69186,6 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
69177
69186
  referencePrefix,
69178
69187
  symbolScale
69179
69188
  }) {
69180
- const CIRCUIT_JSON_SCALE_FACTOR = 15;
69181
- const c2kMatSchScale = symbolScale ?? this.ctx.c2kMatSch?.a ?? CIRCUIT_JSON_SCALE_FACTOR;
69182
69189
  const symbol = new SchematicSymbol4({
69183
69190
  libraryId: libId,
69184
69191
  excludeFromSim: false,
@@ -69204,7 +69211,7 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
69204
69211
  libId,
69205
69212
  symbolData,
69206
69213
  isChip,
69207
- c2kMatSchScale
69214
+ c2kMatSchScale: symbolScale
69208
69215
  });
69209
69216
  symbol.subSymbols.push(drawingSymbol);
69210
69217
  const pinSymbol = createPinSubsymbol({
@@ -69213,7 +69220,7 @@ var AddLibrarySymbolsStage = class extends ConverterStage {
69213
69220
  isChip,
69214
69221
  schematicComponent,
69215
69222
  schematicPorts: this.ctx.db.schematic_port.list(),
69216
- c2kMatSchScale
69223
+ c2kMatSchScale: symbolScale
69217
69224
  });
69218
69225
  symbol.subSymbols.push(pinSymbol);
69219
69226
  symbol._sxEmbeddedFonts = new EmbeddedFonts(false);
@@ -69312,7 +69319,8 @@ var AddSchematicSymbolsStage = class extends ConverterStage {
69312
69319
  const symLibId = new SymbolLibId(libId);
69313
69320
  symbol._sxLibId = symLibId;
69314
69321
  const { reference, value, description } = this.getComponentMetadata(sourceComponent);
69315
- const { refTextPos, valTextPos } = this.getTextPositions(schematicComponent, { x, y });
69322
+ const hasChipManufacturerValue = sourceComponent.ftype === "simple_chip" && Boolean(sourceComponent.manufacturer_part_number);
69323
+ const { refTextPos, valTextPos } = this.getTextPositions(schematicComponent, hasChipManufacturerValue);
69316
69324
  let symbolMetadata;
69317
69325
  if (schematicSymbolId) {
69318
69326
  const schSymEl = this.ctx.circuitJson.find((el) => el.type === "schematic_symbol" && el.schematic_symbol_id === schematicSymbolId);
@@ -69328,7 +69336,7 @@ var AddSchematicSymbolsStage = class extends ConverterStage {
69328
69336
  at: [refTextPos.x, refTextPos.y, 0],
69329
69337
  effects: this.createTextEffects(Number(refMeta?.effects?.font?.size?.x ?? 1.27), refMeta?.effects?.hide ?? false)
69330
69338
  });
69331
- const hideValue = sourceComponent.ftype === "simple_chip";
69339
+ const hideValue = sourceComponent.ftype === "simple_chip" && !hasChipManufacturerValue;
69332
69340
  const valMeta = symbolMetadata?.properties?.Value;
69333
69341
  const valueProperty = new SymbolProperty2({
69334
69342
  key: "Value",
@@ -69447,22 +69455,62 @@ var AddSchematicSymbolsStage = class extends ConverterStage {
69447
69455
  }
69448
69456
  this.finished = true;
69449
69457
  }
69450
- getTextPositions(schematicComponent, symbolKicadPos) {
69458
+ getTextPositions(schematicComponent, placeValueAtNamePosition) {
69459
+ const c2kMatSch = this.ctx.c2kMatSch;
69460
+ const schematicScale = c2kMatSch.a;
69461
+ const symbolKicadPos = applyToPoint5(c2kMatSch, {
69462
+ x: schematicComponent.center.x,
69463
+ y: schematicComponent.center.y
69464
+ });
69465
+ const componentHeightMm = (schematicComponent.size?.height || 1) * schematicScale;
69466
+ const referenceAboveBodyY = symbolKicadPos.y - componentHeightMm / 2 - 3;
69467
+ const isCustomSymbol = this.isCustomSymbolComponent(schematicComponent);
69468
+ if (isCustomSymbol) {
69469
+ const customHeightMm = (schematicComponent.size?.height || 1) * this.ctx.kicadSchematicScaleFactor;
69470
+ const refTextPos2 = {
69471
+ x: symbolKicadPos.x,
69472
+ y: symbolKicadPos.y - customHeightMm / 2 - 3
69473
+ };
69474
+ const valTextPos2 = {
69475
+ x: symbolKicadPos.x,
69476
+ y: symbolKicadPos.y + customHeightMm / 2 + 3
69477
+ };
69478
+ if (placeValueAtNamePosition) {
69479
+ return {
69480
+ refTextPos: refTextPos2,
69481
+ valTextPos: { x: symbolKicadPos.x, y: symbolKicadPos.y }
69482
+ };
69483
+ }
69484
+ return { refTextPos: refTextPos2, valTextPos: valTextPos2 };
69485
+ }
69451
69486
  const schematicTexts = this.ctx.db.schematic_text?.list?.()?.filter((t) => t.schematic_component_id === schematicComponent.schematic_component_id) || [];
69452
69487
  const refText = schematicTexts.find((t) => t.text && t.text.length > 0);
69453
- if (refText && this.ctx.c2kMatSch) {
69454
- const refTextPos2 = applyToPoint5(this.ctx.c2kMatSch, {
69488
+ if (refText) {
69489
+ const nameTextPos = applyToPoint5(c2kMatSch, {
69455
69490
  x: refText.position.x,
69456
69491
  y: refText.position.y
69457
69492
  });
69493
+ if (placeValueAtNamePosition) {
69494
+ return {
69495
+ refTextPos: { x: symbolKicadPos.x, y: referenceAboveBodyY },
69496
+ valTextPos: nameTextPos
69497
+ };
69498
+ }
69499
+ const refTextPos2 = nameTextPos;
69458
69500
  const valTextPos2 = { x: symbolKicadPos.x, y: symbolKicadPos.y + 6 };
69459
69501
  return { refTextPos: refTextPos2, valTextPos: valTextPos2 };
69460
69502
  }
69461
69503
  const symbolName = schematicComponent.symbol_name;
69504
+ if (!symbolName) {
69505
+ return {
69506
+ refTextPos: { x: symbolKicadPos.x, y: referenceAboveBodyY },
69507
+ valTextPos: { x: symbolKicadPos.x, y: symbolKicadPos.y + 6 }
69508
+ };
69509
+ }
69462
69510
  const symbol = symbols3[symbolName];
69463
69511
  if (!symbol) {
69464
69512
  return {
69465
- refTextPos: { x: symbolKicadPos.x, y: symbolKicadPos.y - 6 },
69513
+ refTextPos: { x: symbolKicadPos.x, y: referenceAboveBodyY },
69466
69514
  valTextPos: { x: symbolKicadPos.x, y: symbolKicadPos.y + 6 }
69467
69515
  };
69468
69516
  }
@@ -69480,16 +69528,22 @@ var AddSchematicSymbolsStage = class extends ConverterStage {
69480
69528
  const symbolCenter = symbol.center || { x: 0, y: 0 };
69481
69529
  const isVertical = symbolName.includes("_down") || symbolName.includes("_up");
69482
69530
  const horizontalTextOffset = isVertical ? 0.15 : 0;
69483
- const refTextPos = refTextPrimitive && this.ctx.c2kMatSch ? applyToPoint5(this.ctx.c2kMatSch, {
69531
+ const refTextPos = refTextPrimitive ? applyToPoint5(c2kMatSch, {
69484
69532
  x: schematicComponent.center.x + (refTextPrimitive.x - symbolCenter.x) + horizontalTextOffset,
69485
69533
  y: schematicComponent.center.y + (refTextPrimitive.y - symbolCenter.y)
69486
- }) : { x: symbolKicadPos.x, y: symbolKicadPos.y - 6 };
69487
- const valTextPos = valTextPrimitive && this.ctx.c2kMatSch ? applyToPoint5(this.ctx.c2kMatSch, {
69534
+ }) : { x: symbolKicadPos.x, y: referenceAboveBodyY };
69535
+ const valTextPos = valTextPrimitive ? applyToPoint5(c2kMatSch, {
69488
69536
  x: schematicComponent.center.x + (valTextPrimitive.x - symbolCenter.x) + horizontalTextOffset,
69489
69537
  y: schematicComponent.center.y + (valTextPrimitive.y - symbolCenter.y)
69490
69538
  }) : { x: symbolKicadPos.x, y: symbolKicadPos.y + 6 };
69491
69539
  return { refTextPos, valTextPos };
69492
69540
  }
69541
+ isCustomSymbolComponent(schematicComponent) {
69542
+ const componentId = schematicComponent.schematic_component_id;
69543
+ if (!componentId)
69544
+ return false;
69545
+ return this.ctx.circuitJson.some((el) => (el.type === "schematic_line" || el.type === "schematic_circle" || el.type === "schematic_path") && el.schematic_component_id === componentId && el.schematic_symbol_id);
69546
+ }
69493
69547
  getComponentMetadata(sourceComp) {
69494
69548
  const name = sourceComp.name || "?";
69495
69549
  const reference = getReferenceDesignator(sourceComp);
@@ -69524,7 +69578,7 @@ var AddSchematicSymbolsStage = class extends ConverterStage {
69524
69578
  if (sourceComp.ftype === "simple_chip") {
69525
69579
  return {
69526
69580
  reference,
69527
- value: name,
69581
+ value: sourceComp.manufacturer_part_number || "",
69528
69582
  description: "Integrated Circuit"
69529
69583
  };
69530
69584
  }
@@ -69903,6 +69957,7 @@ function selectSchematicPaperSize(contentWidth, contentHeight, paddingMm = 20) {
69903
69957
  }
69904
69958
  return PAPER_SIZES[PAPER_SIZES.length - 1];
69905
69959
  }
69960
+ var DEFAULT_SCHEMATIC_SCALE_FACTOR = 15;
69906
69961
  var CircuitJsonToKicadSchConverter = class {
69907
69962
  ctx;
69908
69963
  pipeline;
@@ -69912,11 +69967,11 @@ var CircuitJsonToKicadSchConverter = class {
69912
69967
  return this.pipeline[this.currentStageIndex];
69913
69968
  }
69914
69969
  constructor(circuitJson) {
69915
- const CIRCUIT_JSON_SCALE_FACTOR = 15;
69970
+ const kicadSchematicScaleFactor = DEFAULT_SCHEMATIC_SCALE_FACTOR;
69916
69971
  const db = cju(circuitJson);
69917
69972
  const { center, bounds } = getSchematicBoundsAndCenter(db);
69918
- const schematicWidthMm = (bounds.maxX - bounds.minX) * CIRCUIT_JSON_SCALE_FACTOR;
69919
- const schematicHeightMm = (bounds.maxY - bounds.minY) * CIRCUIT_JSON_SCALE_FACTOR;
69973
+ const schematicWidthMm = (bounds.maxX - bounds.minX) * kicadSchematicScaleFactor;
69974
+ const schematicHeightMm = (bounds.maxY - bounds.minY) * kicadSchematicScaleFactor;
69920
69975
  const paperSize = selectSchematicPaperSize(schematicWidthMm, schematicHeightMm);
69921
69976
  const KICAD_CENTER_X = paperSize.width / 2;
69922
69977
  const KICAD_CENTER_Y = paperSize.height / 2;
@@ -69927,8 +69982,9 @@ var CircuitJsonToKicadSchConverter = class {
69927
69982
  generator: "circuit-json-to-kicad",
69928
69983
  generatorVersion: "0.0.1"
69929
69984
  }),
69985
+ kicadSchematicScaleFactor,
69930
69986
  schematicPaperSize: paperSize,
69931
- c2kMatSch: compose2(translate2(KICAD_CENTER_X, KICAD_CENTER_Y), scale(CIRCUIT_JSON_SCALE_FACTOR, -CIRCUIT_JSON_SCALE_FACTOR), translate2(-center.x, -center.y))
69987
+ c2kMatSch: compose2(translate2(KICAD_CENTER_X, KICAD_CENTER_Y), scale(kicadSchematicScaleFactor, -kicadSchematicScaleFactor), translate2(-center.x, -center.y))
69932
69988
  };
69933
69989
  this.pipeline = [
69934
69990
  new InitializeSchematicStage(circuitJson, this.ctx),
@@ -70378,6 +70434,15 @@ function applyMetadataToFootprint({
70378
70434
  effects: createTextEffects2(descMeta?.effects),
70379
70435
  hidden: descMeta?.hide ?? true
70380
70436
  }));
70437
+ newProperties.push(new Property2({
70438
+ key: "Supplier Part Number",
70439
+ value: componentProperty.supplierPartNumber,
70440
+ position: [0, 0, 0],
70441
+ layer: "F.Fab",
70442
+ uuid: generateDeterministicUuid(`${componentProperty.reference}-property-SupplierPartNumber`),
70443
+ effects: createTextEffects2(),
70444
+ hidden: true
70445
+ }));
70381
70446
  footprint.properties = newProperties;
70382
70447
  if (metadata?.attributes) {
70383
70448
  if (!footprint.attr) {
@@ -70431,64 +70496,78 @@ function applyMetadataToFootprint({
70431
70496
  footprint.models = [model, ...existingModels];
70432
70497
  }
70433
70498
  }
70499
+ function getJlcpcbSupplierPartNumber(sourceComp) {
70500
+ const jlcpcbPartNumbers = sourceComp.supplier_part_numbers?.jlcpcb;
70501
+ return jlcpcbPartNumbers && jlcpcbPartNumbers.length > 0 ? jlcpcbPartNumbers.join(", ") : undefined;
70502
+ }
70434
70503
  function getkicadComponentProperty(sourceComp) {
70435
70504
  const name = sourceComp.name || "?";
70436
70505
  const reference = getReferenceDesignator(sourceComp);
70506
+ const supplierPartNumber = getJlcpcbSupplierPartNumber(sourceComp);
70437
70507
  if (sourceComp.ftype === "simple_resistor") {
70438
70508
  const resistor = sourceComp;
70439
70509
  return {
70440
70510
  reference,
70441
- kicadComponentValue: resistor.display_resistance || "R"
70511
+ kicadComponentValue: resistor.display_resistance || "R",
70512
+ supplierPartNumber
70442
70513
  };
70443
70514
  }
70444
70515
  if (sourceComp.ftype === "simple_capacitor") {
70445
70516
  const capacitor = sourceComp;
70446
70517
  return {
70447
70518
  reference,
70448
- kicadComponentValue: capacitor.display_capacitance || "C"
70519
+ kicadComponentValue: capacitor.display_capacitance || "C",
70520
+ supplierPartNumber
70449
70521
  };
70450
70522
  }
70451
70523
  if (sourceComp.ftype === "simple_inductor") {
70452
70524
  const inductor = sourceComp;
70453
70525
  return {
70454
70526
  reference,
70455
- kicadComponentValue: inductor.display_inductance || "L"
70527
+ kicadComponentValue: inductor.display_inductance || "L",
70528
+ supplierPartNumber
70456
70529
  };
70457
70530
  }
70458
70531
  if (sourceComp.ftype === "simple_diode") {
70459
70532
  return {
70460
70533
  reference,
70461
- kicadComponentValue: "D"
70534
+ kicadComponentValue: "D",
70535
+ supplierPartNumber
70462
70536
  };
70463
70537
  }
70464
70538
  if (sourceComp.ftype === "simple_chip") {
70465
70539
  return {
70466
70540
  reference,
70467
- kicadComponentValue: sourceComp?.manufacturer_part_number
70541
+ kicadComponentValue: sourceComp?.manufacturer_part_number,
70542
+ supplierPartNumber
70468
70543
  };
70469
70544
  }
70470
70545
  if (sourceComp.ftype === "simple_led") {
70471
70546
  return {
70472
70547
  reference,
70473
- kicadComponentValue: sourceComp.manufacturer_part_number || "LED"
70548
+ kicadComponentValue: sourceComp.manufacturer_part_number || "LED",
70549
+ supplierPartNumber
70474
70550
  };
70475
70551
  }
70476
70552
  if (sourceComp.ftype === "simple_switch") {
70477
70553
  return {
70478
70554
  reference,
70479
- kicadComponentValue: sourceComp.manufacturer_part_number || "SW"
70555
+ kicadComponentValue: sourceComp.manufacturer_part_number || "SW",
70556
+ supplierPartNumber
70480
70557
  };
70481
70558
  }
70482
70559
  if (sourceComp.ftype === "simple_potentiometer") {
70483
70560
  const potentiometer = sourceComp;
70484
70561
  return {
70485
70562
  reference,
70486
- kicadComponentValue: potentiometer.display_max_resistance || "POT"
70563
+ kicadComponentValue: potentiometer.display_max_resistance || "POT",
70564
+ supplierPartNumber
70487
70565
  };
70488
70566
  }
70489
70567
  return {
70490
70568
  reference,
70491
- kicadComponentValue: name
70569
+ kicadComponentValue: name,
70570
+ supplierPartNumber
70492
70571
  };
70493
70572
  }
70494
70573
  function convertSilkscreenCircles(silkscreenCircles, componentCenter) {
@@ -70706,13 +70785,52 @@ function convertSilkscreenTexts(silkscreenTexts, componentCenter, componentRotat
70706
70785
  }
70707
70786
  return fpTexts;
70708
70787
  }
70788
+ function convertSilkscreenPaths(silkscreenPaths, { componentCenter, componentRotation = 0 }) {
70789
+ const fpLines = [];
70790
+ const rotationMatrix = componentRotation !== 0 ? rotate3(componentRotation * Math.PI / 180) : identity2();
70791
+ for (const path7 of silkscreenPaths) {
70792
+ if (!path7.route || path7.route.length < 2)
70793
+ continue;
70794
+ const layerMap = {
70795
+ top: "F.SilkS",
70796
+ bottom: "B.SilkS"
70797
+ };
70798
+ const kicadLayer = layerMap[path7.layer] || path7.layer || "F.SilkS";
70799
+ for (let i = 0;i < path7.route.length - 1; i++) {
70800
+ const startPoint = path7.route[i];
70801
+ const endPoint = path7.route[i + 1];
70802
+ if (!startPoint || !endPoint)
70803
+ continue;
70804
+ const startRelative = applyToPoint10(rotationMatrix, {
70805
+ x: startPoint.x - componentCenter.x,
70806
+ y: -(startPoint.y - componentCenter.y)
70807
+ });
70808
+ const endRelative = applyToPoint10(rotationMatrix, {
70809
+ x: endPoint.x - componentCenter.x,
70810
+ y: -(endPoint.y - componentCenter.y)
70811
+ });
70812
+ const fpLine = new FpLine({
70813
+ start: { x: startRelative.x, y: startRelative.y },
70814
+ end: { x: endRelative.x, y: endRelative.y },
70815
+ layer: kicadLayer,
70816
+ stroke: new Stroke10
70817
+ });
70818
+ if (fpLine.stroke) {
70819
+ fpLine.stroke.width = path7.stroke_width || 0.15;
70820
+ fpLine.stroke.type = "default";
70821
+ }
70822
+ fpLines.push(fpLine);
70823
+ }
70824
+ }
70825
+ return fpLines;
70826
+ }
70709
70827
  function convertNoteTexts(noteTexts, componentCenter, componentRotation) {
70710
70828
  const fpTexts = [];
70711
70829
  for (const textElement of noteTexts) {
70712
70830
  const relX = textElement.anchor_position.x - componentCenter.x;
70713
70831
  const relY = -(textElement.anchor_position.y - componentCenter.y);
70714
- const rotationMatrix = componentRotation !== 0 ? rotate3(componentRotation * Math.PI / 180) : identity2();
70715
- const rotatedPos = applyToPoint10(rotationMatrix, { x: relX, y: relY });
70832
+ const rotationMatrix = componentRotation !== 0 ? rotate4(componentRotation * Math.PI / 180) : identity3();
70833
+ const rotatedPos = applyToPoint11(rotationMatrix, { x: relX, y: relY });
70716
70834
  const fontSize = textElement.font_size || 1;
70717
70835
  const font = new TextEffectsFont9;
70718
70836
  font.size = { width: fontSize, height: fontSize };
@@ -70776,8 +70894,8 @@ function createSmdPadFromCircuitJson({
70776
70894
  } else {
70777
70895
  throw new Error("Pad must have either x/y coordinates or points array");
70778
70896
  }
70779
- const cj2kicadMatrix = compose4(componentRotation !== 0 ? rotate4(componentRotation * Math.PI / 180) : { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, scale3(1, -1), translate4(-componentCenter.x, -componentCenter.y));
70780
- const rotatedPos = applyToPoint11(cj2kicadMatrix, {
70897
+ const cj2kicadMatrix = compose4(componentRotation !== 0 ? rotate5(componentRotation * Math.PI / 180) : { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, scale3(1, -1), translate4(-componentCenter.x, -componentCenter.y));
70898
+ const rotatedPos = applyToPoint12(cj2kicadMatrix, {
70781
70899
  x: padX,
70782
70900
  y: padY
70783
70901
  });
@@ -70790,6 +70908,8 @@ function createSmdPadFromCircuitJson({
70790
70908
  let padSize;
70791
70909
  let padOptions;
70792
70910
  let padPrimitives;
70911
+ let roundrect_rratio;
70912
+ let rotation = 0;
70793
70913
  if (pcbPad.shape === "circle") {
70794
70914
  padShape = "circle";
70795
70915
  padSize = [
@@ -70800,7 +70920,7 @@ function createSmdPadFromCircuitJson({
70800
70920
  const points = pcbPad.points;
70801
70921
  const pointTransformMatrix = compose4(scale3(1, -1), translate4(-padX, -padY));
70802
70922
  const relativePoints = points.map((p) => {
70803
- const transformed = applyToPoint11(pointTransformMatrix, { x: p.x, y: p.y });
70923
+ const transformed = applyToPoint12(pointTransformMatrix, { x: p.x, y: p.y });
70804
70924
  return new Xy4(transformed.x, transformed.y);
70805
70925
  });
70806
70926
  const grPoly = new PadPrimitiveGrPoly;
@@ -70813,19 +70933,32 @@ function createSmdPadFromCircuitJson({
70813
70933
  padOptions = new PadOptions;
70814
70934
  padOptions.anchor = "circle";
70815
70935
  padSize = [0.2, 0.2];
70816
- } else {
70817
- padShape = "rect";
70818
- padSize = [
70819
- "width" in pcbPad ? pcbPad.width : 0.5,
70820
- "height" in pcbPad ? pcbPad.height : 0.5
70821
- ];
70936
+ } else if (pcbPad.shape === "rotated_rect") {
70937
+ const cornerRadius = pcbPad.corner_radius ?? pcbPad.rect_border_radius;
70938
+ if (cornerRadius) {
70939
+ padShape = "roundrect";
70940
+ roundrect_rratio = cornerRadius / Math.min(pcbPad.width, pcbPad.height);
70941
+ } else {
70942
+ padShape = "rect";
70943
+ }
70944
+ padSize = [pcbPad.width, pcbPad.height];
70945
+ rotation = pcbPad.ccw_rotation;
70946
+ } else if (pcbPad.shape === "rect") {
70947
+ const cornerRadius = pcbPad.corner_radius ?? pcbPad.rect_border_radius;
70948
+ if (cornerRadius) {
70949
+ padShape = "roundrect";
70950
+ roundrect_rratio = cornerRadius / Math.min(pcbPad.width, pcbPad.height);
70951
+ } else {
70952
+ padShape = "rect";
70953
+ }
70954
+ padSize = [pcbPad.width, pcbPad.height];
70822
70955
  }
70823
70956
  const padData = `pad:${componentId}:${padNumber}:${rotatedPos.x},${rotatedPos.y}`;
70824
70957
  const pad = new FootprintPad({
70825
70958
  number: String(padNumber),
70826
70959
  padType: "smd",
70827
70960
  shape: padShape,
70828
- at: [rotatedPos.x, rotatedPos.y, 0],
70961
+ at: [rotatedPos.x, rotatedPos.y, rotation],
70829
70962
  size: padSize,
70830
70963
  layers: [
70831
70964
  `${padLayer}`,
@@ -70845,15 +70978,27 @@ function createSmdPadFromCircuitJson({
70845
70978
  }
70846
70979
  return pad;
70847
70980
  }
70848
- function convertSmdPads(pcbPads, componentCenter, componentRotation, componentId, startPadNumber, getNetInfo) {
70981
+ function convertSmdPads({
70982
+ pcbPads,
70983
+ componentCenter,
70984
+ componentRotation,
70985
+ componentId,
70986
+ startPadNumber,
70987
+ getNetInfo
70988
+ }, ctx) {
70849
70989
  const pads = [];
70850
70990
  let padNumber = startPadNumber;
70851
70991
  for (const pcbPad of pcbPads) {
70852
70992
  const netInfo = getNetInfo(pcbPad.pcb_port_id);
70993
+ const pcbPort = pcbPad.pcb_port_id ? ctx.db.pcb_port?.get(pcbPad.pcb_port_id) : undefined;
70994
+ const sourcePort = pcbPort?.source_port_id ? ctx.db.source_port?.get(pcbPort.source_port_id) : undefined;
70995
+ const pinHint = pcbPad.port_hints?.find((h) => /^pin[A-Za-z0-9_]+$/i.test(h));
70996
+ const gridHint = pcbPad.port_hints?.find((h) => /^[A-Za-z]?\d+[A-Za-z0-9_]*$/.test(h));
70997
+ const resolvedPadNumber = sourcePort?.pin_number != null ? String(sourcePort.pin_number) : pinHint ? pinHint.replace(/^pin/i, "") : gridHint ?? String(padNumber);
70853
70998
  const pad = createSmdPadFromCircuitJson({
70854
70999
  pcbPad,
70855
71000
  componentCenter,
70856
- padNumber,
71001
+ padNumber: resolvedPadNumber,
70857
71002
  componentRotation,
70858
71003
  netInfo,
70859
71004
  componentId
@@ -70876,8 +71021,8 @@ function createThruHolePadFromCircuitJson({
70876
71021
  }
70877
71022
  const relativeX = platedHole.x - componentCenter.x;
70878
71023
  const relativeY = -(platedHole.y - componentCenter.y);
70879
- const rotationMatrix = componentRotation !== 0 ? rotate5(componentRotation * Math.PI / 180) : identity3();
70880
- const rotatedPos = applyToPoint12(rotationMatrix, {
71024
+ const rotationMatrix = componentRotation !== 0 ? rotate6(componentRotation * Math.PI / 180) : identity4();
71025
+ const rotatedPos = applyToPoint13(rotationMatrix, {
70881
71026
  x: relativeX,
70882
71027
  y: relativeY
70883
71028
  });
@@ -70893,7 +71038,7 @@ function createThruHolePadFromCircuitJson({
70893
71038
  y: platedHole.hole_offset_y ?? 0
70894
71039
  };
70895
71040
  if (rawOffset.x !== 0 || rawOffset.y !== 0) {
70896
- const rotatedOffset = applyToPoint12(rotationMatrix, {
71041
+ const rotatedOffset = applyToPoint13(rotationMatrix, {
70897
71042
  x: -rawOffset.x,
70898
71043
  y: rawOffset.y
70899
71044
  });
@@ -70909,10 +71054,7 @@ function createThruHolePadFromCircuitJson({
70909
71054
  });
70910
71055
  } else if (platedHole.shape === "pill" || platedHole.shape === "oval") {
70911
71056
  padShape = "oval";
70912
- padSize = [
70913
- platedHole.outer_width,
70914
- platedHole.outer_height
70915
- ];
71057
+ padSize = [platedHole.outer_width, platedHole.outer_height];
70916
71058
  drill = new PadDrill({
70917
71059
  oval: true,
70918
71060
  diameter: platedHole.hole_width,
@@ -70921,10 +71063,7 @@ function createThruHolePadFromCircuitJson({
70921
71063
  });
70922
71064
  } else if (platedHole.shape === "pill_hole_with_rect_pad") {
70923
71065
  padShape = "rect";
70924
- padSize = [
70925
- platedHole.rect_pad_width,
70926
- platedHole.rect_pad_height
70927
- ];
71066
+ padSize = [platedHole.rect_pad_width, platedHole.rect_pad_height];
70928
71067
  drill = new PadDrill({
70929
71068
  oval: true,
70930
71069
  diameter: platedHole.hole_width,
@@ -70933,20 +71072,15 @@ function createThruHolePadFromCircuitJson({
70933
71072
  });
70934
71073
  } else if (platedHole.shape === "circular_hole_with_rect_pad") {
70935
71074
  padShape = "rect";
70936
- padSize = [
70937
- platedHole.rect_pad_width,
70938
- platedHole.rect_pad_height
70939
- ];
71075
+ padSize = [platedHole.rect_pad_width, platedHole.rect_pad_height];
70940
71076
  drill = new PadDrill({
70941
71077
  diameter: platedHole.hole_diameter,
70942
71078
  offset: drillOffset
70943
71079
  });
71080
+ rotation = platedHole.rect_ccw_rotation || 0;
70944
71081
  } else if (platedHole.shape === "rotated_pill_hole_with_rect_pad") {
70945
71082
  padShape = "rect";
70946
- padSize = [
70947
- platedHole.rect_pad_width,
70948
- platedHole.rect_pad_height
70949
- ];
71083
+ padSize = [platedHole.rect_pad_width, platedHole.rect_pad_height];
70950
71084
  drill = new PadDrill({
70951
71085
  oval: true,
70952
71086
  diameter: platedHole.hole_width,
@@ -70976,15 +71110,27 @@ function createThruHolePadFromCircuitJson({
70976
71110
  }
70977
71111
  return pad;
70978
71112
  }
70979
- function convertPlatedHoles(platedHoles, componentCenter, componentRotation, componentId, startPadNumber, getNetInfo) {
71113
+ function convertPlatedHoles({
71114
+ platedHoles,
71115
+ componentCenter,
71116
+ componentRotation,
71117
+ componentId,
71118
+ startPadNumber,
71119
+ getNetInfo
71120
+ }, ctx) {
70980
71121
  const pads = [];
70981
71122
  let padNumber = startPadNumber;
70982
71123
  for (const platedHole of platedHoles) {
70983
71124
  const netInfo = getNetInfo(platedHole.pcb_port_id);
71125
+ const pcbPort = platedHole.pcb_port_id ? ctx.db.pcb_port?.get(platedHole.pcb_port_id) : undefined;
71126
+ const sourcePort = pcbPort?.source_port_id ? ctx.db.source_port?.get(pcbPort.source_port_id) : undefined;
71127
+ const pinHint = platedHole.port_hints?.find((h) => /^pin[A-Za-z0-9_]+$/i.test(h));
71128
+ const gridHint = platedHole.port_hints?.find((h) => /^[A-Za-z]?\d+[A-Za-z0-9_]*$/.test(h));
71129
+ const resolvedPadNumber = sourcePort?.pin_number != null ? String(sourcePort.pin_number) : pinHint ? pinHint.replace(/^pin/i, "") : gridHint ?? String(padNumber);
70984
71130
  const pad = createThruHolePadFromCircuitJson({
70985
71131
  platedHole,
70986
71132
  componentCenter,
70987
- padNumber,
71133
+ padNumber: resolvedPadNumber,
70988
71134
  componentRotation,
70989
71135
  netInfo,
70990
71136
  componentId
@@ -71006,8 +71152,8 @@ function createNpthPadFromCircuitJson({
71006
71152
  }
71007
71153
  const relativeX = pcbHole.x - componentCenter.x;
71008
71154
  const relativeY = -(pcbHole.y - componentCenter.y);
71009
- const rotationMatrix = componentRotation !== 0 ? rotate6(componentRotation * Math.PI / 180) : identity4();
71010
- const rotatedPos = applyToPoint13(rotationMatrix, {
71155
+ const rotationMatrix = componentRotation !== 0 ? rotate7(componentRotation * Math.PI / 180) : identity5();
71156
+ const rotatedPos = applyToPoint14(rotationMatrix, {
71011
71157
  x: relativeX,
71012
71158
  y: relativeY
71013
71159
  });
@@ -71121,7 +71267,7 @@ var AddFootprintsStage = class extends ConverterStage {
71121
71267
  const sourceComponent = component.source_component_id ? this.ctx.db.source_component.get(component.source_component_id) : null;
71122
71268
  const cadComponent = this.getCadComponentForPcbComponent(component.pcb_component_id);
71123
71269
  const footprintName = sourceComponent ? getKicadCompatibleComponentName(sourceComponent, cadComponent) : "Unknown";
71124
- const transformedPos = applyToPoint14(c2kMatPcb, {
71270
+ const transformedPos = applyToPoint15(c2kMatPcb, {
71125
71271
  x: component.center.x,
71126
71272
  y: component.center.y
71127
71273
  });
@@ -71138,13 +71284,34 @@ var AddFootprintsStage = class extends ConverterStage {
71138
71284
  const pcbNoteTexts = this.ctx.db.pcb_note_text?.list().filter((text) => text.pcb_component_id === component.pcb_component_id) || [];
71139
71285
  fpTexts.push(...convertNoteTexts(pcbNoteTexts, component.center, component.rotation || 0));
71140
71286
  footprint.fpTexts = fpTexts;
71287
+ const pcbSilkscreenPaths = this.ctx.db.pcb_silkscreen_path?.list().filter((path7) => path7.pcb_component_id === component.pcb_component_id) || [];
71288
+ const fpLines = footprint.fpLines ?? [];
71289
+ fpLines.push(...convertSilkscreenPaths(pcbSilkscreenPaths, {
71290
+ componentCenter: component.center,
71291
+ componentRotation: component.rotation || 0
71292
+ }));
71293
+ footprint.fpLines = fpLines;
71141
71294
  const fpPads = footprint.fpPads;
71142
71295
  const getNetInfo = (pcbPortId) => this.getNetInfoForPcbPort(pcbPortId);
71143
71296
  const pcbPads = this.ctx.db.pcb_smtpad?.list().filter((pad) => pad.pcb_component_id === component.pcb_component_id) || [];
71144
- const { pads: smdPads, nextPadNumber } = convertSmdPads(pcbPads, component.center, component.rotation || 0, component.pcb_component_id, 1, getNetInfo);
71297
+ const { pads: smdPads, nextPadNumber } = convertSmdPads({
71298
+ pcbPads,
71299
+ componentCenter: component.center,
71300
+ componentRotation: component.rotation || 0,
71301
+ componentId: component.pcb_component_id,
71302
+ startPadNumber: 1,
71303
+ getNetInfo
71304
+ }, this.ctx);
71145
71305
  fpPads.push(...smdPads);
71146
71306
  const pcbPlatedHoles = this.ctx.db.pcb_plated_hole?.list().filter((hole) => hole.pcb_component_id === component.pcb_component_id) || [];
71147
- const { pads: thruHolePads } = convertPlatedHoles(pcbPlatedHoles, component.center, component.rotation || 0, component.pcb_component_id, nextPadNumber, getNetInfo);
71307
+ const { pads: thruHolePads } = convertPlatedHoles({
71308
+ platedHoles: pcbPlatedHoles,
71309
+ componentCenter: component.center,
71310
+ componentRotation: component.rotation || 0,
71311
+ componentId: component.pcb_component_id,
71312
+ startPadNumber: nextPadNumber,
71313
+ getNetInfo
71314
+ }, this.ctx);
71148
71315
  fpPads.push(...thruHolePads);
71149
71316
  const pcbHoles = this.ctx.db.pcb_hole?.list().filter((hole) => hole.pcb_component_id === component.pcb_component_id) || [];
71150
71317
  const npthPads = convertNpthHoles(pcbHoles, component.center, component.rotation || 0);
@@ -71278,11 +71445,11 @@ var AddTracesStage = class extends ConverterStage {
71278
71445
  for (let i = 0;i < trace.route.length - 1; i++) {
71279
71446
  const startPoint = trace.route[i];
71280
71447
  const endPoint = trace.route[i + 1];
71281
- const transformedStart = applyToPoint15(c2kMatPcb, {
71448
+ const transformedStart = applyToPoint16(c2kMatPcb, {
71282
71449
  x: startPoint.x,
71283
71450
  y: startPoint.y
71284
71451
  });
71285
- const transformedEnd = applyToPoint15(c2kMatPcb, {
71452
+ const transformedEnd = applyToPoint16(c2kMatPcb, {
71286
71453
  x: endPoint.x,
71287
71454
  y: endPoint.y
71288
71455
  });
@@ -71405,7 +71572,7 @@ var AddViasStage = class extends ConverterStage {
71405
71572
  this.finished = true;
71406
71573
  return;
71407
71574
  }
71408
- const transformedPos = applyToPoint16(c2kMatPcb, {
71575
+ const transformedPos = applyToPoint17(c2kMatPcb, {
71409
71576
  x: via.x,
71410
71577
  y: via.y
71411
71578
  });
@@ -71499,7 +71666,7 @@ var AddStandalonePcbElements = class extends ConverterStage {
71499
71666
  if (elm.type === "pcb_hole") {
71500
71667
  const hole = elm;
71501
71668
  const footprintSeed = `standalone_hole:${hole.pcb_hole_id}:${hole.x},${hole.y}`;
71502
- const kicadPos = applyToPoint17(c2kMatPcb, { x: hole.x, y: hole.y });
71669
+ const kicadPos = applyToPoint18(c2kMatPcb, { x: hole.x, y: hole.y });
71503
71670
  const libraryLink = this.getHoleLibraryLink(hole);
71504
71671
  const footprint = new Footprint4({
71505
71672
  libraryLink,
@@ -71518,7 +71685,7 @@ var AddStandalonePcbElements = class extends ConverterStage {
71518
71685
  } else if (elm.type === "pcb_plated_hole") {
71519
71686
  const hole = elm;
71520
71687
  const footprintSeed = `standalone_plated_hole:${hole.pcb_plated_hole_id}:${hole.x},${hole.y}`;
71521
- const kicadPos = applyToPoint17(c2kMatPcb, { x: hole.x, y: hole.y });
71688
+ const kicadPos = applyToPoint18(c2kMatPcb, { x: hole.x, y: hole.y });
71522
71689
  const libraryLink = this.getPlatedHoleLibraryLink(hole);
71523
71690
  const footprint = new Footprint4({
71524
71691
  libraryLink,
@@ -71569,7 +71736,19 @@ var AddStandalonePcbElements = class extends ConverterStage {
71569
71736
  }
71570
71737
  if (shape === "circular_hole_with_rect_pad") {
71571
71738
  const h = hole;
71572
- return `tscircuit:platedhole_${shape}_holeDiameter${h.hole_diameter}mm_rectPadWidth${h.rect_pad_width}mm_rectPadHeight${h.rect_pad_height}mm`;
71739
+ let link = `tscircuit:platedhole_${shape}_holeDiameter${h.hole_diameter}mm_rectPadWidth${h.rect_pad_width}mm_rectPadHeight${h.rect_pad_height}mm`;
71740
+ if (h.rect_ccw_rotation) {
71741
+ link += `_ccwRotation${h.rect_ccw_rotation}deg`;
71742
+ }
71743
+ return link;
71744
+ }
71745
+ if (shape === "rotated_pill_hole_with_rect_pad") {
71746
+ const h = hole;
71747
+ let link = `tscircuit:platedhole_${shape}_holeWidth${h.hole_width}mm_holeHeight${h.hole_height}mm_rectPadWidth${h.rect_pad_width}mm_rectPadHeight${h.rect_pad_height}mm`;
71748
+ if (h.rect_ccw_rotation) {
71749
+ link += `_ccwRotation${h.rect_ccw_rotation}deg`;
71750
+ }
71751
+ return link;
71573
71752
  }
71574
71753
  return "tscircuit:platedhole";
71575
71754
  }
@@ -71584,7 +71763,7 @@ function createFabricationNoteTextFromCircuitJson({
71584
71763
  if (!textElement.text || !textElement.anchor_position) {
71585
71764
  return null;
71586
71765
  }
71587
- const transformedPos = applyToPoint18(c2kMatPcb, {
71766
+ const transformedPos = applyToPoint19(c2kMatPcb, {
71588
71767
  x: textElement.anchor_position.x,
71589
71768
  y: textElement.anchor_position.y
71590
71769
  });
@@ -71640,7 +71819,7 @@ function createGrTextFromCircuitJson({
71640
71819
  if (!textElement.text || !textElement.anchor_position) {
71641
71820
  return null;
71642
71821
  }
71643
- const transformedPos = applyToPoint19(c2kMatPcb, {
71822
+ const transformedPos = applyToPoint20(c2kMatPcb, {
71644
71823
  x: textElement.anchor_position.x,
71645
71824
  y: textElement.anchor_position.y
71646
71825
  });
@@ -71690,6 +71869,20 @@ function createGrTextFromCircuitJson({
71690
71869
  grText.position = position;
71691
71870
  return grText;
71692
71871
  }
71872
+ var pointsAreEqual = (a, b) => !!a && !!b && a.x === b.x && a.y === b.y;
71873
+ var normalizeOutlineCorners = (corners) => {
71874
+ const dedupedCorners = [];
71875
+ for (const corner of corners) {
71876
+ const previousCorner = dedupedCorners[dedupedCorners.length - 1];
71877
+ if (pointsAreEqual(previousCorner, corner))
71878
+ continue;
71879
+ dedupedCorners.push(corner);
71880
+ }
71881
+ while (dedupedCorners.length > 1 && pointsAreEqual(dedupedCorners[0], dedupedCorners[dedupedCorners.length - 1])) {
71882
+ dedupedCorners.pop();
71883
+ }
71884
+ return dedupedCorners;
71885
+ };
71693
71886
  var AddGraphicsStage = class extends ConverterStage {
71694
71887
  _step() {
71695
71888
  const { kicadPcb, c2kMatPcb } = this.ctx;
@@ -71699,7 +71892,7 @@ var AddGraphicsStage = class extends ConverterStage {
71699
71892
  if (!c2kMatPcb) {
71700
71893
  throw new Error("PCB transformation matrix not initialized in context");
71701
71894
  }
71702
- const pcbSilkscreenPaths = this.ctx.db.pcb_silkscreen_path?.list() || [];
71895
+ const pcbSilkscreenPaths = this.ctx.db.pcb_silkscreen_path?.list().filter((path7) => !path7.pcb_component_id) || [];
71703
71896
  for (const path7 of pcbSilkscreenPaths) {
71704
71897
  if (!path7.route || path7.route.length < 2)
71705
71898
  continue;
@@ -71708,11 +71901,11 @@ var AddGraphicsStage = class extends ConverterStage {
71708
71901
  const endPoint = path7.route[i + 1];
71709
71902
  if (!startPoint || !endPoint)
71710
71903
  continue;
71711
- const transformedStart = applyToPoint20(c2kMatPcb, {
71904
+ const transformedStart = applyToPoint21(c2kMatPcb, {
71712
71905
  x: startPoint.x,
71713
71906
  y: startPoint.y
71714
71907
  });
71715
- const transformedEnd = applyToPoint20(c2kMatPcb, {
71908
+ const transformedEnd = applyToPoint21(c2kMatPcb, {
71716
71909
  x: endPoint.x,
71717
71910
  y: endPoint.y
71718
71911
  });
@@ -71765,7 +71958,7 @@ var AddGraphicsStage = class extends ConverterStage {
71765
71958
  }
71766
71959
  let corners;
71767
71960
  if (board.outline && board.outline.length > 0) {
71768
- corners = board.outline;
71961
+ corners = normalizeOutlineCorners(board.outline);
71769
71962
  } else {
71770
71963
  const halfWidth = board.width ? board.width / 2 : 0;
71771
71964
  const halfHeight = board.height ? board.height / 2 : 0;
@@ -71776,12 +71969,18 @@ var AddGraphicsStage = class extends ConverterStage {
71776
71969
  { x: board.center.x - halfWidth, y: board.center.y + halfHeight }
71777
71970
  ];
71778
71971
  }
71779
- const transformedCorners = corners.map((corner) => applyToPoint20(c2kMatPcb, corner));
71972
+ const transformedCorners = corners.map((corner) => applyToPoint21(c2kMatPcb, corner));
71973
+ if (transformedCorners.length < 2) {
71974
+ this.finished = true;
71975
+ return;
71976
+ }
71780
71977
  for (let i = 0;i < transformedCorners.length; i++) {
71781
71978
  const start = transformedCorners[i];
71782
71979
  const end = transformedCorners[(i + 1) % transformedCorners.length];
71783
71980
  if (!start || !end)
71784
71981
  continue;
71982
+ if (pointsAreEqual(start, end))
71983
+ continue;
71785
71984
  const edgeLine = new GrLine({
71786
71985
  start: { x: start.x, y: start.y },
71787
71986
  end: { x: end.x, y: end.y },