partforge 0.98.0 → 0.99.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.
- package/docs/AUTHORING-PARTS.md +25 -0
- package/docs/ERROR-PATTERNS.md +6 -0
- package/package.json +1 -1
package/docs/AUTHORING-PARTS.md
CHANGED
|
@@ -523,6 +523,26 @@ magic vectors. Three habits:
|
|
|
523
523
|
body.cutAll([a, b, c]) // and k.union([base, f1, f2]) for additive batches
|
|
524
524
|
```
|
|
525
525
|
|
|
526
|
+
- **Size cut tools so no two of them land on exactly the same surface.** Booleans are
|
|
527
|
+
cheap right up until two operands share a coincident face, at which point OCCT has to
|
|
528
|
+
classify a surface belonging to both and the search degenerates — seconds become
|
|
529
|
+
minutes, with no error and no warning. Manifold's mesh CSG is unaffected, so the trap
|
|
530
|
+
is invisible until a STEP export (the one format pinned to OCCT) or an OCCT-routed
|
|
531
|
+
build. The classic is a threaded cap: a bore sized straight off the thread's root
|
|
532
|
+
diameter puts the bore wall and the thread root on the same cylinder.
|
|
533
|
+
|
|
534
|
+
```js
|
|
535
|
+
// ✗ the bore wall lands exactly on the thread root
|
|
536
|
+
const boreD = threadRootD;
|
|
537
|
+
cap.cutAll([k.cylinder({ d: boreD, h }), thread]);
|
|
538
|
+
// ✓ a deliberate gap, far below a printable layer
|
|
539
|
+
const boreD = threadRootD - 2 * 0.05;
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
The same applies to a cut that stops exactly flush with a face — overshoot it instead,
|
|
543
|
+
which is why cut tools throughout this guide carry `+ 0.4` / `- 0.2` slop. See
|
|
544
|
+
[boolean-coincident-faces-hang](ERROR-PATTERNS.md#boolean-coincident-faces-hang).
|
|
545
|
+
|
|
526
546
|
The bare `rotate(deg, center, axis)` remains available as the low-level primitive for
|
|
527
547
|
anything `rotateX/Y/Z`/`rotateAbout` can't express, but prefer the vocabulary above.
|
|
528
548
|
|
|
@@ -3350,6 +3370,11 @@ symptom first** — it maps error text → cause → fix. The invariants, one li
|
|
|
3350
3370
|
- **Keep geometry backend-agnostic** (kernel calls only); only STEP requires OCCT
|
|
3351
3371
|
([probe-routed-to-occt](ERROR-PATTERNS.md#probe-routed-to-occt),
|
|
3352
3372
|
[occt-holes-watertight-na](ERROR-PATTERNS.md#occt-holes-watertight-na)).
|
|
3373
|
+
- **Never let two cut tools share an exactly coincident face** — a bore whose radius
|
|
3374
|
+
equals a thread's root radius, a cut ending flush with a face. Give them 0.05-0.1 mm
|
|
3375
|
+
of deliberate clearance, or overshoot the cut. Mesh CSG shrugs; OCCT's boolean
|
|
3376
|
+
degenerates, so the part previews instantly and the STEP export runs for minutes
|
|
3377
|
+
([boolean-coincident-faces-hang](ERROR-PATTERNS.md#boolean-coincident-faces-hang)).
|
|
3353
3378
|
|
|
3354
3379
|
---
|
|
3355
3380
|
|
package/docs/ERROR-PATTERNS.md
CHANGED
|
@@ -61,6 +61,12 @@ The framework itself rebuilds each sub-part fresh per job and applies `place` on
|
|
|
61
61
|
- **Cause:** OCCT fillet/chamfer cost scales with the number of selected edges, and an `inPlane` rim selector on a many-point extruded profile selects every polygon edge (hundreds for a gear), so one op call costs seconds — and re-runs on every parameter change while that path is active.
|
|
62
62
|
- **Fix:** Use `extrude`'s `bevel` option instead of `chamfer` — same geometry, stays on the fast Manifold backend. See [AUTHORING-PARTS.md](AUTHORING-PARTS.md) § "Beveling profile rims: extrude's bevel option".
|
|
63
63
|
|
|
64
|
+
## boolean-coincident-faces-hang
|
|
65
|
+
|
|
66
|
+
- **Symptom:** A part previews instantly but a STEP export (or any OCCT-path build) of one sub-part runs for minutes and never finishes, with no error, no warning, and no progress. Cutting each tool on its own is fast; only the combination hangs. Threaded parts are the usual victims.
|
|
67
|
+
- **Cause:** Two cut tools in the same `cutAll` (or a tool and the body) share an *exactly* coincident face — most often a bore whose radius equals a thread's root radius, so the bore wall and the thread root lie on the same cylinder. OCCT's boolean has to classify a surface that is simultaneously on both operands, and the intersection search degenerates. Manifold's mesh CSG does not care, which is why the preview is fine and only the exact kernel suffers. Measured on one real part: bore alone 0.4 s, thread alone 5.4 s, both together did not finish in fifteen minutes; moving the bore 0.05 mm brought the pair to 12.6 s.
|
|
68
|
+
- **Fix:** Give the surfaces a deliberate clearance instead of letting them land on the same number. Derive one from the other with an explicit gap — `const boreD = threadRootD - 2 * boreClearance;` with `boreClearance` around 0.05-0.1 mm — rather than reusing the same expression for both. The gap is far below a printable layer, so the fit is unchanged. The same rule covers a cut that ends exactly flush with a face (overshoot it by a few tenths, as the surrounding examples do with `+ 0.4` / `- 0.2`) and two tools that abut exactly end-to-end.
|
|
69
|
+
|
|
64
70
|
## chamfer-rescue-bisection
|
|
65
71
|
|
|
66
72
|
- **Symptom:** `partforge: chamfer` warning saying the distance `over-ran the geometry — reduced to` a smaller one (or `has no valid distance`), with an attempt count and elapsed seconds, alongside slow builds.
|
package/package.json
CHANGED