brepjs 18.110.0 → 18.112.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 +277 -1
- package/dist/brepjs.js +275 -5
- package/dist/{healingFns-CPm_VFck.js → healingFns-D00TPE9p.js} +62 -1
- package/dist/{healingFns-C4UE1ZyM.cjs → healingFns-x1sHV-HO.cjs} +73 -0
- package/dist/index.d.ts +3 -3
- package/dist/topology/adjacencyFns.d.ts +15 -0
- package/dist/topology/shapeRef/edgeRefFns.d.ts +15 -0
- package/dist/topology/shapeRef/index.d.ts +3 -1
- package/dist/topology/shapeRef/roleLookup.d.ts +9 -0
- package/dist/topology/shapeRef/shapeRefTypes.d.ts +64 -1
- package/dist/topology/shapeRef/vertexRefFns.d.ts +14 -0
- package/dist/topology/topologyQueryFns.d.ts +5 -0
- package/dist/topology.cjs +1 -1
- package/dist/topology.js +1 -1
- package/package.json +3 -3
package/dist/brepjs.cjs
CHANGED
|
@@ -16,7 +16,7 @@ const require_meshFns = require("./meshFns-1hQSn1p2.cjs");
|
|
|
16
16
|
const require_arrayAccess = require("./arrayAccess-e4H9cBfh.cjs");
|
|
17
17
|
const require_surfaceBuilders = require("./surfaceBuilders-UyyfZy8w.cjs");
|
|
18
18
|
const require_solidBuilders = require("./solidBuilders-DiUv_mD0.cjs");
|
|
19
|
-
const require_healingFns = require("./healingFns-
|
|
19
|
+
const require_healingFns = require("./healingFns-x1sHV-HO.cjs");
|
|
20
20
|
const require_threadFns = require("./threadFns-C8bErjVC.cjs");
|
|
21
21
|
const require_blueprintSketcher = require("./blueprintSketcher-RK-cH6ps.cjs");
|
|
22
22
|
const require_helpers = require("./helpers-BSLPCflF.cjs");
|
|
@@ -1175,6 +1175,276 @@ function withKernelDir(v, fn) {
|
|
|
1175
1175
|
}
|
|
1176
1176
|
}
|
|
1177
1177
|
//#endregion
|
|
1178
|
+
//#region src/topology/shapeRef/roleLookup.ts
|
|
1179
|
+
/** Euclidean distance between two points. */
|
|
1180
|
+
function distance(a, b) {
|
|
1181
|
+
const dx = a[0] - b[0];
|
|
1182
|
+
const dy = a[1] - b[1];
|
|
1183
|
+
const dz = a[2] - b[2];
|
|
1184
|
+
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
1185
|
+
}
|
|
1186
|
+
/** The role whose tracked hashes include this face (reverse lookup). */
|
|
1187
|
+
function roleOfFace(face, origin, roles) {
|
|
1188
|
+
const originRoles = roles.get(origin);
|
|
1189
|
+
if (!originRoles) return void 0;
|
|
1190
|
+
const hash = require_shapeFns.getHashCode(face);
|
|
1191
|
+
for (const [role, hashes] of originRoles) if (hashes.includes(hash)) return role;
|
|
1192
|
+
}
|
|
1193
|
+
/** Current faces a role resolves to — its tracked successors present in `shape`. */
|
|
1194
|
+
function facesForRole(shape, origin, role, roles) {
|
|
1195
|
+
const hashes = roles.get(origin)?.get(role);
|
|
1196
|
+
if (hashes === void 0 || hashes.length === 0) return [];
|
|
1197
|
+
return require_topologyQueryFns.getFaces(shape).filter((f) => hashes.includes(require_shapeFns.getHashCode(f)));
|
|
1198
|
+
}
|
|
1199
|
+
//#endregion
|
|
1200
|
+
//#region src/topology/shapeRef/edgeRefFns.ts
|
|
1201
|
+
/** Midpoint of an edge's endpoint vertices (a closed edge collapses to one). */
|
|
1202
|
+
function endpointMidpoint(verts) {
|
|
1203
|
+
if (verts.length === 0) return void 0;
|
|
1204
|
+
let x = 0;
|
|
1205
|
+
let y = 0;
|
|
1206
|
+
let z = 0;
|
|
1207
|
+
for (const v of verts) {
|
|
1208
|
+
const p = require_topologyQueryFns.vertexPosition(v);
|
|
1209
|
+
x += p[0];
|
|
1210
|
+
y += p[1];
|
|
1211
|
+
z += p[2];
|
|
1212
|
+
}
|
|
1213
|
+
const n = verts.length;
|
|
1214
|
+
return [
|
|
1215
|
+
x / n,
|
|
1216
|
+
y / n,
|
|
1217
|
+
z / n
|
|
1218
|
+
];
|
|
1219
|
+
}
|
|
1220
|
+
function captureEdgeHint(edge) {
|
|
1221
|
+
const lengthResult = require_measureFns.measureLength(edge);
|
|
1222
|
+
return {
|
|
1223
|
+
entityType: "edge",
|
|
1224
|
+
length: lengthResult.ok ? lengthResult.value : void 0,
|
|
1225
|
+
midpoint: endpointMidpoint(require_healingFns.verticesOfEdge(edge))
|
|
1226
|
+
};
|
|
1227
|
+
}
|
|
1228
|
+
function dedupeEdges(edges) {
|
|
1229
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1230
|
+
const out = [];
|
|
1231
|
+
for (const e of edges) {
|
|
1232
|
+
const h = require_shapeFns.getHashCode(e);
|
|
1233
|
+
if (!seen.has(h)) {
|
|
1234
|
+
seen.add(h);
|
|
1235
|
+
out.push(e);
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
return out;
|
|
1239
|
+
}
|
|
1240
|
+
/** Hint scores closer than this are treated as indistinguishable (→ ambiguous). */
|
|
1241
|
+
var HINT_MARGIN$1 = 1e-6;
|
|
1242
|
+
/**
|
|
1243
|
+
* Pick the candidate edge closest to the hint (length + endpoint midpoint).
|
|
1244
|
+
* Returns undefined when it genuinely can't discriminate — the hint carries no
|
|
1245
|
+
* signal, or the two best candidates score within {@link HINT_MARGIN} — so the
|
|
1246
|
+
* caller can report `ambiguous` rather than committing to an arbitrary edge.
|
|
1247
|
+
*/
|
|
1248
|
+
function bestByHint(candidates, hint) {
|
|
1249
|
+
if (hint.length === void 0 && hint.midpoint === void 0) return void 0;
|
|
1250
|
+
let best;
|
|
1251
|
+
let bestScore = Infinity;
|
|
1252
|
+
let secondScore = Infinity;
|
|
1253
|
+
for (const edge of candidates) {
|
|
1254
|
+
let score = 0;
|
|
1255
|
+
if (hint.length !== void 0) {
|
|
1256
|
+
const len = require_measureFns.measureLength(edge);
|
|
1257
|
+
if (len.ok) score += Math.abs(len.value - hint.length);
|
|
1258
|
+
}
|
|
1259
|
+
if (hint.midpoint !== void 0) {
|
|
1260
|
+
const mid = endpointMidpoint(require_healingFns.verticesOfEdge(edge));
|
|
1261
|
+
if (mid !== void 0) score += distance(hint.midpoint, mid);
|
|
1262
|
+
}
|
|
1263
|
+
if (score < bestScore) {
|
|
1264
|
+
secondScore = bestScore;
|
|
1265
|
+
bestScore = score;
|
|
1266
|
+
best = edge;
|
|
1267
|
+
} else if (score < secondScore) secondScore = score;
|
|
1268
|
+
}
|
|
1269
|
+
if (best === void 0 || secondScore - bestScore < HINT_MARGIN$1) return void 0;
|
|
1270
|
+
return best;
|
|
1271
|
+
}
|
|
1272
|
+
/**
|
|
1273
|
+
* Capture a lineage-based reference to `edge`: its two adjacent faces' roles
|
|
1274
|
+
* plus a geometric hint. Returns undefined when the edge doesn't bound two faces
|
|
1275
|
+
* (a boundary/degenerate edge) or when either bounding face has no role yet.
|
|
1276
|
+
*/
|
|
1277
|
+
function createEdgeRef(origin, edge, shape, roles) {
|
|
1278
|
+
const [faceA, faceB] = require_healingFns.facesOfEdge(shape, edge);
|
|
1279
|
+
if (faceA === void 0 || faceB === void 0) return void 0;
|
|
1280
|
+
const roleA = roleOfFace(faceA, origin, roles);
|
|
1281
|
+
const roleB = roleOfFace(faceB, origin, roles);
|
|
1282
|
+
if (roleA === void 0 || roleB === void 0) return void 0;
|
|
1283
|
+
return {
|
|
1284
|
+
origin,
|
|
1285
|
+
faceRoles: [roleA, roleB],
|
|
1286
|
+
hint: captureEdgeHint(edge)
|
|
1287
|
+
};
|
|
1288
|
+
}
|
|
1289
|
+
/**
|
|
1290
|
+
* Resolve an EdgeRef in `shape`: resolve its two face-roles to current faces,
|
|
1291
|
+
* then return the edge they share. One shared edge → exact; several (the two
|
|
1292
|
+
* faces meet along more than one edge) → disambiguate by hint; none, or a
|
|
1293
|
+
* missing bounding face → broken.
|
|
1294
|
+
*/
|
|
1295
|
+
function resolveEdgeRef(ref, roles, shape) {
|
|
1296
|
+
const [roleA, roleB] = ref.faceRoles;
|
|
1297
|
+
const facesA = facesForRole(shape, ref.origin, roleA, roles);
|
|
1298
|
+
const facesB = facesForRole(shape, ref.origin, roleB, roles);
|
|
1299
|
+
if (facesA.length === 0 || facesB.length === 0) return {
|
|
1300
|
+
ref,
|
|
1301
|
+
reason: "not-found"
|
|
1302
|
+
};
|
|
1303
|
+
const candidates = [];
|
|
1304
|
+
for (const a of facesA) for (const b of facesB) candidates.push(...require_healingFns.sharedEdges(a, b));
|
|
1305
|
+
const unique = dedupeEdges(candidates);
|
|
1306
|
+
if (unique.length === 1) {
|
|
1307
|
+
const [only] = unique;
|
|
1308
|
+
if (only !== void 0) return {
|
|
1309
|
+
edge: only,
|
|
1310
|
+
confidence: "exact"
|
|
1311
|
+
};
|
|
1312
|
+
}
|
|
1313
|
+
if (unique.length > 1) {
|
|
1314
|
+
const best = bestByHint(unique, ref.hint);
|
|
1315
|
+
if (best !== void 0) return {
|
|
1316
|
+
edge: best,
|
|
1317
|
+
confidence: "geometric-fallback"
|
|
1318
|
+
};
|
|
1319
|
+
return {
|
|
1320
|
+
ref,
|
|
1321
|
+
reason: "ambiguous",
|
|
1322
|
+
candidates: unique
|
|
1323
|
+
};
|
|
1324
|
+
}
|
|
1325
|
+
return {
|
|
1326
|
+
ref,
|
|
1327
|
+
reason: "not-found"
|
|
1328
|
+
};
|
|
1329
|
+
}
|
|
1330
|
+
//#endregion
|
|
1331
|
+
//#region src/topology/shapeRef/vertexRefFns.ts
|
|
1332
|
+
/** A corner needs at least this many faces to pin a unique point. */
|
|
1333
|
+
var MIN_VERTEX_FACES = 3;
|
|
1334
|
+
/** Hint distances closer than this are indistinguishable (→ ambiguous). */
|
|
1335
|
+
var HINT_MARGIN = 1e-6;
|
|
1336
|
+
/** Hashes of all vertices across `faces`, recording one handle per hash. */
|
|
1337
|
+
function vertexHashes(faces, handles) {
|
|
1338
|
+
const hashes = /* @__PURE__ */ new Set();
|
|
1339
|
+
for (const f of faces) for (const v of require_healingFns.verticesOfFace(f)) {
|
|
1340
|
+
const h = require_shapeFns.getHashCode(v);
|
|
1341
|
+
hashes.add(h);
|
|
1342
|
+
if (!handles.has(h)) handles.set(h, v);
|
|
1343
|
+
}
|
|
1344
|
+
return hashes;
|
|
1345
|
+
}
|
|
1346
|
+
function intersect$2(a, b) {
|
|
1347
|
+
const out = /* @__PURE__ */ new Set();
|
|
1348
|
+
for (const h of a) if (b.has(h)) out.add(h);
|
|
1349
|
+
return out;
|
|
1350
|
+
}
|
|
1351
|
+
/** Vertices present in (a face of) every face-set — the shared corner(s). */
|
|
1352
|
+
function commonVertices(faceSets) {
|
|
1353
|
+
const handles = /* @__PURE__ */ new Map();
|
|
1354
|
+
let common;
|
|
1355
|
+
for (const faces of faceSets) {
|
|
1356
|
+
const hashes = vertexHashes(faces, handles);
|
|
1357
|
+
common = common === void 0 ? hashes : intersect$2(common, hashes);
|
|
1358
|
+
}
|
|
1359
|
+
if (common === void 0) return [];
|
|
1360
|
+
const result = [];
|
|
1361
|
+
for (const h of common) {
|
|
1362
|
+
const v = handles.get(h);
|
|
1363
|
+
if (v !== void 0) result.push(v);
|
|
1364
|
+
}
|
|
1365
|
+
return result;
|
|
1366
|
+
}
|
|
1367
|
+
/** Nearest candidate to the hint position; undefined if no signal or a tie. */
|
|
1368
|
+
function nearestToHint(vertices, hint) {
|
|
1369
|
+
if (hint.position === void 0) return void 0;
|
|
1370
|
+
let best;
|
|
1371
|
+
let bestDist = Infinity;
|
|
1372
|
+
let secondDist = Infinity;
|
|
1373
|
+
for (const v of vertices) {
|
|
1374
|
+
const d = distance(require_topologyQueryFns.vertexPosition(v), hint.position);
|
|
1375
|
+
if (d < bestDist) {
|
|
1376
|
+
secondDist = bestDist;
|
|
1377
|
+
bestDist = d;
|
|
1378
|
+
best = v;
|
|
1379
|
+
} else if (d < secondDist) secondDist = d;
|
|
1380
|
+
}
|
|
1381
|
+
if (best === void 0 || secondDist - bestDist < HINT_MARGIN) return void 0;
|
|
1382
|
+
return best;
|
|
1383
|
+
}
|
|
1384
|
+
/**
|
|
1385
|
+
* Capture a lineage-based reference to `vertex`: the roles of the ≥3 faces
|
|
1386
|
+
* meeting at it, plus a position hint. Returns undefined when fewer than three
|
|
1387
|
+
* named faces meet there (a 2-face "vertex" is ambiguous — an edge has two).
|
|
1388
|
+
*/
|
|
1389
|
+
function createVertexRef(origin, vertex, shape, roles) {
|
|
1390
|
+
const faces = require_healingFns.facesOfVertex(shape, vertex);
|
|
1391
|
+
if (faces.length < MIN_VERTEX_FACES) return void 0;
|
|
1392
|
+
const roleSet = /* @__PURE__ */ new Set();
|
|
1393
|
+
for (const f of faces) {
|
|
1394
|
+
const role = roleOfFace(f, origin, roles);
|
|
1395
|
+
if (role !== void 0) roleSet.add(role);
|
|
1396
|
+
}
|
|
1397
|
+
if (roleSet.size < MIN_VERTEX_FACES) return void 0;
|
|
1398
|
+
return {
|
|
1399
|
+
origin,
|
|
1400
|
+
faceRoles: [...roleSet].sort(),
|
|
1401
|
+
hint: {
|
|
1402
|
+
entityType: "vertex",
|
|
1403
|
+
position: require_topologyQueryFns.vertexPosition(vertex)
|
|
1404
|
+
}
|
|
1405
|
+
};
|
|
1406
|
+
}
|
|
1407
|
+
/**
|
|
1408
|
+
* Resolve a VertexRef in `shape`: gather the current faces of each role, then
|
|
1409
|
+
* return the vertex common to all of them. One common vertex → exact; several →
|
|
1410
|
+
* disambiguate by hint position; none, or a missing role → broken.
|
|
1411
|
+
*/
|
|
1412
|
+
function resolveVertexRef(ref, roles, shape) {
|
|
1413
|
+
const faceSets = [];
|
|
1414
|
+
for (const role of ref.faceRoles) {
|
|
1415
|
+
const faces = facesForRole(shape, ref.origin, role, roles);
|
|
1416
|
+
if (faces.length === 0) return {
|
|
1417
|
+
ref,
|
|
1418
|
+
reason: "not-found"
|
|
1419
|
+
};
|
|
1420
|
+
faceSets.push(faces);
|
|
1421
|
+
}
|
|
1422
|
+
const common = commonVertices(faceSets);
|
|
1423
|
+
if (common.length === 1) {
|
|
1424
|
+
const [only] = common;
|
|
1425
|
+
if (only !== void 0) return {
|
|
1426
|
+
vertex: only,
|
|
1427
|
+
confidence: "exact"
|
|
1428
|
+
};
|
|
1429
|
+
}
|
|
1430
|
+
if (common.length > 1) {
|
|
1431
|
+
const best = nearestToHint(common, ref.hint);
|
|
1432
|
+
if (best !== void 0) return {
|
|
1433
|
+
vertex: best,
|
|
1434
|
+
confidence: "geometric-fallback"
|
|
1435
|
+
};
|
|
1436
|
+
return {
|
|
1437
|
+
ref,
|
|
1438
|
+
reason: "ambiguous",
|
|
1439
|
+
candidates: common
|
|
1440
|
+
};
|
|
1441
|
+
}
|
|
1442
|
+
return {
|
|
1443
|
+
ref,
|
|
1444
|
+
reason: "not-found"
|
|
1445
|
+
};
|
|
1446
|
+
}
|
|
1447
|
+
//#endregion
|
|
1178
1448
|
//#region src/topology/surfaceFns.ts
|
|
1179
1449
|
/**
|
|
1180
1450
|
* Surface creation functions — generate faces from height-map grids.
|
|
@@ -6880,6 +7150,7 @@ exports.createCompound = require_shapeTypes.createCompound;
|
|
|
6880
7150
|
exports.createCompoundBlueprint = require_blueprintFns.createCompoundBlueprint;
|
|
6881
7151
|
exports.createDistanceQuery = require_measureFns.createDistanceQuery;
|
|
6882
7152
|
exports.createEdge = require_shapeTypes.createEdge;
|
|
7153
|
+
exports.createEdgeRef = createEdgeRef;
|
|
6883
7154
|
exports.createFace = require_shapeTypes.createFace;
|
|
6884
7155
|
exports.createHandle = require_shapeTypes.createHandle;
|
|
6885
7156
|
exports.createHistory = require_threadFns.createHistory;
|
|
@@ -6894,6 +7165,7 @@ exports.createShell = require_shapeTypes.createShell;
|
|
|
6894
7165
|
exports.createSolid = require_shapeTypes.createSolid;
|
|
6895
7166
|
exports.createTaskQueue = require_workerPool.createTaskQueue;
|
|
6896
7167
|
exports.createVertex = require_shapeTypes.createVertex;
|
|
7168
|
+
exports.createVertexRef = createVertexRef;
|
|
6897
7169
|
exports.createWire = require_shapeTypes.createWire;
|
|
6898
7170
|
exports.createWorkerClient = require_workerPool.createWorkerClient;
|
|
6899
7171
|
exports.createWorkerHandler = require_workerPool.createWorkerHandler;
|
|
@@ -6985,6 +7257,7 @@ exports.faceFinder = require_helpers.faceFinder;
|
|
|
6985
7257
|
exports.faceGeomType = require_faceFns.faceGeomType;
|
|
6986
7258
|
exports.faceOrientation = require_faceFns.faceOrientation;
|
|
6987
7259
|
exports.facesOfEdge = require_healingFns.facesOfEdge;
|
|
7260
|
+
exports.facesOfVertex = require_healingFns.facesOfVertex;
|
|
6988
7261
|
exports.fieldBoolean = fieldBoolean;
|
|
6989
7262
|
exports.fieldContour = fieldContour;
|
|
6990
7263
|
exports.fieldOffset = fieldOffset;
|
|
@@ -7267,8 +7540,10 @@ exports.resize = require_shapeFns.resize;
|
|
|
7267
7540
|
exports.resolve = resolve;
|
|
7268
7541
|
exports.resolve3D = resolve3D;
|
|
7269
7542
|
exports.resolveDirection = require_types.resolveDirection;
|
|
7543
|
+
exports.resolveEdgeRef = resolveEdgeRef;
|
|
7270
7544
|
exports.resolvePlane = require_planeOps.resolvePlane;
|
|
7271
7545
|
exports.resolveRef = require_shapeRefFns.resolveRef;
|
|
7546
|
+
exports.resolveVertexRef = resolveVertexRef;
|
|
7272
7547
|
exports.reverseCurve = require_blueprintFns.reverseCurve;
|
|
7273
7548
|
exports.revoluteJoint = require_threadFns.revoluteJoint;
|
|
7274
7549
|
exports.revolve = revolve;
|
|
@@ -7418,6 +7693,7 @@ exports.vertex = require_primitiveFns.vertex;
|
|
|
7418
7693
|
exports.vertexFinder = vertexFinder;
|
|
7419
7694
|
exports.vertexPosition = require_topologyQueryFns.vertexPosition;
|
|
7420
7695
|
exports.verticesOfEdge = require_healingFns.verticesOfEdge;
|
|
7696
|
+
exports.verticesOfFace = require_healingFns.verticesOfFace;
|
|
7421
7697
|
exports.voxelBoolean = voxelBoolean;
|
|
7422
7698
|
exports.voxelBooleanField = voxelBooleanField;
|
|
7423
7699
|
exports.voxelBooleanFieldShapes = voxelBooleanFieldShapes;
|
package/dist/brepjs.js
CHANGED
|
@@ -13,8 +13,8 @@ import { a as curveIsPeriodic, c as curvePointAt, d as flipOrientation, f as get
|
|
|
13
13
|
import { a as meshEdges$1, c as meshMultiLOD, d as createMeshCache, i as mesh$1, l as buildMeshCacheKey, n as exportSTEP, o as meshLODs, r as exportSTL, s as meshLODsProgressive, t as exportIGES, u as clearMeshCache } from "./meshFns-DbmidUzH.js";
|
|
14
14
|
import { n as getAtOrThrow, r as lastOrThrow, t as firstOrThrow } from "./arrayAccess-DrUGPADn.js";
|
|
15
15
|
import { _ as makeThreePointArc, d as makeCircle, h as makeLine, l as makeBSplineInterpolation, n as fill, r as makeFace, s as assembleWire } from "./surfaceBuilders-rkE-jE90.js";
|
|
16
|
-
import { _ as section$1, b as split$1, d as booleanPipeline, f as cut$2, g as intersect$
|
|
17
|
-
import { A as edgesOfFace, B as
|
|
16
|
+
import { _ as section$1, b as split$1, d as booleanPipeline, f as cut$2, g as intersect$3, h as fuseAll$2, m as fuse$2, p as cutAll$2, r as makeCylinder, t as makeCompound, v as sectionToFace$1, y as slice$1 } from "./solidBuilders-C32wXQWG.js";
|
|
17
|
+
import { A as edgesOfFace, B as toLODGeometryData, C as shellWithEvolution, D as getNurbsCurveData, E as fuseAllBisect, F as verticesOfFace, H as toLineGeometryData, I as wiresOfFace, L as chamferDistAngle, M as facesOfVertex, N as sharedEdges, O as getNurbsSurfaceData, P as verticesOfEdge, R as toBufferGeometryData, S as intersectWithEvolution, T as cutAllBisect, V as toLODGeometryLevels, _ as positionOnCurve, a as healFace, b as filletWithEvolution, c as isValid$1, d as draft$1, f as fillet$1, g as variableFillet, h as thicken$1, i as heal$1, j as facesOfEdge, k as adjacentFaces, l as solidFromShell, m as shell$1, n as fixSelfIntersection, o as healSolid, p as offset$1, r as fixShape, s as healWire, t as autoHeal, u as chamfer$1, v as chamferWithEvolution, w as checkBoolean, x as fuseWithEvolution, y as cutWithEvolution, z as toGroupedBufferGeometryData } from "./healingFns-D00TPE9p.js";
|
|
18
18
|
import { A as setJointValue, B as findNode, C as cylindricalJoint, D as planarJoint, E as mechanismDOF, F as quatRotate, G as gridPattern, H as updateNode, I as addChild, J as createAssembly, K as linearPattern, L as collectShapes, M as sphericalJoint, N as quatFromAxisAngle, O as prismaticJoint, P as quatFromTo, R as countNodes, S as addJoint, T as jointTransform, U as walkAssembly, V as removeChild, W as circularPattern, _ as exportURDF, a as deserializeHistory, b as inverseKinematics, c as modifyStep, d as replayFrom, f as replayHistory, g as undoLast, h as stepsFrom, i as createRegistry, j as setJointValues, k as revoluteJoint, l as registerOperation, m as stepCount, n as addStep, o as findStep, p as serializeHistory, q as exportAssemblySTEP, r as createHistory, s as getShape, t as thread, u as registerShape, v as importURDF, w as forwardKinematics, x as jointTrajectory, y as jointsFromDH, z as createAssemblyNode } from "./threadFns-bCOhVQLb.js";
|
|
19
19
|
import { n as BaseSketcher2d, r as organiseBlueprints, t as BlueprintSketcher } from "./blueprintSketcher-7rtwqUHZ.js";
|
|
20
20
|
import { a as createTypedFinder, i as wireFinder, n as edgeFinder, r as faceFinder, t as getSingleFace } from "./helpers-DhJwFrkC.js";
|
|
@@ -1186,6 +1186,276 @@ function withKernelDir(v, fn) {
|
|
|
1186
1186
|
}
|
|
1187
1187
|
}
|
|
1188
1188
|
//#endregion
|
|
1189
|
+
//#region src/topology/shapeRef/roleLookup.ts
|
|
1190
|
+
/** Euclidean distance between two points. */
|
|
1191
|
+
function distance(a, b) {
|
|
1192
|
+
const dx = a[0] - b[0];
|
|
1193
|
+
const dy = a[1] - b[1];
|
|
1194
|
+
const dz = a[2] - b[2];
|
|
1195
|
+
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
1196
|
+
}
|
|
1197
|
+
/** The role whose tracked hashes include this face (reverse lookup). */
|
|
1198
|
+
function roleOfFace(face, origin, roles) {
|
|
1199
|
+
const originRoles = roles.get(origin);
|
|
1200
|
+
if (!originRoles) return void 0;
|
|
1201
|
+
const hash = getHashCode(face);
|
|
1202
|
+
for (const [role, hashes] of originRoles) if (hashes.includes(hash)) return role;
|
|
1203
|
+
}
|
|
1204
|
+
/** Current faces a role resolves to — its tracked successors present in `shape`. */
|
|
1205
|
+
function facesForRole(shape, origin, role, roles) {
|
|
1206
|
+
const hashes = roles.get(origin)?.get(role);
|
|
1207
|
+
if (hashes === void 0 || hashes.length === 0) return [];
|
|
1208
|
+
return getFaces(shape).filter((f) => hashes.includes(getHashCode(f)));
|
|
1209
|
+
}
|
|
1210
|
+
//#endregion
|
|
1211
|
+
//#region src/topology/shapeRef/edgeRefFns.ts
|
|
1212
|
+
/** Midpoint of an edge's endpoint vertices (a closed edge collapses to one). */
|
|
1213
|
+
function endpointMidpoint(verts) {
|
|
1214
|
+
if (verts.length === 0) return void 0;
|
|
1215
|
+
let x = 0;
|
|
1216
|
+
let y = 0;
|
|
1217
|
+
let z = 0;
|
|
1218
|
+
for (const v of verts) {
|
|
1219
|
+
const p = vertexPosition(v);
|
|
1220
|
+
x += p[0];
|
|
1221
|
+
y += p[1];
|
|
1222
|
+
z += p[2];
|
|
1223
|
+
}
|
|
1224
|
+
const n = verts.length;
|
|
1225
|
+
return [
|
|
1226
|
+
x / n,
|
|
1227
|
+
y / n,
|
|
1228
|
+
z / n
|
|
1229
|
+
];
|
|
1230
|
+
}
|
|
1231
|
+
function captureEdgeHint(edge) {
|
|
1232
|
+
const lengthResult = measureLength(edge);
|
|
1233
|
+
return {
|
|
1234
|
+
entityType: "edge",
|
|
1235
|
+
length: lengthResult.ok ? lengthResult.value : void 0,
|
|
1236
|
+
midpoint: endpointMidpoint(verticesOfEdge(edge))
|
|
1237
|
+
};
|
|
1238
|
+
}
|
|
1239
|
+
function dedupeEdges(edges) {
|
|
1240
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1241
|
+
const out = [];
|
|
1242
|
+
for (const e of edges) {
|
|
1243
|
+
const h = getHashCode(e);
|
|
1244
|
+
if (!seen.has(h)) {
|
|
1245
|
+
seen.add(h);
|
|
1246
|
+
out.push(e);
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
return out;
|
|
1250
|
+
}
|
|
1251
|
+
/** Hint scores closer than this are treated as indistinguishable (→ ambiguous). */
|
|
1252
|
+
var HINT_MARGIN$1 = 1e-6;
|
|
1253
|
+
/**
|
|
1254
|
+
* Pick the candidate edge closest to the hint (length + endpoint midpoint).
|
|
1255
|
+
* Returns undefined when it genuinely can't discriminate — the hint carries no
|
|
1256
|
+
* signal, or the two best candidates score within {@link HINT_MARGIN} — so the
|
|
1257
|
+
* caller can report `ambiguous` rather than committing to an arbitrary edge.
|
|
1258
|
+
*/
|
|
1259
|
+
function bestByHint(candidates, hint) {
|
|
1260
|
+
if (hint.length === void 0 && hint.midpoint === void 0) return void 0;
|
|
1261
|
+
let best;
|
|
1262
|
+
let bestScore = Infinity;
|
|
1263
|
+
let secondScore = Infinity;
|
|
1264
|
+
for (const edge of candidates) {
|
|
1265
|
+
let score = 0;
|
|
1266
|
+
if (hint.length !== void 0) {
|
|
1267
|
+
const len = measureLength(edge);
|
|
1268
|
+
if (len.ok) score += Math.abs(len.value - hint.length);
|
|
1269
|
+
}
|
|
1270
|
+
if (hint.midpoint !== void 0) {
|
|
1271
|
+
const mid = endpointMidpoint(verticesOfEdge(edge));
|
|
1272
|
+
if (mid !== void 0) score += distance(hint.midpoint, mid);
|
|
1273
|
+
}
|
|
1274
|
+
if (score < bestScore) {
|
|
1275
|
+
secondScore = bestScore;
|
|
1276
|
+
bestScore = score;
|
|
1277
|
+
best = edge;
|
|
1278
|
+
} else if (score < secondScore) secondScore = score;
|
|
1279
|
+
}
|
|
1280
|
+
if (best === void 0 || secondScore - bestScore < HINT_MARGIN$1) return void 0;
|
|
1281
|
+
return best;
|
|
1282
|
+
}
|
|
1283
|
+
/**
|
|
1284
|
+
* Capture a lineage-based reference to `edge`: its two adjacent faces' roles
|
|
1285
|
+
* plus a geometric hint. Returns undefined when the edge doesn't bound two faces
|
|
1286
|
+
* (a boundary/degenerate edge) or when either bounding face has no role yet.
|
|
1287
|
+
*/
|
|
1288
|
+
function createEdgeRef(origin, edge, shape, roles) {
|
|
1289
|
+
const [faceA, faceB] = facesOfEdge(shape, edge);
|
|
1290
|
+
if (faceA === void 0 || faceB === void 0) return void 0;
|
|
1291
|
+
const roleA = roleOfFace(faceA, origin, roles);
|
|
1292
|
+
const roleB = roleOfFace(faceB, origin, roles);
|
|
1293
|
+
if (roleA === void 0 || roleB === void 0) return void 0;
|
|
1294
|
+
return {
|
|
1295
|
+
origin,
|
|
1296
|
+
faceRoles: [roleA, roleB],
|
|
1297
|
+
hint: captureEdgeHint(edge)
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1300
|
+
/**
|
|
1301
|
+
* Resolve an EdgeRef in `shape`: resolve its two face-roles to current faces,
|
|
1302
|
+
* then return the edge they share. One shared edge → exact; several (the two
|
|
1303
|
+
* faces meet along more than one edge) → disambiguate by hint; none, or a
|
|
1304
|
+
* missing bounding face → broken.
|
|
1305
|
+
*/
|
|
1306
|
+
function resolveEdgeRef(ref, roles, shape) {
|
|
1307
|
+
const [roleA, roleB] = ref.faceRoles;
|
|
1308
|
+
const facesA = facesForRole(shape, ref.origin, roleA, roles);
|
|
1309
|
+
const facesB = facesForRole(shape, ref.origin, roleB, roles);
|
|
1310
|
+
if (facesA.length === 0 || facesB.length === 0) return {
|
|
1311
|
+
ref,
|
|
1312
|
+
reason: "not-found"
|
|
1313
|
+
};
|
|
1314
|
+
const candidates = [];
|
|
1315
|
+
for (const a of facesA) for (const b of facesB) candidates.push(...sharedEdges(a, b));
|
|
1316
|
+
const unique = dedupeEdges(candidates);
|
|
1317
|
+
if (unique.length === 1) {
|
|
1318
|
+
const [only] = unique;
|
|
1319
|
+
if (only !== void 0) return {
|
|
1320
|
+
edge: only,
|
|
1321
|
+
confidence: "exact"
|
|
1322
|
+
};
|
|
1323
|
+
}
|
|
1324
|
+
if (unique.length > 1) {
|
|
1325
|
+
const best = bestByHint(unique, ref.hint);
|
|
1326
|
+
if (best !== void 0) return {
|
|
1327
|
+
edge: best,
|
|
1328
|
+
confidence: "geometric-fallback"
|
|
1329
|
+
};
|
|
1330
|
+
return {
|
|
1331
|
+
ref,
|
|
1332
|
+
reason: "ambiguous",
|
|
1333
|
+
candidates: unique
|
|
1334
|
+
};
|
|
1335
|
+
}
|
|
1336
|
+
return {
|
|
1337
|
+
ref,
|
|
1338
|
+
reason: "not-found"
|
|
1339
|
+
};
|
|
1340
|
+
}
|
|
1341
|
+
//#endregion
|
|
1342
|
+
//#region src/topology/shapeRef/vertexRefFns.ts
|
|
1343
|
+
/** A corner needs at least this many faces to pin a unique point. */
|
|
1344
|
+
var MIN_VERTEX_FACES = 3;
|
|
1345
|
+
/** Hint distances closer than this are indistinguishable (→ ambiguous). */
|
|
1346
|
+
var HINT_MARGIN = 1e-6;
|
|
1347
|
+
/** Hashes of all vertices across `faces`, recording one handle per hash. */
|
|
1348
|
+
function vertexHashes(faces, handles) {
|
|
1349
|
+
const hashes = /* @__PURE__ */ new Set();
|
|
1350
|
+
for (const f of faces) for (const v of verticesOfFace(f)) {
|
|
1351
|
+
const h = getHashCode(v);
|
|
1352
|
+
hashes.add(h);
|
|
1353
|
+
if (!handles.has(h)) handles.set(h, v);
|
|
1354
|
+
}
|
|
1355
|
+
return hashes;
|
|
1356
|
+
}
|
|
1357
|
+
function intersect$2(a, b) {
|
|
1358
|
+
const out = /* @__PURE__ */ new Set();
|
|
1359
|
+
for (const h of a) if (b.has(h)) out.add(h);
|
|
1360
|
+
return out;
|
|
1361
|
+
}
|
|
1362
|
+
/** Vertices present in (a face of) every face-set — the shared corner(s). */
|
|
1363
|
+
function commonVertices(faceSets) {
|
|
1364
|
+
const handles = /* @__PURE__ */ new Map();
|
|
1365
|
+
let common;
|
|
1366
|
+
for (const faces of faceSets) {
|
|
1367
|
+
const hashes = vertexHashes(faces, handles);
|
|
1368
|
+
common = common === void 0 ? hashes : intersect$2(common, hashes);
|
|
1369
|
+
}
|
|
1370
|
+
if (common === void 0) return [];
|
|
1371
|
+
const result = [];
|
|
1372
|
+
for (const h of common) {
|
|
1373
|
+
const v = handles.get(h);
|
|
1374
|
+
if (v !== void 0) result.push(v);
|
|
1375
|
+
}
|
|
1376
|
+
return result;
|
|
1377
|
+
}
|
|
1378
|
+
/** Nearest candidate to the hint position; undefined if no signal or a tie. */
|
|
1379
|
+
function nearestToHint(vertices, hint) {
|
|
1380
|
+
if (hint.position === void 0) return void 0;
|
|
1381
|
+
let best;
|
|
1382
|
+
let bestDist = Infinity;
|
|
1383
|
+
let secondDist = Infinity;
|
|
1384
|
+
for (const v of vertices) {
|
|
1385
|
+
const d = distance(vertexPosition(v), hint.position);
|
|
1386
|
+
if (d < bestDist) {
|
|
1387
|
+
secondDist = bestDist;
|
|
1388
|
+
bestDist = d;
|
|
1389
|
+
best = v;
|
|
1390
|
+
} else if (d < secondDist) secondDist = d;
|
|
1391
|
+
}
|
|
1392
|
+
if (best === void 0 || secondDist - bestDist < HINT_MARGIN) return void 0;
|
|
1393
|
+
return best;
|
|
1394
|
+
}
|
|
1395
|
+
/**
|
|
1396
|
+
* Capture a lineage-based reference to `vertex`: the roles of the ≥3 faces
|
|
1397
|
+
* meeting at it, plus a position hint. Returns undefined when fewer than three
|
|
1398
|
+
* named faces meet there (a 2-face "vertex" is ambiguous — an edge has two).
|
|
1399
|
+
*/
|
|
1400
|
+
function createVertexRef(origin, vertex, shape, roles) {
|
|
1401
|
+
const faces = facesOfVertex(shape, vertex);
|
|
1402
|
+
if (faces.length < MIN_VERTEX_FACES) return void 0;
|
|
1403
|
+
const roleSet = /* @__PURE__ */ new Set();
|
|
1404
|
+
for (const f of faces) {
|
|
1405
|
+
const role = roleOfFace(f, origin, roles);
|
|
1406
|
+
if (role !== void 0) roleSet.add(role);
|
|
1407
|
+
}
|
|
1408
|
+
if (roleSet.size < MIN_VERTEX_FACES) return void 0;
|
|
1409
|
+
return {
|
|
1410
|
+
origin,
|
|
1411
|
+
faceRoles: [...roleSet].sort(),
|
|
1412
|
+
hint: {
|
|
1413
|
+
entityType: "vertex",
|
|
1414
|
+
position: vertexPosition(vertex)
|
|
1415
|
+
}
|
|
1416
|
+
};
|
|
1417
|
+
}
|
|
1418
|
+
/**
|
|
1419
|
+
* Resolve a VertexRef in `shape`: gather the current faces of each role, then
|
|
1420
|
+
* return the vertex common to all of them. One common vertex → exact; several →
|
|
1421
|
+
* disambiguate by hint position; none, or a missing role → broken.
|
|
1422
|
+
*/
|
|
1423
|
+
function resolveVertexRef(ref, roles, shape) {
|
|
1424
|
+
const faceSets = [];
|
|
1425
|
+
for (const role of ref.faceRoles) {
|
|
1426
|
+
const faces = facesForRole(shape, ref.origin, role, roles);
|
|
1427
|
+
if (faces.length === 0) return {
|
|
1428
|
+
ref,
|
|
1429
|
+
reason: "not-found"
|
|
1430
|
+
};
|
|
1431
|
+
faceSets.push(faces);
|
|
1432
|
+
}
|
|
1433
|
+
const common = commonVertices(faceSets);
|
|
1434
|
+
if (common.length === 1) {
|
|
1435
|
+
const [only] = common;
|
|
1436
|
+
if (only !== void 0) return {
|
|
1437
|
+
vertex: only,
|
|
1438
|
+
confidence: "exact"
|
|
1439
|
+
};
|
|
1440
|
+
}
|
|
1441
|
+
if (common.length > 1) {
|
|
1442
|
+
const best = nearestToHint(common, ref.hint);
|
|
1443
|
+
if (best !== void 0) return {
|
|
1444
|
+
vertex: best,
|
|
1445
|
+
confidence: "geometric-fallback"
|
|
1446
|
+
};
|
|
1447
|
+
return {
|
|
1448
|
+
ref,
|
|
1449
|
+
reason: "ambiguous",
|
|
1450
|
+
candidates: common
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1453
|
+
return {
|
|
1454
|
+
ref,
|
|
1455
|
+
reason: "not-found"
|
|
1456
|
+
};
|
|
1457
|
+
}
|
|
1458
|
+
//#endregion
|
|
1189
1459
|
//#region src/topology/surfaceFns.ts
|
|
1190
1460
|
/**
|
|
1191
1461
|
* Surface creation functions — generate faces from height-map grids.
|
|
@@ -3514,7 +3784,7 @@ function cutAll(base, tools, options) {
|
|
|
3514
3784
|
}
|
|
3515
3785
|
/** Compute the intersection of two shapes (boolean common). */
|
|
3516
3786
|
function intersect(a, b, options) {
|
|
3517
|
-
return intersect$
|
|
3787
|
+
return intersect$3(resolve(a), resolve(b), {
|
|
3518
3788
|
...options,
|
|
3519
3789
|
unsafe: true
|
|
3520
3790
|
});
|
|
@@ -5631,7 +5901,7 @@ function evalIntersect(node, ctx) {
|
|
|
5631
5901
|
if (!a.ok) return a;
|
|
5632
5902
|
const b = resolveOperand(ctx, node.b, "Intersect.b");
|
|
5633
5903
|
if (!b.ok) return b;
|
|
5634
|
-
return intersect$
|
|
5904
|
+
return intersect$3(a.value, b.value, boolOptions(node, ctx));
|
|
5635
5905
|
}
|
|
5636
5906
|
function resolveAll(ctx, nodes, where) {
|
|
5637
5907
|
const out = [];
|
|
@@ -6786,4 +7056,4 @@ var csg_exports = /* @__PURE__ */ __exportAll({
|
|
|
6786
7056
|
withEvaluator: () => withEvaluator
|
|
6787
7057
|
});
|
|
6788
7058
|
//#endregion
|
|
6789
|
-
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, createWorkerPool, csg_exports as csg, currentQuality, curve2dBoundingBox, curve2dDistanceFrom, curve2dFirstPoint, curve2dIsOnCurve, curve2dLastPoint, curve2dParameter, curve2dSplitAt, curve2dTangentAt, curveAxis, curveEndPoint, curveIsClosed, curveIsPeriodic, curveLength, curvePeriod, curvePointAt, curveStartPoint, curveTangentAt, cut, cut2D, cutAll, cutAllBisect, cutBlueprints, cutWithEvolution, cylinder, cylindricalJoint, 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, exportURDF, 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, forwardKinematics, 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, gridPattern, guidedSweep, heal, healFace, healSolid, healWire, helix, hull, importDXF, importGLB, importIGES, importOBJ, importSTEP, importSTL, importSVG, importSVGPathD, importThreeMF, importURDF, init, initFromManifold, initFromOC, initVoxel, innerWires, instance, instanceCount, instanceGrid, instancedMesh, interpolateCurve, intersect, intersect2D, intersectBlueprints, intersectWithEvolution, invalidateShapeCache, inverseKinematics, ioNs_exports as io, ioError, is2D, is3D, isBatchRequest, isChamferRadius, isClosedWire, isCompSolid, isCompound, isDisposeRequest, isEdge, isEmpty, isEqualShape, isErr, isErrorResponse, isFace, isFilletRadius, isInitRequest, isInside2D, isInstanced, 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, jointTrajectory, jointTransform, jointsFromDH, kernelCall, kernelCallRaw, kernelCallScoped, kernelError, latticeInfill, latticeInfillShape, line, linearPattern, loadFont, loft, loftAll, makeBaseBox, makeExternalGear, makeInternalGear, makePlane, makePlanetaryGear, makeProjectedEdges, manifoldShell, map, mapBoth, mapErr, match, materialize, measureArea, measureCurvatureAt, measureCurvatureAtMid, measureDistance, measureDistanceProps, measureLength, measureLinearProps, measureSurfaceProps, measureVolume, measureVolumeProps, measurement_exports as measurement, mechanismDOF, mesh, meshEdges, meshLODs, meshLODsProgressive, 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, planarJoint, 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, setJointValues, 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, sphericalJoint, split, stepCount, stepsFrom, stretch2D, subFace, supportExtrude, supportsConstraintSketch, supportsProjection, surfaceFromGrid, surfaceFromImage, sweep$1 as sweep, tagFaces, tangentArc, tap, tapErr, textBlueprints, textMetrics, thicken, thread, threePointArc, toBREP, toBufferGeometryData, toGroupedBufferGeometryData, toKernelVec, toLODGeometryData, toLODGeometryLevels, 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 };
|
|
7059
|
+
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, createEdgeRef, createFace, createHandle, createHistory, createKernelHandle, createMeshCache, createNamedPlane, createOperationRegistry, createPlane, createRef, createRegistry, createShell, createSolid, createTaskQueue, createVertex, createVertexRef, createWire, createWorkerClient, createWorkerHandler, createWorkerPool, csg_exports as csg, currentQuality, curve2dBoundingBox, curve2dDistanceFrom, curve2dFirstPoint, curve2dIsOnCurve, curve2dLastPoint, curve2dParameter, curve2dSplitAt, curve2dTangentAt, curveAxis, curveEndPoint, curveIsClosed, curveIsPeriodic, curveLength, curvePeriod, curvePointAt, curveStartPoint, curveTangentAt, cut, cut2D, cutAll, cutAllBisect, cutBlueprints, cutWithEvolution, cylinder, cylindricalJoint, 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, exportURDF, extrude, extrudeAll, face, faceAxis, faceCenter, faceFinder, faceGeomType, faceOrientation, facesOfEdge, facesOfVertex, fieldBoolean, fieldContour, fieldOffset, fieldReinit, fieldShell, fill, filledFace, fillet, filletWithEvolution, findFacesByTag, findNode, findStep, fixSelfIntersection, fixShape, flatMap, flatten, flipFaceOrientation, flipOrientation, fontMetrics, forwardKinematics, 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, gridPattern, guidedSweep, heal, healFace, healSolid, healWire, helix, hull, importDXF, importGLB, importIGES, importOBJ, importSTEP, importSTL, importSVG, importSVGPathD, importThreeMF, importURDF, init, initFromManifold, initFromOC, initVoxel, innerWires, instance, instanceCount, instanceGrid, instancedMesh, interpolateCurve, intersect, intersect2D, intersectBlueprints, intersectWithEvolution, invalidateShapeCache, inverseKinematics, ioNs_exports as io, ioError, is2D, is3D, isBatchRequest, isChamferRadius, isClosedWire, isCompSolid, isCompound, isDisposeRequest, isEdge, isEmpty, isEqualShape, isErr, isErrorResponse, isFace, isFilletRadius, isInitRequest, isInside2D, isInstanced, 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, jointTrajectory, jointTransform, jointsFromDH, kernelCall, kernelCallRaw, kernelCallScoped, kernelError, latticeInfill, latticeInfillShape, line, linearPattern, loadFont, loft, loftAll, makeBaseBox, makeExternalGear, makeInternalGear, makePlane, makePlanetaryGear, makeProjectedEdges, manifoldShell, map, mapBoth, mapErr, match, materialize, measureArea, measureCurvatureAt, measureCurvatureAtMid, measureDistance, measureDistanceProps, measureLength, measureLinearProps, measureSurfaceProps, measureVolume, measureVolumeProps, measurement_exports as measurement, mechanismDOF, mesh, meshEdges, meshLODs, meshLODsProgressive, 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, planarJoint, 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, resolveEdgeRef, resolvePlane, resolveRef, resolveVertexRef, 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, setJointValues, 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, sphericalJoint, split, stepCount, stepsFrom, stretch2D, subFace, supportExtrude, supportsConstraintSketch, supportsProjection, surfaceFromGrid, surfaceFromImage, sweep$1 as sweep, tagFaces, tangentArc, tap, tapErr, textBlueprints, textMetrics, thicken, thread, threePointArc, toBREP, toBufferGeometryData, toGroupedBufferGeometryData, toKernelVec, toLODGeometryData, toLODGeometryLevels, 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, verticesOfFace, voxelBoolean, voxelBooleanField, voxelBooleanFieldShapes, voxelBooleanShapes, voxelField, voxelFieldFromShape, walkAssembly, windingNumbers, wire, wireFinder, wireLoop, wiresOfFace, withKernel, withKernelDir, withKernelPnt, withKernelVec, withQuality, withScope, withScopeResult, withScopeResultAsync, withTier, zip as zipResults };
|
|
@@ -220,6 +220,30 @@ function getEdgeToFacesMap(parent) {
|
|
|
220
220
|
return edgeToFaces;
|
|
221
221
|
}
|
|
222
222
|
/**
|
|
223
|
+
* Build or retrieve the cached vertex→faces adjacency map for a parent shape —
|
|
224
|
+
* the vertex analogue of {@link getEdgeToFacesMap}.
|
|
225
|
+
*/
|
|
226
|
+
function getVertexToFacesMap(parent) {
|
|
227
|
+
const cache = getOrCreateCache(parent);
|
|
228
|
+
if (cache.vertexToFaces) return cache.vertexToFaces;
|
|
229
|
+
const kernel = getKernel();
|
|
230
|
+
const vertexToFaces = /* @__PURE__ */ new Map();
|
|
231
|
+
for (const f of kernel.iterShapes(parent.wrapped, "face")) for (const v of kernel.iterShapes(f, "vertex")) {
|
|
232
|
+
const hash = kernel.hashCode(v, HASH_CODE_MAX);
|
|
233
|
+
let bucket = vertexToFaces.get(hash);
|
|
234
|
+
if (!bucket) {
|
|
235
|
+
bucket = [];
|
|
236
|
+
vertexToFaces.set(hash, bucket);
|
|
237
|
+
}
|
|
238
|
+
if (!bucket.some((entry) => kernel.isSame(entry.vertex, v) && kernel.isSame(entry.face, f))) bucket.push({
|
|
239
|
+
vertex: v,
|
|
240
|
+
face: f
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
cache.vertexToFaces = vertexToFaces;
|
|
244
|
+
return vertexToFaces;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
223
247
|
* Get all faces adjacent to a given edge within a parent shape.
|
|
224
248
|
*
|
|
225
249
|
* An edge typically borders exactly two faces in a solid, or one face
|
|
@@ -251,6 +275,35 @@ function facesOfEdge(parent, edge) {
|
|
|
251
275
|
return wrapAll(results, "face");
|
|
252
276
|
}
|
|
253
277
|
/**
|
|
278
|
+
* Get all faces meeting at a vertex (≥3 for a solid corner, fewer on a
|
|
279
|
+
* boundary), via the cached vertex→faces map. The vertex equivalent of
|
|
280
|
+
* {@link facesOfEdge}, with the same hash-bucket + isSame verification.
|
|
281
|
+
*
|
|
282
|
+
* @param parent - The parent shape to search within.
|
|
283
|
+
* @param vertex - The vertex whose adjacent faces to find.
|
|
284
|
+
*/
|
|
285
|
+
function facesOfVertex(parent, vertex) {
|
|
286
|
+
const kernel = getKernel();
|
|
287
|
+
const vertexToFaces = getVertexToFacesMap(parent);
|
|
288
|
+
const hash = kernel.hashCode(vertex.wrapped, HASH_CODE_MAX);
|
|
289
|
+
const bucket = vertexToFaces.get(hash) ?? [];
|
|
290
|
+
const results = [];
|
|
291
|
+
const seen = /* @__PURE__ */ new Map();
|
|
292
|
+
for (const entry of bucket) {
|
|
293
|
+
if (!kernel.isSame(entry.vertex, vertex.wrapped)) continue;
|
|
294
|
+
const fHash = kernel.hashCode(entry.face, HASH_CODE_MAX);
|
|
295
|
+
const fBucket = seen.get(fHash);
|
|
296
|
+
if (!fBucket) {
|
|
297
|
+
seen.set(fHash, [entry.face]);
|
|
298
|
+
results.push(entry.face);
|
|
299
|
+
} else if (!fBucket.some((r) => kernel.isSame(r, entry.face))) {
|
|
300
|
+
fBucket.push(entry.face);
|
|
301
|
+
results.push(entry.face);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return wrapAll(results, "face");
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
254
307
|
* Get all edges bounding a face.
|
|
255
308
|
*
|
|
256
309
|
* @param face - The face whose edges to enumerate.
|
|
@@ -260,6 +313,14 @@ function edgesOfFace(face) {
|
|
|
260
313
|
return deduplicatedSubShapes(face.wrapped, "edge");
|
|
261
314
|
}
|
|
262
315
|
/**
|
|
316
|
+
* Get all vertices of a face. The vertex equivalent of {@link edgesOfFace}.
|
|
317
|
+
*
|
|
318
|
+
* @param face - The face whose vertices to enumerate.
|
|
319
|
+
*/
|
|
320
|
+
function verticesOfFace(face) {
|
|
321
|
+
return deduplicatedSubShapes(face.wrapped, "vertex");
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
263
324
|
* Get all wires of a face (outer wire + inner hole wires).
|
|
264
325
|
* All wires bounding a face are closed by definition.
|
|
265
326
|
*
|
|
@@ -1376,4 +1437,4 @@ function fixSelfIntersection(wire) {
|
|
|
1376
1437
|
}
|
|
1377
1438
|
}
|
|
1378
1439
|
//#endregion
|
|
1379
|
-
export { edgesOfFace as A,
|
|
1440
|
+
export { edgesOfFace as A, toLODGeometryData as B, shellWithEvolution as C, getNurbsCurveData as D, fuseAllBisect as E, verticesOfFace as F, toLineGeometryData as H, wiresOfFace as I, chamferDistAngle as L, facesOfVertex as M, sharedEdges as N, getNurbsSurfaceData as O, verticesOfEdge as P, toBufferGeometryData as R, intersectWithEvolution as S, cutAllBisect as T, toLODGeometryLevels as V, positionOnCurve as _, healFace as a, filletWithEvolution as b, isValid as c, draft as d, fillet as f, variableFillet as g, thicken as h, heal as i, facesOfEdge as j, adjacentFaces as k, solidFromShell as l, shell as m, fixSelfIntersection as n, healSolid as o, offset as p, fixShape as r, healWire as s, autoHeal as t, chamfer as u, chamferWithEvolution as v, checkBoolean as w, fuseWithEvolution as x, cutWithEvolution as y, toGroupedBufferGeometryData as z };
|
|
@@ -220,6 +220,30 @@ function getEdgeToFacesMap(parent) {
|
|
|
220
220
|
return edgeToFaces;
|
|
221
221
|
}
|
|
222
222
|
/**
|
|
223
|
+
* Build or retrieve the cached vertex→faces adjacency map for a parent shape —
|
|
224
|
+
* the vertex analogue of {@link getEdgeToFacesMap}.
|
|
225
|
+
*/
|
|
226
|
+
function getVertexToFacesMap(parent) {
|
|
227
|
+
const cache = require_topologyQueryFns.getOrCreateCache(parent);
|
|
228
|
+
if (cache.vertexToFaces) return cache.vertexToFaces;
|
|
229
|
+
const kernel = require_shapeTypes.getKernel();
|
|
230
|
+
const vertexToFaces = /* @__PURE__ */ new Map();
|
|
231
|
+
for (const f of kernel.iterShapes(parent.wrapped, "face")) for (const v of kernel.iterShapes(f, "vertex")) {
|
|
232
|
+
const hash = kernel.hashCode(v, require_constants.HASH_CODE_MAX);
|
|
233
|
+
let bucket = vertexToFaces.get(hash);
|
|
234
|
+
if (!bucket) {
|
|
235
|
+
bucket = [];
|
|
236
|
+
vertexToFaces.set(hash, bucket);
|
|
237
|
+
}
|
|
238
|
+
if (!bucket.some((entry) => kernel.isSame(entry.vertex, v) && kernel.isSame(entry.face, f))) bucket.push({
|
|
239
|
+
vertex: v,
|
|
240
|
+
face: f
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
cache.vertexToFaces = vertexToFaces;
|
|
244
|
+
return vertexToFaces;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
223
247
|
* Get all faces adjacent to a given edge within a parent shape.
|
|
224
248
|
*
|
|
225
249
|
* An edge typically borders exactly two faces in a solid, or one face
|
|
@@ -251,6 +275,35 @@ function facesOfEdge(parent, edge) {
|
|
|
251
275
|
return wrapAll(results, "face");
|
|
252
276
|
}
|
|
253
277
|
/**
|
|
278
|
+
* Get all faces meeting at a vertex (≥3 for a solid corner, fewer on a
|
|
279
|
+
* boundary), via the cached vertex→faces map. The vertex equivalent of
|
|
280
|
+
* {@link facesOfEdge}, with the same hash-bucket + isSame verification.
|
|
281
|
+
*
|
|
282
|
+
* @param parent - The parent shape to search within.
|
|
283
|
+
* @param vertex - The vertex whose adjacent faces to find.
|
|
284
|
+
*/
|
|
285
|
+
function facesOfVertex(parent, vertex) {
|
|
286
|
+
const kernel = require_shapeTypes.getKernel();
|
|
287
|
+
const vertexToFaces = getVertexToFacesMap(parent);
|
|
288
|
+
const hash = kernel.hashCode(vertex.wrapped, require_constants.HASH_CODE_MAX);
|
|
289
|
+
const bucket = vertexToFaces.get(hash) ?? [];
|
|
290
|
+
const results = [];
|
|
291
|
+
const seen = /* @__PURE__ */ new Map();
|
|
292
|
+
for (const entry of bucket) {
|
|
293
|
+
if (!kernel.isSame(entry.vertex, vertex.wrapped)) continue;
|
|
294
|
+
const fHash = kernel.hashCode(entry.face, require_constants.HASH_CODE_MAX);
|
|
295
|
+
const fBucket = seen.get(fHash);
|
|
296
|
+
if (!fBucket) {
|
|
297
|
+
seen.set(fHash, [entry.face]);
|
|
298
|
+
results.push(entry.face);
|
|
299
|
+
} else if (!fBucket.some((r) => kernel.isSame(r, entry.face))) {
|
|
300
|
+
fBucket.push(entry.face);
|
|
301
|
+
results.push(entry.face);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return wrapAll(results, "face");
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
254
307
|
* Get all edges bounding a face.
|
|
255
308
|
*
|
|
256
309
|
* @param face - The face whose edges to enumerate.
|
|
@@ -260,6 +313,14 @@ function edgesOfFace(face) {
|
|
|
260
313
|
return deduplicatedSubShapes(face.wrapped, "edge");
|
|
261
314
|
}
|
|
262
315
|
/**
|
|
316
|
+
* Get all vertices of a face. The vertex equivalent of {@link edgesOfFace}.
|
|
317
|
+
*
|
|
318
|
+
* @param face - The face whose vertices to enumerate.
|
|
319
|
+
*/
|
|
320
|
+
function verticesOfFace(face) {
|
|
321
|
+
return deduplicatedSubShapes(face.wrapped, "vertex");
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
263
324
|
* Get all wires of a face (outer wire + inner hole wires).
|
|
264
325
|
* All wires bounding a face are closed by definition.
|
|
265
326
|
*
|
|
@@ -1442,6 +1503,12 @@ Object.defineProperty(exports, "facesOfEdge", {
|
|
|
1442
1503
|
return facesOfEdge;
|
|
1443
1504
|
}
|
|
1444
1505
|
});
|
|
1506
|
+
Object.defineProperty(exports, "facesOfVertex", {
|
|
1507
|
+
enumerable: true,
|
|
1508
|
+
get: function() {
|
|
1509
|
+
return facesOfVertex;
|
|
1510
|
+
}
|
|
1511
|
+
});
|
|
1445
1512
|
Object.defineProperty(exports, "fillet", {
|
|
1446
1513
|
enumerable: true,
|
|
1447
1514
|
get: function() {
|
|
@@ -1610,6 +1677,12 @@ Object.defineProperty(exports, "verticesOfEdge", {
|
|
|
1610
1677
|
return verticesOfEdge;
|
|
1611
1678
|
}
|
|
1612
1679
|
});
|
|
1680
|
+
Object.defineProperty(exports, "verticesOfFace", {
|
|
1681
|
+
enumerable: true,
|
|
1682
|
+
get: function() {
|
|
1683
|
+
return verticesOfFace;
|
|
1684
|
+
}
|
|
1685
|
+
});
|
|
1613
1686
|
Object.defineProperty(exports, "wiresOfFace", {
|
|
1614
1687
|
enumerable: true,
|
|
1615
1688
|
get: function() {
|
package/dist/index.d.ts
CHANGED
|
@@ -87,7 +87,7 @@ export { tagFaces, findFacesByTag, getFaceTags, setTagMetadata, getTagMetadata,
|
|
|
87
87
|
export { colorFaces, colorShape, getFaceColor, getShapeColor, } from './topology/metadata/colorFns.js';
|
|
88
88
|
export type { Color, ColorInput } from './topology/metadata/colorFns.js';
|
|
89
89
|
export { chamferDistAngle as chamferDistAngleShape } from './topology/chamferAngleFns.js';
|
|
90
|
-
export { facesOfEdge, edgesOfFace, wiresOfFace, verticesOfEdge, adjacentFaces, sharedEdges, } from './topology/adjacencyFns.js';
|
|
90
|
+
export { facesOfEdge, edgesOfFace, wiresOfFace, verticesOfEdge, verticesOfFace, facesOfVertex, adjacentFaces, sharedEdges, } from './topology/adjacencyFns.js';
|
|
91
91
|
export { getCurveType, curveStartPoint, curveEndPoint, curvePointAt, curveTangentAt, curveAxis, curveLength, curveIsClosed, curveIsPeriodic, curvePeriod, getOrientation, flipOrientation, offsetWire2D, interpolateCurve, approximateCurve, type InterpolateCurveOptions, type ApproximateCurveOptions, } from './topology/curveFns.js';
|
|
92
92
|
export { getNurbsCurveData, getNurbsSurfaceData } from './topology/nurbsFns.js';
|
|
93
93
|
export type { NurbsCurveData, NurbsSurfaceData } from './kernel/types.js';
|
|
@@ -102,8 +102,8 @@ export { checkBoolean } from './topology/booleanDiagnosticFns.js';
|
|
|
102
102
|
export type { CheckBooleanResult, BooleanIssue, BooleanOpType, BooleanDiagnostics, } from './kernel/types.js';
|
|
103
103
|
export { fuseWithEvolution, cutWithEvolution, intersectWithEvolution, filletWithEvolution, chamferWithEvolution, shellWithEvolution, type EvolutionResult, } from './topology/evolutionFns.js';
|
|
104
104
|
export type { ShapeEvolution } from './kernel/types.js';
|
|
105
|
-
export { captureHint, assignRoles, createRef, updateRoles, resolveRef, defaultScorer, } from './topology/shapeRef/index.js';
|
|
106
|
-
export type { GeometricHint, ShapeRef, RoleTable, ResolvedRef, BrokenRef, FaceScorer, } from './topology/shapeRef/index.js';
|
|
105
|
+
export { captureHint, assignRoles, createRef, updateRoles, resolveRef, defaultScorer, createEdgeRef, resolveEdgeRef, createVertexRef, resolveVertexRef, } from './topology/shapeRef/index.js';
|
|
106
|
+
export type { GeometricHint, ShapeRef, RoleTable, ResolvedRef, BrokenRef, FaceScorer, EdgeHint, EdgeRef, ResolvedEdgeRef, BrokenEdgeRef, VertexHint, VertexRef, ResolvedVertexRef, BrokenVertexRef, } from './topology/shapeRef/index.js';
|
|
107
107
|
export { surfaceFromGrid, surfaceFromImage, type SurfaceFromGridOptions, type SurfaceFromImageOptions, } from './topology/surfaceFns.js';
|
|
108
108
|
export { hull, type HullOptions } from './topology/hullFns.js';
|
|
109
109
|
export { convexHull } from './operations/convexHullFns.js';
|
|
@@ -10,6 +10,15 @@ import { AnyShape, ClosedWire, Dimension, Edge, Face, Vertex } from '../core/sha
|
|
|
10
10
|
* @returns Array of unique faces containing the given edge.
|
|
11
11
|
*/
|
|
12
12
|
export declare function facesOfEdge<D extends Dimension>(parent: AnyShape<D>, edge: Edge<D>): Face<D>[];
|
|
13
|
+
/**
|
|
14
|
+
* Get all faces meeting at a vertex (≥3 for a solid corner, fewer on a
|
|
15
|
+
* boundary), via the cached vertex→faces map. The vertex equivalent of
|
|
16
|
+
* {@link facesOfEdge}, with the same hash-bucket + isSame verification.
|
|
17
|
+
*
|
|
18
|
+
* @param parent - The parent shape to search within.
|
|
19
|
+
* @param vertex - The vertex whose adjacent faces to find.
|
|
20
|
+
*/
|
|
21
|
+
export declare function facesOfVertex<D extends Dimension>(parent: AnyShape<D>, vertex: Vertex<D>): Face<D>[];
|
|
13
22
|
/**
|
|
14
23
|
* Get all edges bounding a face.
|
|
15
24
|
*
|
|
@@ -17,6 +26,12 @@ export declare function facesOfEdge<D extends Dimension>(parent: AnyShape<D>, ed
|
|
|
17
26
|
* @returns Array of unique edges forming the face boundary.
|
|
18
27
|
*/
|
|
19
28
|
export declare function edgesOfFace<D extends Dimension>(face: Face<D>): Edge<D>[];
|
|
29
|
+
/**
|
|
30
|
+
* Get all vertices of a face. The vertex equivalent of {@link edgesOfFace}.
|
|
31
|
+
*
|
|
32
|
+
* @param face - The face whose vertices to enumerate.
|
|
33
|
+
*/
|
|
34
|
+
export declare function verticesOfFace<D extends Dimension>(face: Face<D>): Vertex<D>[];
|
|
20
35
|
/**
|
|
21
36
|
* Get all wires of a face (outer wire + inner hole wires).
|
|
22
37
|
* All wires bounding a face are closed by definition.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Edge, Shape3D } from '../../core/shapeTypes.js';
|
|
2
|
+
import { EdgeRef, ResolvedEdgeRef, BrokenEdgeRef, RoleTable } from './shapeRefTypes.js';
|
|
3
|
+
/**
|
|
4
|
+
* Capture a lineage-based reference to `edge`: its two adjacent faces' roles
|
|
5
|
+
* plus a geometric hint. Returns undefined when the edge doesn't bound two faces
|
|
6
|
+
* (a boundary/degenerate edge) or when either bounding face has no role yet.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createEdgeRef(origin: string, edge: Edge, shape: Shape3D, roles: RoleTable): EdgeRef | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Resolve an EdgeRef in `shape`: resolve its two face-roles to current faces,
|
|
11
|
+
* then return the edge they share. One shared edge → exact; several (the two
|
|
12
|
+
* faces meet along more than one edge) → disambiguate by hint; none, or a
|
|
13
|
+
* missing bounding face → broken.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveEdgeRef(ref: EdgeRef, roles: RoleTable, shape: Shape3D): ResolvedEdgeRef | BrokenEdgeRef;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ShapeRef — stable, serializable face references for parametric replay.
|
|
3
3
|
*/
|
|
4
|
-
export type { GeometricHint, ShapeRef, RoleTable, ResolvedRef, BrokenRef, } from './shapeRefTypes.js';
|
|
4
|
+
export type { GeometricHint, ShapeRef, RoleTable, ResolvedRef, BrokenRef, EdgeHint, EdgeRef, ResolvedEdgeRef, BrokenEdgeRef, VertexHint, VertexRef, ResolvedVertexRef, BrokenVertexRef, } from './shapeRefTypes.js';
|
|
5
5
|
export { type FaceScorer, defaultScorer } from './scoring.js';
|
|
6
6
|
export { captureHint, assignRoles, createRef, updateRoles, resolveRef } from './shapeRefFns.js';
|
|
7
|
+
export { createEdgeRef, resolveEdgeRef } from './edgeRefFns.js';
|
|
8
|
+
export { createVertexRef, resolveVertexRef } from './vertexRefFns.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Face, Shape3D } from '../../core/shapeTypes.js';
|
|
2
|
+
import { Vec3 } from '../../core/types.js';
|
|
3
|
+
import { RoleTable } from './shapeRefTypes.js';
|
|
4
|
+
/** Euclidean distance between two points. */
|
|
5
|
+
export declare function distance(a: Vec3, b: Vec3): number;
|
|
6
|
+
/** The role whose tracked hashes include this face (reverse lookup). */
|
|
7
|
+
export declare function roleOfFace(face: Face, origin: string, roles: RoleTable): string | undefined;
|
|
8
|
+
/** Current faces a role resolves to — its tracked successors present in `shape`. */
|
|
9
|
+
export declare function facesForRole(shape: Shape3D, origin: string, role: string, roles: RoleTable): Face[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Vec3 } from '../../core/types.js';
|
|
2
2
|
import { SurfaceType } from '../faceFns.js';
|
|
3
|
-
import { Face } from '../../core/shapeTypes.js';
|
|
3
|
+
import { Face, Edge, Vertex } from '../../core/shapeTypes.js';
|
|
4
4
|
/** Geometric snapshot of a face, used for fallback matching when hashes change. */
|
|
5
5
|
export interface GeometricHint {
|
|
6
6
|
readonly entityType: 'face';
|
|
@@ -41,3 +41,66 @@ export interface BrokenRef {
|
|
|
41
41
|
readonly reason: 'deleted' | 'ambiguous' | 'not-found';
|
|
42
42
|
readonly candidates?: readonly Face[];
|
|
43
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Geometric snapshot of an edge — a tiebreaker for the rare case where an edge's
|
|
46
|
+
* two faces share more than one edge.
|
|
47
|
+
*/
|
|
48
|
+
export interface EdgeHint {
|
|
49
|
+
readonly entityType: 'edge';
|
|
50
|
+
readonly length?: number | undefined;
|
|
51
|
+
/** Midpoint of the edge's endpoint vertices. */
|
|
52
|
+
readonly midpoint?: Vec3 | undefined;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* A stable reference to an edge, identified by the roles of its two adjacent
|
|
56
|
+
* faces — its lineage. An edge *is* the intersection of its two faces, so this
|
|
57
|
+
* resolves by finding the edge shared by the current faces of those roles
|
|
58
|
+
* (`sharedEdges`). Identity rides on the already-stable face roles rather than
|
|
59
|
+
* the edge's own hash, so it survives edits that re-hash the edge — and it
|
|
60
|
+
* sidesteps the kernel's unreliable `generated`-face hashes entirely.
|
|
61
|
+
*/
|
|
62
|
+
export interface EdgeRef {
|
|
63
|
+
readonly origin: string;
|
|
64
|
+
/** Roles of the two faces this edge bounds. */
|
|
65
|
+
readonly faceRoles: readonly [string, string];
|
|
66
|
+
readonly hint: EdgeHint;
|
|
67
|
+
}
|
|
68
|
+
/** A successfully resolved edge reference. */
|
|
69
|
+
export interface ResolvedEdgeRef {
|
|
70
|
+
readonly edge: Edge;
|
|
71
|
+
readonly confidence: 'exact' | 'geometric-fallback';
|
|
72
|
+
}
|
|
73
|
+
/** An edge reference that could not be resolved. */
|
|
74
|
+
export interface BrokenEdgeRef {
|
|
75
|
+
readonly ref: EdgeRef;
|
|
76
|
+
readonly reason: 'ambiguous' | 'not-found';
|
|
77
|
+
readonly candidates?: readonly Edge[];
|
|
78
|
+
}
|
|
79
|
+
/** Geometric snapshot of a vertex — a tiebreaker when several candidates survive. */
|
|
80
|
+
export interface VertexHint {
|
|
81
|
+
readonly entityType: 'vertex';
|
|
82
|
+
readonly position?: Vec3 | undefined;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A stable reference to a vertex, identified by the roles of the faces meeting
|
|
86
|
+
* at it. A solid corner is where **≥3** faces meet at a point; two faces meet
|
|
87
|
+
* along an *edge* (two endpoints → ambiguous), so a vertex needs ≥3 face-roles.
|
|
88
|
+
* Resolves by finding the vertex common to those roles' current faces.
|
|
89
|
+
*/
|
|
90
|
+
export interface VertexRef {
|
|
91
|
+
readonly origin: string;
|
|
92
|
+
/** Roles of the ≥3 faces meeting at this vertex (sorted). */
|
|
93
|
+
readonly faceRoles: readonly string[];
|
|
94
|
+
readonly hint: VertexHint;
|
|
95
|
+
}
|
|
96
|
+
/** A successfully resolved vertex reference. */
|
|
97
|
+
export interface ResolvedVertexRef {
|
|
98
|
+
readonly vertex: Vertex;
|
|
99
|
+
readonly confidence: 'exact' | 'geometric-fallback';
|
|
100
|
+
}
|
|
101
|
+
/** A vertex reference that could not be resolved. */
|
|
102
|
+
export interface BrokenVertexRef {
|
|
103
|
+
readonly ref: VertexRef;
|
|
104
|
+
readonly reason: 'ambiguous' | 'not-found';
|
|
105
|
+
readonly candidates?: readonly Vertex[];
|
|
106
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Shape3D, Vertex } from '../../core/shapeTypes.js';
|
|
2
|
+
import { VertexRef, ResolvedVertexRef, BrokenVertexRef, RoleTable } from './shapeRefTypes.js';
|
|
3
|
+
/**
|
|
4
|
+
* Capture a lineage-based reference to `vertex`: the roles of the ≥3 faces
|
|
5
|
+
* meeting at it, plus a position hint. Returns undefined when fewer than three
|
|
6
|
+
* named faces meet there (a 2-face "vertex" is ambiguous — an edge has two).
|
|
7
|
+
*/
|
|
8
|
+
export declare function createVertexRef(origin: string, vertex: Vertex, shape: Shape3D, roles: RoleTable): VertexRef | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Resolve a VertexRef in `shape`: gather the current faces of each role, then
|
|
11
|
+
* return the vertex common to all of them. One common vertex → exact; several →
|
|
12
|
+
* disambiguate by hint position; none, or a missing role → broken.
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveVertexRef(ref: VertexRef, roles: RoleTable, shape: Shape3D): ResolvedVertexRef | BrokenVertexRef;
|
|
@@ -20,6 +20,11 @@ export interface TopoCacheEntry {
|
|
|
20
20
|
edge: KernelShape;
|
|
21
21
|
face: KernelShape;
|
|
22
22
|
}>>;
|
|
23
|
+
/** Vertex hash → vertex-face pairs — the vertex analogue of {@link edgeToFaces}. */
|
|
24
|
+
vertexToFaces?: Map<number, Array<{
|
|
25
|
+
vertex: KernelShape;
|
|
26
|
+
face: KernelShape;
|
|
27
|
+
}>>;
|
|
23
28
|
}
|
|
24
29
|
/** @internal Get or create a cache entry for a shape. Used by originTrackingFns. */
|
|
25
30
|
export declare function getOrCreateCache(shape: AnyShape<Dimension>): TopoCacheEntry;
|
package/dist/topology.cjs
CHANGED
|
@@ -5,7 +5,7 @@ const require_shapeFns = require("./shapeFns-ybo0INGL.cjs");
|
|
|
5
5
|
const require_curveFns = require("./curveFns-DgUJpH4z.cjs");
|
|
6
6
|
const require_meshFns = require("./meshFns-1hQSn1p2.cjs");
|
|
7
7
|
const require_solidBuilders = require("./solidBuilders-DiUv_mD0.cjs");
|
|
8
|
-
const require_healingFns = require("./healingFns-
|
|
8
|
+
const require_healingFns = require("./healingFns-x1sHV-HO.cjs");
|
|
9
9
|
const require_primitiveFns = require("./primitiveFns-DLIWtQWA.cjs");
|
|
10
10
|
exports.addHoles = require_primitiveFns.addHoles;
|
|
11
11
|
exports.adjacentFaces = require_healingFns.adjacentFaces;
|
package/dist/topology.js
CHANGED
|
@@ -4,6 +4,6 @@ import { a as isSameShape, i as isEqualShape, n as getHashCode } from "./shapeFn
|
|
|
4
4
|
import { a as curveIsPeriodic, c as curvePointAt, d as flipOrientation, f as getCurveType, h as offsetWire2D, i as curveIsClosed, l as curveStartPoint, m as interpolateCurve, n as curveAxis, o as curveLength, p as getOrientation, r as curveEndPoint, s as curvePeriod, t as approximateCurve, u as curveTangentAt } from "./curveFns-CcSn4-Rf.js";
|
|
5
5
|
import { d as createMeshCache, n as exportSTEP, r as exportSTL, t as exportIGES, u as clearMeshCache } from "./meshFns-DbmidUzH.js";
|
|
6
6
|
import { h as fuseAll, p as cutAll } from "./solidBuilders-C32wXQWG.js";
|
|
7
|
-
import { A as edgesOfFace,
|
|
7
|
+
import { A as edgesOfFace, C as shellWithEvolution, D as getNurbsCurveData, E as fuseAllBisect, H as toLineGeometryData, I as wiresOfFace, L as chamferDistAngle, N as sharedEdges, O as getNurbsSurfaceData, P as verticesOfEdge, R as toBufferGeometryData, S as intersectWithEvolution, T as cutAllBisect, _ as positionOnCurve, a as healFace, b as filletWithEvolution, g as variableFillet, j as facesOfEdge, k as adjacentFaces, l as solidFromShell, n as fixSelfIntersection, o as healSolid, r as fixShape, s as healWire, t as autoHeal, v as chamferWithEvolution, w as checkBoolean, x as fuseWithEvolution, y as cutWithEvolution, z as toGroupedBufferGeometryData } from "./healingFns-D00TPE9p.js";
|
|
8
8
|
import { C as threePointArc, D as wireLoop, E as wire, S as tangentArc, T as vertex, _ as polygon, a as circle, b as sphere, c as cylinder, d as ellipsoid, f as face, g as offsetFace, h as line, i as bsplineApprox, l as ellipse, m as helix, n as bezier, o as compound, p as filledFace, r as box, s as cone, t as addHoles, u as ellipseArc, v as sewShells, w as torus, x as subFace, y as solid } from "./primitiveFns-CBrOyk5S.js";
|
|
9
9
|
export { addHoles, adjacentFaces, approximateCurve, asTopo, autoHeal, bezier, box, bsplineApprox, cast, chamferDistAngle as chamferDistAngleShape, chamferWithEvolution, checkBoolean, circle, classifyPointOnFace, clearMeshCache, compound, cone, createMeshCache, curveAxis, curveEndPoint, curveIsClosed, curveIsPeriodic, curveLength, curvePeriod, curvePointAt, curveStartPoint, curveTangentAt, cutAll, cutAllBisect, cutWithEvolution, cylinder, fromBREP as deserializeShape, downcast, edgesOfFace, ellipse, ellipseArc, ellipsoid, exportIGES, exportSTEP, exportSTL, face, faceAxis, faceCenter, faceGeomType, faceOrientation, facesOfEdge, filledFace, filletWithEvolution, fixSelfIntersection, fixShape, flipFaceOrientation, flipOrientation, fuseAll, fuseAllBisect, fuseWithEvolution, getBounds, getCurveType, getEdges, getFaces, getHashCode, getNurbsCurveData, getNurbsSurfaceData, getOrientation, getSurfaceType, getVertices, getWires, healFace, healSolid, healWire, helix, innerWires, interpolateCurve, intersectWithEvolution, invalidateShapeCache, isCompSolid, isEqualShape, isSameShape, iterEdges, iterFaces, iterTopo, iterVertices, iterWires, line, normalAt, offsetFace, offsetWire2D, outerWire, pointOnSurface, polygon, positionOnCurve, projectPointOnFace, sewShells, shapeType, sharedEdges, shellWithEvolution, solid, solidFromShell, sphere, subFace, tangentArc, threePointArc, toBufferGeometryData, toGroupedBufferGeometryData, toLineGeometryData, torus, uvBounds, uvCoordinates, variableFillet, vertex, vertexPosition, verticesOfEdge, wire, wireLoop, wiresOfFace };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brepjs",
|
|
3
|
-
"version": "18.
|
|
3
|
+
"version": "18.112.0",
|
|
4
4
|
"description": "Web CAD library with pluggable geometry kernel",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cad",
|
|
@@ -268,7 +268,7 @@
|
|
|
268
268
|
"knip": "6.16.1",
|
|
269
269
|
"lint-staged": "17.0.7",
|
|
270
270
|
"lz-string": "1.5.0",
|
|
271
|
-
"occt-wasm": "3.
|
|
271
|
+
"occt-wasm": "3.6.0",
|
|
272
272
|
"prettier": "3.8.4",
|
|
273
273
|
"puppeteer": "25.1.0",
|
|
274
274
|
"size-limit": "12.1.0",
|
|
@@ -284,7 +284,7 @@
|
|
|
284
284
|
"brepjs-manifold": "^0.1.0",
|
|
285
285
|
"brepjs-opencascade": "^0.5.1 || ^0.6.0 || ^0.7.0 || ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^0.14.0 || ^0.15.0 || ^0.16.0",
|
|
286
286
|
"brepkit-wasm": "^0.10.1 || ^1.0.0 || ^2.0.0",
|
|
287
|
-
"occt-wasm": "^3.
|
|
287
|
+
"occt-wasm": "^3.6.0"
|
|
288
288
|
},
|
|
289
289
|
"peerDependenciesMeta": {
|
|
290
290
|
"brepjs-manifold": {
|