partforge 0.77.0 → 0.78.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 +125 -1
- package/docs/AUTHORING-PARTS.md +160 -0
- package/docs/ERROR-PATTERNS.md +30 -0
- package/package.json +1 -1
- package/src/framework/jobs.js +31 -0
- package/src/framework/oracle/describe/accept.js +188 -0
- package/src/framework/oracle/describe/features/dressups.js +173 -0
- package/src/framework/oracle/describe/features/holes.js +129 -0
- package/src/framework/oracle/describe/features/prismatic.js +454 -0
- package/src/framework/oracle/describe/features/sweeps.js +233 -0
- package/src/framework/oracle/describe/fit.js +535 -0
- package/src/framework/oracle/describe/hints.js +91 -0
- package/src/framework/oracle/describe/limits.js +19 -0
- package/src/framework/oracle/describe/patterns.js +494 -0
- package/src/framework/oracle/describe/ransac.js +391 -0
- package/src/framework/oracle/describe/report.js +217 -0
- package/src/framework/oracle/describe/segment.js +498 -0
- package/src/framework/oracle/describe/snap.js +83 -0
- package/src/framework/oracle/describe/surface-graph.js +396 -0
- package/src/framework/oracle/describe/topology.js +121 -0
- package/src/framework/oracle/describe.js +538 -0
- package/src/testing.js +5 -0
- package/types/testing.d.ts +178 -0
package/types/testing.d.ts
CHANGED
|
@@ -454,6 +454,184 @@ export function matchViews(
|
|
|
454
454
|
opts?: { scaleAware?: boolean },
|
|
455
455
|
): { best: ({ view: string } & MatchScores) | null; views: Record<string, number> };
|
|
456
456
|
|
|
457
|
+
// --- describe (the semantic mesh oracle) ------------------------------------
|
|
458
|
+
|
|
459
|
+
/** A raw measurement snapped to intent — never destroys the measurement. */
|
|
460
|
+
export interface Snapped {
|
|
461
|
+
raw: number;
|
|
462
|
+
to: number;
|
|
463
|
+
note: string | null;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/** One fitted surface patch. `fit` is the raw per-type fit record (fit.js). */
|
|
467
|
+
export interface DescribeSurface {
|
|
468
|
+
id: string;
|
|
469
|
+
type: string;
|
|
470
|
+
area: number;
|
|
471
|
+
triangles: number;
|
|
472
|
+
rms: number;
|
|
473
|
+
maxDev: number;
|
|
474
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- shape varies by surface type (plane/cylinder/cone/torus/sphere)
|
|
475
|
+
fit: Record<string, any>;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/** One fitted edge between two surfaces. */
|
|
479
|
+
export interface DescribeArc {
|
|
480
|
+
between: [string, string];
|
|
481
|
+
convexity: "convex" | "concave" | "flat";
|
|
482
|
+
kind: string;
|
|
483
|
+
radius: number | null;
|
|
484
|
+
axis: unknown;
|
|
485
|
+
length: number;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* One recognised feature. Shape varies by `type` (a hole carries `diameter`/
|
|
490
|
+
* `axis`, a fillet carries `radius`/`between`, …) — the fields every family
|
|
491
|
+
* shares are pulled out here; the rest is read by `type`. Every field here
|
|
492
|
+
* must be something a rebuilding agent would want (round 4 review) —
|
|
493
|
+
* `surfaces`/`evidence` are; nothing per-triangle belongs here. describe.js
|
|
494
|
+
* strips any such internal-plumbing field (`faceScope`, a prismatic
|
|
495
|
+
* candidate builder's own per-triangle index map) before a feature reaches
|
|
496
|
+
* this shape, so this catch-all is not a substitute for that discipline.
|
|
497
|
+
*/
|
|
498
|
+
export interface DescribeFeature {
|
|
499
|
+
id: string;
|
|
500
|
+
key: string;
|
|
501
|
+
type: string;
|
|
502
|
+
/** The marginal xor-volume reduction that admitted this feature, normalised
|
|
503
|
+
* to the source volume — the fraction of the PART'S VOLUME this feature
|
|
504
|
+
* accounts for, not a certainty rating (see `DescribeScore`'s own note): a
|
|
505
|
+
* small-but-certain feature legitimately reports a small share. `null` for
|
|
506
|
+
* a type acceptCandidates never proposes (fillet, chamfer, revolve, shell). */
|
|
507
|
+
volumeShare: number | null;
|
|
508
|
+
/** Snapped values for whichever of diameter/depth/radius/width/thickness this feature carries. */
|
|
509
|
+
snapped: Record<string, Snapped>;
|
|
510
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- per-type facts (axis, profile, evidence, …)
|
|
511
|
+
[key: string]: any;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/** A repetition (grid/linear/circular) or a detected mirror plane over the feature list. */
|
|
515
|
+
export interface DescribePattern {
|
|
516
|
+
id: string;
|
|
517
|
+
type: "grid" | "linear" | "circular";
|
|
518
|
+
members: string[];
|
|
519
|
+
axis: number[] | null;
|
|
520
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- per-type spacing/count facts
|
|
521
|
+
[key: string]: any;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/** One connected island of mesh area no surface fit claimed. */
|
|
525
|
+
export interface DescribeResidualRegion {
|
|
526
|
+
triangles: number;
|
|
527
|
+
centroid: number[];
|
|
528
|
+
bounds: { min: number[]; max: number[] };
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/** One proposed rebuild step, in the order acceptCandidates actually admitted it. */
|
|
532
|
+
export interface DescribeSuggestionStep {
|
|
533
|
+
op: string;
|
|
534
|
+
explains: string[];
|
|
535
|
+
pattern: string | null;
|
|
536
|
+
score: number;
|
|
537
|
+
args: Record<string, unknown>;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/** A proposed reconstruction — an interpretation, not a measurement (see `disclaimer`). */
|
|
541
|
+
export interface DescribeSuggestion {
|
|
542
|
+
disclaimer: string;
|
|
543
|
+
params: Array<{ name: string; value: number; from: string }>;
|
|
544
|
+
steps: DescribeSuggestionStep[];
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/** Which of the report's capped arrays actually hit their ceiling (`DESCRIBE_LIMITS`). */
|
|
548
|
+
export interface DescribeTruncated {
|
|
549
|
+
surfaces: boolean;
|
|
550
|
+
edges: boolean;
|
|
551
|
+
features: boolean;
|
|
552
|
+
patterns: boolean;
|
|
553
|
+
residualRegions: boolean;
|
|
554
|
+
suggestionSteps: boolean;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
export interface DescribeScore {
|
|
558
|
+
/** Surface coverage from segmentation: fraction of the mesh's area fitted to some surface type. */
|
|
559
|
+
explainedArea: number;
|
|
560
|
+
/** Shape coverage from reconstruction: fraction of the part's volume the accepted features rebuild. */
|
|
561
|
+
explainedVolumeFraction: number;
|
|
562
|
+
xorFraction: number;
|
|
563
|
+
xorVolume: number;
|
|
564
|
+
note: string;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/** A full `describe()` report — everything measured, meant for archival/`--json`. */
|
|
568
|
+
export interface DescribeReport {
|
|
569
|
+
source: { name: string | null; digest: string | null; triangles: number; watertight: boolean | null; units: "mm" };
|
|
570
|
+
frame: { up: "+Z"; note: string };
|
|
571
|
+
bounds: { min: number[]; max: number[]; size: number[] };
|
|
572
|
+
counts: { surfaces: number; edges: number };
|
|
573
|
+
surfaces: DescribeSurface[];
|
|
574
|
+
edges: DescribeArc[];
|
|
575
|
+
features: DescribeFeature[];
|
|
576
|
+
patterns: DescribePattern[];
|
|
577
|
+
symmetry: unknown[];
|
|
578
|
+
residual: { areaFraction: number; regions: DescribeResidualRegion[] };
|
|
579
|
+
score: DescribeScore;
|
|
580
|
+
suggestion: DescribeSuggestion | null;
|
|
581
|
+
truncated: DescribeTruncated;
|
|
582
|
+
/** Present only when the acceptance loop hit its boolean budget before converging. */
|
|
583
|
+
warning?: "budget-exceeded";
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
/** The model-facing view: capped arrays elided to counts, a coverage banner first when low. */
|
|
587
|
+
export type DescribeCompactReport = Omit<DescribeReport, "surfaces" | "edges"> & {
|
|
588
|
+
/** Present, and serialized FIRST, only when coverage is below `LOW_COVERAGE`. */
|
|
589
|
+
warning?: string;
|
|
590
|
+
};
|
|
591
|
+
|
|
592
|
+
/** A closed-set failure, returned rather than thrown (spec §5's diagnostic triple). */
|
|
593
|
+
export interface DescribeFailure {
|
|
594
|
+
error: "not-manifold" | "too-large" | "empty" | "budget-exceeded" | "unreadable";
|
|
595
|
+
detail: string;
|
|
596
|
+
diagnostic: { cause: string; location: string; correctiveAction: string };
|
|
597
|
+
source: { name: string | null; digest: string | null; [key: string]: unknown };
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/** The closed set of error codes `describe()` can return. */
|
|
601
|
+
export const DESCRIBE_ERRORS: readonly string[];
|
|
602
|
+
|
|
603
|
+
/** Report array ceilings (`MAX_SURFACES`, `MAX_FEATURES`, …) — a plain-data module, no imports. */
|
|
604
|
+
export const DESCRIBE_LIMITS: {
|
|
605
|
+
MAX_SURFACES: number;
|
|
606
|
+
MAX_EDGES: number;
|
|
607
|
+
MAX_FEATURES: number;
|
|
608
|
+
MAX_PATTERNS: number;
|
|
609
|
+
MAX_RESIDUAL_REGIONS: number;
|
|
610
|
+
MAX_SUGGESTION_STEPS: number;
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
/** Below this fraction (the worse of `explainedArea`/`explainedVolumeFraction`) `compactDescribe` prepends a warning. */
|
|
614
|
+
export const LOW_COVERAGE: number;
|
|
615
|
+
|
|
616
|
+
/** A fresh, caller-owned digest memo — scope one per worker, or per test. */
|
|
617
|
+
export function describeMemo(): Map<string, DescribeReport>;
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Mesh in, semantic feature report out. `solid` is a LIVE kernel `Solid` — the
|
|
621
|
+
* kernel has no public mesh->solid constructor, so a caller reads one back via
|
|
622
|
+
* `kernel.import(name)`. Keyed by `opts.digest` in `opts.memo` (when both are
|
|
623
|
+
* given): the report depends on nothing but the mesh bytes, so an edit to the
|
|
624
|
+
* part that produced the mesh can never invalidate it.
|
|
625
|
+
*/
|
|
626
|
+
export function describe(
|
|
627
|
+
kernel: GeometryKernel,
|
|
628
|
+
solid: Solid,
|
|
629
|
+
opts?: { name?: string; digest?: string; budget?: number; memo?: Map<string, DescribeReport> },
|
|
630
|
+
): DescribeReport | DescribeFailure;
|
|
631
|
+
|
|
632
|
+
/** The full report, reduced to what a model should read: capped arrays elided to counts, low-coverage banner first. */
|
|
633
|
+
export function compactDescribe(full: DescribeReport): DescribeCompactReport;
|
|
634
|
+
|
|
457
635
|
// --- rendering --------------------------------------------------------------
|
|
458
636
|
|
|
459
637
|
/** The canonical angle names `renderViews` accepts. */
|