brepjs 18.115.1 → 18.116.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 +132 -36
- package/dist/brepjs.js +132 -36
- package/dist/operations.cjs +1 -1
- package/dist/operations.js +1 -1
- package/dist/{refResolveFns-pRVyjy35.cjs → refResolveFns-BiEBAREW.cjs} +26 -7
- package/dist/{refResolveFns-hEOEcFZ8.js → refResolveFns-Ck6kJzLE.js} +26 -7
- package/dist/shapeRef.cjs +1 -1
- package/dist/shapeRef.js +1 -1
- package/dist/{threadFns-C8bErjVC.cjs → threadFns-BqWHWpea.cjs} +25 -2
- package/dist/{threadFns-bCOhVQLb.js → threadFns-KbYZu7Q9.js} +21 -4
- package/dist/topology/shapeRef/refResolveFns.d.ts +5 -4
- package/package.json +1 -1
package/dist/brepjs.cjs
CHANGED
|
@@ -17,7 +17,7 @@ const require_arrayAccess = require("./arrayAccess-e4H9cBfh.cjs");
|
|
|
17
17
|
const require_surfaceBuilders = require("./surfaceBuilders-UyyfZy8w.cjs");
|
|
18
18
|
const require_solidBuilders = require("./solidBuilders-DiUv_mD0.cjs");
|
|
19
19
|
const require_healingFns = require("./healingFns-xLJ6Cp_O.cjs");
|
|
20
|
-
const require_threadFns = require("./threadFns-
|
|
20
|
+
const require_threadFns = require("./threadFns-BqWHWpea.cjs");
|
|
21
21
|
const require_blueprintSketcher = require("./blueprintSketcher-RK-cH6ps.cjs");
|
|
22
22
|
const require_helpers = require("./helpers-BSLPCflF.cjs");
|
|
23
23
|
const require_drawFns = require("./drawFns-DNxs7PAT.cjs");
|
|
@@ -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-BiEBAREW.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,48 +5837,144 @@ 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
|
+
var IDENTITY_QUAT = [
|
|
5841
|
+
1,
|
|
5842
|
+
0,
|
|
5843
|
+
0,
|
|
5844
|
+
0
|
|
5845
|
+
];
|
|
5846
|
+
/** Resolve a Rotate node's angle/axis/center in `env`, applying the same
|
|
5847
|
+
* defaults as the evaluator (Z axis, origin pivot). Null if any free param
|
|
5848
|
+
* can't be evaluated, so the caller stops peeling there. */
|
|
5849
|
+
function evalRotateParams(node, env) {
|
|
5850
|
+
const a = evalScalar(node.angle, env, "evaluateMesh.peelRigid");
|
|
5851
|
+
if (!a.ok) return null;
|
|
5852
|
+
const axis = node.axis ? evalVec3(node.axis, env, "evaluateMesh.peelRigid") : require_errors.ok([
|
|
5853
|
+
0,
|
|
5854
|
+
0,
|
|
5855
|
+
1
|
|
5856
|
+
]);
|
|
5857
|
+
if (!axis.ok) return null;
|
|
5858
|
+
const center = node.at ? evalVec3(node.at, env, "evaluateMesh.peelRigid") : require_errors.ok([
|
|
5859
|
+
0,
|
|
5860
|
+
0,
|
|
5861
|
+
0
|
|
5862
|
+
]);
|
|
5863
|
+
if (!center.ok) return null;
|
|
5864
|
+
return {
|
|
5865
|
+
angle: a.value,
|
|
5866
|
+
axis: axis.value,
|
|
5867
|
+
center: center.value
|
|
5868
|
+
};
|
|
5869
|
+
}
|
|
5840
5870
|
/**
|
|
5841
|
-
* Peel outer
|
|
5842
|
-
*
|
|
5843
|
-
*
|
|
5844
|
-
*
|
|
5845
|
-
*
|
|
5871
|
+
* Peel outer rigid-motion nodes (Translate / Rotate) off `node`, composing them
|
|
5872
|
+
* into a single rotation + translation. A rigid motion shares its inner
|
|
5873
|
+
* geometry's tessellation — the shape path re-tags it via `locate` (#1633) — so
|
|
5874
|
+
* the inner meshes once and the cached mesh is moved per placement instead of
|
|
5875
|
+
* re-tessellating. Stops at the first non-rigid node (Scale/Mirror/boolean/…) or
|
|
5876
|
+
* one whose parameters can't be evaluated in `env`.
|
|
5877
|
+
*
|
|
5878
|
+
* Composition is outer∘inner: peeling outward, each node's local transform acts
|
|
5879
|
+
* on points the inner nodes already placed, so it post-multiplies the
|
|
5880
|
+
* accumulator. A pure-translation chain keeps the identity rotation, so the mesh
|
|
5881
|
+
* move below degenerates to the exact vertex-shift fast path (normals untouched).
|
|
5846
5882
|
*/
|
|
5847
|
-
function
|
|
5883
|
+
function peelRigid(node, env) {
|
|
5848
5884
|
let inner = node;
|
|
5849
|
-
let
|
|
5850
|
-
let
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5885
|
+
let rot = IDENTITY_QUAT;
|
|
5886
|
+
let trans = [
|
|
5887
|
+
0,
|
|
5888
|
+
0,
|
|
5889
|
+
0
|
|
5890
|
+
];
|
|
5891
|
+
for (;;) if (inner.kind === "Translate") {
|
|
5892
|
+
const v = evalVec3(inner.vector, env, "evaluateMesh.peelRigid");
|
|
5854
5893
|
if (!v.ok) break;
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5894
|
+
const rv = require_threadFns.quatRotate(rot, v.value);
|
|
5895
|
+
trans = [
|
|
5896
|
+
trans[0] + rv[0],
|
|
5897
|
+
trans[1] + rv[1],
|
|
5898
|
+
trans[2] + rv[2]
|
|
5899
|
+
];
|
|
5858
5900
|
inner = inner.target;
|
|
5859
|
-
}
|
|
5901
|
+
} else if (inner.kind === "Rotate") {
|
|
5902
|
+
const p = evalRotateParams(inner, env);
|
|
5903
|
+
if (!p) break;
|
|
5904
|
+
const r = require_threadFns.quatFromAxisAngle(p.axis, p.angle * Math.PI / 180);
|
|
5905
|
+
const newRot = require_threadFns.quatMultiply(rot, r);
|
|
5906
|
+
const rotC = require_threadFns.quatRotate(rot, p.center);
|
|
5907
|
+
const newRotC = require_threadFns.quatRotate(newRot, p.center);
|
|
5908
|
+
trans = [
|
|
5909
|
+
trans[0] + rotC[0] - newRotC[0],
|
|
5910
|
+
trans[1] + rotC[1] - newRotC[1],
|
|
5911
|
+
trans[2] + rotC[2] - newRotC[2]
|
|
5912
|
+
];
|
|
5913
|
+
rot = newRot;
|
|
5914
|
+
inner = inner.target;
|
|
5915
|
+
} else break;
|
|
5860
5916
|
return {
|
|
5861
5917
|
inner,
|
|
5862
|
-
|
|
5863
|
-
|
|
5864
|
-
oy,
|
|
5865
|
-
oz
|
|
5866
|
-
]
|
|
5918
|
+
rot,
|
|
5919
|
+
trans
|
|
5867
5920
|
};
|
|
5868
5921
|
}
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5922
|
+
function isIdentityQuat(q) {
|
|
5923
|
+
return q[0] === 1 && q[1] === 0 && q[2] === 0 && q[3] === 0;
|
|
5924
|
+
}
|
|
5925
|
+
/**
|
|
5926
|
+
* Write `src` (flat xyz) rigidly transformed by quaternion (qw,qx,qy,qz) then
|
|
5927
|
+
* translation (tx,ty,tz) into `dst`. The quaternion-rotate math is inlined with
|
|
5928
|
+
* scalar locals — no per-vertex array allocation — because this runs once per
|
|
5929
|
+
* mesh vertex/normal and helper-allocated vector math regressed the gridfinity
|
|
5930
|
+
* benchmark 17% (see `utils/vec3.ts`). Pass zero translation for normals.
|
|
5931
|
+
*/
|
|
5932
|
+
function rotateXyzBuffer(dst, src, qw, qx, qy, qz, tx, ty, tz) {
|
|
5933
|
+
for (let i = 0; i < src.length; i += 3) {
|
|
5934
|
+
const vx = src[i] ?? 0;
|
|
5935
|
+
const vy = src[i + 1] ?? 0;
|
|
5936
|
+
const vz = src[i + 2] ?? 0;
|
|
5937
|
+
const cx = 2 * (qy * vz - qz * vy);
|
|
5938
|
+
const cy = 2 * (qz * vx - qx * vz);
|
|
5939
|
+
const cz = 2 * (qx * vy - qy * vx);
|
|
5940
|
+
dst[i] = vx + qw * cx + (qy * cz - qz * cy) + tx;
|
|
5941
|
+
dst[i + 1] = vy + qw * cy + (qz * cx - qx * cz) + ty;
|
|
5942
|
+
dst[i + 2] = vz + qw * cz + (qx * cy - qy * cx) + tz;
|
|
5878
5943
|
}
|
|
5944
|
+
}
|
|
5945
|
+
/**
|
|
5946
|
+
* Apply a rigid motion to a mesh: vertices get the rotation then translation,
|
|
5947
|
+
* normals get the rotation only (a unit rotation preserves length, so no
|
|
5948
|
+
* renormalization). UVs and triangles are motion-invariant. A pure translation
|
|
5949
|
+
* (identity rotation) keeps the source normals array by reference and only
|
|
5950
|
+
* shifts vertices — the exact previous translation-only fast path.
|
|
5951
|
+
*/
|
|
5952
|
+
function transformMeshRigid(m, rot, trans) {
|
|
5953
|
+
const [tx, ty, tz] = trans;
|
|
5954
|
+
const pureTranslation = isIdentityQuat(rot);
|
|
5955
|
+
if (pureTranslation && tx === 0 && ty === 0 && tz === 0) return m;
|
|
5956
|
+
const src = m.vertices;
|
|
5957
|
+
const vertices = new Float32Array(src.length);
|
|
5958
|
+
if (pureTranslation) {
|
|
5959
|
+
for (let i = 0; i < src.length; i += 3) {
|
|
5960
|
+
vertices[i] = (src[i] ?? 0) + tx;
|
|
5961
|
+
vertices[i + 1] = (src[i + 1] ?? 0) + ty;
|
|
5962
|
+
vertices[i + 2] = (src[i + 2] ?? 0) + tz;
|
|
5963
|
+
}
|
|
5964
|
+
return {
|
|
5965
|
+
...m,
|
|
5966
|
+
vertices
|
|
5967
|
+
};
|
|
5968
|
+
}
|
|
5969
|
+
const [qw, qx, qy, qz] = rot;
|
|
5970
|
+
rotateXyzBuffer(vertices, src, qw, qx, qy, qz, tx, ty, tz);
|
|
5971
|
+
const sn = m.normals;
|
|
5972
|
+
const normals = new Float32Array(sn.length);
|
|
5973
|
+
rotateXyzBuffer(normals, sn, qw, qx, qy, qz, 0, 0, 0);
|
|
5879
5974
|
return {
|
|
5880
5975
|
...m,
|
|
5881
|
-
vertices
|
|
5976
|
+
vertices,
|
|
5977
|
+
normals
|
|
5882
5978
|
};
|
|
5883
5979
|
}
|
|
5884
5980
|
/**
|
|
@@ -5886,8 +5982,8 @@ function translateMesh(m, offset) {
|
|
|
5886
5982
|
* moved faces location-dependent hashes, so the inner mesh's `faceId`s describe
|
|
5887
5983
|
* the *unplaced* shape; remap them to the placed faces (1:1 by iteration order,
|
|
5888
5984
|
* since `locate` shares the source TShape) so face picking and metadata lookup
|
|
5889
|
-
* resolve against the placed mesh. Origins are
|
|
5890
|
-
* `faceId` changes.
|
|
5985
|
+
* resolve against the placed mesh. Origins are boolean-lineage tags, invariant
|
|
5986
|
+
* under any rigid motion, so only `faceId` changes.
|
|
5891
5987
|
*
|
|
5892
5988
|
* Takes pre-captured hash arrays (not shapes): a bounded shape cache can evict
|
|
5893
5989
|
* and dispose one shape while the other is being evaluated, so the caller reads
|
|
@@ -5983,7 +6079,7 @@ var Evaluator = class {
|
|
|
5983
6079
|
}
|
|
5984
6080
|
return require_errors.ok(cached);
|
|
5985
6081
|
}
|
|
5986
|
-
const { inner,
|
|
6082
|
+
const { inner, rot, trans } = peelRigid(node, env);
|
|
5987
6083
|
if (inner !== node) {
|
|
5988
6084
|
const innerMesh = this.evaluateMesh(inner, env, meshOpts);
|
|
5989
6085
|
if (!innerMesh.ok) return innerMesh;
|
|
@@ -5993,7 +6089,7 @@ var Evaluator = class {
|
|
|
5993
6089
|
const placedShape = this.evaluate(node, env);
|
|
5994
6090
|
if (!placedShape.ok) return placedShape;
|
|
5995
6091
|
const placedHashes = require_topologyQueryFns.getFaces(placedShape.value).map(require_shapeFns.getHashCode);
|
|
5996
|
-
const moved =
|
|
6092
|
+
const moved = transformMeshRigid(innerMesh.value, rot, trans);
|
|
5997
6093
|
const faceGroups = relocateFaceGroups(moved.faceGroups, innerHashes, placedHashes);
|
|
5998
6094
|
const placedSet = new Set(placedHashes);
|
|
5999
6095
|
if (faceGroups.every((g) => placedSet.has(g.faceId))) {
|
package/dist/brepjs.js
CHANGED
|
@@ -15,7 +15,7 @@ import { n as getAtOrThrow, r as lastOrThrow, t as firstOrThrow } from "./arrayA
|
|
|
15
15
|
import { _ as makeThreePointArc, d as makeCircle, h as makeLine, l as makeBSplineInterpolation, n as fill, r as makeFace, s as assembleWire } from "./surfaceBuilders-rkE-jE90.js";
|
|
16
16
|
import { _ as section$1, b as split$1, d as booleanPipeline, f as cut$2, g as intersect$2, h as fuseAll$2, m as fuse$2, p as cutAll$2, r as makeCylinder, t as makeCompound, v as sectionToFace$1, y as slice$1 } from "./solidBuilders-C32wXQWG.js";
|
|
17
17
|
import { A as toBufferGeometryData, C as shellWithEvolution, D as getNurbsCurveData, E as fuseAllBisect, M as toLODGeometryData, N as toLODGeometryLevels, O as getNurbsSurfaceData, P as toLineGeometryData, S as intersectWithEvolution, T as cutAllBisect, _ as positionOnCurve, a as healFace, b as filletWithEvolution, c as isValid$1, d as draft$1, f as fillet$1, g as variableFillet, h as thicken$1, i as heal$1, j as toGroupedBufferGeometryData, k as chamferDistAngle, l as solidFromShell, m as shell$1, n as fixSelfIntersection, o as healSolid, p as offset$1, r as fixShape, s as healWire, t as autoHeal, u as chamfer$1, v as chamferWithEvolution, w as checkBoolean, x as fuseWithEvolution, y as cutWithEvolution } from "./healingFns-2TJHHDg5.js";
|
|
18
|
-
import { A as setJointValue, B as
|
|
18
|
+
import { A as setJointValue, B as createAssemblyNode, C as cylindricalJoint, D as planarJoint, E as mechanismDOF, F as quatMultiply, G as circularPattern, H as removeChild, I as quatRotate, J as exportAssemblySTEP, K as gridPattern, L as addChild, M as sphericalJoint, N as quatFromAxisAngle, O as prismaticJoint, P as quatFromTo, R as collectShapes, S as addJoint, T as jointTransform, U as updateNode, V as findNode, W as walkAssembly, Y as createAssembly, _ as exportURDF, a as deserializeHistory, b as inverseKinematics, c as modifyStep, d as replayFrom, f as replayHistory, g as undoLast, h as stepsFrom, i as createRegistry, j as setJointValues, k as revoluteJoint, l as registerOperation, m as stepCount, n as addStep, o as findStep, p as serializeHistory, q as linearPattern, r as createHistory, s as getShape, t as thread, u as registerShape, v as importURDF, w as forwardKinematics, x as jointTrajectory, y as jointsFromDH, z as countNodes } from "./threadFns-KbYZu7Q9.js";
|
|
19
19
|
import { n as BaseSketcher2d, r as organiseBlueprints, t as BlueprintSketcher } from "./blueprintSketcher-7rtwqUHZ.js";
|
|
20
20
|
import { a as createTypedFinder, i as wireFinder, n as edgeFinder, r as faceFinder, t as getSingleFace } from "./helpers-DhJwFrkC.js";
|
|
21
21
|
import { A as sketchEllipse, D as makeBaseBox, E as deserializeDrawing, F as sketchRectangle, I as sketchRoundedRectangle, L as FaceSketcher, M as sketchHelix, N as sketchParametricFunction, O as polysideInnerRadius, P as sketchPolysides, R as Sketcher, S as drawText, _ as drawPolysides, a as drawingIntersect, b as drawSingleCircle, c as rotateDrawing, d as drawFaceOutline, f as drawProjection, g as drawPointsInterpolation, h as drawParametricFunction, i as drawingFuse, j as sketchFaceOffset, k as sketchCircle, l as scaleDrawing, m as drawEllipse, n as drawingCut, o as drawingToSketchOnPlane, p as drawCircle, r as drawingFillet, s as mirrorDrawing, t as drawingChamfer, u as translateDrawing, v as drawRectangle, w as draw, x as drawSingleEllipse, y as drawRoundedRectangle } from "./drawFns-SQIBls6p.js";
|
|
@@ -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-Ck6kJzLE.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,48 +5840,144 @@ 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
|
+
var IDENTITY_QUAT = [
|
|
5844
|
+
1,
|
|
5845
|
+
0,
|
|
5846
|
+
0,
|
|
5847
|
+
0
|
|
5848
|
+
];
|
|
5849
|
+
/** Resolve a Rotate node's angle/axis/center in `env`, applying the same
|
|
5850
|
+
* defaults as the evaluator (Z axis, origin pivot). Null if any free param
|
|
5851
|
+
* can't be evaluated, so the caller stops peeling there. */
|
|
5852
|
+
function evalRotateParams(node, env) {
|
|
5853
|
+
const a = evalScalar(node.angle, env, "evaluateMesh.peelRigid");
|
|
5854
|
+
if (!a.ok) return null;
|
|
5855
|
+
const axis = node.axis ? evalVec3(node.axis, env, "evaluateMesh.peelRigid") : ok([
|
|
5856
|
+
0,
|
|
5857
|
+
0,
|
|
5858
|
+
1
|
|
5859
|
+
]);
|
|
5860
|
+
if (!axis.ok) return null;
|
|
5861
|
+
const center = node.at ? evalVec3(node.at, env, "evaluateMesh.peelRigid") : ok([
|
|
5862
|
+
0,
|
|
5863
|
+
0,
|
|
5864
|
+
0
|
|
5865
|
+
]);
|
|
5866
|
+
if (!center.ok) return null;
|
|
5867
|
+
return {
|
|
5868
|
+
angle: a.value,
|
|
5869
|
+
axis: axis.value,
|
|
5870
|
+
center: center.value
|
|
5871
|
+
};
|
|
5872
|
+
}
|
|
5843
5873
|
/**
|
|
5844
|
-
* Peel outer
|
|
5845
|
-
*
|
|
5846
|
-
*
|
|
5847
|
-
*
|
|
5848
|
-
*
|
|
5874
|
+
* Peel outer rigid-motion nodes (Translate / Rotate) off `node`, composing them
|
|
5875
|
+
* into a single rotation + translation. A rigid motion shares its inner
|
|
5876
|
+
* geometry's tessellation — the shape path re-tags it via `locate` (#1633) — so
|
|
5877
|
+
* the inner meshes once and the cached mesh is moved per placement instead of
|
|
5878
|
+
* re-tessellating. Stops at the first non-rigid node (Scale/Mirror/boolean/…) or
|
|
5879
|
+
* one whose parameters can't be evaluated in `env`.
|
|
5880
|
+
*
|
|
5881
|
+
* Composition is outer∘inner: peeling outward, each node's local transform acts
|
|
5882
|
+
* on points the inner nodes already placed, so it post-multiplies the
|
|
5883
|
+
* accumulator. A pure-translation chain keeps the identity rotation, so the mesh
|
|
5884
|
+
* move below degenerates to the exact vertex-shift fast path (normals untouched).
|
|
5849
5885
|
*/
|
|
5850
|
-
function
|
|
5886
|
+
function peelRigid(node, env) {
|
|
5851
5887
|
let inner = node;
|
|
5852
|
-
let
|
|
5853
|
-
let
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5888
|
+
let rot = IDENTITY_QUAT;
|
|
5889
|
+
let trans = [
|
|
5890
|
+
0,
|
|
5891
|
+
0,
|
|
5892
|
+
0
|
|
5893
|
+
];
|
|
5894
|
+
for (;;) if (inner.kind === "Translate") {
|
|
5895
|
+
const v = evalVec3(inner.vector, env, "evaluateMesh.peelRigid");
|
|
5857
5896
|
if (!v.ok) break;
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5897
|
+
const rv = quatRotate(rot, v.value);
|
|
5898
|
+
trans = [
|
|
5899
|
+
trans[0] + rv[0],
|
|
5900
|
+
trans[1] + rv[1],
|
|
5901
|
+
trans[2] + rv[2]
|
|
5902
|
+
];
|
|
5861
5903
|
inner = inner.target;
|
|
5862
|
-
}
|
|
5904
|
+
} else if (inner.kind === "Rotate") {
|
|
5905
|
+
const p = evalRotateParams(inner, env);
|
|
5906
|
+
if (!p) break;
|
|
5907
|
+
const r = quatFromAxisAngle(p.axis, p.angle * Math.PI / 180);
|
|
5908
|
+
const newRot = quatMultiply(rot, r);
|
|
5909
|
+
const rotC = quatRotate(rot, p.center);
|
|
5910
|
+
const newRotC = quatRotate(newRot, p.center);
|
|
5911
|
+
trans = [
|
|
5912
|
+
trans[0] + rotC[0] - newRotC[0],
|
|
5913
|
+
trans[1] + rotC[1] - newRotC[1],
|
|
5914
|
+
trans[2] + rotC[2] - newRotC[2]
|
|
5915
|
+
];
|
|
5916
|
+
rot = newRot;
|
|
5917
|
+
inner = inner.target;
|
|
5918
|
+
} else break;
|
|
5863
5919
|
return {
|
|
5864
5920
|
inner,
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
oy,
|
|
5868
|
-
oz
|
|
5869
|
-
]
|
|
5921
|
+
rot,
|
|
5922
|
+
trans
|
|
5870
5923
|
};
|
|
5871
5924
|
}
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5925
|
+
function isIdentityQuat(q) {
|
|
5926
|
+
return q[0] === 1 && q[1] === 0 && q[2] === 0 && q[3] === 0;
|
|
5927
|
+
}
|
|
5928
|
+
/**
|
|
5929
|
+
* Write `src` (flat xyz) rigidly transformed by quaternion (qw,qx,qy,qz) then
|
|
5930
|
+
* translation (tx,ty,tz) into `dst`. The quaternion-rotate math is inlined with
|
|
5931
|
+
* scalar locals — no per-vertex array allocation — because this runs once per
|
|
5932
|
+
* mesh vertex/normal and helper-allocated vector math regressed the gridfinity
|
|
5933
|
+
* benchmark 17% (see `utils/vec3.ts`). Pass zero translation for normals.
|
|
5934
|
+
*/
|
|
5935
|
+
function rotateXyzBuffer(dst, src, qw, qx, qy, qz, tx, ty, tz) {
|
|
5936
|
+
for (let i = 0; i < src.length; i += 3) {
|
|
5937
|
+
const vx = src[i] ?? 0;
|
|
5938
|
+
const vy = src[i + 1] ?? 0;
|
|
5939
|
+
const vz = src[i + 2] ?? 0;
|
|
5940
|
+
const cx = 2 * (qy * vz - qz * vy);
|
|
5941
|
+
const cy = 2 * (qz * vx - qx * vz);
|
|
5942
|
+
const cz = 2 * (qx * vy - qy * vx);
|
|
5943
|
+
dst[i] = vx + qw * cx + (qy * cz - qz * cy) + tx;
|
|
5944
|
+
dst[i + 1] = vy + qw * cy + (qz * cx - qx * cz) + ty;
|
|
5945
|
+
dst[i + 2] = vz + qw * cz + (qx * cy - qy * cx) + tz;
|
|
5881
5946
|
}
|
|
5947
|
+
}
|
|
5948
|
+
/**
|
|
5949
|
+
* Apply a rigid motion to a mesh: vertices get the rotation then translation,
|
|
5950
|
+
* normals get the rotation only (a unit rotation preserves length, so no
|
|
5951
|
+
* renormalization). UVs and triangles are motion-invariant. A pure translation
|
|
5952
|
+
* (identity rotation) keeps the source normals array by reference and only
|
|
5953
|
+
* shifts vertices — the exact previous translation-only fast path.
|
|
5954
|
+
*/
|
|
5955
|
+
function transformMeshRigid(m, rot, trans) {
|
|
5956
|
+
const [tx, ty, tz] = trans;
|
|
5957
|
+
const pureTranslation = isIdentityQuat(rot);
|
|
5958
|
+
if (pureTranslation && tx === 0 && ty === 0 && tz === 0) return m;
|
|
5959
|
+
const src = m.vertices;
|
|
5960
|
+
const vertices = new Float32Array(src.length);
|
|
5961
|
+
if (pureTranslation) {
|
|
5962
|
+
for (let i = 0; i < src.length; i += 3) {
|
|
5963
|
+
vertices[i] = (src[i] ?? 0) + tx;
|
|
5964
|
+
vertices[i + 1] = (src[i + 1] ?? 0) + ty;
|
|
5965
|
+
vertices[i + 2] = (src[i + 2] ?? 0) + tz;
|
|
5966
|
+
}
|
|
5967
|
+
return {
|
|
5968
|
+
...m,
|
|
5969
|
+
vertices
|
|
5970
|
+
};
|
|
5971
|
+
}
|
|
5972
|
+
const [qw, qx, qy, qz] = rot;
|
|
5973
|
+
rotateXyzBuffer(vertices, src, qw, qx, qy, qz, tx, ty, tz);
|
|
5974
|
+
const sn = m.normals;
|
|
5975
|
+
const normals = new Float32Array(sn.length);
|
|
5976
|
+
rotateXyzBuffer(normals, sn, qw, qx, qy, qz, 0, 0, 0);
|
|
5882
5977
|
return {
|
|
5883
5978
|
...m,
|
|
5884
|
-
vertices
|
|
5979
|
+
vertices,
|
|
5980
|
+
normals
|
|
5885
5981
|
};
|
|
5886
5982
|
}
|
|
5887
5983
|
/**
|
|
@@ -5889,8 +5985,8 @@ function translateMesh(m, offset) {
|
|
|
5889
5985
|
* moved faces location-dependent hashes, so the inner mesh's `faceId`s describe
|
|
5890
5986
|
* the *unplaced* shape; remap them to the placed faces (1:1 by iteration order,
|
|
5891
5987
|
* since `locate` shares the source TShape) so face picking and metadata lookup
|
|
5892
|
-
* resolve against the placed mesh. Origins are
|
|
5893
|
-
* `faceId` changes.
|
|
5988
|
+
* resolve against the placed mesh. Origins are boolean-lineage tags, invariant
|
|
5989
|
+
* under any rigid motion, so only `faceId` changes.
|
|
5894
5990
|
*
|
|
5895
5991
|
* Takes pre-captured hash arrays (not shapes): a bounded shape cache can evict
|
|
5896
5992
|
* and dispose one shape while the other is being evaluated, so the caller reads
|
|
@@ -5986,7 +6082,7 @@ var Evaluator = class {
|
|
|
5986
6082
|
}
|
|
5987
6083
|
return ok(cached);
|
|
5988
6084
|
}
|
|
5989
|
-
const { inner,
|
|
6085
|
+
const { inner, rot, trans } = peelRigid(node, env);
|
|
5990
6086
|
if (inner !== node) {
|
|
5991
6087
|
const innerMesh = this.evaluateMesh(inner, env, meshOpts);
|
|
5992
6088
|
if (!innerMesh.ok) return innerMesh;
|
|
@@ -5996,7 +6092,7 @@ var Evaluator = class {
|
|
|
5996
6092
|
const placedShape = this.evaluate(node, env);
|
|
5997
6093
|
if (!placedShape.ok) return placedShape;
|
|
5998
6094
|
const placedHashes = getFaces(placedShape.value).map(getHashCode);
|
|
5999
|
-
const moved =
|
|
6095
|
+
const moved = transformMeshRigid(innerMesh.value, rot, trans);
|
|
6000
6096
|
const faceGroups = relocateFaceGroups(moved.faceGroups, innerHashes, placedHashes);
|
|
6001
6097
|
const placedSet = new Set(placedHashes);
|
|
6002
6098
|
if (faceGroups.every((g) => placedSet.has(g.faceId))) {
|
package/dist/operations.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_threadFns = require("./threadFns-
|
|
2
|
+
const require_threadFns = require("./threadFns-BqWHWpea.cjs");
|
|
3
3
|
const require_loftFns = require("./loftFns-fpTmrIdd.cjs");
|
|
4
4
|
exports.addChild = require_threadFns.addChild;
|
|
5
5
|
exports.addJoint = require_threadFns.addJoint;
|
package/dist/operations.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { A as setJointValue, B as
|
|
1
|
+
import { A as setJointValue, B as createAssemblyNode, C as cylindricalJoint, D as planarJoint, E as mechanismDOF, G as circularPattern, H as removeChild, J as exportAssemblySTEP, K as gridPattern, L as addChild, M as sphericalJoint, O as prismaticJoint, R as collectShapes, S as addJoint, T as jointTransform, U as updateNode, V as findNode, W as walkAssembly, Y as createAssembly, _ as exportURDF, b as inverseKinematics, c as modifyStep, d as replayFrom, f as replayHistory, g as undoLast, h as stepsFrom, i as createRegistry, j as setJointValues, k as revoluteJoint, l as registerOperation, m as stepCount, n as addStep, o as findStep, q as linearPattern, r as createHistory, s as getShape, t as thread, u as registerShape, v as importURDF, w as forwardKinematics, x as jointTrajectory, y as jointsFromDH, z as countNodes } from "./threadFns-KbYZu7Q9.js";
|
|
2
2
|
import { d as twistExtrude, l as supportExtrude, o as complexExtrude, u as sweep } from "./loftFns-CmShFQlv.js";
|
|
3
3
|
export { addChild, addJoint, addStep, circularPattern, collectShapes, complexExtrude, countNodes, createAssembly, createAssemblyNode, createHistory, createRegistry, cylindricalJoint, exportAssemblySTEP, exportURDF, findNode, findStep, forwardKinematics, getShape as getHistoryShape, gridPattern, importURDF, inverseKinematics, jointTrajectory, jointTransform, jointsFromDH, linearPattern, mechanismDOF, modifyStep, planarJoint, prismaticJoint, registerOperation, registerShape, removeChild, replayFrom, replayHistory, revoluteJoint, setJointValue, setJointValues, sphericalJoint, stepCount, stepsFrom, supportExtrude, sweep, thread, twistExtrude, undoLast, updateNode, walkAssembly };
|
|
@@ -739,19 +739,38 @@ function resolveRefIn(ref, shape) {
|
|
|
739
739
|
return resolveLineageRef(ref, rolesFor(ref, shape, /* @__PURE__ */ new Map()), shape);
|
|
740
740
|
}
|
|
741
741
|
/**
|
|
742
|
+
* A plain options object worth recursing into for nested refs — a literal `{}`
|
|
743
|
+
* (or null-prototype) that isn't a lineage ref, a shape handle, or a Date/Map/
|
|
744
|
+
* class instance (which `Object.entries` would silently flatten away).
|
|
745
|
+
*/
|
|
746
|
+
function isPlainOptions(value) {
|
|
747
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
748
|
+
const proto = Object.getPrototypeOf(value);
|
|
749
|
+
if (proto !== Object.prototype && proto !== null) return false;
|
|
750
|
+
return !("wrapped" in value);
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
742
753
|
* Replace every lineage ref in an operation's params with the live entity it
|
|
743
|
-
* resolves to in `shape`, recursing into arrays (
|
|
744
|
-
*
|
|
745
|
-
* re-derived once per `origin` and
|
|
746
|
-
* replay engine pass stable entity
|
|
754
|
+
* resolves to in `shape`, recursing into arrays (a fillet's edge list) and
|
|
755
|
+
* nested plain objects (a `{ selection: { edge } }` options bag). Refs that
|
|
756
|
+
* can't resolve are left as-is. Role tables are re-derived once per `origin` and
|
|
757
|
+
* reused across the whole params map. Lets a replay engine pass stable entity
|
|
758
|
+
* selections that survive upstream edits.
|
|
747
759
|
*/
|
|
748
760
|
function resolveRefParams(params, shape) {
|
|
749
761
|
const roleCache = /* @__PURE__ */ new Map();
|
|
750
762
|
const resolveValue = (value) => {
|
|
763
|
+
if (isLineageRef(value)) {
|
|
764
|
+
const res = resolveLineageRef(value, rolesFor(value, shape, roleCache), shape);
|
|
765
|
+
return res.ok ? res.entity : value;
|
|
766
|
+
}
|
|
751
767
|
if (Array.isArray(value)) return value.map(resolveValue);
|
|
752
|
-
if (
|
|
753
|
-
|
|
754
|
-
|
|
768
|
+
if (isPlainOptions(value)) {
|
|
769
|
+
const nested = {};
|
|
770
|
+
for (const [k, v] of Object.entries(value)) nested[k] = resolveValue(v);
|
|
771
|
+
return nested;
|
|
772
|
+
}
|
|
773
|
+
return value;
|
|
755
774
|
};
|
|
756
775
|
const out = { ...params };
|
|
757
776
|
for (const [key, value] of Object.entries(params)) out[key] = resolveValue(value);
|
|
@@ -739,19 +739,38 @@ function resolveRefIn(ref, shape) {
|
|
|
739
739
|
return resolveLineageRef(ref, rolesFor(ref, shape, /* @__PURE__ */ new Map()), shape);
|
|
740
740
|
}
|
|
741
741
|
/**
|
|
742
|
+
* A plain options object worth recursing into for nested refs — a literal `{}`
|
|
743
|
+
* (or null-prototype) that isn't a lineage ref, a shape handle, or a Date/Map/
|
|
744
|
+
* class instance (which `Object.entries` would silently flatten away).
|
|
745
|
+
*/
|
|
746
|
+
function isPlainOptions(value) {
|
|
747
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
748
|
+
const proto = Object.getPrototypeOf(value);
|
|
749
|
+
if (proto !== Object.prototype && proto !== null) return false;
|
|
750
|
+
return !("wrapped" in value);
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
742
753
|
* Replace every lineage ref in an operation's params with the live entity it
|
|
743
|
-
* resolves to in `shape`, recursing into arrays (
|
|
744
|
-
*
|
|
745
|
-
* re-derived once per `origin` and
|
|
746
|
-
* replay engine pass stable entity
|
|
754
|
+
* resolves to in `shape`, recursing into arrays (a fillet's edge list) and
|
|
755
|
+
* nested plain objects (a `{ selection: { edge } }` options bag). Refs that
|
|
756
|
+
* can't resolve are left as-is. Role tables are re-derived once per `origin` and
|
|
757
|
+
* reused across the whole params map. Lets a replay engine pass stable entity
|
|
758
|
+
* selections that survive upstream edits.
|
|
747
759
|
*/
|
|
748
760
|
function resolveRefParams(params, shape) {
|
|
749
761
|
const roleCache = /* @__PURE__ */ new Map();
|
|
750
762
|
const resolveValue = (value) => {
|
|
763
|
+
if (isLineageRef(value)) {
|
|
764
|
+
const res = resolveLineageRef(value, rolesFor(value, shape, roleCache), shape);
|
|
765
|
+
return res.ok ? res.entity : value;
|
|
766
|
+
}
|
|
751
767
|
if (Array.isArray(value)) return value.map(resolveValue);
|
|
752
|
-
if (
|
|
753
|
-
|
|
754
|
-
|
|
768
|
+
if (isPlainOptions(value)) {
|
|
769
|
+
const nested = {};
|
|
770
|
+
for (const [k, v] of Object.entries(value)) nested[k] = resolveValue(v);
|
|
771
|
+
return nested;
|
|
772
|
+
}
|
|
773
|
+
return value;
|
|
755
774
|
};
|
|
756
775
|
const out = { ...params };
|
|
757
776
|
for (const [key, value] of Object.entries(params)) out[key] = resolveValue(value);
|
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-BiEBAREW.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-Ck6kJzLE.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,6 +5,7 @@ const require_faceFns = require("./faceFns-BV0GnTlt.cjs");
|
|
|
5
5
|
const require_shapeFns = require("./shapeFns-ybo0INGL.cjs");
|
|
6
6
|
const require_solidBuilders = require("./solidBuilders-DiUv_mD0.cjs");
|
|
7
7
|
const require_loftFns = require("./loftFns-fpTmrIdd.cjs");
|
|
8
|
+
const require_refResolveFns = require("./refResolveFns-BiEBAREW.cjs");
|
|
8
9
|
const require_primitiveFns = require("./primitiveFns-DLIWtQWA.cjs");
|
|
9
10
|
//#region src/utils/uuid.ts
|
|
10
11
|
/** Generate a v4-style UUID string using `crypto.getRandomValues`. */
|
|
@@ -1300,6 +1301,22 @@ function registerOperation(registry, type, fn) {
|
|
|
1300
1301
|
return { operations: ops };
|
|
1301
1302
|
}
|
|
1302
1303
|
/**
|
|
1304
|
+
* Resolve any lineage refs in a step's params against its input shape, so an
|
|
1305
|
+
* operation re-targets the SAME entity (edge/face/vertex) after an upstream
|
|
1306
|
+
* parameter edit rebuilds the model. The stored step keeps its refs; resolution
|
|
1307
|
+
* happens fresh at replay.
|
|
1308
|
+
*
|
|
1309
|
+
* Only **single-input** steps auto-resolve: with multiple inputs we can't tell
|
|
1310
|
+
* which input a ref targets, and resolving against the wrong one could silently
|
|
1311
|
+
* return an entity from the wrong shape. Multi-input refs (and ref-free or non-3D
|
|
1312
|
+
* cases) are left raw for the operation to resolve against the input it chooses.
|
|
1313
|
+
*/
|
|
1314
|
+
function resolveStepParams(params, inputs) {
|
|
1315
|
+
const [primary, second] = inputs;
|
|
1316
|
+
if (primary !== void 0 && second === void 0 && require_shapeTypes.isShape3D(primary)) return require_refResolveFns.resolveRefParams(params, primary);
|
|
1317
|
+
return { ...params };
|
|
1318
|
+
}
|
|
1319
|
+
/**
|
|
1303
1320
|
* Replay an entire history from scratch using the given registry.
|
|
1304
1321
|
*
|
|
1305
1322
|
* All initial shapes (those not produced by any step) must already be in the
|
|
@@ -1323,7 +1340,7 @@ function replayHistory(history, registry) {
|
|
|
1323
1340
|
inputs.push(shape);
|
|
1324
1341
|
}
|
|
1325
1342
|
try {
|
|
1326
|
-
const output = fn(inputs, step.parameters);
|
|
1343
|
+
const output = fn(inputs, resolveStepParams(step.parameters, inputs));
|
|
1327
1344
|
current = addStep(current, {
|
|
1328
1345
|
id: step.id,
|
|
1329
1346
|
type: step.type,
|
|
@@ -1367,7 +1384,7 @@ function replayFrom(history, stepId, registry) {
|
|
|
1367
1384
|
inputs.push(shape);
|
|
1368
1385
|
}
|
|
1369
1386
|
try {
|
|
1370
|
-
const output = fn(inputs, step.parameters);
|
|
1387
|
+
const output = fn(inputs, resolveStepParams(step.parameters, inputs));
|
|
1371
1388
|
current = addStep(current, {
|
|
1372
1389
|
id: step.id,
|
|
1373
1390
|
type: step.type,
|
|
@@ -1682,6 +1699,12 @@ Object.defineProperty(exports, "quatFromTo", {
|
|
|
1682
1699
|
return quatFromTo;
|
|
1683
1700
|
}
|
|
1684
1701
|
});
|
|
1702
|
+
Object.defineProperty(exports, "quatMultiply", {
|
|
1703
|
+
enumerable: true,
|
|
1704
|
+
get: function() {
|
|
1705
|
+
return quatMultiply;
|
|
1706
|
+
}
|
|
1707
|
+
});
|
|
1685
1708
|
Object.defineProperty(exports, "quatRotate", {
|
|
1686
1709
|
enumerable: true,
|
|
1687
1710
|
get: function() {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { B as createKernelHandle, R as DisposalScope, Y as _usingCtx, Z as getKernel, t as castShape } from "./shapeTypes-Dpu6mD3m.js";
|
|
1
|
+
import { B as createKernelHandle, R as DisposalScope, Y as _usingCtx, Z as getKernel, h as isShape3D, t as castShape } from "./shapeTypes-Dpu6mD3m.js";
|
|
2
2
|
import { A as ok, T as isOk, b as err, d as validationError, n as computationError, r as ioError, t as BrepErrorCode } from "./errors-DNWJsfVU.js";
|
|
3
3
|
import { d as vecNormalize, s as vecIsZero } from "./vecOps-SKPRvPH-.js";
|
|
4
4
|
import { y as fromBREP } from "./faceFns-B86WGqDg.js";
|
|
5
5
|
import { s as toBREP } from "./shapeFns-DrZOVwHX.js";
|
|
6
6
|
import { h as fuseAll } from "./solidBuilders-C32wXQWG.js";
|
|
7
7
|
import { t as loft } from "./loftFns-CmShFQlv.js";
|
|
8
|
+
import { c as resolveRefParams } from "./refResolveFns-Ck6kJzLE.js";
|
|
8
9
|
import { E as wire, h as line } from "./primitiveFns-CBrOyk5S.js";
|
|
9
10
|
//#region src/utils/uuid.ts
|
|
10
11
|
/** Generate a v4-style UUID string using `crypto.getRandomValues`. */
|
|
@@ -1300,6 +1301,22 @@ function registerOperation(registry, type, fn) {
|
|
|
1300
1301
|
return { operations: ops };
|
|
1301
1302
|
}
|
|
1302
1303
|
/**
|
|
1304
|
+
* Resolve any lineage refs in a step's params against its input shape, so an
|
|
1305
|
+
* operation re-targets the SAME entity (edge/face/vertex) after an upstream
|
|
1306
|
+
* parameter edit rebuilds the model. The stored step keeps its refs; resolution
|
|
1307
|
+
* happens fresh at replay.
|
|
1308
|
+
*
|
|
1309
|
+
* Only **single-input** steps auto-resolve: with multiple inputs we can't tell
|
|
1310
|
+
* which input a ref targets, and resolving against the wrong one could silently
|
|
1311
|
+
* return an entity from the wrong shape. Multi-input refs (and ref-free or non-3D
|
|
1312
|
+
* cases) are left raw for the operation to resolve against the input it chooses.
|
|
1313
|
+
*/
|
|
1314
|
+
function resolveStepParams(params, inputs) {
|
|
1315
|
+
const [primary, second] = inputs;
|
|
1316
|
+
if (primary !== void 0 && second === void 0 && isShape3D(primary)) return resolveRefParams(params, primary);
|
|
1317
|
+
return { ...params };
|
|
1318
|
+
}
|
|
1319
|
+
/**
|
|
1303
1320
|
* Replay an entire history from scratch using the given registry.
|
|
1304
1321
|
*
|
|
1305
1322
|
* All initial shapes (those not produced by any step) must already be in the
|
|
@@ -1323,7 +1340,7 @@ function replayHistory(history, registry) {
|
|
|
1323
1340
|
inputs.push(shape);
|
|
1324
1341
|
}
|
|
1325
1342
|
try {
|
|
1326
|
-
const output = fn(inputs, step.parameters);
|
|
1343
|
+
const output = fn(inputs, resolveStepParams(step.parameters, inputs));
|
|
1327
1344
|
current = addStep(current, {
|
|
1328
1345
|
id: step.id,
|
|
1329
1346
|
type: step.type,
|
|
@@ -1367,7 +1384,7 @@ function replayFrom(history, stepId, registry) {
|
|
|
1367
1384
|
inputs.push(shape);
|
|
1368
1385
|
}
|
|
1369
1386
|
try {
|
|
1370
|
-
const output = fn(inputs, step.parameters);
|
|
1387
|
+
const output = fn(inputs, resolveStepParams(step.parameters, inputs));
|
|
1371
1388
|
current = addStep(current, {
|
|
1372
1389
|
id: step.id,
|
|
1373
1390
|
type: step.type,
|
|
@@ -1496,4 +1513,4 @@ function thread(options) {
|
|
|
1496
1513
|
}
|
|
1497
1514
|
}
|
|
1498
1515
|
//#endregion
|
|
1499
|
-
export { setJointValue as A,
|
|
1516
|
+
export { setJointValue as A, createAssemblyNode as B, cylindricalJoint as C, planarJoint as D, mechanismDOF as E, quatMultiply as F, circularPattern as G, removeChild as H, quatRotate as I, exportAssemblySTEP as J, gridPattern as K, addChild as L, sphericalJoint as M, quatFromAxisAngle as N, prismaticJoint as O, quatFromTo as P, collectShapes as R, addJoint as S, jointTransform as T, updateNode as U, findNode as V, walkAssembly as W, createAssembly as Y, exportURDF as _, deserializeHistory as a, inverseKinematics as b, modifyStep as c, replayFrom as d, replayHistory as f, undoLast as g, stepsFrom as h, createRegistry as i, setJointValues as j, revoluteJoint as k, registerOperation as l, stepCount as m, addStep as n, findStep as o, serializeHistory as p, linearPattern as q, createHistory as r, getShape as s, thread as t, registerShape as u, importURDF as v, forwardKinematics as w, jointTrajectory as x, jointsFromDH as y, countNodes as z };
|
|
@@ -45,9 +45,10 @@ export declare function resolveLineageRef(ref: LineageRef, roles: RoleTable, sha
|
|
|
45
45
|
export declare function resolveRefIn(ref: LineageRef, shape: Shape3D): LineageResolution;
|
|
46
46
|
/**
|
|
47
47
|
* Replace every lineage ref in an operation's params with the live entity it
|
|
48
|
-
* resolves to in `shape`, recursing into arrays (
|
|
49
|
-
*
|
|
50
|
-
* re-derived once per `origin` and
|
|
51
|
-
* replay engine pass stable entity
|
|
48
|
+
* resolves to in `shape`, recursing into arrays (a fillet's edge list) and
|
|
49
|
+
* nested plain objects (a `{ selection: { edge } }` options bag). Refs that
|
|
50
|
+
* can't resolve are left as-is. Role tables are re-derived once per `origin` and
|
|
51
|
+
* reused across the whole params map. Lets a replay engine pass stable entity
|
|
52
|
+
* selections that survive upstream edits.
|
|
52
53
|
*/
|
|
53
54
|
export declare function resolveRefParams(params: Readonly<Record<string, unknown>>, shape: Shape3D): Record<string, unknown>;
|