circuit-json-to-gerber 0.0.59 → 0.0.61
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.
|
@@ -395,6 +395,35 @@ var getFileFunctionLayerSpan = ({
|
|
|
395
395
|
const span = normalizeLayerSpan(requestedLayerSpan, layerCount);
|
|
396
396
|
return `Plated,${getLayerNumber(span.from_layer, layerCount)},${getLayerNumber(span.to_layer, layerCount)},PTH`;
|
|
397
397
|
};
|
|
398
|
+
var getTraceRouteViaElements = (circuitJson) => {
|
|
399
|
+
const routeVias = [];
|
|
400
|
+
for (const element of circuitJson) {
|
|
401
|
+
if (element.type !== "pcb_trace") {
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
for (const [index, point] of element.route.entries()) {
|
|
405
|
+
if (point.route_type !== "via" || typeof point.hole_diameter !== "number" || typeof point.outer_diameter !== "number") {
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
routeVias.push({
|
|
409
|
+
type: "pcb_via",
|
|
410
|
+
pcb_via_id: `${element.pcb_trace_id}_route_via_${index}`,
|
|
411
|
+
x: point.x,
|
|
412
|
+
y: point.y,
|
|
413
|
+
hole_diameter: point.hole_diameter,
|
|
414
|
+
outer_diameter: point.outer_diameter,
|
|
415
|
+
from_layer: point.from_layer,
|
|
416
|
+
to_layer: point.to_layer,
|
|
417
|
+
layers: [point.from_layer, point.to_layer]
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return routeVias;
|
|
422
|
+
};
|
|
423
|
+
var getDrillableElements = (circuitJson) => [
|
|
424
|
+
...circuitJson,
|
|
425
|
+
...getTraceRouteViaElements(circuitJson)
|
|
426
|
+
];
|
|
398
427
|
var convertSoupToExcellonDrillCommands = ({
|
|
399
428
|
circuitJson,
|
|
400
429
|
is_plated,
|
|
@@ -403,6 +432,7 @@ var convertSoupToExcellonDrillCommands = ({
|
|
|
403
432
|
}) => {
|
|
404
433
|
const builder = excellonDrill();
|
|
405
434
|
const layerCount = getLayerCount(circuitJson);
|
|
435
|
+
const drillableElements = getDrillableElements(circuitJson);
|
|
406
436
|
builder.add("M48", {});
|
|
407
437
|
const date_str = (/* @__PURE__ */ new Date()).toISOString();
|
|
408
438
|
builder.add("header_comment", {
|
|
@@ -425,7 +455,7 @@ var convertSoupToExcellonDrillCommands = ({
|
|
|
425
455
|
}).add("FMAT", { format: 2 }).add("unit_format", { unit: "METRIC", lz: null });
|
|
426
456
|
let tool_counter = 10;
|
|
427
457
|
const diameterToToolNumber = {};
|
|
428
|
-
for (const element of
|
|
458
|
+
for (const element of drillableElements) {
|
|
429
459
|
if (!shouldIncludeElement({
|
|
430
460
|
element,
|
|
431
461
|
is_plated,
|
|
@@ -453,7 +483,7 @@ var convertSoupToExcellonDrillCommands = ({
|
|
|
453
483
|
builder.add("G05", {});
|
|
454
484
|
for (let i = 10; i < tool_counter; i++) {
|
|
455
485
|
builder.add("use_tool", { tool_number: i });
|
|
456
|
-
for (const element of
|
|
486
|
+
for (const element of drillableElements) {
|
|
457
487
|
if (element.type === "pcb_plated_hole" || element.type === "pcb_hole" || element.type === "pcb_via") {
|
|
458
488
|
if (!shouldIncludeElement({
|
|
459
489
|
element,
|
|
@@ -540,13 +570,15 @@ var convertSoupToExcellonDrillCommandLayers = ({
|
|
|
540
570
|
}) => {
|
|
541
571
|
const layerCount = getLayerCount(circuitJson);
|
|
542
572
|
const platedSpans = new Map(
|
|
543
|
-
circuitJson.flatMap(
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
573
|
+
getDrillableElements(circuitJson).flatMap(
|
|
574
|
+
(element) => {
|
|
575
|
+
const span = getPlatedElementLayerSpan(element, layerCount);
|
|
576
|
+
if (!span) {
|
|
577
|
+
return [];
|
|
578
|
+
}
|
|
579
|
+
return [[getDrillLayerSpanKey(span, layerCount), span]];
|
|
547
580
|
}
|
|
548
|
-
|
|
549
|
-
})
|
|
581
|
+
)
|
|
550
582
|
);
|
|
551
583
|
const platedDrillLayers = Object.fromEntries(
|
|
552
584
|
[...platedSpans.entries()].sort().map(([spanKey, span]) => [
|
|
@@ -1347,10 +1379,11 @@ function defineAperturesForLayer({
|
|
|
1347
1379
|
}).build()
|
|
1348
1380
|
);
|
|
1349
1381
|
}
|
|
1350
|
-
const apertureConfigs = getAllApertureTemplateConfigsForLayer(
|
|
1382
|
+
const apertureConfigs = getAllApertureTemplateConfigsForLayer({
|
|
1351
1383
|
circuitJson,
|
|
1352
|
-
layerRef
|
|
1353
|
-
|
|
1384
|
+
layer: layerRef,
|
|
1385
|
+
glayer_name
|
|
1386
|
+
});
|
|
1354
1387
|
for (const apertureConfig of apertureConfigs) {
|
|
1355
1388
|
glayer.push(
|
|
1356
1389
|
...gerberBuilder().add("define_aperture_template", {
|
|
@@ -1389,6 +1422,36 @@ var getApertureConfigFromPcbSmtpad = (elm) => {
|
|
|
1389
1422
|
}
|
|
1390
1423
|
throw new Error(`Unsupported shape ${elm.shape}`);
|
|
1391
1424
|
};
|
|
1425
|
+
var getApertureConfigFromPcbSmtpadSoldermask = (elm) => {
|
|
1426
|
+
let soldermaskMargin = 0;
|
|
1427
|
+
if ("soldermask_margin" in elm && typeof elm.soldermask_margin === "number") {
|
|
1428
|
+
soldermaskMargin = elm.soldermask_margin;
|
|
1429
|
+
}
|
|
1430
|
+
if (elm.shape === "rect") {
|
|
1431
|
+
return {
|
|
1432
|
+
standard_template_code: "R",
|
|
1433
|
+
x_size: elm.width + soldermaskMargin * 2,
|
|
1434
|
+
y_size: elm.height + soldermaskMargin * 2
|
|
1435
|
+
};
|
|
1436
|
+
}
|
|
1437
|
+
if (elm.shape === "circle") {
|
|
1438
|
+
return {
|
|
1439
|
+
standard_template_code: "C",
|
|
1440
|
+
diameter: elm.radius * 2 + soldermaskMargin * 2
|
|
1441
|
+
};
|
|
1442
|
+
}
|
|
1443
|
+
if (elm.shape === "rotated_rect") {
|
|
1444
|
+
return {
|
|
1445
|
+
standard_template_code: "R",
|
|
1446
|
+
x_size: elm.width + soldermaskMargin * 2,
|
|
1447
|
+
y_size: elm.height + soldermaskMargin * 2
|
|
1448
|
+
};
|
|
1449
|
+
}
|
|
1450
|
+
if (elm.shape === "polygon") {
|
|
1451
|
+
throw new Error("Polygon SMT pads are drawn as regions, not apertures");
|
|
1452
|
+
}
|
|
1453
|
+
throw new Error(`Unsupported shape ${elm.shape}`);
|
|
1454
|
+
};
|
|
1392
1455
|
var getApertureConfigFromPcbSilkscreenPath = (elm) => {
|
|
1393
1456
|
if ("stroke_width" in elm) {
|
|
1394
1457
|
return {
|
|
@@ -1527,10 +1590,10 @@ var getApertureConfigFromCirclePcbHole = (elm) => {
|
|
|
1527
1590
|
diameter: elm.hole_diameter
|
|
1528
1591
|
};
|
|
1529
1592
|
};
|
|
1530
|
-
var
|
|
1531
|
-
if (
|
|
1593
|
+
var getApertureConfigFromOuterDiameter = (elm) => {
|
|
1594
|
+
if (typeof elm.outer_diameter !== "number") {
|
|
1532
1595
|
throw new Error(
|
|
1533
|
-
"outer_diameter not specified in
|
|
1596
|
+
"outer_diameter not specified in getApertureConfigFromOuterDiameter"
|
|
1534
1597
|
);
|
|
1535
1598
|
}
|
|
1536
1599
|
return {
|
|
@@ -1538,9 +1601,14 @@ var getApertureConfigFromPcbVia = (elm) => {
|
|
|
1538
1601
|
diameter: elm.outer_diameter
|
|
1539
1602
|
};
|
|
1540
1603
|
};
|
|
1541
|
-
function getAllApertureTemplateConfigsForLayer(
|
|
1604
|
+
function getAllApertureTemplateConfigsForLayer({
|
|
1605
|
+
circuitJson,
|
|
1606
|
+
layer,
|
|
1607
|
+
glayer_name
|
|
1608
|
+
}) {
|
|
1542
1609
|
const configs = [];
|
|
1543
1610
|
const configHashMap = /* @__PURE__ */ new Set();
|
|
1611
|
+
const isSoldermaskLayer = glayer_name.endsWith("_Mask");
|
|
1544
1612
|
const addConfigIfNew = (config) => {
|
|
1545
1613
|
const hash = stableStringify(config);
|
|
1546
1614
|
if (!configHashMap.has(hash)) {
|
|
@@ -1551,7 +1619,11 @@ function getAllApertureTemplateConfigsForLayer(circuitJson, layer) {
|
|
|
1551
1619
|
for (const elm of circuitJson) {
|
|
1552
1620
|
if (elm.type === "pcb_smtpad") {
|
|
1553
1621
|
if (elm.layer === layer && elm.shape !== "polygon") {
|
|
1554
|
-
|
|
1622
|
+
if (isSoldermaskLayer) {
|
|
1623
|
+
addConfigIfNew(getApertureConfigFromPcbSmtpadSoldermask(elm));
|
|
1624
|
+
} else {
|
|
1625
|
+
addConfigIfNew(getApertureConfigFromPcbSmtpad(elm));
|
|
1626
|
+
}
|
|
1555
1627
|
}
|
|
1556
1628
|
} else if (elm.type === "pcb_solder_paste") {
|
|
1557
1629
|
if (elm.layer === layer) {
|
|
@@ -1568,14 +1640,26 @@ function getAllApertureTemplateConfigsForLayer(circuitJson, layer) {
|
|
|
1568
1640
|
}
|
|
1569
1641
|
} else if (elm.type === "pcb_plated_hole") {
|
|
1570
1642
|
if (elm.layers.includes(layer)) {
|
|
1643
|
+
if (glayer_name.endsWith("_Mask") && elm.is_covered_with_solder_mask === true) {
|
|
1644
|
+
continue;
|
|
1645
|
+
}
|
|
1571
1646
|
addConfigIfNew(getApertureConfigFromPcbPlatedHole(elm));
|
|
1572
1647
|
}
|
|
1573
1648
|
} else if (elm.type === "pcb_hole") {
|
|
1649
|
+
if (glayer_name.endsWith("_Mask") && elm.is_covered_with_solder_mask === true) {
|
|
1650
|
+
continue;
|
|
1651
|
+
}
|
|
1574
1652
|
if (elm.hole_shape === "circle")
|
|
1575
1653
|
addConfigIfNew(getApertureConfigFromCirclePcbHole(elm));
|
|
1576
1654
|
else console.warn("NOT IMPLEMENTED: drawing gerber for non circle holes");
|
|
1577
1655
|
} else if (elm.type === "pcb_via") {
|
|
1578
|
-
addConfigIfNew(
|
|
1656
|
+
addConfigIfNew(getApertureConfigFromOuterDiameter(elm));
|
|
1657
|
+
} else if (elm.type === "pcb_trace") {
|
|
1658
|
+
for (const point of elm.route) {
|
|
1659
|
+
if (point.route_type === "via" && typeof point.outer_diameter === "number" && (point.from_layer === layer || point.to_layer === layer)) {
|
|
1660
|
+
addConfigIfNew(getApertureConfigFromOuterDiameter(point));
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1579
1663
|
} else if (elm.type === "pcb_silkscreen_path")
|
|
1580
1664
|
addConfigIfNew(getApertureConfigFromPcbSilkscreenPath(elm));
|
|
1581
1665
|
else if (elm.type === "pcb_silkscreen_text")
|
|
@@ -1614,7 +1698,7 @@ var findApertureNumber = (glayer, search_params) => {
|
|
|
1614
1698
|
// package.json
|
|
1615
1699
|
var package_default = {
|
|
1616
1700
|
name: "circuit-json-to-gerber",
|
|
1617
|
-
version: "0.0.
|
|
1701
|
+
version: "0.0.60",
|
|
1618
1702
|
main: "dist/index.js",
|
|
1619
1703
|
type: "module",
|
|
1620
1704
|
scripts: {
|
|
@@ -2194,6 +2278,30 @@ var convertSoupToGerberCommands = (circuitJson, opts = {}) => {
|
|
|
2194
2278
|
}).add("move_operation", { x: a.x, y: mfy(a.y) }).add("plot_operation", { x: b.x, y: mfy(b.y) }).build()
|
|
2195
2279
|
);
|
|
2196
2280
|
}
|
|
2281
|
+
} else if (a.route_type === "via" && b.route_type === "wire") {
|
|
2282
|
+
if (b.layer === layer) {
|
|
2283
|
+
const glayer = glayers[getGerberLayerName(layer, "copper")];
|
|
2284
|
+
glayer.push(
|
|
2285
|
+
...gerberBuilder().add("select_aperture", {
|
|
2286
|
+
aperture_number: findApertureNumber(glayer, {
|
|
2287
|
+
trace_width: b.width
|
|
2288
|
+
})
|
|
2289
|
+
}).add("move_operation", { x: a.x, y: mfy(a.y) }).add("plot_operation", { x: b.x, y: mfy(b.y) }).build()
|
|
2290
|
+
);
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2294
|
+
for (const point of route) {
|
|
2295
|
+
if (point.route_type === "via" && typeof point.outer_diameter === "number" && (point.from_layer === layer || point.to_layer === layer)) {
|
|
2296
|
+
const glayer = glayers[getGerberLayerName(layer, "copper")];
|
|
2297
|
+
glayer.push(
|
|
2298
|
+
...gerberBuilder().add("select_aperture", {
|
|
2299
|
+
aperture_number: findApertureNumber(
|
|
2300
|
+
glayer,
|
|
2301
|
+
getApertureConfigFromOuterDiameter(point)
|
|
2302
|
+
)
|
|
2303
|
+
}).add("flash_operation", { x: point.x, y: mfy(point.y) }).build()
|
|
2304
|
+
);
|
|
2197
2305
|
}
|
|
2198
2306
|
}
|
|
2199
2307
|
} else if (element.type === "pcb_silkscreen_path" && outerLayerRefs.includes(layer)) {
|
|
@@ -2233,11 +2341,16 @@ var convertSoupToGerberCommands = (circuitJson, opts = {}) => {
|
|
|
2233
2341
|
);
|
|
2234
2342
|
} else if (element.type === "pcb_smtpad" && element.shape !== "polygon") {
|
|
2235
2343
|
if (element.layer === layer && outerLayerRefs.includes(layer)) {
|
|
2236
|
-
for (const glayer of [
|
|
2237
|
-
|
|
2238
|
-
|
|
2344
|
+
for (const { glayer, apertureConfig } of [
|
|
2345
|
+
{
|
|
2346
|
+
glayer: glayers[getGerberLayerName(layer, "copper")],
|
|
2347
|
+
apertureConfig: getApertureConfigFromPcbSmtpad(element)
|
|
2348
|
+
},
|
|
2349
|
+
{
|
|
2350
|
+
glayer: glayers[getGerberLayerName(layer, "soldermask")],
|
|
2351
|
+
apertureConfig: getApertureConfigFromPcbSmtpadSoldermask(element)
|
|
2352
|
+
}
|
|
2239
2353
|
]) {
|
|
2240
|
-
const apertureConfig = getApertureConfigFromPcbSmtpad(element);
|
|
2241
2354
|
const apertureNumber = findApertureNumber(glayer, apertureConfig);
|
|
2242
2355
|
const gb = gerberBuilder().add("select_aperture", {
|
|
2243
2356
|
aperture_number: apertureNumber
|
|
@@ -2330,7 +2443,7 @@ var convertSoupToGerberCommands = (circuitJson, opts = {}) => {
|
|
|
2330
2443
|
const layersToAddTo = [
|
|
2331
2444
|
glayers[getGerberLayerName(layer, "copper")]
|
|
2332
2445
|
];
|
|
2333
|
-
if (outerLayerRefs.includes(layer)) {
|
|
2446
|
+
if (outerLayerRefs.includes(layer) && element.is_covered_with_solder_mask !== true) {
|
|
2334
2447
|
layersToAddTo.push(glayers[getGerberLayerName(layer, "soldermask")]);
|
|
2335
2448
|
}
|
|
2336
2449
|
for (const glayer of layersToAddTo) {
|
|
@@ -2438,7 +2551,7 @@ var convertSoupToGerberCommands = (circuitJson, opts = {}) => {
|
|
|
2438
2551
|
}
|
|
2439
2552
|
}
|
|
2440
2553
|
} else if (element.type === "pcb_hole") {
|
|
2441
|
-
if (outerLayerRefs.includes(layer)) {
|
|
2554
|
+
if (outerLayerRefs.includes(layer) && element.is_covered_with_solder_mask !== true) {
|
|
2442
2555
|
for (const glayer of [
|
|
2443
2556
|
glayers[getGerberLayerName(layer, "soldermask")]
|
|
2444
2557
|
]) {
|
|
@@ -2471,7 +2584,7 @@ var convertSoupToGerberCommands = (circuitJson, opts = {}) => {
|
|
|
2471
2584
|
...gerberBuilder().add("select_aperture", {
|
|
2472
2585
|
aperture_number: findApertureNumber(
|
|
2473
2586
|
glayer,
|
|
2474
|
-
|
|
2587
|
+
getApertureConfigFromOuterDiameter(element)
|
|
2475
2588
|
)
|
|
2476
2589
|
}).add("flash_operation", { x: element.x, y: mfy(element.y) }).build()
|
|
2477
2590
|
);
|
|
@@ -2706,4 +2819,4 @@ export {
|
|
|
2706
2819
|
stringifyGerberCommands,
|
|
2707
2820
|
convertSoupToGerberCommands
|
|
2708
2821
|
};
|
|
2709
|
-
//# sourceMappingURL=chunk-
|
|
2822
|
+
//# sourceMappingURL=chunk-KJYUL256.js.map
|