partforge 0.53.0 → 0.55.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 +12 -2
- package/package.json +1 -1
- package/src/framework/app.css +27 -2
- package/src/framework/cutaway-controls.js +4 -27
- package/src/framework/cutaway-gizmo-scene.js +3 -1
- package/src/framework/jobs.js +75 -2
- package/src/framework/measure/dim3-place.js +455 -0
- package/src/framework/measure/dim3-scene.js +438 -0
- package/src/framework/measure/feature-dims.js +258 -0
- package/src/framework/measure/measure-controls.js +110 -0
- package/src/framework/measure/measure-mode.js +546 -0
- package/src/framework/measure/param-link.js +32 -0
- package/src/framework/measure/pins.js +36 -0
- package/src/framework/mount.js +58 -5
- package/src/framework/oracle/match.js +263 -0
- package/src/framework/oracle/measure.js +5 -1
- package/src/framework/oracle/silhouette.js +146 -0
- package/src/framework/panel/render.js +41 -0
- package/src/framework/selection/drag-tracker.js +39 -0
- package/src/framework/selection/feature-highlight.js +99 -0
- package/src/framework/selection/hover.js +14 -90
- package/src/framework/selection/index.js +1 -0
- package/src/framework/selection/pick.js +11 -37
- package/src/framework/teardown.js +29 -0
- package/src/framework/viewer.js +25 -1
- package/src/testing.js +5 -0
- package/types/index.d.ts +16 -0
- package/types/testing.d.ts +116 -1
package/types/testing.d.ts
CHANGED
|
@@ -35,6 +35,15 @@ export function bootOcctKernel(opts?: { fonts?: Record<string, FontSource> }): P
|
|
|
35
35
|
|
|
36
36
|
// --- the job loop -----------------------------------------------------------
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* A reference shape for the `inspect` job to score the part's silhouettes against.
|
|
40
|
+
* A `profile` is millimetres and so is compared at absolute scale too; an `image`
|
|
41
|
+
* is a photo mask with no scale, compared on shape alone.
|
|
42
|
+
*/
|
|
43
|
+
export type MatchTarget =
|
|
44
|
+
| { kind: "profile"; rings: Array<Array<[number, number]>> }
|
|
45
|
+
| { kind: "image"; mask: { data: Uint8Array; width: number; height: number } };
|
|
46
|
+
|
|
38
47
|
/** A job the worker loop accepts. */
|
|
39
48
|
export interface WorkerJob {
|
|
40
49
|
type: "generate" | "export-stl" | "export-step" | "export-3mf" | "inspect";
|
|
@@ -50,6 +59,16 @@ export interface WorkerJob {
|
|
|
50
59
|
jobId?: number;
|
|
51
60
|
/** Single-file export name base. */
|
|
52
61
|
name?: string;
|
|
62
|
+
/**
|
|
63
|
+
* `inspect`: score the part's six canonical silhouettes against these. Absent or
|
|
64
|
+
* empty leaves `match` off the report entirely.
|
|
65
|
+
*
|
|
66
|
+
* A target that cannot be scored — malformed, or with no foreground to score
|
|
67
|
+
* against — is DROPPED rather than reported as a zero, so `report.match` is not
|
|
68
|
+
* index-aligned with this list. Attribute a result by its `kind` and by the
|
|
69
|
+
* relative order of the targets sharing that kind, never by index.
|
|
70
|
+
*/
|
|
71
|
+
matchTargets?: MatchTarget[];
|
|
53
72
|
}
|
|
54
73
|
|
|
55
74
|
/**
|
|
@@ -272,7 +291,16 @@ export function measure(
|
|
|
272
291
|
part: PartDefinition,
|
|
273
292
|
view?: string,
|
|
274
293
|
params?: ResolvedParams,
|
|
275
|
-
opts?: {
|
|
294
|
+
opts?: {
|
|
295
|
+
minWall?: boolean;
|
|
296
|
+
gapThreshold?: number;
|
|
297
|
+
/**
|
|
298
|
+
* A build of this view the caller already has, measured instead of building a
|
|
299
|
+
* second time. It is trusted, not checked against `view`/`params` — hand in a
|
|
300
|
+
* build of the same view you are asking about.
|
|
301
|
+
*/
|
|
302
|
+
built?: BuiltSubPart[];
|
|
303
|
+
},
|
|
276
304
|
): MeasureReport;
|
|
277
305
|
|
|
278
306
|
// --- verify -----------------------------------------------------------------
|
|
@@ -339,6 +367,93 @@ export function verify(
|
|
|
339
367
|
},
|
|
340
368
|
): VerifyReport;
|
|
341
369
|
|
|
370
|
+
// --- silhouette match scoring -----------------------------------------------
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* A binary silhouette. `data` is 0 or 255, one byte per pixel, row 0 at the TOP.
|
|
374
|
+
* `minX`/`minY` are the projected-plane coordinates of the image's BOTTOM-LEFT
|
|
375
|
+
* corner. A mask with no `mmPerPx` carries no scale (a photo), which is what makes
|
|
376
|
+
* the scale-aware comparison unavailable for it.
|
|
377
|
+
*/
|
|
378
|
+
export interface SilhouetteMask {
|
|
379
|
+
data: Uint8Array;
|
|
380
|
+
width: number;
|
|
381
|
+
height: number;
|
|
382
|
+
mmPerPx?: number;
|
|
383
|
+
minX?: number;
|
|
384
|
+
minY?: number;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/** The six canonical orthographic views a part is rasterized into for matching. */
|
|
388
|
+
export const MATCH_VIEWS: string[];
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Project posed meshes onto one of `MATCH_VIEWS` and scanline-fill the silhouette.
|
|
392
|
+
* `null` when there is nothing to draw or the projection has zero extent.
|
|
393
|
+
*/
|
|
394
|
+
export function rasterizeMeshMask(
|
|
395
|
+
meshes: Array<Pick<Mesh, "positions" | "indices">>,
|
|
396
|
+
view: string,
|
|
397
|
+
size?: number,
|
|
398
|
+
): SilhouetteMask | null;
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Fill a set of closed 2-D rings (millimetres) into a mask. All rings share one
|
|
402
|
+
* even-odd group, so a ring inside another is a hole. `null` when nothing fills.
|
|
403
|
+
*/
|
|
404
|
+
export function rasterizeRingsMask(
|
|
405
|
+
rings: Array<Array<[number, number]>>,
|
|
406
|
+
size?: number,
|
|
407
|
+
): SilhouetteMask | null;
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Per-pixel comparison of the two masks: `0` background, `1` overlap, `2` missing
|
|
411
|
+
* (reference only), `3` excess (candidate only).
|
|
412
|
+
*/
|
|
413
|
+
export interface MatchDelta {
|
|
414
|
+
width: number;
|
|
415
|
+
height: number;
|
|
416
|
+
data: Uint8Array;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* How close a candidate silhouette is to a reference one. Shape is compared
|
|
421
|
+
* pose-normalized, so `iou` and `boundaryIoU` ignore position and size. `iouScale`
|
|
422
|
+
* appears only for a scale-aware comparison, which also makes `contourDist` a real
|
|
423
|
+
* millimetre distance instead of a percentage of the reference's bbox diagonal.
|
|
424
|
+
*/
|
|
425
|
+
export interface MatchScores {
|
|
426
|
+
iou: number;
|
|
427
|
+
boundaryIoU: number;
|
|
428
|
+
contourDist: number;
|
|
429
|
+
contourUnit: "mm" | "%bbox-diag";
|
|
430
|
+
iouScale?: number;
|
|
431
|
+
delta: MatchDelta;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Score one candidate mask against a reference. `null` when either has no
|
|
436
|
+
* foreground at all — unscoreable is not the same as scoring zero.
|
|
437
|
+
*
|
|
438
|
+
* `scaleAware` is the caller's promise that both masks are in millimetres; it takes
|
|
439
|
+
* effect only when both actually carry a finite `mmPerPx`.
|
|
440
|
+
*/
|
|
441
|
+
export function matchMasks(
|
|
442
|
+
candidate: SilhouetteMask | null | undefined,
|
|
443
|
+
reference: SilhouetteMask | null | undefined,
|
|
444
|
+
opts?: { scaleAware?: boolean },
|
|
445
|
+
): MatchScores | null;
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Score every view's mask against one reference and name the best. Unscoreable
|
|
449
|
+
* views are left out of `views` entirely; `best` is `null` when none scored.
|
|
450
|
+
*/
|
|
451
|
+
export function matchViews(
|
|
452
|
+
viewMasks: Record<string, SilhouetteMask | null>,
|
|
453
|
+
reference: SilhouetteMask | null | undefined,
|
|
454
|
+
opts?: { scaleAware?: boolean },
|
|
455
|
+
): { best: ({ view: string } & MatchScores) | null; views: Record<string, number> };
|
|
456
|
+
|
|
342
457
|
// --- rendering --------------------------------------------------------------
|
|
343
458
|
|
|
344
459
|
/** The canonical angle names `renderViews` accepts. */
|