circuit-json-to-lbrn 0.0.54 → 0.0.56
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.d.ts +1 -0
- package/dist/index.js +148 -1
- package/lib/ConvertContext.ts +2 -0
- package/lib/createSoldermaskCureLayer.ts +160 -0
- package/lib/index.ts +26 -0
- package/lib/layer-indexes.ts +1 -0
- package/package.json +1 -1
- package/site/index.html +0 -72
- package/site/main.tsx +6 -26
- package/tests/basics/soldermask-cure/__snapshots__/soldermask-cure-with-solderMaskMarginPercent.snap.svg +8 -0
- package/tests/basics/soldermask-cure/__snapshots__/soldermask-cure.snap.svg +8 -0
- package/tests/basics/soldermask-cure/soldermask-cure-with-solderMaskMarginPercent.test.ts +30 -0
- package/tests/basics/soldermask-cure/soldermask-cure.test.ts +30 -0
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ interface ConvertCircuitJsonToLbrnOptions {
|
|
|
10
10
|
margin?: number;
|
|
11
11
|
includeCopper?: boolean;
|
|
12
12
|
includeSoldermask?: boolean;
|
|
13
|
+
includeSoldermaskCure?: boolean;
|
|
13
14
|
globalCopperSoldermaskMarginAdjustment?: number;
|
|
14
15
|
solderMaskMarginPercent?: number;
|
|
15
16
|
includeLayers?: Array<"top" | "bottom">;
|
package/dist/index.js
CHANGED
|
@@ -2749,7 +2749,132 @@ var LAYER_INDEXES = {
|
|
|
2749
2749
|
topCopperCutFill: 6,
|
|
2750
2750
|
bottomCopperCutFill: 7,
|
|
2751
2751
|
topOxidationCleaning: 8,
|
|
2752
|
-
bottomOxidationCleaning: 9
|
|
2752
|
+
bottomOxidationCleaning: 9,
|
|
2753
|
+
soldermaskCure: 10
|
|
2754
|
+
};
|
|
2755
|
+
|
|
2756
|
+
// lib/createSoldermaskCureLayer.ts
|
|
2757
|
+
import { Point as Point4, Polygon as Polygon7 } from "@flatten-js/core";
|
|
2758
|
+
import { ShapeGroup as ShapeGroup3, ShapePath as ShapePath30 } from "lbrnts";
|
|
2759
|
+
var contourToPolygon3 = (contour) => {
|
|
2760
|
+
if (contour.length < 3) return null;
|
|
2761
|
+
const points = contour.map(([x, y]) => new Point4(x, y));
|
|
2762
|
+
try {
|
|
2763
|
+
const polygon = new Polygon7(points);
|
|
2764
|
+
if (polygon.faces.size > 0) {
|
|
2765
|
+
return polygon;
|
|
2766
|
+
}
|
|
2767
|
+
} catch {
|
|
2768
|
+
}
|
|
2769
|
+
return null;
|
|
2770
|
+
};
|
|
2771
|
+
var shapePathToContour = (shapePath) => {
|
|
2772
|
+
if (!shapePath.verts || shapePath.verts.length < 3) return null;
|
|
2773
|
+
const contour = shapePath.verts.map(
|
|
2774
|
+
(vert) => [vert.x, vert.y]
|
|
2775
|
+
);
|
|
2776
|
+
if (contour.length > 3) {
|
|
2777
|
+
const first = contour[0];
|
|
2778
|
+
const last = contour[contour.length - 1];
|
|
2779
|
+
if (first && last && first[0] === last[0] && first[1] === last[1]) {
|
|
2780
|
+
contour.pop();
|
|
2781
|
+
}
|
|
2782
|
+
}
|
|
2783
|
+
return contour.length >= 3 ? contour : null;
|
|
2784
|
+
};
|
|
2785
|
+
var collectSoldermaskContours = (project, soldermaskCutIndex) => {
|
|
2786
|
+
const contours = [];
|
|
2787
|
+
for (const child of project.children) {
|
|
2788
|
+
if (child instanceof ShapePath30) {
|
|
2789
|
+
if (child.cutIndex !== soldermaskCutIndex) {
|
|
2790
|
+
continue;
|
|
2791
|
+
}
|
|
2792
|
+
const contour = shapePathToContour(child);
|
|
2793
|
+
if (contour) {
|
|
2794
|
+
contours.push(contour);
|
|
2795
|
+
}
|
|
2796
|
+
continue;
|
|
2797
|
+
}
|
|
2798
|
+
if (child instanceof ShapeGroup3) {
|
|
2799
|
+
for (const groupChild of child.children) {
|
|
2800
|
+
if (groupChild instanceof ShapePath30) {
|
|
2801
|
+
if (groupChild.cutIndex !== soldermaskCutIndex) {
|
|
2802
|
+
continue;
|
|
2803
|
+
}
|
|
2804
|
+
const contour = shapePathToContour(groupChild);
|
|
2805
|
+
if (contour) {
|
|
2806
|
+
contours.push(contour);
|
|
2807
|
+
}
|
|
2808
|
+
}
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2812
|
+
return contours;
|
|
2813
|
+
};
|
|
2814
|
+
var createSoldermaskCureLayer = async ({
|
|
2815
|
+
ctx
|
|
2816
|
+
}) => {
|
|
2817
|
+
const { project, boardOutlineContour, soldermaskCureCutSetting } = ctx;
|
|
2818
|
+
if (!soldermaskCureCutSetting) {
|
|
2819
|
+
return;
|
|
2820
|
+
}
|
|
2821
|
+
if (ctx.soldermaskCutSetting.index === void 0) {
|
|
2822
|
+
return;
|
|
2823
|
+
}
|
|
2824
|
+
const soldermaskCutIndex = ctx.soldermaskCutSetting.index;
|
|
2825
|
+
if (!boardOutlineContour || boardOutlineContour.length < 3) {
|
|
2826
|
+
console.warn(
|
|
2827
|
+
"Cannot create soldermask cure layer: no board outline available"
|
|
2828
|
+
);
|
|
2829
|
+
return;
|
|
2830
|
+
}
|
|
2831
|
+
try {
|
|
2832
|
+
const manifold = await getManifold();
|
|
2833
|
+
const { CrossSection } = manifold;
|
|
2834
|
+
const allContours = collectSoldermaskContours(project, soldermaskCutIndex);
|
|
2835
|
+
if (allContours.length === 0) {
|
|
2836
|
+
return;
|
|
2837
|
+
}
|
|
2838
|
+
const boardOutline = new CrossSection([boardOutlineContour], "Positive");
|
|
2839
|
+
const soldermaskOpenings = new CrossSection(allContours, "Positive");
|
|
2840
|
+
const cureArea = boardOutline.subtract(soldermaskOpenings);
|
|
2841
|
+
const simplifiedArea = cureArea.simplify(1e-3);
|
|
2842
|
+
const resultContours = simplifiedArea.toPolygons();
|
|
2843
|
+
if (resultContours.length === 0) {
|
|
2844
|
+
boardOutline.delete();
|
|
2845
|
+
soldermaskOpenings.delete();
|
|
2846
|
+
cureArea.delete();
|
|
2847
|
+
simplifiedArea.delete();
|
|
2848
|
+
return;
|
|
2849
|
+
}
|
|
2850
|
+
const shapeGroup = new ShapeGroup3();
|
|
2851
|
+
for (const contour of resultContours) {
|
|
2852
|
+
const polygon = contourToPolygon3(contour);
|
|
2853
|
+
if (!polygon) continue;
|
|
2854
|
+
for (const island of polygon.splitToIslands()) {
|
|
2855
|
+
const { verts, prims } = polygonToShapePathData(island);
|
|
2856
|
+
if (verts.length > 0) {
|
|
2857
|
+
shapeGroup.children.push(
|
|
2858
|
+
new ShapePath30({
|
|
2859
|
+
cutIndex: soldermaskCureCutSetting.index,
|
|
2860
|
+
verts,
|
|
2861
|
+
prims,
|
|
2862
|
+
isClosed: true
|
|
2863
|
+
})
|
|
2864
|
+
);
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
if (shapeGroup.children.length > 0) {
|
|
2869
|
+
project.children.push(shapeGroup);
|
|
2870
|
+
}
|
|
2871
|
+
boardOutline.delete();
|
|
2872
|
+
soldermaskOpenings.delete();
|
|
2873
|
+
cureArea.delete();
|
|
2874
|
+
simplifiedArea.delete();
|
|
2875
|
+
} catch (error) {
|
|
2876
|
+
console.warn("Failed to create soldermask cure layer:", error);
|
|
2877
|
+
}
|
|
2753
2878
|
};
|
|
2754
2879
|
|
|
2755
2880
|
// lib/index.ts
|
|
@@ -2764,6 +2889,8 @@ var convertCircuitJsonToLbrn = async (circuitJson, options = {}) => {
|
|
|
2764
2889
|
const laserSpotSize = options.laserSpotSize ?? 5e-3;
|
|
2765
2890
|
const includeCopper = options.includeCopper ?? true;
|
|
2766
2891
|
const includeSoldermask = options.includeSoldermask ?? false;
|
|
2892
|
+
const includeSoldermaskCure = options.includeSoldermaskCure ?? false;
|
|
2893
|
+
const shouldIncludeSoldermaskCure = includeSoldermask && includeSoldermaskCure;
|
|
2767
2894
|
const globalCopperSoldermaskMarginAdjustment = options.globalCopperSoldermaskMarginAdjustment ?? 0;
|
|
2768
2895
|
const solderMaskMarginPercent = options.solderMaskMarginPercent ?? 0;
|
|
2769
2896
|
const laserProfile = options.laserProfile;
|
|
@@ -2827,6 +2954,21 @@ var convertCircuitJsonToLbrn = async (circuitJson, options = {}) => {
|
|
|
2827
2954
|
crossHatch: true
|
|
2828
2955
|
});
|
|
2829
2956
|
project.children.push(soldermaskCutSetting);
|
|
2957
|
+
let soldermaskCureCutSetting;
|
|
2958
|
+
if (shouldIncludeSoldermaskCure) {
|
|
2959
|
+
soldermaskCureCutSetting = new CutSetting({
|
|
2960
|
+
type: "Scan",
|
|
2961
|
+
index: LAYER_INDEXES.soldermaskCure,
|
|
2962
|
+
name: "Cut Soldermask Cure",
|
|
2963
|
+
numPasses: 1,
|
|
2964
|
+
speed: 150,
|
|
2965
|
+
scanOpt: "individual",
|
|
2966
|
+
interval: 0.18,
|
|
2967
|
+
angle: 45,
|
|
2968
|
+
crossHatch: true
|
|
2969
|
+
});
|
|
2970
|
+
project.children.push(soldermaskCureCutSetting);
|
|
2971
|
+
}
|
|
2830
2972
|
let topTraceClearanceAreaCutSetting;
|
|
2831
2973
|
let bottomTraceClearanceAreaCutSetting;
|
|
2832
2974
|
if (shouldGenerateTraceClearanceZones) {
|
|
@@ -2936,6 +3078,7 @@ var convertCircuitJsonToLbrn = async (circuitJson, options = {}) => {
|
|
|
2936
3078
|
bottomCopperCutSetting,
|
|
2937
3079
|
throughBoardCutSetting,
|
|
2938
3080
|
soldermaskCutSetting,
|
|
3081
|
+
soldermaskCureCutSetting,
|
|
2939
3082
|
connMap,
|
|
2940
3083
|
topCutNetGeoms: /* @__PURE__ */ new Map(),
|
|
2941
3084
|
bottomCutNetGeoms: /* @__PURE__ */ new Map(),
|
|
@@ -2944,6 +3087,7 @@ var convertCircuitJsonToLbrn = async (circuitJson, options = {}) => {
|
|
|
2944
3087
|
origin,
|
|
2945
3088
|
includeCopper,
|
|
2946
3089
|
includeSoldermask,
|
|
3090
|
+
includeSoldermaskCure,
|
|
2947
3091
|
globalCopperSoldermaskMarginAdjustment,
|
|
2948
3092
|
includeLayers,
|
|
2949
3093
|
traceMargin,
|
|
@@ -3040,6 +3184,9 @@ var convertCircuitJsonToLbrn = async (circuitJson, options = {}) => {
|
|
|
3040
3184
|
await createOxidationCleaningLayerForLayer({ layer: "bottom", ctx });
|
|
3041
3185
|
}
|
|
3042
3186
|
}
|
|
3187
|
+
if (shouldIncludeSoldermaskCure) {
|
|
3188
|
+
await createSoldermaskCureLayer({ ctx });
|
|
3189
|
+
}
|
|
3043
3190
|
return project;
|
|
3044
3191
|
};
|
|
3045
3192
|
export {
|
package/lib/ConvertContext.ts
CHANGED
|
@@ -15,6 +15,7 @@ export interface ConvertContext {
|
|
|
15
15
|
bottomCopperCutSetting: CutSetting
|
|
16
16
|
throughBoardCutSetting: CutSetting
|
|
17
17
|
soldermaskCutSetting: CutSetting
|
|
18
|
+
soldermaskCureCutSetting?: CutSetting
|
|
18
19
|
|
|
19
20
|
connMap: ConnectivityMap
|
|
20
21
|
|
|
@@ -33,6 +34,7 @@ export interface ConvertContext {
|
|
|
33
34
|
// Include flags
|
|
34
35
|
includeCopper: boolean
|
|
35
36
|
includeSoldermask: boolean
|
|
37
|
+
includeSoldermaskCure: boolean
|
|
36
38
|
includeLayers: Array<"top" | "bottom">
|
|
37
39
|
|
|
38
40
|
// Global copper soldermask margin adjustment (can be negative)
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { Point, Polygon } from "@flatten-js/core"
|
|
2
|
+
import { ShapeGroup, ShapePath } from "lbrnts"
|
|
3
|
+
import type { ConvertContext } from "./ConvertContext"
|
|
4
|
+
import { getManifold } from "./getManifold"
|
|
5
|
+
import { polygonToShapePathData } from "./polygon-to-shape-path"
|
|
6
|
+
|
|
7
|
+
type Contour = Array<[number, number]>
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Converts a single contour to a flatten-js Polygon
|
|
11
|
+
*/
|
|
12
|
+
const contourToPolygon = (contour: Contour): Polygon | null => {
|
|
13
|
+
if (contour.length < 3) return null
|
|
14
|
+
|
|
15
|
+
const points = contour.map(([x, y]) => new Point(x, y))
|
|
16
|
+
try {
|
|
17
|
+
const polygon = new Polygon(points)
|
|
18
|
+
if (polygon.faces.size > 0) {
|
|
19
|
+
return polygon
|
|
20
|
+
}
|
|
21
|
+
} catch {
|
|
22
|
+
// Skip invalid polygons
|
|
23
|
+
}
|
|
24
|
+
return null
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const shapePathToContour = (shapePath: ShapePath): Contour | null => {
|
|
28
|
+
if (!shapePath.verts || shapePath.verts.length < 3) return null
|
|
29
|
+
const contour = shapePath.verts.map(
|
|
30
|
+
(vert) => [vert.x, vert.y] as [number, number],
|
|
31
|
+
)
|
|
32
|
+
if (contour.length > 3) {
|
|
33
|
+
const first = contour[0]
|
|
34
|
+
const last = contour[contour.length - 1]
|
|
35
|
+
if (first && last && first[0] === last[0] && first[1] === last[1]) {
|
|
36
|
+
contour.pop()
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return contour.length >= 3 ? contour : null
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const collectSoldermaskContours = (
|
|
43
|
+
project: ConvertContext["project"],
|
|
44
|
+
soldermaskCutIndex: number,
|
|
45
|
+
) => {
|
|
46
|
+
const contours: Contour[] = []
|
|
47
|
+
|
|
48
|
+
for (const child of project.children) {
|
|
49
|
+
if (child instanceof ShapePath) {
|
|
50
|
+
if (child.cutIndex !== soldermaskCutIndex) {
|
|
51
|
+
continue
|
|
52
|
+
}
|
|
53
|
+
const contour = shapePathToContour(child)
|
|
54
|
+
if (contour) {
|
|
55
|
+
contours.push(contour)
|
|
56
|
+
}
|
|
57
|
+
continue
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (child instanceof ShapeGroup) {
|
|
61
|
+
for (const groupChild of child.children) {
|
|
62
|
+
if (groupChild instanceof ShapePath) {
|
|
63
|
+
if (groupChild.cutIndex !== soldermaskCutIndex) {
|
|
64
|
+
continue
|
|
65
|
+
}
|
|
66
|
+
const contour = shapePathToContour(groupChild)
|
|
67
|
+
if (contour) {
|
|
68
|
+
contours.push(contour)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return contours
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Creates a soldermask cure layer by subtracting soldermask openings from the board outline.
|
|
80
|
+
*/
|
|
81
|
+
export const createSoldermaskCureLayer = async ({
|
|
82
|
+
ctx,
|
|
83
|
+
}: {
|
|
84
|
+
ctx: ConvertContext
|
|
85
|
+
}): Promise<void> => {
|
|
86
|
+
const { project, boardOutlineContour, soldermaskCureCutSetting } = ctx
|
|
87
|
+
|
|
88
|
+
if (!soldermaskCureCutSetting) {
|
|
89
|
+
return
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (ctx.soldermaskCutSetting.index === undefined) {
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
const soldermaskCutIndex = ctx.soldermaskCutSetting.index
|
|
96
|
+
|
|
97
|
+
if (!boardOutlineContour || boardOutlineContour.length < 3) {
|
|
98
|
+
console.warn(
|
|
99
|
+
"Cannot create soldermask cure layer: no board outline available",
|
|
100
|
+
)
|
|
101
|
+
return
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
const manifold = await getManifold()
|
|
106
|
+
const { CrossSection } = manifold
|
|
107
|
+
|
|
108
|
+
const allContours = collectSoldermaskContours(project, soldermaskCutIndex)
|
|
109
|
+
if (allContours.length === 0) {
|
|
110
|
+
return
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const boardOutline = new CrossSection([boardOutlineContour], "Positive")
|
|
114
|
+
const soldermaskOpenings = new CrossSection(allContours, "Positive")
|
|
115
|
+
const cureArea = boardOutline.subtract(soldermaskOpenings)
|
|
116
|
+
const simplifiedArea = cureArea.simplify(0.001)
|
|
117
|
+
const resultContours: Contour[] = simplifiedArea.toPolygons()
|
|
118
|
+
|
|
119
|
+
if (resultContours.length === 0) {
|
|
120
|
+
boardOutline.delete()
|
|
121
|
+
soldermaskOpenings.delete()
|
|
122
|
+
cureArea.delete()
|
|
123
|
+
simplifiedArea.delete()
|
|
124
|
+
return
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const shapeGroup = new ShapeGroup()
|
|
128
|
+
|
|
129
|
+
for (const contour of resultContours) {
|
|
130
|
+
const polygon = contourToPolygon(contour)
|
|
131
|
+
if (!polygon) continue
|
|
132
|
+
|
|
133
|
+
for (const island of polygon.splitToIslands()) {
|
|
134
|
+
const { verts, prims } = polygonToShapePathData(island)
|
|
135
|
+
|
|
136
|
+
if (verts.length > 0) {
|
|
137
|
+
shapeGroup.children.push(
|
|
138
|
+
new ShapePath({
|
|
139
|
+
cutIndex: soldermaskCureCutSetting.index,
|
|
140
|
+
verts,
|
|
141
|
+
prims,
|
|
142
|
+
isClosed: true,
|
|
143
|
+
}),
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (shapeGroup.children.length > 0) {
|
|
150
|
+
project.children.push(shapeGroup)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
boardOutline.delete()
|
|
154
|
+
soldermaskOpenings.delete()
|
|
155
|
+
cureArea.delete()
|
|
156
|
+
simplifiedArea.delete()
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.warn("Failed to create soldermask cure layer:", error)
|
|
159
|
+
}
|
|
160
|
+
}
|
package/lib/index.ts
CHANGED
|
@@ -19,6 +19,7 @@ import { createTraceClearanceAreasForLayer } from "./createTraceClearanceAreasFo
|
|
|
19
19
|
import { createCopperCutFillForLayer } from "./createCopperCutFillForLayer"
|
|
20
20
|
import { createOxidationCleaningLayerForLayer } from "./createOxidationCleaningLayerForLayer"
|
|
21
21
|
import { LAYER_INDEXES } from "./layer-indexes"
|
|
22
|
+
import { createSoldermaskCureLayer } from "./createSoldermaskCureLayer"
|
|
22
23
|
|
|
23
24
|
export interface ConvertCircuitJsonToLbrnOptions {
|
|
24
25
|
includeSilkscreen?: boolean
|
|
@@ -26,6 +27,7 @@ export interface ConvertCircuitJsonToLbrnOptions {
|
|
|
26
27
|
margin?: number
|
|
27
28
|
includeCopper?: boolean
|
|
28
29
|
includeSoldermask?: boolean
|
|
30
|
+
includeSoldermaskCure?: boolean
|
|
29
31
|
globalCopperSoldermaskMarginAdjustment?: number
|
|
30
32
|
solderMaskMarginPercent?: number
|
|
31
33
|
includeLayers?: Array<"top" | "bottom">
|
|
@@ -79,6 +81,8 @@ export const convertCircuitJsonToLbrn = async (
|
|
|
79
81
|
const laserSpotSize = options.laserSpotSize ?? 0.005
|
|
80
82
|
const includeCopper = options.includeCopper ?? true
|
|
81
83
|
const includeSoldermask = options.includeSoldermask ?? false
|
|
84
|
+
const includeSoldermaskCure = options.includeSoldermaskCure ?? false
|
|
85
|
+
const shouldIncludeSoldermaskCure = includeSoldermask && includeSoldermaskCure
|
|
82
86
|
const globalCopperSoldermaskMarginAdjustment =
|
|
83
87
|
options.globalCopperSoldermaskMarginAdjustment ?? 0
|
|
84
88
|
const solderMaskMarginPercent = options.solderMaskMarginPercent ?? 0
|
|
@@ -158,6 +162,22 @@ export const convertCircuitJsonToLbrn = async (
|
|
|
158
162
|
})
|
|
159
163
|
project.children.push(soldermaskCutSetting)
|
|
160
164
|
|
|
165
|
+
let soldermaskCureCutSetting: CutSetting | undefined
|
|
166
|
+
if (shouldIncludeSoldermaskCure) {
|
|
167
|
+
soldermaskCureCutSetting = new CutSetting({
|
|
168
|
+
type: "Scan",
|
|
169
|
+
index: LAYER_INDEXES.soldermaskCure,
|
|
170
|
+
name: "Cut Soldermask Cure",
|
|
171
|
+
numPasses: 1,
|
|
172
|
+
speed: 150,
|
|
173
|
+
scanOpt: "individual",
|
|
174
|
+
interval: 0.18,
|
|
175
|
+
angle: 45,
|
|
176
|
+
crossHatch: true,
|
|
177
|
+
})
|
|
178
|
+
project.children.push(soldermaskCureCutSetting)
|
|
179
|
+
}
|
|
180
|
+
|
|
161
181
|
// Create trace clearance cut settings if needed
|
|
162
182
|
let topTraceClearanceAreaCutSetting: CutSetting | undefined
|
|
163
183
|
let bottomTraceClearanceAreaCutSetting: CutSetting | undefined
|
|
@@ -282,6 +302,7 @@ export const convertCircuitJsonToLbrn = async (
|
|
|
282
302
|
bottomCopperCutSetting,
|
|
283
303
|
throughBoardCutSetting,
|
|
284
304
|
soldermaskCutSetting,
|
|
305
|
+
soldermaskCureCutSetting,
|
|
285
306
|
connMap,
|
|
286
307
|
topCutNetGeoms: new Map(),
|
|
287
308
|
bottomCutNetGeoms: new Map(),
|
|
@@ -290,6 +311,7 @@ export const convertCircuitJsonToLbrn = async (
|
|
|
290
311
|
origin,
|
|
291
312
|
includeCopper,
|
|
292
313
|
includeSoldermask,
|
|
314
|
+
includeSoldermaskCure,
|
|
293
315
|
globalCopperSoldermaskMarginAdjustment,
|
|
294
316
|
includeLayers,
|
|
295
317
|
traceMargin,
|
|
@@ -411,5 +433,9 @@ export const convertCircuitJsonToLbrn = async (
|
|
|
411
433
|
}
|
|
412
434
|
}
|
|
413
435
|
|
|
436
|
+
if (shouldIncludeSoldermaskCure) {
|
|
437
|
+
await createSoldermaskCureLayer({ ctx })
|
|
438
|
+
}
|
|
439
|
+
|
|
414
440
|
return project
|
|
415
441
|
}
|
package/lib/layer-indexes.ts
CHANGED
package/package.json
CHANGED
package/site/index.html
CHANGED
|
@@ -262,78 +262,6 @@
|
|
|
262
262
|
</div>
|
|
263
263
|
</details>
|
|
264
264
|
</div>
|
|
265
|
-
<div class="md:col-span-2 grid grid-cols-1 md:grid-cols-4 gap-4">
|
|
266
|
-
<label class="flex items-center cursor-pointer">
|
|
267
|
-
<input
|
|
268
|
-
type="checkbox"
|
|
269
|
-
id="includeCopper"
|
|
270
|
-
checked
|
|
271
|
-
class="w-5 h-5 text-blue-500 bg-gray-700 border-gray-600 rounded focus:ring-blue-500 focus:ring-2"
|
|
272
|
-
/>
|
|
273
|
-
<span class="ml-3 text-sm font-medium text-gray-300">
|
|
274
|
-
Include Copper
|
|
275
|
-
</span>
|
|
276
|
-
</label>
|
|
277
|
-
<label class="flex items-center cursor-pointer">
|
|
278
|
-
<input
|
|
279
|
-
type="checkbox"
|
|
280
|
-
id="includeCopperCutFill"
|
|
281
|
-
class="w-5 h-5 text-blue-500 bg-gray-700 border-gray-600 rounded focus:ring-blue-500 focus:ring-2"
|
|
282
|
-
/>
|
|
283
|
-
<span class="ml-3 text-sm font-medium text-gray-300">
|
|
284
|
-
Include Copper Cut Fill
|
|
285
|
-
</span>
|
|
286
|
-
</label>
|
|
287
|
-
<label class="flex items-center cursor-pointer">
|
|
288
|
-
<input
|
|
289
|
-
type="checkbox"
|
|
290
|
-
id="includeSoldermask"
|
|
291
|
-
class="w-5 h-5 text-blue-500 bg-gray-700 border-gray-600 rounded focus:ring-blue-500 focus:ring-2"
|
|
292
|
-
/>
|
|
293
|
-
<span class="ml-3 text-sm font-medium text-gray-300">
|
|
294
|
-
Include Soldermask
|
|
295
|
-
</span>
|
|
296
|
-
</label>
|
|
297
|
-
<label class="flex items-center cursor-pointer">
|
|
298
|
-
<input
|
|
299
|
-
type="checkbox"
|
|
300
|
-
id="includeSilkscreen"
|
|
301
|
-
class="w-5 h-5 text-blue-500 bg-gray-700 border-gray-600 rounded focus:ring-blue-500 focus:ring-2"
|
|
302
|
-
/>
|
|
303
|
-
<span class="ml-3 text-sm font-medium text-gray-300">
|
|
304
|
-
Include Silkscreen Layer
|
|
305
|
-
</span>
|
|
306
|
-
</label>
|
|
307
|
-
</div>
|
|
308
|
-
<div class="md:col-span-2">
|
|
309
|
-
<label class="block text-sm font-medium text-gray-300 mb-2">
|
|
310
|
-
Include Layers
|
|
311
|
-
</label>
|
|
312
|
-
<div class="flex gap-4">
|
|
313
|
-
<label class="flex items-center cursor-pointer">
|
|
314
|
-
<input
|
|
315
|
-
type="checkbox"
|
|
316
|
-
id="includeTopLayer"
|
|
317
|
-
checked
|
|
318
|
-
class="w-5 h-5 text-blue-500 bg-gray-700 border-gray-600 rounded focus:ring-blue-500 focus:ring-2"
|
|
319
|
-
/>
|
|
320
|
-
<span class="ml-3 text-sm font-medium text-gray-300">
|
|
321
|
-
Top
|
|
322
|
-
</span>
|
|
323
|
-
</label>
|
|
324
|
-
<label class="flex items-center cursor-pointer">
|
|
325
|
-
<input
|
|
326
|
-
type="checkbox"
|
|
327
|
-
id="includeBottomLayer"
|
|
328
|
-
checked
|
|
329
|
-
class="w-5 h-5 text-blue-500 bg-gray-700 border-gray-600 rounded focus:ring-blue-500 focus:ring-2"
|
|
330
|
-
/>
|
|
331
|
-
<span class="ml-3 text-sm font-medium text-gray-300">
|
|
332
|
-
Bottom
|
|
333
|
-
</span>
|
|
334
|
-
</label>
|
|
335
|
-
</div>
|
|
336
|
-
</div>
|
|
337
265
|
</div>
|
|
338
266
|
<button
|
|
339
267
|
id="reconvertBtn"
|
package/site/main.tsx
CHANGED
|
@@ -45,27 +45,9 @@ const solderMaskMarginPercentInput = document.getElementById(
|
|
|
45
45
|
const laserSpotSizeInput = document.getElementById(
|
|
46
46
|
"laserSpotSize",
|
|
47
47
|
) as HTMLInputElement
|
|
48
|
-
const includeCopperInput = document.getElementById(
|
|
49
|
-
"includeCopper",
|
|
50
|
-
) as HTMLInputElement
|
|
51
|
-
const includeCopperCutFillInput = document.getElementById(
|
|
52
|
-
"includeCopperCutFill",
|
|
53
|
-
) as HTMLInputElement
|
|
54
48
|
const copperCutFillMarginInput = document.getElementById(
|
|
55
49
|
"copperCutFillMargin",
|
|
56
50
|
) as HTMLInputElement
|
|
57
|
-
const includeSoldermaskInput = document.getElementById(
|
|
58
|
-
"includeSoldermask",
|
|
59
|
-
) as HTMLInputElement
|
|
60
|
-
const includeSilkscreenInput = document.getElementById(
|
|
61
|
-
"includeSilkscreen",
|
|
62
|
-
) as HTMLInputElement
|
|
63
|
-
const includeTopLayerInput = document.getElementById(
|
|
64
|
-
"includeTopLayer",
|
|
65
|
-
) as HTMLInputElement
|
|
66
|
-
const includeBottomLayerInput = document.getElementById(
|
|
67
|
-
"includeBottomLayer",
|
|
68
|
-
) as HTMLInputElement
|
|
69
51
|
const copperSpeedInput = document.getElementById(
|
|
70
52
|
"copperSpeed",
|
|
71
53
|
) as HTMLInputElement
|
|
@@ -159,23 +141,21 @@ function showLoading(show: boolean) {
|
|
|
159
141
|
// Get conversion options from UI
|
|
160
142
|
function getConversionOptions() {
|
|
161
143
|
return {
|
|
162
|
-
includeSilkscreen:
|
|
144
|
+
includeSilkscreen: true,
|
|
163
145
|
origin: {
|
|
164
146
|
x: parseFloat(originXInput.value) || 0,
|
|
165
147
|
y: parseFloat(originYInput.value) || 0,
|
|
166
148
|
},
|
|
167
|
-
includeCopper:
|
|
168
|
-
includeCopperCutFill:
|
|
149
|
+
includeCopper: true,
|
|
150
|
+
includeCopperCutFill: true,
|
|
169
151
|
copperCutFillMargin: parseFloat(copperCutFillMarginInput.value) || 0.5,
|
|
170
|
-
includeSoldermask:
|
|
152
|
+
includeSoldermask: true,
|
|
153
|
+
includeSoldermaskCure: true,
|
|
171
154
|
globalCopperSoldermaskMarginAdjustment:
|
|
172
155
|
parseFloat(globalCopperSoldermaskMarginAdjustmentInput.value) || 0,
|
|
173
156
|
solderMaskMarginPercent:
|
|
174
157
|
parseFloat(solderMaskMarginPercentInput.value) || 0,
|
|
175
|
-
includeLayers: [
|
|
176
|
-
...(includeTopLayerInput.checked ? ["top" as const] : []),
|
|
177
|
-
...(includeBottomLayerInput.checked ? ["bottom" as const] : []),
|
|
178
|
-
],
|
|
158
|
+
includeLayers: ["top", "bottom"] as Array<"top" | "bottom">,
|
|
179
159
|
traceMargin: parseFloat(traceMarginInput.value) || 0,
|
|
180
160
|
laserSpotSize: parseFloat(laserSpotSizeInput.value) || 0.005,
|
|
181
161
|
laserProfile: {
|