partforge 0.131.0 → 0.132.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 +9 -9
- package/docs/ERROR-PATTERNS.md +2 -2
- package/docs/KERNEL-CONTRACT.md +2 -3
- package/package.json +1 -1
- package/src/framework/geometry/polygon.js +17 -8
- package/src/framework/geometry/profile-warnings.js +1 -1
- package/src/parts/bracket.js +4 -5
- package/types/geometry.d.ts +5 -5
package/docs/AUTHORING-PARTS.md
CHANGED
|
@@ -1501,7 +1501,8 @@ in STEP. Use these for every round outline that shows or fits:
|
|
|
1501
1501
|
ring is a region with a hole: extrude `{ outer, holes }` or cut an inner cylinder from an outer
|
|
1502
1502
|
one), `pieProfile(tipR,arcDeg)` (a sector from the origin), `slotProfile(length,r)` (overall
|
|
1503
1503
|
length = `length + 2r`; `length` 0 is a circle), `roundedRectProfile(w,h,r)` (r clamped to
|
|
1504
|
-
min(w,h)/2), `
|
|
1504
|
+
min(w,h)/2), `circleProfile(r, center?)` (a circle), `roundedProfile(points,r)` (round any
|
|
1505
|
+
polygon's corners), and `pathProfile()`.
|
|
1505
1506
|
|
|
1506
1507
|
*Straight edges* — CCW point arrays, built and exported exactly as written:
|
|
1507
1508
|
`regularPolygon(n,r,{flat})`, `hexPolygon(r)`, `starPolygon(points,outerR,innerR)`,
|
|
@@ -1509,14 +1510,13 @@ min(w,h)/2), `roundedProfile(points,r)` (round any polygon's corners), and `path
|
|
|
1509
1510
|
`circlePolygon(r, center?, segs = 48)` — a circle as a fixed point list, for a deliberately
|
|
1510
1511
|
faceted circle or point math of your own (mapping, indexing, spreading its points).
|
|
1511
1512
|
|
|
1512
|
-
*Circles.* `circleProfile(r, center?)` is
|
|
1513
|
-
outline or hole, `k.shape2d`, `revolve`, `hull`,
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
torus** — the primitive keeps real TORUS faces in STEP.
|
|
1513
|
+
*Circles.* `circleProfile(r, center?)` is an exact circle, like the other `*Profile` helpers:
|
|
1514
|
+
hand it to any op — `prism`, an `extrude` outline or hole, `k.shape2d`, `revolve`, `hull`,
|
|
1515
|
+
`loft`, `sweep` (sweep and `offsetPolygon` sample it at 48 points). It is a path contour, not
|
|
1516
|
+
an array, so for point math of your own use `circlePolygon`. (Before partforge 0.132 it
|
|
1517
|
+
returned `circlePolygon`'s points; it takes no `segs`.) For a round SOLID use `k.cylinder`,
|
|
1518
|
+
and **use `k.torus({ rMajor, rMinor })` for a torus** — the primitive keeps real TORUS faces
|
|
1519
|
+
in STEP.
|
|
1520
1520
|
|
|
1521
1521
|
**Patterns** (return `Solid[]` — feed to `k.union(...)` for features or `s.cutAll(...)` for holes):
|
|
1522
1522
|
`linearPattern(solid, count, [dx,dy,dz])`, `circularPattern(solid, count, { center, axis, angle, rotateCopies })`.
|
package/docs/ERROR-PATTERNS.md
CHANGED
|
@@ -826,8 +826,8 @@ between the Manifold preview and the OCCT STEP export.
|
|
|
826
826
|
## profile-sampled-arc
|
|
827
827
|
|
|
828
828
|
- **Symptom:** The build succeeds and its result carries a warning like `prism: profile traces an arc in straight facets (radius ≈ 30.0 mm, 9.0° per facet, up to 0.09 mm inside the true curve) — a point list is built and exported exactly as written, so a print shows those facets. …` (also `extrude: profile …`, `revolve: profile …`, `shape2d: profile …`). A printed part with that outline shows flat spots, and a fit built on it (a bayonet lug in its track, a pin in a slot) binds or rattles. Identical text on both backends.
|
|
829
|
-
- **Cause:** *(partforge ≥ 0.131.)* A point list is built and exported exactly as written: only curves the kernel knows about — primitives, a revolve's sweep, and the arcs of a path contour or `Shape2D` — are faceted per quality tier and refined at export. An arc sampled into a point list keeps the facets it was sampled with, however fine the export. The round `*Polygon` helpers sample at 32 per circle (`ringSectorPolygon`, `slotPolygon`, `piePolygon`, and `roundedRectPolygon`'s corners), `filletPolygon` at 8 segments per corner whatever its angle, `circlePolygon` (and
|
|
830
|
-
- **Fix:** Rebuild the outline from exact curves: `ringSectorProfile`, `slotProfile`, `pieProfile` and `
|
|
829
|
+
- **Cause:** *(partforge ≥ 0.131.)* A point list is built and exported exactly as written: only curves the kernel knows about — primitives, a revolve's sweep, and the arcs of a path contour or `Shape2D` — are faceted per quality tier and refined at export. An arc sampled into a point list keeps the facets it was sampled with, however fine the export. The round `*Polygon` helpers sample at 32 per circle (`ringSectorPolygon`, `slotPolygon`, `piePolygon`, and `roundedRectPolygon`'s corners), `filletPolygon` at 8 segments per corner whatever its angle, `circlePolygon` at 48 (and `circleProfile`, before partforge 0.132), and a hand-written `Math.cos` loop at whatever it was given. The kernel reports the worst run in a profile: three or more facets turning by the same amount, at most 20° each, whose chord sits more than 0.05 mm inside the true arc. The end facets of a run may be shorter (an offset trims them), and coordinates may carry about 0.01 mm of rounding. Hexagons and other deliberate polygons, small holes, and finely sampled loops stay quiet, as does an arc of only two facets, which can't be told from a bend. It checks the outlines the author hands to `prism`, `extrude`, `revolve` and `k.shape2d`, including a bevelled `extrude`'s. It doesn't check what the kernel samples itself (a bevel's rim, a `screwSweep`'s section, a `hull`), or `loft` and `sweep`, which sample curve rings at their own fixed detail. At most three lines are reported per build.
|
|
830
|
+
- **Fix:** Rebuild the outline from exact curves: `ringSectorProfile`, `slotProfile`, `pieProfile`, `roundedRectProfile` and `circleProfile` trace the same outlines as their `*Polygon` namesakes, `roundedProfile` rounds any polygon's corners, and `pathProfile(start).arcTo(to, via)` builds anything else — all are path contours the kernel facets per tier and refines at export (and OCCT keeps as true circles in STEP). There is no export-resolution setting to raise instead. For an exact circle use `circleProfile`; for a round solid, `k.cylinder`. Sampling more points by hand only moves the facets, and it keeps them frozen.
|
|
831
831
|
|
|
832
832
|
## export-kernel-out-of-memory
|
|
833
833
|
|
package/docs/KERNEL-CONTRACT.md
CHANGED
|
@@ -722,9 +722,8 @@ case appears; add its deterministic fixture and establish the source-domain trut
|
|
|
722
722
|
`roundedRectProfile`, `circlePolygon`) are pure functions from numbers to plain CCW point
|
|
723
723
|
lists or arc profiles — *data already in this contract's input format*, with no kernel
|
|
724
724
|
dependency at all. The naming rule: `*Profile` builders return path contours with symbolic
|
|
725
|
-
arcs, `*Polygon` builders return point lists. `circleProfile`
|
|
726
|
-
|
|
727
|
-
that do point math on it have been migrated to `circlePolygon`. The **solid patterns** (`linearPattern`, `circularPattern`) take a
|
|
725
|
+
arcs, `*Polygon` builders return point lists. (`circleProfile` returned `circlePolygon`'s 48
|
|
726
|
+
points until 0.132.) The **solid patterns** (`linearPattern`, `circularPattern`) take a
|
|
728
727
|
`Solid` and call only ops from the tables above (`clone`/`translate`/`rotate`/
|
|
729
728
|
`boundingBox`). The **profile transform** (`offsetPolygon`) takes a point list or
|
|
730
729
|
`{outer, holes}` region and grows or shrinks it by a delta in mm — printer-clearance
|
package/package.json
CHANGED
|
@@ -412,15 +412,24 @@ export function circlePolygon(r, center = [0, 0], segs = 48) {
|
|
|
412
412
|
return pts;
|
|
413
413
|
}
|
|
414
414
|
|
|
415
|
-
//
|
|
416
|
-
//
|
|
417
|
-
//
|
|
418
|
-
//
|
|
419
|
-
//
|
|
420
|
-
//
|
|
421
|
-
|
|
415
|
+
// An exact circle of radius r centred at [cx, cy]: a path contour of two three-point
|
|
416
|
+
// semicircles, starting at angle 0 like circlePolygon's points. The kernel facets it per
|
|
417
|
+
// quality tier (finer at export) and OCCT keeps a true CIRCLE; sweep and offsetPolygon,
|
|
418
|
+
// which take point lists, sample it at 48 per circle (contourToPoints) — the density it
|
|
419
|
+
// had as a point list. Until partforge 0.132 this returned circlePolygon's 48 points;
|
|
420
|
+
// stored parts that did point math on it were migrated to circlePolygon first. A third
|
|
421
|
+
// `segs` argument belonged to the point list, so it is refused by name rather than
|
|
422
|
+
// silently ignored.
|
|
423
|
+
export function circleProfile(r, center = [0, 0], ...rest) {
|
|
422
424
|
if (!(r > 0)) throw new Error("circleProfile: r must be > 0");
|
|
423
|
-
|
|
425
|
+
if (rest.length > 0 && rest[0] !== undefined)
|
|
426
|
+
throw new Error("circleProfile: an exact circle takes no segs — use circlePolygon(r, center, segs) for a faceted circle");
|
|
427
|
+
const [cx, cy] = center;
|
|
428
|
+
const start = [cx + r, cy];
|
|
429
|
+
return contourFrom(start)
|
|
430
|
+
.arc([cx - r, cy], [cx, cy + r])
|
|
431
|
+
.arc([cx + r, cy], [cx, cy - r])
|
|
432
|
+
.close();
|
|
424
433
|
}
|
|
425
434
|
|
|
426
435
|
// --- offsetPolygon ---------------------------------------------------------
|
|
@@ -100,7 +100,7 @@ const NOISE_MM = 0.01;
|
|
|
100
100
|
const SAMPLED_ARC_COACH =
|
|
101
101
|
"a point list is built and exported exactly as written, so a print shows those facets. " +
|
|
102
102
|
"Build curves with the *Profile helpers (ringSectorProfile, slotProfile, pieProfile, " +
|
|
103
|
-
"roundedRectProfile, roundedProfile) or pathProfile().arcTo(…) — the kernel facets those, finer at export.";
|
|
103
|
+
"roundedRectProfile, circleProfile, roundedProfile) or pathProfile().arcTo(…) — the kernel facets those, finer at export.";
|
|
104
104
|
|
|
105
105
|
// The worst sampled-arc run in one closed point ring, or null.
|
|
106
106
|
// → { r, stepDeg, sag } for the run with the largest chord sagitta.
|
package/src/parts/bracket.js
CHANGED
|
@@ -4,11 +4,10 @@
|
|
|
4
4
|
// • cutAll — four corner bolt holes drilled in one batch
|
|
5
5
|
// • cut — a central bore
|
|
6
6
|
// • offset — an optional print-clearance grow with rounded corners
|
|
7
|
-
// The rounded corners
|
|
8
|
-
//
|
|
9
|
-
// circleProfile's fixed 48-gon, within 0.05 mm of round at this size.
|
|
7
|
+
// The rounded corners, the clip disc and the holes are exact arcs (*Profile helpers), so
|
|
8
|
+
// the whole outline stays curve-exact and the kernel refines it at export.
|
|
10
9
|
// Open /bracket.html after `npm run dev`.
|
|
11
|
-
import { roundedRectProfile,
|
|
10
|
+
import { roundedRectProfile, circleProfile } from "partforge/geometry";
|
|
12
11
|
|
|
13
12
|
export default {
|
|
14
13
|
meta: { title: "Cross bracket", units: "mm", background: 0x15181d, environment: "workshop" },
|
|
@@ -65,7 +64,7 @@ export default {
|
|
|
65
64
|
const barH = k.shape2d(roundedRectProfile(p.span, p.bar, p.corner));
|
|
66
65
|
const barV = k.shape2d(roundedRectProfile(p.bar, p.span, p.corner));
|
|
67
66
|
let plate = barH.union(barV); // union
|
|
68
|
-
if (p.clip) plate = plate.intersect(k.shape2d(
|
|
67
|
+
if (p.clip) plate = plate.intersect(k.shape2d(circleProfile(p.span / 2))); // intersect
|
|
69
68
|
const d = p.span / 2 - p.inset;
|
|
70
69
|
const holes = [[d, d], [-d, d], [d, -d], [-d, -d]].map((c) => circleProfile(p.hole_d / 2, c));
|
|
71
70
|
plate = plate.cutAll(holes); // batch cut
|
package/types/geometry.d.ts
CHANGED
|
@@ -71,12 +71,12 @@ export function ringSectorPolygon(innerR: number, outerR: number, arcDeg: number
|
|
|
71
71
|
export function circlePolygon(r: number, center?: Point2, segs?: number): PointsContour;
|
|
72
72
|
|
|
73
73
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
74
|
+
* An exact circle of radius `r` centred at `center`: a path contour of two semicircles
|
|
75
|
+
* starting at angle 0, which the kernel facets per tier (finer at export) and OCCT keeps as
|
|
76
|
+
* a true circle. Not an array — use `circlePolygon` for point math. (Until 0.132 this
|
|
77
|
+
* returned `circlePolygon`'s 48 points; it takes no `segs`.)
|
|
78
78
|
*/
|
|
79
|
-
export function circleProfile(r: number, center?: Point2
|
|
79
|
+
export function circleProfile(r: number, center?: Point2): ArcContour;
|
|
80
80
|
|
|
81
81
|
/**
|
|
82
82
|
* Per-corner rounding geometry shared by `filletPolygon` and `roundedProfile`:
|