altium-to-circuit-json 0.0.82 → 0.0.84
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 +192 -36
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -465,15 +465,6 @@ function createPcbConversionContext({
|
|
|
465
465
|
};
|
|
466
466
|
}
|
|
467
467
|
|
|
468
|
-
// lib/schematic/document/constants.ts
|
|
469
|
-
var SCHEMATIC_SHEET_ID = "schematic_sheet_altium";
|
|
470
|
-
var SCHEMATIC_UNIT_TO_MILLIMETERS = 10.16 / 1.1;
|
|
471
|
-
var SCHEMATIC_SHEET_INSET = 5 / SCHEMATIC_UNIT_TO_MILLIMETERS;
|
|
472
|
-
var SCHEMATIC_SHEET_WIDTH = 297 / SCHEMATIC_UNIT_TO_MILLIMETERS;
|
|
473
|
-
var SCHEMATIC_SHEET_HEIGHT = 210 / SCHEMATIC_UNIT_TO_MILLIMETERS;
|
|
474
|
-
var SCHEMATIC_SHEET_INNER_WIDTH = SCHEMATIC_SHEET_WIDTH - SCHEMATIC_SHEET_INSET * 2;
|
|
475
|
-
var SCHEMATIC_SHEET_INNER_HEIGHT = SCHEMATIC_SHEET_HEIGHT - SCHEMATIC_SHEET_INSET * 2;
|
|
476
|
-
|
|
477
468
|
// lib/schematic/geometry/getAveragePoint.ts
|
|
478
469
|
function getAveragePoint(points) {
|
|
479
470
|
if (points.length === 0) return { x: 0, y: 0 };
|
|
@@ -616,6 +607,15 @@ function unscaleLength(lengthMillimeters, altiumUnitsToMillimetersScale) {
|
|
|
616
607
|
}).x;
|
|
617
608
|
}
|
|
618
609
|
|
|
610
|
+
// lib/schematic/document/constants.ts
|
|
611
|
+
var SCHEMATIC_SHEET_ID = "schematic_sheet_altium";
|
|
612
|
+
var SCHEMATIC_UNIT_TO_MILLIMETERS = 10.16 / 1.1;
|
|
613
|
+
var SCHEMATIC_SHEET_INSET = 5 / SCHEMATIC_UNIT_TO_MILLIMETERS;
|
|
614
|
+
var SCHEMATIC_SHEET_WIDTH = 297 / SCHEMATIC_UNIT_TO_MILLIMETERS;
|
|
615
|
+
var SCHEMATIC_SHEET_HEIGHT = 210 / SCHEMATIC_UNIT_TO_MILLIMETERS;
|
|
616
|
+
var SCHEMATIC_SHEET_INNER_WIDTH = SCHEMATIC_SHEET_WIDTH - SCHEMATIC_SHEET_INSET * 2;
|
|
617
|
+
var SCHEMATIC_SHEET_INNER_HEIGHT = SCHEMATIC_SHEET_HEIGHT - SCHEMATIC_SHEET_INSET * 2;
|
|
618
|
+
|
|
619
619
|
// lib/schematic/document/getPositiveNumber.ts
|
|
620
620
|
function getPositiveNumber(candidate, fallback) {
|
|
621
621
|
const parsed = Number(candidate);
|
|
@@ -623,11 +623,43 @@ function getPositiveNumber(candidate, fallback) {
|
|
|
623
623
|
}
|
|
624
624
|
|
|
625
625
|
// lib/schematic/document/getAltiumSheetDimensions.ts
|
|
626
|
+
var STANDARD_SHEET_SIZES = [
|
|
627
|
+
{ width: 1150, height: 760 },
|
|
628
|
+
{ width: 1550, height: 1110 },
|
|
629
|
+
{ width: 2230, height: 1570 },
|
|
630
|
+
{ width: 3150, height: 2230 },
|
|
631
|
+
{ width: 4460, height: 3150 },
|
|
632
|
+
{ width: 950, height: 750 },
|
|
633
|
+
{ width: 1500, height: 950 },
|
|
634
|
+
{ width: 2e3, height: 1500 },
|
|
635
|
+
{ width: 3200, height: 2e3 },
|
|
636
|
+
{ width: 4200, height: 3200 },
|
|
637
|
+
{ width: 1100, height: 850 },
|
|
638
|
+
{ width: 1400, height: 850 },
|
|
639
|
+
{ width: 1700, height: 1100 },
|
|
640
|
+
{ width: 990, height: 790 },
|
|
641
|
+
{ width: 1540, height: 990 },
|
|
642
|
+
{ width: 2060, height: 1560 },
|
|
643
|
+
{ width: 3260, height: 2060 },
|
|
644
|
+
{ width: 4280, height: 3280 }
|
|
645
|
+
];
|
|
626
646
|
function getAltiumSheetDimensions(sheetRecord) {
|
|
627
|
-
|
|
647
|
+
const customDimensions = {
|
|
628
648
|
width: getPositiveNumber(sheetRecord?.getCaseInsensitive("CUSTOMX"), 1e3),
|
|
629
649
|
height: getPositiveNumber(sheetRecord?.getCaseInsensitive("CUSTOMY"), 800)
|
|
630
650
|
};
|
|
651
|
+
const sheetStyle = sheetRecord?.getCaseInsensitive("SHEETSTYLE");
|
|
652
|
+
if (sheetRecord?.getCaseInsensitive("USECUSTOMSHEET") === "T" || sheetStyle === void 0) {
|
|
653
|
+
return customDimensions;
|
|
654
|
+
}
|
|
655
|
+
const standardDimensions = STANDARD_SHEET_SIZES[Number(sheetStyle)];
|
|
656
|
+
if (!standardDimensions) {
|
|
657
|
+
throw new RangeError(
|
|
658
|
+
`Unsupported Altium schematic sheet style: ${sheetStyle}`
|
|
659
|
+
);
|
|
660
|
+
}
|
|
661
|
+
const isPortrait = Number(sheetRecord?.getCaseInsensitive("WORKSPACEORIENTATION") ?? 0) !== 0;
|
|
662
|
+
return isPortrait ? { width: standardDimensions.height, height: standardDimensions.width } : standardDimensions;
|
|
631
663
|
}
|
|
632
664
|
|
|
633
665
|
// lib/schematic/document/createSheetBorder.ts
|
|
@@ -650,12 +682,26 @@ function createSheetBorder(sheetRecord, scale5) {
|
|
|
650
682
|
|
|
651
683
|
// lib/schematic/document/addSchematicSheet.ts
|
|
652
684
|
function addSchematicSheet(context) {
|
|
685
|
+
const scaledSheetWidth = scaleLength(
|
|
686
|
+
context.sheetDimensions.width,
|
|
687
|
+
context.scale
|
|
688
|
+
);
|
|
689
|
+
const scaledSheetHeight = scaleLength(
|
|
690
|
+
context.sheetDimensions.height,
|
|
691
|
+
context.scale
|
|
692
|
+
);
|
|
693
|
+
const usesCustomSheet = context.sheetRecord?.getCaseInsensitive("USECUSTOMSHEET") === "T";
|
|
694
|
+
const sheetDimensions = usesCustomSheet ? {
|
|
695
|
+
sheet_width: scaledSheetWidth * SCHEMATIC_UNIT_TO_MILLIMETERS,
|
|
696
|
+
sheet_height: scaledSheetHeight * SCHEMATIC_UNIT_TO_MILLIMETERS
|
|
697
|
+
} : {};
|
|
653
698
|
context.elements.push({
|
|
654
699
|
type: "schematic_sheet",
|
|
655
700
|
schematic_sheet_id: SCHEMATIC_SHEET_ID,
|
|
656
701
|
name: context.options.sheetName ?? "Altium schematic",
|
|
657
702
|
outline_color: "#334155",
|
|
658
|
-
sheet_index: 0
|
|
703
|
+
sheet_index: 0,
|
|
704
|
+
...sheetDimensions
|
|
659
705
|
});
|
|
660
706
|
if (context.options.includeSheetBorder === true) {
|
|
661
707
|
context.elements.push(createSheetBorder(context.sheetRecord, context.scale));
|
|
@@ -5181,7 +5227,10 @@ function contourToPoints(contour) {
|
|
|
5181
5227
|
import {
|
|
5182
5228
|
AltiumFillRecord,
|
|
5183
5229
|
AltiumPolygonRecord,
|
|
5184
|
-
AltiumRegionRecord as AltiumRegionRecord3
|
|
5230
|
+
AltiumRegionRecord as AltiumRegionRecord3,
|
|
5231
|
+
getPcbContour as getPcbContour2,
|
|
5232
|
+
getPcbRecordPolygonIndex,
|
|
5233
|
+
getPcbRegionGeometry as getPcbRegionGeometry5
|
|
5185
5234
|
} from "altiumts";
|
|
5186
5235
|
|
|
5187
5236
|
// lib/pcb/copperAreas/convertCopperFill.ts
|
|
@@ -5216,8 +5265,13 @@ function convertCopperFill({
|
|
|
5216
5265
|
}
|
|
5217
5266
|
|
|
5218
5267
|
// lib/pcb/copperAreas/convertCopperPolygon.ts
|
|
5219
|
-
import {
|
|
5268
|
+
import {
|
|
5269
|
+
getPcbContour,
|
|
5270
|
+
getPcbRegionGeometry as getPcbRegionGeometry3
|
|
5271
|
+
} from "altiumts";
|
|
5272
|
+
import polygonClipping from "polygon-clipping";
|
|
5220
5273
|
function convertCopperPolygon({
|
|
5274
|
+
cutouts,
|
|
5221
5275
|
polygonIndex,
|
|
5222
5276
|
layerMap,
|
|
5223
5277
|
record,
|
|
@@ -5227,21 +5281,45 @@ function convertCopperPolygon({
|
|
|
5227
5281
|
if (!layer) return [];
|
|
5228
5282
|
const points = contourToPoints(getPcbContour(record));
|
|
5229
5283
|
if (points.length < 3) return [];
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5284
|
+
const cutoutPolygons = cutouts.map((cutout) => {
|
|
5285
|
+
const geometry = getPcbRegionGeometry3(cutout);
|
|
5286
|
+
return [geometry.outline, ...geometry.holes].map(
|
|
5287
|
+
(contour) => contourToPoints(contour).map((point) => [point.x, point.y])
|
|
5288
|
+
);
|
|
5289
|
+
});
|
|
5290
|
+
const copperPolygons = cutouts.length === 0 ? [[points]] : polygonClipping.difference(
|
|
5291
|
+
[points.map((point) => [point.x, point.y])],
|
|
5292
|
+
cutoutPolygons
|
|
5293
|
+
).map(
|
|
5294
|
+
(polygon) => polygon.map(
|
|
5295
|
+
(ring) => ring.slice(0, -1).map(([x, y]) => ({ x, y }))
|
|
5296
|
+
)
|
|
5297
|
+
);
|
|
5298
|
+
return copperPolygons.flatMap(
|
|
5299
|
+
([outerRing, ...holes], partIndex) => {
|
|
5300
|
+
if (!outerRing || outerRing.length < 3) return [];
|
|
5301
|
+
return [
|
|
5302
|
+
{
|
|
5303
|
+
type: "pcb_copper_pour",
|
|
5304
|
+
pcb_copper_pour_id: `pcb_copper_pour_altium_polygon_${polygonIndex}${partIndex === 0 ? "" : `_island_${partIndex}`}`,
|
|
5305
|
+
...sourceNetId ? { source_net_id: sourceNetId } : {},
|
|
5306
|
+
covered_with_solder_mask: true,
|
|
5307
|
+
layer,
|
|
5308
|
+
...holes.length === 0 ? { shape: "polygon", points: outerRing } : {
|
|
5309
|
+
shape: "brep",
|
|
5310
|
+
brep_shape: {
|
|
5311
|
+
outer_ring: { vertices: outerRing },
|
|
5312
|
+
inner_rings: holes.map((vertices) => ({ vertices }))
|
|
5313
|
+
}
|
|
5314
|
+
}
|
|
5315
|
+
}
|
|
5316
|
+
];
|
|
5239
5317
|
}
|
|
5240
|
-
|
|
5318
|
+
);
|
|
5241
5319
|
}
|
|
5242
5320
|
|
|
5243
5321
|
// lib/pcb/copperAreas/convertCopperRegion.ts
|
|
5244
|
-
import { getPcbRegionGeometry as
|
|
5322
|
+
import { getPcbRegionGeometry as getPcbRegionGeometry4 } from "altiumts";
|
|
5245
5323
|
function convertCopperRegion({
|
|
5246
5324
|
layerMap,
|
|
5247
5325
|
record,
|
|
@@ -5253,7 +5331,7 @@ function convertCopperRegion({
|
|
|
5253
5331
|
}
|
|
5254
5332
|
const layer = layerMap.getLayer(record.layer);
|
|
5255
5333
|
if (!layer) return [];
|
|
5256
|
-
const geometry =
|
|
5334
|
+
const geometry = getPcbRegionGeometry4(record);
|
|
5257
5335
|
const outerVertices = contourToPoints(geometry.outline);
|
|
5258
5336
|
if (outerVertices.length < 3) return [];
|
|
5259
5337
|
const innerRings = geometry.holes.map((hole) => ({ vertices: contourToPoints(hole) })).filter((ring) => ring.vertices.length >= 3);
|
|
@@ -5286,20 +5364,97 @@ function convertCopperRegion({
|
|
|
5286
5364
|
];
|
|
5287
5365
|
}
|
|
5288
5366
|
|
|
5367
|
+
// lib/pcb/copperAreas/isContourInsideContour.ts
|
|
5368
|
+
import { doesLineIntersectLine } from "@tscircuit/math-utils";
|
|
5369
|
+
function isContourInsideContour({
|
|
5370
|
+
innerContour,
|
|
5371
|
+
outerContour
|
|
5372
|
+
}) {
|
|
5373
|
+
const innerBounds = innerContour.bounds;
|
|
5374
|
+
const outerBounds = outerContour.bounds;
|
|
5375
|
+
if (!innerBounds || !outerBounds || innerBounds.minX <= outerBounds.minX || innerBounds.maxX >= outerBounds.maxX || innerBounds.minY <= outerBounds.minY || innerBounds.maxY >= outerBounds.maxY) {
|
|
5376
|
+
return false;
|
|
5377
|
+
}
|
|
5378
|
+
const innerPoints = innerContour.isExplicitlyClosed ? innerContour.points.slice(0, -1) : innerContour.points;
|
|
5379
|
+
const outerPoints = outerContour.isExplicitlyClosed ? outerContour.points.slice(0, -1) : outerContour.points;
|
|
5380
|
+
if (innerPoints.length < 3 || outerPoints.length < 3) return false;
|
|
5381
|
+
const toleranceMils = 8 * Number.EPSILON * Math.max(
|
|
5382
|
+
1,
|
|
5383
|
+
Math.abs(outerBounds.minX),
|
|
5384
|
+
Math.abs(outerBounds.maxX),
|
|
5385
|
+
Math.abs(outerBounds.minY),
|
|
5386
|
+
Math.abs(outerBounds.maxY)
|
|
5387
|
+
);
|
|
5388
|
+
for (const point of innerPoints) {
|
|
5389
|
+
let isInside = false;
|
|
5390
|
+
for (let index = 0; index < outerPoints.length; index++) {
|
|
5391
|
+
const start = outerPoints[index];
|
|
5392
|
+
const end = outerPoints[(index + 1) % outerPoints.length];
|
|
5393
|
+
if (!start || !end) continue;
|
|
5394
|
+
if (start.y > point.y !== end.y > point.y && point.x < start.x + (point.y - start.y) * (end.x - start.x) / (end.y - start.y)) {
|
|
5395
|
+
isInside = !isInside;
|
|
5396
|
+
}
|
|
5397
|
+
}
|
|
5398
|
+
if (!isInside) return false;
|
|
5399
|
+
}
|
|
5400
|
+
for (let innerIndex = 0; innerIndex < innerPoints.length; innerIndex++) {
|
|
5401
|
+
const innerStart = innerPoints[innerIndex];
|
|
5402
|
+
const innerEnd = innerPoints[(innerIndex + 1) % innerPoints.length];
|
|
5403
|
+
if (!innerStart || !innerEnd) continue;
|
|
5404
|
+
for (let outerIndex = 0; outerIndex < outerPoints.length; outerIndex++) {
|
|
5405
|
+
const outerStart = outerPoints[outerIndex];
|
|
5406
|
+
const outerEnd = outerPoints[(outerIndex + 1) % outerPoints.length];
|
|
5407
|
+
if (!outerStart || !outerEnd) continue;
|
|
5408
|
+
if (doesLineIntersectLine([innerStart, innerEnd], [outerStart, outerEnd], {
|
|
5409
|
+
lineThickness: toleranceMils
|
|
5410
|
+
})) {
|
|
5411
|
+
return false;
|
|
5412
|
+
}
|
|
5413
|
+
}
|
|
5414
|
+
}
|
|
5415
|
+
return true;
|
|
5416
|
+
}
|
|
5417
|
+
|
|
5289
5418
|
// lib/pcb/copperAreas/convertAltiumCopperAreas.ts
|
|
5290
5419
|
function convertAltiumCopperAreas(document, {
|
|
5291
5420
|
layerMap = new PcbCopperLayerMap(document),
|
|
5292
5421
|
getSourceNetId = () => void 0
|
|
5293
5422
|
} = {}) {
|
|
5294
|
-
const
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5423
|
+
const polygonsWithCopperRegions = /* @__PURE__ */ new Set();
|
|
5424
|
+
const cutoutsByPolygon = /* @__PURE__ */ new Map();
|
|
5425
|
+
const polygonContours = /* @__PURE__ */ new Map();
|
|
5426
|
+
for (const record of document.records) {
|
|
5427
|
+
if (!(record instanceof AltiumRegionRecord3) || record.recordKind !== "Region") {
|
|
5428
|
+
continue;
|
|
5429
|
+
}
|
|
5430
|
+
const polygonIndex = getPcbRecordPolygonIndex(document, record);
|
|
5431
|
+
const linkedPolygon = document.getPolygonForRecord(record);
|
|
5432
|
+
if (record.regionKind === "COPPER") {
|
|
5433
|
+
if (linkedPolygon) polygonsWithCopperRegions.add(linkedPolygon);
|
|
5434
|
+
} else if (record.regionKind === "POLYGON_CUTOUT") {
|
|
5435
|
+
const cutoutGeometry = getPcbRegionGeometry5(record);
|
|
5436
|
+
const candidatePolygons = polygonIndex === void 0 ? document.polygons : linkedPolygon ? [linkedPolygon] : [];
|
|
5437
|
+
const polygons = candidatePolygons.filter((polygon) => {
|
|
5438
|
+
if (record.layer !== polygon.layer && record.layer !== "MULTILAYER") {
|
|
5439
|
+
return false;
|
|
5440
|
+
}
|
|
5441
|
+
let polygonContour = polygonContours.get(polygon);
|
|
5442
|
+
if (!polygonContour) {
|
|
5443
|
+
polygonContour = getPcbContour2(polygon);
|
|
5444
|
+
polygonContours.set(polygon, polygonContour);
|
|
5445
|
+
}
|
|
5446
|
+
return isContourInsideContour({
|
|
5447
|
+
innerContour: cutoutGeometry.outline,
|
|
5448
|
+
outerContour: polygonContour
|
|
5449
|
+
});
|
|
5450
|
+
});
|
|
5451
|
+
for (const polygon of polygons) {
|
|
5452
|
+
const cutouts = cutoutsByPolygon.get(polygon) ?? [];
|
|
5453
|
+
cutouts.push(record);
|
|
5454
|
+
cutoutsByPolygon.set(polygon, cutouts);
|
|
5298
5455
|
}
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
})
|
|
5302
|
-
);
|
|
5456
|
+
}
|
|
5457
|
+
}
|
|
5303
5458
|
const polygonIndexes = new Map(
|
|
5304
5459
|
document.polygons.map((polygon, index) => [polygon, index])
|
|
5305
5460
|
);
|
|
@@ -5314,10 +5469,11 @@ function convertAltiumCopperAreas(document, {
|
|
|
5314
5469
|
}
|
|
5315
5470
|
if (record instanceof AltiumPolygonRecord) {
|
|
5316
5471
|
const polygonIndex = polygonIndexes.get(record);
|
|
5317
|
-
if (record.shelved === true || polygonIndex === void 0 ||
|
|
5472
|
+
if (record.shelved === true || polygonIndex === void 0 || polygonsWithCopperRegions.has(record)) {
|
|
5318
5473
|
return [];
|
|
5319
5474
|
}
|
|
5320
5475
|
return convertCopperPolygon({
|
|
5476
|
+
cutouts: cutoutsByPolygon.get(record) ?? [],
|
|
5321
5477
|
layerMap,
|
|
5322
5478
|
polygonIndex,
|
|
5323
5479
|
record,
|
|
@@ -5763,12 +5919,12 @@ function convertPcbSilkscreenLine({
|
|
|
5763
5919
|
}
|
|
5764
5920
|
|
|
5765
5921
|
// lib/pcb/silkscreen/convertPcbSilkscreenRegion.ts
|
|
5766
|
-
import { getPcbRegionGeometry as
|
|
5922
|
+
import { getPcbRegionGeometry as getPcbRegionGeometry6 } from "altiumts";
|
|
5767
5923
|
function convertPcbSilkscreenRegion({
|
|
5768
5924
|
record,
|
|
5769
5925
|
recordIndex
|
|
5770
5926
|
}) {
|
|
5771
|
-
const geometry =
|
|
5927
|
+
const geometry = getPcbRegionGeometry6(record);
|
|
5772
5928
|
const outerVertices = geometry.outline.points.map(toMillimeterPoint);
|
|
5773
5929
|
if (outerVertices.length < 3) return void 0;
|
|
5774
5930
|
const innerRings = geometry.holes.map((hole) => ({ vertices: hole.points.map(toMillimeterPoint) })).filter((ring) => ring.vertices.length >= 3);
|