brepjs 18.114.0 → 18.115.1
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/brepjs.cjs +94 -1
- package/dist/brepjs.js +94 -1
- package/dist/{refResolveFns-CayDQeug.js → refResolveFns-hEOEcFZ8.js} +40 -17
- package/dist/{refResolveFns-BK5NSDFd.cjs → refResolveFns-pRVyjy35.cjs} +40 -17
- package/dist/shapeRef.cjs +1 -1
- package/dist/shapeRef.js +1 -1
- package/dist/topology/shapeRef/shapeRefFns.d.ts +9 -7
- package/package.json +1 -1
package/dist/brepjs.cjs
CHANGED
|
@@ -30,7 +30,7 @@ const require_loftFns = require("./loftFns-fpTmrIdd.cjs");
|
|
|
30
30
|
const require_cameraFns = require("./cameraFns-uo1sZbBT.cjs");
|
|
31
31
|
const require_textMetrics = require("./textMetrics-IC_IoI7l.cjs");
|
|
32
32
|
const require_adjacencyFns = require("./adjacencyFns-d8ZabkvX.cjs");
|
|
33
|
-
const require_refResolveFns = require("./refResolveFns-
|
|
33
|
+
const require_refResolveFns = require("./refResolveFns-pRVyjy35.cjs");
|
|
34
34
|
const require_workerPool = require("./workerPool-D30NsiIW.cjs");
|
|
35
35
|
const require_primitiveFns = require("./primitiveFns-DLIWtQWA.cjs");
|
|
36
36
|
//#region src/topology/shapeBooleans.ts
|
|
@@ -5837,6 +5837,76 @@ function cacheKey(node, env, kernelId, tolerance) {
|
|
|
5837
5837
|
const tolHash = tolerance === void 0 ? "d" : fnvMixNumber(fnvInit(), tolerance).toString(16);
|
|
5838
5838
|
return `${toHex(node.structuralHash)}:${kernelId}:${toHex(projHash)}:${tolHash}`;
|
|
5839
5839
|
}
|
|
5840
|
+
/**
|
|
5841
|
+
* Peel outer Translate nodes off `node`, accumulating their env-evaluated
|
|
5842
|
+
* offsets. Pure translations compose by addition, so the inner geometry is
|
|
5843
|
+
* placement-independent: it meshes once and the cached mesh is shifted per
|
|
5844
|
+
* placement instead of re-tessellating. Stops at the first non-Translate node
|
|
5845
|
+
* (or one whose offset can't be evaluated in `env`).
|
|
5846
|
+
*/
|
|
5847
|
+
function peelTranslate(node, env) {
|
|
5848
|
+
let inner = node;
|
|
5849
|
+
let ox = 0;
|
|
5850
|
+
let oy = 0;
|
|
5851
|
+
let oz = 0;
|
|
5852
|
+
while (inner.kind === "Translate") {
|
|
5853
|
+
const v = evalVec3(inner.vector, env, "evaluateMesh.peelTranslate");
|
|
5854
|
+
if (!v.ok) break;
|
|
5855
|
+
ox += v.value[0];
|
|
5856
|
+
oy += v.value[1];
|
|
5857
|
+
oz += v.value[2];
|
|
5858
|
+
inner = inner.target;
|
|
5859
|
+
}
|
|
5860
|
+
return {
|
|
5861
|
+
inner,
|
|
5862
|
+
offset: [
|
|
5863
|
+
ox,
|
|
5864
|
+
oy,
|
|
5865
|
+
oz
|
|
5866
|
+
]
|
|
5867
|
+
};
|
|
5868
|
+
}
|
|
5869
|
+
/** Shift every vertex of a mesh by `offset`; normals, UVs and triangles are unchanged. */
|
|
5870
|
+
function translateMesh(m, offset) {
|
|
5871
|
+
const [dx, dy, dz] = offset;
|
|
5872
|
+
if (dx === 0 && dy === 0 && dz === 0) return m;
|
|
5873
|
+
const vertices = new Float32Array(m.vertices.length);
|
|
5874
|
+
for (let i = 0; i < m.vertices.length; i += 3) {
|
|
5875
|
+
vertices[i] = (m.vertices[i] ?? 0) + dx;
|
|
5876
|
+
vertices[i + 1] = (m.vertices[i + 1] ?? 0) + dy;
|
|
5877
|
+
vertices[i + 2] = (m.vertices[i + 2] ?? 0) + dz;
|
|
5878
|
+
}
|
|
5879
|
+
return {
|
|
5880
|
+
...m,
|
|
5881
|
+
vertices
|
|
5882
|
+
};
|
|
5883
|
+
}
|
|
5884
|
+
/**
|
|
5885
|
+
* Re-key a reused inner mesh's face groups onto the PLACED shape. `locate` gives
|
|
5886
|
+
* moved faces location-dependent hashes, so the inner mesh's `faceId`s describe
|
|
5887
|
+
* the *unplaced* shape; remap them to the placed faces (1:1 by iteration order,
|
|
5888
|
+
* since `locate` shares the source TShape) so face picking and metadata lookup
|
|
5889
|
+
* resolve against the placed mesh. Origins are translation-invariant, so only
|
|
5890
|
+
* `faceId` changes.
|
|
5891
|
+
*
|
|
5892
|
+
* Takes pre-captured hash arrays (not shapes): a bounded shape cache can evict
|
|
5893
|
+
* and dispose one shape while the other is being evaluated, so the caller reads
|
|
5894
|
+
* each shape's face hashes immediately after evaluating it, never holding a
|
|
5895
|
+
* shape handle across the next `evaluate`.
|
|
5896
|
+
*/
|
|
5897
|
+
function relocateFaceGroups(faceGroups, innerHashes, placedHashes) {
|
|
5898
|
+
const remap = /* @__PURE__ */ new Map();
|
|
5899
|
+
const n = Math.min(innerHashes.length, placedHashes.length);
|
|
5900
|
+
for (let i = 0; i < n; i++) {
|
|
5901
|
+
const a = innerHashes[i];
|
|
5902
|
+
const b = placedHashes[i];
|
|
5903
|
+
if (a !== void 0 && b !== void 0) remap.set(a, b);
|
|
5904
|
+
}
|
|
5905
|
+
return faceGroups.map((g) => ({
|
|
5906
|
+
...g,
|
|
5907
|
+
faceId: remap.get(g.faceId) ?? g.faceId
|
|
5908
|
+
}));
|
|
5909
|
+
}
|
|
5840
5910
|
var Evaluator = class {
|
|
5841
5911
|
cache = /* @__PURE__ */ new Map();
|
|
5842
5912
|
refCounts = /* @__PURE__ */ new Map();
|
|
@@ -5913,6 +5983,29 @@ var Evaluator = class {
|
|
|
5913
5983
|
}
|
|
5914
5984
|
return require_errors.ok(cached);
|
|
5915
5985
|
}
|
|
5986
|
+
const { inner, offset } = peelTranslate(node, env);
|
|
5987
|
+
if (inner !== node) {
|
|
5988
|
+
const innerMesh = this.evaluateMesh(inner, env, meshOpts);
|
|
5989
|
+
if (!innerMesh.ok) return innerMesh;
|
|
5990
|
+
const innerShape = this.evaluate(inner, env);
|
|
5991
|
+
if (!innerShape.ok) return innerShape;
|
|
5992
|
+
const innerHashes = require_topologyQueryFns.getFaces(innerShape.value).map(require_shapeFns.getHashCode);
|
|
5993
|
+
const placedShape = this.evaluate(node, env);
|
|
5994
|
+
if (!placedShape.ok) return placedShape;
|
|
5995
|
+
const placedHashes = require_topologyQueryFns.getFaces(placedShape.value).map(require_shapeFns.getHashCode);
|
|
5996
|
+
const moved = translateMesh(innerMesh.value, offset);
|
|
5997
|
+
const faceGroups = relocateFaceGroups(moved.faceGroups, innerHashes, placedHashes);
|
|
5998
|
+
const placedSet = new Set(placedHashes);
|
|
5999
|
+
if (faceGroups.every((g) => placedSet.has(g.faceId))) {
|
|
6000
|
+
const placed = {
|
|
6001
|
+
...moved,
|
|
6002
|
+
faceGroups
|
|
6003
|
+
};
|
|
6004
|
+
this.meshCache.set(meshKey, placed);
|
|
6005
|
+
if (this.maxMeshCacheEntries !== void 0) this.trimMeshCache(this.maxMeshCacheEntries);
|
|
6006
|
+
return require_errors.ok(placed);
|
|
6007
|
+
}
|
|
6008
|
+
}
|
|
5916
6009
|
}
|
|
5917
6010
|
const shape = this.evaluate(node, env);
|
|
5918
6011
|
if (!shape.ok) return shape;
|
package/dist/brepjs.js
CHANGED
|
@@ -29,7 +29,7 @@ import { a as Sketch, c as compoundSketchLoft, d as sketchFace, f as sketchLoft,
|
|
|
29
29
|
import { a as makeProjectedEdges, i as projectEdges, n as cameraLookAt, r as createCamera, s as isProjectionPlane, t as cameraFromPlane } from "./cameraFns-bk9e0F-T.js";
|
|
30
30
|
import { n as textMetrics, r as sketchText, t as fontMetrics } from "./textMetrics-COGYk0LE.js";
|
|
31
31
|
import { a as sharedEdges, c as wiresOfFace, i as facesOfVertex, n as edgesOfFace, o as verticesOfEdge, r as facesOfEdge, s as verticesOfFace, t as adjacentFaces } from "./adjacencyFns-BYnyXXqt.js";
|
|
32
|
-
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-
|
|
32
|
+
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-hEOEcFZ8.js";
|
|
33
33
|
import { _ as isSuccessResponse, a as createWorkerClient, c as enqueueTask, d as rejectAll, f as isBatchRequest, g as isOperationRequest, h as isInitRequest, i as registerHandler, l as isEmpty$1, m as isErrorResponse, n as createOperationRegistry, o as createTaskQueue, p as isDisposeRequest, r as createWorkerHandler, s as dequeueTask, t as createWorkerPool, u as pendingCount } from "./workerPool-XcYX2UZ0.js";
|
|
34
34
|
import { C as threePointArc, D as wireLoop, E as wire, S as tangentArc, T as vertex, _ as polygon, a as circle, b as sphere$1, c as cylinder, d as ellipsoid, f as face, g as offsetFace, h as line, i as bsplineApprox, l as ellipse, m as helix, n as bezier, o as compound, p as filledFace, r as box, s as cone, t as addHoles, u as ellipseArc, v as sewShells, w as torus$1, x as subFace, y as solid } from "./primitiveFns-CBrOyk5S.js";
|
|
35
35
|
//#region \0rolldown/runtime.js
|
|
@@ -5840,6 +5840,76 @@ function cacheKey(node, env, kernelId, tolerance) {
|
|
|
5840
5840
|
const tolHash = tolerance === void 0 ? "d" : fnvMixNumber(fnvInit(), tolerance).toString(16);
|
|
5841
5841
|
return `${toHex(node.structuralHash)}:${kernelId}:${toHex(projHash)}:${tolHash}`;
|
|
5842
5842
|
}
|
|
5843
|
+
/**
|
|
5844
|
+
* Peel outer Translate nodes off `node`, accumulating their env-evaluated
|
|
5845
|
+
* offsets. Pure translations compose by addition, so the inner geometry is
|
|
5846
|
+
* placement-independent: it meshes once and the cached mesh is shifted per
|
|
5847
|
+
* placement instead of re-tessellating. Stops at the first non-Translate node
|
|
5848
|
+
* (or one whose offset can't be evaluated in `env`).
|
|
5849
|
+
*/
|
|
5850
|
+
function peelTranslate(node, env) {
|
|
5851
|
+
let inner = node;
|
|
5852
|
+
let ox = 0;
|
|
5853
|
+
let oy = 0;
|
|
5854
|
+
let oz = 0;
|
|
5855
|
+
while (inner.kind === "Translate") {
|
|
5856
|
+
const v = evalVec3(inner.vector, env, "evaluateMesh.peelTranslate");
|
|
5857
|
+
if (!v.ok) break;
|
|
5858
|
+
ox += v.value[0];
|
|
5859
|
+
oy += v.value[1];
|
|
5860
|
+
oz += v.value[2];
|
|
5861
|
+
inner = inner.target;
|
|
5862
|
+
}
|
|
5863
|
+
return {
|
|
5864
|
+
inner,
|
|
5865
|
+
offset: [
|
|
5866
|
+
ox,
|
|
5867
|
+
oy,
|
|
5868
|
+
oz
|
|
5869
|
+
]
|
|
5870
|
+
};
|
|
5871
|
+
}
|
|
5872
|
+
/** Shift every vertex of a mesh by `offset`; normals, UVs and triangles are unchanged. */
|
|
5873
|
+
function translateMesh(m, offset) {
|
|
5874
|
+
const [dx, dy, dz] = offset;
|
|
5875
|
+
if (dx === 0 && dy === 0 && dz === 0) return m;
|
|
5876
|
+
const vertices = new Float32Array(m.vertices.length);
|
|
5877
|
+
for (let i = 0; i < m.vertices.length; i += 3) {
|
|
5878
|
+
vertices[i] = (m.vertices[i] ?? 0) + dx;
|
|
5879
|
+
vertices[i + 1] = (m.vertices[i + 1] ?? 0) + dy;
|
|
5880
|
+
vertices[i + 2] = (m.vertices[i + 2] ?? 0) + dz;
|
|
5881
|
+
}
|
|
5882
|
+
return {
|
|
5883
|
+
...m,
|
|
5884
|
+
vertices
|
|
5885
|
+
};
|
|
5886
|
+
}
|
|
5887
|
+
/**
|
|
5888
|
+
* Re-key a reused inner mesh's face groups onto the PLACED shape. `locate` gives
|
|
5889
|
+
* moved faces location-dependent hashes, so the inner mesh's `faceId`s describe
|
|
5890
|
+
* the *unplaced* shape; remap them to the placed faces (1:1 by iteration order,
|
|
5891
|
+
* since `locate` shares the source TShape) so face picking and metadata lookup
|
|
5892
|
+
* resolve against the placed mesh. Origins are translation-invariant, so only
|
|
5893
|
+
* `faceId` changes.
|
|
5894
|
+
*
|
|
5895
|
+
* Takes pre-captured hash arrays (not shapes): a bounded shape cache can evict
|
|
5896
|
+
* and dispose one shape while the other is being evaluated, so the caller reads
|
|
5897
|
+
* each shape's face hashes immediately after evaluating it, never holding a
|
|
5898
|
+
* shape handle across the next `evaluate`.
|
|
5899
|
+
*/
|
|
5900
|
+
function relocateFaceGroups(faceGroups, innerHashes, placedHashes) {
|
|
5901
|
+
const remap = /* @__PURE__ */ new Map();
|
|
5902
|
+
const n = Math.min(innerHashes.length, placedHashes.length);
|
|
5903
|
+
for (let i = 0; i < n; i++) {
|
|
5904
|
+
const a = innerHashes[i];
|
|
5905
|
+
const b = placedHashes[i];
|
|
5906
|
+
if (a !== void 0 && b !== void 0) remap.set(a, b);
|
|
5907
|
+
}
|
|
5908
|
+
return faceGroups.map((g) => ({
|
|
5909
|
+
...g,
|
|
5910
|
+
faceId: remap.get(g.faceId) ?? g.faceId
|
|
5911
|
+
}));
|
|
5912
|
+
}
|
|
5843
5913
|
var Evaluator = class {
|
|
5844
5914
|
cache = /* @__PURE__ */ new Map();
|
|
5845
5915
|
refCounts = /* @__PURE__ */ new Map();
|
|
@@ -5916,6 +5986,29 @@ var Evaluator = class {
|
|
|
5916
5986
|
}
|
|
5917
5987
|
return ok(cached);
|
|
5918
5988
|
}
|
|
5989
|
+
const { inner, offset } = peelTranslate(node, env);
|
|
5990
|
+
if (inner !== node) {
|
|
5991
|
+
const innerMesh = this.evaluateMesh(inner, env, meshOpts);
|
|
5992
|
+
if (!innerMesh.ok) return innerMesh;
|
|
5993
|
+
const innerShape = this.evaluate(inner, env);
|
|
5994
|
+
if (!innerShape.ok) return innerShape;
|
|
5995
|
+
const innerHashes = getFaces(innerShape.value).map(getHashCode);
|
|
5996
|
+
const placedShape = this.evaluate(node, env);
|
|
5997
|
+
if (!placedShape.ok) return placedShape;
|
|
5998
|
+
const placedHashes = getFaces(placedShape.value).map(getHashCode);
|
|
5999
|
+
const moved = translateMesh(innerMesh.value, offset);
|
|
6000
|
+
const faceGroups = relocateFaceGroups(moved.faceGroups, innerHashes, placedHashes);
|
|
6001
|
+
const placedSet = new Set(placedHashes);
|
|
6002
|
+
if (faceGroups.every((g) => placedSet.has(g.faceId))) {
|
|
6003
|
+
const placed = {
|
|
6004
|
+
...moved,
|
|
6005
|
+
faceGroups
|
|
6006
|
+
};
|
|
6007
|
+
this.meshCache.set(meshKey, placed);
|
|
6008
|
+
if (this.maxMeshCacheEntries !== void 0) this.trimMeshCache(this.maxMeshCacheEntries);
|
|
6009
|
+
return ok(placed);
|
|
6010
|
+
}
|
|
6011
|
+
}
|
|
5919
6012
|
}
|
|
5920
6013
|
const shape = this.evaluate(node, env);
|
|
5921
6014
|
if (!shape.ok) return shape;
|
|
@@ -70,33 +70,56 @@ function boxRoleFromNormal(n) {
|
|
|
70
70
|
if (n[0] > AXIS_THRESHOLD) return "box:right";
|
|
71
71
|
if (n[0] < -.9) return "box:left";
|
|
72
72
|
}
|
|
73
|
+
/** Axial cap name for a Z-axis primitive: 'top' (+Z) / 'bottom' (-Z). */
|
|
74
|
+
function axialCapName(prefix, face) {
|
|
75
|
+
if (faceGeomType(face) !== "PLANE") return void 0;
|
|
76
|
+
const z = normalAt(face)[2];
|
|
77
|
+
if (z > AXIS_THRESHOLD) return `${prefix}:top`;
|
|
78
|
+
if (z < -.9) return `${prefix}:bottom`;
|
|
79
|
+
}
|
|
80
|
+
/** Semantic role for a Z-axis cylinder face: top/bottom caps + lateral wall. */
|
|
81
|
+
function cylinderRole(face) {
|
|
82
|
+
return faceGeomType(face) === "CYLINDRE" ? "cylinder:lateral" : axialCapName("cylinder", face);
|
|
83
|
+
}
|
|
84
|
+
/** Semantic role for a Z-axis cone/frustum face: top/bottom caps + lateral. */
|
|
85
|
+
function coneRole(face) {
|
|
86
|
+
return faceGeomType(face) === "CONE" ? "cone:lateral" : axialCapName("cone", face);
|
|
87
|
+
}
|
|
88
|
+
/** Semantic role for a sphere's single spherical face. */
|
|
89
|
+
function sphereRole(face) {
|
|
90
|
+
return faceGeomType(face) === "SPHERE" ? "sphere:surface" : void 0;
|
|
91
|
+
}
|
|
92
|
+
/** Per-primitive semantic face namers, keyed by operation type. */
|
|
93
|
+
var ROLE_ASSIGNERS = {
|
|
94
|
+
box: (face) => boxRoleFromNormal(normalAt(face)),
|
|
95
|
+
cylinder: cylinderRole,
|
|
96
|
+
cone: coneRole,
|
|
97
|
+
sphere: sphereRole
|
|
98
|
+
};
|
|
73
99
|
/**
|
|
74
|
-
* Auto-assign role names to
|
|
100
|
+
* Auto-assign role names to a shape's faces from its operation type.
|
|
75
101
|
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
102
|
+
* Known primitives get **semantic** names from face geometry — rebuild-stable
|
|
103
|
+
* across parameter edits that preserve orientation:
|
|
104
|
+
* - `box`: cardinal names by normal ('box:top'/'bottom'/'front'/'back'/'left'/'right').
|
|
105
|
+
* - `cylinder`/`cone` (Z-axis): 'top'/'bottom' caps + 'lateral' wall.
|
|
106
|
+
* - `sphere`: 'sphere:surface'.
|
|
81
107
|
*
|
|
82
|
-
*
|
|
108
|
+
* Faces a primitive namer doesn't recognize (a rotated box's non-cardinal faces),
|
|
109
|
+
* and every face of any other operation type, fall back to positional names
|
|
110
|
+
* ('opType:face_0', 'opType:face_1', ...) — so each face always gets a role.
|
|
83
111
|
*
|
|
84
112
|
* @returns Map from role name to its face hash codes (one at assignment time;
|
|
85
113
|
* a role accrues more hashes only later, when `updateRoles` tracks a split).
|
|
86
114
|
*/
|
|
87
115
|
function assignRoles(shape, operationType) {
|
|
88
|
-
const faces = getFaces(shape);
|
|
89
116
|
const roles = /* @__PURE__ */ new Map();
|
|
90
|
-
|
|
91
|
-
for (const face of faces) {
|
|
92
|
-
const role = boxRoleFromNormal(normalAt(face));
|
|
93
|
-
if (role !== void 0 && !roles.has(role)) roles.set(role, [getHashCode(face)]);
|
|
94
|
-
}
|
|
95
|
-
return roles;
|
|
96
|
-
}
|
|
117
|
+
const assigner = ROLE_ASSIGNERS[operationType];
|
|
97
118
|
let index = 0;
|
|
98
|
-
for (const face of
|
|
99
|
-
|
|
119
|
+
for (const face of getFaces(shape)) {
|
|
120
|
+
const semantic = assigner?.(face);
|
|
121
|
+
const role = semantic !== void 0 && !roles.has(semantic) ? semantic : `${operationType}:face_${index}`;
|
|
122
|
+
roles.set(role, [getHashCode(face)]);
|
|
100
123
|
index++;
|
|
101
124
|
}
|
|
102
125
|
return roles;
|
|
@@ -70,33 +70,56 @@ function boxRoleFromNormal(n) {
|
|
|
70
70
|
if (n[0] > AXIS_THRESHOLD) return "box:right";
|
|
71
71
|
if (n[0] < -.9) return "box:left";
|
|
72
72
|
}
|
|
73
|
+
/** Axial cap name for a Z-axis primitive: 'top' (+Z) / 'bottom' (-Z). */
|
|
74
|
+
function axialCapName(prefix, face) {
|
|
75
|
+
if (require_faceFns.faceGeomType(face) !== "PLANE") return void 0;
|
|
76
|
+
const z = require_faceFns.normalAt(face)[2];
|
|
77
|
+
if (z > AXIS_THRESHOLD) return `${prefix}:top`;
|
|
78
|
+
if (z < -.9) return `${prefix}:bottom`;
|
|
79
|
+
}
|
|
80
|
+
/** Semantic role for a Z-axis cylinder face: top/bottom caps + lateral wall. */
|
|
81
|
+
function cylinderRole(face) {
|
|
82
|
+
return require_faceFns.faceGeomType(face) === "CYLINDRE" ? "cylinder:lateral" : axialCapName("cylinder", face);
|
|
83
|
+
}
|
|
84
|
+
/** Semantic role for a Z-axis cone/frustum face: top/bottom caps + lateral. */
|
|
85
|
+
function coneRole(face) {
|
|
86
|
+
return require_faceFns.faceGeomType(face) === "CONE" ? "cone:lateral" : axialCapName("cone", face);
|
|
87
|
+
}
|
|
88
|
+
/** Semantic role for a sphere's single spherical face. */
|
|
89
|
+
function sphereRole(face) {
|
|
90
|
+
return require_faceFns.faceGeomType(face) === "SPHERE" ? "sphere:surface" : void 0;
|
|
91
|
+
}
|
|
92
|
+
/** Per-primitive semantic face namers, keyed by operation type. */
|
|
93
|
+
var ROLE_ASSIGNERS = {
|
|
94
|
+
box: (face) => boxRoleFromNormal(require_faceFns.normalAt(face)),
|
|
95
|
+
cylinder: cylinderRole,
|
|
96
|
+
cone: coneRole,
|
|
97
|
+
sphere: sphereRole
|
|
98
|
+
};
|
|
73
99
|
/**
|
|
74
|
-
* Auto-assign role names to
|
|
100
|
+
* Auto-assign role names to a shape's faces from its operation type.
|
|
75
101
|
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
102
|
+
* Known primitives get **semantic** names from face geometry — rebuild-stable
|
|
103
|
+
* across parameter edits that preserve orientation:
|
|
104
|
+
* - `box`: cardinal names by normal ('box:top'/'bottom'/'front'/'back'/'left'/'right').
|
|
105
|
+
* - `cylinder`/`cone` (Z-axis): 'top'/'bottom' caps + 'lateral' wall.
|
|
106
|
+
* - `sphere`: 'sphere:surface'.
|
|
81
107
|
*
|
|
82
|
-
*
|
|
108
|
+
* Faces a primitive namer doesn't recognize (a rotated box's non-cardinal faces),
|
|
109
|
+
* and every face of any other operation type, fall back to positional names
|
|
110
|
+
* ('opType:face_0', 'opType:face_1', ...) — so each face always gets a role.
|
|
83
111
|
*
|
|
84
112
|
* @returns Map from role name to its face hash codes (one at assignment time;
|
|
85
113
|
* a role accrues more hashes only later, when `updateRoles` tracks a split).
|
|
86
114
|
*/
|
|
87
115
|
function assignRoles(shape, operationType) {
|
|
88
|
-
const faces = require_topologyQueryFns.getFaces(shape);
|
|
89
116
|
const roles = /* @__PURE__ */ new Map();
|
|
90
|
-
|
|
91
|
-
for (const face of faces) {
|
|
92
|
-
const role = boxRoleFromNormal(require_faceFns.normalAt(face));
|
|
93
|
-
if (role !== void 0 && !roles.has(role)) roles.set(role, [require_shapeFns.getHashCode(face)]);
|
|
94
|
-
}
|
|
95
|
-
return roles;
|
|
96
|
-
}
|
|
117
|
+
const assigner = ROLE_ASSIGNERS[operationType];
|
|
97
118
|
let index = 0;
|
|
98
|
-
for (const face of
|
|
99
|
-
|
|
119
|
+
for (const face of require_topologyQueryFns.getFaces(shape)) {
|
|
120
|
+
const semantic = assigner?.(face);
|
|
121
|
+
const role = semantic !== void 0 && !roles.has(semantic) ? semantic : `${operationType}:face_${index}`;
|
|
122
|
+
roles.set(role, [require_shapeFns.getHashCode(face)]);
|
|
100
123
|
index++;
|
|
101
124
|
}
|
|
102
125
|
return roles;
|
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-pRVyjy35.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-hEOEcFZ8.js";
|
|
2
2
|
export { assignRoles, captureHint, createDerivedFaceRef, createEdgeRef, createRef, createVertexRef, defaultScorer, isDerivedFaceRef, isEdgeRef, isFaceRef, isLineageRef, isVertexRef, resolveDerivedFaceRef, resolveEdgeRef, resolveLineageRef, resolveRef, resolveRefIn, resolveRefParams, resolveVertexRef, updateRoles };
|
|
@@ -5,15 +5,17 @@ import { FaceScorer } from './scoring.js';
|
|
|
5
5
|
/** Snapshot the geometric properties of a face for later matching. */
|
|
6
6
|
export declare function captureHint(face: Face): GeometricHint;
|
|
7
7
|
/**
|
|
8
|
-
* Auto-assign role names to
|
|
8
|
+
* Auto-assign role names to a shape's faces from its operation type.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
10
|
+
* Known primitives get **semantic** names from face geometry — rebuild-stable
|
|
11
|
+
* across parameter edits that preserve orientation:
|
|
12
|
+
* - `box`: cardinal names by normal ('box:top'/'bottom'/'front'/'back'/'left'/'right').
|
|
13
|
+
* - `cylinder`/`cone` (Z-axis): 'top'/'bottom' caps + 'lateral' wall.
|
|
14
|
+
* - `sphere`: 'sphere:surface'.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
16
|
+
* Faces a primitive namer doesn't recognize (a rotated box's non-cardinal faces),
|
|
17
|
+
* and every face of any other operation type, fall back to positional names
|
|
18
|
+
* ('opType:face_0', 'opType:face_1', ...) — so each face always gets a role.
|
|
17
19
|
*
|
|
18
20
|
* @returns Map from role name to its face hash codes (one at assignment time;
|
|
19
21
|
* a role accrues more hashes only later, when `updateRoles` tracks a split).
|