brepjs 18.109.0 → 18.111.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 +153 -1
- package/dist/brepjs.js +152 -2
- package/dist/index.d.ts +2 -2
- package/dist/shapeRef.cjs +1 -1
- package/dist/shapeRef.js +1 -1
- package/dist/{shapeRefFns-C1DefNzr.js → shapeRefFns-ChMnsOAF.js} +97 -45
- package/dist/{shapeRefFns--2FPCL7P.cjs → shapeRefFns-CuepnFOm.cjs} +97 -45
- package/dist/topology/shapeRef/edgeRefFns.d.ts +15 -0
- package/dist/topology/shapeRef/index.d.ts +2 -1
- package/dist/topology/shapeRef/shapeRefFns.d.ts +19 -13
- package/dist/topology/shapeRef/shapeRefTypes.d.ts +42 -3
- package/package.json +3 -3
package/dist/brepjs.cjs
CHANGED
|
@@ -29,7 +29,7 @@ const require_importFns = require("./importFns-CgMQIi0z.cjs");
|
|
|
29
29
|
const require_loftFns = require("./loftFns-fpTmrIdd.cjs");
|
|
30
30
|
const require_cameraFns = require("./cameraFns-uo1sZbBT.cjs");
|
|
31
31
|
const require_textMetrics = require("./textMetrics-IC_IoI7l.cjs");
|
|
32
|
-
const require_shapeRefFns = require("./shapeRefFns
|
|
32
|
+
const require_shapeRefFns = require("./shapeRefFns-CuepnFOm.cjs");
|
|
33
33
|
const require_workerPool = require("./workerPool-D30NsiIW.cjs");
|
|
34
34
|
const require_primitiveFns = require("./primitiveFns-DLIWtQWA.cjs");
|
|
35
35
|
//#region src/topology/shapeBooleans.ts
|
|
@@ -1175,6 +1175,156 @@ function withKernelDir(v, fn) {
|
|
|
1175
1175
|
}
|
|
1176
1176
|
}
|
|
1177
1177
|
//#endregion
|
|
1178
|
+
//#region src/topology/shapeRef/edgeRefFns.ts
|
|
1179
|
+
/** Midpoint of an edge's endpoint vertices (a closed edge collapses to one). */
|
|
1180
|
+
function endpointMidpoint(verts) {
|
|
1181
|
+
if (verts.length === 0) return void 0;
|
|
1182
|
+
let x = 0;
|
|
1183
|
+
let y = 0;
|
|
1184
|
+
let z = 0;
|
|
1185
|
+
for (const v of verts) {
|
|
1186
|
+
const p = require_topologyQueryFns.vertexPosition(v);
|
|
1187
|
+
x += p[0];
|
|
1188
|
+
y += p[1];
|
|
1189
|
+
z += p[2];
|
|
1190
|
+
}
|
|
1191
|
+
const n = verts.length;
|
|
1192
|
+
return [
|
|
1193
|
+
x / n,
|
|
1194
|
+
y / n,
|
|
1195
|
+
z / n
|
|
1196
|
+
];
|
|
1197
|
+
}
|
|
1198
|
+
function distance(a, b) {
|
|
1199
|
+
const dx = a[0] - b[0];
|
|
1200
|
+
const dy = a[1] - b[1];
|
|
1201
|
+
const dz = a[2] - b[2];
|
|
1202
|
+
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
1203
|
+
}
|
|
1204
|
+
function captureEdgeHint(edge) {
|
|
1205
|
+
const lengthResult = require_measureFns.measureLength(edge);
|
|
1206
|
+
return {
|
|
1207
|
+
entityType: "edge",
|
|
1208
|
+
length: lengthResult.ok ? lengthResult.value : void 0,
|
|
1209
|
+
midpoint: endpointMidpoint(require_healingFns.verticesOfEdge(edge))
|
|
1210
|
+
};
|
|
1211
|
+
}
|
|
1212
|
+
/** Reverse the role table: the role whose tracked hashes include this face. */
|
|
1213
|
+
function roleOfFace(face, origin, roles) {
|
|
1214
|
+
const originRoles = roles.get(origin);
|
|
1215
|
+
if (!originRoles) return void 0;
|
|
1216
|
+
const hash = require_shapeFns.getHashCode(face);
|
|
1217
|
+
for (const [role, hashes] of originRoles) if (hashes.includes(hash)) return role;
|
|
1218
|
+
}
|
|
1219
|
+
/** Current faces a role resolves to (its tracked successors present in `shape`). */
|
|
1220
|
+
function facesForRole(shape, origin, role, roles) {
|
|
1221
|
+
const hashes = roles.get(origin)?.get(role);
|
|
1222
|
+
if (hashes === void 0 || hashes.length === 0) return [];
|
|
1223
|
+
return require_topologyQueryFns.getFaces(shape).filter((f) => hashes.includes(require_shapeFns.getHashCode(f)));
|
|
1224
|
+
}
|
|
1225
|
+
function dedupeEdges(edges) {
|
|
1226
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1227
|
+
const out = [];
|
|
1228
|
+
for (const e of edges) {
|
|
1229
|
+
const h = require_shapeFns.getHashCode(e);
|
|
1230
|
+
if (!seen.has(h)) {
|
|
1231
|
+
seen.add(h);
|
|
1232
|
+
out.push(e);
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
return out;
|
|
1236
|
+
}
|
|
1237
|
+
/** Hint scores closer than this are treated as indistinguishable (→ ambiguous). */
|
|
1238
|
+
var HINT_MARGIN = 1e-6;
|
|
1239
|
+
/**
|
|
1240
|
+
* Pick the candidate edge closest to the hint (length + endpoint midpoint).
|
|
1241
|
+
* Returns undefined when it genuinely can't discriminate — the hint carries no
|
|
1242
|
+
* signal, or the two best candidates score within {@link HINT_MARGIN} — so the
|
|
1243
|
+
* caller can report `ambiguous` rather than committing to an arbitrary edge.
|
|
1244
|
+
*/
|
|
1245
|
+
function bestByHint(candidates, hint) {
|
|
1246
|
+
if (hint.length === void 0 && hint.midpoint === void 0) return void 0;
|
|
1247
|
+
let best;
|
|
1248
|
+
let bestScore = Infinity;
|
|
1249
|
+
let secondScore = Infinity;
|
|
1250
|
+
for (const edge of candidates) {
|
|
1251
|
+
let score = 0;
|
|
1252
|
+
if (hint.length !== void 0) {
|
|
1253
|
+
const len = require_measureFns.measureLength(edge);
|
|
1254
|
+
if (len.ok) score += Math.abs(len.value - hint.length);
|
|
1255
|
+
}
|
|
1256
|
+
if (hint.midpoint !== void 0) {
|
|
1257
|
+
const mid = endpointMidpoint(require_healingFns.verticesOfEdge(edge));
|
|
1258
|
+
if (mid !== void 0) score += distance(hint.midpoint, mid);
|
|
1259
|
+
}
|
|
1260
|
+
if (score < bestScore) {
|
|
1261
|
+
secondScore = bestScore;
|
|
1262
|
+
bestScore = score;
|
|
1263
|
+
best = edge;
|
|
1264
|
+
} else if (score < secondScore) secondScore = score;
|
|
1265
|
+
}
|
|
1266
|
+
if (best === void 0 || secondScore - bestScore < HINT_MARGIN) return void 0;
|
|
1267
|
+
return best;
|
|
1268
|
+
}
|
|
1269
|
+
/**
|
|
1270
|
+
* Capture a lineage-based reference to `edge`: its two adjacent faces' roles
|
|
1271
|
+
* plus a geometric hint. Returns undefined when the edge doesn't bound two faces
|
|
1272
|
+
* (a boundary/degenerate edge) or when either bounding face has no role yet.
|
|
1273
|
+
*/
|
|
1274
|
+
function createEdgeRef(origin, edge, shape, roles) {
|
|
1275
|
+
const [faceA, faceB] = require_healingFns.facesOfEdge(shape, edge);
|
|
1276
|
+
if (faceA === void 0 || faceB === void 0) return void 0;
|
|
1277
|
+
const roleA = roleOfFace(faceA, origin, roles);
|
|
1278
|
+
const roleB = roleOfFace(faceB, origin, roles);
|
|
1279
|
+
if (roleA === void 0 || roleB === void 0) return void 0;
|
|
1280
|
+
return {
|
|
1281
|
+
origin,
|
|
1282
|
+
faceRoles: [roleA, roleB],
|
|
1283
|
+
hint: captureEdgeHint(edge)
|
|
1284
|
+
};
|
|
1285
|
+
}
|
|
1286
|
+
/**
|
|
1287
|
+
* Resolve an EdgeRef in `shape`: resolve its two face-roles to current faces,
|
|
1288
|
+
* then return the edge they share. One shared edge → exact; several (the two
|
|
1289
|
+
* faces meet along more than one edge) → disambiguate by hint; none, or a
|
|
1290
|
+
* missing bounding face → broken.
|
|
1291
|
+
*/
|
|
1292
|
+
function resolveEdgeRef(ref, roles, shape) {
|
|
1293
|
+
const [roleA, roleB] = ref.faceRoles;
|
|
1294
|
+
const facesA = facesForRole(shape, ref.origin, roleA, roles);
|
|
1295
|
+
const facesB = facesForRole(shape, ref.origin, roleB, roles);
|
|
1296
|
+
if (facesA.length === 0 || facesB.length === 0) return {
|
|
1297
|
+
ref,
|
|
1298
|
+
reason: "not-found"
|
|
1299
|
+
};
|
|
1300
|
+
const candidates = [];
|
|
1301
|
+
for (const a of facesA) for (const b of facesB) candidates.push(...require_healingFns.sharedEdges(a, b));
|
|
1302
|
+
const unique = dedupeEdges(candidates);
|
|
1303
|
+
if (unique.length === 1) {
|
|
1304
|
+
const [only] = unique;
|
|
1305
|
+
if (only !== void 0) return {
|
|
1306
|
+
edge: only,
|
|
1307
|
+
confidence: "exact"
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1310
|
+
if (unique.length > 1) {
|
|
1311
|
+
const best = bestByHint(unique, ref.hint);
|
|
1312
|
+
if (best !== void 0) return {
|
|
1313
|
+
edge: best,
|
|
1314
|
+
confidence: "geometric-fallback"
|
|
1315
|
+
};
|
|
1316
|
+
return {
|
|
1317
|
+
ref,
|
|
1318
|
+
reason: "ambiguous",
|
|
1319
|
+
candidates: unique
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1322
|
+
return {
|
|
1323
|
+
ref,
|
|
1324
|
+
reason: "not-found"
|
|
1325
|
+
};
|
|
1326
|
+
}
|
|
1327
|
+
//#endregion
|
|
1178
1328
|
//#region src/topology/surfaceFns.ts
|
|
1179
1329
|
/**
|
|
1180
1330
|
* Surface creation functions — generate faces from height-map grids.
|
|
@@ -6880,6 +7030,7 @@ exports.createCompound = require_shapeTypes.createCompound;
|
|
|
6880
7030
|
exports.createCompoundBlueprint = require_blueprintFns.createCompoundBlueprint;
|
|
6881
7031
|
exports.createDistanceQuery = require_measureFns.createDistanceQuery;
|
|
6882
7032
|
exports.createEdge = require_shapeTypes.createEdge;
|
|
7033
|
+
exports.createEdgeRef = createEdgeRef;
|
|
6883
7034
|
exports.createFace = require_shapeTypes.createFace;
|
|
6884
7035
|
exports.createHandle = require_shapeTypes.createHandle;
|
|
6885
7036
|
exports.createHistory = require_threadFns.createHistory;
|
|
@@ -7267,6 +7418,7 @@ exports.resize = require_shapeFns.resize;
|
|
|
7267
7418
|
exports.resolve = resolve;
|
|
7268
7419
|
exports.resolve3D = resolve3D;
|
|
7269
7420
|
exports.resolveDirection = require_types.resolveDirection;
|
|
7421
|
+
exports.resolveEdgeRef = resolveEdgeRef;
|
|
7270
7422
|
exports.resolvePlane = require_planeOps.resolvePlane;
|
|
7271
7423
|
exports.resolveRef = require_shapeRefFns.resolveRef;
|
|
7272
7424
|
exports.reverseCurve = require_blueprintFns.reverseCurve;
|
package/dist/brepjs.js
CHANGED
|
@@ -28,7 +28,7 @@ import { a as revolve$1, c as multiSectionSweep, d as twistExtrude, i as extrude
|
|
|
28
28
|
import { a as Sketch, c as compoundSketchLoft, d as sketchFace, f as sketchLoft, h as sketchWires, i as Sketches, l as compoundSketchRevolve, m as sketchSweep, n as getFont, o as compoundSketchExtrude, p as sketchRevolve, r as loadFont, s as compoundSketchFace, t as textBlueprints, u as sketchExtrude, v as CompoundSketch } from "./textBlueprints-BnkWAqwS.js";
|
|
29
29
|
import { a as makeProjectedEdges, i as projectEdges, n as cameraLookAt, r as createCamera, s as isProjectionPlane, t as cameraFromPlane } from "./cameraFns-bk9e0F-T.js";
|
|
30
30
|
import { n as textMetrics, r as sketchText, t as fontMetrics } from "./textMetrics-COGYk0LE.js";
|
|
31
|
-
import { a as updateRoles, i as resolveRef, n as captureHint, o as defaultScorer, r as createRef, t as assignRoles } from "./shapeRefFns-
|
|
31
|
+
import { a as updateRoles, i as resolveRef, n as captureHint, o as defaultScorer, r as createRef, t as assignRoles } from "./shapeRefFns-ChMnsOAF.js";
|
|
32
32
|
import { _ as isSuccessResponse, a as createWorkerClient, c as enqueueTask, d as rejectAll, f as isBatchRequest, g as isOperationRequest, h as isInitRequest, i as registerHandler, l as isEmpty$1, m as isErrorResponse, n as createOperationRegistry, o as createTaskQueue, p as isDisposeRequest, r as createWorkerHandler, s as dequeueTask, t as createWorkerPool, u as pendingCount } from "./workerPool-XcYX2UZ0.js";
|
|
33
33
|
import { C as threePointArc, D as wireLoop, E as wire, S as tangentArc, T as vertex, _ as polygon, a as circle, b as sphere$1, 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$1, x as subFace, y as solid } from "./primitiveFns-CBrOyk5S.js";
|
|
34
34
|
//#region \0rolldown/runtime.js
|
|
@@ -1186,6 +1186,156 @@ function withKernelDir(v, fn) {
|
|
|
1186
1186
|
}
|
|
1187
1187
|
}
|
|
1188
1188
|
//#endregion
|
|
1189
|
+
//#region src/topology/shapeRef/edgeRefFns.ts
|
|
1190
|
+
/** Midpoint of an edge's endpoint vertices (a closed edge collapses to one). */
|
|
1191
|
+
function endpointMidpoint(verts) {
|
|
1192
|
+
if (verts.length === 0) return void 0;
|
|
1193
|
+
let x = 0;
|
|
1194
|
+
let y = 0;
|
|
1195
|
+
let z = 0;
|
|
1196
|
+
for (const v of verts) {
|
|
1197
|
+
const p = vertexPosition(v);
|
|
1198
|
+
x += p[0];
|
|
1199
|
+
y += p[1];
|
|
1200
|
+
z += p[2];
|
|
1201
|
+
}
|
|
1202
|
+
const n = verts.length;
|
|
1203
|
+
return [
|
|
1204
|
+
x / n,
|
|
1205
|
+
y / n,
|
|
1206
|
+
z / n
|
|
1207
|
+
];
|
|
1208
|
+
}
|
|
1209
|
+
function distance(a, b) {
|
|
1210
|
+
const dx = a[0] - b[0];
|
|
1211
|
+
const dy = a[1] - b[1];
|
|
1212
|
+
const dz = a[2] - b[2];
|
|
1213
|
+
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
1214
|
+
}
|
|
1215
|
+
function captureEdgeHint(edge) {
|
|
1216
|
+
const lengthResult = measureLength(edge);
|
|
1217
|
+
return {
|
|
1218
|
+
entityType: "edge",
|
|
1219
|
+
length: lengthResult.ok ? lengthResult.value : void 0,
|
|
1220
|
+
midpoint: endpointMidpoint(verticesOfEdge(edge))
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1223
|
+
/** Reverse the role table: the role whose tracked hashes include this face. */
|
|
1224
|
+
function roleOfFace(face, origin, roles) {
|
|
1225
|
+
const originRoles = roles.get(origin);
|
|
1226
|
+
if (!originRoles) return void 0;
|
|
1227
|
+
const hash = getHashCode(face);
|
|
1228
|
+
for (const [role, hashes] of originRoles) if (hashes.includes(hash)) return role;
|
|
1229
|
+
}
|
|
1230
|
+
/** Current faces a role resolves to (its tracked successors present in `shape`). */
|
|
1231
|
+
function facesForRole(shape, origin, role, roles) {
|
|
1232
|
+
const hashes = roles.get(origin)?.get(role);
|
|
1233
|
+
if (hashes === void 0 || hashes.length === 0) return [];
|
|
1234
|
+
return getFaces(shape).filter((f) => hashes.includes(getHashCode(f)));
|
|
1235
|
+
}
|
|
1236
|
+
function dedupeEdges(edges) {
|
|
1237
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1238
|
+
const out = [];
|
|
1239
|
+
for (const e of edges) {
|
|
1240
|
+
const h = getHashCode(e);
|
|
1241
|
+
if (!seen.has(h)) {
|
|
1242
|
+
seen.add(h);
|
|
1243
|
+
out.push(e);
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
return out;
|
|
1247
|
+
}
|
|
1248
|
+
/** Hint scores closer than this are treated as indistinguishable (→ ambiguous). */
|
|
1249
|
+
var HINT_MARGIN = 1e-6;
|
|
1250
|
+
/**
|
|
1251
|
+
* Pick the candidate edge closest to the hint (length + endpoint midpoint).
|
|
1252
|
+
* Returns undefined when it genuinely can't discriminate — the hint carries no
|
|
1253
|
+
* signal, or the two best candidates score within {@link HINT_MARGIN} — so the
|
|
1254
|
+
* caller can report `ambiguous` rather than committing to an arbitrary edge.
|
|
1255
|
+
*/
|
|
1256
|
+
function bestByHint(candidates, hint) {
|
|
1257
|
+
if (hint.length === void 0 && hint.midpoint === void 0) return void 0;
|
|
1258
|
+
let best;
|
|
1259
|
+
let bestScore = Infinity;
|
|
1260
|
+
let secondScore = Infinity;
|
|
1261
|
+
for (const edge of candidates) {
|
|
1262
|
+
let score = 0;
|
|
1263
|
+
if (hint.length !== void 0) {
|
|
1264
|
+
const len = measureLength(edge);
|
|
1265
|
+
if (len.ok) score += Math.abs(len.value - hint.length);
|
|
1266
|
+
}
|
|
1267
|
+
if (hint.midpoint !== void 0) {
|
|
1268
|
+
const mid = endpointMidpoint(verticesOfEdge(edge));
|
|
1269
|
+
if (mid !== void 0) score += distance(hint.midpoint, mid);
|
|
1270
|
+
}
|
|
1271
|
+
if (score < bestScore) {
|
|
1272
|
+
secondScore = bestScore;
|
|
1273
|
+
bestScore = score;
|
|
1274
|
+
best = edge;
|
|
1275
|
+
} else if (score < secondScore) secondScore = score;
|
|
1276
|
+
}
|
|
1277
|
+
if (best === void 0 || secondScore - bestScore < HINT_MARGIN) return void 0;
|
|
1278
|
+
return best;
|
|
1279
|
+
}
|
|
1280
|
+
/**
|
|
1281
|
+
* Capture a lineage-based reference to `edge`: its two adjacent faces' roles
|
|
1282
|
+
* plus a geometric hint. Returns undefined when the edge doesn't bound two faces
|
|
1283
|
+
* (a boundary/degenerate edge) or when either bounding face has no role yet.
|
|
1284
|
+
*/
|
|
1285
|
+
function createEdgeRef(origin, edge, shape, roles) {
|
|
1286
|
+
const [faceA, faceB] = facesOfEdge(shape, edge);
|
|
1287
|
+
if (faceA === void 0 || faceB === void 0) return void 0;
|
|
1288
|
+
const roleA = roleOfFace(faceA, origin, roles);
|
|
1289
|
+
const roleB = roleOfFace(faceB, origin, roles);
|
|
1290
|
+
if (roleA === void 0 || roleB === void 0) return void 0;
|
|
1291
|
+
return {
|
|
1292
|
+
origin,
|
|
1293
|
+
faceRoles: [roleA, roleB],
|
|
1294
|
+
hint: captureEdgeHint(edge)
|
|
1295
|
+
};
|
|
1296
|
+
}
|
|
1297
|
+
/**
|
|
1298
|
+
* Resolve an EdgeRef in `shape`: resolve its two face-roles to current faces,
|
|
1299
|
+
* then return the edge they share. One shared edge → exact; several (the two
|
|
1300
|
+
* faces meet along more than one edge) → disambiguate by hint; none, or a
|
|
1301
|
+
* missing bounding face → broken.
|
|
1302
|
+
*/
|
|
1303
|
+
function resolveEdgeRef(ref, roles, shape) {
|
|
1304
|
+
const [roleA, roleB] = ref.faceRoles;
|
|
1305
|
+
const facesA = facesForRole(shape, ref.origin, roleA, roles);
|
|
1306
|
+
const facesB = facesForRole(shape, ref.origin, roleB, roles);
|
|
1307
|
+
if (facesA.length === 0 || facesB.length === 0) return {
|
|
1308
|
+
ref,
|
|
1309
|
+
reason: "not-found"
|
|
1310
|
+
};
|
|
1311
|
+
const candidates = [];
|
|
1312
|
+
for (const a of facesA) for (const b of facesB) candidates.push(...sharedEdges(a, b));
|
|
1313
|
+
const unique = dedupeEdges(candidates);
|
|
1314
|
+
if (unique.length === 1) {
|
|
1315
|
+
const [only] = unique;
|
|
1316
|
+
if (only !== void 0) return {
|
|
1317
|
+
edge: only,
|
|
1318
|
+
confidence: "exact"
|
|
1319
|
+
};
|
|
1320
|
+
}
|
|
1321
|
+
if (unique.length > 1) {
|
|
1322
|
+
const best = bestByHint(unique, ref.hint);
|
|
1323
|
+
if (best !== void 0) return {
|
|
1324
|
+
edge: best,
|
|
1325
|
+
confidence: "geometric-fallback"
|
|
1326
|
+
};
|
|
1327
|
+
return {
|
|
1328
|
+
ref,
|
|
1329
|
+
reason: "ambiguous",
|
|
1330
|
+
candidates: unique
|
|
1331
|
+
};
|
|
1332
|
+
}
|
|
1333
|
+
return {
|
|
1334
|
+
ref,
|
|
1335
|
+
reason: "not-found"
|
|
1336
|
+
};
|
|
1337
|
+
}
|
|
1338
|
+
//#endregion
|
|
1189
1339
|
//#region src/topology/surfaceFns.ts
|
|
1190
1340
|
/**
|
|
1191
1341
|
* Surface creation functions — generate faces from height-map grids.
|
|
@@ -6786,4 +6936,4 @@ var csg_exports = /* @__PURE__ */ __exportAll({
|
|
|
6786
6936
|
withEvaluator: () => withEvaluator
|
|
6787
6937
|
});
|
|
6788
6938
|
//#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 };
|
|
6939
|
+
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, 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, resolveEdgeRef, 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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -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, } from './topology/shapeRef/index.js';
|
|
106
|
+
export type { GeometricHint, ShapeRef, RoleTable, ResolvedRef, BrokenRef, FaceScorer, EdgeHint, EdgeRef, ResolvedEdgeRef, BrokenEdgeRef, } 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';
|
package/dist/shapeRef.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_shapeRefFns = require("./shapeRefFns
|
|
2
|
+
const require_shapeRefFns = require("./shapeRefFns-CuepnFOm.cjs");
|
|
3
3
|
exports.assignRoles = require_shapeRefFns.assignRoles;
|
|
4
4
|
exports.captureHint = require_shapeRefFns.captureHint;
|
|
5
5
|
exports.createRef = require_shapeRefFns.createRef;
|
package/dist/shapeRef.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as updateRoles, i as resolveRef, n as captureHint, o as defaultScorer, r as createRef, t as assignRoles } from "./shapeRefFns-
|
|
1
|
+
import { a as updateRoles, i as resolveRef, n as captureHint, o as defaultScorer, r as createRef, t as assignRoles } from "./shapeRefFns-ChMnsOAF.js";
|
|
2
2
|
export { assignRoles, captureHint, createRef, defaultScorer, resolveRef, updateRoles };
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { n as wasmIndex } from "./vec3-Dpha8d5k.js";
|
|
2
1
|
import { c as getFaces } from "./topologyQueryFns-BeKaWpNm.js";
|
|
3
2
|
import { i as faceGeomType, l as normalAt, r as faceCenter } from "./faceFns-B86WGqDg.js";
|
|
4
3
|
import { n as getHashCode } from "./shapeFns-DrZOVwHX.js";
|
|
@@ -81,7 +80,8 @@ function boxRoleFromNormal(n) {
|
|
|
81
80
|
*
|
|
82
81
|
* For other types: sequential naming ('opType:face_0', 'opType:face_1', ...).
|
|
83
82
|
*
|
|
84
|
-
* @returns Map from role name to face hash
|
|
83
|
+
* @returns Map from role name to its face hash codes (one at assignment time;
|
|
84
|
+
* a role accrues more hashes only later, when `updateRoles` tracks a split).
|
|
85
85
|
*/
|
|
86
86
|
function assignRoles(shape, operationType) {
|
|
87
87
|
const faces = getFaces(shape);
|
|
@@ -89,13 +89,13 @@ function assignRoles(shape, operationType) {
|
|
|
89
89
|
if (operationType === "box") {
|
|
90
90
|
for (const face of faces) {
|
|
91
91
|
const role = boxRoleFromNormal(normalAt(face));
|
|
92
|
-
if (role !== void 0 && !roles.has(role)) roles.set(role, getHashCode(face));
|
|
92
|
+
if (role !== void 0 && !roles.has(role)) roles.set(role, [getHashCode(face)]);
|
|
93
93
|
}
|
|
94
94
|
return roles;
|
|
95
95
|
}
|
|
96
96
|
let index = 0;
|
|
97
97
|
for (const face of faces) {
|
|
98
|
-
roles.set(`${operationType}:face_${index}`, getHashCode(face));
|
|
98
|
+
roles.set(`${operationType}:face_${index}`, [getHashCode(face)]);
|
|
99
99
|
index++;
|
|
100
100
|
}
|
|
101
101
|
return roles;
|
|
@@ -109,31 +109,47 @@ function createRef(origin, role, face) {
|
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
111
|
/**
|
|
112
|
+
* Advance a role's face hashes through one evolution: drop deleted faces,
|
|
113
|
+
* replace a modified face with *all* its successors (a 1→many split keeps every
|
|
114
|
+
* fragment), and keep unchanged faces. Deduped so a shared successor isn't
|
|
115
|
+
* doubled.
|
|
116
|
+
*/
|
|
117
|
+
function nextHashes(hashes, evolution) {
|
|
118
|
+
const successors = [];
|
|
119
|
+
for (const hash of hashes) {
|
|
120
|
+
if (evolution.deleted.has(hash)) continue;
|
|
121
|
+
const modified = evolution.modified.get(hash);
|
|
122
|
+
const targets = modified && modified.length > 0 ? modified : [hash];
|
|
123
|
+
for (const h of targets) if (!successors.includes(h)) successors.push(h);
|
|
124
|
+
}
|
|
125
|
+
return successors;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
112
128
|
* Propagate a role table through a ShapeEvolution record.
|
|
113
129
|
* Returns a new RoleTable with hashes updated according to the evolution.
|
|
114
130
|
*
|
|
115
|
-
* - Deleted faces: role removed
|
|
116
|
-
* - Modified faces: hash
|
|
117
|
-
*
|
|
131
|
+
* - Deleted faces: hash dropped (role removed once all its hashes are gone).
|
|
132
|
+
* - Modified faces: hash replaced by **all** successor hashes — so a 1→many
|
|
133
|
+
* split keeps every fragment, and `resolveRef` disambiguates among them.
|
|
134
|
+
* - Unchanged faces: hash preserved.
|
|
118
135
|
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
136
|
+
* Note: `evolution.generated` is intentionally not consumed here — on the OCCT
|
|
137
|
+
* kernels its hashes refer to an intermediate shape, not the final result, so
|
|
138
|
+
* naming generated faces produces roles that never resolve (verified: 0 live
|
|
139
|
+
* generated hashes across cut/fuse on occt-wasm). Stable names for generated
|
|
140
|
+
* geometry (fillet rounds, boolean seams) need history-fidelity work tracked
|
|
141
|
+
* separately.
|
|
123
142
|
*/
|
|
124
143
|
function updateRoles(roles, origin, evolution) {
|
|
125
144
|
const originRoles = roles.get(origin);
|
|
126
145
|
if (!originRoles) return roles;
|
|
127
146
|
const updatedOriginRoles = /* @__PURE__ */ new Map();
|
|
128
|
-
for (const [role,
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if (modifiedHashes && modifiedHashes.length > 0) updatedOriginRoles.set(role, wasmIndex(modifiedHashes, 0));
|
|
132
|
-
else updatedOriginRoles.set(role, hash);
|
|
147
|
+
for (const [role, hashes] of originRoles) {
|
|
148
|
+
const successors = nextHashes(hashes, evolution);
|
|
149
|
+
if (successors.length > 0) updatedOriginRoles.set(role, successors);
|
|
133
150
|
}
|
|
134
151
|
const newRoles = /* @__PURE__ */ new Map();
|
|
135
|
-
for (const [key, value] of roles)
|
|
136
|
-
else newRoles.set(key, value);
|
|
152
|
+
for (const [key, value] of roles) newRoles.set(key, key === origin ? updatedOriginRoles : value);
|
|
137
153
|
return newRoles;
|
|
138
154
|
}
|
|
139
155
|
/** Ambiguity threshold: if two scores are within this range, it's ambiguous. */
|
|
@@ -141,34 +157,19 @@ var AMBIGUITY_THRESHOLD = .1;
|
|
|
141
157
|
/** Minimum score for geometric fallback to accept a match. */
|
|
142
158
|
var MIN_SCORE = .5;
|
|
143
159
|
/**
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
* 3. Ambiguous if multiple faces score within threshold
|
|
150
|
-
* 4. Not-found if no match above minimum score
|
|
160
|
+
* Score `candidates` against `hint`, returning the best match, a tie within
|
|
161
|
+
* {@link AMBIGUITY_THRESHOLD}, or nothing above {@link MIN_SCORE}. Scoping the
|
|
162
|
+
* candidates to a role's tracked successors (rather than every face) is what
|
|
163
|
+
* makes split-face disambiguation reliable — the fragments compete only with
|
|
164
|
+
* each other, not with unrelated geometry.
|
|
151
165
|
*/
|
|
152
|
-
function
|
|
153
|
-
const faces = getFaces(currentShape);
|
|
154
|
-
const scoreFn = scorer ?? defaultScorer;
|
|
155
|
-
const targetHash = roles.get(ref.origin)?.get(ref.role);
|
|
156
|
-
if (targetHash !== void 0) {
|
|
157
|
-
for (const face of faces) if (getHashCode(face) === targetHash) return {
|
|
158
|
-
face,
|
|
159
|
-
confidence: "exact"
|
|
160
|
-
};
|
|
161
|
-
return {
|
|
162
|
-
ref,
|
|
163
|
-
reason: "deleted"
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
+
function scoreFaces(hint, candidates, scoreFn) {
|
|
166
167
|
let bestScore = -Infinity;
|
|
167
168
|
let bestFace;
|
|
168
169
|
let secondBestScore = -Infinity;
|
|
169
170
|
const scored = [];
|
|
170
|
-
for (const face of
|
|
171
|
-
const score = scoreFn(
|
|
171
|
+
for (const face of candidates) {
|
|
172
|
+
const score = scoreFn(hint, face);
|
|
172
173
|
if (score > MIN_SCORE) scored.push([face, score]);
|
|
173
174
|
if (score > bestScore) {
|
|
174
175
|
secondBestScore = bestScore;
|
|
@@ -178,15 +179,66 @@ function resolveRef(ref, roles, currentShape, scorer) {
|
|
|
178
179
|
}
|
|
179
180
|
if (bestFace !== void 0 && bestScore > MIN_SCORE) {
|
|
180
181
|
if (bestScore - secondBestScore < AMBIGUITY_THRESHOLD && scored.length > 1) return {
|
|
181
|
-
|
|
182
|
-
reason: "ambiguous",
|
|
182
|
+
kind: "ambiguous",
|
|
183
183
|
candidates: scored.filter(([, s]) => s >= bestScore - AMBIGUITY_THRESHOLD).map(([f]) => f)
|
|
184
184
|
};
|
|
185
185
|
return {
|
|
186
|
-
|
|
187
|
-
|
|
186
|
+
kind: "match",
|
|
187
|
+
face: bestFace
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
return { kind: "none" };
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Resolve a ShapeRef to a face in the current shape.
|
|
194
|
+
*
|
|
195
|
+
* Resolution strategy:
|
|
196
|
+
* 1. Exact: the role's tracked successor hashes. One survivor → exact match;
|
|
197
|
+
* several survivors (a face that split) → disambiguate among *only those*
|
|
198
|
+
* fragments; none survive → deleted.
|
|
199
|
+
* 2. Geometric fallback over the whole shape when the role isn't tracked (or a
|
|
200
|
+
* scoped score turned up nothing): best-scoring face, else ambiguous /
|
|
201
|
+
* not-found.
|
|
202
|
+
*/
|
|
203
|
+
function resolveRef(ref, roles, currentShape, scorer) {
|
|
204
|
+
const faces = getFaces(currentShape);
|
|
205
|
+
const scoreFn = scorer ?? defaultScorer;
|
|
206
|
+
const targetHashes = roles.get(ref.origin)?.get(ref.role);
|
|
207
|
+
if (targetHashes !== void 0 && targetHashes.length > 0) {
|
|
208
|
+
const survivors = faces.filter((f) => targetHashes.includes(getHashCode(f)));
|
|
209
|
+
if (survivors.length === 1) {
|
|
210
|
+
const [only] = survivors;
|
|
211
|
+
if (only !== void 0) return {
|
|
212
|
+
face: only,
|
|
213
|
+
confidence: "exact"
|
|
214
|
+
};
|
|
215
|
+
} else if (survivors.length === 0) return {
|
|
216
|
+
ref,
|
|
217
|
+
reason: "deleted"
|
|
188
218
|
};
|
|
219
|
+
else {
|
|
220
|
+
const outcome = scoreFaces(ref.hint, survivors, scoreFn);
|
|
221
|
+
if (outcome.kind === "match") return {
|
|
222
|
+
face: outcome.face,
|
|
223
|
+
confidence: "geometric-fallback"
|
|
224
|
+
};
|
|
225
|
+
if (outcome.kind === "ambiguous") return {
|
|
226
|
+
ref,
|
|
227
|
+
reason: "ambiguous",
|
|
228
|
+
candidates: outcome.candidates
|
|
229
|
+
};
|
|
230
|
+
}
|
|
189
231
|
}
|
|
232
|
+
const outcome = scoreFaces(ref.hint, faces, scoreFn);
|
|
233
|
+
if (outcome.kind === "match") return {
|
|
234
|
+
face: outcome.face,
|
|
235
|
+
confidence: "geometric-fallback"
|
|
236
|
+
};
|
|
237
|
+
if (outcome.kind === "ambiguous") return {
|
|
238
|
+
ref,
|
|
239
|
+
reason: "ambiguous",
|
|
240
|
+
candidates: outcome.candidates
|
|
241
|
+
};
|
|
190
242
|
return {
|
|
191
243
|
ref,
|
|
192
244
|
reason: "not-found"
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const require_vec3 = require("./vec3-CFwOI0ZI.cjs");
|
|
2
1
|
const require_topologyQueryFns = require("./topologyQueryFns-CoXVHuN7.cjs");
|
|
3
2
|
const require_faceFns = require("./faceFns-BV0GnTlt.cjs");
|
|
4
3
|
const require_shapeFns = require("./shapeFns-ybo0INGL.cjs");
|
|
@@ -81,7 +80,8 @@ function boxRoleFromNormal(n) {
|
|
|
81
80
|
*
|
|
82
81
|
* For other types: sequential naming ('opType:face_0', 'opType:face_1', ...).
|
|
83
82
|
*
|
|
84
|
-
* @returns Map from role name to face hash
|
|
83
|
+
* @returns Map from role name to its face hash codes (one at assignment time;
|
|
84
|
+
* a role accrues more hashes only later, when `updateRoles` tracks a split).
|
|
85
85
|
*/
|
|
86
86
|
function assignRoles(shape, operationType) {
|
|
87
87
|
const faces = require_topologyQueryFns.getFaces(shape);
|
|
@@ -89,13 +89,13 @@ function assignRoles(shape, operationType) {
|
|
|
89
89
|
if (operationType === "box") {
|
|
90
90
|
for (const face of faces) {
|
|
91
91
|
const role = boxRoleFromNormal(require_faceFns.normalAt(face));
|
|
92
|
-
if (role !== void 0 && !roles.has(role)) roles.set(role, require_shapeFns.getHashCode(face));
|
|
92
|
+
if (role !== void 0 && !roles.has(role)) roles.set(role, [require_shapeFns.getHashCode(face)]);
|
|
93
93
|
}
|
|
94
94
|
return roles;
|
|
95
95
|
}
|
|
96
96
|
let index = 0;
|
|
97
97
|
for (const face of faces) {
|
|
98
|
-
roles.set(`${operationType}:face_${index}`, require_shapeFns.getHashCode(face));
|
|
98
|
+
roles.set(`${operationType}:face_${index}`, [require_shapeFns.getHashCode(face)]);
|
|
99
99
|
index++;
|
|
100
100
|
}
|
|
101
101
|
return roles;
|
|
@@ -109,31 +109,47 @@ function createRef(origin, role, face) {
|
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
111
|
/**
|
|
112
|
+
* Advance a role's face hashes through one evolution: drop deleted faces,
|
|
113
|
+
* replace a modified face with *all* its successors (a 1→many split keeps every
|
|
114
|
+
* fragment), and keep unchanged faces. Deduped so a shared successor isn't
|
|
115
|
+
* doubled.
|
|
116
|
+
*/
|
|
117
|
+
function nextHashes(hashes, evolution) {
|
|
118
|
+
const successors = [];
|
|
119
|
+
for (const hash of hashes) {
|
|
120
|
+
if (evolution.deleted.has(hash)) continue;
|
|
121
|
+
const modified = evolution.modified.get(hash);
|
|
122
|
+
const targets = modified && modified.length > 0 ? modified : [hash];
|
|
123
|
+
for (const h of targets) if (!successors.includes(h)) successors.push(h);
|
|
124
|
+
}
|
|
125
|
+
return successors;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
112
128
|
* Propagate a role table through a ShapeEvolution record.
|
|
113
129
|
* Returns a new RoleTable with hashes updated according to the evolution.
|
|
114
130
|
*
|
|
115
|
-
* - Deleted faces: role removed
|
|
116
|
-
* - Modified faces: hash
|
|
117
|
-
*
|
|
131
|
+
* - Deleted faces: hash dropped (role removed once all its hashes are gone).
|
|
132
|
+
* - Modified faces: hash replaced by **all** successor hashes — so a 1→many
|
|
133
|
+
* split keeps every fragment, and `resolveRef` disambiguates among them.
|
|
134
|
+
* - Unchanged faces: hash preserved.
|
|
118
135
|
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
136
|
+
* Note: `evolution.generated` is intentionally not consumed here — on the OCCT
|
|
137
|
+
* kernels its hashes refer to an intermediate shape, not the final result, so
|
|
138
|
+
* naming generated faces produces roles that never resolve (verified: 0 live
|
|
139
|
+
* generated hashes across cut/fuse on occt-wasm). Stable names for generated
|
|
140
|
+
* geometry (fillet rounds, boolean seams) need history-fidelity work tracked
|
|
141
|
+
* separately.
|
|
123
142
|
*/
|
|
124
143
|
function updateRoles(roles, origin, evolution) {
|
|
125
144
|
const originRoles = roles.get(origin);
|
|
126
145
|
if (!originRoles) return roles;
|
|
127
146
|
const updatedOriginRoles = /* @__PURE__ */ new Map();
|
|
128
|
-
for (const [role,
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if (modifiedHashes && modifiedHashes.length > 0) updatedOriginRoles.set(role, require_vec3.wasmIndex(modifiedHashes, 0));
|
|
132
|
-
else updatedOriginRoles.set(role, hash);
|
|
147
|
+
for (const [role, hashes] of originRoles) {
|
|
148
|
+
const successors = nextHashes(hashes, evolution);
|
|
149
|
+
if (successors.length > 0) updatedOriginRoles.set(role, successors);
|
|
133
150
|
}
|
|
134
151
|
const newRoles = /* @__PURE__ */ new Map();
|
|
135
|
-
for (const [key, value] of roles)
|
|
136
|
-
else newRoles.set(key, value);
|
|
152
|
+
for (const [key, value] of roles) newRoles.set(key, key === origin ? updatedOriginRoles : value);
|
|
137
153
|
return newRoles;
|
|
138
154
|
}
|
|
139
155
|
/** Ambiguity threshold: if two scores are within this range, it's ambiguous. */
|
|
@@ -141,34 +157,19 @@ var AMBIGUITY_THRESHOLD = .1;
|
|
|
141
157
|
/** Minimum score for geometric fallback to accept a match. */
|
|
142
158
|
var MIN_SCORE = .5;
|
|
143
159
|
/**
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
* 3. Ambiguous if multiple faces score within threshold
|
|
150
|
-
* 4. Not-found if no match above minimum score
|
|
160
|
+
* Score `candidates` against `hint`, returning the best match, a tie within
|
|
161
|
+
* {@link AMBIGUITY_THRESHOLD}, or nothing above {@link MIN_SCORE}. Scoping the
|
|
162
|
+
* candidates to a role's tracked successors (rather than every face) is what
|
|
163
|
+
* makes split-face disambiguation reliable — the fragments compete only with
|
|
164
|
+
* each other, not with unrelated geometry.
|
|
151
165
|
*/
|
|
152
|
-
function
|
|
153
|
-
const faces = require_topologyQueryFns.getFaces(currentShape);
|
|
154
|
-
const scoreFn = scorer ?? defaultScorer;
|
|
155
|
-
const targetHash = roles.get(ref.origin)?.get(ref.role);
|
|
156
|
-
if (targetHash !== void 0) {
|
|
157
|
-
for (const face of faces) if (require_shapeFns.getHashCode(face) === targetHash) return {
|
|
158
|
-
face,
|
|
159
|
-
confidence: "exact"
|
|
160
|
-
};
|
|
161
|
-
return {
|
|
162
|
-
ref,
|
|
163
|
-
reason: "deleted"
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
+
function scoreFaces(hint, candidates, scoreFn) {
|
|
166
167
|
let bestScore = -Infinity;
|
|
167
168
|
let bestFace;
|
|
168
169
|
let secondBestScore = -Infinity;
|
|
169
170
|
const scored = [];
|
|
170
|
-
for (const face of
|
|
171
|
-
const score = scoreFn(
|
|
171
|
+
for (const face of candidates) {
|
|
172
|
+
const score = scoreFn(hint, face);
|
|
172
173
|
if (score > MIN_SCORE) scored.push([face, score]);
|
|
173
174
|
if (score > bestScore) {
|
|
174
175
|
secondBestScore = bestScore;
|
|
@@ -178,15 +179,66 @@ function resolveRef(ref, roles, currentShape, scorer) {
|
|
|
178
179
|
}
|
|
179
180
|
if (bestFace !== void 0 && bestScore > MIN_SCORE) {
|
|
180
181
|
if (bestScore - secondBestScore < AMBIGUITY_THRESHOLD && scored.length > 1) return {
|
|
181
|
-
|
|
182
|
-
reason: "ambiguous",
|
|
182
|
+
kind: "ambiguous",
|
|
183
183
|
candidates: scored.filter(([, s]) => s >= bestScore - AMBIGUITY_THRESHOLD).map(([f]) => f)
|
|
184
184
|
};
|
|
185
185
|
return {
|
|
186
|
-
|
|
187
|
-
|
|
186
|
+
kind: "match",
|
|
187
|
+
face: bestFace
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
return { kind: "none" };
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Resolve a ShapeRef to a face in the current shape.
|
|
194
|
+
*
|
|
195
|
+
* Resolution strategy:
|
|
196
|
+
* 1. Exact: the role's tracked successor hashes. One survivor → exact match;
|
|
197
|
+
* several survivors (a face that split) → disambiguate among *only those*
|
|
198
|
+
* fragments; none survive → deleted.
|
|
199
|
+
* 2. Geometric fallback over the whole shape when the role isn't tracked (or a
|
|
200
|
+
* scoped score turned up nothing): best-scoring face, else ambiguous /
|
|
201
|
+
* not-found.
|
|
202
|
+
*/
|
|
203
|
+
function resolveRef(ref, roles, currentShape, scorer) {
|
|
204
|
+
const faces = require_topologyQueryFns.getFaces(currentShape);
|
|
205
|
+
const scoreFn = scorer ?? defaultScorer;
|
|
206
|
+
const targetHashes = roles.get(ref.origin)?.get(ref.role);
|
|
207
|
+
if (targetHashes !== void 0 && targetHashes.length > 0) {
|
|
208
|
+
const survivors = faces.filter((f) => targetHashes.includes(require_shapeFns.getHashCode(f)));
|
|
209
|
+
if (survivors.length === 1) {
|
|
210
|
+
const [only] = survivors;
|
|
211
|
+
if (only !== void 0) return {
|
|
212
|
+
face: only,
|
|
213
|
+
confidence: "exact"
|
|
214
|
+
};
|
|
215
|
+
} else if (survivors.length === 0) return {
|
|
216
|
+
ref,
|
|
217
|
+
reason: "deleted"
|
|
188
218
|
};
|
|
219
|
+
else {
|
|
220
|
+
const outcome = scoreFaces(ref.hint, survivors, scoreFn);
|
|
221
|
+
if (outcome.kind === "match") return {
|
|
222
|
+
face: outcome.face,
|
|
223
|
+
confidence: "geometric-fallback"
|
|
224
|
+
};
|
|
225
|
+
if (outcome.kind === "ambiguous") return {
|
|
226
|
+
ref,
|
|
227
|
+
reason: "ambiguous",
|
|
228
|
+
candidates: outcome.candidates
|
|
229
|
+
};
|
|
230
|
+
}
|
|
189
231
|
}
|
|
232
|
+
const outcome = scoreFaces(ref.hint, faces, scoreFn);
|
|
233
|
+
if (outcome.kind === "match") return {
|
|
234
|
+
face: outcome.face,
|
|
235
|
+
confidence: "geometric-fallback"
|
|
236
|
+
};
|
|
237
|
+
if (outcome.kind === "ambiguous") return {
|
|
238
|
+
ref,
|
|
239
|
+
reason: "ambiguous",
|
|
240
|
+
candidates: outcome.candidates
|
|
241
|
+
};
|
|
190
242
|
return {
|
|
191
243
|
ref,
|
|
192
244
|
reason: "not-found"
|
|
@@ -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,7 @@
|
|
|
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, } 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';
|
|
@@ -15,32 +15,38 @@ export declare function captureHint(face: Face): GeometricHint;
|
|
|
15
15
|
*
|
|
16
16
|
* For other types: sequential naming ('opType:face_0', 'opType:face_1', ...).
|
|
17
17
|
*
|
|
18
|
-
* @returns Map from role name to face hash
|
|
18
|
+
* @returns Map from role name to its face hash codes (one at assignment time;
|
|
19
|
+
* a role accrues more hashes only later, when `updateRoles` tracks a split).
|
|
19
20
|
*/
|
|
20
|
-
export declare function assignRoles(shape: Shape3D, operationType: string): Map<string, number>;
|
|
21
|
+
export declare function assignRoles(shape: Shape3D, operationType: string): Map<string, number[]>;
|
|
21
22
|
/** Create a ShapeRef from an origin ID, role name, and face. */
|
|
22
23
|
export declare function createRef(origin: string, role: string, face: Face): ShapeRef;
|
|
23
24
|
/**
|
|
24
25
|
* Propagate a role table through a ShapeEvolution record.
|
|
25
26
|
* Returns a new RoleTable with hashes updated according to the evolution.
|
|
26
27
|
*
|
|
27
|
-
* - Deleted faces: role removed
|
|
28
|
-
* - Modified faces: hash
|
|
29
|
-
*
|
|
28
|
+
* - Deleted faces: hash dropped (role removed once all its hashes are gone).
|
|
29
|
+
* - Modified faces: hash replaced by **all** successor hashes — so a 1→many
|
|
30
|
+
* split keeps every fragment, and `resolveRef` disambiguates among them.
|
|
31
|
+
* - Unchanged faces: hash preserved.
|
|
30
32
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
33
|
+
* Note: `evolution.generated` is intentionally not consumed here — on the OCCT
|
|
34
|
+
* kernels its hashes refer to an intermediate shape, not the final result, so
|
|
35
|
+
* naming generated faces produces roles that never resolve (verified: 0 live
|
|
36
|
+
* generated hashes across cut/fuse on occt-wasm). Stable names for generated
|
|
37
|
+
* geometry (fillet rounds, boolean seams) need history-fidelity work tracked
|
|
38
|
+
* separately.
|
|
35
39
|
*/
|
|
36
40
|
export declare function updateRoles(roles: RoleTable, origin: string, evolution: ShapeEvolution): RoleTable;
|
|
37
41
|
/**
|
|
38
42
|
* Resolve a ShapeRef to a face in the current shape.
|
|
39
43
|
*
|
|
40
44
|
* Resolution strategy:
|
|
41
|
-
* 1. Exact
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
+
* 1. Exact: the role's tracked successor hashes. One survivor → exact match;
|
|
46
|
+
* several survivors (a face that split) → disambiguate among *only those*
|
|
47
|
+
* fragments; none survive → deleted.
|
|
48
|
+
* 2. Geometric fallback over the whole shape when the role isn't tracked (or a
|
|
49
|
+
* scoped score turned up nothing): best-scoring face, else ambiguous /
|
|
50
|
+
* not-found.
|
|
45
51
|
*/
|
|
46
52
|
export declare function resolveRef(ref: ShapeRef, roles: RoleTable, currentShape: Shape3D, scorer?: FaceScorer): ResolvedRef | BrokenRef;
|
|
@@ -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 } 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';
|
|
@@ -22,10 +22,14 @@ export interface ShapeRef {
|
|
|
22
22
|
readonly hint: GeometricHint;
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
|
-
* Immutable table mapping `origin -> role ->
|
|
25
|
+
* Immutable table mapping `origin -> role -> faceHashes`.
|
|
26
26
|
* Updated through evolution records when the model is rebuilt.
|
|
27
|
+
*
|
|
28
|
+
* A role usually maps to a single hash, but maps to several after its face
|
|
29
|
+
* splits (a 1→many `modified` evolution); resolution then disambiguates among
|
|
30
|
+
* the surviving successors rather than competing against the whole shape.
|
|
27
31
|
*/
|
|
28
|
-
export type RoleTable = ReadonlyMap<string, ReadonlyMap<string, number>>;
|
|
32
|
+
export type RoleTable = ReadonlyMap<string, ReadonlyMap<string, readonly number[]>>;
|
|
29
33
|
/** A successfully resolved face reference. */
|
|
30
34
|
export interface ResolvedRef {
|
|
31
35
|
readonly face: Face;
|
|
@@ -37,3 +41,38 @@ export interface BrokenRef {
|
|
|
37
41
|
readonly reason: 'deleted' | 'ambiguous' | 'not-found';
|
|
38
42
|
readonly candidates?: readonly Face[];
|
|
39
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
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brepjs",
|
|
3
|
-
"version": "18.
|
|
3
|
+
"version": "18.111.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": {
|