brepjs 18.69.2 → 18.70.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 (89) hide show
  1. package/dist/2d.cjs +6 -6
  2. package/dist/2d.js +6 -6
  3. package/dist/{blueprint-DIQeD9xj.cjs → blueprint-jlSsZ0sZ.cjs} +5 -5
  4. package/dist/{blueprint-Dgl9IkCV.js → blueprint-qVw9ZkE4.js} +5 -5
  5. package/dist/{blueprintFns-BO44cqFY.cjs → blueprintFns-DsuY7gCu.cjs} +2 -2
  6. package/dist/{blueprintFns-sKzHcJ4U.js → blueprintFns-zLwbytjs.js} +2 -2
  7. package/dist/{blueprintSketcher-DbINWerx.js → blueprintSketcher-BRKbVgE2.js} +3 -3
  8. package/dist/{blueprintSketcher-BpOknLmX.cjs → blueprintSketcher-dZZ8e5ey.cjs} +3 -3
  9. package/dist/{boolean2D-DZcOTOSA.cjs → boolean2D-4E1kbwQx.cjs} +4 -4
  10. package/dist/{boolean2D-CreNaKXt.js → boolean2D-CANP43pN.js} +4 -4
  11. package/dist/{booleanFns-DvXg6a2Y.cjs → booleanFns-Bp_wYEwG.cjs} +4 -4
  12. package/dist/{booleanFns-0jDBFjAv.js → booleanFns-DYSaupiG.js} +4 -4
  13. package/dist/brepjs.cjs +304 -95
  14. package/dist/brepjs.js +306 -98
  15. package/dist/{cameraFns-Bwxq0IDz.js → cameraFns-BFRGMXSn.js} +2 -2
  16. package/dist/{cameraFns-CsGSVYgb.cjs → cameraFns-dRK1CnFi.cjs} +2 -2
  17. package/dist/core.cjs +1 -1
  18. package/dist/core.js +1 -1
  19. package/dist/{cornerFinder-ChltJ_ur.cjs → cornerFinder-CQPXY8Aw.cjs} +1 -1
  20. package/dist/{cornerFinder-fMf9-El_.js → cornerFinder-DcHCKoUh.js} +1 -1
  21. package/dist/{curveFns-BhTtS18d.js → curveFns-CXhOkKR4.js} +1 -1
  22. package/dist/{curveFns-CXytEfTr.cjs → curveFns-uPVW6eo-.cjs} +1 -1
  23. package/dist/{drawFns-Bzr38vZx.js → drawFns-ZqWpAG8b.js} +12 -12
  24. package/dist/{drawFns-Bn4vzbUr.cjs → drawFns-eMU4H__w.cjs} +12 -12
  25. package/dist/{extrudeFns-rnUgev_g.js → extrudeFns-CSy2C7WW.js} +1 -1
  26. package/dist/{extrudeFns-C0FsOXev.cjs → extrudeFns-CzQans6p.cjs} +1 -1
  27. package/dist/{faceFns-Dreo5ksY.js → faceFns-BBcrvY7r.js} +11 -3
  28. package/dist/{faceFns-FAZgMVCx.cjs → faceFns-CcLFCtg4.cjs} +16 -2
  29. package/dist/{helpers-D8ycrNeD.cjs → helpers-BmY5kO0w.cjs} +6 -6
  30. package/dist/{helpers--BMa_zB7.js → helpers-CxT3j8jG.js} +6 -6
  31. package/dist/{historyFns-mnmeZ0kB.cjs → historyFns-BEB2Yjld.cjs} +4 -4
  32. package/dist/{historyFns-CR0RejKJ.js → historyFns-ClLT60_V.js} +4 -4
  33. package/dist/{importFns-DRPQExAD.js → importFns-BNDWuBuq.js} +2 -2
  34. package/dist/{importFns-4mi5Ih46.cjs → importFns-DA0Klh7_.cjs} +2 -2
  35. package/dist/index.d.ts +1 -1
  36. package/dist/io.cjs +2 -2
  37. package/dist/io.js +2 -2
  38. package/dist/kernel/brepkit/geometryOps.d.ts +1 -0
  39. package/dist/kernel/interfaces/surfaceOps.d.ts +9 -0
  40. package/dist/kernel/occt/geometryQueryOps.d.ts +9 -0
  41. package/dist/kernel/occtWasm/occtWasmAdapter.cjs +1 -1
  42. package/dist/kernel/occtWasm/occtWasmAdapter.d.ts +4 -0
  43. package/dist/kernel/occtWasm/occtWasmAdapter.js +1 -1
  44. package/dist/kernel/occtWasm/surfaceOps.d.ts +17 -0
  45. package/dist/kernel/solverAdapter.d.ts +8 -2
  46. package/dist/{measureFns-BLEx4ZU3.js → measureFns-DAP8LjBB.js} +3 -3
  47. package/dist/{measureFns-CT0XaSOt.cjs → measureFns-zGABZl6o.cjs} +3 -3
  48. package/dist/measurement.cjs +1 -1
  49. package/dist/measurement.js +1 -1
  50. package/dist/{meshFns-lwgHYQ79.cjs → meshFns-CEGnFm33.cjs} +3 -3
  51. package/dist/{meshFns-B3MjIqk1.js → meshFns-D-nLiHvU.js} +3 -3
  52. package/dist/{occtWasmAdapter-BH7r2nTq.cjs → occtWasmAdapter-Crs07qIe.cjs} +67 -0
  53. package/dist/{occtWasmAdapter-C7FDeTaw.js → occtWasmAdapter-D0MtWZYO.js} +67 -0
  54. package/dist/operations.cjs +2 -2
  55. package/dist/operations.js +2 -2
  56. package/dist/{primitiveFns-DcZDTQ_R.js → primitiveFns-CDbe5gjc.js} +7 -7
  57. package/dist/{primitiveFns-DZmgvzvk.cjs → primitiveFns-CpkG8ZkI.cjs} +7 -7
  58. package/dist/projection.cjs +1 -1
  59. package/dist/projection.js +1 -1
  60. package/dist/query.cjs +2 -2
  61. package/dist/query.js +2 -2
  62. package/dist/{shapeFns-w1YoIn_p.cjs → shapeFns-CDHya-nt.cjs} +2 -2
  63. package/dist/{shapeFns-BnkizFjV.js → shapeFns-DVUNOG2I.js} +2 -2
  64. package/dist/shapeRef.cjs +1 -1
  65. package/dist/shapeRef.js +1 -1
  66. package/dist/{shapeRefFns-B3myHs0D.cjs → shapeRefFns-B1Tygk9V.cjs} +4 -4
  67. package/dist/{shapeRefFns-OVWdFOAC.js → shapeRefFns-CAJUDLTi.js} +4 -4
  68. package/dist/{shapeTypes-yCQ8z5Hc.js → shapeTypes-2cKwu2z4.js} +35 -1
  69. package/dist/{shapeTypes-BIlZar9m.cjs → shapeTypes-DRxArFIc.cjs} +35 -1
  70. package/dist/sketching.cjs +3 -3
  71. package/dist/sketching.js +3 -3
  72. package/dist/{solidBuilders-CPOTKI5i.js → solidBuilders-Bx3UdW91.js} +2 -2
  73. package/dist/{solidBuilders-dNhToZgl.cjs → solidBuilders-ibLq_9EK.cjs} +2 -2
  74. package/dist/{surfaceBuilders-CS1QccDv.js → surfaceBuilders-BtNrSolT.js} +2 -2
  75. package/dist/{surfaceBuilders-CzHPZtd3.cjs → surfaceBuilders-D2PBBoja.cjs} +2 -2
  76. package/dist/text.cjs +2 -2
  77. package/dist/text.js +2 -2
  78. package/dist/{textBlueprints-TG6AH06v.cjs → textBlueprints-COG8m1aE.cjs} +7 -7
  79. package/dist/{textBlueprints-B57ej88L.js → textBlueprints-HfRD4iNF.js} +7 -7
  80. package/dist/{textMetrics-Dag-YREs.cjs → textMetrics-CTSpUXtk.cjs} +1 -1
  81. package/dist/{textMetrics-BxtB3sjj.js → textMetrics-Zp8rzokO.js} +1 -1
  82. package/dist/topology/faceFns.d.ts +9 -0
  83. package/dist/topology/index.d.ts +1 -1
  84. package/dist/topology.cjs +8 -7
  85. package/dist/topology.d.ts +1 -1
  86. package/dist/topology.js +8 -8
  87. package/dist/{topologyQueryFns-BuWZAQ_o.cjs → topologyQueryFns-024l64sD.cjs} +1 -1
  88. package/dist/{topologyQueryFns-Bxdnl5Vt.js → topologyQueryFns-c2RQIcfW.js} +1 -1
  89. package/package.json +1 -1
package/dist/brepjs.cjs CHANGED
@@ -1,36 +1,36 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_textBlueprints = require("./textBlueprints-TG6AH06v.cjs");
3
- const require_shapeTypes = require("./shapeTypes-BIlZar9m.cjs");
4
- const require_occtWasmAdapter = require("./occtWasmAdapter-BH7r2nTq.cjs");
2
+ const require_textBlueprints = require("./textBlueprints-COG8m1aE.cjs");
3
+ const require_shapeTypes = require("./shapeTypes-DRxArFIc.cjs");
4
+ const require_occtWasmAdapter = require("./occtWasmAdapter-Crs07qIe.cjs");
5
5
  const require_vec3 = require("./vec3-CFwOI0ZI.cjs");
6
6
  const require_errors = require("./errors-CXJtc4I7.cjs");
7
- const require_topologyQueryFns = require("./topologyQueryFns-BuWZAQ_o.cjs");
7
+ const require_topologyQueryFns = require("./topologyQueryFns-024l64sD.cjs");
8
8
  const require_constants = require("./constants-BOVyEYGH.cjs");
9
9
  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
- const require_faceFns = require("./faceFns-FAZgMVCx.cjs");
13
- const require_shapeFns = require("./shapeFns-w1YoIn_p.cjs");
14
- const require_curveFns = require("./curveFns-CXytEfTr.cjs");
15
- const require_meshFns = require("./meshFns-lwgHYQ79.cjs");
12
+ const require_faceFns = require("./faceFns-CcLFCtg4.cjs");
13
+ const require_shapeFns = require("./shapeFns-CDHya-nt.cjs");
14
+ const require_curveFns = require("./curveFns-uPVW6eo-.cjs");
15
+ const require_meshFns = require("./meshFns-CEGnFm33.cjs");
16
16
  const require_arrayAccess = require("./arrayAccess-e4H9cBfh.cjs");
17
- const require_surfaceBuilders = require("./surfaceBuilders-CzHPZtd3.cjs");
18
- const require_booleanFns = require("./booleanFns-DvXg6a2Y.cjs");
19
- const require_primitiveFns = require("./primitiveFns-DZmgvzvk.cjs");
20
- const require_historyFns = require("./historyFns-mnmeZ0kB.cjs");
21
- const require_blueprintSketcher = require("./blueprintSketcher-BpOknLmX.cjs");
22
- const require_helpers = require("./helpers-D8ycrNeD.cjs");
23
- const require_drawFns = require("./drawFns-Bn4vzbUr.cjs");
24
- const require_solidBuilders = require("./solidBuilders-dNhToZgl.cjs");
25
- const require_measureFns = require("./measureFns-CT0XaSOt.cjs");
26
- const require_cornerFinder = require("./cornerFinder-ChltJ_ur.cjs");
27
- const require_boolean2D = require("./boolean2D-DZcOTOSA.cjs");
28
- const require_blueprintFns = require("./blueprintFns-BO44cqFY.cjs");
29
- const require_importFns = require("./importFns-4mi5Ih46.cjs");
30
- const require_extrudeFns = require("./extrudeFns-C0FsOXev.cjs");
31
- const require_cameraFns = require("./cameraFns-CsGSVYgb.cjs");
32
- const require_textMetrics = require("./textMetrics-Dag-YREs.cjs");
33
- const require_shapeRefFns = require("./shapeRefFns-B3myHs0D.cjs");
17
+ const require_surfaceBuilders = require("./surfaceBuilders-D2PBBoja.cjs");
18
+ const require_booleanFns = require("./booleanFns-Bp_wYEwG.cjs");
19
+ const require_primitiveFns = require("./primitiveFns-CpkG8ZkI.cjs");
20
+ const require_historyFns = require("./historyFns-BEB2Yjld.cjs");
21
+ const require_blueprintSketcher = require("./blueprintSketcher-dZZ8e5ey.cjs");
22
+ const require_helpers = require("./helpers-BmY5kO0w.cjs");
23
+ const require_drawFns = require("./drawFns-eMU4H__w.cjs");
24
+ const require_solidBuilders = require("./solidBuilders-ibLq_9EK.cjs");
25
+ const require_measureFns = require("./measureFns-zGABZl6o.cjs");
26
+ const require_cornerFinder = require("./cornerFinder-CQPXY8Aw.cjs");
27
+ const require_boolean2D = require("./boolean2D-4E1kbwQx.cjs");
28
+ const require_blueprintFns = require("./blueprintFns-DsuY7gCu.cjs");
29
+ const require_importFns = require("./importFns-DA0Klh7_.cjs");
30
+ const require_extrudeFns = require("./extrudeFns-CzQans6p.cjs");
31
+ const require_cameraFns = require("./cameraFns-dRK1CnFi.cjs");
32
+ const require_textMetrics = require("./textMetrics-CTSpUXtk.cjs");
33
+ const require_shapeRefFns = require("./shapeRefFns-B1Tygk9V.cjs");
34
34
  const require_workerHandler = require("./workerHandler-CdlOTwJg.cjs");
35
35
  //#region src/topology/shapeBooleans.ts
36
36
  var BOPAlgo_GlueShift = 1;
@@ -2134,11 +2134,12 @@ function roof(w, options) {
2134
2134
  //#endregion
2135
2135
  //#region src/kernel/solverAdapter.ts
2136
2136
  /**
2137
- * Standard degrees of freedom left unresolved by each unsupported constraint type.
2138
- * coincident: 3 translational (plane normal alignment + contact)
2139
- * concentric: 2 rotational (axis alignment) + 2 translational (axis centering) = 4
2140
- * distance: 1 translational (offset along normal)
2141
- * angle: 1 rotational
2137
+ * Degrees of freedom each constraint leaves unresolved when it can't be applied
2138
+ * (entity-type mismatch or an unreachable reference). All four types now solve
2139
+ * for well-typed inputs; these counts only feed the diagnostic `dof` for the
2140
+ * unsupported cases.
2141
+ * coincident: 3 translational · concentric: 2 rotational + 2 translational = 4
2142
+ * distance: 1 translational · angle: 1 rotational
2142
2143
  */
2143
2144
  var UNSUPPORTED_DOF = {
2144
2145
  coincident: 3,
@@ -2146,11 +2147,220 @@ var UNSUPPORTED_DOF = {
2146
2147
  distance: 1,
2147
2148
  angle: 1
2148
2149
  };
2150
+ var IDENTITY_ROTATION = [
2151
+ 1,
2152
+ 0,
2153
+ 0,
2154
+ 0
2155
+ ];
2156
+ function add$1(a, b) {
2157
+ return [
2158
+ a[0] + b[0],
2159
+ a[1] + b[1],
2160
+ a[2] + b[2]
2161
+ ];
2162
+ }
2163
+ function sub(a, b) {
2164
+ return [
2165
+ a[0] - b[0],
2166
+ a[1] - b[1],
2167
+ a[2] - b[2]
2168
+ ];
2169
+ }
2170
+ function dot(a, b) {
2171
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
2172
+ }
2173
+ function cross(a, b) {
2174
+ return [
2175
+ a[1] * b[2] - a[2] * b[1],
2176
+ a[2] * b[0] - a[0] * b[2],
2177
+ a[0] * b[1] - a[1] * b[0]
2178
+ ];
2179
+ }
2180
+ function scale$2(a, s) {
2181
+ return [
2182
+ a[0] * s,
2183
+ a[1] * s,
2184
+ a[2] * s
2185
+ ];
2186
+ }
2187
+ function normalize(a) {
2188
+ const l = Math.hypot(a[0], a[1], a[2]) || 1;
2189
+ return [
2190
+ a[0] / l,
2191
+ a[1] / l,
2192
+ a[2] / l
2193
+ ];
2194
+ }
2195
+ /** A unit vector perpendicular to `v` (for the 180° / parallel degenerate cases). */
2196
+ function anyPerpendicular(v) {
2197
+ return normalize(cross(v, Math.abs(v[0]) < .9 ? [
2198
+ 1,
2199
+ 0,
2200
+ 0
2201
+ ] : [
2202
+ 0,
2203
+ 1,
2204
+ 0
2205
+ ]));
2206
+ }
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
+ /** Apply a pose (rotate then translate) to an entity's origin and any directions. */
2253
+ function transformEntity(e, pose) {
2254
+ const origin = add$1(qRotate(pose.rotation, e.origin), pose.position);
2255
+ return {
2256
+ type: e.type,
2257
+ origin,
2258
+ ...e.normal ? { normal: qRotate(pose.rotation, e.normal) } : {},
2259
+ ...e.direction ? { direction: qRotate(pose.rotation, e.direction) } : {}
2260
+ };
2261
+ }
2262
+ /**
2263
+ * Position a dependent plane against an already-placed reference plane.
2264
+ *
2265
+ * `ref` is the reference entity already in world space. The dependent is at the
2266
+ * origin (a node is only solved once, while unplaced), so the returned position
2267
+ * is its absolute translation along the reference normal. `extra` is the gap for
2268
+ * a distance mate (0 for coincident). Plane mates don't reorient the dependent.
2269
+ */
2270
+ function solvePlanePair(ref, dep, extra) {
2271
+ const n = ref.normal ?? [
2272
+ 0,
2273
+ 0,
2274
+ 1
2275
+ ];
2276
+ return {
2277
+ position: scale$2(n, dot(n, sub(ref.origin, dep.origin)) + extra),
2278
+ rotation: IDENTITY_ROTATION
2279
+ };
2280
+ }
2281
+ /**
2282
+ * Concentric (axis-axis) mate: rotate the dependent so its axis is parallel to
2283
+ * the reference axis, then translate so the two axes are collinear (the
2284
+ * dependent's axis point is placed on the reference axis). `ref` is in world
2285
+ * space; the dependent is at the origin.
2286
+ */
2287
+ function solveConcentric(ref, dep) {
2288
+ const dRef = ref.direction ?? [
2289
+ 0,
2290
+ 0,
2291
+ 1
2292
+ ];
2293
+ const rotation = qFromTo(dep.direction ?? [
2294
+ 0,
2295
+ 0,
2296
+ 1
2297
+ ], dRef);
2298
+ const rotatedOrigin = qRotate(rotation, dep.origin);
2299
+ return {
2300
+ position: sub(ref.origin, rotatedOrigin),
2301
+ rotation
2302
+ };
2303
+ }
2304
+ /**
2305
+ * Angle mate: rotate the dependent so the angle between its (plane) normal and
2306
+ * the reference normal equals `angleRad`. Orientation-only — position is left at
2307
+ * the origin. `ref` is in world space; the dependent is at the origin.
2308
+ */
2309
+ function solveAngle(ref, dep, angleRad) {
2310
+ const nRef = normalize(ref.normal ?? [
2311
+ 0,
2312
+ 0,
2313
+ 1
2314
+ ]);
2315
+ const nDep = normalize(dep.normal ?? [
2316
+ 0,
2317
+ 0,
2318
+ 1
2319
+ ]);
2320
+ const phi = Math.acos(Math.max(-1, Math.min(1, dot(nDep, nRef))));
2321
+ const c = cross(nDep, nRef);
2322
+ return {
2323
+ position: [
2324
+ 0,
2325
+ 0,
2326
+ 0
2327
+ ],
2328
+ rotation: qFromAxisAngle(Math.hypot(c[0], c[1], c[2]) < 1e-9 ? anyPerpendicular(nDep) : c, phi - angleRad)
2329
+ };
2330
+ }
2331
+ /** Entity types each positioning constraint requires of (entityA, entityB). */
2332
+ var REQUIRED_ENTITIES = {
2333
+ coincident: "plane",
2334
+ distance: "plane",
2335
+ angle: "plane",
2336
+ concentric: "axis"
2337
+ };
2338
+ var POSITIONING_TYPES = new Set([
2339
+ "coincident",
2340
+ "distance",
2341
+ "angle",
2342
+ "concentric"
2343
+ ]);
2344
+ /** Dispatch a positioning mate to its solver. `ref` is already in world space. */
2345
+ function solveMate(c, ref, dep) {
2346
+ switch (c.type) {
2347
+ case "concentric": return solveConcentric(ref, dep);
2348
+ case "angle": return solveAngle(ref, dep, (c.value ?? 0) * Math.PI / 180);
2349
+ case "distance": return solvePlanePair(ref, dep, c.value ?? 0);
2350
+ default: return solvePlanePair(ref, dep, 0);
2351
+ }
2352
+ }
2149
2353
  /**
2150
2354
  * Solve assembly constraints analytically.
2151
2355
  *
2152
- * Currently handles: fixed, coincident (plane-plane), distance (plane-plane).
2153
- * Returns `converged: false` with unsupported constraint details for concentric and angle.
2356
+ * Handles: fixed, coincident/distance (plane-plane), concentric (axis-axis), and
2357
+ * angle (plane-plane orientation). For a positioning mate, entityA is the
2358
+ * reference and entityB the dependent. Chain roots (nodes never positioned by a
2359
+ * mate) and explicit `fixed` nodes anchor at the origin; constraints then resolve
2360
+ * in topological order — each places its dependent against the reference's solved
2361
+ * pose (rotation included), so multi-body chains compose. Returns
2362
+ * `converged: false` with details for entity-type mismatches and any constraint
2363
+ * whose reference never resolves.
2154
2364
  */
2155
2365
  function solveConstraints(nodes, constraints) {
2156
2366
  const transforms = /* @__PURE__ */ new Map();
@@ -2160,69 +2370,51 @@ function solveConstraints(nodes, constraints) {
2160
2370
  0,
2161
2371
  0
2162
2372
  ],
2163
- rotation: [
2164
- 1,
2165
- 0,
2166
- 0,
2167
- 0
2168
- ]
2373
+ rotation: IDENTITY_ROTATION
2169
2374
  });
2170
2375
  const unsupported = [];
2171
- for (const c of constraints) if (c.type === "coincident" && c.entityA && c.entityB) {
2172
- const a = c.entityA;
2173
- const b = c.entityB;
2174
- if (a.entity.type === "plane" && b.entity.type === "plane") {
2175
- const aNormal = a.entity.normal ?? [
2176
- 0,
2177
- 0,
2178
- 1
2179
- ];
2180
- const aOrigin = a.entity.origin;
2181
- const bOrigin = b.entity.origin;
2182
- const dot = aNormal[0] * (aOrigin[0] - bOrigin[0]) + aNormal[1] * (aOrigin[1] - bOrigin[1]) + aNormal[2] * (aOrigin[2] - bOrigin[2]);
2183
- const pos = [
2184
- dot * aNormal[0],
2185
- dot * aNormal[1],
2186
- dot * aNormal[2]
2187
- ];
2188
- transforms.set(b.node, {
2189
- position: pos,
2190
- rotation: [
2191
- 1,
2192
- 0,
2193
- 0,
2194
- 0
2195
- ]
2196
- });
2197
- } else unsupported.push(`coincident(${a.entity.type}-${b.entity.type})`);
2198
- } else if (c.type === "distance" && c.entityA && c.entityB && c.value !== void 0) {
2199
- const a = c.entityA;
2200
- const b = c.entityB;
2201
- if (a.entity.type === "plane" && b.entity.type === "plane") {
2202
- const aNormal = a.entity.normal ?? [
2203
- 0,
2204
- 0,
2205
- 1
2206
- ];
2207
- const aOrigin = a.entity.origin;
2208
- const bOrigin = b.entity.origin;
2209
- const offset = aNormal[0] * (aOrigin[0] - bOrigin[0]) + aNormal[1] * (aOrigin[1] - bOrigin[1]) + aNormal[2] * (aOrigin[2] - bOrigin[2]) + c.value;
2210
- const pos = [
2211
- offset * aNormal[0],
2212
- offset * aNormal[1],
2213
- offset * aNormal[2]
2214
- ];
2215
- transforms.set(b.node, {
2216
- position: pos,
2217
- rotation: [
2218
- 1,
2376
+ const positioning = constraints.filter((c) => POSITIONING_TYPES.has(c.type) && c.entityA && c.entityB);
2377
+ const dependents = /* @__PURE__ */ new Set();
2378
+ for (const c of positioning) if (c.entityB) dependents.add(c.entityB.node);
2379
+ const placed = /* @__PURE__ */ new Set();
2380
+ for (const node of nodes) if (!dependents.has(node)) placed.add(node);
2381
+ for (const c of constraints) if (c.type === "fixed" && c.entityA) placed.add(c.entityA.node);
2382
+ const pending = [];
2383
+ for (const c of positioning) {
2384
+ if (!c.entityA || !c.entityB) continue;
2385
+ const required = REQUIRED_ENTITIES[c.type];
2386
+ if (c.entityA.entity.type !== required || c.entityB.entity.type !== required) {
2387
+ unsupported.push(`${c.type}(${c.entityA.entity.type}-${c.entityB.entity.type})`);
2388
+ continue;
2389
+ }
2390
+ pending.push(c);
2391
+ }
2392
+ let progress = true;
2393
+ while (progress && pending.length > 0) {
2394
+ progress = false;
2395
+ for (let i = pending.length - 1; i >= 0; i--) {
2396
+ const c = pending[i];
2397
+ if (!c?.entityA || !c.entityB) continue;
2398
+ const ref = c.entityA;
2399
+ const dep = c.entityB;
2400
+ if (!placed.has(ref.node)) continue;
2401
+ pending.splice(i, 1);
2402
+ progress = true;
2403
+ if (placed.has(dep.node)) continue;
2404
+ const refPose = transforms.get(ref.node) ?? {
2405
+ position: [
2219
2406
  0,
2220
2407
  0,
2221
2408
  0
2222
- ]
2223
- });
2224
- } else unsupported.push(`distance(${a.entity.type}-${b.entity.type})`);
2225
- } else if (c.type === "concentric" || c.type === "angle") unsupported.push(c.type);
2409
+ ],
2410
+ rotation: IDENTITY_ROTATION
2411
+ };
2412
+ const refWorld = transformEntity(ref.entity, refPose);
2413
+ transforms.set(dep.node, solveMate(c, refWorld, dep.entity));
2414
+ placed.add(dep.node);
2415
+ }
2416
+ }
2417
+ for (const c of pending) unsupported.push(`${c.type}(unanchored)`);
2226
2418
  return {
2227
2419
  transforms,
2228
2420
  dof: unsupported.reduce((sum, type) => {
@@ -2235,11 +2427,27 @@ function solveConstraints(nodes, constraints) {
2235
2427
  //#endregion
2236
2428
  //#region src/operations/mateFns.ts
2237
2429
  function extractEntity(mate) {
2238
- if (mate.face) return {
2239
- type: "plane",
2240
- origin: require_faceFns.faceCenter(mate.face),
2241
- normal: require_faceFns.normalAt(mate.face)
2242
- };
2430
+ if (mate.face) {
2431
+ const axis = require_faceFns.faceAxis(mate.face);
2432
+ if (axis) return {
2433
+ type: "axis",
2434
+ origin: axis.origin,
2435
+ direction: axis.direction
2436
+ };
2437
+ return {
2438
+ type: "plane",
2439
+ origin: require_faceFns.faceCenter(mate.face),
2440
+ normal: require_faceFns.normalAt(mate.face)
2441
+ };
2442
+ }
2443
+ if (mate.edge) {
2444
+ if (require_curveFns.getCurveType(mate.edge) === "LINE") return {
2445
+ type: "axis",
2446
+ origin: require_curveFns.curveStartPoint(mate.edge),
2447
+ direction: require_curveFns.curveTangentAt(mate.edge)
2448
+ };
2449
+ return null;
2450
+ }
2243
2451
  if (mate.point) return {
2244
2452
  type: "point",
2245
2453
  origin: mate.point
@@ -6327,6 +6535,7 @@ exports.exportThreeMF = require_importFns.exportThreeMF;
6327
6535
  exports.extrude = extrude;
6328
6536
  exports.extrudeAll = require_extrudeFns.extrudeAll;
6329
6537
  exports.face = require_primitiveFns.face;
6538
+ exports.faceAxis = require_faceFns.faceAxis;
6330
6539
  exports.faceCenter = require_faceFns.faceCenter;
6331
6540
  exports.faceFinder = require_helpers.faceFinder;
6332
6541
  exports.faceGeomType = require_faceFns.faceGeomType;