circuit-json-to-step 0.0.22 → 0.0.24
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 +427 -339
- package/lib/index.ts +133 -59
- package/lib/mesh-generation.ts +32 -295
- package/lib/pill-geometry.ts +46 -41
- package/lib/scene-box-to-step.ts +138 -0
- package/lib/scene-geometry.ts +71 -0
- package/lib/step-brep-utils.ts +118 -0
- package/lib/step-model-merger/excluded-entity-types.ts +0 -11
- package/lib/step-model-merger.ts +6 -5
- package/lib/step-style-utils.ts +63 -0
- package/package.json +3 -3
- package/test/basics/basics01/__snapshots__/basics01.snap.png +0 -0
- package/test/basics/basics03/__snapshots__/basics03.snap.png +0 -0
- package/test/basics/basics04/__snapshots__/basics04.snap.png +0 -0
- package/test/basics/basics05/__snapshots__/basics05.snap.png +0 -0
- package/test/basics/basics06/__snapshots__/basics06.snap.png +0 -0
- package/test/basics/basics06/basics06.json +32 -7
- package/test/fixtures/step-snapshot.ts +95 -24
- package/test/repros/kicad-step/__snapshots__/kicad-step-board.snap.png +0 -0
- package/test/repros/kicad-step/__snapshots__/resistor-fixture.snap.png +0 -0
- package/test/repros/kicad-step/__snapshots__/switch-fixture.snap.png +0 -0
- package/test/repros/kicad-step/kicad-step.json +102 -22
- package/test/repros/repro01/__snapshots__/repro01.snap.png +0 -0
- package/test/repros/repro02/__snapshots__/repro02.snap.png +0 -0
- package/test/utils/occt/importer.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -26,207 +26,283 @@ import {
|
|
|
26
26
|
AdvancedFace as AdvancedFace3,
|
|
27
27
|
Circle as Circle2,
|
|
28
28
|
ClosedShell as ClosedShell2,
|
|
29
|
-
ManifoldSolidBrep as
|
|
30
|
-
ColourRgb,
|
|
31
|
-
FillAreaStyleColour,
|
|
32
|
-
FillAreaStyle,
|
|
33
|
-
SurfaceStyleFillArea,
|
|
34
|
-
SurfaceSideStyle,
|
|
35
|
-
SurfaceStyleUsage,
|
|
36
|
-
PresentationStyleAssignment,
|
|
37
|
-
StyledItem,
|
|
29
|
+
ManifoldSolidBrep as ManifoldSolidBrep4,
|
|
38
30
|
MechanicalDesignGeometricPresentationRepresentation,
|
|
39
31
|
AdvancedBrepShapeRepresentation,
|
|
40
32
|
ShapeDefinitionRepresentation
|
|
41
33
|
} from "stepts";
|
|
42
34
|
|
|
43
35
|
// lib/mesh-generation.ts
|
|
36
|
+
import "stepts";
|
|
37
|
+
|
|
38
|
+
// lib/scene-box-to-step.ts
|
|
39
|
+
import { ClosedShell, ManifoldSolidBrep } from "stepts";
|
|
40
|
+
|
|
41
|
+
// lib/step-style-utils.ts
|
|
42
|
+
import {
|
|
43
|
+
ColourRgb,
|
|
44
|
+
FillAreaStyle,
|
|
45
|
+
FillAreaStyleColour,
|
|
46
|
+
PresentationStyleAssignment,
|
|
47
|
+
StyledItem,
|
|
48
|
+
SurfaceSideStyle,
|
|
49
|
+
SurfaceStyleFillArea,
|
|
50
|
+
SurfaceStyleUsage
|
|
51
|
+
} from "stepts";
|
|
52
|
+
function createStyleCache() {
|
|
53
|
+
return /* @__PURE__ */ new Map();
|
|
54
|
+
}
|
|
55
|
+
function createStyledItem(repo, options) {
|
|
56
|
+
const { itemRef, rgb, styleCache, name = "color" } = options;
|
|
57
|
+
const key = rgb.map((value) => value.toFixed(6)).join(",");
|
|
58
|
+
let presStyle = styleCache.get(key);
|
|
59
|
+
if (!presStyle) {
|
|
60
|
+
const color = repo.add(new ColourRgb("", rgb[0], rgb[1], rgb[2]));
|
|
61
|
+
const fillColor = repo.add(new FillAreaStyleColour("", color));
|
|
62
|
+
const fillStyle = repo.add(new FillAreaStyle("", [fillColor]));
|
|
63
|
+
const surfaceFill = repo.add(new SurfaceStyleFillArea(fillStyle));
|
|
64
|
+
const surfaceSide = repo.add(new SurfaceSideStyle("", [surfaceFill]));
|
|
65
|
+
const surfaceUsage = repo.add(new SurfaceStyleUsage(".BOTH.", surfaceSide));
|
|
66
|
+
presStyle = repo.add(new PresentationStyleAssignment([surfaceUsage]));
|
|
67
|
+
styleCache.set(key, presStyle);
|
|
68
|
+
}
|
|
69
|
+
return repo.add(new StyledItem(name, [presStyle], itemRef));
|
|
70
|
+
}
|
|
71
|
+
function createStyledItems(repo, options) {
|
|
72
|
+
const { itemRefs, rgb, styleCache, name } = options;
|
|
73
|
+
return itemRefs.map(
|
|
74
|
+
(itemRef) => createStyledItem(repo, { itemRef, rgb, styleCache, name })
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// lib/scene-geometry.ts
|
|
79
|
+
function rotatePoint3(point, rotation) {
|
|
80
|
+
if (!rotation) return point;
|
|
81
|
+
let { x, y, z } = point;
|
|
82
|
+
if (rotation.x) {
|
|
83
|
+
const cos = Math.cos(rotation.x);
|
|
84
|
+
const sin = Math.sin(rotation.x);
|
|
85
|
+
const nextY = y * cos - z * sin;
|
|
86
|
+
const nextZ = y * sin + z * cos;
|
|
87
|
+
y = nextY;
|
|
88
|
+
z = nextZ;
|
|
89
|
+
}
|
|
90
|
+
if (rotation.y) {
|
|
91
|
+
const cos = Math.cos(rotation.y);
|
|
92
|
+
const sin = Math.sin(rotation.y);
|
|
93
|
+
const nextX = x * cos + z * sin;
|
|
94
|
+
const nextZ = -x * sin + z * cos;
|
|
95
|
+
x = nextX;
|
|
96
|
+
z = nextZ;
|
|
97
|
+
}
|
|
98
|
+
if (rotation.z) {
|
|
99
|
+
const cos = Math.cos(rotation.z);
|
|
100
|
+
const sin = Math.sin(rotation.z);
|
|
101
|
+
const nextX = x * cos - y * sin;
|
|
102
|
+
const nextY = x * sin + y * cos;
|
|
103
|
+
x = nextX;
|
|
104
|
+
y = nextY;
|
|
105
|
+
}
|
|
106
|
+
return { x, y, z };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// lib/step-brep-utils.ts
|
|
44
110
|
import {
|
|
45
111
|
AdvancedFace,
|
|
46
112
|
Axis2Placement3D,
|
|
47
113
|
CartesianPoint,
|
|
48
|
-
ClosedShell,
|
|
49
114
|
Direction,
|
|
50
115
|
EdgeCurve,
|
|
51
116
|
EdgeLoop,
|
|
52
117
|
FaceOuterBound,
|
|
53
118
|
Line,
|
|
54
|
-
ManifoldSolidBrep,
|
|
55
119
|
OrientedEdge,
|
|
56
120
|
Plane,
|
|
57
121
|
Vector,
|
|
58
122
|
VertexPoint
|
|
59
123
|
} from "stepts";
|
|
60
|
-
function
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
124
|
+
function createVertex(repo, point) {
|
|
125
|
+
return repo.add(
|
|
126
|
+
new VertexPoint(
|
|
127
|
+
"",
|
|
128
|
+
repo.add(new CartesianPoint("", point.x, point.y, point.z))
|
|
129
|
+
)
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
function createEdge(repo, vStart, vEnd) {
|
|
133
|
+
const pStart = vStart.resolve(repo).pnt.resolve(repo);
|
|
134
|
+
const pEnd = vEnd.resolve(repo).pnt.resolve(repo);
|
|
135
|
+
const dx = pEnd.x - pStart.x;
|
|
136
|
+
const dy = pEnd.y - pStart.y;
|
|
137
|
+
const dz = pEnd.z - pStart.z;
|
|
138
|
+
const length = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
139
|
+
if (length < 1e-10) {
|
|
140
|
+
const dir2 = repo.add(new Direction("", 1, 0, 0));
|
|
141
|
+
const vec2 = repo.add(new Vector("", dir2, 1e-10));
|
|
142
|
+
const line2 = repo.add(new Line("", vStart.resolve(repo).pnt, vec2));
|
|
143
|
+
return repo.add(new EdgeCurve("", vStart, vEnd, line2, true));
|
|
144
|
+
}
|
|
145
|
+
const dir = repo.add(new Direction("", dx / length, dy / length, dz / length));
|
|
146
|
+
const vec = repo.add(new Vector("", dir, length));
|
|
147
|
+
const line = repo.add(new Line("", vStart.resolve(repo).pnt, vec));
|
|
148
|
+
return repo.add(new EdgeCurve("", vStart, vEnd, line, true));
|
|
149
|
+
}
|
|
150
|
+
function createFaceFromVertices(repo, vertices) {
|
|
151
|
+
const edges = vertices.map(
|
|
152
|
+
(vertex, index) => createEdge(repo, vertex, vertices[(index + 1) % vertices.length])
|
|
153
|
+
);
|
|
154
|
+
const edgeLoop = repo.add(
|
|
155
|
+
new EdgeLoop(
|
|
156
|
+
"",
|
|
157
|
+
edges.map((edge) => repo.add(new OrientedEdge("", edge, true)))
|
|
158
|
+
)
|
|
159
|
+
);
|
|
160
|
+
const p1 = vertices[0].resolve(repo).pnt.resolve(repo);
|
|
161
|
+
const p2 = vertices[1].resolve(repo).pnt.resolve(repo);
|
|
162
|
+
const p3 = vertices[2].resolve(repo).pnt.resolve(repo);
|
|
163
|
+
const ux = p2.x - p1.x;
|
|
164
|
+
const uy = p2.y - p1.y;
|
|
165
|
+
const uz = p2.z - p1.z;
|
|
166
|
+
const vx = p3.x - p1.x;
|
|
167
|
+
const vy = p3.y - p1.y;
|
|
168
|
+
const vz = p3.z - p1.z;
|
|
169
|
+
const nx = uy * vz - uz * vy;
|
|
170
|
+
const ny = uz * vx - ux * vz;
|
|
171
|
+
const nz = ux * vy - uy * vx;
|
|
172
|
+
const normalLength = Math.sqrt(nx * nx + ny * ny + nz * nz);
|
|
173
|
+
const normal = normalLength < 1e-10 ? repo.add(new Direction("", 0, 0, 1)) : repo.add(
|
|
174
|
+
new Direction(
|
|
175
|
+
"",
|
|
176
|
+
nx / normalLength,
|
|
177
|
+
ny / normalLength,
|
|
178
|
+
nz / normalLength
|
|
179
|
+
)
|
|
180
|
+
);
|
|
181
|
+
const refLength = Math.sqrt(ux * ux + uy * uy + uz * uz);
|
|
182
|
+
const refDir = refLength < 1e-10 ? repo.add(new Direction("", 1, 0, 0)) : repo.add(
|
|
183
|
+
new Direction("", ux / refLength, uy / refLength, uz / refLength)
|
|
184
|
+
);
|
|
185
|
+
const placement = repo.add(
|
|
186
|
+
new Axis2Placement3D("", vertices[0].resolve(repo).pnt, normal, refDir)
|
|
187
|
+
);
|
|
188
|
+
const plane = repo.add(new Plane("", placement));
|
|
189
|
+
return repo.add(
|
|
190
|
+
new AdvancedFace(
|
|
191
|
+
"",
|
|
192
|
+
[repo.add(new FaceOuterBound("", edgeLoop, true))],
|
|
193
|
+
plane,
|
|
194
|
+
true
|
|
195
|
+
)
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// lib/scene-box-to-step.ts
|
|
200
|
+
function createSceneBoxSolid(repo, box) {
|
|
201
|
+
if (box.mesh?.triangles?.length) {
|
|
202
|
+
return createSceneMeshSolid(repo, box);
|
|
203
|
+
}
|
|
204
|
+
const localBounds = box.mesh?.boundingBox ? {
|
|
205
|
+
min: box.mesh.boundingBox.min,
|
|
206
|
+
max: box.mesh.boundingBox.max
|
|
207
|
+
} : {
|
|
208
|
+
min: {
|
|
209
|
+
x: -box.size.x / 2,
|
|
210
|
+
y: -box.size.y / 2,
|
|
211
|
+
z: -box.size.z / 2
|
|
125
212
|
},
|
|
126
|
-
{
|
|
127
|
-
|
|
128
|
-
|
|
213
|
+
max: {
|
|
214
|
+
x: box.size.x / 2,
|
|
215
|
+
y: box.size.y / 2,
|
|
216
|
+
z: box.size.z / 2
|
|
129
217
|
}
|
|
130
|
-
|
|
131
|
-
|
|
218
|
+
};
|
|
219
|
+
const corners = [
|
|
220
|
+
{ x: localBounds.min.x, y: localBounds.min.y, z: localBounds.min.z },
|
|
221
|
+
{ x: localBounds.max.x, y: localBounds.min.y, z: localBounds.min.z },
|
|
222
|
+
{ x: localBounds.max.x, y: localBounds.max.y, z: localBounds.min.z },
|
|
223
|
+
{ x: localBounds.min.x, y: localBounds.max.y, z: localBounds.min.z },
|
|
224
|
+
{ x: localBounds.min.x, y: localBounds.min.y, z: localBounds.max.z },
|
|
225
|
+
{ x: localBounds.max.x, y: localBounds.min.y, z: localBounds.max.z },
|
|
226
|
+
{ x: localBounds.max.x, y: localBounds.max.y, z: localBounds.max.z },
|
|
227
|
+
{ x: localBounds.min.x, y: localBounds.max.y, z: localBounds.max.z }
|
|
228
|
+
].map((corner) => {
|
|
229
|
+
const rotated = rotatePoint3(corner, box.rotation);
|
|
230
|
+
return {
|
|
231
|
+
x: rotated.x + box.center.x,
|
|
232
|
+
y: rotated.y + box.center.y,
|
|
233
|
+
z: rotated.z + box.center.z
|
|
234
|
+
};
|
|
235
|
+
});
|
|
236
|
+
const stepCorners = corners.map((corner) => ({
|
|
237
|
+
x: corner.x,
|
|
238
|
+
y: corner.z,
|
|
239
|
+
z: corner.y
|
|
240
|
+
}));
|
|
241
|
+
const vertices = stepCorners.map((corner) => createVertex(repo, corner));
|
|
242
|
+
const faces = [
|
|
243
|
+
[vertices[0], vertices[1], vertices[2], vertices[3]],
|
|
244
|
+
[vertices[4], vertices[7], vertices[6], vertices[5]],
|
|
245
|
+
[vertices[0], vertices[4], vertices[5], vertices[1]],
|
|
246
|
+
[vertices[1], vertices[5], vertices[6], vertices[2]],
|
|
247
|
+
[vertices[2], vertices[6], vertices[7], vertices[3]],
|
|
248
|
+
[vertices[3], vertices[7], vertices[4], vertices[0]]
|
|
249
|
+
].map((faceVertices) => createFaceFromVertices(repo, faceVertices));
|
|
250
|
+
const shell = repo.add(new ClosedShell("", faces));
|
|
251
|
+
return {
|
|
252
|
+
solid: repo.add(new ManifoldSolidBrep(box.label ?? "Component", shell)),
|
|
253
|
+
styledItems: [],
|
|
254
|
+
usesIntrinsicFaceStyles: false,
|
|
255
|
+
styleTargets: faces
|
|
256
|
+
};
|
|
132
257
|
}
|
|
133
|
-
function
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
)
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
triangle.vertices[1].x,
|
|
156
|
-
triangle.vertices[1].y,
|
|
157
|
-
triangle.vertices[1].z
|
|
158
|
-
)
|
|
159
|
-
)
|
|
160
|
-
)
|
|
161
|
-
);
|
|
162
|
-
const v3 = repo.add(
|
|
163
|
-
new VertexPoint(
|
|
164
|
-
"",
|
|
165
|
-
repo.add(
|
|
166
|
-
new CartesianPoint(
|
|
167
|
-
"",
|
|
168
|
-
triangle.vertices[2].x,
|
|
169
|
-
triangle.vertices[2].y,
|
|
170
|
-
triangle.vertices[2].z
|
|
171
|
-
)
|
|
172
|
-
)
|
|
173
|
-
)
|
|
174
|
-
);
|
|
175
|
-
const p1 = v1.resolve(repo).pnt.resolve(repo);
|
|
176
|
-
const p2 = v2.resolve(repo).pnt.resolve(repo);
|
|
177
|
-
const createEdge = (vStart, vEnd) => {
|
|
178
|
-
const pStart = vStart.resolve(repo).pnt.resolve(repo);
|
|
179
|
-
const pEnd = vEnd.resolve(repo).pnt.resolve(repo);
|
|
180
|
-
const dir = repo.add(
|
|
181
|
-
new Direction(
|
|
182
|
-
"",
|
|
183
|
-
pEnd.x - pStart.x,
|
|
184
|
-
pEnd.y - pStart.y,
|
|
185
|
-
pEnd.z - pStart.z
|
|
186
|
-
)
|
|
258
|
+
function createSceneMeshSolid(repo, box) {
|
|
259
|
+
const styleCache = createStyleCache();
|
|
260
|
+
const styledItems = [];
|
|
261
|
+
const faces = box.mesh.triangles.map((triangle) => {
|
|
262
|
+
const vertices = triangle.vertices.map((vertex) => {
|
|
263
|
+
const rotated = rotatePoint3(vertex, box.rotation);
|
|
264
|
+
const translated = {
|
|
265
|
+
x: rotated.x + box.center.x,
|
|
266
|
+
y: rotated.z + box.center.z,
|
|
267
|
+
z: rotated.y + box.center.y
|
|
268
|
+
};
|
|
269
|
+
return createVertex(repo, translated);
|
|
270
|
+
});
|
|
271
|
+
const face = createFaceFromVertices(repo, vertices);
|
|
272
|
+
const faceColor = normalizeTriangleColor(triangle.color);
|
|
273
|
+
if (faceColor) {
|
|
274
|
+
styledItems.push(
|
|
275
|
+
createStyledItem(repo, {
|
|
276
|
+
itemRef: face,
|
|
277
|
+
rgb: faceColor,
|
|
278
|
+
styleCache
|
|
279
|
+
})
|
|
187
280
|
);
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const refX = p2.x - p1.x;
|
|
211
|
-
const refY = p2.y - p1.y;
|
|
212
|
-
const refZ = p2.z - p1.z;
|
|
213
|
-
const refDir = repo.add(new Direction("", refX, refY, refZ));
|
|
214
|
-
const placement = repo.add(
|
|
215
|
-
new Axis2Placement3D("", v1.resolve(repo).pnt, normalDir, refDir)
|
|
216
|
-
);
|
|
217
|
-
const plane = repo.add(new Plane("", placement));
|
|
218
|
-
const face = repo.add(
|
|
219
|
-
new AdvancedFace(
|
|
220
|
-
"",
|
|
221
|
-
[repo.add(new FaceOuterBound("", edgeLoop, true))],
|
|
222
|
-
plane,
|
|
223
|
-
true
|
|
224
|
-
)
|
|
225
|
-
);
|
|
226
|
-
faces.push(face);
|
|
227
|
-
}
|
|
228
|
-
return faces;
|
|
281
|
+
}
|
|
282
|
+
return face;
|
|
283
|
+
});
|
|
284
|
+
const shell = repo.add(new ClosedShell("", faces));
|
|
285
|
+
return {
|
|
286
|
+
solid: repo.add(new ManifoldSolidBrep(box.label ?? "Component", shell)),
|
|
287
|
+
styledItems,
|
|
288
|
+
usesIntrinsicFaceStyles: faces.length > 0 && styledItems.length === faces.length,
|
|
289
|
+
styleTargets: []
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
function normalizeTriangleColor(color) {
|
|
293
|
+
if (!Array.isArray(color) || color.length < 3) return null;
|
|
294
|
+
const scale = color.some((value) => value > 1) ? 255 : 1;
|
|
295
|
+
return [
|
|
296
|
+
clampColorChannel(color[0] / scale),
|
|
297
|
+
clampColorChannel(color[1] / scale),
|
|
298
|
+
clampColorChannel(color[2] / scale)
|
|
299
|
+
];
|
|
300
|
+
}
|
|
301
|
+
function clampColorChannel(value) {
|
|
302
|
+
return Math.max(0, Math.min(1, value));
|
|
229
303
|
}
|
|
304
|
+
|
|
305
|
+
// lib/mesh-generation.ts
|
|
230
306
|
async function generateComponentMeshes(options) {
|
|
231
307
|
const {
|
|
232
308
|
repo,
|
|
@@ -239,25 +315,25 @@ async function generateComponentMeshes(options) {
|
|
|
239
315
|
} = options;
|
|
240
316
|
const solids = [];
|
|
241
317
|
try {
|
|
242
|
-
const filteredCircuitJson = circuitJson.filter((
|
|
243
|
-
if (
|
|
244
|
-
if (
|
|
318
|
+
const filteredCircuitJson = circuitJson.filter((element) => {
|
|
319
|
+
if (element.type === "pcb_board") return false;
|
|
320
|
+
if (element.type === "cad_component" && element.cad_component_id && excludeCadComponentIds?.has(element.cad_component_id)) {
|
|
245
321
|
return false;
|
|
246
322
|
}
|
|
247
|
-
if (
|
|
323
|
+
if (element.type === "pcb_component" && element.pcb_component_id && excludePcbComponentIds?.has(element.pcb_component_id)) {
|
|
248
324
|
return false;
|
|
249
325
|
}
|
|
250
|
-
if (
|
|
326
|
+
if (element.type === "cad_component" && element.model_step_url) {
|
|
251
327
|
return false;
|
|
252
328
|
}
|
|
253
|
-
if (
|
|
329
|
+
if (element.type === "cad_component" && element.pcb_component_id && pcbComponentIdsWithStepUrl?.has(element.pcb_component_id)) {
|
|
254
330
|
return false;
|
|
255
331
|
}
|
|
256
332
|
return true;
|
|
257
|
-
}).map((
|
|
258
|
-
if (!includeExternalMeshes &&
|
|
333
|
+
}).map((element) => {
|
|
334
|
+
if (!includeExternalMeshes && element.type === "cad_component") {
|
|
259
335
|
return {
|
|
260
|
-
...
|
|
336
|
+
...element,
|
|
261
337
|
model_3mf_url: void 0,
|
|
262
338
|
model_obj_url: void 0,
|
|
263
339
|
model_stl_url: void 0,
|
|
@@ -265,7 +341,7 @@ async function generateComponentMeshes(options) {
|
|
|
265
341
|
model_gltf_url: void 0
|
|
266
342
|
};
|
|
267
343
|
}
|
|
268
|
-
return
|
|
344
|
+
return element;
|
|
269
345
|
});
|
|
270
346
|
const gltfModule = "circuit-json-to-gltf";
|
|
271
347
|
const { convertCircuitJsonTo3D } = await import(
|
|
@@ -276,43 +352,8 @@ async function generateComponentMeshes(options) {
|
|
|
276
352
|
boardThickness,
|
|
277
353
|
renderBoardTextures: false
|
|
278
354
|
});
|
|
279
|
-
const allTriangles = [];
|
|
280
355
|
for (const box of scene3d.boxes) {
|
|
281
|
-
|
|
282
|
-
allTriangles.push(...box.mesh.triangles);
|
|
283
|
-
} else {
|
|
284
|
-
const boxTriangles = createBoxTriangles(box);
|
|
285
|
-
allTriangles.push(...boxTriangles);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
if (allTriangles.length > 0) {
|
|
289
|
-
const transformedTriangles = allTriangles.map((tri) => ({
|
|
290
|
-
vertices: tri.vertices.map((v) => ({
|
|
291
|
-
x: v.x,
|
|
292
|
-
y: v.z,
|
|
293
|
-
// GLTF Z becomes STEP Y
|
|
294
|
-
z: v.y
|
|
295
|
-
// GLTF Y becomes STEP Z
|
|
296
|
-
})),
|
|
297
|
-
normal: {
|
|
298
|
-
x: tri.normal.x,
|
|
299
|
-
y: tri.normal.z,
|
|
300
|
-
// GLTF Z becomes STEP Y
|
|
301
|
-
z: tri.normal.y
|
|
302
|
-
// GLTF Y becomes STEP Z
|
|
303
|
-
}
|
|
304
|
-
}));
|
|
305
|
-
const componentFaces = createStepFacesFromTriangles(
|
|
306
|
-
repo,
|
|
307
|
-
transformedTriangles
|
|
308
|
-
);
|
|
309
|
-
const componentShell = repo.add(
|
|
310
|
-
new ClosedShell("", componentFaces)
|
|
311
|
-
);
|
|
312
|
-
const componentSolid = repo.add(
|
|
313
|
-
new ManifoldSolidBrep("Components", componentShell)
|
|
314
|
-
);
|
|
315
|
-
solids.push(componentSolid);
|
|
356
|
+
solids.push(createSceneBoxSolid(repo, box));
|
|
316
357
|
}
|
|
317
358
|
} catch (error) {
|
|
318
359
|
console.warn("Failed to generate component mesh:", error);
|
|
@@ -324,7 +365,7 @@ async function generateComponentMeshes(options) {
|
|
|
324
365
|
import {
|
|
325
366
|
CartesianPoint as CartesianPoint2,
|
|
326
367
|
Direction as Direction2,
|
|
327
|
-
ManifoldSolidBrep as
|
|
368
|
+
ManifoldSolidBrep as ManifoldSolidBrep3,
|
|
328
369
|
Ref,
|
|
329
370
|
Unknown,
|
|
330
371
|
parseRepository
|
|
@@ -343,17 +384,6 @@ var EXCLUDED_ENTITY_TYPES = /* @__PURE__ */ new Set([
|
|
|
343
384
|
"PRODUCT_DEFINITION_SHAPE",
|
|
344
385
|
"SHAPE_DEFINITION_REPRESENTATION",
|
|
345
386
|
"ADVANCED_BREP_SHAPE_REPRESENTATION",
|
|
346
|
-
"MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION",
|
|
347
|
-
"PRESENTATION_STYLE_ASSIGNMENT",
|
|
348
|
-
"SURFACE_STYLE_USAGE",
|
|
349
|
-
"SURFACE_SIDE_STYLE",
|
|
350
|
-
"SURFACE_STYLE_FILL_AREA",
|
|
351
|
-
"FILL_AREA_STYLE",
|
|
352
|
-
"FILL_AREA_STYLE_COLOUR",
|
|
353
|
-
"COLOUR_RGB",
|
|
354
|
-
"STYLED_ITEM",
|
|
355
|
-
"CURVE_STYLE",
|
|
356
|
-
"DRAUGHTING_PRE_DEFINED_CURVE_FONT",
|
|
357
387
|
"PRODUCT_RELATED_PRODUCT_CATEGORY",
|
|
358
388
|
"NEXT_ASSEMBLY_USAGE_OCCURRENCE",
|
|
359
389
|
"CONTEXT_DEPENDENT_SHAPE_REPRESENTATION",
|
|
@@ -498,7 +528,7 @@ function mergeSingleStepModel(targetRepo, stepText, transform, placement) {
|
|
|
498
528
|
}
|
|
499
529
|
const solids = [];
|
|
500
530
|
for (const [oldId, entity] of entries) {
|
|
501
|
-
if (entity instanceof
|
|
531
|
+
if (entity instanceof ManifoldSolidBrep3) {
|
|
502
532
|
const mappedId = idMapping.get(oldId);
|
|
503
533
|
if (mappedId !== void 0) {
|
|
504
534
|
solids.push(new Ref(eid(mappedId)));
|
|
@@ -548,16 +578,16 @@ function adjustTransformForPlacement(entries, transform, placement) {
|
|
|
548
578
|
transform.translation.x = targetX - center.x;
|
|
549
579
|
transform.translation.y = targetY - center.y;
|
|
550
580
|
if (isThroughHoleComponent) {
|
|
551
|
-
transform.translation.z = boardThickness;
|
|
581
|
+
transform.translation.z = boardThickness / 2;
|
|
552
582
|
}
|
|
553
583
|
if (!isThroughHoleComponent && boardThickness > 0) {
|
|
554
584
|
const halfThickness = boardThickness / 2;
|
|
555
|
-
const offsetZ = targetZ
|
|
585
|
+
const offsetZ = targetZ;
|
|
556
586
|
if (normalizedLayer === "bottom") {
|
|
557
587
|
transform.translation.z = -maxZ + offsetZ;
|
|
558
588
|
transform.rotation.x = normalizeDegrees(transform.rotation.x + 180);
|
|
559
589
|
} else {
|
|
560
|
-
transform.translation.z =
|
|
590
|
+
transform.translation.z = halfThickness - minZ + offsetZ;
|
|
561
591
|
}
|
|
562
592
|
} else if (!isThroughHoleComponent) {
|
|
563
593
|
transform.translation.z = targetZ - center.z;
|
|
@@ -722,7 +752,7 @@ function normalizeStepNumericExponents(stepText) {
|
|
|
722
752
|
var package_default = {
|
|
723
753
|
name: "circuit-json-to-step",
|
|
724
754
|
main: "dist/index.js",
|
|
725
|
-
version: "0.0.
|
|
755
|
+
version: "0.0.23",
|
|
726
756
|
type: "module",
|
|
727
757
|
scripts: {
|
|
728
758
|
"pull-reference": `git clone https://github.com/tscircuit/circuit-json.git && find circuit-json/tests -name '*.test.ts' -exec bash -c 'mv "$0" "\${0%.test.ts}.ts"' {} \\; && git clone https://github.com/tscircuit/stepts.git && find stepts/tests -name '*.test.ts' -exec bash -c 'mv "$0" "\${0%.test.ts}.ts"' {} \\;`,
|
|
@@ -740,7 +770,7 @@ var package_default = {
|
|
|
740
770
|
"@resvg/resvg-wasm": "^2.6.2",
|
|
741
771
|
"@tscircuit/circuit-json-util": "^0.0.75",
|
|
742
772
|
"@types/bun": "latest",
|
|
743
|
-
"circuit-json": "^0.0.
|
|
773
|
+
"circuit-json": "^0.0.406",
|
|
744
774
|
"looks-same": "^10.0.1",
|
|
745
775
|
"occt-import-js": "^0.0.23",
|
|
746
776
|
poppygl: "^0.0.17",
|
|
@@ -752,7 +782,7 @@ var package_default = {
|
|
|
752
782
|
},
|
|
753
783
|
dependencies: {
|
|
754
784
|
"circuit-json-to-connectivity-map": "^0.0.22",
|
|
755
|
-
"circuit-json-to-gltf": "^0.0.
|
|
785
|
+
"circuit-json-to-gltf": "^0.0.93",
|
|
756
786
|
"circuit-to-svg": "^0.0.327",
|
|
757
787
|
"schematic-symbols": "^0.0.202",
|
|
758
788
|
stepts: "^0.0.4"
|
|
@@ -1049,7 +1079,7 @@ function createPillHoleLoop(repo, hole, z, xDir) {
|
|
|
1049
1079
|
);
|
|
1050
1080
|
return repo.add(new EdgeLoop2("", orientedEdges));
|
|
1051
1081
|
}
|
|
1052
|
-
function createPillCylindricalFaces(repo, hole,
|
|
1082
|
+
function createPillCylindricalFaces(repo, hole, zMin, zMax, xDir, zDir) {
|
|
1053
1083
|
const geom = getPillGeometry(hole);
|
|
1054
1084
|
const {
|
|
1055
1085
|
centerX,
|
|
@@ -1073,7 +1103,8 @@ function createPillCylindricalFaces(repo, hole, boardThickness, xDir, zDir) {
|
|
|
1073
1103
|
rotation,
|
|
1074
1104
|
centerX,
|
|
1075
1105
|
centerY,
|
|
1076
|
-
|
|
1106
|
+
zMin,
|
|
1107
|
+
zMax,
|
|
1077
1108
|
zDir,
|
|
1078
1109
|
xDir
|
|
1079
1110
|
)
|
|
@@ -1088,7 +1119,8 @@ function createPillCylindricalFaces(repo, hole, boardThickness, xDir, zDir) {
|
|
|
1088
1119
|
rotation,
|
|
1089
1120
|
centerX,
|
|
1090
1121
|
centerY,
|
|
1091
|
-
|
|
1122
|
+
zMin,
|
|
1123
|
+
zMax,
|
|
1092
1124
|
zDir
|
|
1093
1125
|
)
|
|
1094
1126
|
);
|
|
@@ -1103,7 +1135,8 @@ function createPillCylindricalFaces(repo, hole, boardThickness, xDir, zDir) {
|
|
|
1103
1135
|
rotation,
|
|
1104
1136
|
centerX,
|
|
1105
1137
|
centerY,
|
|
1106
|
-
|
|
1138
|
+
zMin,
|
|
1139
|
+
zMax,
|
|
1107
1140
|
zDir,
|
|
1108
1141
|
xDir
|
|
1109
1142
|
)
|
|
@@ -1118,7 +1151,8 @@ function createPillCylindricalFaces(repo, hole, boardThickness, xDir, zDir) {
|
|
|
1118
1151
|
rotation,
|
|
1119
1152
|
centerX,
|
|
1120
1153
|
centerY,
|
|
1121
|
-
|
|
1154
|
+
zMin,
|
|
1155
|
+
zMax,
|
|
1122
1156
|
zDir
|
|
1123
1157
|
)
|
|
1124
1158
|
);
|
|
@@ -1135,7 +1169,8 @@ function createPillCylindricalFaces(repo, hole, boardThickness, xDir, zDir) {
|
|
|
1135
1169
|
rotation,
|
|
1136
1170
|
centerX,
|
|
1137
1171
|
centerY,
|
|
1138
|
-
|
|
1172
|
+
zMin,
|
|
1173
|
+
zMax,
|
|
1139
1174
|
zDir,
|
|
1140
1175
|
xDir
|
|
1141
1176
|
)
|
|
@@ -1150,7 +1185,8 @@ function createPillCylindricalFaces(repo, hole, boardThickness, xDir, zDir) {
|
|
|
1150
1185
|
rotation,
|
|
1151
1186
|
centerX,
|
|
1152
1187
|
centerY,
|
|
1153
|
-
|
|
1188
|
+
zMin,
|
|
1189
|
+
zMax,
|
|
1154
1190
|
zDir
|
|
1155
1191
|
)
|
|
1156
1192
|
);
|
|
@@ -1165,7 +1201,8 @@ function createPillCylindricalFaces(repo, hole, boardThickness, xDir, zDir) {
|
|
|
1165
1201
|
rotation,
|
|
1166
1202
|
centerX,
|
|
1167
1203
|
centerY,
|
|
1168
|
-
|
|
1204
|
+
zMin,
|
|
1205
|
+
zMax,
|
|
1169
1206
|
zDir,
|
|
1170
1207
|
xDir
|
|
1171
1208
|
)
|
|
@@ -1180,14 +1217,15 @@ function createPillCylindricalFaces(repo, hole, boardThickness, xDir, zDir) {
|
|
|
1180
1217
|
rotation,
|
|
1181
1218
|
centerX,
|
|
1182
1219
|
centerY,
|
|
1183
|
-
|
|
1220
|
+
zMin,
|
|
1221
|
+
zMax,
|
|
1184
1222
|
zDir
|
|
1185
1223
|
)
|
|
1186
1224
|
);
|
|
1187
1225
|
}
|
|
1188
1226
|
return faces;
|
|
1189
1227
|
}
|
|
1190
|
-
function createCylindricalWall(repo, centerX, centerY, radius, startAngle, endAngle, rotation, centerX0, centerY0,
|
|
1228
|
+
function createCylindricalWall(repo, centerX, centerY, radius, startAngle, endAngle, rotation, centerX0, centerY0, zMin, zMax, zDir, xDir) {
|
|
1191
1229
|
const bottomStartX = centerX + radius * Math.cos(startAngle);
|
|
1192
1230
|
const bottomStartY = centerY + radius * Math.sin(startAngle);
|
|
1193
1231
|
const bottomEndX = centerX + radius * Math.cos(endAngle);
|
|
@@ -1209,29 +1247,25 @@ function createCylindricalWall(repo, centerX, centerY, radius, startAngle, endAn
|
|
|
1209
1247
|
const bottomStartVertex = repo.add(
|
|
1210
1248
|
new VertexPoint2(
|
|
1211
1249
|
"",
|
|
1212
|
-
repo.add(new CartesianPoint3("", bottomStart.x, bottomStart.y,
|
|
1250
|
+
repo.add(new CartesianPoint3("", bottomStart.x, bottomStart.y, zMin))
|
|
1213
1251
|
)
|
|
1214
1252
|
);
|
|
1215
1253
|
const bottomEndVertex = repo.add(
|
|
1216
1254
|
new VertexPoint2(
|
|
1217
1255
|
"",
|
|
1218
|
-
repo.add(new CartesianPoint3("", bottomEnd.x, bottomEnd.y,
|
|
1256
|
+
repo.add(new CartesianPoint3("", bottomEnd.x, bottomEnd.y, zMin))
|
|
1219
1257
|
)
|
|
1220
1258
|
);
|
|
1221
1259
|
const topStart = repo.add(
|
|
1222
1260
|
new VertexPoint2(
|
|
1223
1261
|
"",
|
|
1224
|
-
repo.add(
|
|
1225
|
-
new CartesianPoint3("", bottomStart.x, bottomStart.y, boardThickness)
|
|
1226
|
-
)
|
|
1262
|
+
repo.add(new CartesianPoint3("", bottomStart.x, bottomStart.y, zMax))
|
|
1227
1263
|
)
|
|
1228
1264
|
);
|
|
1229
1265
|
const topEnd = repo.add(
|
|
1230
1266
|
new VertexPoint2(
|
|
1231
1267
|
"",
|
|
1232
|
-
repo.add(
|
|
1233
|
-
new CartesianPoint3("", bottomEnd.x, bottomEnd.y, boardThickness)
|
|
1234
|
-
)
|
|
1268
|
+
repo.add(new CartesianPoint3("", bottomEnd.x, bottomEnd.y, zMax))
|
|
1235
1269
|
)
|
|
1236
1270
|
);
|
|
1237
1271
|
const centerRotated = rotatePoint(
|
|
@@ -1242,7 +1276,7 @@ function createCylindricalWall(repo, centerX, centerY, radius, startAngle, endAn
|
|
|
1242
1276
|
rotation
|
|
1243
1277
|
);
|
|
1244
1278
|
const bottomCenter = repo.add(
|
|
1245
|
-
new CartesianPoint3("", centerRotated.x, centerRotated.y,
|
|
1279
|
+
new CartesianPoint3("", centerRotated.x, centerRotated.y, zMin)
|
|
1246
1280
|
);
|
|
1247
1281
|
const bottomPlacement = repo.add(
|
|
1248
1282
|
new Axis2Placement3D2(
|
|
@@ -1257,7 +1291,7 @@ function createCylindricalWall(repo, centerX, centerY, radius, startAngle, endAn
|
|
|
1257
1291
|
new EdgeCurve2("", bottomStartVertex, bottomEndVertex, bottomCircle, false)
|
|
1258
1292
|
);
|
|
1259
1293
|
const topCenter = repo.add(
|
|
1260
|
-
new CartesianPoint3("", centerRotated.x, centerRotated.y,
|
|
1294
|
+
new CartesianPoint3("", centerRotated.x, centerRotated.y, zMax)
|
|
1261
1295
|
);
|
|
1262
1296
|
const topPlacement = repo.add(new Axis2Placement3D2("", topCenter, zDir, xDir));
|
|
1263
1297
|
const topCircle = repo.add(new Circle("", topPlacement, radius));
|
|
@@ -1265,37 +1299,34 @@ function createCylindricalWall(repo, centerX, centerY, radius, startAngle, endAn
|
|
|
1265
1299
|
const v1 = repo.add(
|
|
1266
1300
|
new VertexPoint2(
|
|
1267
1301
|
"",
|
|
1268
|
-
repo.add(new CartesianPoint3("", bottomStart.x, bottomStart.y,
|
|
1302
|
+
repo.add(new CartesianPoint3("", bottomStart.x, bottomStart.y, zMin))
|
|
1269
1303
|
)
|
|
1270
1304
|
);
|
|
1271
1305
|
const v2 = repo.add(
|
|
1272
1306
|
new VertexPoint2(
|
|
1273
1307
|
"",
|
|
1274
|
-
repo.add(
|
|
1275
|
-
new CartesianPoint3("", bottomStart.x, bottomStart.y, boardThickness)
|
|
1276
|
-
)
|
|
1308
|
+
repo.add(new CartesianPoint3("", bottomStart.x, bottomStart.y, zMax))
|
|
1277
1309
|
)
|
|
1278
1310
|
);
|
|
1279
1311
|
const v3 = repo.add(
|
|
1280
1312
|
new VertexPoint2(
|
|
1281
1313
|
"",
|
|
1282
|
-
repo.add(new CartesianPoint3("", bottomEnd.x, bottomEnd.y,
|
|
1314
|
+
repo.add(new CartesianPoint3("", bottomEnd.x, bottomEnd.y, zMin))
|
|
1283
1315
|
)
|
|
1284
1316
|
);
|
|
1285
1317
|
const v4 = repo.add(
|
|
1286
1318
|
new VertexPoint2(
|
|
1287
1319
|
"",
|
|
1288
|
-
repo.add(
|
|
1289
|
-
new CartesianPoint3("", bottomEnd.x, bottomEnd.y, boardThickness)
|
|
1290
|
-
)
|
|
1320
|
+
repo.add(new CartesianPoint3("", bottomEnd.x, bottomEnd.y, zMax))
|
|
1291
1321
|
)
|
|
1292
1322
|
);
|
|
1293
1323
|
const dir1 = repo.add(new Direction3("", 0, 0, 1));
|
|
1294
|
-
const
|
|
1324
|
+
const height = zMax - zMin;
|
|
1325
|
+
const vec1 = repo.add(new Vector2("", dir1, height));
|
|
1295
1326
|
const line1 = repo.add(new Line2("", v1.resolve(repo).pnt, vec1));
|
|
1296
1327
|
const edge1 = repo.add(new EdgeCurve2("", v1, v2, line1, true));
|
|
1297
1328
|
const dir2 = repo.add(new Direction3("", 0, 0, 1));
|
|
1298
|
-
const vec2 = repo.add(new Vector2("", dir2,
|
|
1329
|
+
const vec2 = repo.add(new Vector2("", dir2, height));
|
|
1299
1330
|
const line2 = repo.add(new Line2("", v3.resolve(repo).pnt, vec2));
|
|
1300
1331
|
const edge2 = repo.add(new EdgeCurve2("", v3, v4, line2, true));
|
|
1301
1332
|
const loop = repo.add(
|
|
@@ -1321,25 +1352,25 @@ function createCylindricalWall(repo, centerX, centerY, radius, startAngle, endAn
|
|
|
1321
1352
|
)
|
|
1322
1353
|
);
|
|
1323
1354
|
}
|
|
1324
|
-
function createPlanarWall(repo, startX, startY, endX, endY, rotation, centerX0, centerY0,
|
|
1355
|
+
function createPlanarWall(repo, startX, startY, endX, endY, rotation, centerX0, centerY0, zMin, zMax, zDir) {
|
|
1325
1356
|
const start = rotatePoint(startX, startY, centerX0, centerY0, rotation);
|
|
1326
1357
|
const end = rotatePoint(endX, endY, centerX0, centerY0, rotation);
|
|
1327
1358
|
const v1 = repo.add(
|
|
1328
|
-
new VertexPoint2(
|
|
1359
|
+
new VertexPoint2(
|
|
1360
|
+
"",
|
|
1361
|
+
repo.add(new CartesianPoint3("", start.x, start.y, zMin))
|
|
1362
|
+
)
|
|
1329
1363
|
);
|
|
1330
1364
|
const v2 = repo.add(
|
|
1331
|
-
new VertexPoint2("", repo.add(new CartesianPoint3("", end.x, end.y,
|
|
1365
|
+
new VertexPoint2("", repo.add(new CartesianPoint3("", end.x, end.y, zMin)))
|
|
1332
1366
|
);
|
|
1333
1367
|
const v3 = repo.add(
|
|
1334
|
-
new VertexPoint2(
|
|
1335
|
-
"",
|
|
1336
|
-
repo.add(new CartesianPoint3("", end.x, end.y, boardThickness))
|
|
1337
|
-
)
|
|
1368
|
+
new VertexPoint2("", repo.add(new CartesianPoint3("", end.x, end.y, zMax)))
|
|
1338
1369
|
);
|
|
1339
1370
|
const v4 = repo.add(
|
|
1340
1371
|
new VertexPoint2(
|
|
1341
1372
|
"",
|
|
1342
|
-
repo.add(new CartesianPoint3("", start.x, start.y,
|
|
1373
|
+
repo.add(new CartesianPoint3("", start.x, start.y, zMax))
|
|
1343
1374
|
)
|
|
1344
1375
|
);
|
|
1345
1376
|
const dx = end.x - start.x;
|
|
@@ -1358,10 +1389,11 @@ function createPlanarWall(repo, startX, startY, endX, endY, rotation, centerX0,
|
|
|
1358
1389
|
const topLine = repo.add(new Line2("", v4.resolve(repo).pnt, topVec));
|
|
1359
1390
|
const topEdge = repo.add(new EdgeCurve2("", v4, v3, topLine, true));
|
|
1360
1391
|
const vertDir = repo.add(new Direction3("", 0, 0, 1));
|
|
1361
|
-
const
|
|
1392
|
+
const height = zMax - zMin;
|
|
1393
|
+
const vertVec1 = repo.add(new Vector2("", vertDir, height));
|
|
1362
1394
|
const vertLine1 = repo.add(new Line2("", v2.resolve(repo).pnt, vertVec1));
|
|
1363
1395
|
const vertEdge1 = repo.add(new EdgeCurve2("", v2, v3, vertLine1, true));
|
|
1364
|
-
const vertVec2 = repo.add(new Vector2("", vertDir,
|
|
1396
|
+
const vertVec2 = repo.add(new Vector2("", vertDir, height));
|
|
1365
1397
|
const vertLine2 = repo.add(new Line2("", v1.resolve(repo).pnt, vertVec2));
|
|
1366
1398
|
const vertEdge2 = repo.add(new EdgeCurve2("", v1, v4, vertLine2, true));
|
|
1367
1399
|
const loop = repo.add(
|
|
@@ -1378,7 +1410,7 @@ function createPlanarWall(repo, startX, startY, endX, endY, rotation, centerX0,
|
|
|
1378
1410
|
const refDir = repo.add(
|
|
1379
1411
|
new Direction3("", dx / edgeLength, dy / edgeLength, 0)
|
|
1380
1412
|
);
|
|
1381
|
-
const planeOrigin = repo.add(new CartesianPoint3("", start.x, start.y,
|
|
1413
|
+
const planeOrigin = repo.add(new CartesianPoint3("", start.x, start.y, zMin));
|
|
1382
1414
|
const placement = repo.add(
|
|
1383
1415
|
new Axis2Placement3D2("", planeOrigin, normalDir, refDir)
|
|
1384
1416
|
);
|
|
@@ -1406,6 +1438,7 @@ async function circuitJsonToStep(circuitJson, options = {}) {
|
|
|
1406
1438
|
const productName = options.productName ?? "PCB";
|
|
1407
1439
|
const boardCenterX = pcbBoard?.center?.x ?? 0;
|
|
1408
1440
|
const boardCenterY = pcbBoard?.center?.y ?? 0;
|
|
1441
|
+
const halfBoardThickness = boardThickness / 2;
|
|
1409
1442
|
if (!boardWidth || !boardHeight) {
|
|
1410
1443
|
throw new Error(
|
|
1411
1444
|
"Board dimensions not found. Either provide boardWidth and boardHeight in options, or include a pcb_board in the circuit JSON with width and height properties."
|
|
@@ -1495,7 +1528,9 @@ async function circuitJsonToStep(circuitJson, options = {}) {
|
|
|
1495
1528
|
(point) => repo.add(
|
|
1496
1529
|
new VertexPoint3(
|
|
1497
1530
|
"",
|
|
1498
|
-
repo.add(
|
|
1531
|
+
repo.add(
|
|
1532
|
+
new CartesianPoint4("", point.x, point.y, -halfBoardThickness)
|
|
1533
|
+
)
|
|
1499
1534
|
)
|
|
1500
1535
|
)
|
|
1501
1536
|
);
|
|
@@ -1503,7 +1538,9 @@ async function circuitJsonToStep(circuitJson, options = {}) {
|
|
|
1503
1538
|
(point) => repo.add(
|
|
1504
1539
|
new VertexPoint3(
|
|
1505
1540
|
"",
|
|
1506
|
-
repo.add(
|
|
1541
|
+
repo.add(
|
|
1542
|
+
new CartesianPoint4("", point.x, point.y, halfBoardThickness)
|
|
1543
|
+
)
|
|
1507
1544
|
)
|
|
1508
1545
|
)
|
|
1509
1546
|
);
|
|
@@ -1511,14 +1548,30 @@ async function circuitJsonToStep(circuitJson, options = {}) {
|
|
|
1511
1548
|
const halfWidth = boardWidth / 2;
|
|
1512
1549
|
const halfHeight = boardHeight / 2;
|
|
1513
1550
|
const corners = [
|
|
1514
|
-
[
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
[
|
|
1520
|
-
|
|
1521
|
-
|
|
1551
|
+
[
|
|
1552
|
+
boardCenterX - halfWidth,
|
|
1553
|
+
boardCenterY - halfHeight,
|
|
1554
|
+
-halfBoardThickness
|
|
1555
|
+
],
|
|
1556
|
+
[
|
|
1557
|
+
boardCenterX + halfWidth,
|
|
1558
|
+
boardCenterY - halfHeight,
|
|
1559
|
+
-halfBoardThickness
|
|
1560
|
+
],
|
|
1561
|
+
[
|
|
1562
|
+
boardCenterX + halfWidth,
|
|
1563
|
+
boardCenterY + halfHeight,
|
|
1564
|
+
-halfBoardThickness
|
|
1565
|
+
],
|
|
1566
|
+
[
|
|
1567
|
+
boardCenterX - halfWidth,
|
|
1568
|
+
boardCenterY + halfHeight,
|
|
1569
|
+
-halfBoardThickness
|
|
1570
|
+
],
|
|
1571
|
+
[boardCenterX - halfWidth, boardCenterY - halfHeight, halfBoardThickness],
|
|
1572
|
+
[boardCenterX + halfWidth, boardCenterY - halfHeight, halfBoardThickness],
|
|
1573
|
+
[boardCenterX + halfWidth, boardCenterY + halfHeight, halfBoardThickness],
|
|
1574
|
+
[boardCenterX - halfWidth, boardCenterY + halfHeight, halfBoardThickness]
|
|
1522
1575
|
];
|
|
1523
1576
|
const vertices = corners.map(
|
|
1524
1577
|
([x, y, z]) => repo.add(
|
|
@@ -1528,7 +1581,7 @@ async function circuitJsonToStep(circuitJson, options = {}) {
|
|
|
1528
1581
|
bottomVertices = [vertices[0], vertices[1], vertices[2], vertices[3]];
|
|
1529
1582
|
topVertices = [vertices[4], vertices[5], vertices[6], vertices[7]];
|
|
1530
1583
|
}
|
|
1531
|
-
function
|
|
1584
|
+
function createEdge2(v1, v2) {
|
|
1532
1585
|
const p1 = v1.resolve(repo).pnt.resolve(repo);
|
|
1533
1586
|
const p2 = v2.resolve(repo).pnt.resolve(repo);
|
|
1534
1587
|
const dx = p2.x - p1.x;
|
|
@@ -1554,17 +1607,17 @@ async function circuitJsonToStep(circuitJson, options = {}) {
|
|
|
1554
1607
|
for (let i = 0; i < bottomVertices.length; i++) {
|
|
1555
1608
|
const v1 = bottomVertices[i];
|
|
1556
1609
|
const v2 = bottomVertices[(i + 1) % bottomVertices.length];
|
|
1557
|
-
bottomEdges.push(
|
|
1610
|
+
bottomEdges.push(createEdge2(v1, v2));
|
|
1558
1611
|
}
|
|
1559
1612
|
for (let i = 0; i < topVertices.length; i++) {
|
|
1560
1613
|
const v1 = topVertices[i];
|
|
1561
1614
|
const v2 = topVertices[(i + 1) % topVertices.length];
|
|
1562
|
-
topEdges.push(
|
|
1615
|
+
topEdges.push(createEdge2(v1, v2));
|
|
1563
1616
|
}
|
|
1564
1617
|
for (let i = 0; i < bottomVertices.length; i++) {
|
|
1565
|
-
verticalEdges.push(
|
|
1618
|
+
verticalEdges.push(createEdge2(bottomVertices[i], topVertices[i]));
|
|
1566
1619
|
}
|
|
1567
|
-
const origin = repo.add(new CartesianPoint4("", 0, 0,
|
|
1620
|
+
const origin = repo.add(new CartesianPoint4("", 0, 0, -halfBoardThickness));
|
|
1568
1621
|
const xDir = repo.add(new Direction4("", 1, 0, 0));
|
|
1569
1622
|
const zDir = repo.add(new Direction4("", 0, 0, 1));
|
|
1570
1623
|
const bottomFrame = repo.add(
|
|
@@ -1584,16 +1637,20 @@ async function circuitJsonToStep(circuitJson, options = {}) {
|
|
|
1584
1637
|
);
|
|
1585
1638
|
const bottomHoleLoops = [];
|
|
1586
1639
|
for (const hole of holes) {
|
|
1587
|
-
const holeShape = hole.hole_shape
|
|
1640
|
+
const holeShape = hole.hole_shape ?? hole.shape;
|
|
1588
1641
|
if (holeShape === "circle") {
|
|
1589
|
-
const holeX = typeof hole.x === "number" ? hole.x : hole.x
|
|
1590
|
-
const holeY = typeof hole.y === "number" ? hole.y : hole.y
|
|
1591
|
-
const radius = hole.hole_diameter / 2;
|
|
1592
|
-
const holeCenter = repo.add(
|
|
1642
|
+
const holeX = typeof hole.x === "number" ? hole.x : hole.x ?? 0;
|
|
1643
|
+
const holeY = typeof hole.y === "number" ? hole.y : hole.y ?? 0;
|
|
1644
|
+
const radius = (hole.hole_diameter ?? 0) / 2;
|
|
1645
|
+
const holeCenter = repo.add(
|
|
1646
|
+
new CartesianPoint4("", holeX, holeY, -halfBoardThickness)
|
|
1647
|
+
);
|
|
1593
1648
|
const holeVertex = repo.add(
|
|
1594
1649
|
new VertexPoint3(
|
|
1595
1650
|
"",
|
|
1596
|
-
repo.add(
|
|
1651
|
+
repo.add(
|
|
1652
|
+
new CartesianPoint4("", holeX + radius, holeY, -halfBoardThickness)
|
|
1653
|
+
)
|
|
1597
1654
|
)
|
|
1598
1655
|
);
|
|
1599
1656
|
const holePlacement = repo.add(
|
|
@@ -1613,22 +1670,19 @@ async function circuitJsonToStep(circuitJson, options = {}) {
|
|
|
1613
1670
|
);
|
|
1614
1671
|
bottomHoleLoops.push(repo.add(new FaceBound("", holeLoop, true)));
|
|
1615
1672
|
} else if (holeShape === "rotated_pill" || holeShape === "pill") {
|
|
1616
|
-
const pillLoop = createPillHoleLoop(repo, hole,
|
|
1673
|
+
const pillLoop = createPillHoleLoop(repo, hole, -halfBoardThickness, xDir);
|
|
1617
1674
|
bottomHoleLoops.push(repo.add(new FaceBound("", pillLoop, true)));
|
|
1618
1675
|
}
|
|
1619
1676
|
}
|
|
1620
1677
|
const bottomFace = repo.add(
|
|
1621
1678
|
new AdvancedFace3(
|
|
1622
1679
|
"",
|
|
1623
|
-
[
|
|
1624
|
-
repo.add(new FaceOuterBound3("", bottomLoop, true)),
|
|
1625
|
-
...bottomHoleLoops
|
|
1626
|
-
],
|
|
1680
|
+
[repo.add(new FaceOuterBound3("", bottomLoop, true)), ...bottomHoleLoops],
|
|
1627
1681
|
bottomPlane,
|
|
1628
1682
|
true
|
|
1629
1683
|
)
|
|
1630
1684
|
);
|
|
1631
|
-
const topOrigin = repo.add(new CartesianPoint4("", 0, 0,
|
|
1685
|
+
const topOrigin = repo.add(new CartesianPoint4("", 0, 0, halfBoardThickness));
|
|
1632
1686
|
const topFrame = repo.add(new Axis2Placement3D3("", topOrigin, zDir, xDir));
|
|
1633
1687
|
const topPlane = repo.add(new Plane3("", topFrame));
|
|
1634
1688
|
const topLoop = repo.add(
|
|
@@ -1639,19 +1693,19 @@ async function circuitJsonToStep(circuitJson, options = {}) {
|
|
|
1639
1693
|
);
|
|
1640
1694
|
const topHoleLoops = [];
|
|
1641
1695
|
for (const hole of holes) {
|
|
1642
|
-
const holeShape = hole.hole_shape
|
|
1696
|
+
const holeShape = hole.hole_shape ?? hole.shape;
|
|
1643
1697
|
if (holeShape === "circle") {
|
|
1644
|
-
const holeX = typeof hole.x === "number" ? hole.x : hole.x
|
|
1645
|
-
const holeY = typeof hole.y === "number" ? hole.y : hole.y
|
|
1646
|
-
const radius = hole.hole_diameter / 2;
|
|
1698
|
+
const holeX = typeof hole.x === "number" ? hole.x : hole.x ?? 0;
|
|
1699
|
+
const holeY = typeof hole.y === "number" ? hole.y : hole.y ?? 0;
|
|
1700
|
+
const radius = (hole.hole_diameter ?? 0) / 2;
|
|
1647
1701
|
const holeCenter = repo.add(
|
|
1648
|
-
new CartesianPoint4("", holeX, holeY,
|
|
1702
|
+
new CartesianPoint4("", holeX, holeY, halfBoardThickness)
|
|
1649
1703
|
);
|
|
1650
1704
|
const holeVertex = repo.add(
|
|
1651
1705
|
new VertexPoint3(
|
|
1652
1706
|
"",
|
|
1653
1707
|
repo.add(
|
|
1654
|
-
new CartesianPoint4("", holeX + radius, holeY,
|
|
1708
|
+
new CartesianPoint4("", holeX + radius, holeY, halfBoardThickness)
|
|
1655
1709
|
)
|
|
1656
1710
|
)
|
|
1657
1711
|
);
|
|
@@ -1667,7 +1721,7 @@ async function circuitJsonToStep(circuitJson, options = {}) {
|
|
|
1667
1721
|
);
|
|
1668
1722
|
topHoleLoops.push(repo.add(new FaceBound("", holeLoop, true)));
|
|
1669
1723
|
} else if (holeShape === "rotated_pill" || holeShape === "pill") {
|
|
1670
|
-
const pillLoop = createPillHoleLoop(repo, hole,
|
|
1724
|
+
const pillLoop = createPillHoleLoop(repo, hole, halfBoardThickness, xDir);
|
|
1671
1725
|
topHoleLoops.push(repo.add(new FaceBound("", pillLoop, true)));
|
|
1672
1726
|
}
|
|
1673
1727
|
}
|
|
@@ -1689,7 +1743,7 @@ async function circuitJsonToStep(circuitJson, options = {}) {
|
|
|
1689
1743
|
const edgeDir = {
|
|
1690
1744
|
x: bottomV2.x - bottomV1.x,
|
|
1691
1745
|
y: bottomV2.y - bottomV1.y,
|
|
1692
|
-
z:
|
|
1746
|
+
z: -halfBoardThickness
|
|
1693
1747
|
};
|
|
1694
1748
|
const normalDir = repo.add(new Direction4("", edgeDir.y, -edgeDir.x, 0));
|
|
1695
1749
|
const refDir = repo.add(new Direction4("", edgeDir.x, edgeDir.y, 0));
|
|
@@ -1717,16 +1771,20 @@ async function circuitJsonToStep(circuitJson, options = {}) {
|
|
|
1717
1771
|
}
|
|
1718
1772
|
const holeCylindricalFaces = [];
|
|
1719
1773
|
for (const hole of holes) {
|
|
1720
|
-
const holeShape = hole.hole_shape
|
|
1774
|
+
const holeShape = hole.hole_shape ?? hole.shape;
|
|
1721
1775
|
if (holeShape === "circle") {
|
|
1722
|
-
const holeX = typeof hole.x === "number" ? hole.x : hole.x
|
|
1723
|
-
const holeY = typeof hole.y === "number" ? hole.y : hole.y
|
|
1724
|
-
const radius = hole.hole_diameter / 2;
|
|
1725
|
-
const bottomHoleCenter = repo.add(
|
|
1776
|
+
const holeX = typeof hole.x === "number" ? hole.x : hole.x ?? 0;
|
|
1777
|
+
const holeY = typeof hole.y === "number" ? hole.y : hole.y ?? 0;
|
|
1778
|
+
const radius = (hole.hole_diameter ?? 0) / 2;
|
|
1779
|
+
const bottomHoleCenter = repo.add(
|
|
1780
|
+
new CartesianPoint4("", holeX, holeY, -halfBoardThickness)
|
|
1781
|
+
);
|
|
1726
1782
|
const bottomHoleVertex = repo.add(
|
|
1727
1783
|
new VertexPoint3(
|
|
1728
1784
|
"",
|
|
1729
|
-
repo.add(
|
|
1785
|
+
repo.add(
|
|
1786
|
+
new CartesianPoint4("", holeX + radius, holeY, -halfBoardThickness)
|
|
1787
|
+
)
|
|
1730
1788
|
)
|
|
1731
1789
|
);
|
|
1732
1790
|
const bottomHolePlacement = repo.add(
|
|
@@ -1750,13 +1808,13 @@ async function circuitJsonToStep(circuitJson, options = {}) {
|
|
|
1750
1808
|
)
|
|
1751
1809
|
);
|
|
1752
1810
|
const topHoleCenter = repo.add(
|
|
1753
|
-
new CartesianPoint4("", holeX, holeY,
|
|
1811
|
+
new CartesianPoint4("", holeX, holeY, halfBoardThickness)
|
|
1754
1812
|
);
|
|
1755
1813
|
const topHoleVertex = repo.add(
|
|
1756
1814
|
new VertexPoint3(
|
|
1757
1815
|
"",
|
|
1758
1816
|
repo.add(
|
|
1759
|
-
new CartesianPoint4("", holeX + radius, holeY,
|
|
1817
|
+
new CartesianPoint4("", holeX + radius, holeY, halfBoardThickness)
|
|
1760
1818
|
)
|
|
1761
1819
|
)
|
|
1762
1820
|
);
|
|
@@ -1792,7 +1850,8 @@ async function circuitJsonToStep(circuitJson, options = {}) {
|
|
|
1792
1850
|
const pillFaces = createPillCylindricalFaces(
|
|
1793
1851
|
repo,
|
|
1794
1852
|
hole,
|
|
1795
|
-
|
|
1853
|
+
-halfBoardThickness,
|
|
1854
|
+
halfBoardThickness,
|
|
1796
1855
|
xDir,
|
|
1797
1856
|
zDir
|
|
1798
1857
|
);
|
|
@@ -1800,9 +1859,17 @@ async function circuitJsonToStep(circuitJson, options = {}) {
|
|
|
1800
1859
|
}
|
|
1801
1860
|
}
|
|
1802
1861
|
const allFaces = [bottomFace, topFace, ...sideFaces, ...holeCylindricalFaces];
|
|
1862
|
+
const styleCache = createStyleCache();
|
|
1863
|
+
const boardStyledItems = createStyledItems(repo, {
|
|
1864
|
+
itemRefs: allFaces,
|
|
1865
|
+
rgb: [0.2, 0.6, 0.2],
|
|
1866
|
+
styleCache
|
|
1867
|
+
});
|
|
1803
1868
|
const shell = repo.add(new ClosedShell2("", allFaces));
|
|
1804
|
-
const solid = repo.add(new
|
|
1869
|
+
const solid = repo.add(new ManifoldSolidBrep4(productName, shell));
|
|
1805
1870
|
const allSolids = [solid];
|
|
1871
|
+
const componentStyledItems = [];
|
|
1872
|
+
const solidsWithIntrinsicFaceStyles = /* @__PURE__ */ new Set();
|
|
1806
1873
|
let handledComponentIds = /* @__PURE__ */ new Set();
|
|
1807
1874
|
let handledPcbComponentIds = /* @__PURE__ */ new Set();
|
|
1808
1875
|
if (options.includeComponents && options.includeExternalMeshes) {
|
|
@@ -1815,6 +1882,9 @@ async function circuitJsonToStep(circuitJson, options = {}) {
|
|
|
1815
1882
|
handledComponentIds = mergeResult.handledComponentIds;
|
|
1816
1883
|
handledPcbComponentIds = mergeResult.handledPcbComponentIds;
|
|
1817
1884
|
allSolids.push(...mergeResult.solids);
|
|
1885
|
+
mergeResult.solids.forEach((solidRef) => {
|
|
1886
|
+
solidsWithIntrinsicFaceStyles.add(String(solidRef.id));
|
|
1887
|
+
});
|
|
1818
1888
|
}
|
|
1819
1889
|
if (options.includeComponents) {
|
|
1820
1890
|
const pcbComponentIdsWithStepUrl = /* @__PURE__ */ new Set();
|
|
@@ -1854,21 +1924,39 @@ async function circuitJsonToStep(circuitJson, options = {}) {
|
|
|
1854
1924
|
excludePcbComponentIds: handledPcbComponentIds,
|
|
1855
1925
|
pcbComponentIdsWithStepUrl
|
|
1856
1926
|
});
|
|
1857
|
-
|
|
1927
|
+
for (const componentSolid of componentSolids) {
|
|
1928
|
+
allSolids.push(componentSolid.solid);
|
|
1929
|
+
componentStyledItems.push(...componentSolid.styledItems);
|
|
1930
|
+
if (componentSolid.usesIntrinsicFaceStyles) {
|
|
1931
|
+
solidsWithIntrinsicFaceStyles.add(String(componentSolid.solid.id));
|
|
1932
|
+
} else if (componentSolid.styleTargets.length > 0) {
|
|
1933
|
+
componentStyledItems.push(
|
|
1934
|
+
...createStyledItems(repo, {
|
|
1935
|
+
itemRefs: componentSolid.styleTargets,
|
|
1936
|
+
rgb: [0.75, 0.75, 0.75],
|
|
1937
|
+
styleCache
|
|
1938
|
+
})
|
|
1939
|
+
);
|
|
1940
|
+
solidsWithIntrinsicFaceStyles.add(String(componentSolid.solid.id));
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1858
1943
|
}
|
|
1859
1944
|
}
|
|
1860
|
-
const styledItems = [
|
|
1861
|
-
|
|
1945
|
+
const styledItems = [
|
|
1946
|
+
...boardStyledItems,
|
|
1947
|
+
...componentStyledItems
|
|
1948
|
+
];
|
|
1949
|
+
allSolids.forEach((itemRef, index) => {
|
|
1862
1950
|
const isBoard = index === 0;
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
const
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1951
|
+
if (isBoard || solidsWithIntrinsicFaceStyles.has(String(itemRef.id))) {
|
|
1952
|
+
return;
|
|
1953
|
+
}
|
|
1954
|
+
const styledItem = createStyledItem(repo, {
|
|
1955
|
+
itemRef,
|
|
1956
|
+
rgb: [0.75, 0.75, 0.75],
|
|
1957
|
+
styleCache,
|
|
1958
|
+
name: ""
|
|
1959
|
+
});
|
|
1872
1960
|
styledItems.push(styledItem);
|
|
1873
1961
|
});
|
|
1874
1962
|
repo.add(
|