brepjs 18.79.0 → 18.80.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 +154 -11
- package/dist/brepjs.js +154 -11
- package/dist/kernel/solverAdapter.d.ts +5 -3
- package/package.json +1 -1
package/dist/brepjs.cjs
CHANGED
|
@@ -2286,10 +2286,122 @@ function solveAngle(ref, dep, angleRad) {
|
|
|
2286
2286
|
rotation: require_threadFns.quatFromAxisAngle(Math.hypot(c[0], c[1], c[2]) < 1e-9 ? anyPerpendicular(nDep) : c, phi - angleRad)
|
|
2287
2287
|
};
|
|
2288
2288
|
}
|
|
2289
|
-
/**
|
|
2289
|
+
/**
|
|
2290
|
+
* Point-point coincident/distance: place the dependent point on the reference
|
|
2291
|
+
* point (`extra` = 0) or at `extra` along the original separation direction.
|
|
2292
|
+
* If the points already coincide the direction is arbitrary (+X).
|
|
2293
|
+
*/
|
|
2294
|
+
function solvePointPair(refOrigin, depOrigin, extra) {
|
|
2295
|
+
const sep = sub(depOrigin, refOrigin);
|
|
2296
|
+
const len = Math.hypot(sep[0], sep[1], sep[2]);
|
|
2297
|
+
return {
|
|
2298
|
+
position: sub(add$1(refOrigin, scale$2(len < 1e-9 ? [
|
|
2299
|
+
1,
|
|
2300
|
+
0,
|
|
2301
|
+
0
|
|
2302
|
+
] : scale$2(sep, 1 / len), extra)), depOrigin),
|
|
2303
|
+
rotation: IDENTITY_ROTATION
|
|
2304
|
+
};
|
|
2305
|
+
}
|
|
2306
|
+
/**
|
|
2307
|
+
* Move the dependent plane (normal `depNormal`, at the origin) so its signed
|
|
2308
|
+
* distance from the reference point equals `extra` (the mirror of `solvePlanePair`
|
|
2309
|
+
* for a point reference and a plane dependent).
|
|
2310
|
+
*/
|
|
2311
|
+
function solvePlaneToPoint(depNormal, refOrigin, depOrigin, extra) {
|
|
2312
|
+
const n = normalize(depNormal);
|
|
2313
|
+
return {
|
|
2314
|
+
position: scale$2(n, dot(n, sub(refOrigin, depOrigin)) - extra),
|
|
2315
|
+
rotation: IDENTITY_ROTATION
|
|
2316
|
+
};
|
|
2317
|
+
}
|
|
2318
|
+
/**
|
|
2319
|
+
* Reference axis, dependent point: drop the point onto the axis line
|
|
2320
|
+
* (`extra` = 0) or place it at radial distance `extra` from the line, keeping
|
|
2321
|
+
* its along-axis position. A point already on the axis gets an arbitrary radial.
|
|
2322
|
+
*/
|
|
2323
|
+
function solveAxisToPoint(ref, depOrigin, extra) {
|
|
2324
|
+
const d = normalize(ref.direction ?? [
|
|
2325
|
+
0,
|
|
2326
|
+
0,
|
|
2327
|
+
1
|
|
2328
|
+
]);
|
|
2329
|
+
const foot = add$1(ref.origin, scale$2(d, dot(d, sub(depOrigin, ref.origin))));
|
|
2330
|
+
if (extra === 0) return {
|
|
2331
|
+
position: sub(foot, depOrigin),
|
|
2332
|
+
rotation: IDENTITY_ROTATION
|
|
2333
|
+
};
|
|
2334
|
+
const radial = sub(depOrigin, foot);
|
|
2335
|
+
const rlen = Math.hypot(radial[0], radial[1], radial[2]);
|
|
2336
|
+
return {
|
|
2337
|
+
position: sub(add$1(foot, scale$2(rlen < 1e-9 ? anyPerpendicular(d) : scale$2(radial, 1 / rlen), extra)), depOrigin),
|
|
2338
|
+
rotation: IDENTITY_ROTATION
|
|
2339
|
+
};
|
|
2340
|
+
}
|
|
2341
|
+
/**
|
|
2342
|
+
* Reference point, dependent axis: translate the axis line so it passes through
|
|
2343
|
+
* the point (`extra` = 0) or lies at perpendicular distance `extra` from it.
|
|
2344
|
+
* Translation is purely perpendicular to the axis, so the line's direction and
|
|
2345
|
+
* along-axis parameterization are preserved.
|
|
2346
|
+
*/
|
|
2347
|
+
function solvePointToAxis(refOrigin, dep, extra) {
|
|
2348
|
+
const d = normalize(dep.direction ?? [
|
|
2349
|
+
0,
|
|
2350
|
+
0,
|
|
2351
|
+
1
|
|
2352
|
+
]);
|
|
2353
|
+
const w = sub(dep.origin, refOrigin);
|
|
2354
|
+
const perp = sub(w, scale$2(d, dot(d, w)));
|
|
2355
|
+
const plen = Math.hypot(perp[0], perp[1], perp[2]);
|
|
2356
|
+
if (extra === 0) return {
|
|
2357
|
+
position: scale$2(perp, -1),
|
|
2358
|
+
rotation: IDENTITY_ROTATION
|
|
2359
|
+
};
|
|
2360
|
+
return {
|
|
2361
|
+
position: sub(scale$2(plen < 1e-9 ? anyPerpendicular(d) : scale$2(perp, 1 / plen), extra), perp),
|
|
2362
|
+
rotation: IDENTITY_ROTATION
|
|
2363
|
+
};
|
|
2364
|
+
}
|
|
2365
|
+
/**
|
|
2366
|
+
* Axis-axis distance: align the dependent axis parallel to the reference, then
|
|
2367
|
+
* offset it to perpendicular distance `extra` (parallel pin-and-spacer). With
|
|
2368
|
+
* `extra` = 0 the axes become collinear, matching `concentric`.
|
|
2369
|
+
*/
|
|
2370
|
+
function solveAxisAxisDistance(ref, dep, extra) {
|
|
2371
|
+
const dRef = normalize(ref.direction ?? [
|
|
2372
|
+
0,
|
|
2373
|
+
0,
|
|
2374
|
+
1
|
|
2375
|
+
]);
|
|
2376
|
+
const rotation = require_threadFns.quatFromTo(normalize(dep.direction ?? [
|
|
2377
|
+
0,
|
|
2378
|
+
0,
|
|
2379
|
+
1
|
|
2380
|
+
]), dRef);
|
|
2381
|
+
const w = sub(require_threadFns.quatRotate(rotation, dep.origin), ref.origin);
|
|
2382
|
+
const perp = sub(w, scale$2(dRef, dot(dRef, w)));
|
|
2383
|
+
const plen = Math.hypot(perp[0], perp[1], perp[2]);
|
|
2384
|
+
return {
|
|
2385
|
+
position: sub(scale$2(plen < 1e-9 ? anyPerpendicular(dRef) : scale$2(perp, 1 / plen), extra), perp),
|
|
2386
|
+
rotation
|
|
2387
|
+
};
|
|
2388
|
+
}
|
|
2389
|
+
/**
|
|
2390
|
+
* Supported entity-type pairs for the translational mates (`coincident` /
|
|
2391
|
+
* `distance`), keyed `${entityA}-${entityB}`. Both orders are listed where the
|
|
2392
|
+
* solver handles them, so a user need not pre-order the entities.
|
|
2393
|
+
*/
|
|
2394
|
+
var TRANSLATIONAL_PAIRS = new Set([
|
|
2395
|
+
"plane-plane",
|
|
2396
|
+
"plane-point",
|
|
2397
|
+
"point-plane",
|
|
2398
|
+
"point-point",
|
|
2399
|
+
"axis-axis",
|
|
2400
|
+
"axis-point",
|
|
2401
|
+
"point-axis"
|
|
2402
|
+
]);
|
|
2403
|
+
/** Entity types the orientation/axis mates require of (entityA, entityB). */
|
|
2290
2404
|
var REQUIRED_ENTITIES = {
|
|
2291
|
-
coincident: "plane",
|
|
2292
|
-
distance: "plane",
|
|
2293
2405
|
angle: "plane",
|
|
2294
2406
|
concentric: "axis"
|
|
2295
2407
|
};
|
|
@@ -2299,21 +2411,51 @@ var POSITIONING_TYPES = new Set([
|
|
|
2299
2411
|
"angle",
|
|
2300
2412
|
"concentric"
|
|
2301
2413
|
]);
|
|
2414
|
+
/** Whether a positioning mate's entity pair is solvable. */
|
|
2415
|
+
function isSupportedPair(type, a, b) {
|
|
2416
|
+
const required = REQUIRED_ENTITIES[type];
|
|
2417
|
+
if (required) return a === required && b === required;
|
|
2418
|
+
return TRANSLATIONAL_PAIRS.has(`${a}-${b}`);
|
|
2419
|
+
}
|
|
2420
|
+
/**
|
|
2421
|
+
* Solve a `coincident` (extra = 0) or `distance` (extra = value) mate for any
|
|
2422
|
+
* supported entity-type pair. `ref` is already in world space; the dependent is
|
|
2423
|
+
* at the origin. Returns null only for an unsupported pair (filtered out
|
|
2424
|
+
* upstream by `isSupportedPair`).
|
|
2425
|
+
*/
|
|
2426
|
+
function solveTranslational(ref, dep, extra) {
|
|
2427
|
+
switch (`${ref.type}-${dep.type}`) {
|
|
2428
|
+
case "plane-plane":
|
|
2429
|
+
case "plane-point": return solvePlanePair(ref, dep, extra);
|
|
2430
|
+
case "point-plane": return solvePlaneToPoint(dep.normal ?? [
|
|
2431
|
+
0,
|
|
2432
|
+
0,
|
|
2433
|
+
1
|
|
2434
|
+
], ref.origin, dep.origin, extra);
|
|
2435
|
+
case "point-point": return solvePointPair(ref.origin, dep.origin, extra);
|
|
2436
|
+
case "axis-axis": return extra === 0 ? solveConcentric(ref, dep) : solveAxisAxisDistance(ref, dep, extra);
|
|
2437
|
+
case "axis-point": return solveAxisToPoint(ref, dep.origin, extra);
|
|
2438
|
+
case "point-axis": return solvePointToAxis(ref.origin, dep, extra);
|
|
2439
|
+
default: return null;
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2302
2442
|
/** Dispatch a positioning mate to its solver. `ref` is already in world space. */
|
|
2303
2443
|
function solveMate(c, ref, dep) {
|
|
2304
2444
|
switch (c.type) {
|
|
2305
2445
|
case "concentric": return solveConcentric(ref, dep);
|
|
2306
2446
|
case "angle": return solveAngle(ref, dep, (c.value ?? 0) * Math.PI / 180);
|
|
2307
|
-
case "distance": return solvePlanePair(ref, dep, c.value ?? 0);
|
|
2308
|
-
default: return solvePlanePair(ref, dep, 0);
|
|
2447
|
+
case "distance": return solveTranslational(ref, dep, c.value ?? 0) ?? solvePlanePair(ref, dep, c.value ?? 0);
|
|
2448
|
+
default: return solveTranslational(ref, dep, 0) ?? solvePlanePair(ref, dep, 0);
|
|
2309
2449
|
}
|
|
2310
2450
|
}
|
|
2311
2451
|
/**
|
|
2312
2452
|
* Solve assembly constraints analytically.
|
|
2313
2453
|
*
|
|
2314
|
-
* Handles: fixed,
|
|
2315
|
-
*
|
|
2316
|
-
*
|
|
2454
|
+
* Handles: fixed, concentric (axis-axis), angle (plane-plane orientation), and
|
|
2455
|
+
* coincident/distance for any supported entity-type pair (plane-plane,
|
|
2456
|
+
* plane-point, point-point, axis-axis, axis-point, and both point orders — see
|
|
2457
|
+
* `TRANSLATIONAL_PAIRS`). For a positioning mate, entityA is the reference and
|
|
2458
|
+
* entityB the dependent. Chain roots (nodes never positioned by a
|
|
2317
2459
|
* mate) and explicit `fixed` nodes anchor at the origin; constraints then resolve
|
|
2318
2460
|
* in topological order — each places its dependent against the reference's solved
|
|
2319
2461
|
* pose (rotation included), so multi-body chains compose. Returns
|
|
@@ -2340,9 +2482,10 @@ function solveConstraints(nodes, constraints) {
|
|
|
2340
2482
|
const pending = [];
|
|
2341
2483
|
for (const c of positioning) {
|
|
2342
2484
|
if (!c.entityA || !c.entityB) continue;
|
|
2343
|
-
const
|
|
2344
|
-
|
|
2345
|
-
|
|
2485
|
+
const a = c.entityA.entity.type;
|
|
2486
|
+
const b = c.entityB.entity.type;
|
|
2487
|
+
if (!isSupportedPair(c.type, a, b)) {
|
|
2488
|
+
unsupported.push(`${c.type}(${a}-${b})`);
|
|
2346
2489
|
continue;
|
|
2347
2490
|
}
|
|
2348
2491
|
pending.push(c);
|
package/dist/brepjs.js
CHANGED
|
@@ -2297,10 +2297,122 @@ function solveAngle(ref, dep, angleRad) {
|
|
|
2297
2297
|
rotation: quatFromAxisAngle(Math.hypot(c[0], c[1], c[2]) < 1e-9 ? anyPerpendicular(nDep) : c, phi - angleRad)
|
|
2298
2298
|
};
|
|
2299
2299
|
}
|
|
2300
|
-
/**
|
|
2300
|
+
/**
|
|
2301
|
+
* Point-point coincident/distance: place the dependent point on the reference
|
|
2302
|
+
* point (`extra` = 0) or at `extra` along the original separation direction.
|
|
2303
|
+
* If the points already coincide the direction is arbitrary (+X).
|
|
2304
|
+
*/
|
|
2305
|
+
function solvePointPair(refOrigin, depOrigin, extra) {
|
|
2306
|
+
const sep = sub(depOrigin, refOrigin);
|
|
2307
|
+
const len = Math.hypot(sep[0], sep[1], sep[2]);
|
|
2308
|
+
return {
|
|
2309
|
+
position: sub(add$1(refOrigin, scale$2(len < 1e-9 ? [
|
|
2310
|
+
1,
|
|
2311
|
+
0,
|
|
2312
|
+
0
|
|
2313
|
+
] : scale$2(sep, 1 / len), extra)), depOrigin),
|
|
2314
|
+
rotation: IDENTITY_ROTATION
|
|
2315
|
+
};
|
|
2316
|
+
}
|
|
2317
|
+
/**
|
|
2318
|
+
* Move the dependent plane (normal `depNormal`, at the origin) so its signed
|
|
2319
|
+
* distance from the reference point equals `extra` (the mirror of `solvePlanePair`
|
|
2320
|
+
* for a point reference and a plane dependent).
|
|
2321
|
+
*/
|
|
2322
|
+
function solvePlaneToPoint(depNormal, refOrigin, depOrigin, extra) {
|
|
2323
|
+
const n = normalize(depNormal);
|
|
2324
|
+
return {
|
|
2325
|
+
position: scale$2(n, dot(n, sub(refOrigin, depOrigin)) - extra),
|
|
2326
|
+
rotation: IDENTITY_ROTATION
|
|
2327
|
+
};
|
|
2328
|
+
}
|
|
2329
|
+
/**
|
|
2330
|
+
* Reference axis, dependent point: drop the point onto the axis line
|
|
2331
|
+
* (`extra` = 0) or place it at radial distance `extra` from the line, keeping
|
|
2332
|
+
* its along-axis position. A point already on the axis gets an arbitrary radial.
|
|
2333
|
+
*/
|
|
2334
|
+
function solveAxisToPoint(ref, depOrigin, extra) {
|
|
2335
|
+
const d = normalize(ref.direction ?? [
|
|
2336
|
+
0,
|
|
2337
|
+
0,
|
|
2338
|
+
1
|
|
2339
|
+
]);
|
|
2340
|
+
const foot = add$1(ref.origin, scale$2(d, dot(d, sub(depOrigin, ref.origin))));
|
|
2341
|
+
if (extra === 0) return {
|
|
2342
|
+
position: sub(foot, depOrigin),
|
|
2343
|
+
rotation: IDENTITY_ROTATION
|
|
2344
|
+
};
|
|
2345
|
+
const radial = sub(depOrigin, foot);
|
|
2346
|
+
const rlen = Math.hypot(radial[0], radial[1], radial[2]);
|
|
2347
|
+
return {
|
|
2348
|
+
position: sub(add$1(foot, scale$2(rlen < 1e-9 ? anyPerpendicular(d) : scale$2(radial, 1 / rlen), extra)), depOrigin),
|
|
2349
|
+
rotation: IDENTITY_ROTATION
|
|
2350
|
+
};
|
|
2351
|
+
}
|
|
2352
|
+
/**
|
|
2353
|
+
* Reference point, dependent axis: translate the axis line so it passes through
|
|
2354
|
+
* the point (`extra` = 0) or lies at perpendicular distance `extra` from it.
|
|
2355
|
+
* Translation is purely perpendicular to the axis, so the line's direction and
|
|
2356
|
+
* along-axis parameterization are preserved.
|
|
2357
|
+
*/
|
|
2358
|
+
function solvePointToAxis(refOrigin, dep, extra) {
|
|
2359
|
+
const d = normalize(dep.direction ?? [
|
|
2360
|
+
0,
|
|
2361
|
+
0,
|
|
2362
|
+
1
|
|
2363
|
+
]);
|
|
2364
|
+
const w = sub(dep.origin, refOrigin);
|
|
2365
|
+
const perp = sub(w, scale$2(d, dot(d, w)));
|
|
2366
|
+
const plen = Math.hypot(perp[0], perp[1], perp[2]);
|
|
2367
|
+
if (extra === 0) return {
|
|
2368
|
+
position: scale$2(perp, -1),
|
|
2369
|
+
rotation: IDENTITY_ROTATION
|
|
2370
|
+
};
|
|
2371
|
+
return {
|
|
2372
|
+
position: sub(scale$2(plen < 1e-9 ? anyPerpendicular(d) : scale$2(perp, 1 / plen), extra), perp),
|
|
2373
|
+
rotation: IDENTITY_ROTATION
|
|
2374
|
+
};
|
|
2375
|
+
}
|
|
2376
|
+
/**
|
|
2377
|
+
* Axis-axis distance: align the dependent axis parallel to the reference, then
|
|
2378
|
+
* offset it to perpendicular distance `extra` (parallel pin-and-spacer). With
|
|
2379
|
+
* `extra` = 0 the axes become collinear, matching `concentric`.
|
|
2380
|
+
*/
|
|
2381
|
+
function solveAxisAxisDistance(ref, dep, extra) {
|
|
2382
|
+
const dRef = normalize(ref.direction ?? [
|
|
2383
|
+
0,
|
|
2384
|
+
0,
|
|
2385
|
+
1
|
|
2386
|
+
]);
|
|
2387
|
+
const rotation = quatFromTo(normalize(dep.direction ?? [
|
|
2388
|
+
0,
|
|
2389
|
+
0,
|
|
2390
|
+
1
|
|
2391
|
+
]), dRef);
|
|
2392
|
+
const w = sub(quatRotate(rotation, dep.origin), ref.origin);
|
|
2393
|
+
const perp = sub(w, scale$2(dRef, dot(dRef, w)));
|
|
2394
|
+
const plen = Math.hypot(perp[0], perp[1], perp[2]);
|
|
2395
|
+
return {
|
|
2396
|
+
position: sub(scale$2(plen < 1e-9 ? anyPerpendicular(dRef) : scale$2(perp, 1 / plen), extra), perp),
|
|
2397
|
+
rotation
|
|
2398
|
+
};
|
|
2399
|
+
}
|
|
2400
|
+
/**
|
|
2401
|
+
* Supported entity-type pairs for the translational mates (`coincident` /
|
|
2402
|
+
* `distance`), keyed `${entityA}-${entityB}`. Both orders are listed where the
|
|
2403
|
+
* solver handles them, so a user need not pre-order the entities.
|
|
2404
|
+
*/
|
|
2405
|
+
var TRANSLATIONAL_PAIRS = new Set([
|
|
2406
|
+
"plane-plane",
|
|
2407
|
+
"plane-point",
|
|
2408
|
+
"point-plane",
|
|
2409
|
+
"point-point",
|
|
2410
|
+
"axis-axis",
|
|
2411
|
+
"axis-point",
|
|
2412
|
+
"point-axis"
|
|
2413
|
+
]);
|
|
2414
|
+
/** Entity types the orientation/axis mates require of (entityA, entityB). */
|
|
2301
2415
|
var REQUIRED_ENTITIES = {
|
|
2302
|
-
coincident: "plane",
|
|
2303
|
-
distance: "plane",
|
|
2304
2416
|
angle: "plane",
|
|
2305
2417
|
concentric: "axis"
|
|
2306
2418
|
};
|
|
@@ -2310,21 +2422,51 @@ var POSITIONING_TYPES = new Set([
|
|
|
2310
2422
|
"angle",
|
|
2311
2423
|
"concentric"
|
|
2312
2424
|
]);
|
|
2425
|
+
/** Whether a positioning mate's entity pair is solvable. */
|
|
2426
|
+
function isSupportedPair(type, a, b) {
|
|
2427
|
+
const required = REQUIRED_ENTITIES[type];
|
|
2428
|
+
if (required) return a === required && b === required;
|
|
2429
|
+
return TRANSLATIONAL_PAIRS.has(`${a}-${b}`);
|
|
2430
|
+
}
|
|
2431
|
+
/**
|
|
2432
|
+
* Solve a `coincident` (extra = 0) or `distance` (extra = value) mate for any
|
|
2433
|
+
* supported entity-type pair. `ref` is already in world space; the dependent is
|
|
2434
|
+
* at the origin. Returns null only for an unsupported pair (filtered out
|
|
2435
|
+
* upstream by `isSupportedPair`).
|
|
2436
|
+
*/
|
|
2437
|
+
function solveTranslational(ref, dep, extra) {
|
|
2438
|
+
switch (`${ref.type}-${dep.type}`) {
|
|
2439
|
+
case "plane-plane":
|
|
2440
|
+
case "plane-point": return solvePlanePair(ref, dep, extra);
|
|
2441
|
+
case "point-plane": return solvePlaneToPoint(dep.normal ?? [
|
|
2442
|
+
0,
|
|
2443
|
+
0,
|
|
2444
|
+
1
|
|
2445
|
+
], ref.origin, dep.origin, extra);
|
|
2446
|
+
case "point-point": return solvePointPair(ref.origin, dep.origin, extra);
|
|
2447
|
+
case "axis-axis": return extra === 0 ? solveConcentric(ref, dep) : solveAxisAxisDistance(ref, dep, extra);
|
|
2448
|
+
case "axis-point": return solveAxisToPoint(ref, dep.origin, extra);
|
|
2449
|
+
case "point-axis": return solvePointToAxis(ref.origin, dep, extra);
|
|
2450
|
+
default: return null;
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2313
2453
|
/** Dispatch a positioning mate to its solver. `ref` is already in world space. */
|
|
2314
2454
|
function solveMate(c, ref, dep) {
|
|
2315
2455
|
switch (c.type) {
|
|
2316
2456
|
case "concentric": return solveConcentric(ref, dep);
|
|
2317
2457
|
case "angle": return solveAngle(ref, dep, (c.value ?? 0) * Math.PI / 180);
|
|
2318
|
-
case "distance": return solvePlanePair(ref, dep, c.value ?? 0);
|
|
2319
|
-
default: return solvePlanePair(ref, dep, 0);
|
|
2458
|
+
case "distance": return solveTranslational(ref, dep, c.value ?? 0) ?? solvePlanePair(ref, dep, c.value ?? 0);
|
|
2459
|
+
default: return solveTranslational(ref, dep, 0) ?? solvePlanePair(ref, dep, 0);
|
|
2320
2460
|
}
|
|
2321
2461
|
}
|
|
2322
2462
|
/**
|
|
2323
2463
|
* Solve assembly constraints analytically.
|
|
2324
2464
|
*
|
|
2325
|
-
* Handles: fixed,
|
|
2326
|
-
*
|
|
2327
|
-
*
|
|
2465
|
+
* Handles: fixed, concentric (axis-axis), angle (plane-plane orientation), and
|
|
2466
|
+
* coincident/distance for any supported entity-type pair (plane-plane,
|
|
2467
|
+
* plane-point, point-point, axis-axis, axis-point, and both point orders — see
|
|
2468
|
+
* `TRANSLATIONAL_PAIRS`). For a positioning mate, entityA is the reference and
|
|
2469
|
+
* entityB the dependent. Chain roots (nodes never positioned by a
|
|
2328
2470
|
* mate) and explicit `fixed` nodes anchor at the origin; constraints then resolve
|
|
2329
2471
|
* in topological order — each places its dependent against the reference's solved
|
|
2330
2472
|
* pose (rotation included), so multi-body chains compose. Returns
|
|
@@ -2351,9 +2493,10 @@ function solveConstraints(nodes, constraints) {
|
|
|
2351
2493
|
const pending = [];
|
|
2352
2494
|
for (const c of positioning) {
|
|
2353
2495
|
if (!c.entityA || !c.entityB) continue;
|
|
2354
|
-
const
|
|
2355
|
-
|
|
2356
|
-
|
|
2496
|
+
const a = c.entityA.entity.type;
|
|
2497
|
+
const b = c.entityB.entity.type;
|
|
2498
|
+
if (!isSupportedPair(c.type, a, b)) {
|
|
2499
|
+
unsupported.push(`${c.type}(${a}-${b})`);
|
|
2357
2500
|
continue;
|
|
2358
2501
|
}
|
|
2359
2502
|
pending.push(c);
|
|
@@ -34,9 +34,11 @@ export interface SolverResult {
|
|
|
34
34
|
/**
|
|
35
35
|
* Solve assembly constraints analytically.
|
|
36
36
|
*
|
|
37
|
-
* Handles: fixed,
|
|
38
|
-
*
|
|
39
|
-
*
|
|
37
|
+
* Handles: fixed, concentric (axis-axis), angle (plane-plane orientation), and
|
|
38
|
+
* coincident/distance for any supported entity-type pair (plane-plane,
|
|
39
|
+
* plane-point, point-point, axis-axis, axis-point, and both point orders — see
|
|
40
|
+
* `TRANSLATIONAL_PAIRS`). For a positioning mate, entityA is the reference and
|
|
41
|
+
* entityB the dependent. Chain roots (nodes never positioned by a
|
|
40
42
|
* mate) and explicit `fixed` nodes anchor at the origin; constraints then resolve
|
|
41
43
|
* in topological order — each places its dependent against the reference's solved
|
|
42
44
|
* pose (rotation included), so multi-body chains compose. Returns
|