brepjs 18.118.2 → 18.118.4
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/dist/2d.cjs +6 -6
- package/dist/2d.js +6 -6
- package/dist/{adjacencyFns-COWMJ1OX.cjs → adjacencyFns-CiDCunAU.cjs} +2 -2
- package/dist/{adjacencyFns-D026zKM3.js → adjacencyFns-CxepMm7H.js} +2 -2
- package/dist/{blueprint-BeCL-AAl.js → blueprint-BIf01dZl.js} +15 -10
- package/dist/{blueprint-xcDMSkia.cjs → blueprint-Bp_sSxx2.cjs} +17 -11
- package/dist/{blueprintFns-DIMiD67q.cjs → blueprintFns-Dc8amB5a.cjs} +2 -2
- package/dist/{blueprintFns-BkSFPipn.js → blueprintFns-Dl_drDhd.js} +2 -2
- package/dist/{blueprintSketcher-DKfkNg71.js → blueprintSketcher-D-xSC6Mp.js} +5 -4
- package/dist/{blueprintSketcher-DGcCDQq2.cjs → blueprintSketcher-XiLc6fJ4.cjs} +5 -4
- package/dist/{boolean2D-BCTOcf19.js → boolean2D-BNjpYyZl.js} +5 -5
- package/dist/{boolean2D-Dh4IPW_X.cjs → boolean2D-BfKG5Wio.cjs} +7 -6
- package/dist/brepjs.cjs +29 -29
- package/dist/brepjs.js +29 -29
- package/dist/{cameraFns-BAm-2Clq.cjs → cameraFns-ClE0QcuX.cjs} +2 -2
- package/dist/{cameraFns-CRln-7RT.js → cameraFns-DyMKpFHq.js} +2 -2
- package/dist/core/shapeTypes.d.ts +32 -0
- package/dist/core.cjs +1 -1
- package/dist/core.js +1 -1
- package/dist/{cornerFinder-DMJBP4I2.cjs → cornerFinder-CINnfCPc.cjs} +1 -1
- package/dist/{cornerFinder-Bu482P3S.js → cornerFinder-DFswCdwf.js} +1 -1
- package/dist/{curveFns-pGQFlJG-.js → curveFns-BYcTyyb7.js} +1 -1
- package/dist/{curveFns-CpaxYpa4.cjs → curveFns-YvH970hp.cjs} +1 -1
- package/dist/{drawFns-D-PqWuBQ.cjs → drawFns-CG3ksr6q.cjs} +14 -13
- package/dist/{drawFns-BAETgRWM.js → drawFns-DkhqDgS5.js} +14 -13
- package/dist/{faceFns-Bc6sBrBV.js → faceFns-CpOAl1K5.js} +2 -2
- package/dist/{faceFns-rbWcdpvj.cjs → faceFns-DnLXDWq2.cjs} +4 -3
- package/dist/{healingFns-DfshoSeQ.cjs → healingFns-BIcPeCM9.cjs} +16 -15
- package/dist/{healingFns-DHxzmeCt.js → healingFns-BP0xjoIs.js} +16 -15
- package/dist/{helpers-YD71h41H.js → helpers-BVkEnH5n.js} +6 -6
- package/dist/{helpers-CKbgoPDr.cjs → helpers-Beq_ugyN.cjs} +6 -6
- package/dist/{importFns-CQ16LqPQ.cjs → importFns-BZYgEOu-.cjs} +4 -4
- package/dist/{importFns-A437Sgj6.js → importFns-DPQmk2TS.js} +4 -4
- package/dist/io.cjs +2 -2
- package/dist/io.js +2 -2
- package/dist/kernel/occtWasm/booleanOps.d.ts +9 -1
- package/dist/kernel/occtWasm/occtWasmAdapter.cjs +1 -1
- package/dist/kernel/occtWasm/occtWasmAdapter.js +1 -1
- package/dist/kernel/types.d.ts +2 -4
- package/dist/{loftFns-BQktV4u4.cjs → loftFns-CZC_NH_h.cjs} +1 -1
- package/dist/{loftFns-CXc9tRv6.js → loftFns-NauDWzek.js} +1 -1
- package/dist/{measureFns-B_vJqwDc.js → measureFns-BLmLZr0K.js} +3 -3
- package/dist/{measureFns-I5KcAgSb.cjs → measureFns-C4BxD4kC.cjs} +3 -3
- package/dist/measurement.cjs +1 -1
- package/dist/measurement.js +1 -1
- package/dist/{meshFns-COdN1kVO.js → meshFns-BK5O_pJ9.js} +3 -3
- package/dist/{meshFns-fPnPGEPl.cjs → meshFns-BoF6g1go.cjs} +3 -3
- package/dist/{occtWasmAdapter-B2TEQOjs.cjs → occtWasmAdapter-Bj9dX3Lb.cjs} +45 -10
- package/dist/{occtWasmAdapter-CKwtxwNH.js → occtWasmAdapter-wBLknH8f.js} +45 -10
- package/dist/operations.cjs +2 -2
- package/dist/operations.js +2 -2
- package/dist/{primitiveFns-DxP7GVQh.js → primitiveFns-DJUXtN6W.js} +4 -4
- package/dist/{primitiveFns-Cohp602Q.cjs → primitiveFns-DOyyz54-.cjs} +4 -4
- package/dist/projection.cjs +1 -1
- package/dist/projection.js +1 -1
- package/dist/query.cjs +2 -2
- package/dist/query.js +2 -2
- package/dist/{refResolveFns-NGXXyTBa.js → refResolveFns-DL1zXF8u.js} +18 -11
- package/dist/{refResolveFns-Du0v4e3Y.cjs → refResolveFns-DbTYd_Nj.cjs} +18 -11
- package/dist/{shapeFns-DqGDtCsE.js → shapeFns-DED4C70_.js} +84 -23
- package/dist/{shapeFns-DvmBIZaX.cjs → shapeFns-DxAhtxFP.cjs} +84 -23
- package/dist/shapeRef.cjs +1 -1
- package/dist/shapeRef.js +1 -1
- package/dist/{shapeTypes-EI4Uxlsb.js → shapeTypes-BguzpBK0.js} +70 -22
- package/dist/{shapeTypes-BLREi6xB.cjs → shapeTypes-Ca76Bklg.cjs} +87 -21
- package/dist/sketching.cjs +3 -3
- package/dist/sketching.js +3 -3
- package/dist/{solidBuilders-Oq-hxTvJ.js → solidBuilders-_8mqPO7I.js} +6 -5
- package/dist/{solidBuilders-B6DBRdRc.cjs → solidBuilders-yyfZ2Q-7.cjs} +6 -5
- package/dist/{surfaceBuilders-C0pJwtCO.js → surfaceBuilders-CT__o6Be.js} +2 -2
- package/dist/{surfaceBuilders-C-UhFlpS.cjs → surfaceBuilders-De2XKidK.cjs} +2 -2
- package/dist/text.cjs +2 -2
- package/dist/text.js +2 -2
- package/dist/{textBlueprints-lSKzw-nT.cjs → textBlueprints-C17PPSzH.cjs} +9 -8
- package/dist/{textBlueprints-fBpuvT3m.js → textBlueprints-D9l3v-f3.js} +9 -8
- package/dist/{textMetrics-BkTdFBwC.cjs → textMetrics-BwQ7TD47.cjs} +1 -1
- package/dist/{textMetrics-CnrAQwLI.js → textMetrics-GSAxEtaJ.js} +1 -1
- package/dist/{threadFns-DJt3EStH.cjs → threadFns-Bu2c-lu_.cjs} +8 -8
- package/dist/{threadFns-Dlts4xFy.js → threadFns-DOqhI5OK.js} +8 -8
- package/dist/topology.cjs +9 -9
- package/dist/topology.js +9 -9
- package/dist/{topologyQueryFns-1PqfeHrV.cjs → topologyQueryFns-B1QAiZVI.cjs} +1 -1
- package/dist/{topologyQueryFns-BjgBf2t-.js → topologyQueryFns-Dl2F-2d9.js} +1 -1
- package/package.json +16 -15
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { et as getKernel, t as castResultShape } from "./shapeTypes-BguzpBK0.js";
|
|
2
2
|
import { A as ok, b as err, d as validationError, t as BrepErrorCode } from "./errors-DNWJsfVU.js";
|
|
3
|
-
import { C as kernelCall, c as getFaces, l as getOrCreateCache, r as getCacheEntry, w as kernelCallRaw } from "./topologyQueryFns-
|
|
3
|
+
import { C as kernelCall, c as getFaces, l as getOrCreateCache, r as getCacheEntry, w as kernelCallRaw } from "./topologyQueryFns-Dl2F-2d9.js";
|
|
4
4
|
import { n as HASH_CODE_MAX, t as DEG2RAD } from "./constants-ITRzCnCp.js";
|
|
5
5
|
//#region src/topology/metadata/originTrackingFns.ts
|
|
6
6
|
/**
|
|
@@ -13,8 +13,12 @@ import { n as HASH_CODE_MAX, t as DEG2RAD } from "./constants-ITRzCnCp.js";
|
|
|
13
13
|
*/
|
|
14
14
|
function setShapeOrigin(shape, origin) {
|
|
15
15
|
const cache = getOrCreateCache(shape);
|
|
16
|
+
const kernel = getKernel();
|
|
16
17
|
const map = /* @__PURE__ */ new Map();
|
|
17
|
-
for (const
|
|
18
|
+
for (const face of kernel.iterShapes(shape.wrapped, "face")) {
|
|
19
|
+
map.set(kernel.hashCode(face, HASH_CODE_MAX), origin);
|
|
20
|
+
kernel.dispose(face);
|
|
21
|
+
}
|
|
18
22
|
cache.faceOrigins = map;
|
|
19
23
|
}
|
|
20
24
|
/**
|
|
@@ -51,13 +55,44 @@ function propagateOriginsFromEvolution(evolution, inputs, result) {
|
|
|
51
55
|
cache.faceOrigins = resultMap;
|
|
52
56
|
}
|
|
53
57
|
}
|
|
58
|
+
/** Max 3D centroid separation (mm²) for a "near" match — the general case. */
|
|
59
|
+
var MAX_MATCH_DIST_SQ = 100;
|
|
60
|
+
/** Min |outNormal·inNormal| for two faces to count as sharing a plane's orientation. */
|
|
61
|
+
var COPLANAR_NORMAL_MIN = .985;
|
|
62
|
+
/**
|
|
63
|
+
* Max squared perpendicular offset (mm²) from an input face's plane for the
|
|
64
|
+
* output face to count as *coplanar* with it — i.e. a piece the boolean sliced
|
|
65
|
+
* off that same planar surface. 0.1mm² tolerates kernel/mesh float noise while
|
|
66
|
+
* still separating floors that sit even a fraction of a mm apart in depth.
|
|
67
|
+
*/
|
|
68
|
+
var COPLANAR_OFFSET_SQ = .1;
|
|
54
69
|
/**
|
|
55
70
|
* Find the best origin match for a result face by comparing normals and centroids
|
|
56
71
|
* against input face signatures. Returns `undefined` if no good match exists.
|
|
72
|
+
*
|
|
73
|
+
* Two passes, near strictly preferred:
|
|
74
|
+
* 1. Near match — same-facing normal (signed dot ≥ 0.707) and centroids within
|
|
75
|
+
* {@link MAX_MATCH_DIST_SQ}. The general case for regenerated seam faces
|
|
76
|
+
* (feature tops, flush walls). Unchanged legacy behavior. If any near match
|
|
77
|
+
* exists it wins outright — the coplanar pass never runs — so a distant
|
|
78
|
+
* coplanar candidate can't outscore a valid near one.
|
|
79
|
+
* 2. Coplanar match (only when no near match, and only between PLANAR faces) —
|
|
80
|
+
* the output face lies on an input face's plane (parallel *or* antiparallel
|
|
81
|
+
* normal, tiny perpendicular offset) regardless of how far its centroid
|
|
82
|
+
* drifted in-plane. Two cases pass 1 misses:
|
|
83
|
+
* • A boolean that splits a large planar face — a wide cutout floor sliced
|
|
84
|
+
* by an overlapping deeper cutout — leaves pieces >10mm from the parent
|
|
85
|
+
* centroid (past pass 1's cutoff).
|
|
86
|
+
* • A cut flips the cavity face's normal versus the tool face it came from,
|
|
87
|
+
* so the floor is antiparallel to its origin's input face.
|
|
88
|
+
* Both left the surface tagless → body color in multi-color consumers
|
|
89
|
+
* (gridfinity GH #2443). The planar gate keeps a curved output face from
|
|
90
|
+
* inheriting an origin off an unrelated face that merely shares a sampled
|
|
91
|
+
* tangent plane; among coplanar candidates the nearest in-plane wins.
|
|
57
92
|
*/
|
|
58
|
-
function findBestOriginMatch(outNormal, outCentroid, inputSigs) {
|
|
59
|
-
let
|
|
60
|
-
let
|
|
93
|
+
function findBestOriginMatch(outNormal, outCentroid, outPlanar, inputSigs) {
|
|
94
|
+
let bestNearScore = -Infinity;
|
|
95
|
+
let bestNear;
|
|
61
96
|
for (const inp of inputSigs) {
|
|
62
97
|
const dot = outNormal[0] * inp.normal[0] + outNormal[1] * inp.normal[1] + outNormal[2] * inp.normal[2];
|
|
63
98
|
if (dot < .707) continue;
|
|
@@ -65,14 +100,33 @@ function findBestOriginMatch(outNormal, outCentroid, inputSigs) {
|
|
|
65
100
|
const dy = outCentroid[1] - inp.centroid[1];
|
|
66
101
|
const dz = outCentroid[2] - inp.centroid[2];
|
|
67
102
|
const distSq = dx * dx + dy * dy + dz * dz;
|
|
68
|
-
if (distSq >
|
|
69
|
-
const score = dot - distSq /
|
|
70
|
-
if (score >
|
|
71
|
-
|
|
72
|
-
|
|
103
|
+
if (distSq > MAX_MATCH_DIST_SQ) continue;
|
|
104
|
+
const score = dot - distSq / MAX_MATCH_DIST_SQ;
|
|
105
|
+
if (score > bestNearScore) {
|
|
106
|
+
bestNearScore = score;
|
|
107
|
+
bestNear = inp.origin;
|
|
73
108
|
}
|
|
74
109
|
}
|
|
75
|
-
return
|
|
110
|
+
if (bestNear !== void 0) return bestNear;
|
|
111
|
+
if (!outPlanar) return void 0;
|
|
112
|
+
let bestInPlaneSq = Infinity;
|
|
113
|
+
let bestCoplanar;
|
|
114
|
+
for (const inp of inputSigs) {
|
|
115
|
+
if (!inp.planar) continue;
|
|
116
|
+
const dot = outNormal[0] * inp.normal[0] + outNormal[1] * inp.normal[1] + outNormal[2] * inp.normal[2];
|
|
117
|
+
if (Math.abs(dot) < COPLANAR_NORMAL_MIN) continue;
|
|
118
|
+
const dx = outCentroid[0] - inp.centroid[0];
|
|
119
|
+
const dy = outCentroid[1] - inp.centroid[1];
|
|
120
|
+
const dz = outCentroid[2] - inp.centroid[2];
|
|
121
|
+
const perp = dx * inp.normal[0] + dy * inp.normal[1] + dz * inp.normal[2];
|
|
122
|
+
if (perp * perp > COPLANAR_OFFSET_SQ) continue;
|
|
123
|
+
const inPlaneSq = Math.max(0, dx * dx + dy * dy + dz * dz - perp * perp);
|
|
124
|
+
if (inPlaneSq < bestInPlaneSq) {
|
|
125
|
+
bestInPlaneSq = inPlaneSq;
|
|
126
|
+
bestCoplanar = inp.origin;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return bestCoplanar;
|
|
76
130
|
}
|
|
77
131
|
/**
|
|
78
132
|
* Fallback origin propagation when no kernel op object is available
|
|
@@ -126,10 +180,12 @@ function propagateOriginsByHash(inputs, result) {
|
|
|
126
180
|
const bounds = kernel.uvBounds(f.wrapped);
|
|
127
181
|
const normal = kernel.surfaceNormal(f.wrapped, .5 * (bounds.uMin + bounds.uMax), .5 * (bounds.vMin + bounds.vMax));
|
|
128
182
|
const centroid = kernel.surfaceCenterOfMass(f.wrapped);
|
|
183
|
+
const planar = kernel.surfaceType(f.wrapped) === "plane";
|
|
129
184
|
inputSigs.push({
|
|
130
185
|
origin,
|
|
131
186
|
normal,
|
|
132
|
-
centroid
|
|
187
|
+
centroid,
|
|
188
|
+
planar
|
|
133
189
|
});
|
|
134
190
|
} catch {}
|
|
135
191
|
}
|
|
@@ -138,7 +194,7 @@ function propagateOriginsByHash(inputs, result) {
|
|
|
138
194
|
const hash = kernel.hashCode(f.wrapped, HASH_CODE_MAX);
|
|
139
195
|
try {
|
|
140
196
|
const outBounds = kernel.uvBounds(f.wrapped);
|
|
141
|
-
const bestOrigin = findBestOriginMatch(kernel.surfaceNormal(f.wrapped, .5 * (outBounds.uMin + outBounds.uMax), .5 * (outBounds.vMin + outBounds.vMax)), kernel.surfaceCenterOfMass(f.wrapped), inputSigs);
|
|
197
|
+
const bestOrigin = findBestOriginMatch(kernel.surfaceNormal(f.wrapped, .5 * (outBounds.uMin + outBounds.uMax), .5 * (outBounds.vMin + outBounds.vMax)), kernel.surfaceCenterOfMass(f.wrapped), kernel.surfaceType(f.wrapped) === "plane", inputSigs);
|
|
142
198
|
if (bestOrigin !== void 0) resultMap.set(hash, bestOrigin);
|
|
143
199
|
} catch {}
|
|
144
200
|
}
|
|
@@ -390,7 +446,10 @@ function collectInputFaceHashes(inputs) {
|
|
|
390
446
|
const hashes = [];
|
|
391
447
|
for (const input of inputs) {
|
|
392
448
|
const faces = kernel.iterShapes(input.wrapped, "face");
|
|
393
|
-
for (const face of faces)
|
|
449
|
+
for (const face of faces) {
|
|
450
|
+
hashes.push(kernel.hashCode(face, HASH_CODE_MAX));
|
|
451
|
+
kernel.dispose(face);
|
|
452
|
+
}
|
|
394
453
|
}
|
|
395
454
|
return hashes;
|
|
396
455
|
}
|
|
@@ -446,6 +505,8 @@ function propagateMetadataThroughRelocation(source, moved) {
|
|
|
446
505
|
if (sf === void 0 || mf === void 0) continue;
|
|
447
506
|
modified.set(kernel.hashCode(sf, HASH_CODE_MAX), [kernel.hashCode(mf, HASH_CODE_MAX)]);
|
|
448
507
|
}
|
|
508
|
+
for (const f of srcFaces) kernel.dispose(f);
|
|
509
|
+
for (const f of movedFaces) kernel.dispose(f);
|
|
449
510
|
propagateAllMetadata({
|
|
450
511
|
modified,
|
|
451
512
|
generated: /* @__PURE__ */ new Map(),
|
|
@@ -462,7 +523,7 @@ function propagateMetadataThroughRelocation(source, moved) {
|
|
|
462
523
|
function translate(shape, v) {
|
|
463
524
|
const inputFaceHashes = collectInputFaceHashes([shape]);
|
|
464
525
|
const { shape: resultShape, evolution } = getKernel().translateWithHistory(shape.wrapped, v[0], v[1], v[2], inputFaceHashes, HASH_CODE_MAX);
|
|
465
|
-
const result =
|
|
526
|
+
const result = castResultShape(resultShape);
|
|
466
527
|
propagateAllMetadata(evolution, [shape], result);
|
|
467
528
|
return result;
|
|
468
529
|
}
|
|
@@ -478,7 +539,7 @@ function rotate(shape, angle, position = [
|
|
|
478
539
|
]) {
|
|
479
540
|
const inputFaceHashes = collectInputFaceHashes([shape]);
|
|
480
541
|
const { shape: resultShape, evolution } = getKernel().rotateWithHistory(shape.wrapped, angle * DEG2RAD, inputFaceHashes, HASH_CODE_MAX, direction, position);
|
|
481
|
-
const result =
|
|
542
|
+
const result = castResultShape(resultShape);
|
|
482
543
|
propagateAllMetadata(evolution, [shape], result);
|
|
483
544
|
return result;
|
|
484
545
|
}
|
|
@@ -494,7 +555,7 @@ function mirror(shape, planeNormal = [
|
|
|
494
555
|
]) {
|
|
495
556
|
const inputFaceHashes = collectInputFaceHashes([shape]);
|
|
496
557
|
const { shape: resultShape, evolution } = getKernel().mirrorWithHistory(shape.wrapped, planeOrigin, planeNormal, inputFaceHashes, HASH_CODE_MAX);
|
|
497
|
-
const result =
|
|
558
|
+
const result = castResultShape(resultShape);
|
|
498
559
|
propagateAllMetadata(evolution, [shape], result);
|
|
499
560
|
return result;
|
|
500
561
|
}
|
|
@@ -506,7 +567,7 @@ function scale(shape, factor, center = [
|
|
|
506
567
|
]) {
|
|
507
568
|
const inputFaceHashes = collectInputFaceHashes([shape]);
|
|
508
569
|
const { shape: resultShape, evolution } = getKernel().scaleWithHistory(shape.wrapped, center, factor, inputFaceHashes, HASH_CODE_MAX);
|
|
509
|
-
const result =
|
|
570
|
+
const result = castResultShape(resultShape);
|
|
510
571
|
propagateAllMetadata(evolution, [shape], result);
|
|
511
572
|
return result;
|
|
512
573
|
}
|
|
@@ -608,11 +669,11 @@ function applyMatrix(shape, matrix) {
|
|
|
608
669
|
if (isOrthogonalMatrix(linear)) {
|
|
609
670
|
const inputFaceHashes = collectInputFaceHashes([shape]);
|
|
610
671
|
const { shape: resultShape, evolution } = getKernel().generalTransformWithHistory(shape.wrapped, linear, translation, true, inputFaceHashes, HASH_CODE_MAX);
|
|
611
|
-
const result =
|
|
672
|
+
const result = castResultShape(resultShape);
|
|
612
673
|
propagateAllMetadata(evolution, [shape], result);
|
|
613
674
|
return ok(result);
|
|
614
675
|
}
|
|
615
|
-
const result =
|
|
676
|
+
const result = castResultShape(getKernel().generalTransformNonOrthogonal(shape.wrapped, linear, translation));
|
|
616
677
|
propagateMetadataByHash([shape], result);
|
|
617
678
|
return ok(result);
|
|
618
679
|
/* v8 ignore stop */
|
|
@@ -661,7 +722,7 @@ function locate(shape, placement) {
|
|
|
661
722
|
const { trsf, cleanup } = composeTransforms("type" in placement ? [placement] : placement);
|
|
662
723
|
let moved;
|
|
663
724
|
try {
|
|
664
|
-
moved =
|
|
725
|
+
moved = castResultShape(getKernel().locate(shape.wrapped, trsf));
|
|
665
726
|
} finally {
|
|
666
727
|
cleanup();
|
|
667
728
|
}
|
|
@@ -675,7 +736,7 @@ function locate(shape, placement) {
|
|
|
675
736
|
function transformCopy(shape, composed) {
|
|
676
737
|
const inputFaceHashes = collectInputFaceHashes([shape]);
|
|
677
738
|
const { shape: resultShape, evolution } = getKernel().applyComposedTransformWithHistory(shape.wrapped, composed.trsf, inputFaceHashes, HASH_CODE_MAX);
|
|
678
|
-
const result =
|
|
739
|
+
const result = castResultShape(resultShape);
|
|
679
740
|
propagateAllMetadata(evolution, [shape], result);
|
|
680
741
|
return result;
|
|
681
742
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const require_shapeTypes = require("./shapeTypes-
|
|
1
|
+
const require_shapeTypes = require("./shapeTypes-Ca76Bklg.cjs");
|
|
2
2
|
const require_errors = require("./errors-CXJtc4I7.cjs");
|
|
3
|
-
const require_topologyQueryFns = require("./topologyQueryFns-
|
|
3
|
+
const require_topologyQueryFns = require("./topologyQueryFns-B1QAiZVI.cjs");
|
|
4
4
|
const require_constants = require("./constants-BOVyEYGH.cjs");
|
|
5
5
|
//#region src/topology/metadata/originTrackingFns.ts
|
|
6
6
|
/**
|
|
@@ -13,8 +13,12 @@ const require_constants = require("./constants-BOVyEYGH.cjs");
|
|
|
13
13
|
*/
|
|
14
14
|
function setShapeOrigin(shape, origin) {
|
|
15
15
|
const cache = require_topologyQueryFns.getOrCreateCache(shape);
|
|
16
|
+
const kernel = require_shapeTypes.getKernel();
|
|
16
17
|
const map = /* @__PURE__ */ new Map();
|
|
17
|
-
for (const
|
|
18
|
+
for (const face of kernel.iterShapes(shape.wrapped, "face")) {
|
|
19
|
+
map.set(kernel.hashCode(face, require_constants.HASH_CODE_MAX), origin);
|
|
20
|
+
kernel.dispose(face);
|
|
21
|
+
}
|
|
18
22
|
cache.faceOrigins = map;
|
|
19
23
|
}
|
|
20
24
|
/**
|
|
@@ -51,13 +55,44 @@ function propagateOriginsFromEvolution(evolution, inputs, result) {
|
|
|
51
55
|
cache.faceOrigins = resultMap;
|
|
52
56
|
}
|
|
53
57
|
}
|
|
58
|
+
/** Max 3D centroid separation (mm²) for a "near" match — the general case. */
|
|
59
|
+
var MAX_MATCH_DIST_SQ = 100;
|
|
60
|
+
/** Min |outNormal·inNormal| for two faces to count as sharing a plane's orientation. */
|
|
61
|
+
var COPLANAR_NORMAL_MIN = .985;
|
|
62
|
+
/**
|
|
63
|
+
* Max squared perpendicular offset (mm²) from an input face's plane for the
|
|
64
|
+
* output face to count as *coplanar* with it — i.e. a piece the boolean sliced
|
|
65
|
+
* off that same planar surface. 0.1mm² tolerates kernel/mesh float noise while
|
|
66
|
+
* still separating floors that sit even a fraction of a mm apart in depth.
|
|
67
|
+
*/
|
|
68
|
+
var COPLANAR_OFFSET_SQ = .1;
|
|
54
69
|
/**
|
|
55
70
|
* Find the best origin match for a result face by comparing normals and centroids
|
|
56
71
|
* against input face signatures. Returns `undefined` if no good match exists.
|
|
72
|
+
*
|
|
73
|
+
* Two passes, near strictly preferred:
|
|
74
|
+
* 1. Near match — same-facing normal (signed dot ≥ 0.707) and centroids within
|
|
75
|
+
* {@link MAX_MATCH_DIST_SQ}. The general case for regenerated seam faces
|
|
76
|
+
* (feature tops, flush walls). Unchanged legacy behavior. If any near match
|
|
77
|
+
* exists it wins outright — the coplanar pass never runs — so a distant
|
|
78
|
+
* coplanar candidate can't outscore a valid near one.
|
|
79
|
+
* 2. Coplanar match (only when no near match, and only between PLANAR faces) —
|
|
80
|
+
* the output face lies on an input face's plane (parallel *or* antiparallel
|
|
81
|
+
* normal, tiny perpendicular offset) regardless of how far its centroid
|
|
82
|
+
* drifted in-plane. Two cases pass 1 misses:
|
|
83
|
+
* • A boolean that splits a large planar face — a wide cutout floor sliced
|
|
84
|
+
* by an overlapping deeper cutout — leaves pieces >10mm from the parent
|
|
85
|
+
* centroid (past pass 1's cutoff).
|
|
86
|
+
* • A cut flips the cavity face's normal versus the tool face it came from,
|
|
87
|
+
* so the floor is antiparallel to its origin's input face.
|
|
88
|
+
* Both left the surface tagless → body color in multi-color consumers
|
|
89
|
+
* (gridfinity GH #2443). The planar gate keeps a curved output face from
|
|
90
|
+
* inheriting an origin off an unrelated face that merely shares a sampled
|
|
91
|
+
* tangent plane; among coplanar candidates the nearest in-plane wins.
|
|
57
92
|
*/
|
|
58
|
-
function findBestOriginMatch(outNormal, outCentroid, inputSigs) {
|
|
59
|
-
let
|
|
60
|
-
let
|
|
93
|
+
function findBestOriginMatch(outNormal, outCentroid, outPlanar, inputSigs) {
|
|
94
|
+
let bestNearScore = -Infinity;
|
|
95
|
+
let bestNear;
|
|
61
96
|
for (const inp of inputSigs) {
|
|
62
97
|
const dot = outNormal[0] * inp.normal[0] + outNormal[1] * inp.normal[1] + outNormal[2] * inp.normal[2];
|
|
63
98
|
if (dot < .707) continue;
|
|
@@ -65,14 +100,33 @@ function findBestOriginMatch(outNormal, outCentroid, inputSigs) {
|
|
|
65
100
|
const dy = outCentroid[1] - inp.centroid[1];
|
|
66
101
|
const dz = outCentroid[2] - inp.centroid[2];
|
|
67
102
|
const distSq = dx * dx + dy * dy + dz * dz;
|
|
68
|
-
if (distSq >
|
|
69
|
-
const score = dot - distSq /
|
|
70
|
-
if (score >
|
|
71
|
-
|
|
72
|
-
|
|
103
|
+
if (distSq > MAX_MATCH_DIST_SQ) continue;
|
|
104
|
+
const score = dot - distSq / MAX_MATCH_DIST_SQ;
|
|
105
|
+
if (score > bestNearScore) {
|
|
106
|
+
bestNearScore = score;
|
|
107
|
+
bestNear = inp.origin;
|
|
73
108
|
}
|
|
74
109
|
}
|
|
75
|
-
return
|
|
110
|
+
if (bestNear !== void 0) return bestNear;
|
|
111
|
+
if (!outPlanar) return void 0;
|
|
112
|
+
let bestInPlaneSq = Infinity;
|
|
113
|
+
let bestCoplanar;
|
|
114
|
+
for (const inp of inputSigs) {
|
|
115
|
+
if (!inp.planar) continue;
|
|
116
|
+
const dot = outNormal[0] * inp.normal[0] + outNormal[1] * inp.normal[1] + outNormal[2] * inp.normal[2];
|
|
117
|
+
if (Math.abs(dot) < COPLANAR_NORMAL_MIN) continue;
|
|
118
|
+
const dx = outCentroid[0] - inp.centroid[0];
|
|
119
|
+
const dy = outCentroid[1] - inp.centroid[1];
|
|
120
|
+
const dz = outCentroid[2] - inp.centroid[2];
|
|
121
|
+
const perp = dx * inp.normal[0] + dy * inp.normal[1] + dz * inp.normal[2];
|
|
122
|
+
if (perp * perp > COPLANAR_OFFSET_SQ) continue;
|
|
123
|
+
const inPlaneSq = Math.max(0, dx * dx + dy * dy + dz * dz - perp * perp);
|
|
124
|
+
if (inPlaneSq < bestInPlaneSq) {
|
|
125
|
+
bestInPlaneSq = inPlaneSq;
|
|
126
|
+
bestCoplanar = inp.origin;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return bestCoplanar;
|
|
76
130
|
}
|
|
77
131
|
/**
|
|
78
132
|
* Fallback origin propagation when no kernel op object is available
|
|
@@ -126,10 +180,12 @@ function propagateOriginsByHash(inputs, result) {
|
|
|
126
180
|
const bounds = kernel.uvBounds(f.wrapped);
|
|
127
181
|
const normal = kernel.surfaceNormal(f.wrapped, .5 * (bounds.uMin + bounds.uMax), .5 * (bounds.vMin + bounds.vMax));
|
|
128
182
|
const centroid = kernel.surfaceCenterOfMass(f.wrapped);
|
|
183
|
+
const planar = kernel.surfaceType(f.wrapped) === "plane";
|
|
129
184
|
inputSigs.push({
|
|
130
185
|
origin,
|
|
131
186
|
normal,
|
|
132
|
-
centroid
|
|
187
|
+
centroid,
|
|
188
|
+
planar
|
|
133
189
|
});
|
|
134
190
|
} catch {}
|
|
135
191
|
}
|
|
@@ -138,7 +194,7 @@ function propagateOriginsByHash(inputs, result) {
|
|
|
138
194
|
const hash = kernel.hashCode(f.wrapped, require_constants.HASH_CODE_MAX);
|
|
139
195
|
try {
|
|
140
196
|
const outBounds = kernel.uvBounds(f.wrapped);
|
|
141
|
-
const bestOrigin = findBestOriginMatch(kernel.surfaceNormal(f.wrapped, .5 * (outBounds.uMin + outBounds.uMax), .5 * (outBounds.vMin + outBounds.vMax)), kernel.surfaceCenterOfMass(f.wrapped), inputSigs);
|
|
197
|
+
const bestOrigin = findBestOriginMatch(kernel.surfaceNormal(f.wrapped, .5 * (outBounds.uMin + outBounds.uMax), .5 * (outBounds.vMin + outBounds.vMax)), kernel.surfaceCenterOfMass(f.wrapped), kernel.surfaceType(f.wrapped) === "plane", inputSigs);
|
|
142
198
|
if (bestOrigin !== void 0) resultMap.set(hash, bestOrigin);
|
|
143
199
|
} catch {}
|
|
144
200
|
}
|
|
@@ -390,7 +446,10 @@ function collectInputFaceHashes(inputs) {
|
|
|
390
446
|
const hashes = [];
|
|
391
447
|
for (const input of inputs) {
|
|
392
448
|
const faces = kernel.iterShapes(input.wrapped, "face");
|
|
393
|
-
for (const face of faces)
|
|
449
|
+
for (const face of faces) {
|
|
450
|
+
hashes.push(kernel.hashCode(face, require_constants.HASH_CODE_MAX));
|
|
451
|
+
kernel.dispose(face);
|
|
452
|
+
}
|
|
394
453
|
}
|
|
395
454
|
return hashes;
|
|
396
455
|
}
|
|
@@ -446,6 +505,8 @@ function propagateMetadataThroughRelocation(source, moved) {
|
|
|
446
505
|
if (sf === void 0 || mf === void 0) continue;
|
|
447
506
|
modified.set(kernel.hashCode(sf, require_constants.HASH_CODE_MAX), [kernel.hashCode(mf, require_constants.HASH_CODE_MAX)]);
|
|
448
507
|
}
|
|
508
|
+
for (const f of srcFaces) kernel.dispose(f);
|
|
509
|
+
for (const f of movedFaces) kernel.dispose(f);
|
|
449
510
|
propagateAllMetadata({
|
|
450
511
|
modified,
|
|
451
512
|
generated: /* @__PURE__ */ new Map(),
|
|
@@ -462,7 +523,7 @@ function propagateMetadataThroughRelocation(source, moved) {
|
|
|
462
523
|
function translate(shape, v) {
|
|
463
524
|
const inputFaceHashes = collectInputFaceHashes([shape]);
|
|
464
525
|
const { shape: resultShape, evolution } = require_shapeTypes.getKernel().translateWithHistory(shape.wrapped, v[0], v[1], v[2], inputFaceHashes, require_constants.HASH_CODE_MAX);
|
|
465
|
-
const result = require_shapeTypes.
|
|
526
|
+
const result = require_shapeTypes.castResultShape(resultShape);
|
|
466
527
|
propagateAllMetadata(evolution, [shape], result);
|
|
467
528
|
return result;
|
|
468
529
|
}
|
|
@@ -478,7 +539,7 @@ function rotate(shape, angle, position = [
|
|
|
478
539
|
]) {
|
|
479
540
|
const inputFaceHashes = collectInputFaceHashes([shape]);
|
|
480
541
|
const { shape: resultShape, evolution } = require_shapeTypes.getKernel().rotateWithHistory(shape.wrapped, angle * require_constants.DEG2RAD, inputFaceHashes, require_constants.HASH_CODE_MAX, direction, position);
|
|
481
|
-
const result = require_shapeTypes.
|
|
542
|
+
const result = require_shapeTypes.castResultShape(resultShape);
|
|
482
543
|
propagateAllMetadata(evolution, [shape], result);
|
|
483
544
|
return result;
|
|
484
545
|
}
|
|
@@ -494,7 +555,7 @@ function mirror(shape, planeNormal = [
|
|
|
494
555
|
]) {
|
|
495
556
|
const inputFaceHashes = collectInputFaceHashes([shape]);
|
|
496
557
|
const { shape: resultShape, evolution } = require_shapeTypes.getKernel().mirrorWithHistory(shape.wrapped, planeOrigin, planeNormal, inputFaceHashes, require_constants.HASH_CODE_MAX);
|
|
497
|
-
const result = require_shapeTypes.
|
|
558
|
+
const result = require_shapeTypes.castResultShape(resultShape);
|
|
498
559
|
propagateAllMetadata(evolution, [shape], result);
|
|
499
560
|
return result;
|
|
500
561
|
}
|
|
@@ -506,7 +567,7 @@ function scale(shape, factor, center = [
|
|
|
506
567
|
]) {
|
|
507
568
|
const inputFaceHashes = collectInputFaceHashes([shape]);
|
|
508
569
|
const { shape: resultShape, evolution } = require_shapeTypes.getKernel().scaleWithHistory(shape.wrapped, center, factor, inputFaceHashes, require_constants.HASH_CODE_MAX);
|
|
509
|
-
const result = require_shapeTypes.
|
|
570
|
+
const result = require_shapeTypes.castResultShape(resultShape);
|
|
510
571
|
propagateAllMetadata(evolution, [shape], result);
|
|
511
572
|
return result;
|
|
512
573
|
}
|
|
@@ -608,11 +669,11 @@ function applyMatrix(shape, matrix) {
|
|
|
608
669
|
if (isOrthogonalMatrix(linear)) {
|
|
609
670
|
const inputFaceHashes = collectInputFaceHashes([shape]);
|
|
610
671
|
const { shape: resultShape, evolution } = require_shapeTypes.getKernel().generalTransformWithHistory(shape.wrapped, linear, translation, true, inputFaceHashes, require_constants.HASH_CODE_MAX);
|
|
611
|
-
const result = require_shapeTypes.
|
|
672
|
+
const result = require_shapeTypes.castResultShape(resultShape);
|
|
612
673
|
propagateAllMetadata(evolution, [shape], result);
|
|
613
674
|
return require_errors.ok(result);
|
|
614
675
|
}
|
|
615
|
-
const result = require_shapeTypes.
|
|
676
|
+
const result = require_shapeTypes.castResultShape(require_shapeTypes.getKernel().generalTransformNonOrthogonal(shape.wrapped, linear, translation));
|
|
616
677
|
propagateMetadataByHash([shape], result);
|
|
617
678
|
return require_errors.ok(result);
|
|
618
679
|
/* v8 ignore stop */
|
|
@@ -661,7 +722,7 @@ function locate(shape, placement) {
|
|
|
661
722
|
const { trsf, cleanup } = composeTransforms("type" in placement ? [placement] : placement);
|
|
662
723
|
let moved;
|
|
663
724
|
try {
|
|
664
|
-
moved = require_shapeTypes.
|
|
725
|
+
moved = require_shapeTypes.castResultShape(require_shapeTypes.getKernel().locate(shape.wrapped, trsf));
|
|
665
726
|
} finally {
|
|
666
727
|
cleanup();
|
|
667
728
|
}
|
|
@@ -675,7 +736,7 @@ function locate(shape, placement) {
|
|
|
675
736
|
function transformCopy(shape, composed) {
|
|
676
737
|
const inputFaceHashes = collectInputFaceHashes([shape]);
|
|
677
738
|
const { shape: resultShape, evolution } = require_shapeTypes.getKernel().applyComposedTransformWithHistory(shape.wrapped, composed.trsf, inputFaceHashes, require_constants.HASH_CODE_MAX);
|
|
678
|
-
const result = require_shapeTypes.
|
|
739
|
+
const result = require_shapeTypes.castResultShape(resultShape);
|
|
679
740
|
propagateAllMetadata(evolution, [shape], result);
|
|
680
741
|
return result;
|
|
681
742
|
}
|
package/dist/shapeRef.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_refResolveFns = require("./refResolveFns-
|
|
2
|
+
const require_refResolveFns = require("./refResolveFns-DbTYd_Nj.cjs");
|
|
3
3
|
exports.assignRoles = require_refResolveFns.assignRoles;
|
|
4
4
|
exports.captureHint = require_refResolveFns.captureHint;
|
|
5
5
|
exports.createDerivedFaceRef = require_refResolveFns.createDerivedFaceRef;
|
package/dist/shapeRef.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as createRef, a as isVertexRef, b as defaultScorer, c as resolveRefParams, d as createVertexRef, f as resolveVertexRef, g as captureHint, h as assignRoles, i as isLineageRef, l as createDerivedFaceRef, m as resolveEdgeRef, n as isEdgeRef, o as resolveLineageRef, p as createEdgeRef, r as isFaceRef, s as resolveRefIn, t as isDerivedFaceRef, u as resolveDerivedFaceRef, v as resolveRef, y as updateRoles } from "./refResolveFns-
|
|
1
|
+
import { _ as createRef, a as isVertexRef, b as defaultScorer, c as resolveRefParams, d as createVertexRef, f as resolveVertexRef, g as captureHint, h as assignRoles, i as isLineageRef, l as createDerivedFaceRef, m as resolveEdgeRef, n as isEdgeRef, o as resolveLineageRef, p as createEdgeRef, r as isFaceRef, s as resolveRefIn, t as isDerivedFaceRef, u as resolveDerivedFaceRef, v as resolveRef, y as updateRoles } from "./refResolveFns-DL1zXF8u.js";
|
|
2
2
|
export { assignRoles, captureHint, createDerivedFaceRef, createEdgeRef, createRef, createVertexRef, defaultScorer, isDerivedFaceRef, isEdgeRef, isFaceRef, isLineageRef, isVertexRef, resolveDerivedFaceRef, resolveEdgeRef, resolveLineageRef, resolveRef, resolveRefIn, resolveRefParams, resolveVertexRef, updateRoles };
|