altium-to-circuit-json 0.0.13 → 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +128 -5
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -695,6 +695,11 @@ var CARDINAL_DIRECTIONS = [
|
|
|
695
695
|
];
|
|
696
696
|
var SYMBOL_CATALOG = symbols;
|
|
697
697
|
var SYMBOL_NAMES = Object.keys(SYMBOL_CATALOG);
|
|
698
|
+
var INLINE_NET_LABEL_COLOR = "rgb(132, 0, 0)";
|
|
699
|
+
var DEFAULT_INLINE_NET_LABEL_FONT_SIZE = 0.18;
|
|
700
|
+
var MIN_INLINE_NET_LABEL_FONT_SIZE = 0.1;
|
|
701
|
+
var INLINE_NET_LABEL_CHARACTER_WIDTH = 0.12;
|
|
702
|
+
var INLINE_NET_LABEL_HORIZONTAL_PADDING = 0.12;
|
|
698
703
|
function convertSemanticSchematic(document, options) {
|
|
699
704
|
const handledRecords = /* @__PURE__ */ new Set();
|
|
700
705
|
const elements = [];
|
|
@@ -742,6 +747,12 @@ function convertComponents(params) {
|
|
|
742
747
|
(record) => record.recordKind === "2" && (!isPinHidden(record) || options.includeHidden === true)
|
|
743
748
|
);
|
|
744
749
|
if (pins.length === 0) continue;
|
|
750
|
+
const visibleSymbolLabels = new Set(
|
|
751
|
+
visibleOwnedRecords.filter((record) => record.recordKind === "4").flatMap((record) => {
|
|
752
|
+
const text = record.getDecoded("TEXT")?.trim().toUpperCase();
|
|
753
|
+
return text ? [text] : [];
|
|
754
|
+
})
|
|
755
|
+
);
|
|
745
756
|
const designator = findOwnedText(ownedRecords, "34", "Designator") ?? componentRecord.getDecoded("DESIGNATOR") ?? `U${componentIndex}`;
|
|
746
757
|
const value = findOwnedText(ownedRecords, "41", "Comment") ?? componentRecord.getDecoded("COMMENT") ?? componentRecord.getDecoded("DESIGNITEMID") ?? componentRecord.getDecoded("LIBREFERENCE") ?? "";
|
|
747
758
|
const libraryReference = componentRecord.getDecoded("LIBREFERENCE") ?? componentRecord.getDecoded("DESIGNITEMID") ?? designator;
|
|
@@ -774,7 +785,8 @@ function convertComponents(params) {
|
|
|
774
785
|
pin,
|
|
775
786
|
pinIndex,
|
|
776
787
|
schematicComponentId,
|
|
777
|
-
sourceComponentId
|
|
788
|
+
sourceComponentId,
|
|
789
|
+
visibleSymbolLabels
|
|
778
790
|
})
|
|
779
791
|
);
|
|
780
792
|
const bodyBounds = getComponentBodyBounds(
|
|
@@ -863,7 +875,8 @@ function convertComponentPin(params) {
|
|
|
863
875
|
pin,
|
|
864
876
|
pinIndex,
|
|
865
877
|
schematicComponentId,
|
|
866
|
-
sourceComponentId
|
|
878
|
+
sourceComponentId,
|
|
879
|
+
visibleSymbolLabels
|
|
867
880
|
} = params;
|
|
868
881
|
const recordIndex = document.records.indexOf(pin);
|
|
869
882
|
const pinConglomerate = pin.getNumber("PINCONGLOMERATE");
|
|
@@ -894,10 +907,13 @@ function convertComponentPin(params) {
|
|
|
894
907
|
...pinNumber === void 0 ? {} : { pin_number: pinNumber }
|
|
895
908
|
};
|
|
896
909
|
const electricalType = pin.getNumber("ELECTRICAL");
|
|
910
|
+
const normalizedName = name.trim().toUpperCase();
|
|
911
|
+
const functionalName = normalizedName.replace(/\d+$/u, "");
|
|
912
|
+
const showName = pinConglomerate === void 0 || (pinConglomerate & 8) !== 0 || visibleSymbolLabels.has(normalizedName) || visibleSymbolLabels.has(functionalName);
|
|
897
913
|
const schematicPort = {
|
|
898
914
|
type: "schematic_port",
|
|
899
915
|
center: scalePoint(terminalPoint, options.scale),
|
|
900
|
-
display_pin_label: name,
|
|
916
|
+
...showName && name ? { display_pin_label: name } : {},
|
|
901
917
|
distance_from_component_edge: pinLength * options.scale,
|
|
902
918
|
facing_direction: direction,
|
|
903
919
|
is_connected: false,
|
|
@@ -1201,6 +1217,8 @@ function convertConnectivity(params) {
|
|
|
1201
1217
|
} = params;
|
|
1202
1218
|
const sourceNetIdByName = /* @__PURE__ */ new Map();
|
|
1203
1219
|
const sourceNetIdByRecord = /* @__PURE__ */ new Map();
|
|
1220
|
+
const sourcePortCountByRecord = /* @__PURE__ */ new Map();
|
|
1221
|
+
const sourceTraceIdByRecord = /* @__PURE__ */ new Map();
|
|
1204
1222
|
const schematicTraceIdByRecord = /* @__PURE__ */ new Map();
|
|
1205
1223
|
const portsByPoint = groupByPoint(convertedPorts);
|
|
1206
1224
|
for (const [netIndex, net] of graph.nets.entries()) {
|
|
@@ -1226,6 +1244,10 @@ function convertConnectivity(params) {
|
|
|
1226
1244
|
if (firstSourceNetId) sourceNetIdByRecord.set(record, firstSourceNetId);
|
|
1227
1245
|
}
|
|
1228
1246
|
const sourceTraceId = `source_trace_altium_${netIndex}`;
|
|
1247
|
+
for (const record of net.records) {
|
|
1248
|
+
sourcePortCountByRecord.set(record, connectedPorts.length);
|
|
1249
|
+
sourceTraceIdByRecord.set(record, sourceTraceId);
|
|
1250
|
+
}
|
|
1229
1251
|
const sourceTrace = {
|
|
1230
1252
|
type: "source_trace",
|
|
1231
1253
|
connected_source_net_ids: sourceNetIds,
|
|
@@ -1324,7 +1346,9 @@ function convertConnectivity(params) {
|
|
|
1324
1346
|
return {
|
|
1325
1347
|
schematicTraceIdByRecord,
|
|
1326
1348
|
sourceNetIdByName,
|
|
1327
|
-
sourceNetIdByRecord
|
|
1349
|
+
sourceNetIdByRecord,
|
|
1350
|
+
sourcePortCountByRecord,
|
|
1351
|
+
sourceTraceIdByRecord
|
|
1328
1352
|
};
|
|
1329
1353
|
}
|
|
1330
1354
|
function getEquivalentPortPrunedSegmentKeys(params) {
|
|
@@ -1433,8 +1457,27 @@ function convertNetLabels(params) {
|
|
|
1433
1457
|
const name = record.recordKind === "18" ? record.getDecoded("NAME") : record.getDecoded("TEXT");
|
|
1434
1458
|
const location = getLocation(record);
|
|
1435
1459
|
if (!name || !location) continue;
|
|
1436
|
-
const
|
|
1460
|
+
const connectedWires = graph.getConnectedWiresForRecord(record);
|
|
1461
|
+
const wire = connectedWires[0];
|
|
1437
1462
|
if (recordKind === "4" && !wire) continue;
|
|
1463
|
+
const sourceTraceId = connectivity.sourceTraceIdByRecord.get(record);
|
|
1464
|
+
const shouldRenderInline = Boolean(sourceTraceId) && (recordKind === "25" || recordKind === "18" && (record.getNumber("IOTYPE") ?? 0) === 0 && connectivity.sourcePortCountByRecord.get(record) === 2 && !isPowerNet(name));
|
|
1465
|
+
if (shouldRenderInline && sourceTraceId) {
|
|
1466
|
+
handledRecords.add(record);
|
|
1467
|
+
elements.push(
|
|
1468
|
+
createInlineNetLabelText({
|
|
1469
|
+
connectedWires,
|
|
1470
|
+
document,
|
|
1471
|
+
location,
|
|
1472
|
+
name,
|
|
1473
|
+
options,
|
|
1474
|
+
record,
|
|
1475
|
+
recordIndex,
|
|
1476
|
+
sourceTraceId
|
|
1477
|
+
})
|
|
1478
|
+
);
|
|
1479
|
+
continue;
|
|
1480
|
+
}
|
|
1438
1481
|
handledRecords.add(record);
|
|
1439
1482
|
const sourceNetId = connectivity.sourceNetIdByRecord.get(record) ?? getOrCreateSourceNet({
|
|
1440
1483
|
elements,
|
|
@@ -1459,6 +1502,86 @@ function convertNetLabels(params) {
|
|
|
1459
1502
|
elements.push(schematicNetLabel);
|
|
1460
1503
|
}
|
|
1461
1504
|
}
|
|
1505
|
+
function createInlineNetLabelText(params) {
|
|
1506
|
+
const {
|
|
1507
|
+
connectedWires,
|
|
1508
|
+
document,
|
|
1509
|
+
location,
|
|
1510
|
+
name,
|
|
1511
|
+
options,
|
|
1512
|
+
record,
|
|
1513
|
+
recordIndex,
|
|
1514
|
+
sourceTraceId
|
|
1515
|
+
} = params;
|
|
1516
|
+
const direction = getInlineNetLabelDirection(record, location, connectedWires);
|
|
1517
|
+
const scaledLocation = scalePoint(location, options.scale);
|
|
1518
|
+
const fontSize = getInlineNetLabelFontSize(record, document, options.scale);
|
|
1519
|
+
const fontScale = fontSize / DEFAULT_INLINE_NET_LABEL_FONT_SIZE;
|
|
1520
|
+
const textWidth = (name.length * INLINE_NET_LABEL_CHARACTER_WIDTH + INLINE_NET_LABEL_HORIZONTAL_PADDING) * fontScale;
|
|
1521
|
+
const isVertical = direction === "up" || direction === "down";
|
|
1522
|
+
const directionSign = direction === "left" || direction === "down" ? -1 : 1;
|
|
1523
|
+
const isTerminalPort = record.recordKind === "18";
|
|
1524
|
+
const anchor = isTerminalPort ? directionSign > 0 ? "left" : "right" : "center";
|
|
1525
|
+
const position = isTerminalPort ? isVertical ? {
|
|
1526
|
+
x: scaledLocation.x - fontSize / 2,
|
|
1527
|
+
y: scaledLocation.y
|
|
1528
|
+
} : {
|
|
1529
|
+
x: scaledLocation.x,
|
|
1530
|
+
y: scaledLocation.y + fontSize / 2
|
|
1531
|
+
} : isVertical ? {
|
|
1532
|
+
x: scaledLocation.x - fontSize / 2,
|
|
1533
|
+
y: scaledLocation.y + directionSign * textWidth / 2
|
|
1534
|
+
} : {
|
|
1535
|
+
x: scaledLocation.x + directionSign * textWidth / 2,
|
|
1536
|
+
y: scaledLocation.y + fontSize / 2
|
|
1537
|
+
};
|
|
1538
|
+
return {
|
|
1539
|
+
type: "schematic_text",
|
|
1540
|
+
anchor,
|
|
1541
|
+
color: INLINE_NET_LABEL_COLOR,
|
|
1542
|
+
font_size: fontSize,
|
|
1543
|
+
position,
|
|
1544
|
+
rotation: isVertical ? -90 : 0,
|
|
1545
|
+
schematic_sheet_id: options.schematicSheetId,
|
|
1546
|
+
schematic_text_id: `schematic_inline_net_label_altium_${recordIndex}`,
|
|
1547
|
+
source_trace_id: sourceTraceId,
|
|
1548
|
+
text: name
|
|
1549
|
+
};
|
|
1550
|
+
}
|
|
1551
|
+
function getInlineNetLabelFontSize(record, document, scale) {
|
|
1552
|
+
const fontId = Math.max(
|
|
1553
|
+
Math.round(Number(record.getCaseInsensitive("FONTID") ?? 1)),
|
|
1554
|
+
1
|
|
1555
|
+
);
|
|
1556
|
+
const sheetRecord = document.records.find(
|
|
1557
|
+
(candidate) => candidate.recordKind === "31"
|
|
1558
|
+
);
|
|
1559
|
+
const sourceFontSize = Number(
|
|
1560
|
+
sheetRecord?.getCaseInsensitive(`SIZE${fontId}`) ?? DEFAULT_INLINE_NET_LABEL_FONT_SIZE / scale
|
|
1561
|
+
);
|
|
1562
|
+
return Math.min(
|
|
1563
|
+
DEFAULT_INLINE_NET_LABEL_FONT_SIZE,
|
|
1564
|
+
Math.max(MIN_INLINE_NET_LABEL_FONT_SIZE, sourceFontSize * scale)
|
|
1565
|
+
);
|
|
1566
|
+
}
|
|
1567
|
+
function getInlineNetLabelDirection(record, location, connectedWires) {
|
|
1568
|
+
if (record.recordKind !== "18") return getRecordDirection(record);
|
|
1569
|
+
for (const wire of connectedWires) {
|
|
1570
|
+
const points = getSchematicRecordPoints(wire);
|
|
1571
|
+
for (let pointIndex = 1; pointIndex < points.length; pointIndex++) {
|
|
1572
|
+
const start = points[pointIndex - 1];
|
|
1573
|
+
const end = points[pointIndex];
|
|
1574
|
+
if (!start || !end || !isPointOnSegment(location, start, end)) continue;
|
|
1575
|
+
const other = pointsEqual(location, start) ? end : pointsEqual(location, end) ? start : void 0;
|
|
1576
|
+
if (!other) continue;
|
|
1577
|
+
const dx = location.x - other.x;
|
|
1578
|
+
const dy = location.y - other.y;
|
|
1579
|
+
if (Math.abs(dx) >= Math.abs(dy)) return dx < 0 ? "left" : "right";
|
|
1580
|
+
return dy < 0 ? "down" : "up";
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
return getRecordDirection(record);
|
|
1584
|
+
}
|
|
1462
1585
|
function getOrCreateSourceNet(params) {
|
|
1463
1586
|
const { elements, name, sourceNetIdByName } = params;
|
|
1464
1587
|
const normalizedName = name.trim().toUpperCase();
|
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 AltiumRegionRecord,\n AltiumTextRecord,\n AltiumTrackRecord,\n AltiumViaRecord,\n getAltiumBounds,\n getPcbLayerStack,\n getPcbRegionGeometry,\n parseAltiumMeasurementToMils,\n} from \"altiumts\"\nimport type {\n AnyCircuitElement,\n LayerRef,\n PcbBoard,\n PcbComponent,\n PcbCourtyardOutline,\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 includeCourtyards?: 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 if (\n options.includeCourtyards !== false &&\n options.includeComponents !== false\n ) {\n elements.push(...convertCourtyards(document))\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 (isCourtyardLayer(record.layer)) continue\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\ninterface CourtyardPath {\n componentId: string\n layer: \"top\" | \"bottom\"\n points: AltiumPoint[]\n strokeWidthMils: number\n}\n\nfunction convertCourtyards(document: AltiumPcbDocument): PcbCourtyardOutline[] {\n const componentIds = new Map(\n document.components.flatMap((component, index) =>\n component.position ? [[component, componentId(index)] as const] : [],\n ),\n )\n const paths: CourtyardPath[] = []\n\n for (const record of document.records) {\n const layer = getLayer(record)\n if (!isCourtyardLayer(layer)) continue\n const component = document.getComponentForRecord(record)\n const ownedComponentId = component ? componentIds.get(component) : undefined\n if (!ownedComponentId) continue\n const points = getCourtyardRecordPoints(record)\n if (points.length < 2) continue\n paths.push({\n componentId: ownedComponentId,\n layer: mapCourtyardLayer(layer),\n points,\n strokeWidthMils:\n record instanceof AltiumTrackRecord || record instanceof AltiumArcRecord\n ? (record.widthMils ?? 4)\n : 0,\n })\n }\n\n const courtyards: PcbCourtyardOutline[] = []\n for (const path of stitchCourtyardPaths(paths)) {\n if (!isClosedAltiumPath(path.points)) continue\n const outline = removeClosingPoint(path.points).map(toMillimeterPoint)\n if (outline.length < 3) continue\n courtyards.push({\n type: \"pcb_courtyard_outline\",\n pcb_courtyard_outline_id: `pcb_courtyard_outline_altium_${courtyards.length}`,\n pcb_component_id: path.componentId,\n layer: path.layer,\n outline,\n })\n }\n return courtyards\n}\n\nfunction getCourtyardRecordPoints(record: AltiumRecord): AltiumPoint[] {\n if (record instanceof AltiumTrackRecord) {\n return record.start && record.end ? [record.start, record.end] : []\n }\n if (record instanceof AltiumArcRecord) {\n return record.center && record.radiusMils\n ? approximateArc(\n record.center,\n record.radiusMils,\n record.startAngle,\n record.endAngle,\n )\n : []\n }\n if (record instanceof AltiumRegionRecord) {\n return getPcbRegionGeometry(record).outline.points\n }\n return []\n}\n\nfunction stitchCourtyardPaths(paths: CourtyardPath[]): CourtyardPath[] {\n const groups = new Map<string, CourtyardPath[]>()\n for (const path of deduplicateCourtyardPaths(paths)) {\n const key = [\n path.componentId,\n path.layer,\n path.strokeWidthMils.toFixed(4),\n ].join(\"|\")\n const group = groups.get(key) ?? []\n group.push(path)\n groups.set(key, group)\n }\n return [...groups.values()].flatMap(stitchCourtyardPathGroup)\n}\n\nfunction stitchCourtyardPathGroup(group: CourtyardPath[]): CourtyardPath[] {\n const remaining = [...group]\n const stitched: CourtyardPath[] = []\n while (remaining.length > 0) {\n const first = remaining.shift()\n if (!first) break\n const path = { ...first, points: [...first.points] }\n while (appendConnectedCourtyardPath(path, remaining)) {\n // Continue until no segment can extend either end of this path.\n }\n stitched.push(path)\n }\n return stitched\n}\n\nfunction appendConnectedCourtyardPath(\n stitched: CourtyardPath,\n remaining: CourtyardPath[],\n): boolean {\n const stitchedStart = stitched.points[0]\n const stitchedEnd = stitched.points.at(-1)\n if (!stitchedStart || !stitchedEnd) return false\n\n for (const [index, candidate] of remaining.entries()) {\n const candidateStart = candidate.points[0]\n const candidateEnd = candidate.points.at(-1)\n if (!candidateStart || !candidateEnd) continue\n if (altiumPointsApproximatelyEqual(stitchedEnd, candidateStart)) {\n stitched.points.push(...candidate.points.slice(1))\n } else if (altiumPointsApproximatelyEqual(stitchedEnd, candidateEnd)) {\n stitched.points.push(...candidate.points.toReversed().slice(1))\n } else if (altiumPointsApproximatelyEqual(stitchedStart, candidateEnd)) {\n stitched.points.unshift(...candidate.points.slice(0, -1))\n } else if (altiumPointsApproximatelyEqual(stitchedStart, candidateStart)) {\n stitched.points.unshift(...candidate.points.toReversed().slice(0, -1))\n } else {\n continue\n }\n remaining.splice(index, 1)\n return true\n }\n return false\n}\n\nfunction deduplicateCourtyardPaths(paths: CourtyardPath[]): CourtyardPath[] {\n const signatures = new Set<string>()\n return paths.filter((path) => {\n const forwardPoints = path.points.map(formatAltiumPoint).join(\"|\")\n const reversePoints = path.points\n .toReversed()\n .map(formatAltiumPoint)\n .join(\"|\")\n const pointsSignature =\n forwardPoints < reversePoints ? forwardPoints : reversePoints\n const signature = [\n path.componentId,\n path.layer,\n path.strokeWidthMils.toFixed(4),\n pointsSignature,\n ].join(\"|\")\n if (signatures.has(signature)) return false\n signatures.add(signature)\n return true\n })\n}\n\nfunction formatAltiumPoint(point: AltiumPoint): string {\n return `${point.x.toFixed(4)},${point.y.toFixed(4)}`\n}\n\nfunction isClosedAltiumPath(points: AltiumPoint[]): boolean {\n const first = points[0]\n const last = points.at(-1)\n return Boolean(first && last && altiumPointsApproximatelyEqual(first, last))\n}\n\nfunction removeClosingPoint(points: AltiumPoint[]): AltiumPoint[] {\n const first = points[0]\n const last = points.at(-1)\n return first && last && altiumPointsApproximatelyEqual(first, last)\n ? points.slice(0, -1)\n : points\n}\n\nfunction altiumPointsApproximatelyEqual(\n left: AltiumPoint,\n right: AltiumPoint,\n): boolean {\n return (\n Math.abs(left.x - right.x) <= 0.01 && Math.abs(left.y - right.y) <= 0.01\n )\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 isCourtyardLayer(layer: string | undefined): boolean {\n const normalized = normalizeLayer(layer)\n return normalized === \"MECHANICAL15\" || normalized === \"MECHANICAL16\"\n}\n\nfunction mapCourtyardLayer(layer: string | undefined): \"top\" | \"bottom\" {\n return normalizeLayer(layer) === \"MECHANICAL16\" ? \"bottom\" : \"top\"\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 SchematicGroup,\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 const schematicComponentIds = elements\n .filter(\n (\n element,\n ): element is Extract<\n AnyCircuitElement,\n { type: \"schematic_component\" }\n > => element.type === \"schematic_component\",\n )\n .map((element) => element.schematic_component_id)\n if (schematicComponentIds.length > 0) {\n elements.push({\n type: \"schematic_group\",\n schematic_group_id: \"schematic_group_altium\",\n source_group_id: \"source_group_altium\",\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: {\n x: (sheetDimensions.width * scale) / 2,\n y: (sheetDimensions.height * scale) / 2,\n },\n width: sheetDimensions.width * scale,\n height: sheetDimensions.height * scale,\n schematic_component_ids: schematicComponentIds,\n name: options.sheetName ?? \"Altium schematic\",\n } satisfies SchematicGroup)\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"]}
|
|
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 AltiumRegionRecord,\n AltiumTextRecord,\n AltiumTrackRecord,\n AltiumViaRecord,\n getAltiumBounds,\n getPcbLayerStack,\n getPcbRegionGeometry,\n parseAltiumMeasurementToMils,\n} from \"altiumts\"\nimport type {\n AnyCircuitElement,\n LayerRef,\n PcbBoard,\n PcbComponent,\n PcbCourtyardOutline,\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 includeCourtyards?: 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 if (\n options.includeCourtyards !== false &&\n options.includeComponents !== false\n ) {\n elements.push(...convertCourtyards(document))\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 (isCourtyardLayer(record.layer)) continue\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\ninterface CourtyardPath {\n componentId: string\n layer: \"top\" | \"bottom\"\n points: AltiumPoint[]\n strokeWidthMils: number\n}\n\nfunction convertCourtyards(document: AltiumPcbDocument): PcbCourtyardOutline[] {\n const componentIds = new Map(\n document.components.flatMap((component, index) =>\n component.position ? [[component, componentId(index)] as const] : [],\n ),\n )\n const paths: CourtyardPath[] = []\n\n for (const record of document.records) {\n const layer = getLayer(record)\n if (!isCourtyardLayer(layer)) continue\n const component = document.getComponentForRecord(record)\n const ownedComponentId = component ? componentIds.get(component) : undefined\n if (!ownedComponentId) continue\n const points = getCourtyardRecordPoints(record)\n if (points.length < 2) continue\n paths.push({\n componentId: ownedComponentId,\n layer: mapCourtyardLayer(layer),\n points,\n strokeWidthMils:\n record instanceof AltiumTrackRecord || record instanceof AltiumArcRecord\n ? (record.widthMils ?? 4)\n : 0,\n })\n }\n\n const courtyards: PcbCourtyardOutline[] = []\n for (const path of stitchCourtyardPaths(paths)) {\n if (!isClosedAltiumPath(path.points)) continue\n const outline = removeClosingPoint(path.points).map(toMillimeterPoint)\n if (outline.length < 3) continue\n courtyards.push({\n type: \"pcb_courtyard_outline\",\n pcb_courtyard_outline_id: `pcb_courtyard_outline_altium_${courtyards.length}`,\n pcb_component_id: path.componentId,\n layer: path.layer,\n outline,\n })\n }\n return courtyards\n}\n\nfunction getCourtyardRecordPoints(record: AltiumRecord): AltiumPoint[] {\n if (record instanceof AltiumTrackRecord) {\n return record.start && record.end ? [record.start, record.end] : []\n }\n if (record instanceof AltiumArcRecord) {\n return record.center && record.radiusMils\n ? approximateArc(\n record.center,\n record.radiusMils,\n record.startAngle,\n record.endAngle,\n )\n : []\n }\n if (record instanceof AltiumRegionRecord) {\n return getPcbRegionGeometry(record).outline.points\n }\n return []\n}\n\nfunction stitchCourtyardPaths(paths: CourtyardPath[]): CourtyardPath[] {\n const groups = new Map<string, CourtyardPath[]>()\n for (const path of deduplicateCourtyardPaths(paths)) {\n const key = [\n path.componentId,\n path.layer,\n path.strokeWidthMils.toFixed(4),\n ].join(\"|\")\n const group = groups.get(key) ?? []\n group.push(path)\n groups.set(key, group)\n }\n return [...groups.values()].flatMap(stitchCourtyardPathGroup)\n}\n\nfunction stitchCourtyardPathGroup(group: CourtyardPath[]): CourtyardPath[] {\n const remaining = [...group]\n const stitched: CourtyardPath[] = []\n while (remaining.length > 0) {\n const first = remaining.shift()\n if (!first) break\n const path = { ...first, points: [...first.points] }\n while (appendConnectedCourtyardPath(path, remaining)) {\n // Continue until no segment can extend either end of this path.\n }\n stitched.push(path)\n }\n return stitched\n}\n\nfunction appendConnectedCourtyardPath(\n stitched: CourtyardPath,\n remaining: CourtyardPath[],\n): boolean {\n const stitchedStart = stitched.points[0]\n const stitchedEnd = stitched.points.at(-1)\n if (!stitchedStart || !stitchedEnd) return false\n\n for (const [index, candidate] of remaining.entries()) {\n const candidateStart = candidate.points[0]\n const candidateEnd = candidate.points.at(-1)\n if (!candidateStart || !candidateEnd) continue\n if (altiumPointsApproximatelyEqual(stitchedEnd, candidateStart)) {\n stitched.points.push(...candidate.points.slice(1))\n } else if (altiumPointsApproximatelyEqual(stitchedEnd, candidateEnd)) {\n stitched.points.push(...candidate.points.toReversed().slice(1))\n } else if (altiumPointsApproximatelyEqual(stitchedStart, candidateEnd)) {\n stitched.points.unshift(...candidate.points.slice(0, -1))\n } else if (altiumPointsApproximatelyEqual(stitchedStart, candidateStart)) {\n stitched.points.unshift(...candidate.points.toReversed().slice(0, -1))\n } else {\n continue\n }\n remaining.splice(index, 1)\n return true\n }\n return false\n}\n\nfunction deduplicateCourtyardPaths(paths: CourtyardPath[]): CourtyardPath[] {\n const signatures = new Set<string>()\n return paths.filter((path) => {\n const forwardPoints = path.points.map(formatAltiumPoint).join(\"|\")\n const reversePoints = path.points\n .toReversed()\n .map(formatAltiumPoint)\n .join(\"|\")\n const pointsSignature =\n forwardPoints < reversePoints ? forwardPoints : reversePoints\n const signature = [\n path.componentId,\n path.layer,\n path.strokeWidthMils.toFixed(4),\n pointsSignature,\n ].join(\"|\")\n if (signatures.has(signature)) return false\n signatures.add(signature)\n return true\n })\n}\n\nfunction formatAltiumPoint(point: AltiumPoint): string {\n return `${point.x.toFixed(4)},${point.y.toFixed(4)}`\n}\n\nfunction isClosedAltiumPath(points: AltiumPoint[]): boolean {\n const first = points[0]\n const last = points.at(-1)\n return Boolean(first && last && altiumPointsApproximatelyEqual(first, last))\n}\n\nfunction removeClosingPoint(points: AltiumPoint[]): AltiumPoint[] {\n const first = points[0]\n const last = points.at(-1)\n return first && last && altiumPointsApproximatelyEqual(first, last)\n ? points.slice(0, -1)\n : points\n}\n\nfunction altiumPointsApproximatelyEqual(\n left: AltiumPoint,\n right: AltiumPoint,\n): boolean {\n return (\n Math.abs(left.x - right.x) <= 0.01 && Math.abs(left.y - right.y) <= 0.01\n )\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 isCourtyardLayer(layer: string | undefined): boolean {\n const normalized = normalizeLayer(layer)\n return normalized === \"MECHANICAL15\" || normalized === \"MECHANICAL16\"\n}\n\nfunction mapCourtyardLayer(layer: string | undefined): \"top\" | \"bottom\" {\n return normalizeLayer(layer) === \"MECHANICAL16\" ? \"bottom\" : \"top\"\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 SchematicGroup,\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 const schematicComponentIds = elements\n .filter(\n (\n element,\n ): element is Extract<\n AnyCircuitElement,\n { type: \"schematic_component\" }\n > => element.type === \"schematic_component\",\n )\n .map((element) => element.schematic_component_id)\n if (schematicComponentIds.length > 0) {\n elements.push({\n type: \"schematic_group\",\n schematic_group_id: \"schematic_group_altium\",\n source_group_id: \"source_group_altium\",\n schematic_sheet_id: SCHEMATIC_SHEET_ID,\n center: {\n x: (sheetDimensions.width * scale) / 2,\n y: (sheetDimensions.height * scale) / 2,\n },\n width: sheetDimensions.width * scale,\n height: sheetDimensions.height * scale,\n schematic_component_ids: schematicComponentIds,\n name: options.sheetName ?? \"Altium schematic\",\n } satisfies SchematicGroup)\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)\nconst INLINE_NET_LABEL_COLOR = \"rgb(132, 0, 0)\"\nconst DEFAULT_INLINE_NET_LABEL_FONT_SIZE = 0.18\nconst MIN_INLINE_NET_LABEL_FONT_SIZE = 0.1\nconst INLINE_NET_LABEL_CHARACTER_WIDTH = 0.12\nconst INLINE_NET_LABEL_HORIZONTAL_PADDING = 0.12\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 const visibleSymbolLabels = new Set(\n visibleOwnedRecords\n .filter((record) => record.recordKind === \"4\")\n .flatMap((record) => {\n const text = record.getDecoded(\"TEXT\")?.trim().toUpperCase()\n return text ? [text] : []\n }),\n )\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 visibleSymbolLabels,\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 visibleSymbolLabels: Set<string>\n}): ConvertedPort {\n const {\n document,\n options,\n pin,\n pinIndex,\n schematicComponentId,\n sourceComponentId,\n visibleSymbolLabels,\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 normalizedName = name.trim().toUpperCase()\n const functionalName = normalizedName.replace(/\\d+$/u, \"\")\n const showName =\n pinConglomerate === undefined ||\n (pinConglomerate & 0x08) !== 0 ||\n visibleSymbolLabels.has(normalizedName) ||\n visibleSymbolLabels.has(functionalName)\n const schematicPort: SchematicPort = {\n type: \"schematic_port\",\n center: scalePoint(terminalPoint, options.scale),\n ...(showName && name ? { 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 sourcePortCountByRecord: Map<AltiumRecord, number>\n sourceTraceIdByRecord: Map<AltiumRecord, 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 sourcePortCountByRecord = new Map<AltiumRecord, number>()\n const sourceTraceIdByRecord = 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 for (const record of net.records) {\n sourcePortCountByRecord.set(record, connectedPorts.length)\n sourceTraceIdByRecord.set(record, sourceTraceId)\n }\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 sourcePortCountByRecord,\n sourceTraceIdByRecord,\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 connectedWires = graph.getConnectedWiresForRecord(record)\n const wire = connectedWires[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 const sourceTraceId = connectivity.sourceTraceIdByRecord.get(record)\n const shouldRenderInline =\n Boolean(sourceTraceId) &&\n (recordKind === \"25\" ||\n (recordKind === \"18\" &&\n (record.getNumber(\"IOTYPE\") ?? 0) === 0 &&\n connectivity.sourcePortCountByRecord.get(record) === 2 &&\n !isPowerNet(name)))\n if (shouldRenderInline && sourceTraceId) {\n handledRecords.add(record)\n elements.push(\n createInlineNetLabelText({\n connectedWires,\n document,\n location,\n name,\n options,\n record,\n recordIndex,\n sourceTraceId,\n }),\n )\n continue\n }\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 createInlineNetLabelText(params: {\n connectedWires: AltiumRecord[]\n document: AltiumSchDoc\n location: AltiumPoint\n name: string\n options: SemanticSchematicOptions\n record: AltiumRecord\n recordIndex: number\n sourceTraceId: string\n}): SchematicText {\n const {\n connectedWires,\n document,\n location,\n name,\n options,\n record,\n recordIndex,\n sourceTraceId,\n } = params\n const direction = getInlineNetLabelDirection(record, location, connectedWires)\n const scaledLocation = scalePoint(location, options.scale)\n const fontSize = getInlineNetLabelFontSize(record, document, options.scale)\n const fontScale = fontSize / DEFAULT_INLINE_NET_LABEL_FONT_SIZE\n const textWidth =\n (name.length * INLINE_NET_LABEL_CHARACTER_WIDTH +\n INLINE_NET_LABEL_HORIZONTAL_PADDING) *\n fontScale\n const isVertical = direction === \"up\" || direction === \"down\"\n const directionSign = direction === \"left\" || direction === \"down\" ? -1 : 1\n const isTerminalPort = record.recordKind === \"18\"\n const anchor: SchematicText[\"anchor\"] = isTerminalPort\n ? directionSign > 0\n ? \"left\"\n : \"right\"\n : \"center\"\n const position = isTerminalPort\n ? isVertical\n ? {\n x: scaledLocation.x - fontSize / 2,\n y: scaledLocation.y,\n }\n : {\n x: scaledLocation.x,\n y: scaledLocation.y + fontSize / 2,\n }\n : isVertical\n ? {\n x: scaledLocation.x - fontSize / 2,\n y: scaledLocation.y + (directionSign * textWidth) / 2,\n }\n : {\n x: scaledLocation.x + (directionSign * textWidth) / 2,\n y: scaledLocation.y + fontSize / 2,\n }\n\n return {\n type: \"schematic_text\",\n anchor,\n color: INLINE_NET_LABEL_COLOR,\n font_size: fontSize,\n position,\n rotation: isVertical ? -90 : 0,\n schematic_sheet_id: options.schematicSheetId,\n schematic_text_id: `schematic_inline_net_label_altium_${recordIndex}`,\n source_trace_id: sourceTraceId,\n text: name,\n }\n}\n\nfunction getInlineNetLabelFontSize(\n record: AltiumRecord,\n document: AltiumSchDoc,\n scale: number,\n): number {\n const fontId = Math.max(\n Math.round(Number(record.getCaseInsensitive(\"FONTID\") ?? 1)),\n 1,\n )\n const sheetRecord = document.records.find(\n (candidate) => candidate.recordKind === \"31\",\n )\n const sourceFontSize = Number(\n sheetRecord?.getCaseInsensitive(`SIZE${fontId}`) ??\n DEFAULT_INLINE_NET_LABEL_FONT_SIZE / scale,\n )\n return Math.min(\n DEFAULT_INLINE_NET_LABEL_FONT_SIZE,\n Math.max(MIN_INLINE_NET_LABEL_FONT_SIZE, sourceFontSize * scale),\n )\n}\n\nfunction getInlineNetLabelDirection(\n record: AltiumRecord,\n location: AltiumPoint,\n connectedWires: AltiumRecord[],\n): CardinalDirection {\n if (record.recordKind !== \"18\") return getRecordDirection(record)\n\n for (const wire of connectedWires) {\n const points = getSchematicRecordPoints(wire)\n for (let pointIndex = 1; pointIndex < points.length; pointIndex++) {\n const start = points[pointIndex - 1]\n const end = points[pointIndex]\n if (!start || !end || !isPointOnSegment(location, start, end)) continue\n const other = pointsEqual(location, start)\n ? end\n : pointsEqual(location, end)\n ? start\n : undefined\n if (!other) continue\n // A port's location is at the outer end of its short wire stub. Place\n // its inline text away from the component, matching the side on which\n // Altium drew the port name instead of covering the component body.\n const dx = location.x - other.x\n const dy = location.y - other.y\n if (Math.abs(dx) >= Math.abs(dy)) return dx < 0 ? \"left\" : \"right\"\n return dy < 0 ? \"down\" : \"up\"\n }\n }\n\n return getRecordDirection(record)\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.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"description": "Convert Altium schematic and PCB documents into Circuit JSON",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"altiumts": "^0.0.26",
|
|
47
|
-
"circuit-json": "^0.0.
|
|
47
|
+
"circuit-json": "^0.0.475",
|
|
48
48
|
"format-si-unit": "^0.0.11",
|
|
49
49
|
"schematic-symbols": "^0.0.238"
|
|
50
50
|
},
|