altium-to-circuit-json 0.0.7 → 0.0.8

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/README.md CHANGED
@@ -53,7 +53,8 @@ PCB conversion currently emits:
53
53
 
54
54
  Schematic conversion currently emits:
55
55
 
56
- - sheet identity and border geometry;
56
+ - a Circuit JSON `schematic_sheet`, with imported geometry page-fitted and
57
+ centered inside its standard A4 drawing area;
57
58
  - typed source components, source ports, source nets, and source traces;
58
59
  - standard Circuit JSON resistor, capacitor, inductor, diode, LED, test-point,
59
60
  power, and ground symbols;
@@ -67,6 +68,12 @@ Schematic conversion currently emits:
67
68
  - active multipart/display-mode filtering, with multiple placed symbol parts
68
69
  sharing one physical source component.
69
70
 
71
+ By default, schematic coordinates are scaled from the Altium page dimensions
72
+ and centered on the emitted `schematic_sheet`. Set `schematicUnitScale` to use
73
+ an explicit coordinate scale, or `centerOnSchematicSheet: false` to preserve an
74
+ Altium-style origin. The old plain rectangular page outline remains available
75
+ as an opt-in compatibility overlay with `includeSheetBorder: true`.
76
+
70
77
  The package is intentionally an incremental converter. Complete component
71
78
  classification, copper pours/regions, mechanical/dimension primitives, models,
72
79
  and project-level hierarchy remain follow-up areas.
package/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@ interface ConvertAltiumPcbDocOptions {
12
12
  declare function convertAltiumPcbDocToCircuitJson(document: AltiumPcbDocument, options?: ConvertAltiumPcbDocOptions): AnyCircuitElement[];
13
13
 
14
14
  interface ConvertAltiumSchDocOptions {
15
+ centerOnSchematicSheet?: boolean;
15
16
  includeHidden?: boolean;
16
17
  includeSheetBorder?: boolean;
17
18
  includeText?: boolean;
package/dist/index.js CHANGED
@@ -1780,25 +1780,32 @@ function isPowerNet(name) {
1780
1780
  }
1781
1781
 
1782
1782
  // lib/convert-altium-sch-doc-to-circuit-json.ts
1783
- var DEFAULT_SCHEMATIC_UNIT_SCALE = 0.1;
1784
1783
  var SCHEMATIC_SHEET_ID = "schematic_sheet_altium";
1784
+ var SCHEMATIC_UNIT_TO_MILLIMETERS = 10.16 / 1.1;
1785
+ var SCHEMATIC_SHEET_INSET = 5 / SCHEMATIC_UNIT_TO_MILLIMETERS;
1786
+ var SCHEMATIC_SHEET_WIDTH = 297 / SCHEMATIC_UNIT_TO_MILLIMETERS;
1787
+ var SCHEMATIC_SHEET_HEIGHT = 210 / SCHEMATIC_UNIT_TO_MILLIMETERS;
1788
+ var SCHEMATIC_SHEET_INNER_WIDTH = SCHEMATIC_SHEET_WIDTH - SCHEMATIC_SHEET_INSET * 2;
1789
+ var SCHEMATIC_SHEET_INNER_HEIGHT = SCHEMATIC_SHEET_HEIGHT - SCHEMATIC_SHEET_INSET * 2;
1785
1790
  function convertAltiumSchDocToCircuitJson(document, options = {}) {
1786
- const scale = options.schematicUnitScale ?? DEFAULT_SCHEMATIC_UNIT_SCALE;
1791
+ const records = document.records;
1792
+ const sheetRecord = records.find((record) => record.recordKind === "31");
1793
+ const sheetDimensions = getAltiumSheetDimensions(sheetRecord);
1794
+ const scale = options.schematicUnitScale ?? getPageFitScale(sheetDimensions);
1787
1795
  if (!Number.isFinite(scale) || scale <= 0) {
1788
1796
  throw new RangeError("schematicUnitScale must be a positive finite number");
1789
1797
  }
1790
- const records = document.records;
1791
- const sheetRecord = records.find((record) => record.recordKind === "31");
1792
1798
  const context = { document, records, scale, sheetRecord };
1793
1799
  const elements = [
1794
1800
  {
1795
1801
  type: "schematic_sheet",
1796
1802
  schematic_sheet_id: SCHEMATIC_SHEET_ID,
1797
1803
  name: options.sheetName ?? "Altium schematic",
1804
+ outline_color: "#334155",
1798
1805
  sheet_index: 0
1799
1806
  }
1800
1807
  ];
1801
- if (options.includeSheetBorder !== false) {
1808
+ if (options.includeSheetBorder === true) {
1802
1809
  elements.push(createSheetBorder(sheetRecord, scale));
1803
1810
  }
1804
1811
  const semanticConversion = convertSemanticSchematic(document, {
@@ -1814,7 +1821,78 @@ function convertAltiumSchDocToCircuitJson(document, options = {}) {
1814
1821
  const converted = convertSchematicRecord(record, index, context, options);
1815
1822
  elements.push(...converted);
1816
1823
  }
1817
- return elements;
1824
+ if (options.centerOnSchematicSheet === false) return elements;
1825
+ const offset = {
1826
+ x: -sheetDimensions.width * scale / 2,
1827
+ y: -sheetDimensions.height * scale / 2
1828
+ };
1829
+ return elements.map((element) => translateSchematicElement(element, offset));
1830
+ }
1831
+ function getAltiumSheetDimensions(sheetRecord) {
1832
+ return {
1833
+ width: getPositiveNumber(sheetRecord?.getCaseInsensitive("CUSTOMX"), 1e3),
1834
+ height: getPositiveNumber(sheetRecord?.getCaseInsensitive("CUSTOMY"), 800)
1835
+ };
1836
+ }
1837
+ function getPositiveNumber(value, fallback) {
1838
+ const parsed = Number(value);
1839
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
1840
+ }
1841
+ function getPageFitScale(sheetDimensions) {
1842
+ return Math.min(
1843
+ SCHEMATIC_SHEET_INNER_WIDTH / sheetDimensions.width,
1844
+ SCHEMATIC_SHEET_INNER_HEIGHT / sheetDimensions.height
1845
+ );
1846
+ }
1847
+ function translatePoint(point, offset) {
1848
+ return { x: point.x + offset.x, y: point.y + offset.y };
1849
+ }
1850
+ function translateSchematicElement(element, offset) {
1851
+ switch (element.type) {
1852
+ case "schematic_component":
1853
+ case "schematic_port":
1854
+ case "schematic_rect":
1855
+ case "schematic_circle":
1856
+ case "schematic_arc":
1857
+ return { ...element, center: translatePoint(element.center, offset) };
1858
+ case "schematic_net_label":
1859
+ return {
1860
+ ...element,
1861
+ center: translatePoint(element.center, offset),
1862
+ ...element.anchor_position ? {
1863
+ anchor_position: translatePoint(element.anchor_position, offset)
1864
+ } : {}
1865
+ };
1866
+ case "schematic_text":
1867
+ return { ...element, position: translatePoint(element.position, offset) };
1868
+ case "schematic_path":
1869
+ return {
1870
+ ...element,
1871
+ points: element.points.map((point) => translatePoint(point, offset))
1872
+ };
1873
+ case "schematic_line":
1874
+ return {
1875
+ ...element,
1876
+ x1: element.x1 + offset.x,
1877
+ x2: element.x2 + offset.x,
1878
+ y1: element.y1 + offset.y,
1879
+ y2: element.y2 + offset.y
1880
+ };
1881
+ case "schematic_trace":
1882
+ return {
1883
+ ...element,
1884
+ edges: element.edges.map((edge) => ({
1885
+ ...edge,
1886
+ from: translatePoint(edge.from, offset),
1887
+ to: translatePoint(edge.to, offset)
1888
+ })),
1889
+ junctions: element.junctions.map(
1890
+ (junction) => translatePoint(junction, offset)
1891
+ )
1892
+ };
1893
+ default:
1894
+ return element;
1895
+ }
1818
1896
  }
1819
1897
  function convertSchematicRecord(record, index, context, options) {
1820
1898
  const kind = record.recordKind;
@@ -1989,14 +2067,15 @@ function convertSchematicRecord(record, index, context, options) {
1989
2067
  if (kind === "22") {
1990
2068
  const location = getLocation2(record);
1991
2069
  if (!location) return [];
1992
- const radius = 0.4 / scale;
2070
+ const radius = 4;
2071
+ const noErcStrokeWidth = Math.max(scale, 0.02);
1993
2072
  return [
1994
2073
  createLine(
1995
2074
  index,
1996
2075
  { x: location.x - radius, y: location.y - radius },
1997
2076
  { x: location.x + radius, y: location.y + radius },
1998
2077
  color,
1999
- 0.1,
2078
+ noErcStrokeWidth,
2000
2079
  scale,
2001
2080
  "a"
2002
2081
  ),
@@ -2005,7 +2084,7 @@ function convertSchematicRecord(record, index, context, options) {
2005
2084
  { x: location.x + radius, y: location.y - radius },
2006
2085
  { x: location.x - radius, y: location.y + radius },
2007
2086
  color,
2008
- 0.1,
2087
+ noErcStrokeWidth,
2009
2088
  scale,
2010
2089
  "b"
2011
2090
  )
@@ -2396,14 +2475,7 @@ function convertPort(record, index, context, options, color) {
2396
2475
  return elements;
2397
2476
  }
2398
2477
  function createSheetBorder(sheetRecord, scale) {
2399
- const width = Math.max(
2400
- Number(sheetRecord?.getCaseInsensitive("CUSTOMX") ?? 1e3),
2401
- 1
2402
- );
2403
- const height = Math.max(
2404
- Number(sheetRecord?.getCaseInsensitive("CUSTOMY") ?? 800),
2405
- 1
2406
- );
2478
+ const { height, width } = getAltiumSheetDimensions(sheetRecord);
2407
2479
  return {
2408
2480
  type: "schematic_rect",
2409
2481
  schematic_rect_id: "schematic_rect_altium_sheet_border",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../lib/convert-altium-pcb-doc-to-circuit-json.ts","../lib/convert-altium-sch-doc-to-circuit-json.ts","../lib/schematic/convert-semantic-schematic.ts","../lib/convert-altium-to-circuit-json.ts"],"sourcesContent":["import {\n AltiumArcRecord,\n AltiumFillRecord,\n AltiumPadRecord,\n type AltiumPcbDocument,\n type AltiumPoint,\n type AltiumRecord,\n AltiumTextRecord,\n AltiumTrackRecord,\n AltiumViaRecord,\n getAltiumBounds,\n getPcbLayerStack,\n parseAltiumMeasurementToMils,\n} from \"altiumts\"\nimport type {\n AnyCircuitElement,\n LayerRef,\n PcbBoard,\n PcbComponent,\n PcbCutout,\n PcbHole,\n PcbPlatedHole,\n PcbSilkscreenLine,\n PcbSilkscreenPath,\n PcbSilkscreenRect,\n PcbSilkscreenText,\n PcbSmtPad,\n PcbTrace,\n PcbVia,\n} from \"circuit-json\"\n\nconst MILS_TO_MILLIMETERS = 0.0254\nconst BOARD_ID = \"pcb_board_altium\"\nconst BOARD_GRAPHICS_COMPONENT_ID = \"pcb_component_altium_board_graphics\"\n\nexport interface ConvertAltiumPcbDocOptions {\n includeBoardOutline?: boolean\n includeComponents?: boolean\n includePads?: boolean\n includeSilkscreen?: boolean\n includeTraces?: boolean\n includeVias?: boolean\n}\n\nexport function convertAltiumPcbDocToCircuitJson(\n document: AltiumPcbDocument,\n options: ConvertAltiumPcbDocOptions = {},\n): AnyCircuitElement[] {\n const elements: AnyCircuitElement[] = []\n\n if (options.includeBoardOutline !== false) {\n elements.push(createBoard(document))\n for (const [index, cutout] of document.boardGeometry.cutouts.entries()) {\n if (cutout.outline.points.length < 3) continue\n elements.push({\n type: \"pcb_cutout\",\n pcb_cutout_id: `pcb_cutout_altium_${index}`,\n pcb_board_id: BOARD_ID,\n shape: \"polygon\",\n points: cutout.outline.points.map(toMillimeterPoint),\n } satisfies PcbCutout)\n }\n }\n\n if (options.includeComponents !== false) {\n for (const [index, component] of document.components.entries()) {\n const position = component.position\n if (!position) continue\n const bounds = document.getComponentBounds(component)\n elements.push({\n type: \"pcb_component\",\n pcb_component_id: componentId(index),\n source_component_id: `source_component_altium_${index}`,\n center: toMillimeterPoint(position),\n width: milsToMillimeters(\n bounds ? bounds.maxX - bounds.minX : (component.heightMils ?? 20),\n ),\n height: milsToMillimeters(\n bounds ? bounds.maxY - bounds.minY : (component.heightMils ?? 20),\n ),\n layer: component.side === \"bottom\" ? \"bottom\" : \"top\",\n rotation: component.rotation,\n position_mode: \"none\",\n obstructs_within_bounds: false,\n } satisfies PcbComponent)\n }\n }\n\n for (const [index, record] of document.records.entries()) {\n if (record instanceof AltiumPadRecord && options.includePads !== false) {\n const pad = convertPad(record, index)\n if (pad) elements.push(pad)\n continue\n }\n\n if (record instanceof AltiumTrackRecord) {\n if (isOverlayLayer(record.layer)) {\n if (options.includeSilkscreen === false) continue\n const line = convertSilkscreenLine(record, index)\n if (line) elements.push(line)\n } else if (options.includeTraces !== false) {\n const trace = convertTrack(record, index)\n if (trace) elements.push(trace)\n }\n continue\n }\n\n if (record instanceof AltiumViaRecord && options.includeVias !== false) {\n const via = convertVia(record, index)\n if (via) elements.push(via)\n continue\n }\n\n if (\n options.includeSilkscreen === false ||\n !isOverlayLayer(getLayer(record))\n ) {\n continue\n }\n\n if (record instanceof AltiumArcRecord) {\n const path = convertSilkscreenArc(record, index)\n if (path) elements.push(path)\n } else if (record instanceof AltiumFillRecord) {\n const rect = convertSilkscreenFill(record, index)\n if (rect) elements.push(rect)\n } else if (record instanceof AltiumTextRecord) {\n const text = convertSilkscreenText(record, index)\n if (text) elements.push(text)\n }\n }\n\n return elements\n}\n\nfunction createBoard(document: AltiumPcbDocument): PcbBoard {\n const outline = document.boardGeometry.outline.points.map(toMillimeterPoint)\n const bounds =\n getAltiumBounds(document.boardGeometry.outline.points) ??\n getFallbackPcbBounds(document.records)\n const width = Math.max(milsToMillimeters(bounds.maxX - bounds.minX), 0.1)\n const height = Math.max(milsToMillimeters(bounds.maxY - bounds.minY), 0.1)\n const numLayers = document.board\n ? Math.max(\n getPcbLayerStack(document.board).entries.filter((entry) =>\n Boolean(mapCopperLayer(entry.name ?? entry.layerId)),\n ).length,\n 2,\n )\n : 2\n\n return {\n type: \"pcb_board\",\n pcb_board_id: BOARD_ID,\n center: {\n x: milsToMillimeters((bounds.minX + bounds.maxX) / 2),\n y: milsToMillimeters((bounds.minY + bounds.maxY) / 2),\n },\n width,\n height,\n ...(outline.length >= 3 ? { shape: \"polygon\" as const, outline } : {}),\n thickness: 1.6,\n num_layers: numLayers,\n material: \"fr4\",\n }\n}\n\nfunction getFallbackPcbBounds(records: AltiumRecord[]): {\n maxX: number\n maxY: number\n minX: number\n minY: number\n} {\n const points: AltiumPoint[] = []\n for (const record of records) {\n if (\n record instanceof AltiumPadRecord ||\n record instanceof AltiumViaRecord\n ) {\n if (record.position) points.push(record.position)\n } else if (record instanceof AltiumTrackRecord) {\n if (record.start) points.push(record.start)\n if (record.end) points.push(record.end)\n }\n }\n return getAltiumBounds(points) ?? { minX: 0, minY: 0, maxX: 1000, maxY: 800 }\n}\n\nfunction convertTrack(\n record: AltiumTrackRecord,\n index: number,\n): PcbTrace | undefined {\n const start = record.start\n const end = record.end\n const layer = mapCopperLayer(record.layer)\n if (!start || !end || !layer) return undefined\n const width = milsToMillimeters(record.widthMils ?? 4)\n return {\n type: \"pcb_trace\",\n pcb_trace_id: `pcb_trace_altium_${index}`,\n should_round_corners: true,\n route: [\n { route_type: \"wire\", ...toMillimeterPoint(start), width, layer },\n { route_type: \"wire\", ...toMillimeterPoint(end), width, layer },\n ],\n }\n}\n\nfunction convertVia(\n record: AltiumViaRecord,\n index: number,\n): PcbVia | undefined {\n if (!record.position) return undefined\n const startLayer = mapCopperLayer(record.startLayer) ?? \"top\"\n const endLayer = mapCopperLayer(record.endLayer) ?? \"bottom\"\n const layers = startLayer === endLayer ? [startLayer] : [startLayer, endLayer]\n const outerDiameter = milsToMillimeters(record.diameterMils ?? 20)\n return {\n type: \"pcb_via\",\n pcb_via_id: `pcb_via_altium_${index}`,\n ...toMillimeterPoint(record.position),\n outer_diameter: outerDiameter,\n hole_diameter: milsToMillimeters(\n record.holeSizeMils ?? (record.diameterMils ?? 20) * 0.45,\n ),\n layers,\n is_tented: record.tentedTop === true && record.tentedBottom === true,\n }\n}\n\nfunction convertPad(\n record: AltiumPadRecord,\n index: number,\n): PcbSmtPad | PcbPlatedHole | PcbHole | undefined {\n const position = record.position\n const size = record.size\n if (!position || !size) return undefined\n const x = milsToMillimeters(position.x)\n const y = milsToMillimeters(position.y)\n const width = milsToMillimeters(size.width)\n const height = milsToMillimeters(size.height)\n const holeDiameter = milsToMillimeters(record.holeSizeMils ?? 0)\n const shape = normalizeShape(record.shape)\n const id = `altium_${index}`\n\n if (record.plated === false && holeDiameter > 0) {\n return {\n type: \"pcb_hole\",\n pcb_hole_id: `pcb_hole_${id}`,\n hole_shape: \"circle\",\n hole_diameter: holeDiameter,\n x,\n y,\n }\n }\n\n if (record.behavior === \"through-hole\" || holeDiameter > 0) {\n const slotLengthMils = getMeasurement(record, \"SLOTLENGTH\")\n const holeWidthMils = record.holeWidthMils ?? record.holeSizeMils\n const isSlot =\n normalizeShape(record.holeType).includes(\"SLOT\") ||\n (slotLengthMils ?? 0) > (record.holeSizeMils ?? 0) ||\n (holeWidthMils ?? 0) > (record.holeSizeMils ?? 0)\n const layers: LayerRef[] = [\"top\", \"bottom\"]\n\n if (isSlot) {\n const holeWidth = milsToMillimeters(\n Math.max(\n slotLengthMils ?? holeWidthMils ?? record.holeSizeMils ?? 1,\n 1,\n ),\n )\n const holeHeight = Math.max(holeDiameter, MILS_TO_MILLIMETERS)\n if (isRectangularShape(shape)) {\n const rotated = record.holeRotation !== 0 || record.rotation !== 0\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: rotated\n ? \"rotated_pill_hole_with_rect_pad\"\n : \"pill_hole_with_rect_pad\",\n hole_shape: rotated ? \"rotated_pill\" : \"pill\",\n pad_shape: \"rect\",\n hole_width: holeWidth,\n hole_height: holeHeight,\n ...(rotated ? { hole_ccw_rotation: record.holeRotation } : {}),\n rect_pad_width: width,\n rect_pad_height: height,\n ...(rotated ? { rect_ccw_rotation: record.rotation } : {}),\n hole_offset_x: 0,\n hole_offset_y: 0,\n x,\n y,\n layers,\n } as PcbPlatedHole\n }\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"pill\",\n outer_width: width,\n outer_height: height,\n hole_width: holeWidth,\n hole_height: holeHeight,\n ccw_rotation: record.holeRotation || record.rotation,\n x,\n y,\n layers,\n }\n }\n\n if (isRectangularShape(shape)) {\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"circular_hole_with_rect_pad\",\n hole_shape: \"circle\",\n pad_shape: \"rect\",\n hole_diameter: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n rect_pad_width: width,\n rect_pad_height: height,\n rect_border_radius: shape.includes(\"ROUNDRECT\")\n ? Math.min(width, height) * 0.18\n : 0,\n rect_ccw_rotation: record.rotation,\n hole_offset_x: 0,\n hole_offset_y: 0,\n x,\n y,\n layers,\n }\n }\n\n if (shape.includes(\"OCTAGON\")) {\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"hole_with_polygon_pad\",\n hole_shape: \"circle\",\n hole_diameter: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n pad_outline: createOctagonPoints(x, y, width, height, record.rotation),\n hole_offset_x: 0,\n hole_offset_y: 0,\n x,\n y,\n layers,\n }\n }\n\n if (shape === \"ROUND\" || shape === \"CIRCLE\" || shape === \"OVAL\") {\n if (Math.abs(width - height) >= 0.0001) {\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"pill\",\n outer_width: width,\n outer_height: height,\n hole_width: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n hole_height: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n ccw_rotation: record.rotation,\n x,\n y,\n layers,\n }\n }\n }\n\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"circle\",\n outer_diameter: Math.max(width, height),\n hole_diameter: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n x,\n y,\n layers,\n }\n }\n\n const layer = mapCopperLayer(record.layer)\n if (!layer) return undefined\n const base = {\n type: \"pcb_smtpad\" as const,\n pcb_smtpad_id: `pcb_smtpad_${id}`,\n x,\n y,\n layer,\n soldermask_margin:\n record.solderMaskExpansionMils === undefined\n ? undefined\n : milsToMillimeters(record.solderMaskExpansionMils),\n }\n\n if (shape.includes(\"OCTAGON\")) {\n return {\n ...base,\n shape: \"polygon\",\n points: createOctagonPoints(x, y, width, height, record.rotation),\n }\n }\n if (shape === \"ROUND\" || shape === \"CIRCLE\" || shape === \"OVAL\") {\n if (Math.abs(width - height) < 0.0001) {\n return { ...base, shape: \"circle\", radius: width / 2 }\n }\n return record.rotation === 0\n ? {\n ...base,\n shape: \"pill\",\n width,\n height,\n radius: Math.min(width, height) / 2,\n }\n : {\n ...base,\n shape: \"rotated_pill\",\n width,\n height,\n radius: Math.min(width, height) / 2,\n ccw_rotation: record.rotation,\n }\n }\n\n const cornerRadius = shape.includes(\"ROUNDRECT\")\n ? Math.min(width, height) * 0.18\n : undefined\n return record.rotation === 0\n ? { ...base, shape: \"rect\", width, height, corner_radius: cornerRadius }\n : {\n ...base,\n shape: \"rotated_rect\",\n width,\n height,\n corner_radius: cornerRadius,\n ccw_rotation: record.rotation,\n }\n}\n\nfunction convertSilkscreenLine(\n record: AltiumTrackRecord,\n index: number,\n): PcbSilkscreenLine | undefined {\n if (!record.start || !record.end) return undefined\n return {\n type: \"pcb_silkscreen_line\",\n pcb_silkscreen_line_id: `pcb_silkscreen_line_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n stroke_width: milsToMillimeters(record.widthMils ?? 4),\n ...withNumberedPoints(record.start, record.end),\n layer: mapOverlayLayer(record.layer),\n }\n}\n\nfunction convertSilkscreenArc(\n record: AltiumArcRecord,\n index: number,\n): PcbSilkscreenPath | undefined {\n if (!record.center || !record.radiusMils) return undefined\n const points = approximateArc(\n record.center,\n record.radiusMils,\n record.startAngle,\n record.endAngle,\n )\n return {\n type: \"pcb_silkscreen_path\",\n pcb_silkscreen_path_id: `pcb_silkscreen_path_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n route: points.map(toMillimeterPoint),\n stroke_width: milsToMillimeters(record.widthMils ?? 4),\n layer: mapOverlayLayer(record.layer),\n }\n}\n\nfunction convertSilkscreenFill(\n record: AltiumFillRecord,\n index: number,\n): PcbSilkscreenRect | undefined {\n if (!record.bounds) return undefined\n const width = milsToMillimeters(record.bounds.maxX - record.bounds.minX)\n const height = milsToMillimeters(record.bounds.maxY - record.bounds.minY)\n return {\n type: \"pcb_silkscreen_rect\",\n pcb_silkscreen_rect_id: `pcb_silkscreen_rect_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n center: {\n x: milsToMillimeters((record.bounds.minX + record.bounds.maxX) / 2),\n y: milsToMillimeters((record.bounds.minY + record.bounds.maxY) / 2),\n },\n width,\n height,\n stroke_width: Math.min(width, height),\n is_filled: true,\n has_stroke: false,\n ccw_rotation: record.rotation,\n layer: mapOverlayLayer(record.layer),\n }\n}\n\nfunction convertSilkscreenText(\n record: AltiumTextRecord,\n index: number,\n): PcbSilkscreenText | undefined {\n const text =\n decodeAltiumWideString(record.getDecoded(\"WIDESTRING\")) ||\n record.getDecoded(\"TEXT\") ||\n record.text\n if (!record.position || !text) return undefined\n return {\n type: \"pcb_silkscreen_text\",\n pcb_silkscreen_text_id: `pcb_silkscreen_text_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n text,\n font: \"tscircuit2024\",\n font_size: milsToMillimeters(record.heightMils ?? 30),\n anchor_position: toMillimeterPoint(record.position),\n anchor_alignment: mapTextAnchor(record.justification),\n ccw_rotation: record.rotation,\n layer: mapOverlayLayer(record.layer),\n is_mirrored: record.mirrored,\n }\n}\n\nfunction decodeAltiumWideString(raw: string | undefined): string {\n if (!raw) return \"\"\n if (!/^\\d+(?:,\\d+)*$/u.test(raw)) return raw\n try {\n return String.fromCodePoint(...raw.split(\",\").map(Number))\n } catch {\n return raw\n }\n}\n\nfunction pcbComponentIdForRecord(record: AltiumRecord): string {\n const index = record.getNumber(\"COMPONENT\")\n return index === undefined || index < 0\n ? BOARD_GRAPHICS_COMPONENT_ID\n : componentId(index)\n}\n\nfunction componentId(index: number): string {\n return `pcb_component_altium_${index}`\n}\n\nfunction mapTextAnchor(\n justification: string | undefined,\n): \"bottom_left\" | \"bottom_center\" | \"bottom_right\" | \"center\" {\n const normalized = justification?.replace(/[\\s_-]+/gu, \"\").toUpperCase()\n if (normalized?.includes(\"CENTER\")) return \"bottom_center\"\n if (normalized?.includes(\"RIGHT\")) return \"bottom_right\"\n if (normalized?.includes(\"LEFT\")) return \"bottom_left\"\n return \"center\"\n}\n\nfunction mapCopperLayer(layer: string | undefined): LayerRef | undefined {\n const normalized = normalizeLayer(layer)\n if (normalized === \"TOP\" || normalized === \"TOPLAYER\") return \"top\"\n if (normalized === \"BOTTOM\" || normalized === \"BOTTOMLAYER\") return \"bottom\"\n const innerMatch = /^(?:MID|MIDLAYER|INTERNALPLANE)(\\d+)$/u.exec(normalized)\n if (!innerMatch?.[1]) return undefined\n const innerNumber = Math.min(Math.max(Number(innerMatch[1]), 1), 8)\n return `inner${innerNumber}` as LayerRef\n}\n\nfunction isOverlayLayer(layer: string | undefined): boolean {\n const normalized = normalizeLayer(layer)\n return normalized === \"TOPOVERLAY\" || normalized === \"BOTTOMOVERLAY\"\n}\n\nfunction mapOverlayLayer(layer: string | undefined): \"top\" | \"bottom\" {\n return normalizeLayer(layer) === \"BOTTOMOVERLAY\" ? \"bottom\" : \"top\"\n}\n\nfunction getLayer(record: AltiumRecord): string | undefined {\n return record.getDecoded(\"LAYER\")\n}\n\nfunction normalizeLayer(layer: string | undefined): string {\n return (layer ?? \"\").replace(/[\\s_.-]+/gu, \"\").toUpperCase()\n}\n\nfunction normalizeShape(shape: string | undefined): string {\n return (shape ?? \"ROUND\").replace(/[\\s_-]+/gu, \"\").toUpperCase()\n}\n\nfunction isRectangularShape(shape: string): boolean {\n return shape.includes(\"RECT\") || shape === \"SQUARE\"\n}\n\nfunction getMeasurement(record: AltiumRecord, key: string): number | undefined {\n return parseAltiumMeasurementToMils(record.getCaseInsensitive(key))\n}\n\nfunction milsToMillimeters(value: number): number {\n return value * MILS_TO_MILLIMETERS\n}\n\nfunction toMillimeterPoint(point: AltiumPoint): { x: number; y: number } {\n return { x: milsToMillimeters(point.x), y: milsToMillimeters(point.y) }\n}\n\nfunction withNumberedPoints(\n start: AltiumPoint,\n end: AltiumPoint,\n): { x1: number; x2: number; y1: number; y2: number } {\n return {\n x1: milsToMillimeters(start.x),\n y1: milsToMillimeters(start.y),\n x2: milsToMillimeters(end.x),\n y2: milsToMillimeters(end.y),\n }\n}\n\nfunction approximateArc(\n center: AltiumPoint,\n radius: number,\n startAngle: number,\n endAngle: number,\n): AltiumPoint[] {\n const sweep = endAngle - startAngle || 360\n const segments = Math.max(8, Math.ceil(Math.abs(sweep) / 7.5))\n return Array.from({ length: segments + 1 }, (_, index) => {\n const angle = startAngle + (sweep * index) / segments\n const radians = (angle * Math.PI) / 180\n return {\n x: center.x + Math.cos(radians) * radius,\n y: center.y + Math.sin(radians) * radius,\n }\n })\n}\n\nfunction createOctagonPoints(\n x: number,\n y: number,\n width: number,\n height: number,\n rotation: number,\n): Array<{ x: number; y: number }> {\n const halfWidth = width / 2\n const halfHeight = height / 2\n const chamfer = Math.min(width, height) / 4\n const points = [\n { x: -halfWidth + chamfer, y: -halfHeight },\n { x: halfWidth - chamfer, y: -halfHeight },\n { x: halfWidth, y: -halfHeight + chamfer },\n { x: halfWidth, y: halfHeight - chamfer },\n { x: halfWidth - chamfer, y: halfHeight },\n { x: -halfWidth + chamfer, y: halfHeight },\n { x: -halfWidth, y: halfHeight - chamfer },\n { x: -halfWidth, y: -halfHeight + chamfer },\n ]\n const radians = (rotation * Math.PI) / 180\n return points.map((point) => ({\n x: x + point.x * Math.cos(radians) - point.y * Math.sin(radians),\n y: y + point.x * Math.sin(radians) + point.y * Math.cos(radians),\n }))\n}\n","import {\n type AltiumPoint,\n type AltiumRecord,\n type AltiumSchDoc,\n getSchematicRecordPoints,\n} from \"altiumts\"\nimport type {\n AnyCircuitElement,\n SchematicArc,\n SchematicCircle,\n SchematicLine,\n SchematicPath,\n SchematicRect,\n SchematicSheet,\n SchematicText,\n SchematicTrace,\n} from \"circuit-json\"\nimport { convertSemanticSchematic } from \"./schematic/convert-semantic-schematic\"\n\nconst DEFAULT_SCHEMATIC_UNIT_SCALE = 0.1\nconst SCHEMATIC_SHEET_ID = \"schematic_sheet_altium\"\n\nexport interface ConvertAltiumSchDocOptions {\n includeHidden?: boolean\n includeSheetBorder?: boolean\n includeText?: boolean\n schematicUnitScale?: number\n sheetName?: string\n}\n\ninterface SchematicContext {\n document: AltiumSchDoc\n records: AltiumRecord[]\n scale: number\n sheetRecord?: AltiumRecord\n}\n\nexport function convertAltiumSchDocToCircuitJson(\n document: AltiumSchDoc,\n options: ConvertAltiumSchDocOptions = {},\n): AnyCircuitElement[] {\n const scale = options.schematicUnitScale ?? DEFAULT_SCHEMATIC_UNIT_SCALE\n if (!Number.isFinite(scale) || scale <= 0) {\n throw new RangeError(\"schematicUnitScale must be a positive finite number\")\n }\n\n const records = document.records\n const sheetRecord = records.find((record) => record.recordKind === \"31\")\n const context: SchematicContext = { document, records, scale, sheetRecord }\n const elements: AnyCircuitElement[] = [\n {\n type: \"schematic_sheet\",\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n name: options.sheetName ?? \"Altium schematic\",\n sheet_index: 0,\n } satisfies SchematicSheet,\n ]\n\n if (options.includeSheetBorder !== false) {\n elements.push(createSheetBorder(sheetRecord, scale))\n }\n\n const semanticConversion = convertSemanticSchematic(document, {\n includeHidden: options.includeHidden,\n includeText: options.includeText,\n scale,\n schematicSheetId: SCHEMATIC_SHEET_ID,\n })\n elements.push(...semanticConversion.elements)\n\n for (const [index, record] of records.entries()) {\n if (semanticConversion.handledRecords.has(record)) continue\n if (!shouldRenderSchematicRecord(record, context)) continue\n const converted = convertSchematicRecord(record, index, context, options)\n elements.push(...converted)\n }\n\n return elements\n}\n\nfunction convertSchematicRecord(\n record: AltiumRecord,\n index: number,\n context: SchematicContext,\n options: ConvertAltiumSchDocOptions,\n): AnyCircuitElement[] {\n const kind = record.recordKind\n const scale = context.scale\n const color = altiumColorToCss(record.getCaseInsensitive(\"COLOR\"), \"#1f2937\")\n const strokeWidth = Math.max(\n Number(record.getCaseInsensitive(\"LINEWIDTH\") ?? 1) * scale,\n 0.05,\n )\n\n if (kind === \"27\") {\n const points = getSchematicRecordPoints(record).map((point) =>\n scalePoint(point, scale),\n )\n if (points.length < 2) return []\n return [\n {\n type: \"schematic_trace\",\n schematic_trace_id: `schematic_trace_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n junctions: [],\n edges: points.slice(1).map((point, pointIndex) => ({\n from: points[pointIndex] ?? point,\n to: point,\n })),\n } satisfies SchematicTrace,\n ]\n }\n\n if (kind === \"6\" || kind === \"7\") {\n const points = getSchematicRecordPoints(record).map((point) =>\n scalePoint(point, scale),\n )\n if (points.length < 2) return []\n return [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_path_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points,\n stroke_width: strokeWidth,\n stroke_color: color,\n fill_color:\n kind === \"7\"\n ? altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"transparent\",\n )\n : undefined,\n is_filled: kind === \"7\",\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n }\n\n if (kind === \"13\") {\n const location = getLocation(record)\n const corner = getCorner(record)\n if (!location || !corner) return []\n return [createLine(index, location, corner, color, strokeWidth, scale)]\n }\n\n if (kind === \"10\" || kind === \"14\") {\n const rectangle = getRectangle(record)\n if (!rectangle) return []\n return [\n {\n type: \"schematic_rect\",\n schematic_rect_id: `schematic_rect_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(\n {\n x: (rectangle.minX + rectangle.maxX) / 2,\n y: (rectangle.minY + rectangle.maxY) / 2,\n },\n scale,\n ),\n width: (rectangle.maxX - rectangle.minX) * scale,\n height: (rectangle.maxY - rectangle.minY) * scale,\n rotation: 0,\n stroke_width: strokeWidth,\n color,\n is_filled: record.getBoolean(\"ISSOLID\") === true,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_dashed: false,\n } satisfies SchematicRect,\n ]\n }\n\n if (kind === \"8\") {\n const center = getLocation(record)\n if (!center) return []\n const radiusX = getCoordinate(record, \"RADIUS\", 1)\n const radiusY = getCoordinate(record, \"SECONDARYRADIUS\", radiusX)\n if (Math.abs(radiusX - radiusY) < 0.0001) {\n return [\n {\n type: \"schematic_circle\",\n schematic_circle_id: `schematic_circle_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(center, scale),\n radius: radiusX * scale,\n stroke_width: strokeWidth,\n color,\n is_filled: record.getBoolean(\"ISSOLID\") === true,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_dashed: false,\n } satisfies SchematicCircle,\n ]\n }\n return [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_ellipse_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: approximateEllipse(center, radiusX, radiusY).map((point) =>\n scalePoint(point, scale),\n ),\n stroke_width: strokeWidth,\n stroke_color: color,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_filled: record.getBoolean(\"ISSOLID\") === true,\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n }\n\n if (kind === \"11\" || kind === \"12\") {\n const center = getLocation(record)\n if (!center) return []\n return [\n {\n type: \"schematic_arc\",\n schematic_arc_id: `schematic_arc_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(center, scale),\n radius: getCoordinate(record, \"RADIUS\", 1) * scale,\n start_angle_degrees: Number(\n record.getCaseInsensitive(\"STARTANGLE\") ?? 0,\n ),\n end_angle_degrees: Number(record.getCaseInsensitive(\"ENDANGLE\") ?? 360),\n direction: \"counterclockwise\",\n stroke_width: strokeWidth,\n color,\n is_dashed: false,\n } satisfies SchematicArc,\n ]\n }\n\n if (kind === \"2\") {\n return convertPin(record, index, context, options, color)\n }\n\n if (kind === \"29\") {\n const location = getLocation(record)\n if (!location) return []\n return [\n {\n type: \"schematic_circle\",\n schematic_circle_id: `schematic_junction_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(location, scale),\n radius: Math.max(\n Number(record.getCaseInsensitive(\"SIZE\") ?? 1) * 0.18,\n 0.15,\n ),\n color,\n is_filled: true,\n fill_color: color,\n is_dashed: false,\n } satisfies SchematicCircle,\n ]\n }\n\n if (kind === \"22\") {\n const location = getLocation(record)\n if (!location) return []\n const radius = 0.4 / scale\n return [\n createLine(\n index,\n { x: location.x - radius, y: location.y - radius },\n { x: location.x + radius, y: location.y + radius },\n color,\n 0.1,\n scale,\n \"a\",\n ),\n createLine(\n index,\n { x: location.x + radius, y: location.y - radius },\n { x: location.x - radius, y: location.y + radius },\n color,\n 0.1,\n scale,\n \"b\",\n ),\n ]\n }\n\n if (kind === \"17\") {\n return convertPowerPort(record, index, context, options, color)\n }\n\n if (kind === \"18\") {\n return convertPort(record, index, context, options, color)\n }\n\n if (kind === \"4\" || kind === \"25\" || kind === \"34\" || kind === \"41\") {\n if (options.includeText === false) return []\n if (record.getBoolean(\"ISHIDDEN\") && !options.includeHidden) return []\n const text =\n record.getDecoded(\"TEXT\") ??\n record.getDecoded(\"NAME\") ??\n record.getDecoded(\"DESIGNATOR\")\n const location = getLocation(record)\n if (!text || !location) return []\n return [createText(record, index, text, location, color, context)]\n }\n\n if (kind === \"28\") {\n const rectangle = getRectangle(record)\n const text = decodeMultilineText(record.getDecoded(\"TEXT\") ?? \"\")\n if (!rectangle || !text || options.includeText === false) return []\n const fontSize = getFontSize(record, context)\n const fontFamily = getFontFamily(record, context)\n const margin = Math.max(getCoordinate(record, \"TEXTMARGIN\", 0), 0)\n const frameWidth = rectangle.maxX - rectangle.minX\n const frameHeight = rectangle.maxY - rectangle.minY\n const availableWidth = Math.max(frameWidth - margin * 2, fontSize)\n const availableHeight = Math.max(frameHeight - margin * 2, fontSize)\n const wrappedLines =\n record.getBoolean(\"WORDWRAP\") === false\n ? text.split(\"\\n\")\n : wrapSchematicText(text, availableWidth, fontSize, fontFamily)\n const lineHeight = fontSize\n const visibleLines =\n record.getBoolean(\"CLIPTORECT\") === false\n ? wrappedLines\n : wrappedLines.slice(\n 0,\n Math.max(Math.ceil(availableHeight / lineHeight), 1),\n )\n const alignment = Number(record.getCaseInsensitive(\"ALIGNMENT\") ?? 1)\n const horizontalAnchor =\n alignment === 2 ? \"center\" : alignment === 3 ? \"right\" : \"left\"\n const textX =\n horizontalAnchor === \"center\"\n ? (rectangle.minX + rectangle.maxX) / 2\n : horizontalAnchor === \"right\"\n ? rectangle.maxX - margin\n : rectangle.minX + margin\n const textColor = altiumColorToCss(\n record.getCaseInsensitive(\"TEXTCOLOR\") ??\n record.getCaseInsensitive(\"COLOR\"),\n \"#1f2937\",\n )\n const elements: AnyCircuitElement[] = visibleLines.map((line, lineIndex) =>\n createDirectText(\n `schematic_text_frame_line_altium_${index}_${lineIndex}`,\n line,\n {\n x: textX,\n y: rectangle.maxY - margin - lineIndex * lineHeight,\n },\n fontSize,\n textColor,\n scale,\n 0,\n `top_${horizontalAnchor}` as SchematicText[\"anchor\"],\n ),\n )\n\n const isSolid = record.getBoolean(\"ISSOLID\") === true\n const showBorder = record.getBoolean(\"SHOWBORDER\") === true\n if (isSolid || showBorder) {\n elements.unshift({\n type: \"schematic_rect\",\n schematic_rect_id: `schematic_text_frame_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(\n {\n x: (rectangle.minX + rectangle.maxX) / 2,\n y: (rectangle.minY + rectangle.maxY) / 2,\n },\n scale,\n ),\n width: frameWidth * scale,\n height: frameHeight * scale,\n rotation: 0,\n stroke_width: showBorder ? strokeWidth : 0,\n color: showBorder ? color : \"transparent\",\n is_filled: isSolid,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_dashed: false,\n } satisfies SchematicRect)\n }\n\n return elements\n }\n\n return []\n}\n\nfunction convertPin(\n record: AltiumRecord,\n index: number,\n context: SchematicContext,\n options: ConvertAltiumSchDocOptions,\n color: string,\n): AnyCircuitElement[] {\n const location = getLocation(record)\n if (!location) return []\n const pinConglomerate = record.getNumber(\"PINCONGLOMERATE\")\n const hidden =\n record.getBoolean(\"ISHIDDEN\") ||\n (pinConglomerate !== undefined && (pinConglomerate & 0x04) !== 0)\n if (hidden && !options.includeHidden) return []\n const orientation =\n (pinConglomerate ?? Number(record.getCaseInsensitive(\"ORIENTATION\") ?? 0)) &\n 3\n const direction = [\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n { x: -1, y: 0 },\n { x: 0, y: -1 },\n ][orientation] ?? { x: 1, y: 0 }\n const length = Math.max(\n Number(record.getCaseInsensitive(\"PINLENGTH\") ?? 10),\n 1,\n )\n const end = {\n x: location.x + direction.x * length,\n y: location.y + direction.y * length,\n }\n const elements: AnyCircuitElement[] = [\n createLine(index, location, end, color, 0.1, context.scale, \"pin\"),\n ]\n if (options.includeText === false) return elements\n\n const name = record.getDecoded(\"NAME\") ?? \"\"\n const designator = record.getDecoded(\"DESIGNATOR\") ?? \"\"\n const showName =\n pinConglomerate === undefined || (pinConglomerate & 0x08) !== 0\n const showDesignator =\n pinConglomerate === undefined || (pinConglomerate & 0x10) !== 0\n const rotation = orientation === 1 || orientation === 3 ? 90 : 0\n const directionMatchesText = orientation === 0 || orientation === 1\n const nameAnchor = directionMatchesText ? \"right\" : \"left\"\n const designatorAnchor = directionMatchesText ? \"left\" : \"right\"\n const textOffset = 2\n\n if (showName && name) {\n elements.push(\n createDirectText(\n `schematic_pin_name_altium_${index}`,\n name,\n {\n x: location.x - direction.x * textOffset,\n y: location.y - direction.y * textOffset,\n },\n 6,\n color,\n context.scale,\n rotation,\n nameAnchor,\n ),\n )\n }\n if (showDesignator && designator) {\n elements.push(\n createDirectText(\n `schematic_pin_designator_altium_${index}`,\n designator,\n {\n x: location.x + direction.x * textOffset,\n y: location.y + direction.y * textOffset,\n },\n 6,\n color,\n context.scale,\n rotation,\n designatorAnchor,\n ),\n )\n }\n return elements\n}\n\nfunction convertPowerPort(\n record: AltiumRecord,\n index: number,\n context: SchematicContext,\n options: ConvertAltiumSchDocOptions,\n color: string,\n): AnyCircuitElement[] {\n const location = getLocation(record)\n if (!location) return []\n const orientation =\n ((Math.round(record.getNumber(\"ORIENTATION\") ?? 0) % 4) + 4) % 4\n const direction = [\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n { x: -1, y: 0 },\n { x: 0, y: -1 },\n ][orientation] ?? { x: 1, y: 0 }\n const perpendicular = { x: -direction.y, y: direction.x }\n const point = (along: number, across = 0): AltiumPoint => ({\n x: location.x + direction.x * along + perpendicular.x * across,\n y: location.y + direction.y * along + perpendicular.y * across,\n })\n const style = Math.round(Number(record.getCaseInsensitive(\"STYLE\") ?? 2))\n const elements: AnyCircuitElement[] = []\n let labelDistance: number\n\n if (style === 2) {\n elements.push(\n createLine(\n index,\n location,\n point(8),\n color,\n 0.1,\n context.scale,\n \"power_port_stem\",\n ),\n createLine(\n index,\n point(8, -5),\n point(8, 5),\n color,\n 0.1,\n context.scale,\n \"power_port_bar\",\n ),\n )\n labelDistance = 12\n } else if (style === 5) {\n elements.push(\n createLine(\n index,\n location,\n point(4),\n color,\n 0.1,\n context.scale,\n \"power_port_stem\",\n ),\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_power_port_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: [point(4, -7), point(4, 7), point(12)].map((value) =>\n scalePoint(value, context.scale),\n ),\n stroke_width: 0.1,\n stroke_color: color,\n is_filled: false,\n is_dashed: false,\n } satisfies SchematicPath,\n )\n labelDistance = 16\n } else if (style === 4) {\n elements.push(\n createLine(\n index,\n location,\n point(4),\n color,\n 0.1,\n context.scale,\n \"power_port_stem\",\n ),\n ...[\n { along: 4, halfWidth: 7 },\n { along: 8, halfWidth: 4.5 },\n { along: 12, halfWidth: 2 },\n ].map(({ along, halfWidth }, lineIndex) =>\n createLine(\n index,\n point(along, -halfWidth),\n point(along, halfWidth),\n color,\n 0.1,\n context.scale,\n `power_port_ground_${lineIndex}`,\n ),\n ),\n )\n labelDistance = 16\n } else if (style === 6) {\n elements.push(\n createLine(\n index,\n location,\n point(4),\n color,\n 0.1,\n context.scale,\n \"power_port_stem\",\n ),\n createLine(\n index,\n point(4, -7),\n point(4, 7),\n color,\n 0.1,\n context.scale,\n \"power_port_chassis_bar\",\n ),\n ...[\n { from: -7, to: -9 },\n { from: 0, to: -2 },\n { from: 7, to: 5 },\n ].map(({ from, to }, lineIndex) =>\n createLine(\n index,\n point(4, from),\n point(9, to),\n color,\n 0.1,\n context.scale,\n `power_port_chassis_${lineIndex}`,\n ),\n ),\n )\n labelDistance = 14\n } else {\n elements.push({\n type: \"schematic_path\",\n schematic_path_id: `schematic_power_port_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: [location, point(10, -5), point(10, 5)].map((value) =>\n scalePoint(value, context.scale),\n ),\n stroke_width: 0.1,\n stroke_color: color,\n fill_color: color,\n is_filled: true,\n is_dashed: false,\n } satisfies SchematicPath)\n labelDistance = 14\n }\n const text = record.getDecoded(\"TEXT\") ?? record.getDecoded(\"NAME\")\n if (\n text &&\n options.includeText !== false &&\n record.getBoolean(\"SHOWNETNAME\") !== false\n ) {\n const vertical = direction.y !== 0\n const anchor: SchematicText[\"anchor\"] = vertical\n ? direction.y > 0\n ? \"bottom_center\"\n : \"top_center\"\n : direction.x > 0\n ? \"center_left\"\n : \"center_right\"\n elements.push(\n createDirectText(\n `schematic_power_port_text_altium_${index}`,\n text,\n point(labelDistance),\n getFontSize(record, context),\n color,\n context.scale,\n 0,\n anchor,\n ),\n )\n }\n return elements\n}\n\nfunction convertPort(\n record: AltiumRecord,\n index: number,\n context: SchematicContext,\n options: ConvertAltiumSchDocOptions,\n color: string,\n): AnyCircuitElement[] {\n const location = getLocation(record)\n if (!location) return []\n const width = Math.max(Number(record.getCaseInsensitive(\"WIDTH\") ?? 16), 10)\n const height = Math.max(Number(record.getCaseInsensitive(\"HEIGHT\") ?? 10), 4)\n const halfHeight = height / 2\n const pointDepth = Math.min(width * 0.22, height)\n const ioType = Number(record.getCaseInsensitive(\"IOTYPE\") ?? 0)\n const points =\n ioType === 1\n ? [\n { x: location.x, y: location.y },\n { x: location.x + pointDepth, y: location.y + halfHeight },\n { x: location.x + width, y: location.y + halfHeight },\n { x: location.x + width, y: location.y - halfHeight },\n { x: location.x + pointDepth, y: location.y - halfHeight },\n ]\n : ioType === 2\n ? [\n { x: location.x, y: location.y + halfHeight },\n {\n x: location.x + width - pointDepth,\n y: location.y + halfHeight,\n },\n { x: location.x + width, y: location.y },\n {\n x: location.x + width - pointDepth,\n y: location.y - halfHeight,\n },\n { x: location.x, y: location.y - halfHeight },\n ]\n : [\n { x: location.x, y: location.y + halfHeight },\n { x: location.x + width, y: location.y + halfHeight },\n { x: location.x + width, y: location.y - halfHeight },\n { x: location.x, y: location.y - halfHeight },\n ]\n const elements: AnyCircuitElement[] = [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_port_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: points.map((point) => scalePoint(point, context.scale)),\n stroke_width: 0.1,\n stroke_color: color,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_filled: true,\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n const name = record.getDecoded(\"NAME\")\n if (name && options.includeText !== false) {\n elements.push(\n createDirectText(\n `schematic_port_text_altium_${index}`,\n name,\n { x: location.x + width / 2, y: location.y },\n getFontSize(record, context),\n altiumColorToCss(record.getCaseInsensitive(\"TEXTCOLOR\"), color),\n context.scale,\n 0,\n \"center\",\n ),\n )\n }\n return elements\n}\n\nfunction createSheetBorder(\n sheetRecord: AltiumRecord | undefined,\n scale: number,\n): SchematicRect {\n const width = Math.max(\n Number(sheetRecord?.getCaseInsensitive(\"CUSTOMX\") ?? 1000),\n 1,\n )\n const height = Math.max(\n Number(sheetRecord?.getCaseInsensitive(\"CUSTOMY\") ?? 800),\n 1,\n )\n return {\n type: \"schematic_rect\",\n schematic_rect_id: \"schematic_rect_altium_sheet_border\",\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: { x: (width * scale) / 2, y: (height * scale) / 2 },\n width: width * scale,\n height: height * scale,\n rotation: 0,\n stroke_width: 0.1,\n color: \"#334155\",\n is_filled: false,\n is_dashed: false,\n }\n}\n\nfunction createLine(\n index: number,\n start: AltiumPoint,\n end: AltiumPoint,\n color: string,\n strokeWidth: number,\n scale: number,\n suffix = \"line\",\n): SchematicLine {\n return {\n type: \"schematic_line\",\n schematic_line_id: `schematic_line_altium_${index}_${suffix}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n x1: start.x * scale,\n y1: start.y * scale,\n x2: end.x * scale,\n y2: end.y * scale,\n stroke_width: strokeWidth,\n color,\n is_dashed: false,\n }\n}\n\nfunction createText(\n record: AltiumRecord,\n index: number,\n text: string,\n location: AltiumPoint,\n color: string,\n context: SchematicContext,\n anchorOverride?: SchematicText[\"anchor\"],\n): SchematicText {\n const positioning = getTextPositioning(record)\n return createDirectText(\n `schematic_text_altium_${index}`,\n text,\n location,\n getFontSize(record, context),\n color,\n context.scale,\n positioning.rotation,\n anchorOverride ?? positioning.anchor,\n )\n}\n\nfunction createDirectText(\n id: string,\n text: string,\n location: AltiumPoint,\n fontSize: number,\n color: string,\n scale: number,\n rotation: number,\n anchor: SchematicText[\"anchor\"],\n): SchematicText {\n return {\n type: \"schematic_text\",\n schematic_text_id: id,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n text,\n font_size: Math.max(fontSize * scale, 0.2),\n position: scalePoint(location, scale),\n rotation,\n anchor,\n color,\n }\n}\n\nfunction getFontSize(record: AltiumRecord, context: SchematicContext): number {\n const fontId = Math.max(\n Math.round(Number(record.getCaseInsensitive(\"FONTID\") ?? 1)),\n 1,\n )\n return Math.max(\n Number(context.sheetRecord?.getCaseInsensitive(`SIZE${fontId}`) ?? 9),\n 1,\n )\n}\n\nfunction getFontFamily(\n record: AltiumRecord,\n context: SchematicContext,\n): string {\n const fontId = Math.max(\n Math.round(Number(record.getCaseInsensitive(\"FONTID\") ?? 1)),\n 1,\n )\n return context.sheetRecord?.getDecoded(`FONTNAME${fontId}`) ?? \"Arial\"\n}\n\nfunction getTextPositioning(record: AltiumRecord): {\n anchor: SchematicText[\"anchor\"]\n rotation: number\n} {\n const justification = Math.min(\n Math.max(Math.round(record.getNumber(\"JUSTIFICATION\") ?? 0), 0),\n 8,\n )\n const orientation =\n ((Math.round(record.getNumber(\"ORIENTATION\") ?? 0) % 4) + 4) % 4\n let column = justification % 3\n const row = Math.floor(justification / 3)\n if (orientation === 2 || orientation === 3) column = 2 - column\n const horizontal = [\"left\", \"center\", \"right\"][column] ?? \"left\"\n const vertical = [\"bottom\", \"center\", \"top\"][row] ?? \"bottom\"\n const anchor =\n horizontal === \"center\" && vertical === \"center\"\n ? \"center\"\n : (`${vertical}_${horizontal}` as SchematicText[\"anchor\"])\n return {\n anchor,\n rotation: orientation === 1 || orientation === 3 ? 90 : 0,\n }\n}\n\nfunction shouldRenderSchematicRecord(\n record: AltiumRecord,\n context: SchematicContext,\n): boolean {\n let ownerPartId = record.getNumber(\"OWNERPARTID\")\n let ownerPartDisplayMode = record.getNumber(\"OWNERPARTDISPLAYMODE\")\n let current: AltiumRecord | undefined = record\n const visited = new Set<AltiumRecord>()\n\n while (current && !visited.has(current)) {\n visited.add(current)\n const parent = context.document.getParent(current)\n if (!parent) return true\n\n if (ownerPartId === undefined || ownerPartId <= 0) {\n ownerPartId = current.getNumber(\"OWNERPARTID\")\n }\n if (ownerPartDisplayMode === undefined) {\n ownerPartDisplayMode = current.getNumber(\"OWNERPARTDISPLAYMODE\")\n }\n\n if (parent.recordKind === \"1\") {\n const currentPartId = parent.getNumber(\"CURRENTPARTID\") ?? 1\n return (\n (ownerPartId === undefined ||\n ownerPartId <= 0 ||\n ownerPartId === currentPartId) &&\n (ownerPartDisplayMode === undefined || ownerPartDisplayMode === 0)\n )\n }\n current = parent\n }\n return true\n}\n\nfunction getLocation(record: AltiumRecord): AltiumPoint | undefined {\n if (\n record.getCaseInsensitive(\"LOCATION.X\") === undefined ||\n record.getCaseInsensitive(\"LOCATION.Y\") === undefined\n ) {\n return undefined\n }\n return {\n x: getCoordinate(record, \"LOCATION.X\"),\n y: getCoordinate(record, \"LOCATION.Y\"),\n }\n}\n\nfunction getCorner(record: AltiumRecord): AltiumPoint | undefined {\n if (\n record.getCaseInsensitive(\"CORNER.X\") === undefined ||\n record.getCaseInsensitive(\"CORNER.Y\") === undefined\n ) {\n return undefined\n }\n return {\n x: getCoordinate(record, \"CORNER.X\"),\n y: getCoordinate(record, \"CORNER.Y\"),\n }\n}\n\nfunction getRectangle(\n record: AltiumRecord,\n): { maxX: number; maxY: number; minX: number; minY: number } | undefined {\n const location = getLocation(record)\n const corner = getCorner(record)\n if (!location || !corner) return undefined\n return {\n minX: Math.min(location.x, corner.x),\n minY: Math.min(location.y, corner.y),\n maxX: Math.max(location.x, corner.x),\n maxY: Math.max(location.y, corner.y),\n }\n}\n\nfunction getCoordinate(\n record: AltiumRecord,\n key: string,\n fallback = 0,\n): number {\n const integerPart = Number(record.getCaseInsensitive(key) ?? fallback)\n const fractionRaw = record.getCaseInsensitive(`${key}_FRAC`)\n if (!Number.isFinite(integerPart) || fractionRaw === undefined) {\n return Number.isFinite(integerPart) ? integerPart : fallback\n }\n const fraction = Number(`0.${fractionRaw.replace(/^[+-]/u, \"\")}`)\n if (!Number.isFinite(fraction)) return integerPart\n return integerPart < 0 ? integerPart - fraction : integerPart + fraction\n}\n\nfunction scalePoint(point: AltiumPoint, scale: number): AltiumPoint {\n return { x: point.x * scale, y: point.y * scale }\n}\n\nfunction approximateEllipse(\n center: AltiumPoint,\n radiusX: number,\n radiusY: number,\n): AltiumPoint[] {\n return Array.from({ length: 49 }, (_, index) => {\n const radians = (index / 48) * Math.PI * 2\n return {\n x: center.x + Math.cos(radians) * radiusX,\n y: center.y + Math.sin(radians) * radiusY,\n }\n })\n}\n\nfunction decodeMultilineText(text: string): string {\n return text.replaceAll(\"~1\", \"\\n\").replaceAll(\"\\\\n\", \"\\n\")\n}\n\nfunction wrapSchematicText(\n text: string,\n maximumWidth: number,\n fontSize: number,\n fontFamily: string,\n): string[] {\n return text.split(\"\\n\").flatMap((paragraph) => {\n if (\n estimateSchematicTextWidth(paragraph, fontSize, fontFamily) <=\n maximumWidth\n ) {\n return [paragraph]\n }\n const words = paragraph.split(/\\s+/u)\n const lines: string[] = []\n let line = \"\"\n for (const word of words) {\n if (!line) {\n line = word\n } else if (\n estimateSchematicTextWidth(`${line} ${word}`, fontSize, fontFamily) <=\n maximumWidth\n ) {\n line = `${line} ${word}`\n } else {\n lines.push(line)\n line = word\n }\n }\n if (line) lines.push(line)\n return lines.length > 0 ? lines : [paragraph]\n })\n}\n\nfunction estimateSchematicTextWidth(\n text: string,\n fontSize: number,\n fontFamily: string,\n): number {\n if (/courier|mono/iu.test(fontFamily)) return text.length * fontSize * 0.6\n if (!/times|cambria|serif/iu.test(fontFamily)) {\n return text.length * fontSize * 0.52\n }\n\n return [...text].reduce((width, character) => {\n const emWidth =\n character === \" \"\n ? 0.23\n : /[ilI1.,:;!'`|]/u.test(character)\n ? 0.2\n : /[mwMW@%]/u.test(character)\n ? 0.7\n : /[A-Z0-9]/u.test(character)\n ? 0.5\n : 0.4\n return width + emWidth * fontSize\n }, 0)\n}\n\nfunction altiumColorToCss(raw: string | undefined, fallback: string): string {\n if (raw === undefined) return fallback\n const value = Number(raw)\n if (!Number.isInteger(value) || value < 0) return fallback\n const red = value & 0xff\n const green = (value >>> 8) & 0xff\n const blue = (value >>> 16) & 0xff\n return `#${toHex(red)}${toHex(green)}${toHex(blue)}`\n}\n\nfunction toHex(value: number): string {\n return value.toString(16).padStart(2, \"0\")\n}\n","import {\n type AltiumPoint,\n type AltiumRecord,\n type AltiumSchDoc,\n getSchematicDocumentIndex,\n getSchematicRecordPoints,\n} from \"altiumts\"\nimport {\n type AnyCircuitElement,\n type SchematicComponent,\n type SchematicNetLabel,\n type SchematicPort,\n type SchematicText,\n type SchematicTrace,\n type SourceComponentBase,\n type SourceNet,\n type SourcePort,\n type SourceTrace,\n source_simple_capacitor,\n source_simple_crystal,\n source_simple_inductor,\n source_simple_mosfet,\n source_simple_resistor,\n} from \"circuit-json\"\nimport { parseAndConvertSiUnit } from \"format-si-unit\"\nimport { type SchSymbol, symbols } from \"schematic-symbols\"\n\nexport interface SemanticSchematicOptions {\n includeHidden?: boolean\n includeText?: boolean\n scale: number\n schematicSheetId: string\n}\n\nexport interface SemanticSchematicConversion {\n elements: AnyCircuitElement[]\n handledRecords: Set<AltiumRecord>\n}\n\ninterface ConvertedPort {\n isSchematicVisible: boolean\n point: AltiumPoint\n record: AltiumRecord\n schematicPort: SchematicPort\n sourcePort: SourcePort\n}\n\ninterface SymbolPortAssignment {\n convertedPort: ConvertedPort\n symbolPort: SchSymbol[\"ports\"][number]\n}\n\ninterface SymbolSelection {\n assignments: SymbolPortAssignment[]\n name: string\n symbol: SchSymbol\n}\n\ninterface SemanticNet {\n id: string\n names: string[]\n points: AltiumPoint[]\n records: AltiumRecord[]\n}\n\ninterface SemanticNetGraph {\n getConnectedWiresForRecord(record: AltiumRecord): AltiumRecord[]\n nets: SemanticNet[]\n}\n\ninterface Bounds {\n maxX: number\n maxY: number\n minX: number\n minY: number\n}\n\ntype CardinalDirection = \"up\" | \"down\" | \"left\" | \"right\"\n\nconst DIRECTION_BY_ORIENTATION: readonly CardinalDirection[] = [\n \"right\",\n \"up\",\n \"left\",\n \"down\",\n]\n\nconst VECTOR_BY_DIRECTION: Readonly<Record<CardinalDirection, AltiumPoint>> = {\n down: { x: 0, y: -1 },\n left: { x: -1, y: 0 },\n right: { x: 1, y: 0 },\n up: { x: 0, y: 1 },\n}\n\nconst CARDINAL_DIRECTIONS: readonly CardinalDirection[] = [\n \"right\",\n \"up\",\n \"left\",\n \"down\",\n]\n\nconst SYMBOL_CATALOG = symbols as Record<string, SchSymbol | undefined>\nconst SYMBOL_NAMES = Object.keys(SYMBOL_CATALOG)\n\n/**\n * Converts records that have native Circuit JSON semantics before the\n * primitive fallback runs. This deliberately favors Circuit JSON's component,\n * port, trace, net, and symbol model over reproducing Altium's drawing style.\n */\nexport function convertSemanticSchematic(\n document: AltiumSchDoc,\n options: SemanticSchematicOptions,\n): SemanticSchematicConversion {\n const handledRecords = new Set<AltiumRecord>()\n const elements: AnyCircuitElement[] = []\n const convertedPorts: ConvertedPort[] = []\n\n convertComponents({\n convertedPorts,\n document,\n elements,\n handledRecords,\n options,\n })\n\n const semanticNetGraph = buildSemanticNetGraph(document, convertedPorts)\n\n const connectivity = convertConnectivity({\n convertedPorts,\n document,\n elements,\n handledRecords,\n semanticNetGraph,\n options,\n })\n\n convertNetLabels({\n connectivity,\n document,\n elements,\n handledRecords,\n semanticNetGraph,\n options,\n })\n\n return { elements, handledRecords }\n}\n\nfunction convertComponents(params: {\n convertedPorts: ConvertedPort[]\n document: AltiumSchDoc\n elements: AnyCircuitElement[]\n handledRecords: Set<AltiumRecord>\n options: SemanticSchematicOptions\n}): void {\n const { convertedPorts, document, elements, handledRecords, options } = params\n const documentIndex = getSchematicDocumentIndex(document)\n const sourceComponentIdByDesignator = new Map<string, string>()\n\n for (const [componentIndex, componentRecord] of document.records.entries()) {\n if (componentRecord.recordKind !== \"1\") continue\n handledRecords.add(componentRecord)\n\n const ownedRecords = documentIndex.getOwnedRecords(componentRecord)\n for (const ownedRecord of ownedRecords) handledRecords.add(ownedRecord)\n\n const currentPartId = componentRecord.getNumber(\"CURRENTPARTID\") ?? 1\n const visibleOwnedRecords = ownedRecords.filter((record) =>\n isOwnedRecordVisible(record, currentPartId),\n )\n const pins = visibleOwnedRecords.filter(\n (record) =>\n record.recordKind === \"2\" &&\n (!isPinHidden(record) || options.includeHidden === true),\n )\n if (pins.length === 0) continue\n\n const designator =\n findOwnedText(ownedRecords, \"34\", \"Designator\") ??\n componentRecord.getDecoded(\"DESIGNATOR\") ??\n `U${componentIndex}`\n const value =\n findOwnedText(ownedRecords, \"41\", \"Comment\") ??\n componentRecord.getDecoded(\"COMMENT\") ??\n componentRecord.getDecoded(\"DESIGNITEMID\") ??\n componentRecord.getDecoded(\"LIBREFERENCE\") ??\n \"\"\n const libraryReference =\n componentRecord.getDecoded(\"LIBREFERENCE\") ??\n componentRecord.getDecoded(\"DESIGNITEMID\") ??\n designator\n const manufacturerPartNumber = findOwnedText(\n ownedRecords,\n \"41\",\n \"Mfr_part_number\",\n )\n const normalizedDesignator = designator.trim().toUpperCase()\n const existingSourceComponentId =\n sourceComponentIdByDesignator.get(normalizedDesignator)\n const sourceComponentId =\n existingSourceComponentId ?? `source_component_altium_${componentIndex}`\n const schematicComponentId = `schematic_component_altium_${componentIndex}`\n if (!existingSourceComponentId) {\n sourceComponentIdByDesignator.set(normalizedDesignator, sourceComponentId)\n elements.push(\n createSourceComponent({\n designator,\n libraryReference,\n manufacturerPartNumber,\n pinCount: pins.length,\n sourceComponentId,\n value,\n }),\n )\n }\n\n const componentPorts = pins.map((pin, pinIndex) =>\n convertComponentPin({\n document,\n options,\n pin,\n pinIndex,\n schematicComponentId,\n sourceComponentId,\n }),\n )\n const bodyBounds = getComponentBodyBounds(\n visibleOwnedRecords,\n componentPorts.map(({ point }) => point),\n )\n const symbolSelection = selectCircuitJsonSymbol({\n designator,\n libraryReference,\n ports: componentPorts,\n })\n const center = scalePoint(getBoundsCenter(bodyBounds), options.scale)\n const size = symbolSelection\n ? { ...symbolSelection.symbol.size }\n : {\n height: Math.max(\n (bodyBounds.maxY - bodyBounds.minY) * options.scale,\n 0.4,\n ),\n width: Math.max(\n (bodyBounds.maxX - bodyBounds.minX) * options.scale,\n 0.4,\n ),\n }\n if (symbolSelection) {\n applyNativeSymbolPortGeometry({\n center,\n selection: symbolSelection,\n })\n }\n convertedPorts.push(...componentPorts)\n elements.push(\n ...componentPorts.flatMap(\n ({ isSchematicVisible, sourcePort, schematicPort }) => [\n sourcePort,\n ...(isSchematicVisible ? [schematicPort] : []),\n ],\n ),\n )\n const schematicComponent: SchematicComponent = {\n type: \"schematic_component\",\n center,\n // circuit-to-svg uses this flag as the renderable component gate for\n // both generated boxes and components selected by symbol_name.\n is_box_with_pins: true,\n schematic_component_id: schematicComponentId,\n schematic_sheet_id: options.schematicSheetId,\n size,\n source_component_id: sourceComponentId,\n symbol_display_value: value,\n ...(symbolSelection ? { symbol_name: symbolSelection.name } : {}),\n }\n elements.push(schematicComponent)\n\n if (!symbolSelection && options.includeText !== false) {\n elements.push(\n createComponentText({\n anchor: \"bottom_left\",\n component: schematicComponent,\n id: `schematic_component_designator_altium_${componentIndex}`,\n position: {\n x: center.x - size.width / 2,\n y: center.y + size.height / 2 + 0.13,\n },\n text: designator,\n }),\n )\n if (value) {\n elements.push(\n createComponentText({\n anchor: \"top_left\",\n component: schematicComponent,\n id: `schematic_component_value_altium_${componentIndex}`,\n position: {\n x: center.x - size.width / 2,\n y: center.y - size.height / 2 - 0.13,\n },\n text: value,\n }),\n )\n }\n }\n }\n}\n\nfunction convertComponentPin(params: {\n document: AltiumSchDoc\n options: SemanticSchematicOptions\n pin: AltiumRecord\n pinIndex: number\n schematicComponentId: string\n sourceComponentId: string\n}): ConvertedPort {\n const {\n document,\n options,\n pin,\n pinIndex,\n schematicComponentId,\n sourceComponentId,\n } = params\n const recordIndex = document.records.indexOf(pin)\n const pinConglomerate = pin.getNumber(\"PINCONGLOMERATE\")\n const orientation = (pinConglomerate ?? pin.getNumber(\"ORIENTATION\") ?? 0) & 3\n const direction = DIRECTION_BY_ORIENTATION[orientation] ?? \"right\"\n const directionVector = VECTOR_BY_DIRECTION[direction]\n const location = getLocation(pin) ?? { x: 0, y: 0 }\n const pinLength = Math.max(pin.getNumber(\"PINLENGTH\") ?? 10, 0)\n const terminalPoint = {\n x: location.x + directionVector.x * pinLength,\n y: location.y + directionVector.y * pinLength,\n }\n const designator = pin.getDecoded(\"DESIGNATOR\") ?? `${pinIndex + 1}`\n const pinNumber = parsePinNumber(designator)\n const name = pin.getDecoded(\"NAME\") ?? designator\n const sourcePortId = `source_port_altium_${recordIndex}`\n const schematicPortId = `schematic_port_altium_${recordIndex}`\n const sourcePort: SourcePort = {\n type: \"source_port\",\n name,\n port_hints: uniqueStrings([\n designator,\n name,\n pinNumber === undefined ? undefined : `pin${pinNumber}`,\n ]),\n source_component_id: sourceComponentId,\n source_port_id: sourcePortId,\n ...(pinNumber === undefined ? {} : { pin_number: pinNumber }),\n }\n const electricalType = pin.getNumber(\"ELECTRICAL\")\n const schematicPort: SchematicPort = {\n type: \"schematic_port\",\n center: scalePoint(terminalPoint, options.scale),\n display_pin_label: name,\n distance_from_component_edge: pinLength * options.scale,\n facing_direction: direction,\n is_connected: false,\n schematic_component_id: schematicComponentId,\n schematic_port_id: schematicPortId,\n schematic_sheet_id: options.schematicSheetId,\n side_of_component: directionToSide(direction),\n source_port_id: sourcePortId,\n true_ccw_index: pinIndex,\n ...(pinNumber === undefined ? {} : { pin_number: pinNumber }),\n ...(electricalType === 0 || electricalType === 1\n ? { has_input_arrow: true }\n : {}),\n ...(electricalType === 1 || electricalType === 2\n ? { has_output_arrow: true }\n : {}),\n }\n return {\n isSchematicVisible: true,\n point: terminalPoint,\n record: pin,\n schematicPort,\n sourcePort,\n }\n}\n\nfunction createSourceComponent(params: {\n designator: string\n libraryReference: string\n manufacturerPartNumber?: string\n pinCount: number\n sourceComponentId: string\n value: string\n}): AnyCircuitElement {\n const {\n designator,\n libraryReference,\n manufacturerPartNumber,\n pinCount,\n sourceComponentId,\n value,\n } = params\n const classification = classifyComponent({ designator, libraryReference })\n const primaryValue = getPrimaryComponentValue(value)\n const common = {\n type: \"source_component\" as const,\n display_name: designator,\n display_value: value || undefined,\n manufacturer_part_number: manufacturerPartNumber,\n name: designator,\n source_component_id: sourceComponentId,\n }\n\n if (classification === \"resistor\") {\n const parsed = source_simple_resistor.safeParse({\n ...common,\n display_resistance: value || undefined,\n ftype: \"simple_resistor\",\n resistance: primaryValue || 0,\n })\n if (parsed.success) return parsed.data\n }\n if (classification === \"capacitor\") {\n const parsed = source_simple_capacitor.safeParse({\n ...common,\n display_capacitance: value || undefined,\n ftype: \"simple_capacitor\",\n capacitance: primaryValue || 0,\n })\n if (parsed.success) return parsed.data\n }\n if (classification === \"inductor\") {\n const parsed = source_simple_inductor.safeParse({\n ...common,\n display_inductance: value || undefined,\n ftype: \"simple_inductor\",\n inductance: primaryValue || 0,\n })\n if (parsed.success) return parsed.data\n }\n if (classification === \"crystal\" && (pinCount === 2 || pinCount === 4)) {\n const frequency = parseAndConvertSiUnit(value, \"Hz\").value\n if (typeof frequency === \"number\" && Number.isFinite(frequency)) {\n const parsed = source_simple_crystal.safeParse({\n ...common,\n frequency,\n ftype: \"simple_crystal\",\n pin_variant: pinCount === 4 ? \"four_pin\" : \"two_pin\",\n })\n if (parsed.success) return parsed.data\n }\n }\n if (classification === \"mosfet\" && pinCount >= 3) {\n const parsed = source_simple_mosfet.safeParse({\n ...common,\n ...getMosfetVariant(libraryReference),\n ftype: \"simple_mosfet\",\n })\n if (parsed.success) return parsed.data\n }\n\n const ftype:\n | \"simple_chip\"\n | \"simple_diode\"\n | \"simple_led\"\n | \"simple_test_point\" =\n classification === \"diode\"\n ? \"simple_diode\"\n : classification === \"led\"\n ? \"simple_led\"\n : classification === \"testpoint\"\n ? \"simple_test_point\"\n : \"simple_chip\"\n return {\n ...common,\n ftype,\n } satisfies SourceComponentBase\n}\n\nfunction createComponentText(params: {\n anchor: SchematicText[\"anchor\"]\n component: SchematicComponent\n id: string\n position: AltiumPoint\n text: string\n}): SchematicText {\n const { anchor, component, id, position, text } = params\n return {\n type: \"schematic_text\",\n anchor,\n color: \"#006464\",\n font_size: 0.18,\n position,\n rotation: 0,\n schematic_component_id: component.schematic_component_id,\n schematic_sheet_id: component.schematic_sheet_id,\n schematic_text_id: id,\n text,\n }\n}\n\n/**\n * Altium permits labels and pin hot spots to land anywhere on a wire segment,\n * not only on declared polyline vertices. Build the electrical graph with\n * those geometric joins so Circuit JSON source traces carry the real ports and\n * net names. Mid-segment crossings remain disconnected unless one wire has a\n * vertex there or Altium emits an explicit junction record.\n */\nfunction buildSemanticNetGraph(\n document: AltiumSchDoc,\n convertedPorts: ConvertedPort[],\n): SemanticNetGraph {\n const disjointSet = new PointDisjointSet()\n const pointValues = new Map<string, AltiumPoint>()\n const wireRecords = document.records.filter(\n (record) => record.recordKind === \"27\",\n )\n const segments: Array<{ end: AltiumPoint; start: AltiumPoint }> = []\n\n for (const wire of wireRecords) {\n const points = getSchematicRecordPoints(wire)\n for (const point of points) {\n addGraphPoint(disjointSet, pointValues, point)\n }\n for (let index = 1; index < points.length; index++) {\n const start = points[index - 1]\n const end = points[index]\n if (!start || !end) continue\n disjointSet.union(pointKey(start), pointKey(end))\n segments.push({ end, start })\n }\n }\n\n const positionedRecords = document.records.flatMap((record) => {\n if (![\"4\", \"17\", \"18\", \"25\", \"29\"].includes(record.recordKind ?? \"\")) {\n return []\n }\n const point = getLocation(record)\n return point ? [{ point, record }] : []\n })\n const positionedPins = convertedPorts.map(({ point, record }) => ({\n point,\n record,\n }))\n const joinPoints = [\n ...new Map(\n wireRecords\n .flatMap((wire) => getSchematicRecordPoints(wire))\n .map((point) => [pointKey(point), point]),\n ).values(),\n ...positionedRecords.map(({ point }) => point),\n ...positionedPins.map(({ point }) => point),\n ]\n\n for (const point of joinPoints) {\n addGraphPoint(disjointSet, pointValues, point)\n for (const segment of segments) {\n if (isPointOnSegment(point, segment.start, segment.end)) {\n disjointSet.union(pointKey(point), pointKey(segment.start))\n }\n }\n }\n\n interface MutableSemanticNet {\n id: string\n names: Set<string>\n points: Map<string, AltiumPoint>\n records: Set<AltiumRecord>\n }\n const groupedByRoot = new Map<string, MutableSemanticNet>()\n const getGroup = (point: AltiumPoint): MutableSemanticNet => {\n const root = disjointSet.find(pointKey(point))\n const existing = groupedByRoot.get(root)\n if (existing) return existing\n const created: MutableSemanticNet = {\n id: root,\n names: new Set(),\n points: new Map(),\n records: new Set(),\n }\n groupedByRoot.set(root, created)\n return created\n }\n\n for (const point of pointValues.values()) {\n getGroup(point).points.set(pointKey(point), point)\n }\n for (const wire of wireRecords) {\n const firstPoint = getSchematicRecordPoints(wire)[0]\n if (firstPoint) getGroup(firstPoint).records.add(wire)\n }\n for (const { point, record } of [...positionedRecords, ...positionedPins]) {\n const group = getGroup(point)\n group.records.add(record)\n const name = getElectricalRecordName(record)\n if (name) group.names.add(name)\n }\n\n const connectedWiresByRecord = new Map<AltiumRecord, AltiumRecord[]>()\n for (const group of groupedByRoot.values()) {\n const wires = [...group.records].filter(\n (record) => record.recordKind === \"27\",\n )\n for (const record of group.records) {\n connectedWiresByRecord.set(record, wires)\n }\n }\n\n const mergedGroups: MutableSemanticNet[] = []\n for (const group of groupedByRoot.values()) {\n if (group.records.size === 0) continue\n const normalizedNames = new Set(\n [...group.names].map((name) => name.trim().toUpperCase()),\n )\n const matches = mergedGroups.filter((candidate) =>\n [...candidate.names].some((name) =>\n normalizedNames.has(name.trim().toUpperCase()),\n ),\n )\n if (matches.length === 0 || normalizedNames.size === 0) {\n mergedGroups.push(group)\n continue\n }\n const target = matches[0]\n if (!target) continue\n mergeSemanticNetGroup(target, group)\n for (const duplicate of matches.slice(1)) {\n mergeSemanticNetGroup(target, duplicate)\n const duplicateIndex = mergedGroups.indexOf(duplicate)\n if (duplicateIndex >= 0) mergedGroups.splice(duplicateIndex, 1)\n }\n }\n\n const nets: SemanticNet[] = mergedGroups.map((group) => ({\n id: group.id,\n names: [...group.names],\n points: [...group.points.values()],\n records: [...group.records],\n }))\n return {\n getConnectedWiresForRecord: (record) =>\n connectedWiresByRecord.get(record) ?? [],\n nets,\n }\n}\n\nfunction addGraphPoint(\n disjointSet: PointDisjointSet,\n pointValues: Map<string, AltiumPoint>,\n point: AltiumPoint,\n): void {\n const key = pointKey(point)\n disjointSet.add(key)\n pointValues.set(key, point)\n}\n\nfunction getElectricalRecordName(record: AltiumRecord): string | undefined {\n if (record.recordKind === \"18\") return record.getDecoded(\"NAME\")\n if ([\"4\", \"17\", \"25\"].includes(record.recordKind ?? \"\")) {\n return record.getDecoded(\"TEXT\")\n }\n return undefined\n}\n\nfunction mergeSemanticNetGroup(\n target: {\n names: Set<string>\n points: Map<string, AltiumPoint>\n records: Set<AltiumRecord>\n },\n source: {\n names: Set<string>\n points: Map<string, AltiumPoint>\n records: Set<AltiumRecord>\n },\n): void {\n for (const name of source.names) target.names.add(name)\n for (const [key, point] of source.points) target.points.set(key, point)\n for (const record of source.records) target.records.add(record)\n}\n\nfunction isPointOnSegment(\n point: AltiumPoint,\n start: AltiumPoint,\n end: AltiumPoint,\n): boolean {\n const dx = end.x - start.x\n const dy = end.y - start.y\n const cross = (point.x - start.x) * dy - (point.y - start.y) * dx\n const tolerance = 0.000001 * Math.max(Math.abs(dx), Math.abs(dy), 1)\n if (Math.abs(cross) > tolerance) return false\n const dot = (point.x - start.x) * dx + (point.y - start.y) * dy\n if (dot < -tolerance) return false\n const lengthSquared = dx * dx + dy * dy\n return dot <= lengthSquared + tolerance\n}\n\nfunction splitSegmentAtPoints(\n start: AltiumPoint,\n end: AltiumPoint,\n candidates: AltiumPoint[],\n): AltiumPoint[] {\n const dx = end.x - start.x\n const dy = end.y - start.y\n const lengthSquared = dx * dx + dy * dy\n if (lengthSquared === 0) return [start]\n\n const pointsByKey = new Map<string, AltiumPoint>([\n [pointKey(start), start],\n [pointKey(end), end],\n ])\n for (const candidate of candidates) {\n if (isPointOnSegment(candidate, start, end)) {\n pointsByKey.set(pointKey(candidate), candidate)\n }\n }\n return [...pointsByKey.values()].sort((left, right) => {\n const leftDistance = (left.x - start.x) * dx + (left.y - start.y) * dy\n const rightDistance = (right.x - start.x) * dx + (right.y - start.y) * dy\n return leftDistance - rightDistance\n })\n}\n\nclass PointDisjointSet {\n private readonly parent = new Map<string, string>()\n\n add(value: string): void {\n if (!this.parent.has(value)) this.parent.set(value, value)\n }\n\n find(value: string): string {\n this.add(value)\n const parent = this.parent.get(value) ?? value\n if (parent === value) return value\n const root = this.find(parent)\n this.parent.set(value, root)\n return root\n }\n\n union(left: string, right: string): void {\n const leftRoot = this.find(left)\n const rightRoot = this.find(right)\n if (leftRoot !== rightRoot) this.parent.set(rightRoot, leftRoot)\n }\n}\n\ninterface ConnectivityConversion {\n sourceNetIdByRecord: Map<AltiumRecord, string>\n sourceNetIdByName: Map<string, string>\n schematicTraceIdByRecord: Map<AltiumRecord, string>\n}\n\nfunction convertConnectivity(params: {\n convertedPorts: ConvertedPort[]\n document: AltiumSchDoc\n elements: AnyCircuitElement[]\n handledRecords: Set<AltiumRecord>\n options: SemanticSchematicOptions\n semanticNetGraph: SemanticNetGraph\n}): ConnectivityConversion {\n const {\n convertedPorts,\n document,\n elements,\n handledRecords,\n options,\n semanticNetGraph: graph,\n } = params\n const sourceNetIdByName = new Map<string, string>()\n const sourceNetIdByRecord = new Map<AltiumRecord, string>()\n const schematicTraceIdByRecord = new Map<AltiumRecord, string>()\n const portsByPoint = groupByPoint(convertedPorts)\n\n for (const [netIndex, net] of graph.nets.entries()) {\n const wires = net.records.filter((record) => record.recordKind === \"27\")\n const connectedConvertedPorts = uniqueConvertedPorts(\n net.points.flatMap((point) => portsByPoint.get(pointKey(point)) ?? []),\n )\n const connectedPorts = connectedConvertedPorts.map(\n ({ sourcePort }) => sourcePort.source_port_id,\n )\n if (\n wires.length === 0 &&\n !(\n (net.names.length > 0 && connectedPorts.length > 0) ||\n connectedPorts.length > 1\n )\n ) {\n continue\n }\n const sourceNetIds = net.names.map((name) =>\n getOrCreateSourceNet({\n elements,\n name,\n sourceNetIdByName,\n }),\n )\n for (const record of net.records) {\n const firstSourceNetId = sourceNetIds[0]\n if (firstSourceNetId) sourceNetIdByRecord.set(record, firstSourceNetId)\n }\n\n const sourceTraceId = `source_trace_altium_${netIndex}`\n const sourceTrace: SourceTrace = {\n type: \"source_trace\",\n connected_source_net_ids: sourceNetIds,\n connected_source_port_ids: connectedPorts,\n display_name: net.names[0],\n name: net.names[0],\n source_trace_id: sourceTraceId,\n }\n elements.push(sourceTrace)\n\n const netJunctions = document.records\n .filter(\n (record) =>\n record.recordKind === \"29\" &&\n net.points.some((point) => pointsEqual(point, getLocation(record))),\n )\n .flatMap((record) => {\n handledRecords.add(record)\n const location = getLocation(record)\n return location ? [scalePoint(location, options.scale)] : []\n })\n\n for (const wire of wires) handledRecords.add(wire)\n const prunedSegmentKeys = getEquivalentPortPrunedSegmentKeys({\n convertedPorts: connectedConvertedPorts,\n net,\n wires,\n })\n let renderedWireIndex = 0\n for (const wire of wires) {\n const wireRecordIndex = document.records.indexOf(wire)\n const schematicTraceId = `schematic_trace_altium_${wireRecordIndex}`\n const points = getSchematicRecordPoints(wire)\n const edges: SchematicTrace[\"edges\"] = []\n for (let pointIndex = 1; pointIndex < points.length; pointIndex++) {\n const from = points[pointIndex - 1]\n const to = points[pointIndex]\n if (!from || !to) continue\n const segmentPoints = splitSegmentAtPoints(from, to, net.points)\n for (\n let segmentPointIndex = 1;\n segmentPointIndex < segmentPoints.length;\n segmentPointIndex++\n ) {\n const segmentFrom = segmentPoints[segmentPointIndex - 1]\n const segmentTo = segmentPoints[segmentPointIndex]\n if (!segmentFrom || !segmentTo) continue\n if (prunedSegmentKeys.has(segmentKey(segmentFrom, segmentTo))) {\n continue\n }\n const fromPort = portsByPoint\n .get(pointKey(segmentFrom))\n ?.find((port) => port.isSchematicVisible)\n const toPort = portsByPoint\n .get(pointKey(segmentTo))\n ?.find((port) => port.isSchematicVisible)\n const fromPortId = getPortIdAtElectricalPoint(\n fromPort,\n segmentFrom,\n options.scale,\n )\n const toPortId = getPortIdAtElectricalPoint(\n toPort,\n segmentTo,\n options.scale,\n )\n edges.push({\n from: scalePoint(segmentFrom, options.scale),\n to: scalePoint(segmentTo, options.scale),\n ...(fromPortId ? { from_schematic_port_id: fromPortId } : {}),\n ...(toPortId ? { to_schematic_port_id: toPortId } : {}),\n })\n }\n }\n if (edges.length === 0) continue\n schematicTraceIdByRecord.set(wire, schematicTraceId)\n elements.push({\n type: \"schematic_trace\",\n edges,\n junctions: renderedWireIndex === 0 ? netJunctions : [],\n schematic_sheet_id: options.schematicSheetId,\n schematic_trace_id: schematicTraceId,\n source_trace_id: sourceTraceId,\n } satisfies SchematicTrace)\n renderedWireIndex++\n }\n\n for (const convertedPort of connectedConvertedPorts) {\n if (!convertedPort.isSchematicVisible) continue\n const electricalTerminal = scalePoint(convertedPort.point, options.scale)\n if (pointsEqual(convertedPort.schematicPort.center, electricalTerminal)) {\n continue\n }\n const portRecordIndex = document.records.indexOf(convertedPort.record)\n elements.push({\n type: \"schematic_trace\",\n edges: createPortLeadEdges(convertedPort, electricalTerminal),\n junctions: [],\n schematic_sheet_id: options.schematicSheetId,\n schematic_trace_id: `schematic_trace_altium_port_lead_${portRecordIndex}`,\n source_trace_id: sourceTraceId,\n } satisfies SchematicTrace)\n }\n\n const connectedPortIds = new Set(connectedPorts)\n for (const convertedPort of convertedPorts) {\n if (\n convertedPort.isSchematicVisible &&\n connectedPortIds.has(convertedPort.sourcePort.source_port_id)\n ) {\n convertedPort.schematicPort.is_connected = true\n }\n }\n }\n\n return {\n schematicTraceIdByRecord,\n sourceNetIdByName,\n sourceNetIdByRecord,\n }\n}\n\nfunction getEquivalentPortPrunedSegmentKeys(params: {\n convertedPorts: ConvertedPort[]\n net: SemanticNet\n wires: AltiumRecord[]\n}): Set<string> {\n const { convertedPorts, net, wires } = params\n const hiddenPortPoints = convertedPorts\n .filter((port) => !port.isSchematicVisible)\n .map((port) => port.point)\n if (hiddenPortPoints.length === 0) return new Set()\n\n const protectedPointKeys = new Set(\n convertedPorts\n .filter((port) => port.isSchematicVisible)\n .map((port) => pointKey(port.point)),\n )\n for (const record of net.records) {\n if (![\"4\", \"17\", \"18\", \"25\"].includes(record.recordKind ?? \"\")) continue\n const location = getLocation(record)\n if (location) protectedPointKeys.add(pointKey(location))\n }\n\n interface PrunableSegment {\n endKey: string\n key: string\n startKey: string\n }\n const segments = new Map<string, PrunableSegment>()\n const segmentKeysByPoint = new Map<string, Set<string>>()\n const addIncidentSegment = (point: AltiumPoint, key: string): void => {\n const pointSegments = segmentKeysByPoint.get(pointKey(point))\n if (pointSegments) pointSegments.add(key)\n else segmentKeysByPoint.set(pointKey(point), new Set([key]))\n }\n\n for (const wire of wires) {\n const wirePoints = getSchematicRecordPoints(wire)\n for (let pointIndex = 1; pointIndex < wirePoints.length; pointIndex++) {\n const from = wirePoints[pointIndex - 1]\n const to = wirePoints[pointIndex]\n if (!from || !to) continue\n const segmentPoints = splitSegmentAtPoints(from, to, net.points)\n for (\n let splitIndex = 1;\n splitIndex < segmentPoints.length;\n splitIndex++\n ) {\n const segmentFrom = segmentPoints[splitIndex - 1]\n const segmentTo = segmentPoints[splitIndex]\n if (!segmentFrom || !segmentTo) continue\n const key = segmentKey(segmentFrom, segmentTo)\n segments.set(key, {\n endKey: pointKey(segmentTo),\n key,\n startKey: pointKey(segmentFrom),\n })\n addIncidentSegment(segmentFrom, key)\n addIncidentSegment(segmentTo, key)\n }\n }\n }\n\n const removedSegmentKeys = new Set<string>()\n const pendingPointKeys = hiddenPortPoints.map((point) => pointKey(point))\n while (pendingPointKeys.length > 0) {\n const currentPointKey = pendingPointKeys.shift()\n if (!currentPointKey || protectedPointKeys.has(currentPointKey)) continue\n const activeSegmentKeys = [\n ...(segmentKeysByPoint.get(currentPointKey) ?? []),\n ].filter((key) => !removedSegmentKeys.has(key))\n if (activeSegmentKeys.length !== 1) continue\n const segment = segments.get(activeSegmentKeys[0] ?? \"\")\n if (!segment) continue\n removedSegmentKeys.add(segment.key)\n pendingPointKeys.push(\n segment.startKey === currentPointKey ? segment.endKey : segment.startKey,\n )\n }\n return removedSegmentKeys\n}\n\nfunction segmentKey(start: AltiumPoint, end: AltiumPoint): string {\n const startKey = pointKey(start)\n const endKey = pointKey(end)\n return startKey < endKey ? `${startKey}|${endKey}` : `${endKey}|${startKey}`\n}\n\nfunction createPortLeadEdges(\n convertedPort: ConvertedPort,\n electricalTerminal: AltiumPoint,\n): SchematicTrace[\"edges\"] {\n const portCenter = convertedPort.schematicPort.center\n const facingDirection =\n convertedPort.schematicPort.facing_direction ?? \"right\"\n const elbow =\n facingDirection === \"left\" || facingDirection === \"right\"\n ? { x: electricalTerminal.x, y: portCenter.y }\n : { x: portCenter.x, y: electricalTerminal.y }\n const points = [portCenter, elbow, electricalTerminal].filter(\n (point, index, allPoints) =>\n index === 0 || !pointsEqual(point, allPoints[index - 1]),\n )\n\n return points.slice(1).flatMap((to, index) => {\n const from = points[index]\n if (!from) return []\n return [\n {\n from,\n ...(index === 0\n ? {\n from_schematic_port_id:\n convertedPort.schematicPort.schematic_port_id,\n }\n : {}),\n to,\n },\n ]\n })\n}\n\nfunction convertNetLabels(params: {\n connectivity: ConnectivityConversion\n document: AltiumSchDoc\n elements: AnyCircuitElement[]\n handledRecords: Set<AltiumRecord>\n options: SemanticSchematicOptions\n semanticNetGraph: SemanticNetGraph\n}): void {\n const {\n connectivity,\n document,\n elements,\n handledRecords,\n options,\n semanticNetGraph: graph,\n } = params\n\n for (const [recordIndex, record] of document.records.entries()) {\n const recordKind = record.recordKind\n if (!recordKind || ![\"4\", \"17\", \"18\", \"25\"].includes(recordKind)) {\n continue\n }\n if (record.getBoolean(\"ISHIDDEN\") && options.includeHidden !== true) {\n handledRecords.add(record)\n continue\n }\n const name =\n record.recordKind === \"18\"\n ? record.getDecoded(\"NAME\")\n : record.getDecoded(\"TEXT\")\n const location = getLocation(record)\n if (!name || !location) continue\n const wire = graph.getConnectedWiresForRecord(record)[0]\n // Altium's generic label record is also used for page titles and notes.\n // It is only an electrical net label when it touches a wire.\n if (recordKind === \"4\" && !wire) continue\n handledRecords.add(record)\n\n const sourceNetId =\n connectivity.sourceNetIdByRecord.get(record) ??\n getOrCreateSourceNet({\n elements,\n name,\n sourceNetIdByName: connectivity.sourceNetIdByName,\n })\n const schematicTraceId = wire\n ? connectivity.schematicTraceIdByRecord.get(wire)\n : undefined\n const direction = getRecordDirection(record)\n const symbolName =\n record.recordKind === \"17\"\n ? getPowerPortSymbolName(record, direction)\n : undefined\n const schematicNetLabel: SchematicNetLabel = {\n type: \"schematic_net_label\",\n anchor_position: scalePoint(location, options.scale),\n anchor_side:\n record.recordKind === \"18\" || record.recordKind === \"4\"\n ? \"left\"\n : directionToOppositeSide(direction),\n center: scalePoint(location, options.scale),\n schematic_net_label_id: `schematic_net_label_altium_${recordIndex}`,\n schematic_sheet_id: options.schematicSheetId,\n source_net_id: sourceNetId,\n text: name,\n ...(schematicTraceId ? { schematic_trace_id: schematicTraceId } : {}),\n ...(symbolName ? { symbol_name: symbolName } : {}),\n }\n elements.push(schematicNetLabel)\n }\n}\n\nfunction getOrCreateSourceNet(params: {\n elements: AnyCircuitElement[]\n name: string\n sourceNetIdByName: Map<string, string>\n}): string {\n const { elements, name, sourceNetIdByName } = params\n const normalizedName = name.trim().toUpperCase()\n const existing = sourceNetIdByName.get(normalizedName)\n if (existing) return existing\n\n const sourceNetIdBase = `source_net_altium_${sanitizeId(name)}`\n const existingIds = new Set(\n elements.flatMap((element) =>\n element.type === \"source_net\" ? [element.source_net_id] : [],\n ),\n )\n let sourceNetId = sourceNetIdBase\n let suffix = 2\n while (existingIds.has(sourceNetId)) {\n sourceNetId = `${sourceNetIdBase}_${suffix}`\n suffix++\n }\n const sourceNet: SourceNet = {\n type: \"source_net\",\n is_ground: isGroundNet(name),\n is_power: isPowerNet(name),\n member_source_group_ids: [],\n name,\n source_net_id: sourceNetId,\n }\n elements.push(sourceNet)\n sourceNetIdByName.set(normalizedName, sourceNetId)\n return sourceNetId\n}\n\nfunction selectCircuitJsonSymbol(params: {\n designator: string\n libraryReference: string\n ports: ConvertedPort[]\n}): SymbolSelection | undefined {\n const { designator, libraryReference, ports } = params\n const classification = classifyComponent({ designator, libraryReference })\n let baseName: string | undefined\n let candidateNames: string[] = []\n if (classification === \"testpoint\" && ports.length === 1) {\n baseName = \"testpoint\"\n } else if (classification === \"crystal\" && ports.length === 2) {\n baseName = \"crystal\"\n } else if (classification === \"crystal\" && ports.length === 4) {\n baseName = \"crystal_4pin\"\n } else if (\n classification === \"mosfet\" &&\n ports.length >= 3 &&\n hasCompleteMosfetFunctionalGroups(ports)\n ) {\n const { channel_type, mosfet_mode } = getMosfetVariant(libraryReference)\n const channel = channel_type === \"p\" ? \"p\" : \"n\"\n const mode = mosfet_mode === \"depletion\" ? \"d\" : \"e\"\n const prefix = `${channel}_channel_${mode}_mosfet_transistor_gate_`\n candidateNames = SYMBOL_NAMES.filter((name) => name.startsWith(prefix))\n } else if (ports.length !== 2) {\n return undefined\n } else if (classification === \"resistor\") {\n baseName = \"boxresistor\"\n } else if (classification === \"capacitor\") {\n baseName = isPolarizedCapacitor(libraryReference)\n ? \"capacitor_polarized\"\n : \"capacitor\"\n } else if (classification === \"ferrite_bead\") {\n baseName = \"ferrite_bead\"\n } else if (classification === \"inductor\") {\n baseName = \"inductor\"\n } else if (classification === \"led\") {\n baseName = \"led\"\n }\n if (classification === \"diode\") {\n const lower = libraryReference.toLowerCase()\n baseName = lower.includes(\"schottky\") ? \"schottky_diode\" : \"diode\"\n }\n if (baseName) {\n candidateNames = CARDINAL_DIRECTIONS.map(\n (direction) => `${baseName}_${direction}`,\n )\n }\n if (candidateNames.length === 0) return undefined\n\n const selections = candidateNames.flatMap((name) => {\n const symbol = SYMBOL_CATALOG[name]\n const supportsEquivalentMosfetPads =\n classification === \"mosfet\" && symbol?.ports.length === 3\n if (\n !symbol ||\n (!supportsEquivalentMosfetPads && symbol.ports.length !== ports.length)\n ) {\n return []\n }\n const assignments = assignConvertedPortsToSymbolPorts(ports, symbol, {\n allowFunctionalPortReuse: classification === \"mosfet\",\n geometryInterchangeableLabels:\n classification === \"crystal\" && ports.length === 4\n ? new Set([\"2\", \"4\"])\n : undefined,\n })\n return assignments.length === ports.length\n ? [{ assignments, name, symbol } satisfies SymbolSelection]\n : []\n })\n return selections.sort(\n (left, right) =>\n getSymbolDirectionScore(left) - getSymbolDirectionScore(right),\n )[0]\n}\n\nfunction hasCompleteMosfetFunctionalGroups(ports: ConvertedPort[]): boolean {\n const groups = ports.map((port) =>\n normalizeFunctionalPortLabel(port.sourcePort.name),\n )\n return (\n groups.every((group) => group !== undefined) && new Set(groups).size === 3\n )\n}\n\nfunction assignConvertedPortsToSymbolPorts(\n ports: ConvertedPort[],\n symbol: SchSymbol,\n options: {\n allowFunctionalPortReuse?: boolean\n geometryInterchangeableLabels?: Set<string>\n } = {},\n): SymbolPortAssignment[] {\n const unusedSymbolPorts = new Set(symbol.ports)\n const orderedPorts = [...ports].sort(compareConvertedPorts)\n const assignments: SymbolPortAssignment[] = []\n const convertedCenter = getAveragePoint(ports.map(({ point }) => point))\n\n for (const [portIndex, convertedPort] of orderedPorts.entries()) {\n const rawHints = [\n convertedPort.schematicPort.pin_number?.toString(),\n convertedPort.sourcePort.name,\n ...(convertedPort.sourcePort.port_hints ?? []),\n ].filter((hint): hint is string => Boolean(hint))\n const functionalHints = new Set(\n rawHints.flatMap((hint) => {\n const normalized = normalizeFunctionalPortLabel(hint)\n return normalized ? [normalized] : []\n }),\n )\n const functionalPortCandidates = options.allowFunctionalPortReuse\n ? symbol.ports\n : [...unusedSymbolPorts]\n const functionalSymbolPort = functionalPortCandidates.find((symbolPort) =>\n symbolPort.labels.some((label) => {\n const normalized = normalizeFunctionalPortLabel(label)\n return normalized ? functionalHints.has(normalized) : false\n }),\n )\n const exactHints = new Set(rawHints.map((hint) => hint.toLowerCase()))\n const exactSymbolPort = [...unusedSymbolPorts].find((symbolPort) =>\n symbolPort.labels.some((label) => exactHints.has(label.toLowerCase())),\n )\n const interchangeableLabels = options.geometryInterchangeableLabels\n const isGeometryInterchangeable = rawHints.some((hint) =>\n interchangeableLabels?.has(hint.toLowerCase()),\n )\n const geometrySymbolPort = isGeometryInterchangeable\n ? [...unusedSymbolPorts]\n .filter((symbolPort) =>\n symbolPort.labels.some((label) =>\n interchangeableLabels?.has(label.toLowerCase()),\n ),\n )\n .sort(\n (left, right) =>\n getVectorDifference(\n subtractPoints(convertedPort.point, convertedCenter),\n subtractPoints(left, symbol.center),\n ) -\n getVectorDifference(\n subtractPoints(convertedPort.point, convertedCenter),\n subtractPoints(right, symbol.center),\n ),\n )[0]\n : undefined\n const symbolPort =\n functionalSymbolPort ??\n geometrySymbolPort ??\n exactSymbolPort ??\n symbol.ports[portIndex] ??\n [...unusedSymbolPorts][0]\n if (!symbolPort) continue\n if (!functionalSymbolPort || !options.allowFunctionalPortReuse) {\n unusedSymbolPorts.delete(symbolPort)\n }\n assignments.push({ convertedPort, symbolPort })\n }\n return assignments\n}\n\nfunction getAveragePoint(points: AltiumPoint[]): AltiumPoint {\n if (points.length === 0) return { x: 0, y: 0 }\n return {\n x: points.reduce((sum, point) => sum + point.x, 0) / points.length,\n y: points.reduce((sum, point) => sum + point.y, 0) / points.length,\n }\n}\n\nfunction compareConvertedPorts(\n left: ConvertedPort,\n right: ConvertedPort,\n): number {\n const leftPinNumber = left.schematicPort.pin_number\n const rightPinNumber = right.schematicPort.pin_number\n if (leftPinNumber !== undefined && rightPinNumber !== undefined) {\n return leftPinNumber - rightPinNumber\n }\n return (\n (left.schematicPort.true_ccw_index ?? 0) -\n (right.schematicPort.true_ccw_index ?? 0)\n )\n}\n\nfunction getSymbolDirectionScore(selection: SymbolSelection): number {\n const [first, second] = selection.assignments\n if (!first) return Number.POSITIVE_INFINITY\n if (!second) {\n const expectedDirection =\n VECTOR_BY_DIRECTION[\n first.convertedPort.schematicPort.facing_direction ?? \"right\"\n ]\n return getVectorDifference(\n expectedDirection,\n subtractPoints(first.symbolPort, selection.symbol.center),\n )\n }\n let difference = 0\n let comparisonCount = 0\n for (\n let firstIndex = 0;\n firstIndex < selection.assignments.length;\n firstIndex++\n ) {\n for (\n let secondIndex = firstIndex + 1;\n secondIndex < selection.assignments.length;\n secondIndex++\n ) {\n const firstAssignment = selection.assignments[firstIndex]\n const secondAssignment = selection.assignments[secondIndex]\n if (!firstAssignment || !secondAssignment) continue\n const pairDifference = getVectorDifference(\n subtractPoints(\n secondAssignment.convertedPort.point,\n firstAssignment.convertedPort.point,\n ),\n subtractPoints(secondAssignment.symbolPort, firstAssignment.symbolPort),\n )\n if (!Number.isFinite(pairDifference)) continue\n difference += pairDifference\n comparisonCount++\n }\n }\n return comparisonCount > 0\n ? difference / comparisonCount\n : Number.POSITIVE_INFINITY\n}\n\nfunction normalizeFunctionalPortLabel(value: string): string | undefined {\n const normalized = value.toLowerCase().replace(/[^a-z]/gu, \"\")\n if (normalized === \"g\" || normalized === \"gate\") return \"gate\"\n if (normalized === \"d\" || normalized === \"drain\") return \"drain\"\n if (normalized === \"s\" || normalized === \"source\") return \"source\"\n return undefined\n}\n\nfunction getVectorDifference(left: AltiumPoint, right: AltiumPoint): number {\n const leftLength = Math.hypot(left.x, left.y)\n const rightLength = Math.hypot(right.x, right.y)\n if (leftLength === 0 || rightLength === 0) {\n return Number.POSITIVE_INFINITY\n }\n const cosine =\n (left.x * right.x + left.y * right.y) / (leftLength * rightLength)\n return 1 - Math.max(-1, Math.min(1, cosine))\n}\n\nfunction applyNativeSymbolPortGeometry(params: {\n center: AltiumPoint\n selection: SymbolSelection\n}): void {\n const { center, selection } = params\n const assignmentsBySymbolPort = new Map<\n SchSymbol[\"ports\"][number],\n SymbolPortAssignment[]\n >()\n for (const assignment of selection.assignments) {\n const assignments = assignmentsBySymbolPort.get(assignment.symbolPort)\n if (assignments) assignments.push(assignment)\n else assignmentsBySymbolPort.set(assignment.symbolPort, [assignment])\n }\n\n for (const [symbolPort, assignments] of assignmentsBySymbolPort) {\n const offset = subtractPoints(symbolPort, selection.symbol.center)\n const direction = getDirectionForVector(offset)\n const symbolPortCenter = {\n x: center.x + offset.x,\n y: center.y + offset.y,\n }\n const representative = assignments.sort(\n (left, right) =>\n getPointDistance(\n left.convertedPort.schematicPort.center,\n symbolPortCenter,\n ) -\n getPointDistance(\n right.convertedPort.schematicPort.center,\n symbolPortCenter,\n ),\n )[0]\n for (const { convertedPort } of assignments) {\n convertedPort.isSchematicVisible =\n convertedPort === representative?.convertedPort\n convertedPort.schematicPort.center = symbolPortCenter\n convertedPort.schematicPort.distance_from_component_edge = Math.hypot(\n offset.x,\n offset.y,\n )\n convertedPort.schematicPort.facing_direction = direction\n convertedPort.schematicPort.side_of_component = directionToSide(direction)\n }\n }\n}\n\nfunction getPointDistance(left: AltiumPoint, right: AltiumPoint): number {\n return Math.hypot(left.x - right.x, left.y - right.y)\n}\n\nfunction getDirectionForVector(vector: AltiumPoint): CardinalDirection {\n if (Math.abs(vector.x) >= Math.abs(vector.y)) {\n return vector.x >= 0 ? \"right\" : \"left\"\n }\n return vector.y >= 0 ? \"up\" : \"down\"\n}\n\nfunction subtractPoints(\n left: { x: number; y: number },\n right: { x: number; y: number },\n): AltiumPoint {\n return { x: left.x - right.x, y: left.y - right.y }\n}\n\nfunction classifyComponent(params: {\n designator: string\n libraryReference: string\n}):\n | \"capacitor\"\n | \"crystal\"\n | \"diode\"\n | \"ferrite_bead\"\n | \"inductor\"\n | \"led\"\n | \"mosfet\"\n | \"resistor\"\n | \"testpoint\"\n | \"unknown\" {\n const { designator, libraryReference } = params\n const prefix = designator.match(/^[A-Z]+/iu)?.[0]?.toUpperCase() ?? \"\"\n const lowerReference = libraryReference.toLowerCase()\n if (prefix === \"TP\" || lowerReference.includes(\"testpoint\")) {\n return \"testpoint\"\n }\n if (\n prefix === \"Y\" ||\n lowerReference.includes(\"crystal\") ||\n /(?:^|[_-])cry(?:\\d|[_-]|$)/iu.test(libraryReference)\n ) {\n return \"crystal\"\n }\n if (lowerReference.includes(\"mosfet\")) return \"mosfet\"\n if (\n prefix === \"FB\" ||\n prefix === \"FL\" ||\n lowerReference.includes(\"ferrite\") ||\n lowerReference.includes(\"emifilter_ind\")\n ) {\n return \"ferrite_bead\"\n }\n if (prefix === \"LED\" || lowerReference.includes(\"led\")) return \"led\"\n if (prefix === \"R\" || lowerReference.includes(\"resistor\")) return \"resistor\"\n if (prefix === \"C\" || /(?:^|[_-])cap(?:[_-]|$)/iu.test(libraryReference)) {\n return \"capacitor\"\n }\n if (prefix === \"L\" || lowerReference.includes(\"inductor\")) return \"inductor\"\n if (prefix === \"D\" || lowerReference.includes(\"diode\")) return \"diode\"\n return \"unknown\"\n}\n\nfunction getMosfetVariant(libraryReference: string): {\n channel_type: \"n\" | \"p\"\n mosfet_mode: \"depletion\" | \"enhancement\"\n} {\n const lowerReference = libraryReference.toLowerCase()\n const isPChannel =\n /(?:^|[_-])p(?:channel)?(?:[_-]|$)/iu.test(libraryReference) ||\n lowerReference.includes(\"pmos\") ||\n lowerReference.includes(\"csd25\")\n return {\n channel_type: isPChannel ? \"p\" : \"n\",\n mosfet_mode: lowerReference.includes(\"depletion\")\n ? \"depletion\"\n : \"enhancement\",\n }\n}\n\nfunction isPolarizedCapacitor(libraryReference: string): boolean {\n return /(?:^|[_-])cap(?:acitor)?[_-]?pol(?:arized)?(?:[_-]|$)/iu.test(\n libraryReference,\n )\n}\n\nfunction getPrimaryComponentValue(value: string): string {\n return value.split(/[_/\\s]+/u).find(Boolean) ?? value\n}\n\nfunction getPowerPortSymbolName(\n record: AltiumRecord,\n direction: CardinalDirection,\n): string {\n const style = Math.round(record.getNumber(\"STYLE\") ?? 2)\n if (style === 4) return `digital_ground_${direction}`\n if (style === 5) return `ground_${direction}`\n if (style === 6) return `tilted_ground_${direction}`\n return `vcc_${direction}`\n}\n\nfunction getComponentBodyBounds(\n records: AltiumRecord[],\n portPoints: AltiumPoint[],\n): Bounds {\n const rectangles = records\n .filter((record) => record.recordKind === \"14\")\n .flatMap((record) => {\n const rectangle = getRectangle(record)\n return rectangle ? [rectangle] : []\n })\n if (rectangles.length > 0) return mergeBounds(rectangles)\n\n const points: AltiumPoint[] = []\n for (const record of records) {\n if (record.recordKind === \"2\") continue\n const location = getLocation(record)\n const corner = getCorner(record)\n if (location && corner) points.push(location, corner)\n points.push(...getSchematicRecordPoints(record))\n if (record.recordKind === \"8\" && location) {\n const radiusX = Math.abs(record.getNumber(\"RADIUS\") ?? 0)\n const radiusY = Math.abs(record.getNumber(\"SECONDARYRADIUS\") ?? radiusX)\n points.push(\n { x: location.x - radiusX, y: location.y - radiusY },\n { x: location.x + radiusX, y: location.y + radiusY },\n )\n }\n }\n if (points.length > 0) return getBoundsForPoints(points)\n const bounds = getBoundsForPoints(portPoints)\n if (bounds.minX === bounds.maxX) {\n bounds.minX -= 2\n bounds.maxX += 2\n }\n if (bounds.minY === bounds.maxY) {\n bounds.minY -= 2\n bounds.maxY += 2\n }\n return bounds\n}\n\nfunction findOwnedText(\n records: AltiumRecord[],\n recordKind: string,\n name: string,\n): string | undefined {\n return records\n .find(\n (record) =>\n record.recordKind === recordKind &&\n record.getDecoded(\"NAME\")?.toLowerCase() === name.toLowerCase(),\n )\n ?.getDecoded(\"TEXT\")\n}\n\nfunction isOwnedRecordVisible(\n record: AltiumRecord,\n currentPartId: number,\n): boolean {\n const ownerPartId = record.getNumber(\"OWNERPARTID\")\n const ownerPartDisplayMode = record.getNumber(\"OWNERPARTDISPLAYMODE\")\n return (\n (ownerPartId === undefined ||\n ownerPartId <= 0 ||\n ownerPartId === currentPartId) &&\n (ownerPartDisplayMode === undefined || ownerPartDisplayMode === 0)\n )\n}\n\nfunction isPinHidden(pin: AltiumRecord): boolean {\n const pinConglomerate = pin.getNumber(\"PINCONGLOMERATE\")\n return (\n pin.getBoolean(\"ISHIDDEN\") === true ||\n (pinConglomerate !== undefined && (pinConglomerate & 0x04) !== 0)\n )\n}\n\nfunction getRecordDirection(record: AltiumRecord): CardinalDirection {\n const orientation =\n ((Math.round(record.getNumber(\"ORIENTATION\") ?? 0) % 4) + 4) % 4\n return DIRECTION_BY_ORIENTATION[orientation] ?? \"right\"\n}\n\nfunction directionToSide(\n direction: CardinalDirection,\n): NonNullable<SchematicPort[\"side_of_component\"]> {\n if (direction === \"up\") return \"top\"\n if (direction === \"down\") return \"bottom\"\n return direction\n}\n\nfunction directionToOppositeSide(\n direction: CardinalDirection,\n): SchematicNetLabel[\"anchor_side\"] {\n if (direction === \"up\") return \"bottom\"\n if (direction === \"down\") return \"top\"\n return direction === \"left\" ? \"right\" : \"left\"\n}\n\nfunction groupByPoint(ports: ConvertedPort[]): Map<string, ConvertedPort[]> {\n const grouped = new Map<string, ConvertedPort[]>()\n for (const port of ports) {\n const key = pointKey(port.point)\n const existing = grouped.get(key)\n if (existing) existing.push(port)\n else grouped.set(key, [port])\n }\n return grouped\n}\n\nfunction uniqueConvertedPorts(ports: ConvertedPort[]): ConvertedPort[] {\n const seenSourcePortIds = new Set<string>()\n return ports.filter((port) => {\n const sourcePortId = port.sourcePort.source_port_id\n if (seenSourcePortIds.has(sourcePortId)) return false\n seenSourcePortIds.add(sourcePortId)\n return true\n })\n}\n\nfunction getPortIdAtElectricalPoint(\n port: ConvertedPort | undefined,\n electricalPoint: AltiumPoint,\n scale: number,\n): string | undefined {\n if (!port?.isSchematicVisible) return undefined\n return pointsEqual(\n port.schematicPort.center,\n scalePoint(electricalPoint, scale),\n )\n ? port.schematicPort.schematic_port_id\n : undefined\n}\n\nfunction getBoundsForPoints(points: AltiumPoint[]): Bounds {\n if (points.length === 0) return { maxX: 1, maxY: 1, minX: -1, minY: -1 }\n return {\n maxX: Math.max(...points.map((point) => point.x)),\n maxY: Math.max(...points.map((point) => point.y)),\n minX: Math.min(...points.map((point) => point.x)),\n minY: Math.min(...points.map((point) => point.y)),\n }\n}\n\nfunction mergeBounds(bounds: Bounds[]): Bounds {\n return {\n maxX: Math.max(...bounds.map((bound) => bound.maxX)),\n maxY: Math.max(...bounds.map((bound) => bound.maxY)),\n minX: Math.min(...bounds.map((bound) => bound.minX)),\n minY: Math.min(...bounds.map((bound) => bound.minY)),\n }\n}\n\nfunction getBoundsCenter(bounds: Bounds): AltiumPoint {\n return {\n x: (bounds.minX + bounds.maxX) / 2,\n y: (bounds.minY + bounds.maxY) / 2,\n }\n}\n\nfunction getRectangle(record: AltiumRecord): Bounds | undefined {\n const location = getLocation(record)\n const corner = getCorner(record)\n if (!location || !corner) return undefined\n return {\n maxX: Math.max(location.x, corner.x),\n maxY: Math.max(location.y, corner.y),\n minX: Math.min(location.x, corner.x),\n minY: Math.min(location.y, corner.y),\n }\n}\n\nfunction getLocation(record: AltiumRecord): AltiumPoint | undefined {\n const x = getCoordinate(record, \"LOCATION.X\")\n const y = getCoordinate(record, \"LOCATION.Y\")\n return x === undefined || y === undefined ? undefined : { x, y }\n}\n\nfunction getCorner(record: AltiumRecord): AltiumPoint | undefined {\n const x = getCoordinate(record, \"CORNER.X\")\n const y = getCoordinate(record, \"CORNER.Y\")\n return x === undefined || y === undefined ? undefined : { x, y }\n}\n\nfunction getCoordinate(record: AltiumRecord, key: string): number | undefined {\n const raw = record.getCaseInsensitive(key)\n if (raw === undefined) return undefined\n const integer = Number(raw)\n if (!Number.isFinite(integer)) return undefined\n const fractionRaw = record.getCaseInsensitive(`${key}_FRAC`)\n if (fractionRaw === undefined) return integer\n const fraction = Number(`0.${fractionRaw.replace(/^[+-]/u, \"\")}`)\n if (!Number.isFinite(fraction)) return integer\n return integer < 0 ? integer - fraction : integer + fraction\n}\n\nfunction parsePinNumber(value: string): number | undefined {\n const parsed = Number(value)\n return Number.isInteger(parsed) && parsed >= 0 ? parsed : undefined\n}\n\nfunction scalePoint(point: AltiumPoint, scale: number): AltiumPoint {\n return { x: point.x * scale, y: point.y * scale }\n}\n\nfunction pointKey(point: AltiumPoint): string {\n return `${point.x.toFixed(6)},${point.y.toFixed(6)}`\n}\n\nfunction pointsEqual(\n left: AltiumPoint,\n right: AltiumPoint | undefined,\n): boolean {\n return (\n right !== undefined &&\n Math.abs(left.x - right.x) < 0.000001 &&\n Math.abs(left.y - right.y) < 0.000001\n )\n}\n\nfunction uniqueStrings(values: Array<string | undefined>): string[] {\n return [...new Set(values.filter((value): value is string => Boolean(value)))]\n}\n\nfunction sanitizeId(value: string): string {\n const sanitized = value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/gu, \"_\")\n .replace(/^_+|_+$/gu, \"\")\n return sanitized || \"unnamed\"\n}\n\nfunction isGroundNet(name: string): boolean {\n return /(?:^|[_+-])(?:[adp]?gnd|ground)(?:$|[_+\\d-])/iu.test(name)\n}\n\nfunction isPowerNet(name: string): boolean {\n return (\n isGroundNet(name) ||\n /(?:^|[_+-])(?:vcc|vdd|vss)(?:$|[a-z0-9_+-])/iu.test(name) ||\n /(?:^|[_+-])(?:vin|vout|pwr|power)(?:$|[_+\\d-])/iu.test(name)\n )\n}\n","import {\n AltiumBinaryPcbDoc,\n AltiumPcbDoc,\n type AltiumPcbDocument,\n AltiumSchDoc,\n parseAltiumFile,\n parseAltiumPcbDoc,\n parseAltiumSchDoc,\n} from \"altiumts\"\nimport type { AnyCircuitElement } from \"circuit-json\"\nimport {\n type ConvertAltiumPcbDocOptions,\n convertAltiumPcbDocToCircuitJson,\n} from \"./convert-altium-pcb-doc-to-circuit-json\"\nimport {\n type ConvertAltiumSchDocOptions,\n convertAltiumSchDocToCircuitJson,\n} from \"./convert-altium-sch-doc-to-circuit-json\"\n\nexport type AltiumSourceType = \"auto\" | \"pcb\" | \"schematic\"\n\nexport interface ConvertAltiumToCircuitJsonOptions {\n pcb?: ConvertAltiumPcbDocOptions\n schematic?: ConvertAltiumSchDocOptions\n sourceType?: AltiumSourceType\n}\n\nexport type SupportedAltiumDocument = AltiumPcbDocument | AltiumSchDoc\n\nexport function convertAltiumToCircuitJson(\n source: ArrayBuffer | Uint8Array | string,\n options: ConvertAltiumToCircuitJsonOptions = {},\n): AnyCircuitElement[] {\n const sourceType = options.sourceType ?? \"auto\"\n\n if (sourceType === \"pcb\") {\n if (typeof source === \"string\") {\n return convertAltiumPcbDocToCircuitJson(\n parseAltiumPcbDoc(source),\n options.pcb,\n )\n }\n const { document } = parseAltiumFile(toUint8Array(source))\n if (\n !(document instanceof AltiumPcbDoc) &&\n !(document instanceof AltiumBinaryPcbDoc)\n ) {\n throw new TypeError(\n `Expected an Altium PCB document, got ${document.type}`,\n )\n }\n return convertAltiumPcbDocToCircuitJson(document, options.pcb)\n }\n if (sourceType === \"schematic\") {\n return convertAltiumSchDocToCircuitJson(\n parseAltiumSchDoc(normalizeSchematicSource(source)),\n options.schematic,\n )\n }\n\n const bytes = toUint8Array(source)\n const { document } = parseAltiumFile(bytes)\n return convertAltiumDocumentToCircuitJson(document, options)\n}\n\nexport function convertAltiumDocumentToCircuitJson(\n document: unknown,\n options: ConvertAltiumToCircuitJsonOptions = {},\n): AnyCircuitElement[] {\n if (document instanceof AltiumSchDoc) {\n return convertAltiumSchDocToCircuitJson(document, options.schematic)\n }\n if (\n document instanceof AltiumPcbDoc ||\n document instanceof AltiumBinaryPcbDoc\n ) {\n return convertAltiumPcbDocToCircuitJson(document, options.pcb)\n }\n const type =\n typeof document === \"object\" && document !== null && \"type\" in document\n ? String(document.type)\n : typeof document\n throw new TypeError(`Unsupported Altium document type: ${type}`)\n}\n\nfunction toUint8Array(source: ArrayBuffer | Uint8Array | string): Uint8Array {\n if (typeof source === \"string\") return new TextEncoder().encode(source)\n if (source instanceof Uint8Array) return source\n return new Uint8Array(source)\n}\n\nfunction normalizeSchematicSource(\n source: ArrayBuffer | Uint8Array | string,\n): Uint8Array | string {\n return source instanceof ArrayBuffer ? new Uint8Array(source) : source\n}\n"],"mappings":"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","names":["getSchematicRecordPoints","symbolPort","getSchematicRecordPoints","scalePoint","getLocation","getCorner","getRectangle","getCoordinate","document"]}
1
+ {"version":3,"sources":["../lib/convert-altium-pcb-doc-to-circuit-json.ts","../lib/convert-altium-sch-doc-to-circuit-json.ts","../lib/schematic/convert-semantic-schematic.ts","../lib/convert-altium-to-circuit-json.ts"],"sourcesContent":["import {\n AltiumArcRecord,\n AltiumFillRecord,\n AltiumPadRecord,\n type AltiumPcbDocument,\n type AltiumPoint,\n type AltiumRecord,\n AltiumTextRecord,\n AltiumTrackRecord,\n AltiumViaRecord,\n getAltiumBounds,\n getPcbLayerStack,\n parseAltiumMeasurementToMils,\n} from \"altiumts\"\nimport type {\n AnyCircuitElement,\n LayerRef,\n PcbBoard,\n PcbComponent,\n PcbCutout,\n PcbHole,\n PcbPlatedHole,\n PcbSilkscreenLine,\n PcbSilkscreenPath,\n PcbSilkscreenRect,\n PcbSilkscreenText,\n PcbSmtPad,\n PcbTrace,\n PcbVia,\n} from \"circuit-json\"\n\nconst MILS_TO_MILLIMETERS = 0.0254\nconst BOARD_ID = \"pcb_board_altium\"\nconst BOARD_GRAPHICS_COMPONENT_ID = \"pcb_component_altium_board_graphics\"\n\nexport interface ConvertAltiumPcbDocOptions {\n includeBoardOutline?: boolean\n includeComponents?: boolean\n includePads?: boolean\n includeSilkscreen?: boolean\n includeTraces?: boolean\n includeVias?: boolean\n}\n\nexport function convertAltiumPcbDocToCircuitJson(\n document: AltiumPcbDocument,\n options: ConvertAltiumPcbDocOptions = {},\n): AnyCircuitElement[] {\n const elements: AnyCircuitElement[] = []\n\n if (options.includeBoardOutline !== false) {\n elements.push(createBoard(document))\n for (const [index, cutout] of document.boardGeometry.cutouts.entries()) {\n if (cutout.outline.points.length < 3) continue\n elements.push({\n type: \"pcb_cutout\",\n pcb_cutout_id: `pcb_cutout_altium_${index}`,\n pcb_board_id: BOARD_ID,\n shape: \"polygon\",\n points: cutout.outline.points.map(toMillimeterPoint),\n } satisfies PcbCutout)\n }\n }\n\n if (options.includeComponents !== false) {\n for (const [index, component] of document.components.entries()) {\n const position = component.position\n if (!position) continue\n const bounds = document.getComponentBounds(component)\n elements.push({\n type: \"pcb_component\",\n pcb_component_id: componentId(index),\n source_component_id: `source_component_altium_${index}`,\n center: toMillimeterPoint(position),\n width: milsToMillimeters(\n bounds ? bounds.maxX - bounds.minX : (component.heightMils ?? 20),\n ),\n height: milsToMillimeters(\n bounds ? bounds.maxY - bounds.minY : (component.heightMils ?? 20),\n ),\n layer: component.side === \"bottom\" ? \"bottom\" : \"top\",\n rotation: component.rotation,\n position_mode: \"none\",\n obstructs_within_bounds: false,\n } satisfies PcbComponent)\n }\n }\n\n for (const [index, record] of document.records.entries()) {\n if (record instanceof AltiumPadRecord && options.includePads !== false) {\n const pad = convertPad(record, index)\n if (pad) elements.push(pad)\n continue\n }\n\n if (record instanceof AltiumTrackRecord) {\n if (isOverlayLayer(record.layer)) {\n if (options.includeSilkscreen === false) continue\n const line = convertSilkscreenLine(record, index)\n if (line) elements.push(line)\n } else if (options.includeTraces !== false) {\n const trace = convertTrack(record, index)\n if (trace) elements.push(trace)\n }\n continue\n }\n\n if (record instanceof AltiumViaRecord && options.includeVias !== false) {\n const via = convertVia(record, index)\n if (via) elements.push(via)\n continue\n }\n\n if (\n options.includeSilkscreen === false ||\n !isOverlayLayer(getLayer(record))\n ) {\n continue\n }\n\n if (record instanceof AltiumArcRecord) {\n const path = convertSilkscreenArc(record, index)\n if (path) elements.push(path)\n } else if (record instanceof AltiumFillRecord) {\n const rect = convertSilkscreenFill(record, index)\n if (rect) elements.push(rect)\n } else if (record instanceof AltiumTextRecord) {\n const text = convertSilkscreenText(record, index)\n if (text) elements.push(text)\n }\n }\n\n return elements\n}\n\nfunction createBoard(document: AltiumPcbDocument): PcbBoard {\n const outline = document.boardGeometry.outline.points.map(toMillimeterPoint)\n const bounds =\n getAltiumBounds(document.boardGeometry.outline.points) ??\n getFallbackPcbBounds(document.records)\n const width = Math.max(milsToMillimeters(bounds.maxX - bounds.minX), 0.1)\n const height = Math.max(milsToMillimeters(bounds.maxY - bounds.minY), 0.1)\n const numLayers = document.board\n ? Math.max(\n getPcbLayerStack(document.board).entries.filter((entry) =>\n Boolean(mapCopperLayer(entry.name ?? entry.layerId)),\n ).length,\n 2,\n )\n : 2\n\n return {\n type: \"pcb_board\",\n pcb_board_id: BOARD_ID,\n center: {\n x: milsToMillimeters((bounds.minX + bounds.maxX) / 2),\n y: milsToMillimeters((bounds.minY + bounds.maxY) / 2),\n },\n width,\n height,\n ...(outline.length >= 3 ? { shape: \"polygon\" as const, outline } : {}),\n thickness: 1.6,\n num_layers: numLayers,\n material: \"fr4\",\n }\n}\n\nfunction getFallbackPcbBounds(records: AltiumRecord[]): {\n maxX: number\n maxY: number\n minX: number\n minY: number\n} {\n const points: AltiumPoint[] = []\n for (const record of records) {\n if (\n record instanceof AltiumPadRecord ||\n record instanceof AltiumViaRecord\n ) {\n if (record.position) points.push(record.position)\n } else if (record instanceof AltiumTrackRecord) {\n if (record.start) points.push(record.start)\n if (record.end) points.push(record.end)\n }\n }\n return getAltiumBounds(points) ?? { minX: 0, minY: 0, maxX: 1000, maxY: 800 }\n}\n\nfunction convertTrack(\n record: AltiumTrackRecord,\n index: number,\n): PcbTrace | undefined {\n const start = record.start\n const end = record.end\n const layer = mapCopperLayer(record.layer)\n if (!start || !end || !layer) return undefined\n const width = milsToMillimeters(record.widthMils ?? 4)\n return {\n type: \"pcb_trace\",\n pcb_trace_id: `pcb_trace_altium_${index}`,\n should_round_corners: true,\n route: [\n { route_type: \"wire\", ...toMillimeterPoint(start), width, layer },\n { route_type: \"wire\", ...toMillimeterPoint(end), width, layer },\n ],\n }\n}\n\nfunction convertVia(\n record: AltiumViaRecord,\n index: number,\n): PcbVia | undefined {\n if (!record.position) return undefined\n const startLayer = mapCopperLayer(record.startLayer) ?? \"top\"\n const endLayer = mapCopperLayer(record.endLayer) ?? \"bottom\"\n const layers = startLayer === endLayer ? [startLayer] : [startLayer, endLayer]\n const outerDiameter = milsToMillimeters(record.diameterMils ?? 20)\n return {\n type: \"pcb_via\",\n pcb_via_id: `pcb_via_altium_${index}`,\n ...toMillimeterPoint(record.position),\n outer_diameter: outerDiameter,\n hole_diameter: milsToMillimeters(\n record.holeSizeMils ?? (record.diameterMils ?? 20) * 0.45,\n ),\n layers,\n is_tented: record.tentedTop === true && record.tentedBottom === true,\n }\n}\n\nfunction convertPad(\n record: AltiumPadRecord,\n index: number,\n): PcbSmtPad | PcbPlatedHole | PcbHole | undefined {\n const position = record.position\n const size = record.size\n if (!position || !size) return undefined\n const x = milsToMillimeters(position.x)\n const y = milsToMillimeters(position.y)\n const width = milsToMillimeters(size.width)\n const height = milsToMillimeters(size.height)\n const holeDiameter = milsToMillimeters(record.holeSizeMils ?? 0)\n const shape = normalizeShape(record.shape)\n const id = `altium_${index}`\n\n if (record.plated === false && holeDiameter > 0) {\n return {\n type: \"pcb_hole\",\n pcb_hole_id: `pcb_hole_${id}`,\n hole_shape: \"circle\",\n hole_diameter: holeDiameter,\n x,\n y,\n }\n }\n\n if (record.behavior === \"through-hole\" || holeDiameter > 0) {\n const slotLengthMils = getMeasurement(record, \"SLOTLENGTH\")\n const holeWidthMils = record.holeWidthMils ?? record.holeSizeMils\n const isSlot =\n normalizeShape(record.holeType).includes(\"SLOT\") ||\n (slotLengthMils ?? 0) > (record.holeSizeMils ?? 0) ||\n (holeWidthMils ?? 0) > (record.holeSizeMils ?? 0)\n const layers: LayerRef[] = [\"top\", \"bottom\"]\n\n if (isSlot) {\n const holeWidth = milsToMillimeters(\n Math.max(\n slotLengthMils ?? holeWidthMils ?? record.holeSizeMils ?? 1,\n 1,\n ),\n )\n const holeHeight = Math.max(holeDiameter, MILS_TO_MILLIMETERS)\n if (isRectangularShape(shape)) {\n const rotated = record.holeRotation !== 0 || record.rotation !== 0\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: rotated\n ? \"rotated_pill_hole_with_rect_pad\"\n : \"pill_hole_with_rect_pad\",\n hole_shape: rotated ? \"rotated_pill\" : \"pill\",\n pad_shape: \"rect\",\n hole_width: holeWidth,\n hole_height: holeHeight,\n ...(rotated ? { hole_ccw_rotation: record.holeRotation } : {}),\n rect_pad_width: width,\n rect_pad_height: height,\n ...(rotated ? { rect_ccw_rotation: record.rotation } : {}),\n hole_offset_x: 0,\n hole_offset_y: 0,\n x,\n y,\n layers,\n } as PcbPlatedHole\n }\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"pill\",\n outer_width: width,\n outer_height: height,\n hole_width: holeWidth,\n hole_height: holeHeight,\n ccw_rotation: record.holeRotation || record.rotation,\n x,\n y,\n layers,\n }\n }\n\n if (isRectangularShape(shape)) {\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"circular_hole_with_rect_pad\",\n hole_shape: \"circle\",\n pad_shape: \"rect\",\n hole_diameter: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n rect_pad_width: width,\n rect_pad_height: height,\n rect_border_radius: shape.includes(\"ROUNDRECT\")\n ? Math.min(width, height) * 0.18\n : 0,\n rect_ccw_rotation: record.rotation,\n hole_offset_x: 0,\n hole_offset_y: 0,\n x,\n y,\n layers,\n }\n }\n\n if (shape.includes(\"OCTAGON\")) {\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"hole_with_polygon_pad\",\n hole_shape: \"circle\",\n hole_diameter: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n pad_outline: createOctagonPoints(x, y, width, height, record.rotation),\n hole_offset_x: 0,\n hole_offset_y: 0,\n x,\n y,\n layers,\n }\n }\n\n if (shape === \"ROUND\" || shape === \"CIRCLE\" || shape === \"OVAL\") {\n if (Math.abs(width - height) >= 0.0001) {\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"pill\",\n outer_width: width,\n outer_height: height,\n hole_width: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n hole_height: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n ccw_rotation: record.rotation,\n x,\n y,\n layers,\n }\n }\n }\n\n return {\n type: \"pcb_plated_hole\",\n pcb_plated_hole_id: `pcb_plated_hole_${id}`,\n shape: \"circle\",\n outer_diameter: Math.max(width, height),\n hole_diameter: Math.max(holeDiameter, MILS_TO_MILLIMETERS),\n x,\n y,\n layers,\n }\n }\n\n const layer = mapCopperLayer(record.layer)\n if (!layer) return undefined\n const base = {\n type: \"pcb_smtpad\" as const,\n pcb_smtpad_id: `pcb_smtpad_${id}`,\n x,\n y,\n layer,\n soldermask_margin:\n record.solderMaskExpansionMils === undefined\n ? undefined\n : milsToMillimeters(record.solderMaskExpansionMils),\n }\n\n if (shape.includes(\"OCTAGON\")) {\n return {\n ...base,\n shape: \"polygon\",\n points: createOctagonPoints(x, y, width, height, record.rotation),\n }\n }\n if (shape === \"ROUND\" || shape === \"CIRCLE\" || shape === \"OVAL\") {\n if (Math.abs(width - height) < 0.0001) {\n return { ...base, shape: \"circle\", radius: width / 2 }\n }\n return record.rotation === 0\n ? {\n ...base,\n shape: \"pill\",\n width,\n height,\n radius: Math.min(width, height) / 2,\n }\n : {\n ...base,\n shape: \"rotated_pill\",\n width,\n height,\n radius: Math.min(width, height) / 2,\n ccw_rotation: record.rotation,\n }\n }\n\n const cornerRadius = shape.includes(\"ROUNDRECT\")\n ? Math.min(width, height) * 0.18\n : undefined\n return record.rotation === 0\n ? { ...base, shape: \"rect\", width, height, corner_radius: cornerRadius }\n : {\n ...base,\n shape: \"rotated_rect\",\n width,\n height,\n corner_radius: cornerRadius,\n ccw_rotation: record.rotation,\n }\n}\n\nfunction convertSilkscreenLine(\n record: AltiumTrackRecord,\n index: number,\n): PcbSilkscreenLine | undefined {\n if (!record.start || !record.end) return undefined\n return {\n type: \"pcb_silkscreen_line\",\n pcb_silkscreen_line_id: `pcb_silkscreen_line_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n stroke_width: milsToMillimeters(record.widthMils ?? 4),\n ...withNumberedPoints(record.start, record.end),\n layer: mapOverlayLayer(record.layer),\n }\n}\n\nfunction convertSilkscreenArc(\n record: AltiumArcRecord,\n index: number,\n): PcbSilkscreenPath | undefined {\n if (!record.center || !record.radiusMils) return undefined\n const points = approximateArc(\n record.center,\n record.radiusMils,\n record.startAngle,\n record.endAngle,\n )\n return {\n type: \"pcb_silkscreen_path\",\n pcb_silkscreen_path_id: `pcb_silkscreen_path_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n route: points.map(toMillimeterPoint),\n stroke_width: milsToMillimeters(record.widthMils ?? 4),\n layer: mapOverlayLayer(record.layer),\n }\n}\n\nfunction convertSilkscreenFill(\n record: AltiumFillRecord,\n index: number,\n): PcbSilkscreenRect | undefined {\n if (!record.bounds) return undefined\n const width = milsToMillimeters(record.bounds.maxX - record.bounds.minX)\n const height = milsToMillimeters(record.bounds.maxY - record.bounds.minY)\n return {\n type: \"pcb_silkscreen_rect\",\n pcb_silkscreen_rect_id: `pcb_silkscreen_rect_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n center: {\n x: milsToMillimeters((record.bounds.minX + record.bounds.maxX) / 2),\n y: milsToMillimeters((record.bounds.minY + record.bounds.maxY) / 2),\n },\n width,\n height,\n stroke_width: Math.min(width, height),\n is_filled: true,\n has_stroke: false,\n ccw_rotation: record.rotation,\n layer: mapOverlayLayer(record.layer),\n }\n}\n\nfunction convertSilkscreenText(\n record: AltiumTextRecord,\n index: number,\n): PcbSilkscreenText | undefined {\n const text =\n decodeAltiumWideString(record.getDecoded(\"WIDESTRING\")) ||\n record.getDecoded(\"TEXT\") ||\n record.text\n if (!record.position || !text) return undefined\n return {\n type: \"pcb_silkscreen_text\",\n pcb_silkscreen_text_id: `pcb_silkscreen_text_altium_${index}`,\n pcb_component_id: pcbComponentIdForRecord(record),\n text,\n font: \"tscircuit2024\",\n font_size: milsToMillimeters(record.heightMils ?? 30),\n anchor_position: toMillimeterPoint(record.position),\n anchor_alignment: mapTextAnchor(record.justification),\n ccw_rotation: record.rotation,\n layer: mapOverlayLayer(record.layer),\n is_mirrored: record.mirrored,\n }\n}\n\nfunction decodeAltiumWideString(raw: string | undefined): string {\n if (!raw) return \"\"\n if (!/^\\d+(?:,\\d+)*$/u.test(raw)) return raw\n try {\n return String.fromCodePoint(...raw.split(\",\").map(Number))\n } catch {\n return raw\n }\n}\n\nfunction pcbComponentIdForRecord(record: AltiumRecord): string {\n const index = record.getNumber(\"COMPONENT\")\n return index === undefined || index < 0\n ? BOARD_GRAPHICS_COMPONENT_ID\n : componentId(index)\n}\n\nfunction componentId(index: number): string {\n return `pcb_component_altium_${index}`\n}\n\nfunction mapTextAnchor(\n justification: string | undefined,\n): \"bottom_left\" | \"bottom_center\" | \"bottom_right\" | \"center\" {\n const normalized = justification?.replace(/[\\s_-]+/gu, \"\").toUpperCase()\n if (normalized?.includes(\"CENTER\")) return \"bottom_center\"\n if (normalized?.includes(\"RIGHT\")) return \"bottom_right\"\n if (normalized?.includes(\"LEFT\")) return \"bottom_left\"\n return \"center\"\n}\n\nfunction mapCopperLayer(layer: string | undefined): LayerRef | undefined {\n const normalized = normalizeLayer(layer)\n if (normalized === \"TOP\" || normalized === \"TOPLAYER\") return \"top\"\n if (normalized === \"BOTTOM\" || normalized === \"BOTTOMLAYER\") return \"bottom\"\n const innerMatch = /^(?:MID|MIDLAYER|INTERNALPLANE)(\\d+)$/u.exec(normalized)\n if (!innerMatch?.[1]) return undefined\n const innerNumber = Math.min(Math.max(Number(innerMatch[1]), 1), 8)\n return `inner${innerNumber}` as LayerRef\n}\n\nfunction isOverlayLayer(layer: string | undefined): boolean {\n const normalized = normalizeLayer(layer)\n return normalized === \"TOPOVERLAY\" || normalized === \"BOTTOMOVERLAY\"\n}\n\nfunction mapOverlayLayer(layer: string | undefined): \"top\" | \"bottom\" {\n return normalizeLayer(layer) === \"BOTTOMOVERLAY\" ? \"bottom\" : \"top\"\n}\n\nfunction getLayer(record: AltiumRecord): string | undefined {\n return record.getDecoded(\"LAYER\")\n}\n\nfunction normalizeLayer(layer: string | undefined): string {\n return (layer ?? \"\").replace(/[\\s_.-]+/gu, \"\").toUpperCase()\n}\n\nfunction normalizeShape(shape: string | undefined): string {\n return (shape ?? \"ROUND\").replace(/[\\s_-]+/gu, \"\").toUpperCase()\n}\n\nfunction isRectangularShape(shape: string): boolean {\n return shape.includes(\"RECT\") || shape === \"SQUARE\"\n}\n\nfunction getMeasurement(record: AltiumRecord, key: string): number | undefined {\n return parseAltiumMeasurementToMils(record.getCaseInsensitive(key))\n}\n\nfunction milsToMillimeters(value: number): number {\n return value * MILS_TO_MILLIMETERS\n}\n\nfunction toMillimeterPoint(point: AltiumPoint): { x: number; y: number } {\n return { x: milsToMillimeters(point.x), y: milsToMillimeters(point.y) }\n}\n\nfunction withNumberedPoints(\n start: AltiumPoint,\n end: AltiumPoint,\n): { x1: number; x2: number; y1: number; y2: number } {\n return {\n x1: milsToMillimeters(start.x),\n y1: milsToMillimeters(start.y),\n x2: milsToMillimeters(end.x),\n y2: milsToMillimeters(end.y),\n }\n}\n\nfunction approximateArc(\n center: AltiumPoint,\n radius: number,\n startAngle: number,\n endAngle: number,\n): AltiumPoint[] {\n const sweep = endAngle - startAngle || 360\n const segments = Math.max(8, Math.ceil(Math.abs(sweep) / 7.5))\n return Array.from({ length: segments + 1 }, (_, index) => {\n const angle = startAngle + (sweep * index) / segments\n const radians = (angle * Math.PI) / 180\n return {\n x: center.x + Math.cos(radians) * radius,\n y: center.y + Math.sin(radians) * radius,\n }\n })\n}\n\nfunction createOctagonPoints(\n x: number,\n y: number,\n width: number,\n height: number,\n rotation: number,\n): Array<{ x: number; y: number }> {\n const halfWidth = width / 2\n const halfHeight = height / 2\n const chamfer = Math.min(width, height) / 4\n const points = [\n { x: -halfWidth + chamfer, y: -halfHeight },\n { x: halfWidth - chamfer, y: -halfHeight },\n { x: halfWidth, y: -halfHeight + chamfer },\n { x: halfWidth, y: halfHeight - chamfer },\n { x: halfWidth - chamfer, y: halfHeight },\n { x: -halfWidth + chamfer, y: halfHeight },\n { x: -halfWidth, y: halfHeight - chamfer },\n { x: -halfWidth, y: -halfHeight + chamfer },\n ]\n const radians = (rotation * Math.PI) / 180\n return points.map((point) => ({\n x: x + point.x * Math.cos(radians) - point.y * Math.sin(radians),\n y: y + point.x * Math.sin(radians) + point.y * Math.cos(radians),\n }))\n}\n","import {\n type AltiumPoint,\n type AltiumRecord,\n type AltiumSchDoc,\n getSchematicRecordPoints,\n} from \"altiumts\"\nimport type {\n AnyCircuitElement,\n Point,\n SchematicArc,\n SchematicCircle,\n SchematicLine,\n SchematicPath,\n SchematicRect,\n SchematicSheet,\n SchematicText,\n SchematicTrace,\n} from \"circuit-json\"\nimport { convertSemanticSchematic } from \"./schematic/convert-semantic-schematic\"\n\nconst SCHEMATIC_SHEET_ID = \"schematic_sheet_altium\"\n// circuit-to-svg renders schematic_sheet as a centered A4 page. Keep imported\n// coordinates inside the same 5 mm inset used by that renderer.\nconst SCHEMATIC_UNIT_TO_MILLIMETERS = 10.16 / 1.1\nconst SCHEMATIC_SHEET_INSET = 5 / SCHEMATIC_UNIT_TO_MILLIMETERS\nconst SCHEMATIC_SHEET_WIDTH = 297 / SCHEMATIC_UNIT_TO_MILLIMETERS\nconst SCHEMATIC_SHEET_HEIGHT = 210 / SCHEMATIC_UNIT_TO_MILLIMETERS\nconst SCHEMATIC_SHEET_INNER_WIDTH =\n SCHEMATIC_SHEET_WIDTH - SCHEMATIC_SHEET_INSET * 2\nconst SCHEMATIC_SHEET_INNER_HEIGHT =\n SCHEMATIC_SHEET_HEIGHT - SCHEMATIC_SHEET_INSET * 2\n\nexport interface ConvertAltiumSchDocOptions {\n centerOnSchematicSheet?: boolean\n includeHidden?: boolean\n includeSheetBorder?: boolean\n includeText?: boolean\n schematicUnitScale?: number\n sheetName?: string\n}\n\ninterface SchematicContext {\n document: AltiumSchDoc\n records: AltiumRecord[]\n scale: number\n sheetRecord?: AltiumRecord\n}\n\nexport function convertAltiumSchDocToCircuitJson(\n document: AltiumSchDoc,\n options: ConvertAltiumSchDocOptions = {},\n): AnyCircuitElement[] {\n const records = document.records\n const sheetRecord = records.find((record) => record.recordKind === \"31\")\n const sheetDimensions = getAltiumSheetDimensions(sheetRecord)\n const scale = options.schematicUnitScale ?? getPageFitScale(sheetDimensions)\n if (!Number.isFinite(scale) || scale <= 0) {\n throw new RangeError(\"schematicUnitScale must be a positive finite number\")\n }\n\n const context: SchematicContext = { document, records, scale, sheetRecord }\n const elements: AnyCircuitElement[] = [\n {\n type: \"schematic_sheet\",\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n name: options.sheetName ?? \"Altium schematic\",\n outline_color: \"#334155\",\n sheet_index: 0,\n } satisfies SchematicSheet,\n ]\n\n if (options.includeSheetBorder === true) {\n elements.push(createSheetBorder(sheetRecord, scale))\n }\n\n const semanticConversion = convertSemanticSchematic(document, {\n includeHidden: options.includeHidden,\n includeText: options.includeText,\n scale,\n schematicSheetId: SCHEMATIC_SHEET_ID,\n })\n elements.push(...semanticConversion.elements)\n\n for (const [index, record] of records.entries()) {\n if (semanticConversion.handledRecords.has(record)) continue\n if (!shouldRenderSchematicRecord(record, context)) continue\n const converted = convertSchematicRecord(record, index, context, options)\n elements.push(...converted)\n }\n\n if (options.centerOnSchematicSheet === false) return elements\n\n const offset = {\n x: (-sheetDimensions.width * scale) / 2,\n y: (-sheetDimensions.height * scale) / 2,\n }\n return elements.map((element) => translateSchematicElement(element, offset))\n}\n\ninterface SheetDimensions {\n height: number\n width: number\n}\n\nfunction getAltiumSheetDimensions(\n sheetRecord: AltiumRecord | undefined,\n): SheetDimensions {\n return {\n width: getPositiveNumber(sheetRecord?.getCaseInsensitive(\"CUSTOMX\"), 1000),\n height: getPositiveNumber(sheetRecord?.getCaseInsensitive(\"CUSTOMY\"), 800),\n }\n}\n\nfunction getPositiveNumber(value: unknown, fallback: number): number {\n const parsed = Number(value)\n return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback\n}\n\nfunction getPageFitScale(sheetDimensions: SheetDimensions): number {\n return Math.min(\n SCHEMATIC_SHEET_INNER_WIDTH / sheetDimensions.width,\n SCHEMATIC_SHEET_INNER_HEIGHT / sheetDimensions.height,\n )\n}\n\nfunction translatePoint(point: Point, offset: Point): Point {\n return { x: point.x + offset.x, y: point.y + offset.y }\n}\n\nfunction translateSchematicElement(\n element: AnyCircuitElement,\n offset: Point,\n): AnyCircuitElement {\n switch (element.type) {\n case \"schematic_component\":\n case \"schematic_port\":\n case \"schematic_rect\":\n case \"schematic_circle\":\n case \"schematic_arc\":\n return { ...element, center: translatePoint(element.center, offset) }\n case \"schematic_net_label\":\n return {\n ...element,\n center: translatePoint(element.center, offset),\n ...(element.anchor_position\n ? {\n anchor_position: translatePoint(element.anchor_position, offset),\n }\n : {}),\n }\n case \"schematic_text\":\n return { ...element, position: translatePoint(element.position, offset) }\n case \"schematic_path\":\n return {\n ...element,\n points: element.points.map((point) => translatePoint(point, offset)),\n }\n case \"schematic_line\":\n return {\n ...element,\n x1: element.x1 + offset.x,\n x2: element.x2 + offset.x,\n y1: element.y1 + offset.y,\n y2: element.y2 + offset.y,\n }\n case \"schematic_trace\":\n return {\n ...element,\n edges: element.edges.map((edge) => ({\n ...edge,\n from: translatePoint(edge.from, offset),\n to: translatePoint(edge.to, offset),\n })),\n junctions: element.junctions.map((junction) =>\n translatePoint(junction, offset),\n ),\n }\n default:\n return element\n }\n}\n\nfunction convertSchematicRecord(\n record: AltiumRecord,\n index: number,\n context: SchematicContext,\n options: ConvertAltiumSchDocOptions,\n): AnyCircuitElement[] {\n const kind = record.recordKind\n const scale = context.scale\n const color = altiumColorToCss(record.getCaseInsensitive(\"COLOR\"), \"#1f2937\")\n const strokeWidth = Math.max(\n Number(record.getCaseInsensitive(\"LINEWIDTH\") ?? 1) * scale,\n 0.05,\n )\n\n if (kind === \"27\") {\n const points = getSchematicRecordPoints(record).map((point) =>\n scalePoint(point, scale),\n )\n if (points.length < 2) return []\n return [\n {\n type: \"schematic_trace\",\n schematic_trace_id: `schematic_trace_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n junctions: [],\n edges: points.slice(1).map((point, pointIndex) => ({\n from: points[pointIndex] ?? point,\n to: point,\n })),\n } satisfies SchematicTrace,\n ]\n }\n\n if (kind === \"6\" || kind === \"7\") {\n const points = getSchematicRecordPoints(record).map((point) =>\n scalePoint(point, scale),\n )\n if (points.length < 2) return []\n return [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_path_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points,\n stroke_width: strokeWidth,\n stroke_color: color,\n fill_color:\n kind === \"7\"\n ? altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"transparent\",\n )\n : undefined,\n is_filled: kind === \"7\",\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n }\n\n if (kind === \"13\") {\n const location = getLocation(record)\n const corner = getCorner(record)\n if (!location || !corner) return []\n return [createLine(index, location, corner, color, strokeWidth, scale)]\n }\n\n if (kind === \"10\" || kind === \"14\") {\n const rectangle = getRectangle(record)\n if (!rectangle) return []\n return [\n {\n type: \"schematic_rect\",\n schematic_rect_id: `schematic_rect_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(\n {\n x: (rectangle.minX + rectangle.maxX) / 2,\n y: (rectangle.minY + rectangle.maxY) / 2,\n },\n scale,\n ),\n width: (rectangle.maxX - rectangle.minX) * scale,\n height: (rectangle.maxY - rectangle.minY) * scale,\n rotation: 0,\n stroke_width: strokeWidth,\n color,\n is_filled: record.getBoolean(\"ISSOLID\") === true,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_dashed: false,\n } satisfies SchematicRect,\n ]\n }\n\n if (kind === \"8\") {\n const center = getLocation(record)\n if (!center) return []\n const radiusX = getCoordinate(record, \"RADIUS\", 1)\n const radiusY = getCoordinate(record, \"SECONDARYRADIUS\", radiusX)\n if (Math.abs(radiusX - radiusY) < 0.0001) {\n return [\n {\n type: \"schematic_circle\",\n schematic_circle_id: `schematic_circle_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(center, scale),\n radius: radiusX * scale,\n stroke_width: strokeWidth,\n color,\n is_filled: record.getBoolean(\"ISSOLID\") === true,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_dashed: false,\n } satisfies SchematicCircle,\n ]\n }\n return [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_ellipse_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: approximateEllipse(center, radiusX, radiusY).map((point) =>\n scalePoint(point, scale),\n ),\n stroke_width: strokeWidth,\n stroke_color: color,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_filled: record.getBoolean(\"ISSOLID\") === true,\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n }\n\n if (kind === \"11\" || kind === \"12\") {\n const center = getLocation(record)\n if (!center) return []\n return [\n {\n type: \"schematic_arc\",\n schematic_arc_id: `schematic_arc_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(center, scale),\n radius: getCoordinate(record, \"RADIUS\", 1) * scale,\n start_angle_degrees: Number(\n record.getCaseInsensitive(\"STARTANGLE\") ?? 0,\n ),\n end_angle_degrees: Number(record.getCaseInsensitive(\"ENDANGLE\") ?? 360),\n direction: \"counterclockwise\",\n stroke_width: strokeWidth,\n color,\n is_dashed: false,\n } satisfies SchematicArc,\n ]\n }\n\n if (kind === \"2\") {\n return convertPin(record, index, context, options, color)\n }\n\n if (kind === \"29\") {\n const location = getLocation(record)\n if (!location) return []\n return [\n {\n type: \"schematic_circle\",\n schematic_circle_id: `schematic_junction_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(location, scale),\n radius: Math.max(\n Number(record.getCaseInsensitive(\"SIZE\") ?? 1) * 0.18,\n 0.15,\n ),\n color,\n is_filled: true,\n fill_color: color,\n is_dashed: false,\n } satisfies SchematicCircle,\n ]\n }\n\n if (kind === \"22\") {\n const location = getLocation(record)\n if (!location) return []\n // altiumts renders the \"Small Cross\" no-ERC symbol with four Altium\n // coordinate units on either side of its anchor.\n const radius = 4\n const noErcStrokeWidth = Math.max(scale, 0.02)\n return [\n createLine(\n index,\n { x: location.x - radius, y: location.y - radius },\n { x: location.x + radius, y: location.y + radius },\n color,\n noErcStrokeWidth,\n scale,\n \"a\",\n ),\n createLine(\n index,\n { x: location.x + radius, y: location.y - radius },\n { x: location.x - radius, y: location.y + radius },\n color,\n noErcStrokeWidth,\n scale,\n \"b\",\n ),\n ]\n }\n\n if (kind === \"17\") {\n return convertPowerPort(record, index, context, options, color)\n }\n\n if (kind === \"18\") {\n return convertPort(record, index, context, options, color)\n }\n\n if (kind === \"4\" || kind === \"25\" || kind === \"34\" || kind === \"41\") {\n if (options.includeText === false) return []\n if (record.getBoolean(\"ISHIDDEN\") && !options.includeHidden) return []\n const text =\n record.getDecoded(\"TEXT\") ??\n record.getDecoded(\"NAME\") ??\n record.getDecoded(\"DESIGNATOR\")\n const location = getLocation(record)\n if (!text || !location) return []\n return [createText(record, index, text, location, color, context)]\n }\n\n if (kind === \"28\") {\n const rectangle = getRectangle(record)\n const text = decodeMultilineText(record.getDecoded(\"TEXT\") ?? \"\")\n if (!rectangle || !text || options.includeText === false) return []\n const fontSize = getFontSize(record, context)\n const fontFamily = getFontFamily(record, context)\n const margin = Math.max(getCoordinate(record, \"TEXTMARGIN\", 0), 0)\n const frameWidth = rectangle.maxX - rectangle.minX\n const frameHeight = rectangle.maxY - rectangle.minY\n const availableWidth = Math.max(frameWidth - margin * 2, fontSize)\n const availableHeight = Math.max(frameHeight - margin * 2, fontSize)\n const wrappedLines =\n record.getBoolean(\"WORDWRAP\") === false\n ? text.split(\"\\n\")\n : wrapSchematicText(text, availableWidth, fontSize, fontFamily)\n const lineHeight = fontSize\n const visibleLines =\n record.getBoolean(\"CLIPTORECT\") === false\n ? wrappedLines\n : wrappedLines.slice(\n 0,\n Math.max(Math.ceil(availableHeight / lineHeight), 1),\n )\n const alignment = Number(record.getCaseInsensitive(\"ALIGNMENT\") ?? 1)\n const horizontalAnchor =\n alignment === 2 ? \"center\" : alignment === 3 ? \"right\" : \"left\"\n const textX =\n horizontalAnchor === \"center\"\n ? (rectangle.minX + rectangle.maxX) / 2\n : horizontalAnchor === \"right\"\n ? rectangle.maxX - margin\n : rectangle.minX + margin\n const textColor = altiumColorToCss(\n record.getCaseInsensitive(\"TEXTCOLOR\") ??\n record.getCaseInsensitive(\"COLOR\"),\n \"#1f2937\",\n )\n const elements: AnyCircuitElement[] = visibleLines.map((line, lineIndex) =>\n createDirectText(\n `schematic_text_frame_line_altium_${index}_${lineIndex}`,\n line,\n {\n x: textX,\n y: rectangle.maxY - margin - lineIndex * lineHeight,\n },\n fontSize,\n textColor,\n scale,\n 0,\n `top_${horizontalAnchor}` as SchematicText[\"anchor\"],\n ),\n )\n\n const isSolid = record.getBoolean(\"ISSOLID\") === true\n const showBorder = record.getBoolean(\"SHOWBORDER\") === true\n if (isSolid || showBorder) {\n elements.unshift({\n type: \"schematic_rect\",\n schematic_rect_id: `schematic_text_frame_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: scalePoint(\n {\n x: (rectangle.minX + rectangle.maxX) / 2,\n y: (rectangle.minY + rectangle.maxY) / 2,\n },\n scale,\n ),\n width: frameWidth * scale,\n height: frameHeight * scale,\n rotation: 0,\n stroke_width: showBorder ? strokeWidth : 0,\n color: showBorder ? color : \"transparent\",\n is_filled: isSolid,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_dashed: false,\n } satisfies SchematicRect)\n }\n\n return elements\n }\n\n return []\n}\n\nfunction convertPin(\n record: AltiumRecord,\n index: number,\n context: SchematicContext,\n options: ConvertAltiumSchDocOptions,\n color: string,\n): AnyCircuitElement[] {\n const location = getLocation(record)\n if (!location) return []\n const pinConglomerate = record.getNumber(\"PINCONGLOMERATE\")\n const hidden =\n record.getBoolean(\"ISHIDDEN\") ||\n (pinConglomerate !== undefined && (pinConglomerate & 0x04) !== 0)\n if (hidden && !options.includeHidden) return []\n const orientation =\n (pinConglomerate ?? Number(record.getCaseInsensitive(\"ORIENTATION\") ?? 0)) &\n 3\n const direction = [\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n { x: -1, y: 0 },\n { x: 0, y: -1 },\n ][orientation] ?? { x: 1, y: 0 }\n const length = Math.max(\n Number(record.getCaseInsensitive(\"PINLENGTH\") ?? 10),\n 1,\n )\n const end = {\n x: location.x + direction.x * length,\n y: location.y + direction.y * length,\n }\n const elements: AnyCircuitElement[] = [\n createLine(index, location, end, color, 0.1, context.scale, \"pin\"),\n ]\n if (options.includeText === false) return elements\n\n const name = record.getDecoded(\"NAME\") ?? \"\"\n const designator = record.getDecoded(\"DESIGNATOR\") ?? \"\"\n const showName =\n pinConglomerate === undefined || (pinConglomerate & 0x08) !== 0\n const showDesignator =\n pinConglomerate === undefined || (pinConglomerate & 0x10) !== 0\n const rotation = orientation === 1 || orientation === 3 ? 90 : 0\n const directionMatchesText = orientation === 0 || orientation === 1\n const nameAnchor = directionMatchesText ? \"right\" : \"left\"\n const designatorAnchor = directionMatchesText ? \"left\" : \"right\"\n const textOffset = 2\n\n if (showName && name) {\n elements.push(\n createDirectText(\n `schematic_pin_name_altium_${index}`,\n name,\n {\n x: location.x - direction.x * textOffset,\n y: location.y - direction.y * textOffset,\n },\n 6,\n color,\n context.scale,\n rotation,\n nameAnchor,\n ),\n )\n }\n if (showDesignator && designator) {\n elements.push(\n createDirectText(\n `schematic_pin_designator_altium_${index}`,\n designator,\n {\n x: location.x + direction.x * textOffset,\n y: location.y + direction.y * textOffset,\n },\n 6,\n color,\n context.scale,\n rotation,\n designatorAnchor,\n ),\n )\n }\n return elements\n}\n\nfunction convertPowerPort(\n record: AltiumRecord,\n index: number,\n context: SchematicContext,\n options: ConvertAltiumSchDocOptions,\n color: string,\n): AnyCircuitElement[] {\n const location = getLocation(record)\n if (!location) return []\n const orientation =\n ((Math.round(record.getNumber(\"ORIENTATION\") ?? 0) % 4) + 4) % 4\n const direction = [\n { x: 1, y: 0 },\n { x: 0, y: 1 },\n { x: -1, y: 0 },\n { x: 0, y: -1 },\n ][orientation] ?? { x: 1, y: 0 }\n const perpendicular = { x: -direction.y, y: direction.x }\n const point = (along: number, across = 0): AltiumPoint => ({\n x: location.x + direction.x * along + perpendicular.x * across,\n y: location.y + direction.y * along + perpendicular.y * across,\n })\n const style = Math.round(Number(record.getCaseInsensitive(\"STYLE\") ?? 2))\n const elements: AnyCircuitElement[] = []\n let labelDistance: number\n\n if (style === 2) {\n elements.push(\n createLine(\n index,\n location,\n point(8),\n color,\n 0.1,\n context.scale,\n \"power_port_stem\",\n ),\n createLine(\n index,\n point(8, -5),\n point(8, 5),\n color,\n 0.1,\n context.scale,\n \"power_port_bar\",\n ),\n )\n labelDistance = 12\n } else if (style === 5) {\n elements.push(\n createLine(\n index,\n location,\n point(4),\n color,\n 0.1,\n context.scale,\n \"power_port_stem\",\n ),\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_power_port_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: [point(4, -7), point(4, 7), point(12)].map((value) =>\n scalePoint(value, context.scale),\n ),\n stroke_width: 0.1,\n stroke_color: color,\n is_filled: false,\n is_dashed: false,\n } satisfies SchematicPath,\n )\n labelDistance = 16\n } else if (style === 4) {\n elements.push(\n createLine(\n index,\n location,\n point(4),\n color,\n 0.1,\n context.scale,\n \"power_port_stem\",\n ),\n ...[\n { along: 4, halfWidth: 7 },\n { along: 8, halfWidth: 4.5 },\n { along: 12, halfWidth: 2 },\n ].map(({ along, halfWidth }, lineIndex) =>\n createLine(\n index,\n point(along, -halfWidth),\n point(along, halfWidth),\n color,\n 0.1,\n context.scale,\n `power_port_ground_${lineIndex}`,\n ),\n ),\n )\n labelDistance = 16\n } else if (style === 6) {\n elements.push(\n createLine(\n index,\n location,\n point(4),\n color,\n 0.1,\n context.scale,\n \"power_port_stem\",\n ),\n createLine(\n index,\n point(4, -7),\n point(4, 7),\n color,\n 0.1,\n context.scale,\n \"power_port_chassis_bar\",\n ),\n ...[\n { from: -7, to: -9 },\n { from: 0, to: -2 },\n { from: 7, to: 5 },\n ].map(({ from, to }, lineIndex) =>\n createLine(\n index,\n point(4, from),\n point(9, to),\n color,\n 0.1,\n context.scale,\n `power_port_chassis_${lineIndex}`,\n ),\n ),\n )\n labelDistance = 14\n } else {\n elements.push({\n type: \"schematic_path\",\n schematic_path_id: `schematic_power_port_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: [location, point(10, -5), point(10, 5)].map((value) =>\n scalePoint(value, context.scale),\n ),\n stroke_width: 0.1,\n stroke_color: color,\n fill_color: color,\n is_filled: true,\n is_dashed: false,\n } satisfies SchematicPath)\n labelDistance = 14\n }\n const text = record.getDecoded(\"TEXT\") ?? record.getDecoded(\"NAME\")\n if (\n text &&\n options.includeText !== false &&\n record.getBoolean(\"SHOWNETNAME\") !== false\n ) {\n const vertical = direction.y !== 0\n const anchor: SchematicText[\"anchor\"] = vertical\n ? direction.y > 0\n ? \"bottom_center\"\n : \"top_center\"\n : direction.x > 0\n ? \"center_left\"\n : \"center_right\"\n elements.push(\n createDirectText(\n `schematic_power_port_text_altium_${index}`,\n text,\n point(labelDistance),\n getFontSize(record, context),\n color,\n context.scale,\n 0,\n anchor,\n ),\n )\n }\n return elements\n}\n\nfunction convertPort(\n record: AltiumRecord,\n index: number,\n context: SchematicContext,\n options: ConvertAltiumSchDocOptions,\n color: string,\n): AnyCircuitElement[] {\n const location = getLocation(record)\n if (!location) return []\n const width = Math.max(Number(record.getCaseInsensitive(\"WIDTH\") ?? 16), 10)\n const height = Math.max(Number(record.getCaseInsensitive(\"HEIGHT\") ?? 10), 4)\n const halfHeight = height / 2\n const pointDepth = Math.min(width * 0.22, height)\n const ioType = Number(record.getCaseInsensitive(\"IOTYPE\") ?? 0)\n const points =\n ioType === 1\n ? [\n { x: location.x, y: location.y },\n { x: location.x + pointDepth, y: location.y + halfHeight },\n { x: location.x + width, y: location.y + halfHeight },\n { x: location.x + width, y: location.y - halfHeight },\n { x: location.x + pointDepth, y: location.y - halfHeight },\n ]\n : ioType === 2\n ? [\n { x: location.x, y: location.y + halfHeight },\n {\n x: location.x + width - pointDepth,\n y: location.y + halfHeight,\n },\n { x: location.x + width, y: location.y },\n {\n x: location.x + width - pointDepth,\n y: location.y - halfHeight,\n },\n { x: location.x, y: location.y - halfHeight },\n ]\n : [\n { x: location.x, y: location.y + halfHeight },\n { x: location.x + width, y: location.y + halfHeight },\n { x: location.x + width, y: location.y - halfHeight },\n { x: location.x, y: location.y - halfHeight },\n ]\n const elements: AnyCircuitElement[] = [\n {\n type: \"schematic_path\",\n schematic_path_id: `schematic_port_altium_${index}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n points: points.map((point) => scalePoint(point, context.scale)),\n stroke_width: 0.1,\n stroke_color: color,\n fill_color: altiumColorToCss(\n record.getCaseInsensitive(\"AREACOLOR\"),\n \"#ffffff\",\n ),\n is_filled: true,\n is_dashed: false,\n } satisfies SchematicPath,\n ]\n const name = record.getDecoded(\"NAME\")\n if (name && options.includeText !== false) {\n elements.push(\n createDirectText(\n `schematic_port_text_altium_${index}`,\n name,\n { x: location.x + width / 2, y: location.y },\n getFontSize(record, context),\n altiumColorToCss(record.getCaseInsensitive(\"TEXTCOLOR\"), color),\n context.scale,\n 0,\n \"center\",\n ),\n )\n }\n return elements\n}\n\nfunction createSheetBorder(\n sheetRecord: AltiumRecord | undefined,\n scale: number,\n): SchematicRect {\n const { height, width } = getAltiumSheetDimensions(sheetRecord)\n return {\n type: \"schematic_rect\",\n schematic_rect_id: \"schematic_rect_altium_sheet_border\",\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: { x: (width * scale) / 2, y: (height * scale) / 2 },\n width: width * scale,\n height: height * scale,\n rotation: 0,\n stroke_width: 0.1,\n color: \"#334155\",\n is_filled: false,\n is_dashed: false,\n }\n}\n\nfunction createLine(\n index: number,\n start: AltiumPoint,\n end: AltiumPoint,\n color: string,\n strokeWidth: number,\n scale: number,\n suffix = \"line\",\n): SchematicLine {\n return {\n type: \"schematic_line\",\n schematic_line_id: `schematic_line_altium_${index}_${suffix}`,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n x1: start.x * scale,\n y1: start.y * scale,\n x2: end.x * scale,\n y2: end.y * scale,\n stroke_width: strokeWidth,\n color,\n is_dashed: false,\n }\n}\n\nfunction createText(\n record: AltiumRecord,\n index: number,\n text: string,\n location: AltiumPoint,\n color: string,\n context: SchematicContext,\n anchorOverride?: SchematicText[\"anchor\"],\n): SchematicText {\n const positioning = getTextPositioning(record)\n return createDirectText(\n `schematic_text_altium_${index}`,\n text,\n location,\n getFontSize(record, context),\n color,\n context.scale,\n positioning.rotation,\n anchorOverride ?? positioning.anchor,\n )\n}\n\nfunction createDirectText(\n id: string,\n text: string,\n location: AltiumPoint,\n fontSize: number,\n color: string,\n scale: number,\n rotation: number,\n anchor: SchematicText[\"anchor\"],\n): SchematicText {\n return {\n type: \"schematic_text\",\n schematic_text_id: id,\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n text,\n font_size: Math.max(fontSize * scale, 0.2),\n position: scalePoint(location, scale),\n rotation,\n anchor,\n color,\n }\n}\n\nfunction getFontSize(record: AltiumRecord, context: SchematicContext): number {\n const fontId = Math.max(\n Math.round(Number(record.getCaseInsensitive(\"FONTID\") ?? 1)),\n 1,\n )\n return Math.max(\n Number(context.sheetRecord?.getCaseInsensitive(`SIZE${fontId}`) ?? 9),\n 1,\n )\n}\n\nfunction getFontFamily(\n record: AltiumRecord,\n context: SchematicContext,\n): string {\n const fontId = Math.max(\n Math.round(Number(record.getCaseInsensitive(\"FONTID\") ?? 1)),\n 1,\n )\n return context.sheetRecord?.getDecoded(`FONTNAME${fontId}`) ?? \"Arial\"\n}\n\nfunction getTextPositioning(record: AltiumRecord): {\n anchor: SchematicText[\"anchor\"]\n rotation: number\n} {\n const justification = Math.min(\n Math.max(Math.round(record.getNumber(\"JUSTIFICATION\") ?? 0), 0),\n 8,\n )\n const orientation =\n ((Math.round(record.getNumber(\"ORIENTATION\") ?? 0) % 4) + 4) % 4\n let column = justification % 3\n const row = Math.floor(justification / 3)\n if (orientation === 2 || orientation === 3) column = 2 - column\n const horizontal = [\"left\", \"center\", \"right\"][column] ?? \"left\"\n const vertical = [\"bottom\", \"center\", \"top\"][row] ?? \"bottom\"\n const anchor =\n horizontal === \"center\" && vertical === \"center\"\n ? \"center\"\n : (`${vertical}_${horizontal}` as SchematicText[\"anchor\"])\n return {\n anchor,\n rotation: orientation === 1 || orientation === 3 ? 90 : 0,\n }\n}\n\nfunction shouldRenderSchematicRecord(\n record: AltiumRecord,\n context: SchematicContext,\n): boolean {\n let ownerPartId = record.getNumber(\"OWNERPARTID\")\n let ownerPartDisplayMode = record.getNumber(\"OWNERPARTDISPLAYMODE\")\n let current: AltiumRecord | undefined = record\n const visited = new Set<AltiumRecord>()\n\n while (current && !visited.has(current)) {\n visited.add(current)\n const parent = context.document.getParent(current)\n if (!parent) return true\n\n if (ownerPartId === undefined || ownerPartId <= 0) {\n ownerPartId = current.getNumber(\"OWNERPARTID\")\n }\n if (ownerPartDisplayMode === undefined) {\n ownerPartDisplayMode = current.getNumber(\"OWNERPARTDISPLAYMODE\")\n }\n\n if (parent.recordKind === \"1\") {\n const currentPartId = parent.getNumber(\"CURRENTPARTID\") ?? 1\n return (\n (ownerPartId === undefined ||\n ownerPartId <= 0 ||\n ownerPartId === currentPartId) &&\n (ownerPartDisplayMode === undefined || ownerPartDisplayMode === 0)\n )\n }\n current = parent\n }\n return true\n}\n\nfunction getLocation(record: AltiumRecord): AltiumPoint | undefined {\n if (\n record.getCaseInsensitive(\"LOCATION.X\") === undefined ||\n record.getCaseInsensitive(\"LOCATION.Y\") === undefined\n ) {\n return undefined\n }\n return {\n x: getCoordinate(record, \"LOCATION.X\"),\n y: getCoordinate(record, \"LOCATION.Y\"),\n }\n}\n\nfunction getCorner(record: AltiumRecord): AltiumPoint | undefined {\n if (\n record.getCaseInsensitive(\"CORNER.X\") === undefined ||\n record.getCaseInsensitive(\"CORNER.Y\") === undefined\n ) {\n return undefined\n }\n return {\n x: getCoordinate(record, \"CORNER.X\"),\n y: getCoordinate(record, \"CORNER.Y\"),\n }\n}\n\nfunction getRectangle(\n record: AltiumRecord,\n): { maxX: number; maxY: number; minX: number; minY: number } | undefined {\n const location = getLocation(record)\n const corner = getCorner(record)\n if (!location || !corner) return undefined\n return {\n minX: Math.min(location.x, corner.x),\n minY: Math.min(location.y, corner.y),\n maxX: Math.max(location.x, corner.x),\n maxY: Math.max(location.y, corner.y),\n }\n}\n\nfunction getCoordinate(\n record: AltiumRecord,\n key: string,\n fallback = 0,\n): number {\n const integerPart = Number(record.getCaseInsensitive(key) ?? fallback)\n const fractionRaw = record.getCaseInsensitive(`${key}_FRAC`)\n if (!Number.isFinite(integerPart) || fractionRaw === undefined) {\n return Number.isFinite(integerPart) ? integerPart : fallback\n }\n const fraction = Number(`0.${fractionRaw.replace(/^[+-]/u, \"\")}`)\n if (!Number.isFinite(fraction)) return integerPart\n return integerPart < 0 ? integerPart - fraction : integerPart + fraction\n}\n\nfunction scalePoint(point: AltiumPoint, scale: number): AltiumPoint {\n return { x: point.x * scale, y: point.y * scale }\n}\n\nfunction approximateEllipse(\n center: AltiumPoint,\n radiusX: number,\n radiusY: number,\n): AltiumPoint[] {\n return Array.from({ length: 49 }, (_, index) => {\n const radians = (index / 48) * Math.PI * 2\n return {\n x: center.x + Math.cos(radians) * radiusX,\n y: center.y + Math.sin(radians) * radiusY,\n }\n })\n}\n\nfunction decodeMultilineText(text: string): string {\n return text.replaceAll(\"~1\", \"\\n\").replaceAll(\"\\\\n\", \"\\n\")\n}\n\nfunction wrapSchematicText(\n text: string,\n maximumWidth: number,\n fontSize: number,\n fontFamily: string,\n): string[] {\n return text.split(\"\\n\").flatMap((paragraph) => {\n if (\n estimateSchematicTextWidth(paragraph, fontSize, fontFamily) <=\n maximumWidth\n ) {\n return [paragraph]\n }\n const words = paragraph.split(/\\s+/u)\n const lines: string[] = []\n let line = \"\"\n for (const word of words) {\n if (!line) {\n line = word\n } else if (\n estimateSchematicTextWidth(`${line} ${word}`, fontSize, fontFamily) <=\n maximumWidth\n ) {\n line = `${line} ${word}`\n } else {\n lines.push(line)\n line = word\n }\n }\n if (line) lines.push(line)\n return lines.length > 0 ? lines : [paragraph]\n })\n}\n\nfunction estimateSchematicTextWidth(\n text: string,\n fontSize: number,\n fontFamily: string,\n): number {\n if (/courier|mono/iu.test(fontFamily)) return text.length * fontSize * 0.6\n if (!/times|cambria|serif/iu.test(fontFamily)) {\n return text.length * fontSize * 0.52\n }\n\n return [...text].reduce((width, character) => {\n const emWidth =\n character === \" \"\n ? 0.23\n : /[ilI1.,:;!'`|]/u.test(character)\n ? 0.2\n : /[mwMW@%]/u.test(character)\n ? 0.7\n : /[A-Z0-9]/u.test(character)\n ? 0.5\n : 0.4\n return width + emWidth * fontSize\n }, 0)\n}\n\nfunction altiumColorToCss(raw: string | undefined, fallback: string): string {\n if (raw === undefined) return fallback\n const value = Number(raw)\n if (!Number.isInteger(value) || value < 0) return fallback\n const red = value & 0xff\n const green = (value >>> 8) & 0xff\n const blue = (value >>> 16) & 0xff\n return `#${toHex(red)}${toHex(green)}${toHex(blue)}`\n}\n\nfunction toHex(value: number): string {\n return value.toString(16).padStart(2, \"0\")\n}\n","import {\n type AltiumPoint,\n type AltiumRecord,\n type AltiumSchDoc,\n getSchematicDocumentIndex,\n getSchematicRecordPoints,\n} from \"altiumts\"\nimport {\n type AnyCircuitElement,\n type SchematicComponent,\n type SchematicNetLabel,\n type SchematicPort,\n type SchematicText,\n type SchematicTrace,\n type SourceComponentBase,\n type SourceNet,\n type SourcePort,\n type SourceTrace,\n source_simple_capacitor,\n source_simple_crystal,\n source_simple_inductor,\n source_simple_mosfet,\n source_simple_resistor,\n} from \"circuit-json\"\nimport { parseAndConvertSiUnit } from \"format-si-unit\"\nimport { type SchSymbol, symbols } from \"schematic-symbols\"\n\nexport interface SemanticSchematicOptions {\n includeHidden?: boolean\n includeText?: boolean\n scale: number\n schematicSheetId: string\n}\n\nexport interface SemanticSchematicConversion {\n elements: AnyCircuitElement[]\n handledRecords: Set<AltiumRecord>\n}\n\ninterface ConvertedPort {\n isSchematicVisible: boolean\n point: AltiumPoint\n record: AltiumRecord\n schematicPort: SchematicPort\n sourcePort: SourcePort\n}\n\ninterface SymbolPortAssignment {\n convertedPort: ConvertedPort\n symbolPort: SchSymbol[\"ports\"][number]\n}\n\ninterface SymbolSelection {\n assignments: SymbolPortAssignment[]\n name: string\n symbol: SchSymbol\n}\n\ninterface SemanticNet {\n id: string\n names: string[]\n points: AltiumPoint[]\n records: AltiumRecord[]\n}\n\ninterface SemanticNetGraph {\n getConnectedWiresForRecord(record: AltiumRecord): AltiumRecord[]\n nets: SemanticNet[]\n}\n\ninterface Bounds {\n maxX: number\n maxY: number\n minX: number\n minY: number\n}\n\ntype CardinalDirection = \"up\" | \"down\" | \"left\" | \"right\"\n\nconst DIRECTION_BY_ORIENTATION: readonly CardinalDirection[] = [\n \"right\",\n \"up\",\n \"left\",\n \"down\",\n]\n\nconst VECTOR_BY_DIRECTION: Readonly<Record<CardinalDirection, AltiumPoint>> = {\n down: { x: 0, y: -1 },\n left: { x: -1, y: 0 },\n right: { x: 1, y: 0 },\n up: { x: 0, y: 1 },\n}\n\nconst CARDINAL_DIRECTIONS: readonly CardinalDirection[] = [\n \"right\",\n \"up\",\n \"left\",\n \"down\",\n]\n\nconst SYMBOL_CATALOG = symbols as Record<string, SchSymbol | undefined>\nconst SYMBOL_NAMES = Object.keys(SYMBOL_CATALOG)\n\n/**\n * Converts records that have native Circuit JSON semantics before the\n * primitive fallback runs. This deliberately favors Circuit JSON's component,\n * port, trace, net, and symbol model over reproducing Altium's drawing style.\n */\nexport function convertSemanticSchematic(\n document: AltiumSchDoc,\n options: SemanticSchematicOptions,\n): SemanticSchematicConversion {\n const handledRecords = new Set<AltiumRecord>()\n const elements: AnyCircuitElement[] = []\n const convertedPorts: ConvertedPort[] = []\n\n convertComponents({\n convertedPorts,\n document,\n elements,\n handledRecords,\n options,\n })\n\n const semanticNetGraph = buildSemanticNetGraph(document, convertedPorts)\n\n const connectivity = convertConnectivity({\n convertedPorts,\n document,\n elements,\n handledRecords,\n semanticNetGraph,\n options,\n })\n\n convertNetLabels({\n connectivity,\n document,\n elements,\n handledRecords,\n semanticNetGraph,\n options,\n })\n\n return { elements, handledRecords }\n}\n\nfunction convertComponents(params: {\n convertedPorts: ConvertedPort[]\n document: AltiumSchDoc\n elements: AnyCircuitElement[]\n handledRecords: Set<AltiumRecord>\n options: SemanticSchematicOptions\n}): void {\n const { convertedPorts, document, elements, handledRecords, options } = params\n const documentIndex = getSchematicDocumentIndex(document)\n const sourceComponentIdByDesignator = new Map<string, string>()\n\n for (const [componentIndex, componentRecord] of document.records.entries()) {\n if (componentRecord.recordKind !== \"1\") continue\n handledRecords.add(componentRecord)\n\n const ownedRecords = documentIndex.getOwnedRecords(componentRecord)\n for (const ownedRecord of ownedRecords) handledRecords.add(ownedRecord)\n\n const currentPartId = componentRecord.getNumber(\"CURRENTPARTID\") ?? 1\n const visibleOwnedRecords = ownedRecords.filter((record) =>\n isOwnedRecordVisible(record, currentPartId),\n )\n const pins = visibleOwnedRecords.filter(\n (record) =>\n record.recordKind === \"2\" &&\n (!isPinHidden(record) || options.includeHidden === true),\n )\n if (pins.length === 0) continue\n\n const designator =\n findOwnedText(ownedRecords, \"34\", \"Designator\") ??\n componentRecord.getDecoded(\"DESIGNATOR\") ??\n `U${componentIndex}`\n const value =\n findOwnedText(ownedRecords, \"41\", \"Comment\") ??\n componentRecord.getDecoded(\"COMMENT\") ??\n componentRecord.getDecoded(\"DESIGNITEMID\") ??\n componentRecord.getDecoded(\"LIBREFERENCE\") ??\n \"\"\n const libraryReference =\n componentRecord.getDecoded(\"LIBREFERENCE\") ??\n componentRecord.getDecoded(\"DESIGNITEMID\") ??\n designator\n const manufacturerPartNumber = findOwnedText(\n ownedRecords,\n \"41\",\n \"Mfr_part_number\",\n )\n const normalizedDesignator = designator.trim().toUpperCase()\n const existingSourceComponentId =\n sourceComponentIdByDesignator.get(normalizedDesignator)\n const sourceComponentId =\n existingSourceComponentId ?? `source_component_altium_${componentIndex}`\n const schematicComponentId = `schematic_component_altium_${componentIndex}`\n if (!existingSourceComponentId) {\n sourceComponentIdByDesignator.set(normalizedDesignator, sourceComponentId)\n elements.push(\n createSourceComponent({\n designator,\n libraryReference,\n manufacturerPartNumber,\n pinCount: pins.length,\n sourceComponentId,\n value,\n }),\n )\n }\n\n const componentPorts = pins.map((pin, pinIndex) =>\n convertComponentPin({\n document,\n options,\n pin,\n pinIndex,\n schematicComponentId,\n sourceComponentId,\n }),\n )\n const bodyBounds = getComponentBodyBounds(\n visibleOwnedRecords,\n componentPorts.map(({ point }) => point),\n )\n const symbolSelection = selectCircuitJsonSymbol({\n designator,\n libraryReference,\n ports: componentPorts,\n })\n const center = scalePoint(getBoundsCenter(bodyBounds), options.scale)\n const size = symbolSelection\n ? { ...symbolSelection.symbol.size }\n : {\n height: Math.max(\n (bodyBounds.maxY - bodyBounds.minY) * options.scale,\n 0.4,\n ),\n width: Math.max(\n (bodyBounds.maxX - bodyBounds.minX) * options.scale,\n 0.4,\n ),\n }\n if (symbolSelection) {\n applyNativeSymbolPortGeometry({\n center,\n selection: symbolSelection,\n })\n }\n convertedPorts.push(...componentPorts)\n elements.push(\n ...componentPorts.flatMap(\n ({ isSchematicVisible, sourcePort, schematicPort }) => [\n sourcePort,\n ...(isSchematicVisible ? [schematicPort] : []),\n ],\n ),\n )\n const schematicComponent: SchematicComponent = {\n type: \"schematic_component\",\n center,\n // circuit-to-svg uses this flag as the renderable component gate for\n // both generated boxes and components selected by symbol_name.\n is_box_with_pins: true,\n schematic_component_id: schematicComponentId,\n schematic_sheet_id: options.schematicSheetId,\n size,\n source_component_id: sourceComponentId,\n symbol_display_value: value,\n ...(symbolSelection ? { symbol_name: symbolSelection.name } : {}),\n }\n elements.push(schematicComponent)\n\n if (!symbolSelection && options.includeText !== false) {\n elements.push(\n createComponentText({\n anchor: \"bottom_left\",\n component: schematicComponent,\n id: `schematic_component_designator_altium_${componentIndex}`,\n position: {\n x: center.x - size.width / 2,\n y: center.y + size.height / 2 + 0.13,\n },\n text: designator,\n }),\n )\n if (value) {\n elements.push(\n createComponentText({\n anchor: \"top_left\",\n component: schematicComponent,\n id: `schematic_component_value_altium_${componentIndex}`,\n position: {\n x: center.x - size.width / 2,\n y: center.y - size.height / 2 - 0.13,\n },\n text: value,\n }),\n )\n }\n }\n }\n}\n\nfunction convertComponentPin(params: {\n document: AltiumSchDoc\n options: SemanticSchematicOptions\n pin: AltiumRecord\n pinIndex: number\n schematicComponentId: string\n sourceComponentId: string\n}): ConvertedPort {\n const {\n document,\n options,\n pin,\n pinIndex,\n schematicComponentId,\n sourceComponentId,\n } = params\n const recordIndex = document.records.indexOf(pin)\n const pinConglomerate = pin.getNumber(\"PINCONGLOMERATE\")\n const orientation = (pinConglomerate ?? pin.getNumber(\"ORIENTATION\") ?? 0) & 3\n const direction = DIRECTION_BY_ORIENTATION[orientation] ?? \"right\"\n const directionVector = VECTOR_BY_DIRECTION[direction]\n const location = getLocation(pin) ?? { x: 0, y: 0 }\n const pinLength = Math.max(pin.getNumber(\"PINLENGTH\") ?? 10, 0)\n const terminalPoint = {\n x: location.x + directionVector.x * pinLength,\n y: location.y + directionVector.y * pinLength,\n }\n const designator = pin.getDecoded(\"DESIGNATOR\") ?? `${pinIndex + 1}`\n const pinNumber = parsePinNumber(designator)\n const name = pin.getDecoded(\"NAME\") ?? designator\n const sourcePortId = `source_port_altium_${recordIndex}`\n const schematicPortId = `schematic_port_altium_${recordIndex}`\n const sourcePort: SourcePort = {\n type: \"source_port\",\n name,\n port_hints: uniqueStrings([\n designator,\n name,\n pinNumber === undefined ? undefined : `pin${pinNumber}`,\n ]),\n source_component_id: sourceComponentId,\n source_port_id: sourcePortId,\n ...(pinNumber === undefined ? {} : { pin_number: pinNumber }),\n }\n const electricalType = pin.getNumber(\"ELECTRICAL\")\n const schematicPort: SchematicPort = {\n type: \"schematic_port\",\n center: scalePoint(terminalPoint, options.scale),\n display_pin_label: name,\n distance_from_component_edge: pinLength * options.scale,\n facing_direction: direction,\n is_connected: false,\n schematic_component_id: schematicComponentId,\n schematic_port_id: schematicPortId,\n schematic_sheet_id: options.schematicSheetId,\n side_of_component: directionToSide(direction),\n source_port_id: sourcePortId,\n true_ccw_index: pinIndex,\n ...(pinNumber === undefined ? {} : { pin_number: pinNumber }),\n ...(electricalType === 0 || electricalType === 1\n ? { has_input_arrow: true }\n : {}),\n ...(electricalType === 1 || electricalType === 2\n ? { has_output_arrow: true }\n : {}),\n }\n return {\n isSchematicVisible: true,\n point: terminalPoint,\n record: pin,\n schematicPort,\n sourcePort,\n }\n}\n\nfunction createSourceComponent(params: {\n designator: string\n libraryReference: string\n manufacturerPartNumber?: string\n pinCount: number\n sourceComponentId: string\n value: string\n}): AnyCircuitElement {\n const {\n designator,\n libraryReference,\n manufacturerPartNumber,\n pinCount,\n sourceComponentId,\n value,\n } = params\n const classification = classifyComponent({ designator, libraryReference })\n const primaryValue = getPrimaryComponentValue(value)\n const common = {\n type: \"source_component\" as const,\n display_name: designator,\n display_value: value || undefined,\n manufacturer_part_number: manufacturerPartNumber,\n name: designator,\n source_component_id: sourceComponentId,\n }\n\n if (classification === \"resistor\") {\n const parsed = source_simple_resistor.safeParse({\n ...common,\n display_resistance: value || undefined,\n ftype: \"simple_resistor\",\n resistance: primaryValue || 0,\n })\n if (parsed.success) return parsed.data\n }\n if (classification === \"capacitor\") {\n const parsed = source_simple_capacitor.safeParse({\n ...common,\n display_capacitance: value || undefined,\n ftype: \"simple_capacitor\",\n capacitance: primaryValue || 0,\n })\n if (parsed.success) return parsed.data\n }\n if (classification === \"inductor\") {\n const parsed = source_simple_inductor.safeParse({\n ...common,\n display_inductance: value || undefined,\n ftype: \"simple_inductor\",\n inductance: primaryValue || 0,\n })\n if (parsed.success) return parsed.data\n }\n if (classification === \"crystal\" && (pinCount === 2 || pinCount === 4)) {\n const frequency = parseAndConvertSiUnit(value, \"Hz\").value\n if (typeof frequency === \"number\" && Number.isFinite(frequency)) {\n const parsed = source_simple_crystal.safeParse({\n ...common,\n frequency,\n ftype: \"simple_crystal\",\n pin_variant: pinCount === 4 ? \"four_pin\" : \"two_pin\",\n })\n if (parsed.success) return parsed.data\n }\n }\n if (classification === \"mosfet\" && pinCount >= 3) {\n const parsed = source_simple_mosfet.safeParse({\n ...common,\n ...getMosfetVariant(libraryReference),\n ftype: \"simple_mosfet\",\n })\n if (parsed.success) return parsed.data\n }\n\n const ftype:\n | \"simple_chip\"\n | \"simple_diode\"\n | \"simple_led\"\n | \"simple_test_point\" =\n classification === \"diode\"\n ? \"simple_diode\"\n : classification === \"led\"\n ? \"simple_led\"\n : classification === \"testpoint\"\n ? \"simple_test_point\"\n : \"simple_chip\"\n return {\n ...common,\n ftype,\n } satisfies SourceComponentBase\n}\n\nfunction createComponentText(params: {\n anchor: SchematicText[\"anchor\"]\n component: SchematicComponent\n id: string\n position: AltiumPoint\n text: string\n}): SchematicText {\n const { anchor, component, id, position, text } = params\n return {\n type: \"schematic_text\",\n anchor,\n color: \"#006464\",\n font_size: 0.18,\n position,\n rotation: 0,\n schematic_component_id: component.schematic_component_id,\n schematic_sheet_id: component.schematic_sheet_id,\n schematic_text_id: id,\n text,\n }\n}\n\n/**\n * Altium permits labels and pin hot spots to land anywhere on a wire segment,\n * not only on declared polyline vertices. Build the electrical graph with\n * those geometric joins so Circuit JSON source traces carry the real ports and\n * net names. Mid-segment crossings remain disconnected unless one wire has a\n * vertex there or Altium emits an explicit junction record.\n */\nfunction buildSemanticNetGraph(\n document: AltiumSchDoc,\n convertedPorts: ConvertedPort[],\n): SemanticNetGraph {\n const disjointSet = new PointDisjointSet()\n const pointValues = new Map<string, AltiumPoint>()\n const wireRecords = document.records.filter(\n (record) => record.recordKind === \"27\",\n )\n const segments: Array<{ end: AltiumPoint; start: AltiumPoint }> = []\n\n for (const wire of wireRecords) {\n const points = getSchematicRecordPoints(wire)\n for (const point of points) {\n addGraphPoint(disjointSet, pointValues, point)\n }\n for (let index = 1; index < points.length; index++) {\n const start = points[index - 1]\n const end = points[index]\n if (!start || !end) continue\n disjointSet.union(pointKey(start), pointKey(end))\n segments.push({ end, start })\n }\n }\n\n const positionedRecords = document.records.flatMap((record) => {\n if (![\"4\", \"17\", \"18\", \"25\", \"29\"].includes(record.recordKind ?? \"\")) {\n return []\n }\n const point = getLocation(record)\n return point ? [{ point, record }] : []\n })\n const positionedPins = convertedPorts.map(({ point, record }) => ({\n point,\n record,\n }))\n const joinPoints = [\n ...new Map(\n wireRecords\n .flatMap((wire) => getSchematicRecordPoints(wire))\n .map((point) => [pointKey(point), point]),\n ).values(),\n ...positionedRecords.map(({ point }) => point),\n ...positionedPins.map(({ point }) => point),\n ]\n\n for (const point of joinPoints) {\n addGraphPoint(disjointSet, pointValues, point)\n for (const segment of segments) {\n if (isPointOnSegment(point, segment.start, segment.end)) {\n disjointSet.union(pointKey(point), pointKey(segment.start))\n }\n }\n }\n\n interface MutableSemanticNet {\n id: string\n names: Set<string>\n points: Map<string, AltiumPoint>\n records: Set<AltiumRecord>\n }\n const groupedByRoot = new Map<string, MutableSemanticNet>()\n const getGroup = (point: AltiumPoint): MutableSemanticNet => {\n const root = disjointSet.find(pointKey(point))\n const existing = groupedByRoot.get(root)\n if (existing) return existing\n const created: MutableSemanticNet = {\n id: root,\n names: new Set(),\n points: new Map(),\n records: new Set(),\n }\n groupedByRoot.set(root, created)\n return created\n }\n\n for (const point of pointValues.values()) {\n getGroup(point).points.set(pointKey(point), point)\n }\n for (const wire of wireRecords) {\n const firstPoint = getSchematicRecordPoints(wire)[0]\n if (firstPoint) getGroup(firstPoint).records.add(wire)\n }\n for (const { point, record } of [...positionedRecords, ...positionedPins]) {\n const group = getGroup(point)\n group.records.add(record)\n const name = getElectricalRecordName(record)\n if (name) group.names.add(name)\n }\n\n const connectedWiresByRecord = new Map<AltiumRecord, AltiumRecord[]>()\n for (const group of groupedByRoot.values()) {\n const wires = [...group.records].filter(\n (record) => record.recordKind === \"27\",\n )\n for (const record of group.records) {\n connectedWiresByRecord.set(record, wires)\n }\n }\n\n const mergedGroups: MutableSemanticNet[] = []\n for (const group of groupedByRoot.values()) {\n if (group.records.size === 0) continue\n const normalizedNames = new Set(\n [...group.names].map((name) => name.trim().toUpperCase()),\n )\n const matches = mergedGroups.filter((candidate) =>\n [...candidate.names].some((name) =>\n normalizedNames.has(name.trim().toUpperCase()),\n ),\n )\n if (matches.length === 0 || normalizedNames.size === 0) {\n mergedGroups.push(group)\n continue\n }\n const target = matches[0]\n if (!target) continue\n mergeSemanticNetGroup(target, group)\n for (const duplicate of matches.slice(1)) {\n mergeSemanticNetGroup(target, duplicate)\n const duplicateIndex = mergedGroups.indexOf(duplicate)\n if (duplicateIndex >= 0) mergedGroups.splice(duplicateIndex, 1)\n }\n }\n\n const nets: SemanticNet[] = mergedGroups.map((group) => ({\n id: group.id,\n names: [...group.names],\n points: [...group.points.values()],\n records: [...group.records],\n }))\n return {\n getConnectedWiresForRecord: (record) =>\n connectedWiresByRecord.get(record) ?? [],\n nets,\n }\n}\n\nfunction addGraphPoint(\n disjointSet: PointDisjointSet,\n pointValues: Map<string, AltiumPoint>,\n point: AltiumPoint,\n): void {\n const key = pointKey(point)\n disjointSet.add(key)\n pointValues.set(key, point)\n}\n\nfunction getElectricalRecordName(record: AltiumRecord): string | undefined {\n if (record.recordKind === \"18\") return record.getDecoded(\"NAME\")\n if ([\"4\", \"17\", \"25\"].includes(record.recordKind ?? \"\")) {\n return record.getDecoded(\"TEXT\")\n }\n return undefined\n}\n\nfunction mergeSemanticNetGroup(\n target: {\n names: Set<string>\n points: Map<string, AltiumPoint>\n records: Set<AltiumRecord>\n },\n source: {\n names: Set<string>\n points: Map<string, AltiumPoint>\n records: Set<AltiumRecord>\n },\n): void {\n for (const name of source.names) target.names.add(name)\n for (const [key, point] of source.points) target.points.set(key, point)\n for (const record of source.records) target.records.add(record)\n}\n\nfunction isPointOnSegment(\n point: AltiumPoint,\n start: AltiumPoint,\n end: AltiumPoint,\n): boolean {\n const dx = end.x - start.x\n const dy = end.y - start.y\n const cross = (point.x - start.x) * dy - (point.y - start.y) * dx\n const tolerance = 0.000001 * Math.max(Math.abs(dx), Math.abs(dy), 1)\n if (Math.abs(cross) > tolerance) return false\n const dot = (point.x - start.x) * dx + (point.y - start.y) * dy\n if (dot < -tolerance) return false\n const lengthSquared = dx * dx + dy * dy\n return dot <= lengthSquared + tolerance\n}\n\nfunction splitSegmentAtPoints(\n start: AltiumPoint,\n end: AltiumPoint,\n candidates: AltiumPoint[],\n): AltiumPoint[] {\n const dx = end.x - start.x\n const dy = end.y - start.y\n const lengthSquared = dx * dx + dy * dy\n if (lengthSquared === 0) return [start]\n\n const pointsByKey = new Map<string, AltiumPoint>([\n [pointKey(start), start],\n [pointKey(end), end],\n ])\n for (const candidate of candidates) {\n if (isPointOnSegment(candidate, start, end)) {\n pointsByKey.set(pointKey(candidate), candidate)\n }\n }\n return [...pointsByKey.values()].sort((left, right) => {\n const leftDistance = (left.x - start.x) * dx + (left.y - start.y) * dy\n const rightDistance = (right.x - start.x) * dx + (right.y - start.y) * dy\n return leftDistance - rightDistance\n })\n}\n\nclass PointDisjointSet {\n private readonly parent = new Map<string, string>()\n\n add(value: string): void {\n if (!this.parent.has(value)) this.parent.set(value, value)\n }\n\n find(value: string): string {\n this.add(value)\n const parent = this.parent.get(value) ?? value\n if (parent === value) return value\n const root = this.find(parent)\n this.parent.set(value, root)\n return root\n }\n\n union(left: string, right: string): void {\n const leftRoot = this.find(left)\n const rightRoot = this.find(right)\n if (leftRoot !== rightRoot) this.parent.set(rightRoot, leftRoot)\n }\n}\n\ninterface ConnectivityConversion {\n sourceNetIdByRecord: Map<AltiumRecord, string>\n sourceNetIdByName: Map<string, string>\n schematicTraceIdByRecord: Map<AltiumRecord, string>\n}\n\nfunction convertConnectivity(params: {\n convertedPorts: ConvertedPort[]\n document: AltiumSchDoc\n elements: AnyCircuitElement[]\n handledRecords: Set<AltiumRecord>\n options: SemanticSchematicOptions\n semanticNetGraph: SemanticNetGraph\n}): ConnectivityConversion {\n const {\n convertedPorts,\n document,\n elements,\n handledRecords,\n options,\n semanticNetGraph: graph,\n } = params\n const sourceNetIdByName = new Map<string, string>()\n const sourceNetIdByRecord = new Map<AltiumRecord, string>()\n const schematicTraceIdByRecord = new Map<AltiumRecord, string>()\n const portsByPoint = groupByPoint(convertedPorts)\n\n for (const [netIndex, net] of graph.nets.entries()) {\n const wires = net.records.filter((record) => record.recordKind === \"27\")\n const connectedConvertedPorts = uniqueConvertedPorts(\n net.points.flatMap((point) => portsByPoint.get(pointKey(point)) ?? []),\n )\n const connectedPorts = connectedConvertedPorts.map(\n ({ sourcePort }) => sourcePort.source_port_id,\n )\n if (\n wires.length === 0 &&\n !(\n (net.names.length > 0 && connectedPorts.length > 0) ||\n connectedPorts.length > 1\n )\n ) {\n continue\n }\n const sourceNetIds = net.names.map((name) =>\n getOrCreateSourceNet({\n elements,\n name,\n sourceNetIdByName,\n }),\n )\n for (const record of net.records) {\n const firstSourceNetId = sourceNetIds[0]\n if (firstSourceNetId) sourceNetIdByRecord.set(record, firstSourceNetId)\n }\n\n const sourceTraceId = `source_trace_altium_${netIndex}`\n const sourceTrace: SourceTrace = {\n type: \"source_trace\",\n connected_source_net_ids: sourceNetIds,\n connected_source_port_ids: connectedPorts,\n display_name: net.names[0],\n name: net.names[0],\n source_trace_id: sourceTraceId,\n }\n elements.push(sourceTrace)\n\n const netJunctions = document.records\n .filter(\n (record) =>\n record.recordKind === \"29\" &&\n net.points.some((point) => pointsEqual(point, getLocation(record))),\n )\n .flatMap((record) => {\n handledRecords.add(record)\n const location = getLocation(record)\n return location ? [scalePoint(location, options.scale)] : []\n })\n\n for (const wire of wires) handledRecords.add(wire)\n const prunedSegmentKeys = getEquivalentPortPrunedSegmentKeys({\n convertedPorts: connectedConvertedPorts,\n net,\n wires,\n })\n let renderedWireIndex = 0\n for (const wire of wires) {\n const wireRecordIndex = document.records.indexOf(wire)\n const schematicTraceId = `schematic_trace_altium_${wireRecordIndex}`\n const points = getSchematicRecordPoints(wire)\n const edges: SchematicTrace[\"edges\"] = []\n for (let pointIndex = 1; pointIndex < points.length; pointIndex++) {\n const from = points[pointIndex - 1]\n const to = points[pointIndex]\n if (!from || !to) continue\n const segmentPoints = splitSegmentAtPoints(from, to, net.points)\n for (\n let segmentPointIndex = 1;\n segmentPointIndex < segmentPoints.length;\n segmentPointIndex++\n ) {\n const segmentFrom = segmentPoints[segmentPointIndex - 1]\n const segmentTo = segmentPoints[segmentPointIndex]\n if (!segmentFrom || !segmentTo) continue\n if (prunedSegmentKeys.has(segmentKey(segmentFrom, segmentTo))) {\n continue\n }\n const fromPort = portsByPoint\n .get(pointKey(segmentFrom))\n ?.find((port) => port.isSchematicVisible)\n const toPort = portsByPoint\n .get(pointKey(segmentTo))\n ?.find((port) => port.isSchematicVisible)\n const fromPortId = getPortIdAtElectricalPoint(\n fromPort,\n segmentFrom,\n options.scale,\n )\n const toPortId = getPortIdAtElectricalPoint(\n toPort,\n segmentTo,\n options.scale,\n )\n edges.push({\n from: scalePoint(segmentFrom, options.scale),\n to: scalePoint(segmentTo, options.scale),\n ...(fromPortId ? { from_schematic_port_id: fromPortId } : {}),\n ...(toPortId ? { to_schematic_port_id: toPortId } : {}),\n })\n }\n }\n if (edges.length === 0) continue\n schematicTraceIdByRecord.set(wire, schematicTraceId)\n elements.push({\n type: \"schematic_trace\",\n edges,\n junctions: renderedWireIndex === 0 ? netJunctions : [],\n schematic_sheet_id: options.schematicSheetId,\n schematic_trace_id: schematicTraceId,\n source_trace_id: sourceTraceId,\n } satisfies SchematicTrace)\n renderedWireIndex++\n }\n\n for (const convertedPort of connectedConvertedPorts) {\n if (!convertedPort.isSchematicVisible) continue\n const electricalTerminal = scalePoint(convertedPort.point, options.scale)\n if (pointsEqual(convertedPort.schematicPort.center, electricalTerminal)) {\n continue\n }\n const portRecordIndex = document.records.indexOf(convertedPort.record)\n elements.push({\n type: \"schematic_trace\",\n edges: createPortLeadEdges(convertedPort, electricalTerminal),\n junctions: [],\n schematic_sheet_id: options.schematicSheetId,\n schematic_trace_id: `schematic_trace_altium_port_lead_${portRecordIndex}`,\n source_trace_id: sourceTraceId,\n } satisfies SchematicTrace)\n }\n\n const connectedPortIds = new Set(connectedPorts)\n for (const convertedPort of convertedPorts) {\n if (\n convertedPort.isSchematicVisible &&\n connectedPortIds.has(convertedPort.sourcePort.source_port_id)\n ) {\n convertedPort.schematicPort.is_connected = true\n }\n }\n }\n\n return {\n schematicTraceIdByRecord,\n sourceNetIdByName,\n sourceNetIdByRecord,\n }\n}\n\nfunction getEquivalentPortPrunedSegmentKeys(params: {\n convertedPorts: ConvertedPort[]\n net: SemanticNet\n wires: AltiumRecord[]\n}): Set<string> {\n const { convertedPorts, net, wires } = params\n const hiddenPortPoints = convertedPorts\n .filter((port) => !port.isSchematicVisible)\n .map((port) => port.point)\n if (hiddenPortPoints.length === 0) return new Set()\n\n const protectedPointKeys = new Set(\n convertedPorts\n .filter((port) => port.isSchematicVisible)\n .map((port) => pointKey(port.point)),\n )\n for (const record of net.records) {\n if (![\"4\", \"17\", \"18\", \"25\"].includes(record.recordKind ?? \"\")) continue\n const location = getLocation(record)\n if (location) protectedPointKeys.add(pointKey(location))\n }\n\n interface PrunableSegment {\n endKey: string\n key: string\n startKey: string\n }\n const segments = new Map<string, PrunableSegment>()\n const segmentKeysByPoint = new Map<string, Set<string>>()\n const addIncidentSegment = (point: AltiumPoint, key: string): void => {\n const pointSegments = segmentKeysByPoint.get(pointKey(point))\n if (pointSegments) pointSegments.add(key)\n else segmentKeysByPoint.set(pointKey(point), new Set([key]))\n }\n\n for (const wire of wires) {\n const wirePoints = getSchematicRecordPoints(wire)\n for (let pointIndex = 1; pointIndex < wirePoints.length; pointIndex++) {\n const from = wirePoints[pointIndex - 1]\n const to = wirePoints[pointIndex]\n if (!from || !to) continue\n const segmentPoints = splitSegmentAtPoints(from, to, net.points)\n for (\n let splitIndex = 1;\n splitIndex < segmentPoints.length;\n splitIndex++\n ) {\n const segmentFrom = segmentPoints[splitIndex - 1]\n const segmentTo = segmentPoints[splitIndex]\n if (!segmentFrom || !segmentTo) continue\n const key = segmentKey(segmentFrom, segmentTo)\n segments.set(key, {\n endKey: pointKey(segmentTo),\n key,\n startKey: pointKey(segmentFrom),\n })\n addIncidentSegment(segmentFrom, key)\n addIncidentSegment(segmentTo, key)\n }\n }\n }\n\n const removedSegmentKeys = new Set<string>()\n const pendingPointKeys = hiddenPortPoints.map((point) => pointKey(point))\n while (pendingPointKeys.length > 0) {\n const currentPointKey = pendingPointKeys.shift()\n if (!currentPointKey || protectedPointKeys.has(currentPointKey)) continue\n const activeSegmentKeys = [\n ...(segmentKeysByPoint.get(currentPointKey) ?? []),\n ].filter((key) => !removedSegmentKeys.has(key))\n if (activeSegmentKeys.length !== 1) continue\n const segment = segments.get(activeSegmentKeys[0] ?? \"\")\n if (!segment) continue\n removedSegmentKeys.add(segment.key)\n pendingPointKeys.push(\n segment.startKey === currentPointKey ? segment.endKey : segment.startKey,\n )\n }\n return removedSegmentKeys\n}\n\nfunction segmentKey(start: AltiumPoint, end: AltiumPoint): string {\n const startKey = pointKey(start)\n const endKey = pointKey(end)\n return startKey < endKey ? `${startKey}|${endKey}` : `${endKey}|${startKey}`\n}\n\nfunction createPortLeadEdges(\n convertedPort: ConvertedPort,\n electricalTerminal: AltiumPoint,\n): SchematicTrace[\"edges\"] {\n const portCenter = convertedPort.schematicPort.center\n const facingDirection =\n convertedPort.schematicPort.facing_direction ?? \"right\"\n const elbow =\n facingDirection === \"left\" || facingDirection === \"right\"\n ? { x: electricalTerminal.x, y: portCenter.y }\n : { x: portCenter.x, y: electricalTerminal.y }\n const points = [portCenter, elbow, electricalTerminal].filter(\n (point, index, allPoints) =>\n index === 0 || !pointsEqual(point, allPoints[index - 1]),\n )\n\n return points.slice(1).flatMap((to, index) => {\n const from = points[index]\n if (!from) return []\n return [\n {\n from,\n ...(index === 0\n ? {\n from_schematic_port_id:\n convertedPort.schematicPort.schematic_port_id,\n }\n : {}),\n to,\n },\n ]\n })\n}\n\nfunction convertNetLabels(params: {\n connectivity: ConnectivityConversion\n document: AltiumSchDoc\n elements: AnyCircuitElement[]\n handledRecords: Set<AltiumRecord>\n options: SemanticSchematicOptions\n semanticNetGraph: SemanticNetGraph\n}): void {\n const {\n connectivity,\n document,\n elements,\n handledRecords,\n options,\n semanticNetGraph: graph,\n } = params\n\n for (const [recordIndex, record] of document.records.entries()) {\n const recordKind = record.recordKind\n if (!recordKind || ![\"4\", \"17\", \"18\", \"25\"].includes(recordKind)) {\n continue\n }\n if (record.getBoolean(\"ISHIDDEN\") && options.includeHidden !== true) {\n handledRecords.add(record)\n continue\n }\n const name =\n record.recordKind === \"18\"\n ? record.getDecoded(\"NAME\")\n : record.getDecoded(\"TEXT\")\n const location = getLocation(record)\n if (!name || !location) continue\n const wire = graph.getConnectedWiresForRecord(record)[0]\n // Altium's generic label record is also used for page titles and notes.\n // It is only an electrical net label when it touches a wire.\n if (recordKind === \"4\" && !wire) continue\n handledRecords.add(record)\n\n const sourceNetId =\n connectivity.sourceNetIdByRecord.get(record) ??\n getOrCreateSourceNet({\n elements,\n name,\n sourceNetIdByName: connectivity.sourceNetIdByName,\n })\n const schematicTraceId = wire\n ? connectivity.schematicTraceIdByRecord.get(wire)\n : undefined\n const direction = getRecordDirection(record)\n const symbolName =\n record.recordKind === \"17\"\n ? getPowerPortSymbolName(record, direction)\n : undefined\n const schematicNetLabel: SchematicNetLabel = {\n type: \"schematic_net_label\",\n anchor_position: scalePoint(location, options.scale),\n anchor_side:\n record.recordKind === \"18\" || record.recordKind === \"4\"\n ? \"left\"\n : directionToOppositeSide(direction),\n center: scalePoint(location, options.scale),\n schematic_net_label_id: `schematic_net_label_altium_${recordIndex}`,\n schematic_sheet_id: options.schematicSheetId,\n source_net_id: sourceNetId,\n text: name,\n ...(schematicTraceId ? { schematic_trace_id: schematicTraceId } : {}),\n ...(symbolName ? { symbol_name: symbolName } : {}),\n }\n elements.push(schematicNetLabel)\n }\n}\n\nfunction getOrCreateSourceNet(params: {\n elements: AnyCircuitElement[]\n name: string\n sourceNetIdByName: Map<string, string>\n}): string {\n const { elements, name, sourceNetIdByName } = params\n const normalizedName = name.trim().toUpperCase()\n const existing = sourceNetIdByName.get(normalizedName)\n if (existing) return existing\n\n const sourceNetIdBase = `source_net_altium_${sanitizeId(name)}`\n const existingIds = new Set(\n elements.flatMap((element) =>\n element.type === \"source_net\" ? [element.source_net_id] : [],\n ),\n )\n let sourceNetId = sourceNetIdBase\n let suffix = 2\n while (existingIds.has(sourceNetId)) {\n sourceNetId = `${sourceNetIdBase}_${suffix}`\n suffix++\n }\n const sourceNet: SourceNet = {\n type: \"source_net\",\n is_ground: isGroundNet(name),\n is_power: isPowerNet(name),\n member_source_group_ids: [],\n name,\n source_net_id: sourceNetId,\n }\n elements.push(sourceNet)\n sourceNetIdByName.set(normalizedName, sourceNetId)\n return sourceNetId\n}\n\nfunction selectCircuitJsonSymbol(params: {\n designator: string\n libraryReference: string\n ports: ConvertedPort[]\n}): SymbolSelection | undefined {\n const { designator, libraryReference, ports } = params\n const classification = classifyComponent({ designator, libraryReference })\n let baseName: string | undefined\n let candidateNames: string[] = []\n if (classification === \"testpoint\" && ports.length === 1) {\n baseName = \"testpoint\"\n } else if (classification === \"crystal\" && ports.length === 2) {\n baseName = \"crystal\"\n } else if (classification === \"crystal\" && ports.length === 4) {\n baseName = \"crystal_4pin\"\n } else if (\n classification === \"mosfet\" &&\n ports.length >= 3 &&\n hasCompleteMosfetFunctionalGroups(ports)\n ) {\n const { channel_type, mosfet_mode } = getMosfetVariant(libraryReference)\n const channel = channel_type === \"p\" ? \"p\" : \"n\"\n const mode = mosfet_mode === \"depletion\" ? \"d\" : \"e\"\n const prefix = `${channel}_channel_${mode}_mosfet_transistor_gate_`\n candidateNames = SYMBOL_NAMES.filter((name) => name.startsWith(prefix))\n } else if (ports.length !== 2) {\n return undefined\n } else if (classification === \"resistor\") {\n baseName = \"boxresistor\"\n } else if (classification === \"capacitor\") {\n baseName = isPolarizedCapacitor(libraryReference)\n ? \"capacitor_polarized\"\n : \"capacitor\"\n } else if (classification === \"ferrite_bead\") {\n baseName = \"ferrite_bead\"\n } else if (classification === \"inductor\") {\n baseName = \"inductor\"\n } else if (classification === \"led\") {\n baseName = \"led\"\n }\n if (classification === \"diode\") {\n const lower = libraryReference.toLowerCase()\n baseName = lower.includes(\"schottky\") ? \"schottky_diode\" : \"diode\"\n }\n if (baseName) {\n candidateNames = CARDINAL_DIRECTIONS.map(\n (direction) => `${baseName}_${direction}`,\n )\n }\n if (candidateNames.length === 0) return undefined\n\n const selections = candidateNames.flatMap((name) => {\n const symbol = SYMBOL_CATALOG[name]\n const supportsEquivalentMosfetPads =\n classification === \"mosfet\" && symbol?.ports.length === 3\n if (\n !symbol ||\n (!supportsEquivalentMosfetPads && symbol.ports.length !== ports.length)\n ) {\n return []\n }\n const assignments = assignConvertedPortsToSymbolPorts(ports, symbol, {\n allowFunctionalPortReuse: classification === \"mosfet\",\n geometryInterchangeableLabels:\n classification === \"crystal\" && ports.length === 4\n ? new Set([\"2\", \"4\"])\n : undefined,\n })\n return assignments.length === ports.length\n ? [{ assignments, name, symbol } satisfies SymbolSelection]\n : []\n })\n return selections.sort(\n (left, right) =>\n getSymbolDirectionScore(left) - getSymbolDirectionScore(right),\n )[0]\n}\n\nfunction hasCompleteMosfetFunctionalGroups(ports: ConvertedPort[]): boolean {\n const groups = ports.map((port) =>\n normalizeFunctionalPortLabel(port.sourcePort.name),\n )\n return (\n groups.every((group) => group !== undefined) && new Set(groups).size === 3\n )\n}\n\nfunction assignConvertedPortsToSymbolPorts(\n ports: ConvertedPort[],\n symbol: SchSymbol,\n options: {\n allowFunctionalPortReuse?: boolean\n geometryInterchangeableLabels?: Set<string>\n } = {},\n): SymbolPortAssignment[] {\n const unusedSymbolPorts = new Set(symbol.ports)\n const orderedPorts = [...ports].sort(compareConvertedPorts)\n const assignments: SymbolPortAssignment[] = []\n const convertedCenter = getAveragePoint(ports.map(({ point }) => point))\n\n for (const [portIndex, convertedPort] of orderedPorts.entries()) {\n const rawHints = [\n convertedPort.schematicPort.pin_number?.toString(),\n convertedPort.sourcePort.name,\n ...(convertedPort.sourcePort.port_hints ?? []),\n ].filter((hint): hint is string => Boolean(hint))\n const functionalHints = new Set(\n rawHints.flatMap((hint) => {\n const normalized = normalizeFunctionalPortLabel(hint)\n return normalized ? [normalized] : []\n }),\n )\n const functionalPortCandidates = options.allowFunctionalPortReuse\n ? symbol.ports\n : [...unusedSymbolPorts]\n const functionalSymbolPort = functionalPortCandidates.find((symbolPort) =>\n symbolPort.labels.some((label) => {\n const normalized = normalizeFunctionalPortLabel(label)\n return normalized ? functionalHints.has(normalized) : false\n }),\n )\n const exactHints = new Set(rawHints.map((hint) => hint.toLowerCase()))\n const exactSymbolPort = [...unusedSymbolPorts].find((symbolPort) =>\n symbolPort.labels.some((label) => exactHints.has(label.toLowerCase())),\n )\n const interchangeableLabels = options.geometryInterchangeableLabels\n const isGeometryInterchangeable = rawHints.some((hint) =>\n interchangeableLabels?.has(hint.toLowerCase()),\n )\n const geometrySymbolPort = isGeometryInterchangeable\n ? [...unusedSymbolPorts]\n .filter((symbolPort) =>\n symbolPort.labels.some((label) =>\n interchangeableLabels?.has(label.toLowerCase()),\n ),\n )\n .sort(\n (left, right) =>\n getVectorDifference(\n subtractPoints(convertedPort.point, convertedCenter),\n subtractPoints(left, symbol.center),\n ) -\n getVectorDifference(\n subtractPoints(convertedPort.point, convertedCenter),\n subtractPoints(right, symbol.center),\n ),\n )[0]\n : undefined\n const symbolPort =\n functionalSymbolPort ??\n geometrySymbolPort ??\n exactSymbolPort ??\n symbol.ports[portIndex] ??\n [...unusedSymbolPorts][0]\n if (!symbolPort) continue\n if (!functionalSymbolPort || !options.allowFunctionalPortReuse) {\n unusedSymbolPorts.delete(symbolPort)\n }\n assignments.push({ convertedPort, symbolPort })\n }\n return assignments\n}\n\nfunction getAveragePoint(points: AltiumPoint[]): AltiumPoint {\n if (points.length === 0) return { x: 0, y: 0 }\n return {\n x: points.reduce((sum, point) => sum + point.x, 0) / points.length,\n y: points.reduce((sum, point) => sum + point.y, 0) / points.length,\n }\n}\n\nfunction compareConvertedPorts(\n left: ConvertedPort,\n right: ConvertedPort,\n): number {\n const leftPinNumber = left.schematicPort.pin_number\n const rightPinNumber = right.schematicPort.pin_number\n if (leftPinNumber !== undefined && rightPinNumber !== undefined) {\n return leftPinNumber - rightPinNumber\n }\n return (\n (left.schematicPort.true_ccw_index ?? 0) -\n (right.schematicPort.true_ccw_index ?? 0)\n )\n}\n\nfunction getSymbolDirectionScore(selection: SymbolSelection): number {\n const [first, second] = selection.assignments\n if (!first) return Number.POSITIVE_INFINITY\n if (!second) {\n const expectedDirection =\n VECTOR_BY_DIRECTION[\n first.convertedPort.schematicPort.facing_direction ?? \"right\"\n ]\n return getVectorDifference(\n expectedDirection,\n subtractPoints(first.symbolPort, selection.symbol.center),\n )\n }\n let difference = 0\n let comparisonCount = 0\n for (\n let firstIndex = 0;\n firstIndex < selection.assignments.length;\n firstIndex++\n ) {\n for (\n let secondIndex = firstIndex + 1;\n secondIndex < selection.assignments.length;\n secondIndex++\n ) {\n const firstAssignment = selection.assignments[firstIndex]\n const secondAssignment = selection.assignments[secondIndex]\n if (!firstAssignment || !secondAssignment) continue\n const pairDifference = getVectorDifference(\n subtractPoints(\n secondAssignment.convertedPort.point,\n firstAssignment.convertedPort.point,\n ),\n subtractPoints(secondAssignment.symbolPort, firstAssignment.symbolPort),\n )\n if (!Number.isFinite(pairDifference)) continue\n difference += pairDifference\n comparisonCount++\n }\n }\n return comparisonCount > 0\n ? difference / comparisonCount\n : Number.POSITIVE_INFINITY\n}\n\nfunction normalizeFunctionalPortLabel(value: string): string | undefined {\n const normalized = value.toLowerCase().replace(/[^a-z]/gu, \"\")\n if (normalized === \"g\" || normalized === \"gate\") return \"gate\"\n if (normalized === \"d\" || normalized === \"drain\") return \"drain\"\n if (normalized === \"s\" || normalized === \"source\") return \"source\"\n return undefined\n}\n\nfunction getVectorDifference(left: AltiumPoint, right: AltiumPoint): number {\n const leftLength = Math.hypot(left.x, left.y)\n const rightLength = Math.hypot(right.x, right.y)\n if (leftLength === 0 || rightLength === 0) {\n return Number.POSITIVE_INFINITY\n }\n const cosine =\n (left.x * right.x + left.y * right.y) / (leftLength * rightLength)\n return 1 - Math.max(-1, Math.min(1, cosine))\n}\n\nfunction applyNativeSymbolPortGeometry(params: {\n center: AltiumPoint\n selection: SymbolSelection\n}): void {\n const { center, selection } = params\n const assignmentsBySymbolPort = new Map<\n SchSymbol[\"ports\"][number],\n SymbolPortAssignment[]\n >()\n for (const assignment of selection.assignments) {\n const assignments = assignmentsBySymbolPort.get(assignment.symbolPort)\n if (assignments) assignments.push(assignment)\n else assignmentsBySymbolPort.set(assignment.symbolPort, [assignment])\n }\n\n for (const [symbolPort, assignments] of assignmentsBySymbolPort) {\n const offset = subtractPoints(symbolPort, selection.symbol.center)\n const direction = getDirectionForVector(offset)\n const symbolPortCenter = {\n x: center.x + offset.x,\n y: center.y + offset.y,\n }\n const representative = assignments.sort(\n (left, right) =>\n getPointDistance(\n left.convertedPort.schematicPort.center,\n symbolPortCenter,\n ) -\n getPointDistance(\n right.convertedPort.schematicPort.center,\n symbolPortCenter,\n ),\n )[0]\n for (const { convertedPort } of assignments) {\n convertedPort.isSchematicVisible =\n convertedPort === representative?.convertedPort\n convertedPort.schematicPort.center = symbolPortCenter\n convertedPort.schematicPort.distance_from_component_edge = Math.hypot(\n offset.x,\n offset.y,\n )\n convertedPort.schematicPort.facing_direction = direction\n convertedPort.schematicPort.side_of_component = directionToSide(direction)\n }\n }\n}\n\nfunction getPointDistance(left: AltiumPoint, right: AltiumPoint): number {\n return Math.hypot(left.x - right.x, left.y - right.y)\n}\n\nfunction getDirectionForVector(vector: AltiumPoint): CardinalDirection {\n if (Math.abs(vector.x) >= Math.abs(vector.y)) {\n return vector.x >= 0 ? \"right\" : \"left\"\n }\n return vector.y >= 0 ? \"up\" : \"down\"\n}\n\nfunction subtractPoints(\n left: { x: number; y: number },\n right: { x: number; y: number },\n): AltiumPoint {\n return { x: left.x - right.x, y: left.y - right.y }\n}\n\nfunction classifyComponent(params: {\n designator: string\n libraryReference: string\n}):\n | \"capacitor\"\n | \"crystal\"\n | \"diode\"\n | \"ferrite_bead\"\n | \"inductor\"\n | \"led\"\n | \"mosfet\"\n | \"resistor\"\n | \"testpoint\"\n | \"unknown\" {\n const { designator, libraryReference } = params\n const prefix = designator.match(/^[A-Z]+/iu)?.[0]?.toUpperCase() ?? \"\"\n const lowerReference = libraryReference.toLowerCase()\n if (prefix === \"TP\" || lowerReference.includes(\"testpoint\")) {\n return \"testpoint\"\n }\n if (\n prefix === \"Y\" ||\n lowerReference.includes(\"crystal\") ||\n /(?:^|[_-])cry(?:\\d|[_-]|$)/iu.test(libraryReference)\n ) {\n return \"crystal\"\n }\n if (lowerReference.includes(\"mosfet\")) return \"mosfet\"\n if (\n prefix === \"FB\" ||\n prefix === \"FL\" ||\n lowerReference.includes(\"ferrite\") ||\n lowerReference.includes(\"emifilter_ind\")\n ) {\n return \"ferrite_bead\"\n }\n if (prefix === \"LED\" || lowerReference.includes(\"led\")) return \"led\"\n if (prefix === \"R\" || lowerReference.includes(\"resistor\")) return \"resistor\"\n if (prefix === \"C\" || /(?:^|[_-])cap(?:[_-]|$)/iu.test(libraryReference)) {\n return \"capacitor\"\n }\n if (prefix === \"L\" || lowerReference.includes(\"inductor\")) return \"inductor\"\n if (prefix === \"D\" || lowerReference.includes(\"diode\")) return \"diode\"\n return \"unknown\"\n}\n\nfunction getMosfetVariant(libraryReference: string): {\n channel_type: \"n\" | \"p\"\n mosfet_mode: \"depletion\" | \"enhancement\"\n} {\n const lowerReference = libraryReference.toLowerCase()\n const isPChannel =\n /(?:^|[_-])p(?:channel)?(?:[_-]|$)/iu.test(libraryReference) ||\n lowerReference.includes(\"pmos\") ||\n lowerReference.includes(\"csd25\")\n return {\n channel_type: isPChannel ? \"p\" : \"n\",\n mosfet_mode: lowerReference.includes(\"depletion\")\n ? \"depletion\"\n : \"enhancement\",\n }\n}\n\nfunction isPolarizedCapacitor(libraryReference: string): boolean {\n return /(?:^|[_-])cap(?:acitor)?[_-]?pol(?:arized)?(?:[_-]|$)/iu.test(\n libraryReference,\n )\n}\n\nfunction getPrimaryComponentValue(value: string): string {\n return value.split(/[_/\\s]+/u).find(Boolean) ?? value\n}\n\nfunction getPowerPortSymbolName(\n record: AltiumRecord,\n direction: CardinalDirection,\n): string {\n const style = Math.round(record.getNumber(\"STYLE\") ?? 2)\n if (style === 4) return `digital_ground_${direction}`\n if (style === 5) return `ground_${direction}`\n if (style === 6) return `tilted_ground_${direction}`\n return `vcc_${direction}`\n}\n\nfunction getComponentBodyBounds(\n records: AltiumRecord[],\n portPoints: AltiumPoint[],\n): Bounds {\n const rectangles = records\n .filter((record) => record.recordKind === \"14\")\n .flatMap((record) => {\n const rectangle = getRectangle(record)\n return rectangle ? [rectangle] : []\n })\n if (rectangles.length > 0) return mergeBounds(rectangles)\n\n const points: AltiumPoint[] = []\n for (const record of records) {\n if (record.recordKind === \"2\") continue\n const location = getLocation(record)\n const corner = getCorner(record)\n if (location && corner) points.push(location, corner)\n points.push(...getSchematicRecordPoints(record))\n if (record.recordKind === \"8\" && location) {\n const radiusX = Math.abs(record.getNumber(\"RADIUS\") ?? 0)\n const radiusY = Math.abs(record.getNumber(\"SECONDARYRADIUS\") ?? radiusX)\n points.push(\n { x: location.x - radiusX, y: location.y - radiusY },\n { x: location.x + radiusX, y: location.y + radiusY },\n )\n }\n }\n if (points.length > 0) return getBoundsForPoints(points)\n const bounds = getBoundsForPoints(portPoints)\n if (bounds.minX === bounds.maxX) {\n bounds.minX -= 2\n bounds.maxX += 2\n }\n if (bounds.minY === bounds.maxY) {\n bounds.minY -= 2\n bounds.maxY += 2\n }\n return bounds\n}\n\nfunction findOwnedText(\n records: AltiumRecord[],\n recordKind: string,\n name: string,\n): string | undefined {\n return records\n .find(\n (record) =>\n record.recordKind === recordKind &&\n record.getDecoded(\"NAME\")?.toLowerCase() === name.toLowerCase(),\n )\n ?.getDecoded(\"TEXT\")\n}\n\nfunction isOwnedRecordVisible(\n record: AltiumRecord,\n currentPartId: number,\n): boolean {\n const ownerPartId = record.getNumber(\"OWNERPARTID\")\n const ownerPartDisplayMode = record.getNumber(\"OWNERPARTDISPLAYMODE\")\n return (\n (ownerPartId === undefined ||\n ownerPartId <= 0 ||\n ownerPartId === currentPartId) &&\n (ownerPartDisplayMode === undefined || ownerPartDisplayMode === 0)\n )\n}\n\nfunction isPinHidden(pin: AltiumRecord): boolean {\n const pinConglomerate = pin.getNumber(\"PINCONGLOMERATE\")\n return (\n pin.getBoolean(\"ISHIDDEN\") === true ||\n (pinConglomerate !== undefined && (pinConglomerate & 0x04) !== 0)\n )\n}\n\nfunction getRecordDirection(record: AltiumRecord): CardinalDirection {\n const orientation =\n ((Math.round(record.getNumber(\"ORIENTATION\") ?? 0) % 4) + 4) % 4\n return DIRECTION_BY_ORIENTATION[orientation] ?? \"right\"\n}\n\nfunction directionToSide(\n direction: CardinalDirection,\n): NonNullable<SchematicPort[\"side_of_component\"]> {\n if (direction === \"up\") return \"top\"\n if (direction === \"down\") return \"bottom\"\n return direction\n}\n\nfunction directionToOppositeSide(\n direction: CardinalDirection,\n): SchematicNetLabel[\"anchor_side\"] {\n if (direction === \"up\") return \"bottom\"\n if (direction === \"down\") return \"top\"\n return direction === \"left\" ? \"right\" : \"left\"\n}\n\nfunction groupByPoint(ports: ConvertedPort[]): Map<string, ConvertedPort[]> {\n const grouped = new Map<string, ConvertedPort[]>()\n for (const port of ports) {\n const key = pointKey(port.point)\n const existing = grouped.get(key)\n if (existing) existing.push(port)\n else grouped.set(key, [port])\n }\n return grouped\n}\n\nfunction uniqueConvertedPorts(ports: ConvertedPort[]): ConvertedPort[] {\n const seenSourcePortIds = new Set<string>()\n return ports.filter((port) => {\n const sourcePortId = port.sourcePort.source_port_id\n if (seenSourcePortIds.has(sourcePortId)) return false\n seenSourcePortIds.add(sourcePortId)\n return true\n })\n}\n\nfunction getPortIdAtElectricalPoint(\n port: ConvertedPort | undefined,\n electricalPoint: AltiumPoint,\n scale: number,\n): string | undefined {\n if (!port?.isSchematicVisible) return undefined\n return pointsEqual(\n port.schematicPort.center,\n scalePoint(electricalPoint, scale),\n )\n ? port.schematicPort.schematic_port_id\n : undefined\n}\n\nfunction getBoundsForPoints(points: AltiumPoint[]): Bounds {\n if (points.length === 0) return { maxX: 1, maxY: 1, minX: -1, minY: -1 }\n return {\n maxX: Math.max(...points.map((point) => point.x)),\n maxY: Math.max(...points.map((point) => point.y)),\n minX: Math.min(...points.map((point) => point.x)),\n minY: Math.min(...points.map((point) => point.y)),\n }\n}\n\nfunction mergeBounds(bounds: Bounds[]): Bounds {\n return {\n maxX: Math.max(...bounds.map((bound) => bound.maxX)),\n maxY: Math.max(...bounds.map((bound) => bound.maxY)),\n minX: Math.min(...bounds.map((bound) => bound.minX)),\n minY: Math.min(...bounds.map((bound) => bound.minY)),\n }\n}\n\nfunction getBoundsCenter(bounds: Bounds): AltiumPoint {\n return {\n x: (bounds.minX + bounds.maxX) / 2,\n y: (bounds.minY + bounds.maxY) / 2,\n }\n}\n\nfunction getRectangle(record: AltiumRecord): Bounds | undefined {\n const location = getLocation(record)\n const corner = getCorner(record)\n if (!location || !corner) return undefined\n return {\n maxX: Math.max(location.x, corner.x),\n maxY: Math.max(location.y, corner.y),\n minX: Math.min(location.x, corner.x),\n minY: Math.min(location.y, corner.y),\n }\n}\n\nfunction getLocation(record: AltiumRecord): AltiumPoint | undefined {\n const x = getCoordinate(record, \"LOCATION.X\")\n const y = getCoordinate(record, \"LOCATION.Y\")\n return x === undefined || y === undefined ? undefined : { x, y }\n}\n\nfunction getCorner(record: AltiumRecord): AltiumPoint | undefined {\n const x = getCoordinate(record, \"CORNER.X\")\n const y = getCoordinate(record, \"CORNER.Y\")\n return x === undefined || y === undefined ? undefined : { x, y }\n}\n\nfunction getCoordinate(record: AltiumRecord, key: string): number | undefined {\n const raw = record.getCaseInsensitive(key)\n if (raw === undefined) return undefined\n const integer = Number(raw)\n if (!Number.isFinite(integer)) return undefined\n const fractionRaw = record.getCaseInsensitive(`${key}_FRAC`)\n if (fractionRaw === undefined) return integer\n const fraction = Number(`0.${fractionRaw.replace(/^[+-]/u, \"\")}`)\n if (!Number.isFinite(fraction)) return integer\n return integer < 0 ? integer - fraction : integer + fraction\n}\n\nfunction parsePinNumber(value: string): number | undefined {\n const parsed = Number(value)\n return Number.isInteger(parsed) && parsed >= 0 ? parsed : undefined\n}\n\nfunction scalePoint(point: AltiumPoint, scale: number): AltiumPoint {\n return { x: point.x * scale, y: point.y * scale }\n}\n\nfunction pointKey(point: AltiumPoint): string {\n return `${point.x.toFixed(6)},${point.y.toFixed(6)}`\n}\n\nfunction pointsEqual(\n left: AltiumPoint,\n right: AltiumPoint | undefined,\n): boolean {\n return (\n right !== undefined &&\n Math.abs(left.x - right.x) < 0.000001 &&\n Math.abs(left.y - right.y) < 0.000001\n )\n}\n\nfunction uniqueStrings(values: Array<string | undefined>): string[] {\n return [...new Set(values.filter((value): value is string => Boolean(value)))]\n}\n\nfunction sanitizeId(value: string): string {\n const sanitized = value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/gu, \"_\")\n .replace(/^_+|_+$/gu, \"\")\n return sanitized || \"unnamed\"\n}\n\nfunction isGroundNet(name: string): boolean {\n return /(?:^|[_+-])(?:[adp]?gnd|ground)(?:$|[_+\\d-])/iu.test(name)\n}\n\nfunction isPowerNet(name: string): boolean {\n return (\n isGroundNet(name) ||\n /(?:^|[_+-])(?:vcc|vdd|vss)(?:$|[a-z0-9_+-])/iu.test(name) ||\n /(?:^|[_+-])(?:vin|vout|pwr|power)(?:$|[_+\\d-])/iu.test(name)\n )\n}\n","import {\n AltiumBinaryPcbDoc,\n AltiumPcbDoc,\n type AltiumPcbDocument,\n AltiumSchDoc,\n parseAltiumFile,\n parseAltiumPcbDoc,\n parseAltiumSchDoc,\n} from \"altiumts\"\nimport type { AnyCircuitElement } from \"circuit-json\"\nimport {\n type ConvertAltiumPcbDocOptions,\n convertAltiumPcbDocToCircuitJson,\n} from \"./convert-altium-pcb-doc-to-circuit-json\"\nimport {\n type ConvertAltiumSchDocOptions,\n convertAltiumSchDocToCircuitJson,\n} from \"./convert-altium-sch-doc-to-circuit-json\"\n\nexport type AltiumSourceType = \"auto\" | \"pcb\" | \"schematic\"\n\nexport interface ConvertAltiumToCircuitJsonOptions {\n pcb?: ConvertAltiumPcbDocOptions\n schematic?: ConvertAltiumSchDocOptions\n sourceType?: AltiumSourceType\n}\n\nexport type SupportedAltiumDocument = AltiumPcbDocument | AltiumSchDoc\n\nexport function convertAltiumToCircuitJson(\n source: ArrayBuffer | Uint8Array | string,\n options: ConvertAltiumToCircuitJsonOptions = {},\n): AnyCircuitElement[] {\n const sourceType = options.sourceType ?? \"auto\"\n\n if (sourceType === \"pcb\") {\n if (typeof source === \"string\") {\n return convertAltiumPcbDocToCircuitJson(\n parseAltiumPcbDoc(source),\n options.pcb,\n )\n }\n const { document } = parseAltiumFile(toUint8Array(source))\n if (\n !(document instanceof AltiumPcbDoc) &&\n !(document instanceof AltiumBinaryPcbDoc)\n ) {\n throw new TypeError(\n `Expected an Altium PCB document, got ${document.type}`,\n )\n }\n return convertAltiumPcbDocToCircuitJson(document, options.pcb)\n }\n if (sourceType === \"schematic\") {\n return convertAltiumSchDocToCircuitJson(\n parseAltiumSchDoc(normalizeSchematicSource(source)),\n options.schematic,\n )\n }\n\n const bytes = toUint8Array(source)\n const { document } = parseAltiumFile(bytes)\n return convertAltiumDocumentToCircuitJson(document, options)\n}\n\nexport function convertAltiumDocumentToCircuitJson(\n document: unknown,\n options: ConvertAltiumToCircuitJsonOptions = {},\n): AnyCircuitElement[] {\n if (document instanceof AltiumSchDoc) {\n return convertAltiumSchDocToCircuitJson(document, options.schematic)\n }\n if (\n document instanceof AltiumPcbDoc ||\n document instanceof AltiumBinaryPcbDoc\n ) {\n return convertAltiumPcbDocToCircuitJson(document, options.pcb)\n }\n const type =\n typeof document === \"object\" && document !== null && \"type\" in document\n ? String(document.type)\n : typeof document\n throw new TypeError(`Unsupported Altium document type: ${type}`)\n}\n\nfunction toUint8Array(source: ArrayBuffer | Uint8Array | string): Uint8Array {\n if (typeof source === \"string\") return new TextEncoder().encode(source)\n if (source instanceof Uint8Array) return source\n return new Uint8Array(source)\n}\n\nfunction normalizeSchematicSource(\n source: ArrayBuffer | Uint8Array | string,\n): Uint8Array | string {\n return source instanceof ArrayBuffer ? new Uint8Array(source) : source\n}\n"],"mappings":"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","names":["getSchematicRecordPoints","symbolPort","getSchematicRecordPoints","scalePoint","getLocation","getCorner","getRectangle","getCoordinate","document"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "altium-to-circuit-json",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "Convert Altium schematic and PCB documents into Circuit JSON",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",