brepjs 20.13.4 → 20.13.6
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/2d.cjs +6 -6
- package/dist/2d.js +6 -6
- package/dist/{adjacencyFns-DjblerpV.cjs → adjacencyFns-BLtq-nUN.cjs} +3 -3
- package/dist/{adjacencyFns-Ce4lxSWp.js → adjacencyFns-C1Hxy0tk.js} +3 -3
- package/dist/{blueprint-CeIbNzdp.js → blueprint-BzI6waZa.js} +5 -5
- package/dist/{blueprint-D4YxCDeX.cjs → blueprint-DlpFhHbU.cjs} +5 -5
- package/dist/{blueprintFns-fc9ZUSqe.cjs → blueprintFns-Cc9OyvKE.cjs} +2 -2
- package/dist/{blueprintFns-DEeIBzwN.js → blueprintFns-HFd0lu9A.js} +2 -2
- package/dist/{blueprintSketcher-BQ6ApvaQ.js → blueprintSketcher-BrQee61I.js} +3 -3
- package/dist/{blueprintSketcher-DID7kq5g.cjs → blueprintSketcher-DUT3-Cuo.cjs} +3 -3
- package/dist/{boolean2D-BsrkJbMe.cjs → boolean2D-BC0TwxyB.cjs} +4 -4
- package/dist/{boolean2D-QMPt29HH.js → boolean2D-CvBeghsg.js} +4 -4
- package/dist/{booleanFns-BuxgJmu2.js → booleanFns-Dtg2jqzi.js} +5 -5
- package/dist/{booleanFns-CQIepT9X.cjs → booleanFns-Dti1CK1F.cjs} +5 -5
- package/dist/brepjs.cjs +30 -30
- package/dist/brepjs.js +30 -30
- package/dist/{cameraFns-DL3zo3ol.cjs → cameraFns--Ab792oE.cjs} +3 -3
- package/dist/{cameraFns-s8km1l0J.js → cameraFns-CXONX5Da.js} +3 -3
- package/dist/core/disposal.d.ts +4 -1
- package/dist/core.cjs +2 -2
- package/dist/core.js +2 -2
- package/dist/{cornerFinder-D7P4vdaD.js → cornerFinder-C7f43oKE.js} +1 -1
- package/dist/{cornerFinder-uPZDWiyt.cjs → cornerFinder-DUzrQsfW.cjs} +1 -1
- package/dist/{curveFns-CQtl1RzI.js → curveFns-Dzgl3_MC.js} +1 -1
- package/dist/{curveFns-DkG5mlUj.cjs → curveFns-QaNfJzko.cjs} +1 -1
- package/dist/{drawFns-CSYj0D8x.cjs → drawFns-BRXk9fLg.cjs} +12 -12
- package/dist/{drawFns-BKnz1pa1.js → drawFns-WvF0fehK.js} +12 -12
- package/dist/{faceFns-f8AWRrzK.js → faceFns-BG1CBQUM.js} +2 -2
- package/dist/{faceFns-C_iC_WkC.cjs → faceFns-dj_c8LVc.cjs} +2 -2
- package/dist/{healingFns-W4_K9hXo.cjs → healingFns-BSNNLyXP.cjs} +12 -14
- package/dist/{healingFns-BRXArH8z.js → healingFns-CfkUEqcL.js} +12 -14
- package/dist/{helpers-m-lbbfaz.cjs → helpers-6Emek9dE.cjs} +6 -6
- package/dist/{helpers-COdYBjWD.js → helpers-DolHn2_s.js} +6 -6
- package/dist/{importFns-Kr02P3cy.cjs → importFns-CZb21dj7.cjs} +5 -5
- package/dist/{importFns-D8U3wLhV.js → importFns-D1AxkVC3.js} +5 -5
- package/dist/io.cjs +2 -2
- package/dist/io.js +2 -2
- package/dist/kernel/brepkit/brepkitWasmTypes.d.ts +17 -19
- package/dist/kernel/brepkit/constructionOps.d.ts +1 -1
- package/dist/kernel/brepkit/helpers.d.ts +25 -4
- package/dist/kernel/brepkit/modifierOps.d.ts +3 -3
- package/dist/kernel/occtWasm/occtWasmAdapter.cjs +1 -1
- package/dist/kernel/occtWasm/occtWasmAdapter.js +1 -1
- package/dist/{loftFns-CVk6mzZj.cjs → loftFns-BD0na-M4.cjs} +4 -4
- package/dist/{loftFns-MN9TgyG4.js → loftFns-Cua-MamP.js} +4 -4
- package/dist/{measureFns-9aeYKFiR.cjs → measureFns-FrNeGmXh.cjs} +4 -4
- package/dist/{measureFns-9GzKgCdl.js → measureFns-WGYWWnQ1.js} +4 -4
- package/dist/measurement.cjs +2 -2
- package/dist/measurement.js +2 -2
- package/dist/{meshFns-BwsjspzI.cjs → meshFns-Dy1a9wl_.cjs} +4 -4
- package/dist/{meshFns-un9EDg7X.js → meshFns-Lie8oAac.js} +4 -4
- package/dist/{occtWasmAdapter-4YnvqZOW.cjs → occtWasmAdapter-B9ZXx36v.cjs} +1 -1
- package/dist/{occtWasmAdapter-CGsnjMOe.js → occtWasmAdapter-CGkZIHyM.js} +1 -1
- package/dist/operations/sweepFns.d.ts +3 -3
- package/dist/operations.cjs +2 -2
- package/dist/operations.js +2 -2
- package/dist/{primitiveFns-CIPm9vsq.cjs → primitiveFns-Dpn3ZtUE.cjs} +5 -5
- package/dist/{primitiveFns-BICas2bb.js → primitiveFns-w-ST-RDJ.js} +5 -5
- package/dist/{principalBoxFns-CQZRNYI3.cjs → principalBoxFns-3ZURcOFP.cjs} +3 -3
- package/dist/{principalBoxFns-DQytdykp.js → principalBoxFns-CjfJnZfH.js} +3 -3
- package/dist/projection.cjs +1 -1
- package/dist/projection.js +1 -1
- package/dist/query.cjs +2 -2
- package/dist/query.js +2 -2
- package/dist/{refResolveFns-DNnNqpyn.cjs → refResolveFns-ROMmhWfH.cjs} +6 -6
- package/dist/{refResolveFns-CpPBZkjT.js → refResolveFns-Yy1n2BHJ.js} +6 -6
- package/dist/{shapeFns-D6-l0Nwn.js → shapeFns-BRRrZc1X.js} +2 -2
- package/dist/{shapeFns-Dr_0yhYg.cjs → shapeFns-CljM3iMI.cjs} +2 -2
- package/dist/shapeRef.cjs +1 -1
- package/dist/shapeRef.js +1 -1
- package/dist/{shapeTypes-B23U9msC.cjs → shapeTypes-DEe6gtTR.cjs} +460 -89
- package/dist/{shapeTypes-CSWkqhe9.js → shapeTypes-w2wyXEis.js} +460 -89
- package/dist/sketching.cjs +3 -3
- package/dist/sketching.js +3 -3
- package/dist/{solidBuilders-CQ1oQdBY.js → solidBuilders-BxIYXIv-.js} +3 -3
- package/dist/{solidBuilders-DIlNbnwK.cjs → solidBuilders-yQFZe6jf.cjs} +3 -3
- package/dist/{surfaceBuilders-ZW6W8S1a.js → surfaceBuilders-BZ7BW8I0.js} +3 -3
- package/dist/{surfaceBuilders-BV-QYvCL.cjs → surfaceBuilders-dWcQ_BpM.cjs} +3 -3
- package/dist/text.cjs +2 -2
- package/dist/text.js +2 -2
- package/dist/{textBlueprints-CwsfEEBS.js → textBlueprints-CxhhPEaF.js} +8 -8
- package/dist/{textBlueprints-DYrv0GjE.cjs → textBlueprints-Tx73Xex5.cjs} +8 -8
- package/dist/{textMetrics-gC0qYCN1.cjs → textMetrics-9q5S5II9.cjs} +1 -1
- package/dist/{textMetrics-B_WRck8_.js → textMetrics-B5dKPalE.js} +1 -1
- package/dist/{threadFns-srKixiXB.cjs → threadFns-BnNo5eND.cjs} +7 -7
- package/dist/{threadFns-D9m_ywSR.js → threadFns-Dfu2jV41.js} +7 -7
- package/dist/topology/apiTypes.d.ts +0 -3
- package/dist/topology/modifierFns.d.ts +4 -6
- package/dist/topology.cjs +9 -9
- package/dist/topology.js +9 -9
- package/dist/{topologyQueryFns-D8Du44mm.js → topologyQueryFns-CTl4cWYD.js} +1 -1
- package/dist/{topologyQueryFns-DJJoFJPW.cjs → topologyQueryFns-I_m8o-s7.cjs} +1 -1
- package/dist/{validityTypes-DSzSU07u.js → validityTypes-C2K0Eepw.js} +1 -1
- package/dist/{validityTypes-BkX2hYwP.cjs → validityTypes-DgknRAAp.cjs} +1 -1
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_occtWasmAdapter = require("./occtWasmAdapter-
|
|
1
|
+
const require_occtWasmAdapter = require("./occtWasmAdapter-B9ZXx36v.cjs");
|
|
2
2
|
const require_bug = require("./bug-CBcpIPuf.cjs");
|
|
3
3
|
// src/kernel/quality.ts
|
|
4
4
|
/**
|
|
@@ -5401,14 +5401,13 @@ var TAU$1 = 2 * Math.PI;
|
|
|
5401
5401
|
/**
|
|
5402
5402
|
* The frame of an analytic circle or ellipse edge, evaluated at t as
|
|
5403
5403
|
* center + U·cos t + V·sin t, recovered from its points at 0, π/2 and π.
|
|
5404
|
-
*
|
|
5405
|
-
*
|
|
5404
|
+
* A NURBS edge that happens to be a circle reports CIRCLE too but runs over
|
|
5405
|
+
* its knots, so it gets no frame; only an analytic edge has no NURBS data.
|
|
5406
5406
|
*/
|
|
5407
5407
|
function conicFrame(bk, edgeId) {
|
|
5408
|
-
const params = bk.getEdgeCurveParameters(edgeId);
|
|
5409
|
-
if (require_bug.wasmIndex(params, 0) !== 0 || require_bug.wasmIndex(params, 1) !== TAU$1) return void 0;
|
|
5410
5408
|
const curveType = bk.getEdgeCurveType(edgeId);
|
|
5411
5409
|
if (curveType !== "CIRCLE" && curveType !== "ELLIPSE") return void 0;
|
|
5410
|
+
if (bk.getEdgeNurbsData(edgeId) !== null) return void 0;
|
|
5412
5411
|
const at = (t) => {
|
|
5413
5412
|
const p = bk.evaluateEdgeCurve(edgeId, t);
|
|
5414
5413
|
return [
|
|
@@ -5452,10 +5451,11 @@ function edgeEnds(bk, edgeId) {
|
|
|
5452
5451
|
]];
|
|
5453
5452
|
}
|
|
5454
5453
|
/**
|
|
5455
|
-
* The curve parameters an edge spans. brepkit reports a circle or
|
|
5456
|
-
* domain as the whole [0, 2π] even for an arc
|
|
5457
|
-
*
|
|
5458
|
-
*
|
|
5454
|
+
* The curve parameters an edge spans. brepkit before 4.5.10 reports a circle or
|
|
5455
|
+
* ellipse edge's domain as the whole [0, 2π] even for an arc, so an arc's span
|
|
5456
|
+
* is read off the curve's frame on every kernel: it runs counterclockwise about
|
|
5457
|
+
* the curve's axis from the angle of its start vertex to that of its end vertex
|
|
5458
|
+
* (brepkit's own `circle_param_range`).
|
|
5459
5459
|
*/
|
|
5460
5460
|
function edgeParamRange(bk, edgeId) {
|
|
5461
5461
|
const params = bk.getEdgeCurveParameters(edgeId);
|
|
@@ -5717,6 +5717,35 @@ function nextSyntheticId() {
|
|
|
5717
5717
|
}
|
|
5718
5718
|
/** JS-side storage for compound children (wires, faces, edges). */
|
|
5719
5719
|
var syntheticCompounds = /* @__PURE__ */ new Map();
|
|
5720
|
+
/**
|
|
5721
|
+
* Each solid's piece ids, per kernel. getSolidPieces builds new solids and
|
|
5722
|
+
* shells for a solid in several pieces on every call, and the arena frees
|
|
5723
|
+
* nothing one handle at a time, so a solid is split once and its pieces keep
|
|
5724
|
+
* one identity until the solid changes in place or the arena rolls back.
|
|
5725
|
+
*/
|
|
5726
|
+
var solidPiecesByKernel = /* @__PURE__ */ new WeakMap();
|
|
5727
|
+
/** A solid's piece ids, from `split` the first time they are asked for. */
|
|
5728
|
+
function cachedSolidPieces(bk, solidId, split) {
|
|
5729
|
+
let known = solidPiecesByKernel.get(bk);
|
|
5730
|
+
if (!known) {
|
|
5731
|
+
known = /* @__PURE__ */ new Map();
|
|
5732
|
+
solidPiecesByKernel.set(bk, known);
|
|
5733
|
+
}
|
|
5734
|
+
const cached = known.get(solidId);
|
|
5735
|
+
if (cached) return cached;
|
|
5736
|
+
const pieces = split();
|
|
5737
|
+
known.set(solidId, pieces);
|
|
5738
|
+
for (const piece of pieces) if (!known.has(piece)) known.set(piece, [piece]);
|
|
5739
|
+
return pieces;
|
|
5740
|
+
}
|
|
5741
|
+
/**
|
|
5742
|
+
* Forget one solid's pieces after the kernel changes it in place, or every
|
|
5743
|
+
* solid's after the arena rolls back and its ids can name new entities.
|
|
5744
|
+
*/
|
|
5745
|
+
function forgetSolidPieces(bk, solidId) {
|
|
5746
|
+
if (solidId === void 0) solidPiecesByKernel.delete(bk);
|
|
5747
|
+
else solidPiecesByKernel.get(bk)?.delete(solidId);
|
|
5748
|
+
}
|
|
5720
5749
|
var _warned = /* @__PURE__ */ new Set();
|
|
5721
5750
|
/** Emit a console.warn once per key per session. */
|
|
5722
5751
|
function warnOnce(key, message) {
|
|
@@ -5764,17 +5793,35 @@ function resolveUniformAngle(faces, angleDeg) {
|
|
|
5764
5793
|
return uniform;
|
|
5765
5794
|
}
|
|
5766
5795
|
// src/kernel/brepkit/topologyOps.ts
|
|
5796
|
+
/**
|
|
5797
|
+
* One solid per separate piece of material in a solid: a boolean can leave
|
|
5798
|
+
* several pieces in one kernel solid, all in one shell. A solid in one piece
|
|
5799
|
+
* keeps its own handle, since the kernel answers a solid whose cavity shares
|
|
5800
|
+
* its shell with a rebuilt one.
|
|
5801
|
+
*/
|
|
5802
|
+
function solidPieces(bk, solid) {
|
|
5803
|
+
if (typeof bk.getSolidPieces !== "function") return [solid];
|
|
5804
|
+
const id = unwrap$1(solid, "solid");
|
|
5805
|
+
const pieces = cachedSolidPieces(bk, id, () => {
|
|
5806
|
+
const found = toArray(bk.getSolidPieces(id));
|
|
5807
|
+
return found.length > 1 ? found : [id];
|
|
5808
|
+
});
|
|
5809
|
+
return pieces.length > 1 ? pieces.map(solidHandle) : [solid];
|
|
5810
|
+
}
|
|
5767
5811
|
function iterCompound(bk, h, type) {
|
|
5768
5812
|
const children = syntheticCompounds.get(h);
|
|
5769
|
-
if (children) return children.flatMap((child) =>
|
|
5770
|
-
|
|
5813
|
+
if (children) return children.flatMap((child) => {
|
|
5814
|
+
if (child.type === "solid" && type === "solid") return solidPieces(bk, child);
|
|
5815
|
+
return child.type === type ? [child] : iterShapes$1(bk, child, type);
|
|
5816
|
+
});
|
|
5817
|
+
if (type === "solid") return toArray(bk.getCompoundSolids(h)).flatMap((id) => solidPieces(bk, solidHandle(id)));
|
|
5771
5818
|
if (type === "face" || type === "edge" || type === "vertex" || type === "wire") return toArray(bk.getCompoundSolids(h)).map(solidHandle).flatMap((s) => iterShapes$1(bk, s, type));
|
|
5772
5819
|
return [];
|
|
5773
5820
|
}
|
|
5774
5821
|
function iterSolid(bk, shape, h, type) {
|
|
5775
5822
|
switch (type) {
|
|
5776
|
-
case "solid": return
|
|
5777
|
-
case "shell": return toArray(bk.getSolidShells(
|
|
5823
|
+
case "solid": return solidPieces(bk, shape);
|
|
5824
|
+
case "shell": return solidPieces(bk, shape).flatMap((piece) => toArray(bk.getSolidShells(unwrap$1(piece, "solid"))).map(shellHandle));
|
|
5778
5825
|
case "face": return toArray(bk.getSolidFaces(h)).map(faceHandle);
|
|
5779
5826
|
case "edge": return toArray(bk.getSolidEdges(h)).map(edgeHandle);
|
|
5780
5827
|
case "vertex": return toArray(bk.getSolidVertices(h)).map(vertexHandle);
|
|
@@ -5910,12 +5957,23 @@ function faceIdsForSew(bk, shape) {
|
|
|
5910
5957
|
function sew(bk, shapes, tolerance) {
|
|
5911
5958
|
const faceIds = shapes.flatMap((s) => faceIdsForSew(bk, s));
|
|
5912
5959
|
const tol = tolerance ?? 1e-7;
|
|
5960
|
+
let solidId;
|
|
5913
5961
|
try {
|
|
5914
|
-
|
|
5962
|
+
solidId = bk.weldShellsAndFaces(faceIds, tol);
|
|
5915
5963
|
} catch (e) {
|
|
5916
5964
|
console.warn("brepkit: weldShellsAndFaces failed, falling back to sewFaces:", e);
|
|
5965
|
+
solidId = bk.sewFaces(faceIds, tol);
|
|
5917
5966
|
}
|
|
5918
|
-
return
|
|
5967
|
+
return sewnShell(bk, solidId);
|
|
5968
|
+
}
|
|
5969
|
+
/**
|
|
5970
|
+
* Both sewing bindings wrap the one shell they sew in a solid and return the
|
|
5971
|
+
* solid's handle; the shell has its own, which shell queries need.
|
|
5972
|
+
*/
|
|
5973
|
+
function sewnShell(bk, solidId) {
|
|
5974
|
+
const [shellId] = toArray(bk.getSolidShells(solidId));
|
|
5975
|
+
if (shellId === void 0) throw new Error("brepkit: sewing returned a solid with no shell");
|
|
5976
|
+
return shellHandle(shellId);
|
|
5919
5977
|
}
|
|
5920
5978
|
/** Co-located factory: returns the topology-iteration slice of {@link KernelAdapter} bound to `bk`. */
|
|
5921
5979
|
function makeTopologyOps$1(bk) {
|
|
@@ -6174,33 +6232,76 @@ function recognizeFeatures(bk, shape, tolerance) {
|
|
|
6174
6232
|
const solidId = unwrapSolidOrThrow(shape, "recognizeFeatures");
|
|
6175
6233
|
return bk.recognizeFeatures(solidId, tolerance);
|
|
6176
6234
|
}
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
const
|
|
6180
|
-
|
|
6181
|
-
const
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6235
|
+
/** The solids whose edges a projection draws: a solid itself, or every solid of a compound. */
|
|
6236
|
+
function projectedSolidIds(bk, shape) {
|
|
6237
|
+
const h = shape;
|
|
6238
|
+
if (h.type === "solid") return [h.id];
|
|
6239
|
+
const ids = h.type === "compound" ? iterShapes$1(bk, shape, "solid").map((s) => unwrap$1(s)) : [];
|
|
6240
|
+
if (ids.length === 0) throw new Error(`brepkit: projectEdges needs a solid or a compound of solids, got ${h.type}`);
|
|
6241
|
+
return ids;
|
|
6242
|
+
}
|
|
6243
|
+
/**
|
|
6244
|
+
* brepkit returns polyline approximations of the projection, so tie the
|
|
6245
|
+
* tessellation deflection to model scale (1/1000 of the bbox diagonal) to
|
|
6246
|
+
* stay resolution-independent across part sizes.
|
|
6247
|
+
*/
|
|
6248
|
+
function projectionDeflection(bk, solidIds) {
|
|
6249
|
+
const min = [
|
|
6250
|
+
Infinity,
|
|
6251
|
+
Infinity,
|
|
6252
|
+
Infinity
|
|
6253
|
+
];
|
|
6254
|
+
const max = [
|
|
6255
|
+
-Infinity,
|
|
6256
|
+
-Infinity,
|
|
6257
|
+
-Infinity
|
|
6185
6258
|
];
|
|
6186
|
-
let deflection = .1;
|
|
6187
6259
|
try {
|
|
6188
|
-
const
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6260
|
+
for (const id of solidIds) {
|
|
6261
|
+
const bb = bk.boundingBox(id);
|
|
6262
|
+
for (let k = 0; k < 3; k++) {
|
|
6263
|
+
min[k] = Math.min(require_bug.wasmIndex(min, k), require_bug.wasmIndex(bb, k));
|
|
6264
|
+
max[k] = Math.max(require_bug.wasmIndex(max, k), require_bug.wasmIndex(bb, k + 3));
|
|
6265
|
+
}
|
|
6266
|
+
}
|
|
6267
|
+
} catch {
|
|
6268
|
+
return .1;
|
|
6269
|
+
}
|
|
6270
|
+
const diag = dist3(...min, ...max);
|
|
6271
|
+
return diag > 0 ? Math.max(diag * .001, 1e-6) : .1;
|
|
6272
|
+
}
|
|
6273
|
+
function parseProjection(json) {
|
|
6196
6274
|
try {
|
|
6197
|
-
|
|
6275
|
+
return JSON.parse(json);
|
|
6198
6276
|
} catch {
|
|
6199
|
-
|
|
6277
|
+
return {
|
|
6200
6278
|
visible: [],
|
|
6201
6279
|
hidden: []
|
|
6202
6280
|
};
|
|
6203
6281
|
}
|
|
6282
|
+
}
|
|
6283
|
+
/** Each solid's edges, hidden wherever any of the solids lies in front of them. */
|
|
6284
|
+
function projectSolids(bk, solidIds, view) {
|
|
6285
|
+
const deflection = projectionDeflection(bk, solidIds);
|
|
6286
|
+
const [only, ...others] = solidIds;
|
|
6287
|
+
if (only !== void 0 && others.length === 0) return parseProjection(bk.projectEdges(only, ...view, true, deflection));
|
|
6288
|
+
if (typeof bk.projectSolidsEdges === "function") return parseProjection(bk.projectSolidsEdges(solidIds, ...view, true, deflection));
|
|
6289
|
+
const parts = solidIds.map((id) => parseProjection(bk.projectEdges(id, ...view, true, deflection)));
|
|
6290
|
+
return {
|
|
6291
|
+
visible: parts.flatMap((p) => p.visible),
|
|
6292
|
+
hidden: parts.flatMap((p) => p.hidden)
|
|
6293
|
+
};
|
|
6294
|
+
}
|
|
6295
|
+
function projectEdges(bk, shape, cameraOrigin, cameraDirection, cameraXAxis) {
|
|
6296
|
+
const parsed = projectSolids(bk, projectedSolidIds(bk, shape), [
|
|
6297
|
+
...cameraOrigin,
|
|
6298
|
+
...cameraDirection,
|
|
6299
|
+
...cameraXAxis ?? [
|
|
6300
|
+
1,
|
|
6301
|
+
0,
|
|
6302
|
+
0
|
|
6303
|
+
]
|
|
6304
|
+
]);
|
|
6204
6305
|
const polylinesToCompound = (polylines) => {
|
|
6205
6306
|
const edges = [];
|
|
6206
6307
|
for (const poly of polylines) for (let i = 0; i + 3 < poly.length; i += 2) {
|
|
@@ -6592,6 +6693,7 @@ function isValidStrict(bk, shape) {
|
|
|
6592
6693
|
function healSolid(bk, shape) {
|
|
6593
6694
|
const h = shape;
|
|
6594
6695
|
if (h.type !== "solid") throw new Error(`brepkit: healSolid requires a solid, got ${h.type}. Consider using makeCompound() to combine shapes first.`);
|
|
6696
|
+
forgetSolidPieces(bk, h.id);
|
|
6595
6697
|
try {
|
|
6596
6698
|
const remaining = bk.repairSolid(unwrap$1(shape));
|
|
6597
6699
|
if (remaining > 0) console.warn(`brepkit: repairSolid left ${remaining} error(s) on solid.`);
|
|
@@ -6614,19 +6716,25 @@ function healWire(_bk, wire, _face) {
|
|
|
6614
6716
|
}
|
|
6615
6717
|
function mergeCoincidentVertices(bk, shape, tolerance) {
|
|
6616
6718
|
const solidId = unwrapSolidOrThrow(shape, "mergeCoincidentVertices");
|
|
6719
|
+
forgetSolidPieces(bk, solidId);
|
|
6617
6720
|
return bk.mergeCoincidentVertices(solidId, tolerance);
|
|
6618
6721
|
}
|
|
6619
6722
|
function removeDegenerateEdges(bk, shape, tolerance) {
|
|
6620
6723
|
const solidId = unwrapSolidOrThrow(shape, "removeDegenerateEdges");
|
|
6724
|
+
forgetSolidPieces(bk, solidId);
|
|
6621
6725
|
return bk.removeDegenerateEdges(solidId, tolerance);
|
|
6622
6726
|
}
|
|
6623
6727
|
function fixFaceOrientations(bk, shape) {
|
|
6624
6728
|
const solidId = unwrapSolidOrThrow(shape, "fixFaceOrientations");
|
|
6729
|
+
forgetSolidPieces(bk, solidId);
|
|
6625
6730
|
return bk.fixFaceOrientations(solidId);
|
|
6626
6731
|
}
|
|
6627
6732
|
function fixShape(bk, shape) {
|
|
6628
6733
|
const h = shape;
|
|
6629
|
-
if (h.type === "solid")
|
|
6734
|
+
if (h.type === "solid") {
|
|
6735
|
+
forgetSolidPieces(bk, h.id);
|
|
6736
|
+
bk.healSolid(h.id);
|
|
6737
|
+
}
|
|
6630
6738
|
return shape;
|
|
6631
6739
|
}
|
|
6632
6740
|
function fixSelfIntersection(_bk, wire) {
|
|
@@ -6973,7 +7081,7 @@ function makeWire(bk, edges) {
|
|
|
6973
7081
|
if (h.type === "wire") for (const childEdgeId of toArray(bk.getWireEdges(h.id))) edgeIds.push(childEdgeId);
|
|
6974
7082
|
else edgeIds.push(unwrap$1(e, "edge"));
|
|
6975
7083
|
}
|
|
6976
|
-
return wireHandle(bk.makeWire(edgeIds, true));
|
|
7084
|
+
return wireHandle(bk.makeWire(chainEdges$1(bk, edgeIds), true));
|
|
6977
7085
|
}
|
|
6978
7086
|
function makeFace(bk, wire, planar) {
|
|
6979
7087
|
const h = wire;
|
|
@@ -7170,21 +7278,85 @@ function makeBezierEdge(bk, points) {
|
|
|
7170
7278
|
function makeTangentArc(bk, startPoint, startTangent, endPoint) {
|
|
7171
7279
|
return edgeHandle(bk.makeTangentArc3d(startPoint[0], startPoint[1], startPoint[2], startTangent[0], startTangent[1], startTangent[2], endPoint[0], endPoint[1], endPoint[2]));
|
|
7172
7280
|
}
|
|
7173
|
-
|
|
7281
|
+
/** The X axis occt's `gp_Ax3(P, V)` picks when given only a direction, so a helix starts where occt-wasm's does. */
|
|
7282
|
+
function occtDefaultXDir(a, b, c) {
|
|
7283
|
+
const [aa, ba, ca] = [
|
|
7284
|
+
Math.abs(a),
|
|
7285
|
+
Math.abs(b),
|
|
7286
|
+
Math.abs(c)
|
|
7287
|
+
];
|
|
7288
|
+
let x;
|
|
7289
|
+
if (ba <= aa && ba <= ca) x = aa > ca ? [
|
|
7290
|
+
-c,
|
|
7291
|
+
0,
|
|
7292
|
+
a
|
|
7293
|
+
] : [
|
|
7294
|
+
c,
|
|
7295
|
+
0,
|
|
7296
|
+
-a
|
|
7297
|
+
];
|
|
7298
|
+
else if (aa <= ba && aa <= ca) x = ba > ca ? [
|
|
7299
|
+
0,
|
|
7300
|
+
-c,
|
|
7301
|
+
b
|
|
7302
|
+
] : [
|
|
7303
|
+
0,
|
|
7304
|
+
c,
|
|
7305
|
+
-b
|
|
7306
|
+
];
|
|
7307
|
+
else x = aa > ba ? [
|
|
7308
|
+
-b,
|
|
7309
|
+
a,
|
|
7310
|
+
0
|
|
7311
|
+
] : [
|
|
7312
|
+
b,
|
|
7313
|
+
-a,
|
|
7314
|
+
0
|
|
7315
|
+
];
|
|
7316
|
+
const len = Math.hypot(x[0], x[1], x[2]);
|
|
7317
|
+
return [
|
|
7318
|
+
x[0] / len,
|
|
7319
|
+
x[1] / len,
|
|
7320
|
+
x[2] / len
|
|
7321
|
+
];
|
|
7322
|
+
}
|
|
7323
|
+
function makeHelixWire(bk, pitch, height, radius, center, direction, leftHanded) {
|
|
7174
7324
|
const turns = height / pitch;
|
|
7175
7325
|
const nSamples = Math.max(4, Math.ceil(turns * 16));
|
|
7176
|
-
const cx = center
|
|
7177
|
-
|
|
7178
|
-
|
|
7326
|
+
const [cx, cy, cz] = center ?? [
|
|
7327
|
+
0,
|
|
7328
|
+
0,
|
|
7329
|
+
0
|
|
7330
|
+
];
|
|
7331
|
+
const [dx, dy, dz] = direction ?? [
|
|
7332
|
+
0,
|
|
7333
|
+
0,
|
|
7334
|
+
1
|
|
7335
|
+
];
|
|
7336
|
+
const dLen = Math.hypot(dx, dy, dz);
|
|
7337
|
+
const z = [
|
|
7338
|
+
dx / dLen,
|
|
7339
|
+
dy / dLen,
|
|
7340
|
+
dz / dLen
|
|
7341
|
+
];
|
|
7342
|
+
const x = occtDefaultXDir(z[0], z[1], z[2]);
|
|
7343
|
+
const y = [
|
|
7344
|
+
z[1] * x[2] - z[2] * x[1],
|
|
7345
|
+
z[2] * x[0] - z[0] * x[2],
|
|
7346
|
+
z[0] * x[1] - z[1] * x[0]
|
|
7347
|
+
];
|
|
7179
7348
|
const sign = leftHanded ? -1 : 1;
|
|
7180
7349
|
const points = [];
|
|
7181
7350
|
for (let i = 0; i <= nSamples; i++) {
|
|
7182
7351
|
const t = i / nSamples;
|
|
7183
7352
|
const angle = sign * 2 * Math.PI * turns * t;
|
|
7353
|
+
const u = radius * Math.cos(angle);
|
|
7354
|
+
const v = radius * Math.sin(angle);
|
|
7355
|
+
const h = height * t;
|
|
7184
7356
|
points.push([
|
|
7185
|
-
cx +
|
|
7186
|
-
cy +
|
|
7187
|
-
cz +
|
|
7357
|
+
cx + u * x[0] + v * y[0] + h * z[0],
|
|
7358
|
+
cy + u * x[1] + v * y[1] + h * z[1],
|
|
7359
|
+
cz + u * x[2] + v * y[2] + h * z[2]
|
|
7188
7360
|
]);
|
|
7189
7361
|
}
|
|
7190
7362
|
return makeWire(bk, [interpolatePoints(bk, points)]);
|
|
@@ -7197,10 +7369,110 @@ function makeWireFromMixed(bk, items) {
|
|
|
7197
7369
|
else if (h.type === "wire") for (const childEdgeId of toArray(bk.getWireEdges(h.id))) edgeIds.push(childEdgeId);
|
|
7198
7370
|
}
|
|
7199
7371
|
if (edgeIds.length === 0) throw new Error("brepkit: makeWireFromMixed requires at least one edge");
|
|
7200
|
-
|
|
7372
|
+
const chain = chainEdges$1(bk, edgeIds);
|
|
7373
|
+
return wireHandle(bk.makeWire(chain, chainCloses(bk, chain)));
|
|
7201
7374
|
}
|
|
7202
7375
|
/** Matches the 1e-7 linear tolerance brepkit's makeWire welds vertices within. */
|
|
7203
7376
|
var WIRE_CLOSE_TOLERANCE = 1e-7;
|
|
7377
|
+
/**
|
|
7378
|
+
* The edges in an order where each starts where the one before ends, any edge
|
|
7379
|
+
* running the other way rebuilt to run on. brepkit's makeWire takes each edge
|
|
7380
|
+
* as it runs and a face refuses a wire whose edges do not run end to end, so a
|
|
7381
|
+
* profile closed by its mirror image, whose edges leave from the first half's
|
|
7382
|
+
* start, needs that half turned round. Edges that make no single chain, or
|
|
7383
|
+
* that cannot be rebuilt, come back as given.
|
|
7384
|
+
*/
|
|
7385
|
+
function chainEdges$1(bk, edgeIds) {
|
|
7386
|
+
const [first, ...left] = edgeIds;
|
|
7387
|
+
if (first === void 0 || left.length === 0) return edgeIds;
|
|
7388
|
+
const ends = new Map(left.map((id) => [id, edgeEnds(bk, id)]));
|
|
7389
|
+
let [head, tail] = edgeEnds(bk, first);
|
|
7390
|
+
const chain = [first];
|
|
7391
|
+
while (left.length > 0) {
|
|
7392
|
+
const after = takeLink(bk, left, ends, tail, "start");
|
|
7393
|
+
if (after) {
|
|
7394
|
+
chain.push(after.id);
|
|
7395
|
+
tail = after.free;
|
|
7396
|
+
continue;
|
|
7397
|
+
}
|
|
7398
|
+
const before = takeLink(bk, left, ends, head, "end");
|
|
7399
|
+
if (!before) return edgeIds;
|
|
7400
|
+
chain.unshift(before.id);
|
|
7401
|
+
head = before.free;
|
|
7402
|
+
}
|
|
7403
|
+
return chain;
|
|
7404
|
+
}
|
|
7405
|
+
/**
|
|
7406
|
+
* Take from `left` the first edge with an end at `at`, to join the chain there
|
|
7407
|
+
* by its `side` end; an edge that meets `at` with its other end is rebuilt to
|
|
7408
|
+
* run the other way. Returns the joining edge and the end it leaves free.
|
|
7409
|
+
*/
|
|
7410
|
+
function takeLink(bk, left, ends, at, side) {
|
|
7411
|
+
const touches = (p) => dist3(...p, ...at) < WIRE_CLOSE_TOLERANCE;
|
|
7412
|
+
for (const [i, id] of left.entries()) {
|
|
7413
|
+
const edge = ends.get(id);
|
|
7414
|
+
if (!edge) continue;
|
|
7415
|
+
const [start, end] = edge;
|
|
7416
|
+
const [joins, free] = side === "start" ? [start, end] : [end, start];
|
|
7417
|
+
if (touches(joins)) {
|
|
7418
|
+
left.splice(i, 1);
|
|
7419
|
+
return {
|
|
7420
|
+
id,
|
|
7421
|
+
free
|
|
7422
|
+
};
|
|
7423
|
+
}
|
|
7424
|
+
if (touches(free)) {
|
|
7425
|
+
const turned = reversedEdge(bk, id, start, end);
|
|
7426
|
+
if (turned === void 0) return void 0;
|
|
7427
|
+
left.splice(i, 1);
|
|
7428
|
+
return {
|
|
7429
|
+
id: turned,
|
|
7430
|
+
free: joins
|
|
7431
|
+
};
|
|
7432
|
+
}
|
|
7433
|
+
}
|
|
7434
|
+
}
|
|
7435
|
+
/**
|
|
7436
|
+
* A new edge on the same curve, running from `end` to `start`, or `undefined`
|
|
7437
|
+
* for a curve the adapter cannot rebuild.
|
|
7438
|
+
*/
|
|
7439
|
+
function reversedEdge(bk, id, start, end) {
|
|
7440
|
+
const nurbs = bk.getEdgeNurbsData(id);
|
|
7441
|
+
if (nurbs !== null) return reversedNurbsEdge(bk, nurbs, start, end);
|
|
7442
|
+
const curveType = bk.getEdgeCurveType(id);
|
|
7443
|
+
if (curveType === "LINE") return bk.makeLineEdge(...end, ...start);
|
|
7444
|
+
const frame = conicFrame(bk, id);
|
|
7445
|
+
if (!frame) return void 0;
|
|
7446
|
+
const { center, u, v } = frame;
|
|
7447
|
+
const n = [
|
|
7448
|
+
v[1] * u[2] - v[2] * u[1],
|
|
7449
|
+
v[2] * u[0] - v[0] * u[2],
|
|
7450
|
+
v[0] * u[1] - v[1] * u[0]
|
|
7451
|
+
];
|
|
7452
|
+
const nLen = Math.hypot(...n);
|
|
7453
|
+
const axis = [
|
|
7454
|
+
n[0] / nLen,
|
|
7455
|
+
n[1] / nLen,
|
|
7456
|
+
n[2] / nLen
|
|
7457
|
+
];
|
|
7458
|
+
if (curveType === "CIRCLE") return bk.makeCircleArc3d(...end, ...start, ...center, ...axis);
|
|
7459
|
+
const major = Math.hypot(...u);
|
|
7460
|
+
const ref = [
|
|
7461
|
+
u[0] / major,
|
|
7462
|
+
u[1] / major,
|
|
7463
|
+
u[2] / major
|
|
7464
|
+
];
|
|
7465
|
+
return bk.makeEllipseArc3d(...end, ...start, ...center, ...axis, ...ref, major, Math.hypot(...v));
|
|
7466
|
+
}
|
|
7467
|
+
function reversedNurbsEdge(bk, json, start, end) {
|
|
7468
|
+
const data = JSON.parse(json);
|
|
7469
|
+
const lo = require_bug.wasmIndex(data.knots, 0);
|
|
7470
|
+
const hi = require_bug.wasmIndex(data.knots, data.knots.length - 1);
|
|
7471
|
+
const knots = data.knots.map((k) => lo + hi - k).reverse();
|
|
7472
|
+
const poles = [];
|
|
7473
|
+
for (let i = data.controlPoints.length - 3; i >= 0; i -= 3) poles.push(...data.controlPoints.slice(i, i + 3));
|
|
7474
|
+
return bk.makeNurbsEdge(...end, ...start, data.degree, knots, poles, [...data.weights].reverse());
|
|
7475
|
+
}
|
|
7204
7476
|
function chainCloses(bk, edgeIds) {
|
|
7205
7477
|
const first = bk.getEdgeVertices(require_bug.wasmIndex(edgeIds, 0));
|
|
7206
7478
|
const last = bk.getEdgeVertices(require_bug.wasmIndex(edgeIds, edgeIds.length - 1));
|
|
@@ -7239,15 +7511,7 @@ function makeBoxFromCorners(bk, p1, p2) {
|
|
|
7239
7511
|
return box;
|
|
7240
7512
|
}
|
|
7241
7513
|
function solidFromShell(bk, shell) {
|
|
7242
|
-
|
|
7243
|
-
if (h.type === "solid") return shell;
|
|
7244
|
-
if (h.type === "shell") {
|
|
7245
|
-
try {
|
|
7246
|
-
bk.getSolidFaces(h.id);
|
|
7247
|
-
return solidHandle(h.id);
|
|
7248
|
-
} catch {}
|
|
7249
|
-
return solidHandle(bk.solidFromShell(h.id));
|
|
7250
|
-
}
|
|
7514
|
+
if (shell.type === "solid") return shell;
|
|
7251
7515
|
return solidHandle(bk.solidFromShell(unwrap$1(shell, "shell")));
|
|
7252
7516
|
}
|
|
7253
7517
|
function makeNonPlanarFace(bk, wire) {
|
|
@@ -7734,45 +7998,80 @@ function fillet(bk, shape, edges, radius) {
|
|
|
7734
7998
|
const solidId = unwrapSolidOrThrow(shape, "fillet");
|
|
7735
7999
|
const edgeIds = edges.map((e) => unwrap$1(e, "edge"));
|
|
7736
8000
|
if (typeof radius === "number") return solidHandle(bk.fillet(solidId, edgeIds, radius));
|
|
7737
|
-
const
|
|
7738
|
-
for (const edge of edges) {
|
|
8001
|
+
const laws = edges.map((edge, i) => {
|
|
7739
8002
|
const r = typeof radius === "function" ? radius(edge) : radius;
|
|
7740
8003
|
const [start, end] = Array.isArray(r) ? r : [r, r];
|
|
7741
|
-
|
|
7742
|
-
|
|
8004
|
+
return {
|
|
8005
|
+
edge: require_bug.wasmIndex(edgeIds, i),
|
|
8006
|
+
start,
|
|
8007
|
+
end
|
|
8008
|
+
};
|
|
8009
|
+
});
|
|
8010
|
+
const [first] = laws;
|
|
8011
|
+
if (!first) throw new Error("brepkit: fillet needs at least one edge");
|
|
8012
|
+
if (laws.every((l) => l.start === first.start && l.end === first.start)) return solidHandle(bk.fillet(solidId, edgeIds, first.start));
|
|
8013
|
+
return filletAlongLaws(bk, solidId, laws);
|
|
8014
|
+
}
|
|
8015
|
+
var lawProbes = /* @__PURE__ */ new WeakMap();
|
|
8016
|
+
/**
|
|
8017
|
+
* brepkit-wasm before 4.6.9 cuts a flat bevel along a radius law, and the peer
|
|
8018
|
+
* range still admits those builds. Rounding a 10 mm cube edge from 1 to 2 tells
|
|
8019
|
+
* them apart: a round removes 5.0 mm3 and a bevel 11.7. The probe runs once per
|
|
8020
|
+
* kernel, inside a checkpoint it restores and discards, so it leaves nothing behind.
|
|
8021
|
+
*/
|
|
8022
|
+
function roundsAlongLaws(bk) {
|
|
8023
|
+
const known = lawProbes.get(bk);
|
|
8024
|
+
if (known !== void 0) return known;
|
|
8025
|
+
let rounds;
|
|
8026
|
+
const mark = bk.checkpoint();
|
|
8027
|
+
try {
|
|
8028
|
+
const cube = bk.makeBox(10, 10, 10);
|
|
8029
|
+
const edge = require_bug.wasmIndex(bk.getSolidEdges(cube), 0);
|
|
8030
|
+
const spec = JSON.stringify([{
|
|
8031
|
+
edge,
|
|
8032
|
+
law: "linear",
|
|
8033
|
+
start: 1,
|
|
8034
|
+
end: 2
|
|
8035
|
+
}]);
|
|
8036
|
+
rounds = 1e3 - bk.volume(bk.filletVariable(cube, spec), DEFAULT_DEFLECTION) < 8;
|
|
8037
|
+
} catch {
|
|
8038
|
+
rounds = false;
|
|
8039
|
+
} finally {
|
|
8040
|
+
bk.restore(mark);
|
|
8041
|
+
bk.discardCheckpoint(mark);
|
|
7743
8042
|
}
|
|
7744
|
-
|
|
7745
|
-
|
|
7746
|
-
if (only === void 0) throw new Error("brepkit: fillet needs at least one edge");
|
|
7747
|
-
return solidHandle(bk.fillet(solidId, edgeIds, only));
|
|
8043
|
+
lawProbes.set(bk, rounds);
|
|
8044
|
+
return rounds;
|
|
7748
8045
|
}
|
|
7749
8046
|
/**
|
|
7750
|
-
*
|
|
7751
|
-
*
|
|
7752
|
-
* a chamfer fails on them ("no manifold edges to chamfer"), and a fillet builds
|
|
7753
|
-
* the right body but leaves the input solid corrupt, so that filleting the
|
|
7754
|
-
* input's four vertical cube edges at 2 mm afterwards cuts a flat chamfer.
|
|
8047
|
+
* One filletVariable call for every edge, each along its own constant or
|
|
8048
|
+
* linear law, running from the edge's start vertex to its end.
|
|
7755
8049
|
*/
|
|
7756
|
-
function
|
|
7757
|
-
|
|
8050
|
+
function filletAlongLaws(bk, solidId, laws) {
|
|
8051
|
+
if (!roundsAlongLaws(bk)) throw new require_occtWasmAdapter.UnsupportedKernelOperationError("brepkit: a fillet along a radius law needs brepkit-wasm 4.6.9 or newer");
|
|
8052
|
+
const spec = laws.map(({ edge, start, end }) => ({
|
|
8053
|
+
edge,
|
|
8054
|
+
law: start === end ? "constant" : "linear",
|
|
8055
|
+
start,
|
|
8056
|
+
end
|
|
8057
|
+
}));
|
|
8058
|
+
return solidHandle(bk.filletVariable(solidId, JSON.stringify(spec)));
|
|
7758
8059
|
}
|
|
7759
8060
|
/**
|
|
7760
|
-
* brepkit
|
|
7761
|
-
*
|
|
7762
|
-
*
|
|
7763
|
-
* (the flat chamfer) where fillet removes 77.26. A radius that varies along an
|
|
7764
|
-
* edge is refused rather than built that way.
|
|
8061
|
+
* brepkit takes one distance for every edge of a chamfer call, and a second
|
|
8062
|
+
* call on the first one's result cannot name the input's other edges: it fails
|
|
8063
|
+
* on them ("no manifold edges to chamfer").
|
|
7765
8064
|
*/
|
|
7766
|
-
function
|
|
7767
|
-
return new require_occtWasmAdapter.UnsupportedKernelOperationError(
|
|
8065
|
+
function perEdgeUnsupported(what) {
|
|
8066
|
+
return new require_occtWasmAdapter.UnsupportedKernelOperationError(`brepkit: different ${what} on different edges in one call is not supported`);
|
|
7768
8067
|
}
|
|
7769
8068
|
/** occt's hashCode upper bound, which the kernel-agnostic filletVariable spec hashes edges with. */
|
|
7770
8069
|
var HASH_UPPER_BOUND = 2147483647;
|
|
7771
8070
|
/**
|
|
7772
8071
|
* A variable fillet spec on one edge: `{ edge: hashCode, radii: [{ param, radius }] }`
|
|
7773
|
-
* from variableFillet, or `{ edgeId, startRadius, endRadius }`.
|
|
7774
|
-
*
|
|
7775
|
-
*
|
|
8072
|
+
* from variableFillet, or `{ edgeId, startRadius, endRadius }`. Like occt-wasm, a
|
|
8073
|
+
* profile runs linearly from its first radius to its last, so one of more than two
|
|
8074
|
+
* points is unsupported rather than flattened to a line.
|
|
7776
8075
|
*/
|
|
7777
8076
|
function filletVariable$1(bk, shape, spec) {
|
|
7778
8077
|
const solidId = unwrapSolidOrThrow(shape, "filletVariable");
|
|
@@ -7788,9 +8087,15 @@ function filletVariable$1(bk, shape, spec) {
|
|
|
7788
8087
|
radii = [parsed.startRadius, parsed.endRadius];
|
|
7789
8088
|
} else throw new require_occtWasmAdapter.UnsupportedKernelOperationError("brepkit: filletVariable: unrecognized spec");
|
|
7790
8089
|
if (edgeId === void 0) throw new Error("brepkit: filletVariable: the edge is not an edge of the shape");
|
|
7791
|
-
|
|
7792
|
-
|
|
7793
|
-
|
|
8090
|
+
if (radii.length > 2) throw new require_occtWasmAdapter.UnsupportedKernelOperationError("brepkit: filletVariable supports only a linear (<=2-point) radius profile");
|
|
8091
|
+
const start = require_bug.wasmIndex(radii, 0);
|
|
8092
|
+
const end = require_bug.wasmIndex(radii, radii.length - 1);
|
|
8093
|
+
if (start === end) return solidHandle(bk.fillet(solidId, [edgeId], start));
|
|
8094
|
+
return filletAlongLaws(bk, solidId, [{
|
|
8095
|
+
edge: edgeId,
|
|
8096
|
+
start,
|
|
8097
|
+
end
|
|
8098
|
+
}]);
|
|
7794
8099
|
}
|
|
7795
8100
|
/**
|
|
7796
8101
|
* A symmetric chamfer for two equal distances, brepkit's two-distance chamfer
|
|
@@ -7941,10 +8246,13 @@ function offsetWire2D(bk, wire, offsetVal, joinType) {
|
|
|
7941
8246
|
return wireHandle(bk.makePolygonWire(coords3d));
|
|
7942
8247
|
}
|
|
7943
8248
|
function simplify$1(bk, shape) {
|
|
7944
|
-
if (shape.type === "solid")
|
|
7945
|
-
bk
|
|
7946
|
-
|
|
7947
|
-
|
|
8249
|
+
if (shape.type === "solid") {
|
|
8250
|
+
forgetSolidPieces(bk, unwrap$1(shape));
|
|
8251
|
+
try {
|
|
8252
|
+
bk.healSolid(unwrap$1(shape));
|
|
8253
|
+
} catch (e) {
|
|
8254
|
+
console.warn("brepkit: healing failed in simplify:", e);
|
|
8255
|
+
}
|
|
7948
8256
|
}
|
|
7949
8257
|
return shape;
|
|
7950
8258
|
}
|
|
@@ -10190,7 +10498,7 @@ function area$1(bk, shape) {
|
|
|
10190
10498
|
const h = shape;
|
|
10191
10499
|
if (h.type === "face") return bk.faceArea(unwrap$1(shape), DEFAULT_DEFLECTION);
|
|
10192
10500
|
if (h.type === "solid") return bk.surfaceArea(unwrap$1(shape), DEFAULT_DEFLECTION);
|
|
10193
|
-
if (h.type === "compound") {
|
|
10501
|
+
if (h.type === "compound" || h.type === "shell") {
|
|
10194
10502
|
const faces = iterShapes$1(bk, shape, "face");
|
|
10195
10503
|
let total = 0;
|
|
10196
10504
|
for (const face of faces) total += bk.faceArea(unwrap$1(face), DEFAULT_DEFLECTION);
|
|
@@ -10764,12 +11072,65 @@ function trySmoothPipeShell(bk, faceId, spine) {
|
|
|
10764
11072
|
return;
|
|
10765
11073
|
}
|
|
10766
11074
|
}
|
|
11075
|
+
/**
|
|
11076
|
+
* The curve a guided sweep runs along: one line, or one edge brepkit stores
|
|
11077
|
+
* as NURBS. brepkit gives no NURBS for a circle or an ellipse, and reading one
|
|
11078
|
+
* by its end points would sweep along the chord.
|
|
11079
|
+
*/
|
|
11080
|
+
function guideCurve(bk, shape, role) {
|
|
11081
|
+
const edges = shape.type === "edge" ? [shape] : iterShapes$1(bk, shape, "edge");
|
|
11082
|
+
const [edge] = edges;
|
|
11083
|
+
if (edges.length !== 1 || !edge) throw new require_occtWasmAdapter.UnsupportedKernelOperationError(`brepkit: a guided sweep takes a single-edge ${role}, got ${edges.length} edges`);
|
|
11084
|
+
const edgeId = unwrap$1(edge, "edge");
|
|
11085
|
+
const curveType = bk.getEdgeCurveType(edgeId);
|
|
11086
|
+
if (curveType !== "LINE" && bk.getEdgeNurbsData(edgeId) === null) throw new require_occtWasmAdapter.UnsupportedKernelOperationError(`brepkit: a guided sweep takes a line or NURBS ${role}, got ${curveType}`);
|
|
11087
|
+
const data = extractNurbsFromEdge(bk, edge);
|
|
11088
|
+
if (!data) throw new Error(`brepkit: guided sweep could not read the ${role}`);
|
|
11089
|
+
return data;
|
|
11090
|
+
}
|
|
11091
|
+
/**
|
|
11092
|
+
* brepkit places a guided sweep's sections at twice the spine's control points
|
|
11093
|
+
* (at least 4) and rules flat between them, so a straight spine twists through
|
|
11094
|
+
* 4 segments whatever the guide does: a square turned 90° comes out 2.5% light.
|
|
11095
|
+
* Splitting a straight spine into twice as many collinear spans as the guide
|
|
11096
|
+
* has control points samples the twist more finely than the guide is drawn.
|
|
11097
|
+
*/
|
|
11098
|
+
function densifyStraightSpine(path, spans) {
|
|
11099
|
+
if (path.degree !== 1 || path.controlPoints.length !== 6 || spans <= 1) return path;
|
|
11100
|
+
const start = require_bug.vec3At(path.controlPoints, 0);
|
|
11101
|
+
const end = require_bug.vec3At(path.controlPoints, 3);
|
|
11102
|
+
const controlPoints = [];
|
|
11103
|
+
const interior = [];
|
|
11104
|
+
for (let i = 0; i <= spans; i++) {
|
|
11105
|
+
const t = i / spans;
|
|
11106
|
+
controlPoints.push(...start.map((s, k) => s + (require_bug.wasmIndex(end, k) - s) * t));
|
|
11107
|
+
if (i > 0 && i < spans) interior.push(t);
|
|
11108
|
+
}
|
|
11109
|
+
return {
|
|
11110
|
+
degree: 1,
|
|
11111
|
+
knots: [
|
|
11112
|
+
0,
|
|
11113
|
+
0,
|
|
11114
|
+
...interior,
|
|
11115
|
+
1,
|
|
11116
|
+
1
|
|
11117
|
+
],
|
|
11118
|
+
controlPoints,
|
|
11119
|
+
weights: new Array(spans + 1).fill(1)
|
|
11120
|
+
};
|
|
11121
|
+
}
|
|
11122
|
+
function guidedPipeShell(bk, faceId, spine, auxiliary) {
|
|
11123
|
+
const aux = guideCurve(bk, auxiliary, "auxiliary spine");
|
|
11124
|
+
const path = densifyStraightSpine(guideCurve(bk, spine, "spine"), 2 * (aux.controlPoints.length / 3));
|
|
11125
|
+
return solidHandle(bk.guidedSweep(faceId, path.degree, path.knots, path.controlPoints, path.weights, aux.degree, aux.knots, aux.controlPoints, aux.weights));
|
|
11126
|
+
}
|
|
10767
11127
|
function sweepPipeShell(bk, profile, spine, options) {
|
|
10768
|
-
if (options?.["auxiliary"] !== void 0) throw new require_occtWasmAdapter.UnsupportedKernelOperationError("brepkit: sweepPipeShell has no auxiliary spine (twist or guided sweep)");
|
|
10769
11128
|
if (options?.["law"] !== void 0) throw new require_occtWasmAdapter.UnsupportedKernelOperationError("brepkit: sweepPipeShell has no scaling law");
|
|
10770
11129
|
const profileHandle = profile;
|
|
10771
11130
|
const faceId = profileHandle.type === "wire" ? bk.makeFaceFromWire(profileHandle.id) : unwrap$1(profile, "face");
|
|
10772
11131
|
const shellMode = !!(options && options["shellMode"]);
|
|
11132
|
+
const auxiliary = options?.["auxiliary"];
|
|
11133
|
+
if (auxiliary !== void 0) return wrapPipeShellResult(guidedPipeShell(bk, faceId, spine, auxiliary), profile, shellMode);
|
|
10773
11134
|
const transitionMode = options?.["transitionMode"];
|
|
10774
11135
|
const contactMode = transitionMode ? mapStringTransitionMode(transitionMode) : void 0;
|
|
10775
11136
|
if (contactMode) {
|
|
@@ -10867,11 +11228,18 @@ function makeSweepOps$1(bk) {
|
|
|
10867
11228
|
function makeCoreOps$1(bk) {
|
|
10868
11229
|
return {
|
|
10869
11230
|
dispose: () => {},
|
|
10870
|
-
executeBatch: (json) =>
|
|
11231
|
+
executeBatch: (json) => {
|
|
11232
|
+
try {
|
|
11233
|
+
return bk.executeBatch(json);
|
|
11234
|
+
} finally {
|
|
11235
|
+
forgetSolidPieces(bk);
|
|
11236
|
+
}
|
|
11237
|
+
},
|
|
10871
11238
|
checkpoint: () => bk.checkpoint(),
|
|
10872
11239
|
checkpointCount: () => bk.checkpointCount(),
|
|
10873
11240
|
restoreCheckpoint: (cp) => {
|
|
10874
11241
|
bk.restore(cp);
|
|
11242
|
+
forgetSolidPieces(bk);
|
|
10875
11243
|
},
|
|
10876
11244
|
discardCheckpoint: (cp) => {
|
|
10877
11245
|
bk.discardCheckpoint(cp);
|
|
@@ -17235,7 +17603,10 @@ function createBorrowedHandle(ocShape) {
|
|
|
17235
17603
|
* frees *every* slot allocated after the checkpoint, so a live shape handle in
|
|
17236
17604
|
* the return value would dangle. Use for data-returning batch analysis over many
|
|
17237
17605
|
* bodies; never to wrap a shape builder. Inputs allocated before the call are
|
|
17238
|
-
* untouched (restore only frees from the mark forward)
|
|
17606
|
+
* untouched (restore only frees from the mark forward), but `fn` must not query
|
|
17607
|
+
* their cached topology (`getFaces`, `getSolids`, adjacency): the cache keeps the
|
|
17608
|
+
* sub-shape handles it allocates, and the restore would leave it holding freed
|
|
17609
|
+
* slots.
|
|
17239
17610
|
*
|
|
17240
17611
|
* No-op wrapper on kernels without arena checkpoints (occt/manifold): `fn` runs
|
|
17241
17612
|
* directly and those kernels' own disposal applies.
|