partforge 0.109.1 → 0.111.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/bin/cli.js +22 -3
- package/docs/AUTHORING-PARTS.md +68 -12
- package/docs/ERROR-PATTERNS.md +19 -0
- package/docs/KERNEL-CONTRACT.md +40 -2
- package/package.json +1 -1
- package/src/framework/geometry/boolean-gate.js +200 -0
- package/src/framework/geometry/errors.js +11 -0
- package/src/framework/geometry/manifold-backend.js +46 -7
- package/src/framework/geometry/occt-backend.js +91 -17
- package/src/framework/lint/rules-verify.js +17 -1
- package/src/framework/oracle/dfm-profiles.js +45 -5
- package/src/framework/oracle/gates.js +10 -1
- package/src/framework/oracle/measure.js +27 -1
- package/src/framework/oracle/overhang.js +111 -0
- package/src/framework/oracle/verify.js +73 -8
- package/src/framework/verify-metrics.js +8 -0
- package/src/oracle.js +1 -0
- package/types/oracle.d.ts +1 -1
- package/types/part.d.ts +20 -0
- package/types/testing.d.ts +46 -4
package/types/oracle.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export {
|
|
|
12
12
|
type MeasureReport, type SubPartFacts, type AggregateFacts, type BuiltSubPart,
|
|
13
13
|
type VerifyReport, type VerifyCaseResult, type VerifyCheck, type CheckStatus,
|
|
14
14
|
// mesh facts, gaps, BVH, min wall
|
|
15
|
-
meshVolume, bboxSize, bounds, meshArea, assemblyGaps, meshGaps, buildBVH, meshTriangles, minWall,
|
|
15
|
+
meshVolume, bboxSize, bounds, meshArea, assemblyGaps, meshGaps, buildBVH, meshTriangles, minWall, overhang,
|
|
16
16
|
type Gap, type BVH,
|
|
17
17
|
// mesh file parsers (the import pipeline's own readers)
|
|
18
18
|
parseStl, parse3MF,
|
package/types/part.d.ts
CHANGED
|
@@ -408,6 +408,13 @@ export interface DfmProfile {
|
|
|
408
408
|
bed?: [number, number, number];
|
|
409
409
|
/** Minimum wall in mm — a warning, never a gate. */
|
|
410
410
|
minWall?: number;
|
|
411
|
+
/**
|
|
412
|
+
* Steepest unsupported face the process prints cleanly, in degrees from
|
|
413
|
+
* vertical (45 on the FDM profiles; absent on resin). Checked only for a part
|
|
414
|
+
* that also declares `verify.orientation: "print"`; `null` switches it off
|
|
415
|
+
* under a named base. A warning, never a gate.
|
|
416
|
+
*/
|
|
417
|
+
overhang?: number | null;
|
|
411
418
|
/** Carried for a future gap check; not enforced yet. */
|
|
412
419
|
clearance?: number;
|
|
413
420
|
/** Inherit from a named profile and override the rest. */
|
|
@@ -441,6 +448,12 @@ export interface SubPartExpectations {
|
|
|
441
448
|
boundsMin?: Expectation;
|
|
442
449
|
boundsMax?: Expectation;
|
|
443
450
|
minWall?: Expectation;
|
|
451
|
+
/**
|
|
452
|
+
* Unsupported downward-facing surface in mm² (faces steeper than the profile's
|
|
453
|
+
* `overhang` angle, bed at the sub-part's own lowest Z). Measured only under
|
|
454
|
+
* `verify.orientation: "print"`; a warning, never a gate.
|
|
455
|
+
*/
|
|
456
|
+
overhangArea?: Expectation;
|
|
444
457
|
/** Symmetric-difference volume vs. the sub-part's declared `reference` import. */
|
|
445
458
|
refXorVolume?: Expectation;
|
|
446
459
|
/** Percent volume delta vs. the sub-part's declared `reference` import. */
|
|
@@ -476,6 +489,13 @@ export interface ExpectMap {
|
|
|
476
489
|
export interface VerifyBlock<P = ResolvedParams, D = Derived> {
|
|
477
490
|
/** A named DFM profile or an inline one. */
|
|
478
491
|
process?: DfmProfileName | DfmProfile;
|
|
492
|
+
/**
|
|
493
|
+
* `"print"` declares the part is laid out for its bed — Z up, each sub-part's
|
|
494
|
+
* bed at its own lowest Z — which is the only way the profile's `overhang`
|
|
495
|
+
* check is armed. Omit it while a part is still being shaped or is bound for
|
|
496
|
+
* another process.
|
|
497
|
+
*/
|
|
498
|
+
orientation?: "print";
|
|
479
499
|
/** Which cases to check; default is `"defaults"` plus every preset name. */
|
|
480
500
|
cases?: string[];
|
|
481
501
|
/**
|
package/types/testing.d.ts
CHANGED
|
@@ -250,6 +250,17 @@ export function minWall(
|
|
|
250
250
|
totalTriangles: number;
|
|
251
251
|
} | null;
|
|
252
252
|
|
|
253
|
+
/**
|
|
254
|
+
* Unsupported downward-facing surface (oracle/overhang.js): the mm² of faces
|
|
255
|
+
* steeper than `maxAngle` from vertical, excluding the footprint on the bed
|
|
256
|
+
* (`bedZ`, else the mesh's lowest Z) and a near-bed band. One pass, no index;
|
|
257
|
+
* `null` only for an empty mesh. Bridges and bore ceilings count.
|
|
258
|
+
*/
|
|
259
|
+
export function overhang(
|
|
260
|
+
mesh: Mesh,
|
|
261
|
+
opts?: { maxAngle?: number; bedZ?: number; bedEps?: number; bedBand?: number },
|
|
262
|
+
): { area: number; worstAngle: number | null; at: Point3 | null } | null;
|
|
263
|
+
|
|
253
264
|
// --- measure ----------------------------------------------------------------
|
|
254
265
|
|
|
255
266
|
export interface SubPartFacts {
|
|
@@ -272,6 +283,16 @@ export interface SubPartFacts {
|
|
|
272
283
|
minWallAt: number[] | null;
|
|
273
284
|
minWallSampled: boolean;
|
|
274
285
|
minWallSamples: { sampled: number; total: number } | null;
|
|
286
|
+
/**
|
|
287
|
+
* Unsupported downward-facing area in mm² (oracle/overhang.js), `null` when the
|
|
288
|
+
* part is not laid out for a bed (`verify.orientation: "print"` under a
|
|
289
|
+
* profile with an `overhang` angle). Bridges and bore ceilings count.
|
|
290
|
+
*/
|
|
291
|
+
overhangArea: number | null;
|
|
292
|
+
/** Steepest offending face, degrees from vertical; `null` when none. */
|
|
293
|
+
overhangAngle: number | null;
|
|
294
|
+
/** Centroid of the largest offending face; `null` when none. */
|
|
295
|
+
overhangAt: number[] | null;
|
|
275
296
|
}
|
|
276
297
|
|
|
277
298
|
export interface AggregateFacts {
|
|
@@ -289,6 +310,8 @@ export interface MeasureReport {
|
|
|
289
310
|
view: string;
|
|
290
311
|
/** Whether this run cast min-wall rays at all. */
|
|
291
312
|
measuredMinWall: boolean;
|
|
313
|
+
/** The overhang angle every sub-part's `overhangArea` was measured against, `null` when the pass did not run. */
|
|
314
|
+
measuredOverhang: number | null;
|
|
292
315
|
subparts: SubPartFacts[];
|
|
293
316
|
aggregate: AggregateFacts;
|
|
294
317
|
overlaps: Overlap[];
|
|
@@ -308,6 +331,12 @@ export function measure(
|
|
|
308
331
|
params?: ResolvedParams,
|
|
309
332
|
opts?: {
|
|
310
333
|
minWall?: boolean;
|
|
334
|
+
/**
|
|
335
|
+
* The overhang angle to measure against (degrees from vertical), or `null`
|
|
336
|
+
* for "not checked". Omitted, measure derives it from the part's own
|
|
337
|
+
* `verify` block the way verify does.
|
|
338
|
+
*/
|
|
339
|
+
overhang?: number | null;
|
|
311
340
|
gapThreshold?: number;
|
|
312
341
|
/**
|
|
313
342
|
* A build of this view the caller already has, measured instead of building a
|
|
@@ -323,7 +352,8 @@ export function measure(
|
|
|
323
352
|
export type CheckStatus = "pass" | "fail" | "warn" | "skip";
|
|
324
353
|
|
|
325
354
|
export interface VerifyCheck {
|
|
326
|
-
|
|
355
|
+
/** `"part"` is the vacuous-verify notice; `"case"` the quick-lap "not measured" marker. */
|
|
356
|
+
scope: "view" | "subpart" | "part" | "case";
|
|
327
357
|
/** The sub-part name, `"a×b"` for a pair check, or `null` for a scalar view metric. */
|
|
328
358
|
subpart: string | null;
|
|
329
359
|
metric: string;
|
|
@@ -339,7 +369,7 @@ export interface VerifyCheck {
|
|
|
339
369
|
hint?: string;
|
|
340
370
|
/** A stable ERROR-PATTERNS.md entry id. */
|
|
341
371
|
pattern?: string;
|
|
342
|
-
/** A caveat
|
|
372
|
+
/** A measurement caveat or companion reading — `minWall` (sampling) and `overhangArea` (the steepest angle) set one. */
|
|
343
373
|
note?: string;
|
|
344
374
|
/** `[x, y, z]` in mm, for the metrics that have one. */
|
|
345
375
|
location?: number[] | null;
|
|
@@ -353,13 +383,25 @@ export interface VerifyCaseResult {
|
|
|
353
383
|
}
|
|
354
384
|
|
|
355
385
|
export interface VerifyReport {
|
|
356
|
-
/**
|
|
357
|
-
|
|
386
|
+
/**
|
|
387
|
+
* Tri-state: `true` when every declared check passed, `false` on any gate
|
|
388
|
+
* failure, `null` when no verdict can be given — a quick lap that could not
|
|
389
|
+
* measure a gate, or a part that declared no expectations at all (`declared`
|
|
390
|
+
* is 0 and `warnings` carries a `no expectations declared` notice). Never read
|
|
391
|
+
* `null` as a pass.
|
|
392
|
+
*/
|
|
393
|
+
ok: boolean | null;
|
|
358
394
|
view: string;
|
|
359
395
|
cases: VerifyCaseResult[];
|
|
360
396
|
/** Every failing check, flattened, each tagged with its `case`. */
|
|
361
397
|
failures: Array<VerifyCheck & { case: string }>;
|
|
362
398
|
warnings: Array<VerifyCheck & { case: string }>;
|
|
399
|
+
/** Checks a quick lap could not evaluate. */
|
|
400
|
+
unevaluated: Array<VerifyCheck & { case: string }>;
|
|
401
|
+
/** Check instances the part or its profile declared, across cases (near-miss notices excluded). */
|
|
402
|
+
declared: number;
|
|
403
|
+
/** Of `declared`, how many were actually answered — a skipped or unevaluated check is not. Zero withholds `ok`. */
|
|
404
|
+
evaluated: number;
|
|
363
405
|
}
|
|
364
406
|
|
|
365
407
|
/**
|