brepjs 18.70.0 → 18.72.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/brepjs.cjs CHANGED
@@ -2132,8 +2132,88 @@ function roof(w, options) {
2132
2132
  }
2133
2133
  }
2134
2134
  //#endregion
2135
+ //#region src/utils/quaternion.ts
2136
+ function dot$1(a, b) {
2137
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
2138
+ }
2139
+ function cross$1(a, b) {
2140
+ return [
2141
+ a[1] * b[2] - a[2] * b[1],
2142
+ a[2] * b[0] - a[0] * b[2],
2143
+ a[0] * b[1] - a[1] * b[0]
2144
+ ];
2145
+ }
2146
+ function normalize$1(a) {
2147
+ const l = Math.hypot(a[0], a[1], a[2]) || 1;
2148
+ return [
2149
+ a[0] / l,
2150
+ a[1] / l,
2151
+ a[2] / l
2152
+ ];
2153
+ }
2154
+ /** A unit vector perpendicular to `v` (for the 180°/parallel degenerate cases). */
2155
+ function anyPerpendicular$1(v) {
2156
+ return normalize$1(cross$1(v, Math.abs(v[0]) < .9 ? [
2157
+ 1,
2158
+ 0,
2159
+ 0
2160
+ ] : [
2161
+ 0,
2162
+ 1,
2163
+ 0
2164
+ ]));
2165
+ }
2166
+ /** Rotate vector `v` by quaternion `q`. */
2167
+ function quatRotate(q, v) {
2168
+ const [w, x, y, z] = q;
2169
+ const tx = 2 * (y * v[2] - z * v[1]);
2170
+ const ty = 2 * (z * v[0] - x * v[2]);
2171
+ const tz = 2 * (x * v[1] - y * v[0]);
2172
+ return [
2173
+ v[0] + w * tx + (y * tz - z * ty),
2174
+ v[1] + w * ty + (z * tx - x * tz),
2175
+ v[2] + w * tz + (x * ty - y * tx)
2176
+ ];
2177
+ }
2178
+ /** Quaternion for a rotation of `angle` radians about (unit-normalized) `axis`. */
2179
+ function quatFromAxisAngle(axis, angle) {
2180
+ const h = angle / 2;
2181
+ const s = Math.sin(h);
2182
+ const u = normalize$1(axis);
2183
+ return [
2184
+ Math.cos(h),
2185
+ u[0] * s,
2186
+ u[1] * s,
2187
+ u[2] * s
2188
+ ];
2189
+ }
2190
+ /** Shortest-arc quaternion rotating unit vector `from` onto unit vector `to`. */
2191
+ function quatFromTo(from, to) {
2192
+ const a = normalize$1(from);
2193
+ const b = normalize$1(to);
2194
+ const d = dot$1(a, b);
2195
+ if (d >= .999999999) return [
2196
+ 1,
2197
+ 0,
2198
+ 0,
2199
+ 0
2200
+ ];
2201
+ if (d <= -.999999999) return quatFromAxisAngle(anyPerpendicular$1(a), Math.PI);
2202
+ const c = cross$1(a, b);
2203
+ const len = Math.hypot(1 + d, c[0], c[1], c[2]) || 1;
2204
+ return [
2205
+ (1 + d) / len,
2206
+ c[0] / len,
2207
+ c[1] / len,
2208
+ c[2] / len
2209
+ ];
2210
+ }
2211
+ //#endregion
2135
2212
  //#region src/kernel/solverAdapter.ts
2136
2213
  /**
2214
+ * Constraint solver adapter — analytical solver for simple assembly mates.
2215
+ */
2216
+ /**
2137
2217
  * Degrees of freedom each constraint leaves unresolved when it can't be applied
2138
2218
  * (entity-type mismatch or an unreachable reference). All four types now solve
2139
2219
  * for well-typed inputs; these counts only feed the diagnostic `dof` for the
@@ -2192,7 +2272,7 @@ function normalize(a) {
2192
2272
  a[2] / l
2193
2273
  ];
2194
2274
  }
2195
- /** A unit vector perpendicular to `v` (for the 180° / parallel degenerate cases). */
2275
+ /** A unit vector perpendicular to `v` (for the parallel-normals degenerate case). */
2196
2276
  function anyPerpendicular(v) {
2197
2277
  return normalize(cross(v, Math.abs(v[0]) < .9 ? [
2198
2278
  1,
@@ -2204,59 +2284,14 @@ function anyPerpendicular(v) {
2204
2284
  0
2205
2285
  ]));
2206
2286
  }
2207
- /** Rotate vector `v` by quaternion `q` = [w, x, y, z]. */
2208
- function qRotate(q, v) {
2209
- const [w, x, y, z] = q;
2210
- const tx = 2 * (y * v[2] - z * v[1]);
2211
- const ty = 2 * (z * v[0] - x * v[2]);
2212
- const tz = 2 * (x * v[1] - y * v[0]);
2213
- return [
2214
- v[0] + w * tx + (y * tz - z * ty),
2215
- v[1] + w * ty + (z * tx - x * tz),
2216
- v[2] + w * tz + (x * ty - y * tx)
2217
- ];
2218
- }
2219
- function qFromAxisAngle(axis, angle) {
2220
- const h = angle / 2;
2221
- const s = Math.sin(h);
2222
- const u = normalize(axis);
2223
- return [
2224
- Math.cos(h),
2225
- u[0] * s,
2226
- u[1] * s,
2227
- u[2] * s
2228
- ];
2229
- }
2230
- /** Shortest-arc quaternion rotating unit vector `from` onto unit vector `to`. */
2231
- function qFromTo(from, to) {
2232
- const a = normalize(from);
2233
- const b = normalize(to);
2234
- const d = dot(a, b);
2235
- if (d >= .999999999) return IDENTITY_ROTATION;
2236
- if (d <= -.999999999) return qFromAxisAngle(anyPerpendicular(a), Math.PI);
2237
- const c = cross(a, b);
2238
- const q = [
2239
- 1 + d,
2240
- c[0],
2241
- c[1],
2242
- c[2]
2243
- ];
2244
- const l = Math.hypot(q[0], q[1], q[2], q[3]) || 1;
2245
- return [
2246
- q[0] / l,
2247
- q[1] / l,
2248
- q[2] / l,
2249
- q[3] / l
2250
- ];
2251
- }
2252
2287
  /** Apply a pose (rotate then translate) to an entity's origin and any directions. */
2253
2288
  function transformEntity(e, pose) {
2254
- const origin = add$1(qRotate(pose.rotation, e.origin), pose.position);
2289
+ const origin = add$1(quatRotate(pose.rotation, e.origin), pose.position);
2255
2290
  return {
2256
2291
  type: e.type,
2257
2292
  origin,
2258
- ...e.normal ? { normal: qRotate(pose.rotation, e.normal) } : {},
2259
- ...e.direction ? { direction: qRotate(pose.rotation, e.direction) } : {}
2293
+ ...e.normal ? { normal: quatRotate(pose.rotation, e.normal) } : {},
2294
+ ...e.direction ? { direction: quatRotate(pose.rotation, e.direction) } : {}
2260
2295
  };
2261
2296
  }
2262
2297
  /**
@@ -2290,12 +2325,12 @@ function solveConcentric(ref, dep) {
2290
2325
  0,
2291
2326
  1
2292
2327
  ];
2293
- const rotation = qFromTo(dep.direction ?? [
2328
+ const rotation = quatFromTo(dep.direction ?? [
2294
2329
  0,
2295
2330
  0,
2296
2331
  1
2297
2332
  ], dRef);
2298
- const rotatedOrigin = qRotate(rotation, dep.origin);
2333
+ const rotatedOrigin = quatRotate(rotation, dep.origin);
2299
2334
  return {
2300
2335
  position: sub(ref.origin, rotatedOrigin),
2301
2336
  rotation
@@ -2325,7 +2360,7 @@ function solveAngle(ref, dep, angleRad) {
2325
2360
  0,
2326
2361
  0
2327
2362
  ],
2328
- rotation: qFromAxisAngle(Math.hypot(c[0], c[1], c[2]) < 1e-9 ? anyPerpendicular(nDep) : c, phi - angleRad)
2363
+ rotation: quatFromAxisAngle(Math.hypot(c[0], c[1], c[2]) < 1e-9 ? anyPerpendicular(nDep) : c, phi - angleRad)
2329
2364
  };
2330
2365
  }
2331
2366
  /** Entity types each positioning constraint requires of (entityA, entityB). */
@@ -2567,6 +2602,102 @@ function solveAssembly(assembly) {
2567
2602
  }
2568
2603
  }
2569
2604
  //#endregion
2605
+ //#region src/operations/jointFns.ts
2606
+ var DEG2RAD$1 = Math.PI / 180;
2607
+ function clamp(value, min, max) {
2608
+ return Math.min(max, Math.max(min, value));
2609
+ }
2610
+ function unit(v) {
2611
+ const l = Math.hypot(v[0], v[1], v[2]) || 1;
2612
+ return [
2613
+ v[0] / l,
2614
+ v[1] / l,
2615
+ v[2] / l
2616
+ ];
2617
+ }
2618
+ function makeJoint(type, parent, child, axis, opts, defMin, defMax) {
2619
+ const a = opts.min ?? defMin;
2620
+ const b = opts.max ?? defMax;
2621
+ const min = Math.min(a, b);
2622
+ const max = Math.max(a, b);
2623
+ return {
2624
+ type,
2625
+ parent,
2626
+ child,
2627
+ axis: {
2628
+ origin: axis.origin,
2629
+ direction: unit(axis.direction)
2630
+ },
2631
+ min,
2632
+ max,
2633
+ value: clamp(opts.value ?? 0, min, max)
2634
+ };
2635
+ }
2636
+ /** A revolute (hinge) joint — the child rotates about `axis` by `value` degrees. */
2637
+ function revoluteJoint(parent, child, axis, opts = {}) {
2638
+ return makeJoint("revolute", parent, child, axis, opts, -180, 180);
2639
+ }
2640
+ /**
2641
+ * A prismatic (slider) joint — the child translates along `axis` by `value`
2642
+ * units. Only `axis.direction` is used; `axis.origin` is ignored (a pure
2643
+ * translation has no anchor point), unlike a revolute joint which rotates about
2644
+ * the axis line through `origin`.
2645
+ */
2646
+ function prismaticJoint(parent, child, axis, opts = {}) {
2647
+ return makeJoint("prismatic", parent, child, axis, opts, 0, 100);
2648
+ }
2649
+ /** Return a copy of `joint` with its drivable parameter set (clamped to range). */
2650
+ function setJointValue(joint, value) {
2651
+ return {
2652
+ ...joint,
2653
+ value: clamp(value, joint.min, joint.max)
2654
+ };
2655
+ }
2656
+ /**
2657
+ * The child's local rigid transform (relative to the parent) for a joint value.
2658
+ * Defaults to the joint's stored value; an explicit value is clamped to range.
2659
+ *
2660
+ * - **revolute**: rotation of `value` degrees about the axis line. Rotating
2661
+ * about a line through `origin` is `p ↦ R·p + (origin − R·origin)`.
2662
+ * - **prismatic**: translation of `value` units along the axis direction.
2663
+ */
2664
+ function jointTransform(joint, value = joint.value) {
2665
+ const v = clamp(value, joint.min, joint.max);
2666
+ const dir = unit(joint.axis.direction);
2667
+ if (joint.type === "prismatic") return {
2668
+ position: [
2669
+ dir[0] * v,
2670
+ dir[1] * v,
2671
+ dir[2] * v
2672
+ ],
2673
+ rotation: [
2674
+ 1,
2675
+ 0,
2676
+ 0,
2677
+ 0
2678
+ ]
2679
+ };
2680
+ const rotation = quatFromAxisAngle(dir, v * DEG2RAD$1);
2681
+ const o = joint.axis.origin;
2682
+ const ro = quatRotate(rotation, o);
2683
+ return {
2684
+ position: [
2685
+ o[0] - ro[0],
2686
+ o[1] - ro[1],
2687
+ o[2] - ro[2]
2688
+ ],
2689
+ rotation
2690
+ };
2691
+ }
2692
+ /** Attach a joint to an assembly node. Returns a new node (immutable). */
2693
+ function addJoint(assembly, joint) {
2694
+ const existing = assembly.joints ?? [];
2695
+ return {
2696
+ ...assembly,
2697
+ joints: [...existing, joint]
2698
+ };
2699
+ }
2700
+ //#endregion
2570
2701
  //#region src/measurement/interferenceFns.ts
2571
2702
  /**
2572
2703
  * Interference detection between shapes.
@@ -6365,6 +6496,7 @@ exports.Sketcher = require_drawFns.Sketcher;
6365
6496
  exports.Sketches = require_textBlueprints.Sketches;
6366
6497
  exports.addChild = require_historyFns.addChild;
6367
6498
  exports.addHoles = require_primitiveFns.addHoles;
6499
+ exports.addJoint = addJoint;
6368
6500
  exports.addMate = addMate;
6369
6501
  exports.addStep = require_historyFns.addStep;
6370
6502
  exports.adjacentFaces = require_primitiveFns.adjacentFaces;
@@ -6682,6 +6814,7 @@ exports.iterSolids = require_topologyQueryFns.iterSolids;
6682
6814
  exports.iterTopo = require_faceFns.iterTopo;
6683
6815
  exports.iterVertices = require_topologyQueryFns.iterVertices;
6684
6816
  exports.iterWires = require_topologyQueryFns.iterWires;
6817
+ exports.jointTransform = jointTransform;
6685
6818
  exports.kernelCall = require_topologyQueryFns.kernelCall;
6686
6819
  exports.kernelCallRaw = require_topologyQueryFns.kernelCallRaw;
6687
6820
  exports.kernelCallScoped = require_topologyQueryFns.kernelCallScoped;
@@ -6776,6 +6909,7 @@ Object.defineProperty(exports, "primitives", {
6776
6909
  return primitives_exports;
6777
6910
  }
6778
6911
  });
6912
+ exports.prismaticJoint = prismaticJoint;
6779
6913
  exports.projectEdges = require_cameraFns.projectEdges;
6780
6914
  exports.projectPointOnFace = require_faceFns.projectPointOnFace;
6781
6915
  Object.defineProperty(exports, "query", {
@@ -6807,6 +6941,7 @@ exports.resolveDirection = require_types.resolveDirection;
6807
6941
  exports.resolvePlane = require_planeOps.resolvePlane;
6808
6942
  exports.resolveRef = require_shapeRefFns.resolveRef;
6809
6943
  exports.reverseCurve = require_blueprintFns.reverseCurve;
6944
+ exports.revoluteJoint = revoluteJoint;
6810
6945
  exports.revolve = revolve;
6811
6946
  exports.roof = roof;
6812
6947
  exports.rotate = rotate;
@@ -6835,6 +6970,7 @@ exports.sdfTorus = torus;
6835
6970
  exports.section = section;
6836
6971
  exports.sectionToFace = sectionToFace;
6837
6972
  exports.serializeHistory = require_historyFns.serializeHistory;
6973
+ exports.setJointValue = setJointValue;
6838
6974
  exports.setShapeOrigin = require_shapeFns.setShapeOrigin;
6839
6975
  exports.setTagMetadata = require_shapeFns.setTagMetadata;
6840
6976
  exports.sewShells = require_primitiveFns.sewShells;
package/dist/brepjs.js CHANGED
@@ -2143,8 +2143,88 @@ function roof(w, options) {
2143
2143
  }
2144
2144
  }
2145
2145
  //#endregion
2146
+ //#region src/utils/quaternion.ts
2147
+ function dot$1(a, b) {
2148
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
2149
+ }
2150
+ function cross$1(a, b) {
2151
+ return [
2152
+ a[1] * b[2] - a[2] * b[1],
2153
+ a[2] * b[0] - a[0] * b[2],
2154
+ a[0] * b[1] - a[1] * b[0]
2155
+ ];
2156
+ }
2157
+ function normalize$1(a) {
2158
+ const l = Math.hypot(a[0], a[1], a[2]) || 1;
2159
+ return [
2160
+ a[0] / l,
2161
+ a[1] / l,
2162
+ a[2] / l
2163
+ ];
2164
+ }
2165
+ /** A unit vector perpendicular to `v` (for the 180°/parallel degenerate cases). */
2166
+ function anyPerpendicular$1(v) {
2167
+ return normalize$1(cross$1(v, Math.abs(v[0]) < .9 ? [
2168
+ 1,
2169
+ 0,
2170
+ 0
2171
+ ] : [
2172
+ 0,
2173
+ 1,
2174
+ 0
2175
+ ]));
2176
+ }
2177
+ /** Rotate vector `v` by quaternion `q`. */
2178
+ function quatRotate(q, v) {
2179
+ const [w, x, y, z] = q;
2180
+ const tx = 2 * (y * v[2] - z * v[1]);
2181
+ const ty = 2 * (z * v[0] - x * v[2]);
2182
+ const tz = 2 * (x * v[1] - y * v[0]);
2183
+ return [
2184
+ v[0] + w * tx + (y * tz - z * ty),
2185
+ v[1] + w * ty + (z * tx - x * tz),
2186
+ v[2] + w * tz + (x * ty - y * tx)
2187
+ ];
2188
+ }
2189
+ /** Quaternion for a rotation of `angle` radians about (unit-normalized) `axis`. */
2190
+ function quatFromAxisAngle(axis, angle) {
2191
+ const h = angle / 2;
2192
+ const s = Math.sin(h);
2193
+ const u = normalize$1(axis);
2194
+ return [
2195
+ Math.cos(h),
2196
+ u[0] * s,
2197
+ u[1] * s,
2198
+ u[2] * s
2199
+ ];
2200
+ }
2201
+ /** Shortest-arc quaternion rotating unit vector `from` onto unit vector `to`. */
2202
+ function quatFromTo(from, to) {
2203
+ const a = normalize$1(from);
2204
+ const b = normalize$1(to);
2205
+ const d = dot$1(a, b);
2206
+ if (d >= .999999999) return [
2207
+ 1,
2208
+ 0,
2209
+ 0,
2210
+ 0
2211
+ ];
2212
+ if (d <= -.999999999) return quatFromAxisAngle(anyPerpendicular$1(a), Math.PI);
2213
+ const c = cross$1(a, b);
2214
+ const len = Math.hypot(1 + d, c[0], c[1], c[2]) || 1;
2215
+ return [
2216
+ (1 + d) / len,
2217
+ c[0] / len,
2218
+ c[1] / len,
2219
+ c[2] / len
2220
+ ];
2221
+ }
2222
+ //#endregion
2146
2223
  //#region src/kernel/solverAdapter.ts
2147
2224
  /**
2225
+ * Constraint solver adapter — analytical solver for simple assembly mates.
2226
+ */
2227
+ /**
2148
2228
  * Degrees of freedom each constraint leaves unresolved when it can't be applied
2149
2229
  * (entity-type mismatch or an unreachable reference). All four types now solve
2150
2230
  * for well-typed inputs; these counts only feed the diagnostic `dof` for the
@@ -2203,7 +2283,7 @@ function normalize(a) {
2203
2283
  a[2] / l
2204
2284
  ];
2205
2285
  }
2206
- /** A unit vector perpendicular to `v` (for the 180° / parallel degenerate cases). */
2286
+ /** A unit vector perpendicular to `v` (for the parallel-normals degenerate case). */
2207
2287
  function anyPerpendicular(v) {
2208
2288
  return normalize(cross(v, Math.abs(v[0]) < .9 ? [
2209
2289
  1,
@@ -2215,59 +2295,14 @@ function anyPerpendicular(v) {
2215
2295
  0
2216
2296
  ]));
2217
2297
  }
2218
- /** Rotate vector `v` by quaternion `q` = [w, x, y, z]. */
2219
- function qRotate(q, v) {
2220
- const [w, x, y, z] = q;
2221
- const tx = 2 * (y * v[2] - z * v[1]);
2222
- const ty = 2 * (z * v[0] - x * v[2]);
2223
- const tz = 2 * (x * v[1] - y * v[0]);
2224
- return [
2225
- v[0] + w * tx + (y * tz - z * ty),
2226
- v[1] + w * ty + (z * tx - x * tz),
2227
- v[2] + w * tz + (x * ty - y * tx)
2228
- ];
2229
- }
2230
- function qFromAxisAngle(axis, angle) {
2231
- const h = angle / 2;
2232
- const s = Math.sin(h);
2233
- const u = normalize(axis);
2234
- return [
2235
- Math.cos(h),
2236
- u[0] * s,
2237
- u[1] * s,
2238
- u[2] * s
2239
- ];
2240
- }
2241
- /** Shortest-arc quaternion rotating unit vector `from` onto unit vector `to`. */
2242
- function qFromTo(from, to) {
2243
- const a = normalize(from);
2244
- const b = normalize(to);
2245
- const d = dot(a, b);
2246
- if (d >= .999999999) return IDENTITY_ROTATION;
2247
- if (d <= -.999999999) return qFromAxisAngle(anyPerpendicular(a), Math.PI);
2248
- const c = cross(a, b);
2249
- const q = [
2250
- 1 + d,
2251
- c[0],
2252
- c[1],
2253
- c[2]
2254
- ];
2255
- const l = Math.hypot(q[0], q[1], q[2], q[3]) || 1;
2256
- return [
2257
- q[0] / l,
2258
- q[1] / l,
2259
- q[2] / l,
2260
- q[3] / l
2261
- ];
2262
- }
2263
2298
  /** Apply a pose (rotate then translate) to an entity's origin and any directions. */
2264
2299
  function transformEntity(e, pose) {
2265
- const origin = add$1(qRotate(pose.rotation, e.origin), pose.position);
2300
+ const origin = add$1(quatRotate(pose.rotation, e.origin), pose.position);
2266
2301
  return {
2267
2302
  type: e.type,
2268
2303
  origin,
2269
- ...e.normal ? { normal: qRotate(pose.rotation, e.normal) } : {},
2270
- ...e.direction ? { direction: qRotate(pose.rotation, e.direction) } : {}
2304
+ ...e.normal ? { normal: quatRotate(pose.rotation, e.normal) } : {},
2305
+ ...e.direction ? { direction: quatRotate(pose.rotation, e.direction) } : {}
2271
2306
  };
2272
2307
  }
2273
2308
  /**
@@ -2301,12 +2336,12 @@ function solveConcentric(ref, dep) {
2301
2336
  0,
2302
2337
  1
2303
2338
  ];
2304
- const rotation = qFromTo(dep.direction ?? [
2339
+ const rotation = quatFromTo(dep.direction ?? [
2305
2340
  0,
2306
2341
  0,
2307
2342
  1
2308
2343
  ], dRef);
2309
- const rotatedOrigin = qRotate(rotation, dep.origin);
2344
+ const rotatedOrigin = quatRotate(rotation, dep.origin);
2310
2345
  return {
2311
2346
  position: sub(ref.origin, rotatedOrigin),
2312
2347
  rotation
@@ -2336,7 +2371,7 @@ function solveAngle(ref, dep, angleRad) {
2336
2371
  0,
2337
2372
  0
2338
2373
  ],
2339
- rotation: qFromAxisAngle(Math.hypot(c[0], c[1], c[2]) < 1e-9 ? anyPerpendicular(nDep) : c, phi - angleRad)
2374
+ rotation: quatFromAxisAngle(Math.hypot(c[0], c[1], c[2]) < 1e-9 ? anyPerpendicular(nDep) : c, phi - angleRad)
2340
2375
  };
2341
2376
  }
2342
2377
  /** Entity types each positioning constraint requires of (entityA, entityB). */
@@ -2578,6 +2613,102 @@ function solveAssembly(assembly) {
2578
2613
  }
2579
2614
  }
2580
2615
  //#endregion
2616
+ //#region src/operations/jointFns.ts
2617
+ var DEG2RAD$1 = Math.PI / 180;
2618
+ function clamp(value, min, max) {
2619
+ return Math.min(max, Math.max(min, value));
2620
+ }
2621
+ function unit(v) {
2622
+ const l = Math.hypot(v[0], v[1], v[2]) || 1;
2623
+ return [
2624
+ v[0] / l,
2625
+ v[1] / l,
2626
+ v[2] / l
2627
+ ];
2628
+ }
2629
+ function makeJoint(type, parent, child, axis, opts, defMin, defMax) {
2630
+ const a = opts.min ?? defMin;
2631
+ const b = opts.max ?? defMax;
2632
+ const min = Math.min(a, b);
2633
+ const max = Math.max(a, b);
2634
+ return {
2635
+ type,
2636
+ parent,
2637
+ child,
2638
+ axis: {
2639
+ origin: axis.origin,
2640
+ direction: unit(axis.direction)
2641
+ },
2642
+ min,
2643
+ max,
2644
+ value: clamp(opts.value ?? 0, min, max)
2645
+ };
2646
+ }
2647
+ /** A revolute (hinge) joint — the child rotates about `axis` by `value` degrees. */
2648
+ function revoluteJoint(parent, child, axis, opts = {}) {
2649
+ return makeJoint("revolute", parent, child, axis, opts, -180, 180);
2650
+ }
2651
+ /**
2652
+ * A prismatic (slider) joint — the child translates along `axis` by `value`
2653
+ * units. Only `axis.direction` is used; `axis.origin` is ignored (a pure
2654
+ * translation has no anchor point), unlike a revolute joint which rotates about
2655
+ * the axis line through `origin`.
2656
+ */
2657
+ function prismaticJoint(parent, child, axis, opts = {}) {
2658
+ return makeJoint("prismatic", parent, child, axis, opts, 0, 100);
2659
+ }
2660
+ /** Return a copy of `joint` with its drivable parameter set (clamped to range). */
2661
+ function setJointValue(joint, value) {
2662
+ return {
2663
+ ...joint,
2664
+ value: clamp(value, joint.min, joint.max)
2665
+ };
2666
+ }
2667
+ /**
2668
+ * The child's local rigid transform (relative to the parent) for a joint value.
2669
+ * Defaults to the joint's stored value; an explicit value is clamped to range.
2670
+ *
2671
+ * - **revolute**: rotation of `value` degrees about the axis line. Rotating
2672
+ * about a line through `origin` is `p ↦ R·p + (origin − R·origin)`.
2673
+ * - **prismatic**: translation of `value` units along the axis direction.
2674
+ */
2675
+ function jointTransform(joint, value = joint.value) {
2676
+ const v = clamp(value, joint.min, joint.max);
2677
+ const dir = unit(joint.axis.direction);
2678
+ if (joint.type === "prismatic") return {
2679
+ position: [
2680
+ dir[0] * v,
2681
+ dir[1] * v,
2682
+ dir[2] * v
2683
+ ],
2684
+ rotation: [
2685
+ 1,
2686
+ 0,
2687
+ 0,
2688
+ 0
2689
+ ]
2690
+ };
2691
+ const rotation = quatFromAxisAngle(dir, v * DEG2RAD$1);
2692
+ const o = joint.axis.origin;
2693
+ const ro = quatRotate(rotation, o);
2694
+ return {
2695
+ position: [
2696
+ o[0] - ro[0],
2697
+ o[1] - ro[1],
2698
+ o[2] - ro[2]
2699
+ ],
2700
+ rotation
2701
+ };
2702
+ }
2703
+ /** Attach a joint to an assembly node. Returns a new node (immutable). */
2704
+ function addJoint(assembly, joint) {
2705
+ const existing = assembly.joints ?? [];
2706
+ return {
2707
+ ...assembly,
2708
+ joints: [...existing, joint]
2709
+ };
2710
+ }
2711
+ //#endregion
2581
2712
  //#region src/measurement/interferenceFns.ts
2582
2713
  /**
2583
2714
  * Interference detection between shapes.
@@ -6347,4 +6478,4 @@ var csg_exports = /* @__PURE__ */ __exportAll({
6347
6478
  withEvaluator: () => withEvaluator
6348
6479
  });
6349
6480
  //#endregion
6350
- export { BaseSketcher2d, BlueprintSketcher, BrepBugError, BrepErrorCode, BrepWrapperError, BrepkitAdapter, CompoundSketch, DEFAULT_CAPABILITIES, DEG2RAD, DisposalScope, EXACT_BREP_CAPABILITIES, FaceSketcher, HASH_CODE_MAX, OK, OcctWasmAdapter, RAD2DEG, Sketch, Sketcher, Sketches, addChild, addHoles, addMate, addStep, adjacentFaces, all, andThen, applyGlue, applyMatrix, approximateCurve, as2D, as3D, asTopo, assignRoles, autoHeal, bezier, blueprintToDXF, booleanPipeline, booleans_exports as booleans, boss, box, bsplineApprox, bug, cameraFromPlane, cameraLookAt, captureHint, cast, castShape, castShape3D, chamfer, chamferDistAngle as chamferDistAngleShape, chamferWithEvolution, checkAllInterferences, checkBoolean, checkInterference, circle, circularPattern, classifyPointOnFace, clearMeshCache, clone, closedWire, collect, collectShapes, colorFaces, colorShape, complexExtrude, composeTransforms, compound, compoundSketchExtrude, compoundSketchFace, compoundSketchLoft, compoundSketchRevolve, computationError, computeStraightSkeleton, cone, construction_exports as construction, convexHull, cornerFinder, countNodes, createAssembly, createAssemblyNode, createBlueprint, createCamera, createCompound, createCompoundBlueprint, createDistanceQuery, createEdge, createFace, createHandle, createHistory, createKernelHandle, createMeshCache, createNamedPlane, createOperationRegistry, createPlane, createRef, createRegistry, createShell, createSolid, createTaskQueue, createVertex, createWire, createWorkerClient, createWorkerHandler, csg_exports as csg, currentQuality, curve2dBoundingBox, curve2dDistanceFrom, curve2dFirstPoint, curve2dIsOnCurve, curve2dLastPoint, curve2dParameter, curve2dSplitAt, curve2dTangentAt, curveEndPoint, curveIsClosed, curveIsPeriodic, curveLength, curvePeriod, curvePointAt, curveStartPoint, curveTangentAt, cut, cut2D, cutAll, cutAllBisect, cutBlueprints, cutWithEvolution, cylinder, defaultScorer, dequeueTask, describe, deserializeDrawing, deserializeHistory, fromBREP as deserializeShape, downcast, draft, draw, drawCircle, drawEllipse, drawFaceOutline, drawParametricFunction, drawPointsInterpolation, drawPolysides, drawProjection, drawRectangle, drawRoundedRectangle, drawSingleCircle, drawSingleEllipse, drawText, drawingChamfer, drawingCut, drawingFillet, drawingFuse, drawingIntersect, drawingToSketchOnPlane, drill, edgeFinder, edgesOfFace, ellipse, ellipseArc, ellipsoid, enqueueTask, err, exportAssemblySTEP, exportDXF, exportGlb, exportGltf, exportIGES, exportOBJ, exportSTEP, exportSTEPConfigured, exportSTL, exportThreeMF, extrude, extrudeAll, face, faceAxis, faceCenter, faceFinder, faceGeomType, faceOrientation, facesOfEdge, fieldBoolean, fieldContour, fieldOffset, fieldReinit, fieldShell, fill, filledFace, fillet, filletWithEvolution, findFacesByTag, findNode, findStep, fixSelfIntersection, fixShape, flatMap, flatten, flipFaceOrientation, flipOrientation, fontMetrics, fromBREP$1 as fromBREP, fromKernelDir, fromKernelPnt, fromKernelVec, fromNullable, fuse, fuse2D, fuseAll, fuseAllBisect, fuseBlueprints, fuseWithEvolution, gearGeometry, getActiveVoxelId, getBounds, getBounds2D, getCompSolids, getCurveType, getDisposalStats, getEdges, getFaceColor, getFaceOrigins, getFaceTags, getFaces, getFont, getHashCode, getShape as getHistoryShape, getKernel, getKernelCapabilities, getKernelTier, getNurbsCurveData, getNurbsSurfaceData, getOrientation, getOrientation2D, getPerformanceStats, getShapeColor, getShapeKind, getShells, getSingleFace, getSolids, getSurfaceType, getTagMetadata, getVertices, getVoxel, getWires, guidedSweep, heal, healFace, healSolid, healWire, helix, hull, importDXF, importGLB, importIGES, importOBJ, importSTEP, importSTL, importSVG, importSVGPathD, importThreeMF, init, initFromManifold, initFromOC, initVoxel, innerWires, interpolateCurve, intersect, intersect2D, intersectBlueprints, intersectWithEvolution, invalidateShapeCache, ioNs_exports as io, ioError, is2D, is3D, isChamferRadius, isClosedWire, isCompSolid, isCompound, isDisposeRequest, isEdge, isEmpty, isEqualShape, isErr, isErrorResponse, isFace, isFilletRadius, isInitRequest, isInside2D, isLive, isManifoldShell, isNumber, isOk, isOperationRequest, isOrientedFace, isPlanarFace, isPlanarWire, isProjectionPlane, isEmpty$1 as isQueueEmpty, isSameShape, isShape1D, isShape3D, isShell, isSolid, isSuccessResponse, isValid, isValidSolid, isVertex, isWire, iterCompSolids, iterEdges, iterFaces, iterShells, iterSolids, iterTopo, iterVertices, iterWires, kernelCall, kernelCallRaw, kernelCallScoped, kernelError, latticeInfill, latticeInfillShape, line, linearPattern, loadFont, loft, loftAll, makeBaseBox, makeExternalGear, makeInternalGear, makePlane, makePlanetaryGear, makeProjectedEdges, manifoldShell, map, mapBoth, mapErr, match, measureArea, measureCurvatureAt, measureCurvatureAtMid, measureDistance, measureDistanceProps, measureLength, measureLinearProps, measureSurfaceProps, measureVolume, measureVolumeProps, measurement_exports as measurement, mesh, meshEdges, meshMultiLOD, minkowski, mirror, mirror2D, mirrorDrawing, mirrorJoin, modifiers_exports as modifiers, modifyStep, moduleInitError, multiSectionSweep, normalAt, offset, offsetFace, offsetMesh, offsetShape, offsetWire2D, ok, or, orElse, organiseBlueprints, orientedFace, outerWire, patterns_exports as patterns, pendingCount, pipeline, pivotPlane, planarFace, planarWire, planetPlacements, pocket, pointOnSurface, pointsInside, polygon, polyhedron, polysideInnerRadius, polysidesBlueprint, positionOnCurve, prewarm, primitives_exports as primitives, projectEdges, projectPointOnFace, query_exports as query, queryError, rectangularPattern, registerHandler, registerKernel, registerKernelTier, registerOperation, registerShape, registerVoxel, rejectAll, removeChild, removeHolesFromFace, repairMesh, replayFrom, replayHistory, resetDisposalStats, resetPerformanceStats, resize, resolve, resolve3D, resolveDirection, resolvePlane, resolveRef, reverseCurve, revolve, roof, rotate, rotate2D, rotateDrawing, roundedRectangleBlueprint, scale, scale2D, scaleDrawing, box$1 as sdfBox, capsule as sdfCapsule, cone$1 as sdfCone, cylinder$1 as sdfCylinder, fieldAxialRamp as sdfFieldAxialRamp, fieldClamp as sdfFieldClamp, fieldConst as sdfFieldConst, fieldFromSdf as sdfFieldFromSdf, fieldRadialRamp as sdfFieldRadialRamp, lattice as sdfLattice, plane as sdfPlane, roundedBox as sdfRoundedBox, sphere as sdfSphere, strutLattice as sdfStrutLattice, sweep as sdfSweep, torus as sdfTorus, section, sectionToFace, serializeHistory, setShapeOrigin, setTagMetadata, sewShells, shape, shapeToMeshInput, shapeType, sharedEdges, shell, shellMesh, shellShape, shellWithEvolution, simplify, sketchCircle, sketchEllipse, sketchExtrude, sketchFace, sketchFaceOffset, sketchHelix, sketchLoft, sketchOnFace2D, sketchOnPlane2D, sketchParametricFunction, sketchPolysides, sketchRectangle, sketchRevolve, sketchRoundedRectangle, sketchSweep, sketchText, sketchWires, sketcherStateError, slice, solid, solidFromShell, solveAssembly, sphere$1 as sphere, split, stepCount, stepsFrom, stretch2D, subFace, supportExtrude, supportsConstraintSketch, supportsProjection, surfaceFromGrid, surfaceFromImage, sweep$1 as sweep, tagFaces, tangentArc, tap, tapErr, textBlueprints, textMetrics, thicken, threePointArc, toBREP, toBufferGeometryData, toGroupedBufferGeometryData, toKernelVec, toLODGeometryData, toLineGeometryData, toSVGPathD, toVec2, toVec3, torus$1 as torus, tpmsLattice, transformCopy, transforms_exports as transforms, translate, translate2D, translateDrawing, translatePlane, tryCatch, tryCatchAsync, twistExtrude, typeCastError, undoLast, unsupportedError, unwrap, unwrapErr, unwrapOr, unwrapOrElse, updateNode, updateRoles, uvBounds, uvCoordinates, validSolid, validatePlanetary, validationError, variableFillet, vecAdd, vecAngle, vecCross, vecDistance, vecDot, vecEquals, vecIsZero, vecLength, vecLengthSq, vecNegate, vecNormalize, vecProjectToPlane, vecRepr, vecRotate, vecScale, vecSub, vertex, vertexFinder, vertexPosition, verticesOfEdge, voxelBoolean, voxelBooleanField, voxelBooleanFieldShapes, voxelBooleanShapes, voxelField, voxelFieldFromShape, walkAssembly, windingNumbers, wire, wireFinder, wireLoop, wiresOfFace, withKernel, withKernelDir, withKernelPnt, withKernelVec, withQuality, withScope, withScopeResult, withScopeResultAsync, withTier, zip as zipResults };
6481
+ export { BaseSketcher2d, BlueprintSketcher, BrepBugError, BrepErrorCode, BrepWrapperError, BrepkitAdapter, CompoundSketch, DEFAULT_CAPABILITIES, DEG2RAD, DisposalScope, EXACT_BREP_CAPABILITIES, FaceSketcher, HASH_CODE_MAX, OK, OcctWasmAdapter, RAD2DEG, Sketch, Sketcher, Sketches, addChild, addHoles, addJoint, addMate, addStep, adjacentFaces, all, andThen, applyGlue, applyMatrix, approximateCurve, as2D, as3D, asTopo, assignRoles, autoHeal, bezier, blueprintToDXF, booleanPipeline, booleans_exports as booleans, boss, box, bsplineApprox, bug, cameraFromPlane, cameraLookAt, captureHint, cast, castShape, castShape3D, chamfer, chamferDistAngle as chamferDistAngleShape, chamferWithEvolution, checkAllInterferences, checkBoolean, checkInterference, circle, circularPattern, classifyPointOnFace, clearMeshCache, clone, closedWire, collect, collectShapes, colorFaces, colorShape, complexExtrude, composeTransforms, compound, compoundSketchExtrude, compoundSketchFace, compoundSketchLoft, compoundSketchRevolve, computationError, computeStraightSkeleton, cone, construction_exports as construction, convexHull, cornerFinder, countNodes, createAssembly, createAssemblyNode, createBlueprint, createCamera, createCompound, createCompoundBlueprint, createDistanceQuery, createEdge, createFace, createHandle, createHistory, createKernelHandle, createMeshCache, createNamedPlane, createOperationRegistry, createPlane, createRef, createRegistry, createShell, createSolid, createTaskQueue, createVertex, createWire, createWorkerClient, createWorkerHandler, csg_exports as csg, currentQuality, curve2dBoundingBox, curve2dDistanceFrom, curve2dFirstPoint, curve2dIsOnCurve, curve2dLastPoint, curve2dParameter, curve2dSplitAt, curve2dTangentAt, curveEndPoint, curveIsClosed, curveIsPeriodic, curveLength, curvePeriod, curvePointAt, curveStartPoint, curveTangentAt, cut, cut2D, cutAll, cutAllBisect, cutBlueprints, cutWithEvolution, cylinder, defaultScorer, dequeueTask, describe, deserializeDrawing, deserializeHistory, fromBREP as deserializeShape, downcast, draft, draw, drawCircle, drawEllipse, drawFaceOutline, drawParametricFunction, drawPointsInterpolation, drawPolysides, drawProjection, drawRectangle, drawRoundedRectangle, drawSingleCircle, drawSingleEllipse, drawText, drawingChamfer, drawingCut, drawingFillet, drawingFuse, drawingIntersect, drawingToSketchOnPlane, drill, edgeFinder, edgesOfFace, ellipse, ellipseArc, ellipsoid, enqueueTask, err, exportAssemblySTEP, exportDXF, exportGlb, exportGltf, exportIGES, exportOBJ, exportSTEP, exportSTEPConfigured, exportSTL, exportThreeMF, extrude, extrudeAll, face, faceAxis, faceCenter, faceFinder, faceGeomType, faceOrientation, facesOfEdge, fieldBoolean, fieldContour, fieldOffset, fieldReinit, fieldShell, fill, filledFace, fillet, filletWithEvolution, findFacesByTag, findNode, findStep, fixSelfIntersection, fixShape, flatMap, flatten, flipFaceOrientation, flipOrientation, fontMetrics, fromBREP$1 as fromBREP, fromKernelDir, fromKernelPnt, fromKernelVec, fromNullable, fuse, fuse2D, fuseAll, fuseAllBisect, fuseBlueprints, fuseWithEvolution, gearGeometry, getActiveVoxelId, getBounds, getBounds2D, getCompSolids, getCurveType, getDisposalStats, getEdges, getFaceColor, getFaceOrigins, getFaceTags, getFaces, getFont, getHashCode, getShape as getHistoryShape, getKernel, getKernelCapabilities, getKernelTier, getNurbsCurveData, getNurbsSurfaceData, getOrientation, getOrientation2D, getPerformanceStats, getShapeColor, getShapeKind, getShells, getSingleFace, getSolids, getSurfaceType, getTagMetadata, getVertices, getVoxel, getWires, guidedSweep, heal, healFace, healSolid, healWire, helix, hull, importDXF, importGLB, importIGES, importOBJ, importSTEP, importSTL, importSVG, importSVGPathD, importThreeMF, init, initFromManifold, initFromOC, initVoxel, innerWires, interpolateCurve, intersect, intersect2D, intersectBlueprints, intersectWithEvolution, invalidateShapeCache, ioNs_exports as io, ioError, is2D, is3D, isChamferRadius, isClosedWire, isCompSolid, isCompound, isDisposeRequest, isEdge, isEmpty, isEqualShape, isErr, isErrorResponse, isFace, isFilletRadius, isInitRequest, isInside2D, isLive, isManifoldShell, isNumber, isOk, isOperationRequest, isOrientedFace, isPlanarFace, isPlanarWire, isProjectionPlane, isEmpty$1 as isQueueEmpty, isSameShape, isShape1D, isShape3D, isShell, isSolid, isSuccessResponse, isValid, isValidSolid, isVertex, isWire, iterCompSolids, iterEdges, iterFaces, iterShells, iterSolids, iterTopo, iterVertices, iterWires, jointTransform, kernelCall, kernelCallRaw, kernelCallScoped, kernelError, latticeInfill, latticeInfillShape, line, linearPattern, loadFont, loft, loftAll, makeBaseBox, makeExternalGear, makeInternalGear, makePlane, makePlanetaryGear, makeProjectedEdges, manifoldShell, map, mapBoth, mapErr, match, measureArea, measureCurvatureAt, measureCurvatureAtMid, measureDistance, measureDistanceProps, measureLength, measureLinearProps, measureSurfaceProps, measureVolume, measureVolumeProps, measurement_exports as measurement, mesh, meshEdges, meshMultiLOD, minkowski, mirror, mirror2D, mirrorDrawing, mirrorJoin, modifiers_exports as modifiers, modifyStep, moduleInitError, multiSectionSweep, normalAt, offset, offsetFace, offsetMesh, offsetShape, offsetWire2D, ok, or, orElse, organiseBlueprints, orientedFace, outerWire, patterns_exports as patterns, pendingCount, pipeline, pivotPlane, planarFace, planarWire, planetPlacements, pocket, pointOnSurface, pointsInside, polygon, polyhedron, polysideInnerRadius, polysidesBlueprint, positionOnCurve, prewarm, primitives_exports as primitives, prismaticJoint, projectEdges, projectPointOnFace, query_exports as query, queryError, rectangularPattern, registerHandler, registerKernel, registerKernelTier, registerOperation, registerShape, registerVoxel, rejectAll, removeChild, removeHolesFromFace, repairMesh, replayFrom, replayHistory, resetDisposalStats, resetPerformanceStats, resize, resolve, resolve3D, resolveDirection, resolvePlane, resolveRef, reverseCurve, revoluteJoint, revolve, roof, rotate, rotate2D, rotateDrawing, roundedRectangleBlueprint, scale, scale2D, scaleDrawing, box$1 as sdfBox, capsule as sdfCapsule, cone$1 as sdfCone, cylinder$1 as sdfCylinder, fieldAxialRamp as sdfFieldAxialRamp, fieldClamp as sdfFieldClamp, fieldConst as sdfFieldConst, fieldFromSdf as sdfFieldFromSdf, fieldRadialRamp as sdfFieldRadialRamp, lattice as sdfLattice, plane as sdfPlane, roundedBox as sdfRoundedBox, sphere as sdfSphere, strutLattice as sdfStrutLattice, sweep as sdfSweep, torus as sdfTorus, section, sectionToFace, serializeHistory, setJointValue, setShapeOrigin, setTagMetadata, sewShells, shape, shapeToMeshInput, shapeType, sharedEdges, shell, shellMesh, shellShape, shellWithEvolution, simplify, sketchCircle, sketchEllipse, sketchExtrude, sketchFace, sketchFaceOffset, sketchHelix, sketchLoft, sketchOnFace2D, sketchOnPlane2D, sketchParametricFunction, sketchPolysides, sketchRectangle, sketchRevolve, sketchRoundedRectangle, sketchSweep, sketchText, sketchWires, sketcherStateError, slice, solid, solidFromShell, solveAssembly, sphere$1 as sphere, split, stepCount, stepsFrom, stretch2D, subFace, supportExtrude, supportsConstraintSketch, supportsProjection, surfaceFromGrid, surfaceFromImage, sweep$1 as sweep, tagFaces, tangentArc, tap, tapErr, textBlueprints, textMetrics, thicken, threePointArc, toBREP, toBufferGeometryData, toGroupedBufferGeometryData, toKernelVec, toLODGeometryData, toLineGeometryData, toSVGPathD, toVec2, toVec3, torus$1 as torus, tpmsLattice, transformCopy, transforms_exports as transforms, translate, translate2D, translateDrawing, translatePlane, tryCatch, tryCatchAsync, twistExtrude, typeCastError, undoLast, unsupportedError, unwrap, unwrapErr, unwrapOr, unwrapOrElse, updateNode, updateRoles, uvBounds, uvCoordinates, validSolid, validatePlanetary, validationError, variableFillet, vecAdd, vecAngle, vecCross, vecDistance, vecDot, vecEquals, vecIsZero, vecLength, vecLengthSq, vecNegate, vecNormalize, vecProjectToPlane, vecRepr, vecRotate, vecScale, vecSub, vertex, vertexFinder, vertexPosition, verticesOfEdge, voxelBoolean, voxelBooleanField, voxelBooleanFieldShapes, voxelBooleanShapes, voxelField, voxelFieldFromShape, walkAssembly, windingNumbers, wire, wireFinder, wireLoop, wiresOfFace, withKernel, withKernelDir, withKernelPnt, withKernelVec, withQuality, withScope, withScopeResult, withScopeResultAsync, withTier, zip as zipResults };
package/dist/index.d.ts CHANGED
@@ -121,6 +121,7 @@ export { exportAssemblySTEP, type ShapeOptions, type SupportedUnit, } from './op
121
121
  export { linearPattern, circularPattern } from './operations/patternFns.js';
122
122
  export { createAssemblyNode, addChild, removeChild, updateNode, findNode, walkAssembly, countNodes, collectShapes, type AssemblyNode, type AssemblyNodeOptions, } from './operations/assemblyFns.js';
123
123
  export { addMate, solveAssembly, type MateConstraint, type MateEntity, type AssemblySolveResult, } from './operations/mateFns.js';
124
+ export { revoluteJoint, prismaticJoint, setJointValue, jointTransform, addJoint, type Joint, type JointAxis, type JointType, type JointPose, type JointOptions, } from './operations/jointFns.js';
124
125
  export { createHistory, addStep, undoLast, findStep, getShape as getHistoryShape, stepCount, stepsFrom, registerShape, createRegistry, registerOperation, replayHistory, replayFrom, modifyStep, serializeHistory, deserializeHistory, type OperationStep, type ModelHistory, type SerializedHistory, type OperationFn, type OperationRegistry as HistoryOperationRegistry, } from './operations/historyFns.js';
125
126
  export { measureVolume, measureArea, measureLength, measureDistance, measureDistanceProps, createDistanceQuery, measureVolumeProps, measureSurfaceProps, measureLinearProps, type PhysicalProps, type VolumeProps, type SurfaceProps, type LinearProps, type DistanceProps, measureCurvatureAt, measureCurvatureAtMid, type CurvatureResult, } from './measurement/measureFns.js';
126
127
  export { checkInterference, checkAllInterferences, type InterferenceResult, type InterferencePair, } from './measurement/interferenceFns.js';
@@ -11,6 +11,8 @@ export interface AssemblyNode {
11
11
  readonly metadata?: Readonly<Record<string, unknown>>;
12
12
  readonly children: ReadonlyArray<AssemblyNode>;
13
13
  readonly mates?: readonly unknown[];
14
+ /** Drivable kinematic joints (see jointFns). Typed loosely to avoid a cycle. */
15
+ readonly joints?: readonly unknown[];
14
16
  }
15
17
  export interface AssemblyNodeOptions {
16
18
  shape?: AnyShape;
@@ -0,0 +1,55 @@
1
+ import { Vec3 } from '../core/types.js';
2
+ import { AssemblyNode } from './assemblyFns.js';
3
+ /** A joint axis: a point on the axis line plus a direction. */
4
+ export interface JointAxis {
5
+ readonly origin: Vec3;
6
+ readonly direction: Vec3;
7
+ }
8
+ export type JointType = 'revolute' | 'prismatic';
9
+ export interface Joint {
10
+ readonly type: JointType;
11
+ /** Reference body (stays put); the child moves relative to it. */
12
+ readonly parent: string;
13
+ readonly child: string;
14
+ readonly axis: JointAxis;
15
+ /** Range bounds — degrees for revolute, length units for prismatic. */
16
+ readonly min: number;
17
+ readonly max: number;
18
+ /** Current drivable parameter, always clamped to `[min, max]`. */
19
+ readonly value: number;
20
+ }
21
+ /** A rigid transform: translation + quaternion rotation `[w, x, y, z]`. */
22
+ export interface JointPose {
23
+ readonly position: Vec3;
24
+ readonly rotation: [number, number, number, number];
25
+ }
26
+ export interface JointOptions {
27
+ /** Range lower bound. Default: -180 (revolute) / 0 (prismatic). */
28
+ min?: number;
29
+ /** Range upper bound. Default: 180 (revolute) / 100 (prismatic). */
30
+ max?: number;
31
+ /** Initial value, clamped to the range. Default: 0. */
32
+ value?: number;
33
+ }
34
+ /** A revolute (hinge) joint — the child rotates about `axis` by `value` degrees. */
35
+ export declare function revoluteJoint(parent: string, child: string, axis: JointAxis, opts?: JointOptions): Joint;
36
+ /**
37
+ * A prismatic (slider) joint — the child translates along `axis` by `value`
38
+ * units. Only `axis.direction` is used; `axis.origin` is ignored (a pure
39
+ * translation has no anchor point), unlike a revolute joint which rotates about
40
+ * the axis line through `origin`.
41
+ */
42
+ export declare function prismaticJoint(parent: string, child: string, axis: JointAxis, opts?: JointOptions): Joint;
43
+ /** Return a copy of `joint` with its drivable parameter set (clamped to range). */
44
+ export declare function setJointValue(joint: Joint, value: number): Joint;
45
+ /**
46
+ * The child's local rigid transform (relative to the parent) for a joint value.
47
+ * Defaults to the joint's stored value; an explicit value is clamped to range.
48
+ *
49
+ * - **revolute**: rotation of `value` degrees about the axis line. Rotating
50
+ * about a line through `origin` is `p ↦ R·p + (origin − R·origin)`.
51
+ * - **prismatic**: translation of `value` units along the axis direction.
52
+ */
53
+ export declare function jointTransform(joint: Joint, value?: number): JointPose;
54
+ /** Attach a joint to an assembly node. Returns a new node (immutable). */
55
+ export declare function addJoint(assembly: AssemblyNode, joint: Joint): AssemblyNode;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Quaternion helpers for rigid rotations, shared by the constraint solver and
3
+ * the joint/kinematics layer. Scalar-first convention: `[w, x, y, z]`.
4
+ *
5
+ * Layer 0 (utils): no internal imports — `Vec3` is declared locally.
6
+ * @module
7
+ */
8
+ export type Vec3 = readonly [number, number, number];
9
+ export type Quat = readonly [number, number, number, number];
10
+ /** Rotate vector `v` by quaternion `q`. */
11
+ export declare function quatRotate(q: Quat, v: Vec3): [number, number, number];
12
+ /** Quaternion for a rotation of `angle` radians about (unit-normalized) `axis`. */
13
+ export declare function quatFromAxisAngle(axis: Vec3, angle: number): [number, number, number, number];
14
+ /** Shortest-arc quaternion rotating unit vector `from` onto unit vector `to`. */
15
+ export declare function quatFromTo(from: Vec3, to: Vec3): [number, number, number, number];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brepjs",
3
- "version": "18.70.0",
3
+ "version": "18.72.0",
4
4
  "description": "Web CAD library with pluggable geometry kernel",
5
5
  "keywords": [
6
6
  "cad",