@constructorfleet/sketchforge-engine 1.26.0 → 1.27.0

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.
Files changed (48) hide show
  1. package/dist/cadAnalysis.d.ts +94 -0
  2. package/dist/cadAnalysis.d.ts.map +1 -0
  3. package/dist/cadAnalysis.js +143 -0
  4. package/dist/cadAnalysis.js.map +1 -0
  5. package/dist/cadShell.d.ts +143 -0
  6. package/dist/cadShell.d.ts.map +1 -0
  7. package/dist/cadShell.js +306 -0
  8. package/dist/cadShell.js.map +1 -0
  9. package/dist/domain/sketchforge.d.ts +1 -1
  10. package/dist/domain/sketchforge.d.ts.map +1 -1
  11. package/dist/engine.d.ts.map +1 -1
  12. package/dist/engine.js +57 -15
  13. package/dist/engine.js.map +1 -1
  14. package/dist/parametricRecompute.d.ts.map +1 -1
  15. package/dist/parametricRecompute.js +7 -4
  16. package/dist/parametricRecompute.js.map +1 -1
  17. package/dist/revolveRequests.d.ts.map +1 -1
  18. package/dist/serverCadInterference.d.ts +8 -45
  19. package/dist/serverCadInterference.d.ts.map +1 -1
  20. package/dist/serverCadInterference.js +13 -42
  21. package/dist/serverCadInterference.js.map +1 -1
  22. package/dist/serverCadOperations.d.ts.map +1 -1
  23. package/dist/serverCadOperations.js +76 -25
  24. package/dist/serverCadOperations.js.map +1 -1
  25. package/dist/serverCadShell.d.ts +7 -94
  26. package/dist/serverCadShell.d.ts.map +1 -1
  27. package/dist/serverCadShell.js +25 -269
  28. package/dist/serverCadShell.js.map +1 -1
  29. package/dist/serverCadThickness.d.ts +8 -8
  30. package/dist/serverCadThickness.d.ts.map +1 -1
  31. package/dist/serverCadThickness.js +15 -42
  32. package/dist/serverCadThickness.js.map +1 -1
  33. package/dist/serverStepExplode.d.ts +1 -2
  34. package/dist/serverStepExplode.d.ts.map +1 -1
  35. package/dist/serverStepExplode.js +15 -148
  36. package/dist/serverStepExplode.js.map +1 -1
  37. package/dist/sketchFaceDraftKernel.d.ts +5 -5
  38. package/dist/sketchFaceDraftKernel.d.ts.map +1 -1
  39. package/dist/sketchFaceDraftKernel.js +11 -9
  40. package/dist/sketchFaceDraftKernel.js.map +1 -1
  41. package/dist/stepAssemblyExplode.d.ts +45 -0
  42. package/dist/stepAssemblyExplode.d.ts.map +1 -0
  43. package/dist/stepAssemblyExplode.js +195 -0
  44. package/dist/stepAssemblyExplode.js.map +1 -0
  45. package/dist/support/cadModifierTypes.d.ts +59 -0
  46. package/dist/support/cadModifierTypes.d.ts.map +1 -1
  47. package/dist/support/i18n/locales/en/messages.json +13 -1
  48. package/package.json +1 -1
@@ -1,142 +1,31 @@
1
1
  /**
2
2
  * Hollowing a solid on the server, with a wall of a given thickness.
3
3
  *
4
- * This is the operation a 3D print needs most and the editor has never had: a
5
- * solid box weighs 8 grams of filament and a 2 mm-walled one weighs two, and a
6
- * box with its top face left open is a tray. OCCT does it with
7
- * `BRepOffsetAPI_MakeThickSolid`, which the bundled kernel exposes as `shell`.
4
+ * This is the operation a 3D print needs most: a solid box weighs 8 grams of
5
+ * filament and a 2 mm-walled one weighs two, and a box with its top face left
6
+ * open is a tray. The hollowing itself is `cadShell.ts`, which the editor's
7
+ * CAD worker shares; this module is the Node side of it.
8
8
  *
9
9
  * Node-only, and built on the same footing as the fillet endpoint: the shape is
10
10
  * rebuilt as true geometry rather than meshed, and the result is stored with
11
11
  * its exact BREP alongside the triangles, so a hollowed part still exports to
12
12
  * STEP and can still be filleted afterwards.
13
- *
14
- * Two things about `shell` are worth knowing before changing any of this, both
15
- * found by measuring rather than by reading:
16
- *
17
- * - With no faces removed it does not hollow anything. It returns the *inner*
18
- * solid -- the original offset inwards by the thickness -- so a sealed
19
- * hollow has to be the original cut by that, which is what `hollowedSolid`
20
- * does. Asking it to hollow a closed solid directly gives you back a
21
- * smaller solid part, which looks plausible and is not what was asked for.
22
- * - A thickness that does not fit does not reliably fail. Past half the
23
- * part it variously returns an empty compound, a solid that reports
24
- * `isValid: false` with a correct bounding box, or the original solid
25
- * untouched with every extent and the validity flag intact. Only the volume
26
- * tells those apart from a real answer, which is why `hollowedSolid`
27
- * measures it rather than trusting the call to throw.
28
13
  */
29
14
  import { withCadKernel } from "./serverCadKernel.js";
30
15
  import { exactPlainSketchRevolveSolid, isPlainFullTurnSketchRevolve, meshedCadResult, orientedSolidForShape, ServerCadError } from "./serverCadOperations.js";
31
- /**
32
- * The precision OCCT reconstructs the thick solid at.
33
- *
34
- * `1e-6` is the kernel's own recommendation for a precise shell and matches
35
- * what brepjs uses; the looser `1e-3` survives more inputs but produces
36
- * different topology, which would make a shelled part disagree with the same
37
- * part shelled in the editor's worker later.
38
- */
39
- const SHELL_TOLERANCE = 1e-6;
40
- /** How closely a face's normal must line up with an axis to be named for it. */
41
- const AXIS_TOLERANCE = 1e-3;
42
- /**
43
- * Names for the faces a request is likely to want open, by where they point.
44
- *
45
- * A caller that knows the geometry can name face indexes from the listing, but
46
- * nobody wants to list a box's faces to find out which one is the lid. The
47
- * local frame these resolve in is the one every geometry builder here produces:
48
- * centred in X and Z, base at Y=0, +Z towards the viewer.
49
- */
50
- const FACE_DIRECTIONS = {
51
- top: { x: 0, y: 1, z: 0 },
52
- bottom: { x: 0, y: -1, z: 0 },
53
- right: { x: 1, y: 0, z: 0 },
54
- left: { x: -1, y: 0, z: 0 },
55
- front: { x: 0, y: 0, z: 1 },
56
- back: { x: 0, y: 0, z: -1 },
57
- };
58
- export const FACE_DIRECTION_NAMES = Object.keys(FACE_DIRECTIONS);
59
- /**
60
- * The normal pointing out of the solid at the middle of a face.
61
- *
62
- * Exported because the measurement endpoint needs the same normal to answer
63
- * "what is the angle between these two faces", and a second copy of this would
64
- * be free to drift from the one the face listing and the shell request agree on.
65
- */
66
- export function faceOutwardNormal(cad, face) {
67
- try {
68
- const bounds = cad.uvBounds(face);
69
- // `surfaceNormal` already accounts for the face's own orientation, so a
70
- // reversed face reports the normal pointing out of the solid rather than
71
- // the surface's natural one. Verified against a box's six faces and
72
- // against the inner faces of a hollow, where the two disagree.
73
- const normal = cad.surfaceNormal(face, (bounds.uMin + bounds.uMax) / 2, (bounds.vMin + bounds.vMax) / 2);
74
- if (![normal.x, normal.y, normal.z].every(Number.isFinite))
75
- return null;
76
- return normal;
77
- }
78
- catch {
79
- return null;
80
- }
81
- }
82
- function axisOf(normal) {
83
- if (!normal)
84
- return null;
85
- for (const name of FACE_DIRECTION_NAMES) {
86
- const direction = FACE_DIRECTIONS[name];
87
- const dot = normal.x * direction.x + normal.y * direction.y + normal.z * direction.z;
88
- if (dot > 1 - AXIS_TOLERANCE)
89
- return name;
90
- }
91
- return null;
92
- }
93
- /** How far out along its own direction a face sits, which is what settles a tie. */
94
- function reachAlong(centroid, direction) {
95
- return centroid.x * direction.x + centroid.y * direction.y + centroid.z * direction.z;
96
- }
16
+ import { CadShellError, describeShellFaces, shellSolid } from "./cadShell.js";
17
+ export { FACE_DIRECTION_NAMES, faceOutwardNormal } from "./cadShell.js";
97
18
  function faceSummaries(cad, solid, shape, preferStoredIds = true) {
98
- const faces = cad.getSubShapes(solid, "face");
99
- const storedIds = preferStoredIds && shape.faceIds?.length === faces.length ? shape.faceIds : undefined;
100
- const described = faces.map((handle, index) => {
101
- const normal = faceOutwardNormal(cad, handle);
102
- let surfaceType = "unknown";
103
- try {
104
- surfaceType = cad.surfaceType(handle);
105
- }
106
- catch {
107
- // Not every surface reports a type; the area and centroid still do.
108
- }
109
- const centroid = cad.getSurfaceCenterOfMass(handle);
110
- return {
111
- index,
112
- id: storedIds?.[index] ?? `face_${encodeURIComponent(shape.id)}_${index}`,
113
- surfaceType,
114
- area: cad.getSurfaceArea(handle),
115
- centroid: { x: centroid.x, y: centroid.y, z: centroid.z },
116
- normal: normal ? { x: normal.x, y: normal.y, z: normal.z } : null,
117
- // A flat face is the only kind a direction name can mean: "the top" of a
118
- // sphere is a point on a curved surface, not a lid you can take off.
119
- axis: surfaceType === "plane" ? axisOf(normal) : null,
120
- };
121
- });
122
- // Several faces can point the same way -- the lid of a hollow box and the
123
- // floor of its cavity both point up -- so a name belongs to the outermost of
124
- // them. Without this, opening "top" on an already-hollow part would pick the
125
- // cavity floor and quietly produce nonsense.
126
- const furthest = new Map();
127
- for (const face of described) {
128
- if (!face.axis)
129
- continue;
130
- const reach = reachAlong(face.centroid, FACE_DIRECTIONS[face.axis]);
131
- const best = furthest.get(face.axis);
132
- if (best === undefined || reach > best)
133
- furthest.set(face.axis, reach);
134
- }
135
- return described.map(({ axis, ...face }) => ({
136
- ...face,
137
- facing: axis && Math.abs(reachAlong(face.centroid, FACE_DIRECTIONS[axis]) - (furthest.get(axis) ?? 0)) < AXIS_TOLERANCE
138
- ? axis
139
- : null,
19
+ const described = describeShellFaces(cad, solid);
20
+ const storedIds = preferStoredIds && shape.faceIds?.length === described.length ? shape.faceIds : undefined;
21
+ return described.map((face) => ({
22
+ index: face.index,
23
+ id: storedIds?.[face.index] ?? `face_${encodeURIComponent(shape.id)}_${face.index}`,
24
+ surfaceType: face.surfaceType,
25
+ area: face.area,
26
+ centroid: face.centroid,
27
+ normal: face.normal,
28
+ facing: face.facing,
140
29
  }));
141
30
  }
142
31
  /** A shape's faces, numbered as a shell request refers to them by index. */
@@ -152,143 +41,8 @@ export function shapeFaces(shape, options = {}) {
152
41
  return faceSummaries(cad, orientedSolidForShape(cad, shape), shape);
153
42
  });
154
43
  }
155
- /**
156
- * The face indexes a request's `openFaces` names, in listing order.
157
- *
158
- * Mixed on purpose: `["top"]` is what a script asking for a tray wants to write,
159
- * and an index from the listing is the only way to name a face that no direction
160
- * describes -- one wall of a hexagonal pot, say.
161
- */
162
- function resolveOpenFaces(requested, faces) {
163
- const chosen = new Set();
164
- for (const entry of requested) {
165
- if (typeof entry === "number") {
166
- if (!Number.isInteger(entry) || entry < 0 || entry >= faces.length) {
167
- throw new ServerCadError(`Face indexes must be between 0 and ${faces.length - 1}.`, 400);
168
- }
169
- chosen.add(entry);
170
- continue;
171
- }
172
- const name = entry.trim().toLowerCase();
173
- if (!FACE_DIRECTION_NAMES.includes(name)) {
174
- throw new ServerCadError(`"${entry}" is not a face direction. Use one of ${FACE_DIRECTION_NAMES.join(", ")}, or a face index from the face listing.`, 400);
175
- }
176
- const matched = faces.filter((face) => face.facing === name);
177
- if (matched.length === 0) {
178
- throw new ServerCadError(`This shape has no flat ${name} face to open. Name a face index from the face listing instead.`, 422);
179
- }
180
- for (const face of matched)
181
- chosen.add(face.index);
182
- }
183
- return [...chosen].sort((left, right) => left - right);
184
- }
185
- /** The single solid inside whatever OCCT handed back, or the shape itself. */
186
- function soleSolid(cad, result) {
187
- const solids = cad.getSubShapes(result, "solid");
188
- return solids.length === 1 ? solids[0] : result;
189
- }
190
- function volumeOf(cad, shape) {
191
- try {
192
- const volume = cad.getVolume(shape);
193
- return Number.isFinite(volume) ? volume : null;
194
- }
195
- catch {
196
- return null;
197
- }
198
- }
199
- const TOO_THICK = "That wall thickness is too large for this shape: hollowing it at that thickness leaves no cavity. Try a thinner wall.";
200
- /**
201
- * What OCCT refusing outright actually means, as far as it can be told apart.
202
- *
203
- * A thickness that merely does not fit does not throw: it comes back as an
204
- * empty compound, a solid that fails its own validity check, or the original
205
- * untouched, all of which `hollowedSolid` catches by measuring. A throw is the
206
- * other failure, and it tracks the *kind of surface* rather than the number.
207
- *
208
- * It is not "curved": an analytic sphere, cylinder, cone and torus all offset
209
- * perfectly well. What fails is a **spline** skin -- OCCT will not offset one
210
- * inwards at any thickness or at any reconstruction tolerance (checked at 1e-6,
211
- * 1e-4, 1e-3 and 1e-2). In this app that is an elliptical ball, a loft, and
212
- * anything built by extruding a profile wire, because those surfaces are
213
- * splines however round they look.
214
- */
215
- const CANNOT_OFFSET = "OCCT could not hollow this shape: its surfaces cannot be offset inwards into a sound solid. A shape whose skin is a spline rather than an analytic surface -- a ball with unequal radii, a loft -- fails this way at any wall thickness, however round it looks.";
216
44
  /** What a result OCCT built but cannot write out means, which is nothing good. */
217
45
  const UNREADABLE = "The hollowed solid came out of OCCT in a state it cannot read back, so it has not been stored. Try a different wall thickness.";
218
- /** Whether a handle is a solid OCCT itself will vouch for. */
219
- function isSoundSolid(cad, shape) {
220
- try {
221
- return cad.isSolid(shape) && Boolean(cad.isValid(shape));
222
- }
223
- catch {
224
- // An empty compound throws from `isValid` rather than reporting false.
225
- return false;
226
- }
227
- }
228
- /**
229
- * The hollowed solid, or a refusal.
230
- *
231
- * Both paths run through OCCT's thick-solid builder, which answers two
232
- * different questions depending on whether any face is removed -- see the
233
- * module note. The checks around it are not belt and braces: every one of them
234
- * has a real input that reaches it, and the order matters, because it is what
235
- * separates a wall that does not fit from a shape that cannot be hollowed at
236
- * all. The inward offset is measured before it is cut away, so a thickness
237
- * that collapses it is reported as a thickness rather than blamed on the
238
- * shape's surfaces.
239
- */
240
- function hollowedSolid(cad, solid, thickness, openFaces) {
241
- const sourceVolume = volumeOf(cad, solid);
242
- if (sourceVolume === null || sourceVolume <= 0) {
243
- throw new ServerCadError("That shape has no volume to hollow out.");
244
- }
245
- let hollow;
246
- if (openFaces.length > 0) {
247
- const faces = cad.getSubShapes(solid, "face");
248
- try {
249
- hollow = cad.shell(solid, openFaces.map((index) => faces[index]), thickness, SHELL_TOLERANCE);
250
- }
251
- catch {
252
- throw new ServerCadError(CANNOT_OFFSET);
253
- }
254
- }
255
- else {
256
- // No face removed: `shell` returns the inward offset solid rather than a
257
- // hollow, so the sealed void is the original cut by it.
258
- let inner;
259
- try {
260
- inner = cad.shell(solid, [], thickness, SHELL_TOLERANCE);
261
- }
262
- catch {
263
- throw new ServerCadError(CANNOT_OFFSET);
264
- }
265
- // The cavity, before it is a cavity. Past half the part this is an empty
266
- // compound, and cutting the solid by it throws -- which would otherwise
267
- // read as the shape's fault rather than the thickness's.
268
- const innerVolume = volumeOf(cad, inner);
269
- if (!isSoundSolid(cad, inner) || innerVolume === null || innerVolume <= 0 || innerVolume >= sourceVolume) {
270
- throw new ServerCadError(TOO_THICK);
271
- }
272
- try {
273
- hollow = cad.cut(solid, inner);
274
- }
275
- catch {
276
- throw new ServerCadError(CANNOT_OFFSET);
277
- }
278
- }
279
- const result = soleSolid(cad, hollow);
280
- if (!isSoundSolid(cad, result))
281
- throw new ServerCadError(TOO_THICK);
282
- const volume = volumeOf(cad, result);
283
- if (volume === null || volume <= 0)
284
- throw new ServerCadError(TOO_THICK);
285
- // Past the thickness that fits, OCCT hands back the original solid with
286
- // every extent and the validity flag intact. Hollowing always removes the
287
- // cavity, so a result that weighs what it started at did nothing.
288
- if (volume >= sourceVolume * (1 - 1e-6))
289
- throw new ServerCadError(TOO_THICK);
290
- return result;
291
- }
292
46
  /**
293
47
  * Hollow a shape out and return the exact result with a mesh of it.
294
48
  *
@@ -301,14 +55,16 @@ export function applyShell(shape, request) {
301
55
  }
302
56
  return withCadKernel((cad) => {
303
57
  const solid = orientedSolidForShape(cad, shape);
304
- const faces = faceSummaries(cad, solid, shape);
305
- if (faces.length === 0)
306
- throw new ServerCadError("That shape has no faces to hollow out.");
307
- const openFaces = resolveOpenFaces(request.openFaces ?? [], faces);
308
- if (openFaces.length === faces.length) {
309
- throw new ServerCadError("Leaving every face open would remove the shape rather than hollow it. Leave at least one face closed.");
58
+ let hollow;
59
+ try {
60
+ hollow = shellSolid(cad, solid, request).solid;
61
+ }
62
+ catch (error) {
63
+ // The same refusal, said the way the REST API says it.
64
+ if (error instanceof CadShellError)
65
+ throw new ServerCadError(error.message, error.status);
66
+ throw error;
310
67
  }
311
- const hollow = hollowedSolid(cad, solid, request.thickness, openFaces);
312
68
  try {
313
69
  return meshedCadResult(cad, hollow, shape);
314
70
  }
@@ -1 +1 @@
1
- {"version":3,"file":"serverCadShell.js","sourceRoot":"","sources":["../src/serverCadShell.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"serverCadShell.js","sourceRoot":"","sources":["../src/serverCadShell.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,4BAA4B,EAAE,4BAA4B,EAAE,eAAe,EAAE,qBAAqB,EAAE,cAAc,EAAwB,MAAM,0BAA0B,CAAC;AACpL,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,UAAU,EAAqB,MAAM,eAAe,CAAC;AAGjG,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAsB,MAAM,eAAe,CAAC;AAc5F,SAAS,aAAa,CAAC,GAAe,EAAE,KAAkB,EAAE,KAAqB,EAAE,eAAe,GAAG,IAAI;IACvG,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACjD,MAAM,SAAS,GAAG,eAAe,IAAI,KAAK,CAAC,OAAO,EAAE,MAAM,KAAK,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5G,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC9B,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,EAAE,EAAE,SAAS,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,QAAQ,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE;QACnF,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAC,CAAC;AACN,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,UAAU,CAAC,KAAqB,EAAE,UAAkC,EAAE;IACpF,OAAO,aAAa,CAAC,CAAC,GAAG,EAAE,EAAE;QAC3B,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,4BAA4B,CAAC,KAAK,CAAC,EAAE,CAAC;YACxE,IAAI,KAAK,CAAC,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjE,MAAM,IAAI,cAAc,CAAC,gFAAgF,CAAC,CAAC;YAC7G,CAAC;YACD,MAAM,KAAK,GAAG,4BAA4B,CAAC,GAAG,EAAE,KAAK,CAAC,aAAc,EAAE,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;YAClG,OAAO,aAAa,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,aAAa,CAAC,GAAG,EAAE,qBAAqB,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,GACd,gIAAgI,CAAC;AAEnI;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,KAAqB,EAAE,OAA8B;IAC9E,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,SAAS,IAAI,CAAC,EAAE,CAAC;QAClE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,+CAA+C,EAAE,GAAG,CAAC,CAAC,CAAC;IAClG,CAAC;IAED,OAAO,aAAa,CAAC,CAAC,GAAG,EAAE,EAAE;QAC3B,MAAM,KAAK,GAAG,qBAAqB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAChD,IAAI,MAAmB,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC;QACjD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,uDAAuD;YACvD,IAAI,KAAK,YAAY,aAAa;gBAAE,MAAM,IAAI,cAAc,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YAC1F,MAAM,KAAK,CAAC;QACd,CAAC;QACD,IAAI,CAAC;YACH,OAAO,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QAC7C,CAAC;QAAC,MAAM,CAAC;YACP,sEAAsE;YACtE,uEAAuE;YACvE,sEAAsE;YACtE,MAAM,IAAI,cAAc,CAAC,UAAU,CAAC,CAAC;QACvC,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -1,12 +1,12 @@
1
- /** Sampled wall-thickness analysis for exact project solids. Node-only. */
1
+ /**
2
+ * Sampled wall-thickness analysis for exact project solids. Node-only.
3
+ *
4
+ * The sampling lives in `cadAnalysis`, which the editor's CAD worker shares;
5
+ * this places the stored shape and runs it on the server's kernel.
6
+ */
7
+ import { type WallThicknessResult } from "./cadAnalysis.js";
2
8
  import type { WorkplaneShape } from "./domain/sketchforge.js";
3
- export type WallThicknessResult = {
4
- minimum: number | null;
5
- unit: "mm";
6
- method: "sampled-opposing-surface-distance";
7
- samplesPerFace: number;
8
- facesChecked: number;
9
- };
9
+ export type { WallThicknessResult } from "./cadAnalysis.js";
10
10
  /**
11
11
  * Return the smallest sampled distance between opposing faces. This is a
12
12
  * screening estimate, not a medial-axis or certified minimum-thickness result.
@@ -1 +1 @@
1
- {"version":3,"file":"serverCadThickness.d.ts","sourceRoot":"","sources":["../src/serverCadThickness.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAM3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAK9D,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,mCAAmC,CAAC;IAC5C,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAeF;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAuBjF"}
1
+ {"version":3,"file":"serverCadThickness.d.ts","sourceRoot":"","sources":["../src/serverCadThickness.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAA8C,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACxG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAE9D,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE5D;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC,CASjF"}
@@ -1,54 +1,27 @@
1
- /** Sampled wall-thickness analysis for exact project solids. Node-only. */
1
+ /**
2
+ * Sampled wall-thickness analysis for exact project solids. Node-only.
3
+ *
4
+ * The sampling lives in `cadAnalysis`, which the editor's CAD worker shares;
5
+ * this places the stored shape and runs it on the server's kernel.
6
+ */
2
7
  import { withCadKernel } from "./serverCadKernel.js";
3
8
  import { ServerCadError } from "./serverCadOperations.js";
4
9
  import { placedSolidForShape } from "./serverShapeBooleans.js";
5
- const MAX_FACES = 256;
6
- const GRID = 5;
7
- function samples(cad, face) {
8
- const uv = cad.uvBounds(face);
9
- const points = [];
10
- for (let i = 0; i < GRID; i += 1)
11
- for (let j = 0; j < GRID; j += 1) {
12
- const u = uv.uMin + (uv.uMax - uv.uMin) * (i + 0.5) / GRID;
13
- const v = uv.vMin + (uv.vMax - uv.vMin) * (j + 0.5) / GRID;
14
- if (cad.classifyPointOnFace(face, u, v) !== "out") {
15
- points.push({ point: cad.pointOnSurface(face, u, v), normal: cad.surfaceNormal(face, u, v) });
16
- }
17
- }
18
- return points;
19
- }
10
+ import { sampledWallThickness, WallThicknessRefusal } from "./cadAnalysis.js";
20
11
  /**
21
12
  * Return the smallest sampled distance between opposing faces. This is a
22
13
  * screening estimate, not a medial-axis or certified minimum-thickness result.
23
14
  */
24
15
  export function wallThickness(shape) {
25
16
  return withCadKernel((cad) => {
26
- const solid = placedSolidForShape(cad, shape);
27
- const faces = cad.getSubShapes(solid, "face");
28
- if (!faces.length)
29
- throw new ServerCadError("The shape has no faces to analyze.");
30
- if (faces.length > MAX_FACES)
31
- throw new ServerCadError(`Wall-thickness analysis supports at most ${MAX_FACES} faces.`, 413);
32
- const sampled = faces.map((face) => samples(cad, face));
33
- let minimum = Infinity;
34
- for (let i = 0; i < faces.length; i += 1)
35
- for (let j = i + 1; j < faces.length; j += 1) {
36
- for (const source of sampled[i]) {
37
- for (const target of sampled[j]) {
38
- const dot = source.normal.x * target.normal.x + source.normal.y * target.normal.y + source.normal.z * target.normal.z;
39
- if (dot > -0.5)
40
- continue;
41
- const uv = cad.uvFromPoint(faces[j], source.point);
42
- if (cad.classifyPointOnFace(faces[j], uv.u, uv.v) === "out")
43
- continue;
44
- const projected = cad.pointOnSurface(faces[j], uv.u, uv.v);
45
- const distance = Math.hypot(source.point.x - projected.x, source.point.y - projected.y, source.point.z - projected.z);
46
- if (distance > 1e-7 && distance < minimum)
47
- minimum = distance;
48
- }
49
- }
50
- }
51
- return { minimum: Number.isFinite(minimum) ? minimum : null, unit: "mm", method: "sampled-opposing-surface-distance", samplesPerFace: GRID * GRID, facesChecked: faces.length };
17
+ try {
18
+ return sampledWallThickness(cad, placedSolidForShape(cad, shape));
19
+ }
20
+ catch (error) {
21
+ if (error instanceof WallThicknessRefusal)
22
+ throw new ServerCadError(error.message, error.reason === "too_many_faces" ? 413 : 422);
23
+ throw error;
24
+ }
52
25
  });
53
26
  }
54
27
  //# sourceMappingURL=serverCadThickness.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"serverCadThickness.js","sourceRoot":"","sources":["../src/serverCadThickness.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"serverCadThickness.js","sourceRoot":"","sources":["../src/serverCadThickness.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAA4B,MAAM,kBAAkB,CAAC;AAKxG;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAqB;IACjD,OAAO,aAAa,CAAC,CAAC,GAAG,EAAE,EAAE;QAC3B,IAAI,CAAC;YACH,OAAO,oBAAoB,CAAC,GAAG,EAAE,mBAAmB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;QACpE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,oBAAoB;gBAAE,MAAM,IAAI,cAAc,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,KAAK,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAClI,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -1,7 +1,6 @@
1
1
  /** Split a retained STEP source into positioned, independently editable solids. Node-only. */
2
2
  import type { ProjectAsset, WorkplaneShape } from "./domain/sketchforge.js";
3
- export declare const MAX_EXPLODE_SOLIDS = 200;
4
- export declare const MAX_EXPLODE_SOURCE_BYTES: number;
3
+ export { MAX_EXPLODE_SOLIDS, MAX_EXPLODE_SOURCE_BYTES } from "./stepAssemblyExplode.js";
5
4
  /** Turn a STEP-imported mesh shape into one exact mesh/B-rep-backed shape per solid. */
6
5
  export declare function explodeStepAssembly(shape: WorkplaneShape, source: ProjectAsset): Promise<WorkplaneShape[]>;
7
6
  //# sourceMappingURL=serverStepExplode.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"serverStepExplode.d.ts","sourceRoot":"","sources":["../src/serverStepExplode.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAS9F,OAAO,KAAK,EAAE,YAAY,EAA0C,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGpH,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,eAAO,MAAM,wBAAwB,QAAkB,CAAC;AAgExD,wFAAwF;AACxF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CA4F1G"}
1
+ {"version":3,"file":"serverStepExplode.d.ts","sourceRoot":"","sources":["../src/serverStepExplode.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAK9F,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAE5E,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAMxF,wFAAwF;AACxF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAc1G"}