brepjs 18.116.0 → 18.117.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/2d.cjs +4 -4
  2. package/dist/2d.js +4 -4
  3. package/dist/{blueprint-BwkD2qeC.cjs → blueprint-Bb6y8xmG.cjs} +1 -1
  4. package/dist/{blueprint-Dw0QqImu.js → blueprint-ccFH0CU4.js} +1 -1
  5. package/dist/{blueprintFns-B-aybpEo.cjs → blueprintFns-B7nDXYsr.cjs} +2 -2
  6. package/dist/{blueprintFns-BowWsZgJ.js → blueprintFns-Cvhzcmrk.js} +2 -2
  7. package/dist/{blueprintSketcher-RK-cH6ps.cjs → blueprintSketcher-BY6R2umG.cjs} +2 -2
  8. package/dist/{blueprintSketcher-7rtwqUHZ.js → blueprintSketcher-Cw_Epicg.js} +2 -2
  9. package/dist/{boolean2D-y0SSZfe2.js → boolean2D-BiPWJMSB.js} +3 -3
  10. package/dist/{boolean2D-CZUEOoAh.cjs → boolean2D-mBIMAMP3.cjs} +3 -3
  11. package/dist/brepjs.cjs +156 -50
  12. package/dist/brepjs.js +156 -51
  13. package/dist/{cornerFinder-DUGeBIvD.js → cornerFinder-Baa3j5Ph.js} +1 -1
  14. package/dist/{cornerFinder-B4q88TRb.cjs → cornerFinder-DaHVcKSL.cjs} +1 -1
  15. package/dist/{drawFns-SQIBls6p.js → drawFns-Blkxt9ei.js} +6 -6
  16. package/dist/{drawFns-DNxs7PAT.cjs → drawFns-NEdyNRo-.cjs} +6 -6
  17. package/dist/{healingFns-xLJ6Cp_O.cjs → healingFns-DiVnJgwh.cjs} +2 -2
  18. package/dist/{healingFns-2TJHHDg5.js → healingFns-TnTWI_K_.js} +2 -2
  19. package/dist/{helpers-DhJwFrkC.js → helpers-BuJ2542Q.js} +1 -1
  20. package/dist/{helpers-BSLPCflF.cjs → helpers-Cy4IH0Dc.cjs} +1 -1
  21. package/dist/{importFns-CgMQIi0z.cjs → importFns-2X1Bh_-e.cjs} +1 -1
  22. package/dist/{importFns-nR9lEx22.js → importFns-DU6m8NVC.js} +1 -1
  23. package/dist/index.d.ts +1 -1
  24. package/dist/io.cjs +2 -2
  25. package/dist/io.js +2 -2
  26. package/dist/{meshFns-DbmidUzH.js → meshFns-DBsxqJd3.js} +1 -1
  27. package/dist/{meshFns-1hQSn1p2.cjs → meshFns-HyzvCIhb.cjs} +1 -1
  28. package/dist/operations.cjs +1 -1
  29. package/dist/operations.js +1 -1
  30. package/dist/{primitiveFns-DLIWtQWA.cjs → primitiveFns-DvGRmEox.cjs} +2 -2
  31. package/dist/{primitiveFns-CBrOyk5S.js → primitiveFns-LYeAjO6E.js} +2 -2
  32. package/dist/query.cjs +2 -2
  33. package/dist/query.js +2 -2
  34. package/dist/{refResolveFns-BiEBAREW.cjs → refResolveFns-BGcsRo5a.cjs} +1 -1
  35. package/dist/{refResolveFns-Ck6kJzLE.js → refResolveFns-BzIXnBrs.js} +1 -1
  36. package/dist/{shapeFns-DrZOVwHX.js → shapeFns-DJHbIsRX.js} +26 -1
  37. package/dist/{shapeFns-ybo0INGL.cjs → shapeFns-aI4Hr4XV.cjs} +31 -0
  38. package/dist/shapeRef.cjs +1 -1
  39. package/dist/shapeRef.js +1 -1
  40. package/dist/sketching.cjs +3 -3
  41. package/dist/sketching.js +3 -3
  42. package/dist/{solidBuilders-C32wXQWG.js → solidBuilders-CjrjwCtG.js} +1 -1
  43. package/dist/{solidBuilders-DiUv_mD0.cjs → solidBuilders-DSokszEg.cjs} +1 -1
  44. package/dist/text.cjs +2 -2
  45. package/dist/text.js +2 -2
  46. package/dist/{textBlueprints-D5lsZswr.cjs → textBlueprints-BvD0c2S0.cjs} +2 -2
  47. package/dist/{textBlueprints-BnkWAqwS.js → textBlueprints-gMoNCh6B.js} +2 -2
  48. package/dist/{textMetrics-COGYk0LE.js → textMetrics-7Je4nat3.js} +1 -1
  49. package/dist/{textMetrics-IC_IoI7l.cjs → textMetrics-BZwyjpX_.cjs} +1 -1
  50. package/dist/{threadFns-Dgr2qyJv.js → threadFns-B9udL9Zs.js} +5 -5
  51. package/dist/{threadFns-KrG_i9_w.cjs → threadFns-cKaZIY34.cjs} +10 -4
  52. package/dist/topology/api.d.ts +7 -0
  53. package/dist/topology/shapeFns.d.ts +1 -1
  54. package/dist/topology/transformFns.d.ts +15 -0
  55. package/dist/topology.cjs +5 -5
  56. package/dist/topology.js +5 -5
  57. package/package.json +1 -1
package/dist/2d.cjs CHANGED
@@ -2,10 +2,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_shapeTypes = require("./shapeTypes-BTTwjHy5.cjs");
3
3
  const require_errors = require("./errors-CXJtc4I7.cjs");
4
4
  const require_topologyQueryFns = require("./topologyQueryFns-CoXVHuN7.cjs");
5
- const require_blueprintSketcher = require("./blueprintSketcher-RK-cH6ps.cjs");
6
- const require_blueprint = require("./blueprint-BwkD2qeC.cjs");
7
- const require_boolean2D = require("./boolean2D-CZUEOoAh.cjs");
8
- const require_blueprintFns = require("./blueprintFns-B-aybpEo.cjs");
5
+ const require_blueprintSketcher = require("./blueprintSketcher-BY6R2umG.cjs");
6
+ const require_blueprint = require("./blueprint-Bb6y8xmG.cjs");
7
+ const require_boolean2D = require("./boolean2D-mBIMAMP3.cjs");
8
+ const require_blueprintFns = require("./blueprintFns-B7nDXYsr.cjs");
9
9
  //#region src/core/curve2dHandle.ts
10
10
  /**
11
11
  * Wrap a raw kernel 2D curve handle with brand + disposal tracking.
package/dist/2d.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { B as createKernelHandle, Q as getKernel2D, a as createEdge } from "./shapeTypes-Dpu6mD3m.js";
2
2
  import { A as ok, b as err, d as validationError, t as BrepErrorCode } from "./errors-DNWJsfVU.js";
3
3
  import { w as kernelCallRaw } from "./topologyQueryFns-BeKaWpNm.js";
4
- import { a as Blueprints, i as CompoundBlueprint, r as organiseBlueprints } from "./blueprintSketcher-7rtwqUHZ.js";
5
- import { _ as Curve2D, t as Blueprint, y as BoundingBox2d } from "./blueprint-Dw0QqImu.js";
6
- import { a as fuseBlueprints, c as roundedRectangleBlueprint, i as cutBlueprints, n as fuse2D, o as intersectBlueprints, r as intersect2D, s as polysidesBlueprint, t as cut2D } from "./boolean2D-y0SSZfe2.js";
7
- import { S as reverseCurve, _ as curve2dIsOnCurve, a as isInside2D, b as curve2dSplitAt, c as scale2D, d as stretch2D, f as toSVGPathD, g as curve2dFirstPoint, h as curve2dDistanceFrom, i as getOrientation2D, l as sketchOnFace2D, m as curve2dBoundingBox, o as mirror2D, p as translate2D, r as getBounds2D, s as rotate2D, t as createBlueprint, u as sketchOnPlane2D, v as curve2dLastPoint, x as curve2dTangentAt, y as curve2dParameter } from "./blueprintFns-BowWsZgJ.js";
4
+ import { a as Blueprints, i as CompoundBlueprint, r as organiseBlueprints } from "./blueprintSketcher-Cw_Epicg.js";
5
+ import { _ as Curve2D, t as Blueprint, y as BoundingBox2d } from "./blueprint-ccFH0CU4.js";
6
+ import { a as fuseBlueprints, c as roundedRectangleBlueprint, i as cutBlueprints, n as fuse2D, o as intersectBlueprints, r as intersect2D, s as polysidesBlueprint, t as cut2D } from "./boolean2D-BiPWJMSB.js";
7
+ import { S as reverseCurve, _ as curve2dIsOnCurve, a as isInside2D, b as curve2dSplitAt, c as scale2D, d as stretch2D, f as toSVGPathD, g as curve2dFirstPoint, h as curve2dDistanceFrom, i as getOrientation2D, l as sketchOnFace2D, m as curve2dBoundingBox, o as mirror2D, p as translate2D, r as getBounds2D, s as rotate2D, t as createBlueprint, u as sketchOnPlane2D, v as curve2dLastPoint, x as curve2dTangentAt, y as curve2dParameter } from "./blueprintFns-Cvhzcmrk.js";
8
8
  //#region src/core/curve2dHandle.ts
9
9
  /**
10
10
  * Wrap a raw kernel 2D curve handle with brand + disposal tracking.
@@ -8,7 +8,7 @@ const require_faceFns = require("./faceFns-BV0GnTlt.cjs");
8
8
  const require_curveFns = require("./curveFns-DgUJpH4z.cjs");
9
9
  const require_arrayAccess = require("./arrayAccess-e4H9cBfh.cjs");
10
10
  const require_surfaceBuilders = require("./surfaceBuilders-UyyfZy8w.cjs");
11
- const require_helpers = require("./helpers-BSLPCflF.cjs");
11
+ const require_helpers = require("./helpers-Cy4IH0Dc.cjs");
12
12
  //#region src/2d/lib/definitions.ts
13
13
  /** Type guard that checks whether a value is a `Point2D`. */
14
14
  function isPoint2D(point) {
@@ -8,7 +8,7 @@ import { _ as cast, h as uvCoordinates, i as faceGeomType, m as uvBounds, r as f
8
8
  import { p as getOrientation } from "./curveFns-CcSn4-Rf.js";
9
9
  import { n as getAtOrThrow, r as lastOrThrow, t as firstOrThrow } from "./arrayAccess-DrUGPADn.js";
10
10
  import { r as makeFace } from "./surfaceBuilders-rkE-jE90.js";
11
- import { _ as samePoint, b as subtract2d, l as add2d, o as normalize2d, p as distance2d, t as getSingleFace, v as scalarMultiply2d } from "./helpers-DhJwFrkC.js";
11
+ import { _ as samePoint, b as subtract2d, l as add2d, o as normalize2d, p as distance2d, t as getSingleFace, v as scalarMultiply2d } from "./helpers-BuJ2542Q.js";
12
12
  //#region src/2d/lib/definitions.ts
13
13
  /** Type guard that checks whether a value is a `Point2D`. */
14
14
  function isPoint2D(point) {
@@ -1,6 +1,6 @@
1
1
  const require_errors = require("./errors-CXJtc4I7.cjs");
2
- const require_blueprintSketcher = require("./blueprintSketcher-RK-cH6ps.cjs");
3
- const require_blueprint = require("./blueprint-BwkD2qeC.cjs");
2
+ const require_blueprintSketcher = require("./blueprintSketcher-BY6R2umG.cjs");
3
+ const require_blueprint = require("./blueprint-Bb6y8xmG.cjs");
4
4
  //#region src/2d/lib/curve2dFns.ts
5
5
  /**
6
6
  * Return a reversed copy of the curve (non-mutating).
@@ -1,6 +1,6 @@
1
1
  import { A as ok, b as err, d as validationError, t as BrepErrorCode } from "./errors-DNWJsfVU.js";
2
- import { i as CompoundBlueprint } from "./blueprintSketcher-7rtwqUHZ.js";
3
- import { t as Blueprint } from "./blueprint-Dw0QqImu.js";
2
+ import { i as CompoundBlueprint } from "./blueprintSketcher-Cw_Epicg.js";
3
+ import { t as Blueprint } from "./blueprint-ccFH0CU4.js";
4
4
  //#region src/2d/lib/curve2dFns.ts
5
5
  /**
6
6
  * Return a reversed copy of the curve (non-mutating).
@@ -3,8 +3,8 @@ const require_vec3 = require("./vec3-CFwOI0ZI.cjs");
3
3
  const require_errors = require("./errors-CXJtc4I7.cjs");
4
4
  const require_constants = require("./constants-BOVyEYGH.cjs");
5
5
  const require_arrayAccess = require("./arrayAccess-e4H9cBfh.cjs");
6
- const require_helpers = require("./helpers-BSLPCflF.cjs");
7
- const require_blueprint = require("./blueprint-BwkD2qeC.cjs");
6
+ const require_helpers = require("./helpers-Cy4IH0Dc.cjs");
7
+ const require_blueprint = require("./blueprint-Bb6y8xmG.cjs");
8
8
  //#region node_modules/flatqueue/index.js
9
9
  /**
10
10
  * @typedef {Float64ArrayConstructor | Float32ArrayConstructor |
@@ -3,8 +3,8 @@ import { n as wasmIndex } from "./vec3-Dpha8d5k.js";
3
3
  import { A as ok, R as unwrap, T as isOk, b as err, h as bug, n as computationError, s as safeIndex } from "./errors-DNWJsfVU.js";
4
4
  import { r as RAD2DEG, t as DEG2RAD } from "./constants-ITRzCnCp.js";
5
5
  import { t as firstOrThrow } from "./arrayAccess-DrUGPADn.js";
6
- import { _ as samePoint, b as subtract2d, d as cartesianToPolar, f as crossProduct2d, g as rotate2d, h as polarToCartesian, l as add2d, m as polarAngle2d, o as normalize2d, p as distance2d, v as scalarMultiply2d } from "./helpers-DhJwFrkC.js";
7
- import { _ as Curve2D, c as make2dCircle, f as make2dSegmentCurve, h as approximateAsBSpline, m as make2dThreePointArc, n as asSVG, o as make2dArcFromCenter, p as make2dTangentArc, r as viewbox, s as make2dBezierCurve, t as Blueprint, u as make2dEllipseArc, x as isPoint2D, y as BoundingBox2d } from "./blueprint-Dw0QqImu.js";
6
+ import { _ as samePoint, b as subtract2d, d as cartesianToPolar, f as crossProduct2d, g as rotate2d, h as polarToCartesian, l as add2d, m as polarAngle2d, o as normalize2d, p as distance2d, v as scalarMultiply2d } from "./helpers-BuJ2542Q.js";
7
+ import { _ as Curve2D, c as make2dCircle, f as make2dSegmentCurve, h as approximateAsBSpline, m as make2dThreePointArc, n as asSVG, o as make2dArcFromCenter, p as make2dTangentArc, r as viewbox, s as make2dBezierCurve, t as Blueprint, u as make2dEllipseArc, x as isPoint2D, y as BoundingBox2d } from "./blueprint-ccFH0CU4.js";
8
8
  //#region node_modules/flatqueue/index.js
9
9
  /**
10
10
  * @typedef {Float64ArrayConstructor | Float32ArrayConstructor |
@@ -2,9 +2,9 @@ import { n as wasmIndex } from "./vec3-Dpha8d5k.js";
2
2
  import { R as unwrap, h as bug, s as safeIndex } from "./errors-DNWJsfVU.js";
3
3
  import { r as lastOrThrow } from "./arrayAccess-DrUGPADn.js";
4
4
  import { v as zip } from "./surfaceBuilders-rkE-jE90.js";
5
- import { a as Blueprints, i as CompoundBlueprint, l as intersectCurves, r as organiseBlueprints, t as BlueprintSketcher, u as Flatbush } from "./blueprintSketcher-7rtwqUHZ.js";
6
- import { _ as samePoint$1, b as subtract2d, f as crossProduct2d, s as PRECISION_INTERSECTION } from "./helpers-DhJwFrkC.js";
7
- import { b as removeDuplicatePoints, f as make2dSegmentCurve, t as Blueprint } from "./blueprint-Dw0QqImu.js";
5
+ import { a as Blueprints, i as CompoundBlueprint, l as intersectCurves, r as organiseBlueprints, t as BlueprintSketcher, u as Flatbush } from "./blueprintSketcher-Cw_Epicg.js";
6
+ import { _ as samePoint$1, b as subtract2d, f as crossProduct2d, s as PRECISION_INTERSECTION } from "./helpers-BuJ2542Q.js";
7
+ import { b as removeDuplicatePoints, f as make2dSegmentCurve, t as Blueprint } from "./blueprint-ccFH0CU4.js";
8
8
  //#region src/2d/blueprints/cannedBlueprints.ts
9
9
  /**
10
10
  * Create a regular polygon blueprint inscribed in a circle of the given radius.
@@ -2,9 +2,9 @@ const require_vec3 = require("./vec3-CFwOI0ZI.cjs");
2
2
  const require_errors = require("./errors-CXJtc4I7.cjs");
3
3
  const require_arrayAccess = require("./arrayAccess-e4H9cBfh.cjs");
4
4
  const require_surfaceBuilders = require("./surfaceBuilders-UyyfZy8w.cjs");
5
- const require_blueprintSketcher = require("./blueprintSketcher-RK-cH6ps.cjs");
6
- const require_helpers = require("./helpers-BSLPCflF.cjs");
7
- const require_blueprint = require("./blueprint-BwkD2qeC.cjs");
5
+ const require_blueprintSketcher = require("./blueprintSketcher-BY6R2umG.cjs");
6
+ const require_helpers = require("./helpers-Cy4IH0Dc.cjs");
7
+ const require_blueprint = require("./blueprint-Bb6y8xmG.cjs");
8
8
  //#region src/2d/blueprints/cannedBlueprints.ts
9
9
  /**
10
10
  * Create a regular polygon blueprint inscribed in a circle of the given radius.
package/dist/brepjs.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_textBlueprints = require("./textBlueprints-D5lsZswr.cjs");
2
+ const require_textBlueprints = require("./textBlueprints-BvD0c2S0.cjs");
3
3
  const require_shapeTypes = require("./shapeTypes-BTTwjHy5.cjs");
4
4
  const require_occtWasmAdapter = require("./occtWasmAdapter-B2TEQOjs.cjs");
5
5
  const require_vec3 = require("./vec3-CFwOI0ZI.cjs");
@@ -10,29 +10,29 @@ const require_types = require("./types-KjA8tY4Y.cjs");
10
10
  const require_vecOps = require("./vecOps-CCnJt-yH.cjs");
11
11
  const require_planeOps = require("./planeOps-BA4HfgQu.cjs");
12
12
  const require_faceFns = require("./faceFns-BV0GnTlt.cjs");
13
- const require_shapeFns = require("./shapeFns-ybo0INGL.cjs");
13
+ const require_shapeFns = require("./shapeFns-aI4Hr4XV.cjs");
14
14
  const require_curveFns = require("./curveFns-DgUJpH4z.cjs");
15
- const require_meshFns = require("./meshFns-1hQSn1p2.cjs");
15
+ const require_meshFns = require("./meshFns-HyzvCIhb.cjs");
16
16
  const require_arrayAccess = require("./arrayAccess-e4H9cBfh.cjs");
17
17
  const require_surfaceBuilders = require("./surfaceBuilders-UyyfZy8w.cjs");
18
- const require_solidBuilders = require("./solidBuilders-DiUv_mD0.cjs");
19
- const require_healingFns = require("./healingFns-xLJ6Cp_O.cjs");
20
- const require_threadFns = require("./threadFns-KrG_i9_w.cjs");
21
- const require_blueprintSketcher = require("./blueprintSketcher-RK-cH6ps.cjs");
22
- const require_helpers = require("./helpers-BSLPCflF.cjs");
23
- const require_drawFns = require("./drawFns-DNxs7PAT.cjs");
18
+ const require_solidBuilders = require("./solidBuilders-DSokszEg.cjs");
19
+ const require_healingFns = require("./healingFns-DiVnJgwh.cjs");
20
+ const require_threadFns = require("./threadFns-cKaZIY34.cjs");
21
+ const require_blueprintSketcher = require("./blueprintSketcher-BY6R2umG.cjs");
22
+ const require_helpers = require("./helpers-Cy4IH0Dc.cjs");
23
+ const require_drawFns = require("./drawFns-NEdyNRo-.cjs");
24
24
  const require_measureFns = require("./measureFns-DblG0Yaz.cjs");
25
- const require_cornerFinder = require("./cornerFinder-B4q88TRb.cjs");
26
- const require_boolean2D = require("./boolean2D-CZUEOoAh.cjs");
27
- const require_blueprintFns = require("./blueprintFns-B-aybpEo.cjs");
28
- const require_importFns = require("./importFns-CgMQIi0z.cjs");
25
+ const require_cornerFinder = require("./cornerFinder-DaHVcKSL.cjs");
26
+ const require_boolean2D = require("./boolean2D-mBIMAMP3.cjs");
27
+ const require_blueprintFns = require("./blueprintFns-B7nDXYsr.cjs");
28
+ const require_importFns = require("./importFns-2X1Bh_-e.cjs");
29
29
  const require_loftFns = require("./loftFns-fpTmrIdd.cjs");
30
30
  const require_cameraFns = require("./cameraFns-uo1sZbBT.cjs");
31
- const require_textMetrics = require("./textMetrics-IC_IoI7l.cjs");
31
+ const require_textMetrics = require("./textMetrics-BZwyjpX_.cjs");
32
32
  const require_adjacencyFns = require("./adjacencyFns-d8ZabkvX.cjs");
33
- const require_refResolveFns = require("./refResolveFns-BiEBAREW.cjs");
33
+ const require_refResolveFns = require("./refResolveFns-BGcsRo5a.cjs");
34
34
  const require_workerPool = require("./workerPool-D30NsiIW.cjs");
35
- const require_primitiveFns = require("./primitiveFns-DLIWtQWA.cjs");
35
+ const require_primitiveFns = require("./primitiveFns-DvGRmEox.cjs");
36
36
  //#region src/topology/shapeBooleans.ts
37
37
  var BOPAlgo_GlueShift = 1;
38
38
  var BOPAlgo_GlueFull = 2;
@@ -3474,6 +3474,15 @@ function applyMatrix(shape, matrix) {
3474
3474
  function transformCopy(shape, composed) {
3475
3475
  return require_shapeFns.transformCopy(resolve(shape), composed);
3476
3476
  }
3477
+ /**
3478
+ * Placement-only rigid move (translate / rotate) via the kernel's cheap location
3479
+ * re-tag — O(1) on occt-wasm ≥3.6.0, falling back to a copy elsewhere. Same
3480
+ * face-metadata guarantee as `translate`, at location-swap cost. Ideal for
3481
+ * placing one cached cell at N positions without paying for N deep copies.
3482
+ */
3483
+ function locate(shape, placement) {
3484
+ return require_shapeFns.locate(resolve(shape), placement);
3485
+ }
3477
3486
  /** Fuse two 3D shapes (boolean union). */
3478
3487
  function fuse(a, b, options) {
3479
3488
  return require_solidBuilders.fuse(resolve(a), resolve(b), {
@@ -5837,48 +5846,144 @@ function cacheKey(node, env, kernelId, tolerance) {
5837
5846
  const tolHash = tolerance === void 0 ? "d" : fnvMixNumber(fnvInit(), tolerance).toString(16);
5838
5847
  return `${toHex(node.structuralHash)}:${kernelId}:${toHex(projHash)}:${tolHash}`;
5839
5848
  }
5849
+ var IDENTITY_QUAT = [
5850
+ 1,
5851
+ 0,
5852
+ 0,
5853
+ 0
5854
+ ];
5855
+ /** Resolve a Rotate node's angle/axis/center in `env`, applying the same
5856
+ * defaults as the evaluator (Z axis, origin pivot). Null if any free param
5857
+ * can't be evaluated, so the caller stops peeling there. */
5858
+ function evalRotateParams(node, env) {
5859
+ const a = evalScalar(node.angle, env, "evaluateMesh.peelRigid");
5860
+ if (!a.ok) return null;
5861
+ const axis = node.axis ? evalVec3(node.axis, env, "evaluateMesh.peelRigid") : require_errors.ok([
5862
+ 0,
5863
+ 0,
5864
+ 1
5865
+ ]);
5866
+ if (!axis.ok) return null;
5867
+ const center = node.at ? evalVec3(node.at, env, "evaluateMesh.peelRigid") : require_errors.ok([
5868
+ 0,
5869
+ 0,
5870
+ 0
5871
+ ]);
5872
+ if (!center.ok) return null;
5873
+ return {
5874
+ angle: a.value,
5875
+ axis: axis.value,
5876
+ center: center.value
5877
+ };
5878
+ }
5840
5879
  /**
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`).
5880
+ * Peel outer rigid-motion nodes (Translate / Rotate) off `node`, composing them
5881
+ * into a single rotation + translation. A rigid motion shares its inner
5882
+ * geometry's tessellation the shape path re-tags it via `locate` (#1633) — so
5883
+ * the inner meshes once and the cached mesh is moved per placement instead of
5884
+ * re-tessellating. Stops at the first non-rigid node (Scale/Mirror/boolean/…) or
5885
+ * one whose parameters can't be evaluated in `env`.
5886
+ *
5887
+ * Composition is outer∘inner: peeling outward, each node's local transform acts
5888
+ * on points the inner nodes already placed, so it post-multiplies the
5889
+ * accumulator. A pure-translation chain keeps the identity rotation, so the mesh
5890
+ * move below degenerates to the exact vertex-shift fast path (normals untouched).
5846
5891
  */
5847
- function peelTranslate(node, env) {
5892
+ function peelRigid(node, env) {
5848
5893
  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");
5894
+ let rot = IDENTITY_QUAT;
5895
+ let trans = [
5896
+ 0,
5897
+ 0,
5898
+ 0
5899
+ ];
5900
+ for (;;) if (inner.kind === "Translate") {
5901
+ const v = evalVec3(inner.vector, env, "evaluateMesh.peelRigid");
5854
5902
  if (!v.ok) break;
5855
- ox += v.value[0];
5856
- oy += v.value[1];
5857
- oz += v.value[2];
5903
+ const rv = require_threadFns.quatRotate(rot, v.value);
5904
+ trans = [
5905
+ trans[0] + rv[0],
5906
+ trans[1] + rv[1],
5907
+ trans[2] + rv[2]
5908
+ ];
5858
5909
  inner = inner.target;
5859
- }
5910
+ } else if (inner.kind === "Rotate") {
5911
+ const p = evalRotateParams(inner, env);
5912
+ if (!p) break;
5913
+ const r = require_threadFns.quatFromAxisAngle(p.axis, p.angle * Math.PI / 180);
5914
+ const newRot = require_threadFns.quatMultiply(rot, r);
5915
+ const rotC = require_threadFns.quatRotate(rot, p.center);
5916
+ const newRotC = require_threadFns.quatRotate(newRot, p.center);
5917
+ trans = [
5918
+ trans[0] + rotC[0] - newRotC[0],
5919
+ trans[1] + rotC[1] - newRotC[1],
5920
+ trans[2] + rotC[2] - newRotC[2]
5921
+ ];
5922
+ rot = newRot;
5923
+ inner = inner.target;
5924
+ } else break;
5860
5925
  return {
5861
5926
  inner,
5862
- offset: [
5863
- ox,
5864
- oy,
5865
- oz
5866
- ]
5927
+ rot,
5928
+ trans
5867
5929
  };
5868
5930
  }
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;
5931
+ function isIdentityQuat(q) {
5932
+ return q[0] === 1 && q[1] === 0 && q[2] === 0 && q[3] === 0;
5933
+ }
5934
+ /**
5935
+ * Write `src` (flat xyz) rigidly transformed by quaternion (qw,qx,qy,qz) then
5936
+ * translation (tx,ty,tz) into `dst`. The quaternion-rotate math is inlined with
5937
+ * scalar locals no per-vertex array allocation — because this runs once per
5938
+ * mesh vertex/normal and helper-allocated vector math regressed the gridfinity
5939
+ * benchmark 17% (see `utils/vec3.ts`). Pass zero translation for normals.
5940
+ */
5941
+ function rotateXyzBuffer(dst, src, qw, qx, qy, qz, tx, ty, tz) {
5942
+ for (let i = 0; i < src.length; i += 3) {
5943
+ const vx = src[i] ?? 0;
5944
+ const vy = src[i + 1] ?? 0;
5945
+ const vz = src[i + 2] ?? 0;
5946
+ const cx = 2 * (qy * vz - qz * vy);
5947
+ const cy = 2 * (qz * vx - qx * vz);
5948
+ const cz = 2 * (qx * vy - qy * vx);
5949
+ dst[i] = vx + qw * cx + (qy * cz - qz * cy) + tx;
5950
+ dst[i + 1] = vy + qw * cy + (qz * cx - qx * cz) + ty;
5951
+ dst[i + 2] = vz + qw * cz + (qx * cy - qy * cx) + tz;
5952
+ }
5953
+ }
5954
+ /**
5955
+ * Apply a rigid motion to a mesh: vertices get the rotation then translation,
5956
+ * normals get the rotation only (a unit rotation preserves length, so no
5957
+ * renormalization). UVs and triangles are motion-invariant. A pure translation
5958
+ * (identity rotation) keeps the source normals array by reference and only
5959
+ * shifts vertices — the exact previous translation-only fast path.
5960
+ */
5961
+ function transformMeshRigid(m, rot, trans) {
5962
+ const [tx, ty, tz] = trans;
5963
+ const pureTranslation = isIdentityQuat(rot);
5964
+ if (pureTranslation && tx === 0 && ty === 0 && tz === 0) return m;
5965
+ const src = m.vertices;
5966
+ const vertices = new Float32Array(src.length);
5967
+ if (pureTranslation) {
5968
+ for (let i = 0; i < src.length; i += 3) {
5969
+ vertices[i] = (src[i] ?? 0) + tx;
5970
+ vertices[i + 1] = (src[i + 1] ?? 0) + ty;
5971
+ vertices[i + 2] = (src[i + 2] ?? 0) + tz;
5972
+ }
5973
+ return {
5974
+ ...m,
5975
+ vertices
5976
+ };
5878
5977
  }
5978
+ const [qw, qx, qy, qz] = rot;
5979
+ rotateXyzBuffer(vertices, src, qw, qx, qy, qz, tx, ty, tz);
5980
+ const sn = m.normals;
5981
+ const normals = new Float32Array(sn.length);
5982
+ rotateXyzBuffer(normals, sn, qw, qx, qy, qz, 0, 0, 0);
5879
5983
  return {
5880
5984
  ...m,
5881
- vertices
5985
+ vertices,
5986
+ normals
5882
5987
  };
5883
5988
  }
5884
5989
  /**
@@ -5886,8 +5991,8 @@ function translateMesh(m, offset) {
5886
5991
  * moved faces location-dependent hashes, so the inner mesh's `faceId`s describe
5887
5992
  * the *unplaced* shape; remap them to the placed faces (1:1 by iteration order,
5888
5993
  * 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.
5994
+ * resolve against the placed mesh. Origins are boolean-lineage tags, invariant
5995
+ * under any rigid motion, so only `faceId` changes.
5891
5996
  *
5892
5997
  * Takes pre-captured hash arrays (not shapes): a bounded shape cache can evict
5893
5998
  * and dispose one shape while the other is being evaluated, so the caller reads
@@ -5983,7 +6088,7 @@ var Evaluator = class {
5983
6088
  }
5984
6089
  return require_errors.ok(cached);
5985
6090
  }
5986
- const { inner, offset } = peelTranslate(node, env);
6091
+ const { inner, rot, trans } = peelRigid(node, env);
5987
6092
  if (inner !== node) {
5988
6093
  const innerMesh = this.evaluateMesh(inner, env, meshOpts);
5989
6094
  if (!innerMesh.ok) return innerMesh;
@@ -5993,7 +6098,7 @@ var Evaluator = class {
5993
6098
  const placedShape = this.evaluate(node, env);
5994
6099
  if (!placedShape.ok) return placedShape;
5995
6100
  const placedHashes = require_topologyQueryFns.getFaces(placedShape.value).map(require_shapeFns.getHashCode);
5996
- const moved = translateMesh(innerMesh.value, offset);
6101
+ const moved = transformMeshRigid(innerMesh.value, rot, trans);
5997
6102
  const faceGroups = relocateFaceGroups(moved.faceGroups, innerHashes, placedHashes);
5998
6103
  const placedSet = new Set(placedHashes);
5999
6104
  if (faceGroups.every((g) => placedSet.has(g.faceId))) {
@@ -7251,6 +7356,7 @@ exports.latticeInfillShape = latticeInfillShape;
7251
7356
  exports.line = require_primitiveFns.line;
7252
7357
  exports.linearPattern = require_threadFns.linearPattern;
7253
7358
  exports.loadFont = require_textBlueprints.loadFont;
7359
+ exports.locate = locate;
7254
7360
  exports.loft = loft;
7255
7361
  exports.loftAll = require_loftFns.loftAll;
7256
7362
  exports.makeBaseBox = require_drawFns.makeBaseBox;