brepjs 8.0.0 → 8.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/dist/2d/blueprints/booleanHelpers.d.ts +32 -0
  2. package/dist/2d/blueprints/booleanHelpers.d.ts.map +1 -0
  3. package/dist/2d/blueprints/booleanOperations.d.ts +5 -3
  4. package/dist/2d/blueprints/booleanOperations.d.ts.map +1 -1
  5. package/dist/2d/blueprints/intersectionSegments.d.ts +12 -0
  6. package/dist/2d/blueprints/intersectionSegments.d.ts.map +1 -0
  7. package/dist/2d/blueprints/segmentAssembly.d.ts +31 -0
  8. package/dist/2d/blueprints/segmentAssembly.d.ts.map +1 -0
  9. package/dist/2d.cjs +2 -2
  10. package/dist/2d.js +8 -8
  11. package/dist/{Blueprint-D3JfGJTz.js → Blueprint-B9fhnpFp.js} +117 -30
  12. package/dist/{Blueprint-CVctc41Z.cjs → Blueprint-VGbo3izk.cjs} +111 -24
  13. package/dist/{boolean2D-BdZATaHs.cjs → boolean2D-B1XrGVgx.cjs} +426 -345
  14. package/dist/{boolean2D-hOw5Qay5.js → boolean2D-_WiqPxWZ.js} +391 -310
  15. package/dist/{booleanFns-BBSVKhL2.cjs → booleanFns-BxW-N3rP.cjs} +12 -16
  16. package/dist/{booleanFns-CqehfzcK.js → booleanFns-CkccZ7UL.js} +14 -18
  17. package/dist/brepjs.cjs +133 -62
  18. package/dist/brepjs.js +290 -217
  19. package/dist/{cast-DQaUibmm.js → cast-C4Ff_1Qe.js} +2 -2
  20. package/dist/{cast-DkB0GKmQ.cjs → cast-DIiyxDLo.cjs} +2 -2
  21. package/dist/core/disposal.d.ts +1 -1
  22. package/dist/core/disposal.d.ts.map +1 -1
  23. package/dist/core.cjs +3 -3
  24. package/dist/core.js +3 -3
  25. package/dist/cornerFinder-BndBNtJE.cjs +58 -0
  26. package/dist/cornerFinder-DzGzfiqb.js +59 -0
  27. package/dist/curveBuilders-BUoFO1UG.cjs +196 -0
  28. package/dist/curveBuilders-CBlIWlbU.js +197 -0
  29. package/dist/{curveFns-BilyYL_s.cjs → curveFns-BrJDkaWi.cjs} +31 -44
  30. package/dist/{curveFns-CdVE4da7.js → curveFns-BshHA9Ys.js} +31 -44
  31. package/dist/{drawFns-921SkhDL.js → drawFns-Btmlh_Oz.js} +13 -14
  32. package/dist/{drawFns-CUyx50gi.cjs → drawFns-D2eDcf4k.cjs} +58 -59
  33. package/dist/{faceFns-DHu-2JpA.js → faceFns-DDzCECn3.js} +3 -3
  34. package/dist/{faceFns-BwK7FP7N.cjs → faceFns-NDRFeekj.cjs} +3 -3
  35. package/dist/helpers-Ck8GJ58k.cjs +203 -0
  36. package/dist/helpers-jku2V1DY.js +204 -0
  37. package/dist/io.cjs +4 -4
  38. package/dist/io.js +4 -4
  39. package/dist/kernel/occtAdapter.d.ts +1 -0
  40. package/dist/kernel/occtAdapter.d.ts.map +1 -1
  41. package/dist/kernel/sweepOps.d.ts +8 -0
  42. package/dist/kernel/sweepOps.d.ts.map +1 -1
  43. package/dist/kernel/types.d.ts +1 -0
  44. package/dist/kernel/types.d.ts.map +1 -1
  45. package/dist/loft-Bk9EM0gZ.js +373 -0
  46. package/dist/loft-DJXwxV_L.cjs +372 -0
  47. package/dist/{measurement-C5JGCuUP.js → measurement-DlXaTzKc.js} +3 -3
  48. package/dist/{measurement-fxm_pW7x.cjs → measurement-LcGh4wV0.cjs} +3 -3
  49. package/dist/measurement.cjs +1 -1
  50. package/dist/measurement.js +1 -1
  51. package/dist/{meshFns-AqAjTTVl.js → meshFns-Djzdn-CS.js} +1 -1
  52. package/dist/{meshFns-BhrZGi6w.cjs → meshFns-c8lDKfYy.cjs} +1 -1
  53. package/dist/{occtBoundary-du8_ex-p.cjs → occtBoundary-6kQSl3cF.cjs} +21 -0
  54. package/dist/{occtBoundary-CwegMzqc.js → occtBoundary-CqXvDhZY.js} +26 -5
  55. package/dist/operations/extrude.d.ts.map +1 -1
  56. package/dist/operations/extrudeFns.d.ts.map +1 -1
  57. package/dist/operations/extrudeUtils.d.ts +17 -0
  58. package/dist/operations/extrudeUtils.d.ts.map +1 -1
  59. package/dist/{operations-C1rWoba2.js → operations-CrQlFDHc.js} +30 -7
  60. package/dist/{operations-BP1wVDw0.cjs → operations-Do-WZGXc.cjs} +30 -7
  61. package/dist/operations.cjs +2 -2
  62. package/dist/operations.js +4 -4
  63. package/dist/query/cornerFinder.d.ts +48 -0
  64. package/dist/query/cornerFinder.d.ts.map +1 -0
  65. package/dist/query/directionUtils.d.ts +6 -0
  66. package/dist/query/directionUtils.d.ts.map +1 -0
  67. package/dist/query/edgeFinder.d.ts +15 -0
  68. package/dist/query/edgeFinder.d.ts.map +1 -0
  69. package/dist/query/faceFinder.d.ts +15 -0
  70. package/dist/query/faceFinder.d.ts.map +1 -0
  71. package/dist/query/finderCore.d.ts +35 -0
  72. package/dist/query/finderCore.d.ts.map +1 -0
  73. package/dist/query/finderFns.d.ts +21 -106
  74. package/dist/query/finderFns.d.ts.map +1 -1
  75. package/dist/query/shapeDistanceFilter.d.ts +11 -0
  76. package/dist/query/shapeDistanceFilter.d.ts.map +1 -0
  77. package/dist/query/vertexFinder.d.ts +16 -0
  78. package/dist/query/vertexFinder.d.ts.map +1 -0
  79. package/dist/query/wireFinder.d.ts +10 -0
  80. package/dist/query/wireFinder.d.ts.map +1 -0
  81. package/dist/query.cjs +42 -5
  82. package/dist/query.js +40 -2
  83. package/dist/{shapeFns-BrF97sKt.js → shapeFns-DQtpzndX.js} +17 -18
  84. package/dist/{shapeFns-BvOndshS.cjs → shapeFns-cN4qGpbO.cjs} +6 -7
  85. package/dist/{shapeTypes-DKhwEnUM.cjs → shapeTypes-BJ3Hmskg.cjs} +24 -20
  86. package/dist/{shapeTypes-BlSElW8z.js → shapeTypes-C9sUsmEW.js} +32 -28
  87. package/dist/sketching/Sketcher.d.ts.map +1 -1
  88. package/dist/sketching/Sketcher2d.d.ts +12 -4
  89. package/dist/sketching/Sketcher2d.d.ts.map +1 -1
  90. package/dist/sketching/ellipseUtils.d.ts +29 -0
  91. package/dist/sketching/ellipseUtils.d.ts.map +1 -0
  92. package/dist/sketching.cjs +2 -2
  93. package/dist/sketching.js +2 -2
  94. package/dist/topology/booleanFns.d.ts.map +1 -1
  95. package/dist/topology/curveBuilders.d.ts +75 -0
  96. package/dist/topology/curveBuilders.d.ts.map +1 -0
  97. package/dist/topology/curveFns.d.ts.map +1 -1
  98. package/dist/topology/primitiveFns.d.ts.map +1 -1
  99. package/dist/topology/shapeFns.d.ts.map +1 -1
  100. package/dist/topology/shapeHelpers.d.ts +6 -173
  101. package/dist/topology/shapeHelpers.d.ts.map +1 -1
  102. package/dist/topology/shapeUtils.d.ts +13 -0
  103. package/dist/topology/shapeUtils.d.ts.map +1 -0
  104. package/dist/topology/solidBuilders.d.ts +70 -0
  105. package/dist/topology/solidBuilders.d.ts.map +1 -0
  106. package/dist/topology/surfaceBuilders.d.ts +35 -0
  107. package/dist/topology/surfaceBuilders.d.ts.map +1 -0
  108. package/dist/topology/wrapperFns.d.ts +1 -0
  109. package/dist/topology/wrapperFns.d.ts.map +1 -1
  110. package/dist/{topology-tFzqSrGH.js → topology-CtfUZwLR.js} +8 -8
  111. package/dist/{topology-CIooytHH.cjs → topology-DXq8dLsi.cjs} +8 -8
  112. package/dist/topology.cjs +7 -7
  113. package/dist/topology.js +31 -31
  114. package/dist/{vectors-CBuaMeZv.js → vectors-BVgXsYWl.js} +1 -1
  115. package/dist/{vectors-ChWEZPwy.cjs → vectors-DK2hEKcI.cjs} +1 -1
  116. package/dist/vectors.cjs +2 -2
  117. package/dist/vectors.js +2 -2
  118. package/package.json +1 -1
  119. package/dist/loft-BzWFokmC.cjs +0 -178
  120. package/dist/loft-CtG5nMq5.js +0 -179
  121. package/dist/query-V6nV-VfL.js +0 -396
  122. package/dist/query-hMSmOWJP.cjs +0 -395
  123. package/dist/shapeHelpers-B2SXz1p4.cjs +0 -488
  124. package/dist/shapeHelpers-BcoZf2N9.js +0 -489
@@ -1,179 +0,0 @@
1
- import { g as getKernel, a as toVec3, m as makeOcAx1 } from "./occtBoundary-CwegMzqc.js";
2
- import { D as DEG2RAD, v as vecAdd, g as vecLength } from "./vecOps-ZDdZWbwT.js";
3
- import { d as downcast, c as cast, a as isShape3D, b as isWire } from "./cast-DQaUibmm.js";
4
- import { e as err, x as validationError, l as ok, u as unwrap, a as andThen, o as occtError, p as typeCastError } from "./errors-wGhcJMpB.js";
5
- import { n as gcWithScope, o as localGC, p as createSolid } from "./shapeTypes-BlSElW8z.js";
6
- import { m as makeLine, a as assembleWire, b as makeHelix, c as makeVertex } from "./shapeHelpers-BcoZf2N9.js";
7
- function buildLawFromProfile(extrusionLength, { profile, endFactor = 1 }) {
8
- const oc = getKernel().oc;
9
- const r = gcWithScope();
10
- let law;
11
- if (profile === "s-curve") {
12
- law = r(new oc.Law_S());
13
- law.Set_1(0, 1, extrusionLength, endFactor);
14
- } else if (profile === "linear") {
15
- law = r(new oc.Law_Linear());
16
- law.Set(0, 1, extrusionLength, endFactor);
17
- } else {
18
- return err(
19
- validationError("UNSUPPORTED_PROFILE", `Unsupported extrusion profile: ${String(profile)}`)
20
- );
21
- }
22
- return ok(law.Trim(0, extrusionLength, 1e-6));
23
- }
24
- const basicFaceExtrusion = (face, extrusionVec) => {
25
- const oc = getKernel().oc;
26
- const [r, gc] = localGC();
27
- const vec = toVec3(extrusionVec);
28
- const ocVec = r(new oc.gp_Vec_4(vec[0], vec[1], vec[2]));
29
- const solidBuilder = r(new oc.BRepPrimAPI_MakePrism_1(face.wrapped, ocVec, false, true));
30
- const solid = createSolid(unwrap(downcast(solidBuilder.Shape())));
31
- gc();
32
- return solid;
33
- };
34
- const revolution = (face, center = [0, 0, 0], direction = [0, 0, 1], angle = 360) => {
35
- const oc = getKernel().oc;
36
- const [r, gc] = localGC();
37
- const centerVec = toVec3(center);
38
- const directionVec = toVec3(direction);
39
- const ax = r(makeOcAx1(centerVec, directionVec));
40
- const revolBuilder = r(new oc.BRepPrimAPI_MakeRevol_1(face.wrapped, ax, angle * DEG2RAD, false));
41
- const result = andThen(cast(revolBuilder.Shape()), (shape) => {
42
- if (!isShape3D(shape))
43
- return err(typeCastError("REVOLUTION_NOT_3D", "Revolution did not produce a 3D shape"));
44
- return ok(shape);
45
- });
46
- gc();
47
- return result;
48
- };
49
- function genericSweep(wire, spine, {
50
- frenet = false,
51
- auxiliarySpine,
52
- law = null,
53
- transitionMode = "right",
54
- withContact,
55
- support,
56
- forceProfileSpineOthogonality
57
- } = {}, shellMode = false) {
58
- const oc = getKernel().oc;
59
- const [r, gc] = localGC();
60
- const withCorrection = transitionMode === "round" ? true : !!forceProfileSpineOthogonality;
61
- const sweepBuilder = r(new oc.BRepOffsetAPI_MakePipeShell(spine.wrapped));
62
- {
63
- const mode = {
64
- transformed: oc.BRepBuilderAPI_TransitionMode.BRepBuilderAPI_Transformed,
65
- round: oc.BRepBuilderAPI_TransitionMode.BRepBuilderAPI_RoundCorner,
66
- right: oc.BRepBuilderAPI_TransitionMode.BRepBuilderAPI_RightCorner
67
- }[transitionMode];
68
- if (mode) sweepBuilder.SetTransitionMode(mode);
69
- }
70
- if (support) {
71
- sweepBuilder.SetMode_4(support);
72
- } else if (frenet) {
73
- sweepBuilder.SetMode_1(frenet);
74
- }
75
- if (auxiliarySpine) {
76
- sweepBuilder.SetMode_5(
77
- auxiliarySpine.wrapped,
78
- false,
79
- oc.BRepFill_TypeOfContact.BRepFill_NoContact
80
- );
81
- }
82
- if (!law) sweepBuilder.Add_1(wire.wrapped, !!withContact, withCorrection);
83
- else sweepBuilder.SetLaw_1(wire.wrapped, law, !!withContact, withCorrection);
84
- const progress = r(new oc.Message_ProgressRange_1());
85
- sweepBuilder.Build(progress);
86
- if (!sweepBuilder.IsDone()) {
87
- gc();
88
- return err(occtError("SWEEP_FAILED", "Sweep operation failed"));
89
- }
90
- if (!shellMode) {
91
- sweepBuilder.MakeSolid();
92
- }
93
- const shape = unwrap(cast(sweepBuilder.Shape()));
94
- if (!isShape3D(shape)) {
95
- gc();
96
- return err(typeCastError("SWEEP_NOT_3D", "Sweep did not produce a 3D shape"));
97
- }
98
- if (shellMode) {
99
- const startWire = unwrap(cast(sweepBuilder.FirstShape()));
100
- const endWire = unwrap(cast(sweepBuilder.LastShape()));
101
- if (!isWire(startWire)) {
102
- gc();
103
- return err(typeCastError("SWEEP_START_NOT_WIRE", "Sweep did not produce a start Wire"));
104
- }
105
- if (!isWire(endWire)) {
106
- gc();
107
- return err(typeCastError("SWEEP_END_NOT_WIRE", "Sweep did not produce an end Wire"));
108
- }
109
- gc();
110
- return ok([shape, startWire, endWire]);
111
- }
112
- gc();
113
- return ok(shape);
114
- }
115
- function complexExtrude(wire, center, normal, profileShape, shellMode = false) {
116
- const [r, gc] = localGC();
117
- const centerVec = toVec3(center);
118
- const normalVec = toVec3(normal);
119
- const endVec = vecAdd(centerVec, normalVec);
120
- const mainSpineEdge = r(makeLine(centerVec, endVec));
121
- const spine = r(unwrap(assembleWire([mainSpineEdge])));
122
- const law = profileShape ? r(unwrap(buildLawFromProfile(vecLength(normalVec), profileShape))) : null;
123
- const result = shellMode ? genericSweep(wire, spine, { law }, shellMode) : genericSweep(wire, spine, { law }, shellMode);
124
- gc();
125
- return result;
126
- }
127
- function twistExtrude(wire, angleDegrees, center, normal, profileShape, shellMode = false) {
128
- const [r, gc] = localGC();
129
- const centerVec = toVec3(center);
130
- const normalVec = toVec3(normal);
131
- const endVec = vecAdd(centerVec, normalVec);
132
- const mainSpineEdge = r(makeLine(centerVec, endVec));
133
- const spine = r(unwrap(assembleWire([mainSpineEdge])));
134
- const extrusionLength = vecLength(normalVec);
135
- const pitch = 360 / angleDegrees * extrusionLength;
136
- const radius = 1;
137
- const auxiliarySpine = r(makeHelix(pitch, extrusionLength, radius, centerVec, normalVec));
138
- const law = profileShape ? r(unwrap(buildLawFromProfile(extrusionLength, profileShape))) : null;
139
- const result = shellMode ? genericSweep(wire, spine, { auxiliarySpine, law }, shellMode) : genericSweep(wire, spine, { auxiliarySpine, law }, shellMode);
140
- gc();
141
- return result;
142
- }
143
- const loft = (wires, { ruled = true, startPoint, endPoint } = {}, returnShell = false) => {
144
- if (wires.length === 0 && !startPoint && !endPoint) {
145
- return err(validationError("LOFT_EMPTY", "Loft requires at least one wire or start/end point"));
146
- }
147
- const oc = getKernel().oc;
148
- const [r, gc] = localGC();
149
- const loftBuilder = r(new oc.BRepOffsetAPI_ThruSections(!returnShell, ruled, 1e-6));
150
- if (startPoint) {
151
- loftBuilder.AddVertex(r(makeVertex(toVec3(startPoint))).wrapped);
152
- }
153
- wires.forEach((w) => loftBuilder.AddWire(w.wrapped));
154
- if (endPoint) {
155
- loftBuilder.AddVertex(r(makeVertex(toVec3(endPoint))).wrapped);
156
- }
157
- const progress = r(new oc.Message_ProgressRange_1());
158
- loftBuilder.Build(progress);
159
- if (!loftBuilder.IsDone()) {
160
- gc();
161
- return err(occtError("LOFT_FAILED", "Loft operation failed"));
162
- }
163
- const result = andThen(cast(loftBuilder.Shape()), (shape) => {
164
- if (!isShape3D(shape))
165
- return err(typeCastError("LOFT_NOT_3D", "Loft did not produce a 3D shape"));
166
- return ok(shape);
167
- });
168
- gc();
169
- return result;
170
- };
171
- export {
172
- buildLawFromProfile as a,
173
- basicFaceExtrusion as b,
174
- complexExtrude as c,
175
- genericSweep as g,
176
- loft as l,
177
- revolution as r,
178
- twistExtrude as t
179
- };
@@ -1,396 +0,0 @@
1
- import { g as getKernel, d as toOcPnt } from "./occtBoundary-CwegMzqc.js";
2
- import { c as castShape, n as gcWithScope, e as isFace } from "./shapeTypes-BlSElW8z.js";
3
- import { j as vecNormalize, c as vecDistance, d as vecDot, D as DEG2RAD } from "./vecOps-ZDdZWbwT.js";
4
- import { bug } from "./result.js";
5
- import { i as iterTopo, d as downcast } from "./cast-DQaUibmm.js";
6
- import { v as vertexPosition, k as getHashCode, n as isSameShape } from "./shapeFns-BrF97sKt.js";
7
- import { g as getSurfaceType, n as normalAt } from "./faceFns-DHu-2JpA.js";
8
- import { m as measureArea } from "./measurement-C5JGCuUP.js";
9
- import { l as getCurveType, f as curveLength, c as curveIsClosed } from "./curveFns-CdVE4da7.js";
10
- import { e as err, q as queryError, l as ok, u as unwrap } from "./errors-wGhcJMpB.js";
11
- const PRECISION_INTERSECTION = 1e-9;
12
- const PRECISION_OFFSET = 1e-8;
13
- const PRECISION_POINT = 1e-6;
14
- const samePoint = ([x0, y0], [x1, y1], precision = PRECISION_POINT) => {
15
- return Math.abs(x0 - x1) <= precision && Math.abs(y0 - y1) <= precision;
16
- };
17
- const add2d = ([x0, y0], [x1, y1]) => {
18
- return [x0 + x1, y0 + y1];
19
- };
20
- const subtract2d = ([x0, y0], [x1, y1]) => {
21
- return [x0 - x1, y0 - y1];
22
- };
23
- const scalarMultiply2d = ([x0, y0], scalar) => {
24
- return [x0 * scalar, y0 * scalar];
25
- };
26
- const distance2d = ([x0, y0], [x1, y1] = [0, 0]) => {
27
- return Math.sqrt((x0 - x1) ** 2 + (y0 - y1) ** 2);
28
- };
29
- const squareDistance2d = ([x0, y0], [x1, y1] = [0, 0]) => {
30
- return (x0 - x1) ** 2 + (y0 - y1) ** 2;
31
- };
32
- function crossProduct2d([x0, y0], [x1, y1]) {
33
- return x0 * y1 - y0 * x1;
34
- }
35
- const angle2d = ([x0, y0], [x1, y1] = [0, 0]) => {
36
- return Math.atan2(y1 * x0 - y0 * x1, x0 * x1 + y0 * y1);
37
- };
38
- const polarAngle2d = ([x0, y0], [x1, y1] = [0, 0]) => {
39
- return Math.atan2(y1 - y0, x1 - x0);
40
- };
41
- const normalize2d = ([x0, y0]) => {
42
- const l = distance2d([x0, y0]);
43
- if (l < 1e-12) {
44
- bug("normalize2d", "Cannot normalize zero-length vector");
45
- }
46
- return [x0 / l, y0 / l];
47
- };
48
- const rotate2d = (point, angle, center = [0, 0]) => {
49
- const [px0, py0] = point;
50
- const [cx, cy] = center;
51
- const px = px0 - cx;
52
- const py = py0 - cy;
53
- const sinA = Math.sin(angle);
54
- const cosA = Math.cos(angle);
55
- const xnew = px * cosA - py * sinA;
56
- const ynew = px * sinA + py * cosA;
57
- return [xnew + cx, ynew + cy];
58
- };
59
- const polarToCartesian = (r, theta) => {
60
- const x = Math.cos(theta) * r;
61
- const y = Math.sin(theta) * r;
62
- return [x, y];
63
- };
64
- const cartesianToPolar = ([x, y]) => {
65
- const r = distance2d([x, y]);
66
- const theta = Math.atan2(y, x);
67
- return [r, theta];
68
- };
69
- function createFinder(topoKind, filters, getNormal) {
70
- const withFilter = (pred) => createFinder(topoKind, [...filters, pred]);
71
- const shouldKeep = (element) => filters.every((f) => f(element));
72
- const extractElements = (shape) => {
73
- const result = [];
74
- for (const raw of iterTopo(shape.wrapped, topoKind)) {
75
- const element = castShape(unwrap(downcast(raw)));
76
- if (shouldKeep(element)) {
77
- result.push(element);
78
- }
79
- }
80
- return result;
81
- };
82
- const finder = {
83
- _filters: filters,
84
- _topoKind: topoKind,
85
- when: (pred) => withFilter(pred),
86
- inList: (elements) => {
87
- const hashSet = /* @__PURE__ */ new Map();
88
- for (const e of elements) {
89
- const h = getHashCode(e);
90
- const bucket = hashSet.get(h);
91
- if (bucket) bucket.push(e);
92
- else hashSet.set(h, [e]);
93
- }
94
- return withFilter((el) => {
95
- const bucket = hashSet.get(getHashCode(el));
96
- return !!bucket && bucket.some((e) => isSameShape(e, el));
97
- });
98
- },
99
- not: (builderFn) => {
100
- const inner = builderFn(createFinder(topoKind, []));
101
- return withFilter((el) => !inner.shouldKeep(el));
102
- },
103
- either: (fns) => {
104
- const builtFinders = fns.map((fn) => fn(createFinder(topoKind, [])));
105
- return withFilter((el) => builtFinders.some((f) => f.shouldKeep(el)));
106
- },
107
- findAll: (shape) => extractElements(shape),
108
- findUnique: (shape) => {
109
- const elements = extractElements(shape);
110
- if (elements.length !== 1) {
111
- return err(
112
- queryError(
113
- "FINDER_NOT_UNIQUE",
114
- `Finder expected a unique match but found ${elements.length} element(s)`
115
- )
116
- );
117
- }
118
- return ok(elements[0]);
119
- },
120
- shouldKeep
121
- };
122
- return finder;
123
- }
124
- const DIRECTIONS = {
125
- X: [1, 0, 0],
126
- Y: [0, 1, 0],
127
- Z: [0, 0, 1]
128
- };
129
- function resolveDir(dir) {
130
- if (typeof dir === "string") return DIRECTIONS[dir] ?? [0, 0, 1];
131
- return dir;
132
- }
133
- function edgeFinder() {
134
- return createEdgeFinder([]);
135
- }
136
- function createEdgeFinder(filters) {
137
- const base = createFinder("edge", filters);
138
- const withFilter = (pred) => createEdgeFinder([...filters, pred]);
139
- return {
140
- ...base,
141
- when: (pred) => createEdgeFinder([...filters, pred]),
142
- inList: (elements) => createEdgeFinder([...base.inList(elements)._filters]),
143
- not: (fn) => createEdgeFinder([...base.not(fn)._filters]),
144
- either: (fns) => createEdgeFinder([
145
- ...base.either(fns)._filters
146
- ]),
147
- inDirection: (dir = "Z", angle = 0) => {
148
- const d = vecNormalize(resolveDir(dir));
149
- return withFilter((edge) => {
150
- const oc = getKernel().oc;
151
- const r = gcWithScope();
152
- const adaptor = r(new oc.BRepAdaptor_Curve_2(edge.wrapped));
153
- const tmpPnt = r(new oc.gp_Pnt_1());
154
- const tmpVec = r(new oc.gp_Vec_1());
155
- const mid = (Number(adaptor.FirstParameter()) + Number(adaptor.LastParameter())) / 2;
156
- adaptor.D1(mid, tmpPnt, tmpVec);
157
- const tangent = vecNormalize([tmpVec.X(), tmpVec.Y(), tmpVec.Z()]);
158
- const ang = Math.acos(Math.min(1, Math.abs(vecDot(tangent, d))));
159
- return Math.abs(ang - DEG2RAD * angle) < 1e-6;
160
- });
161
- },
162
- ofLength: (length, tolerance = 1e-3) => withFilter((edge) => Math.abs(curveLength(edge) - length) < tolerance),
163
- ofCurveType: (curveType) => withFilter((edge) => getCurveType(edge) === curveType),
164
- parallelTo: (dir = "Z") => createEdgeFinder([...filters]).inDirection(dir, 0),
165
- atDistance: (distance, point = [0, 0, 0]) => withFilter((edge) => {
166
- const oc = getKernel().oc;
167
- const r = gcWithScope();
168
- const pnt = r(toOcPnt(point));
169
- const vtxMaker = r(new oc.BRepBuilderAPI_MakeVertex(pnt));
170
- const vtx = vtxMaker.Vertex();
171
- const distTool = r(new oc.BRepExtrema_DistShapeShape_1());
172
- distTool.LoadS1(vtx);
173
- distTool.LoadS2(edge.wrapped);
174
- const progress = r(new oc.Message_ProgressRange_1());
175
- distTool.Perform(progress);
176
- const d = distTool.Value();
177
- return Math.abs(d - distance) < 1e-6;
178
- })
179
- };
180
- }
181
- function faceFinder() {
182
- return createFaceFinder([]);
183
- }
184
- function createFaceFinder(filters) {
185
- const base = createFinder("face", filters);
186
- const withFilter = (pred) => createFaceFinder([...filters, pred]);
187
- return {
188
- ...base,
189
- when: (pred) => createFaceFinder([...filters, pred]),
190
- inList: (elements) => createFaceFinder([...base.inList(elements)._filters]),
191
- not: (fn) => createFaceFinder([...base.not(fn)._filters]),
192
- either: (fns) => createFaceFinder([
193
- ...base.either(fns)._filters
194
- ]),
195
- inDirection: (dir = "Z", angle = 0) => {
196
- const d = vecNormalize(resolveDir(dir));
197
- return withFilter((face) => {
198
- const n = normalAt(face);
199
- const ang = Math.acos(Math.min(1, Math.abs(vecDot(vecNormalize(n), d))));
200
- return Math.abs(ang - DEG2RAD * angle) < 1e-6;
201
- });
202
- },
203
- parallelTo: (dir = "Z") => createFaceFinder([...filters]).inDirection(dir, 0),
204
- ofSurfaceType: (surfaceType) => withFilter((face) => unwrap(getSurfaceType(face)) === surfaceType),
205
- ofArea: (area, tolerance = 1e-3) => withFilter((face) => Math.abs(measureArea(face) - area) < tolerance),
206
- atDistance: (distance, point = [0, 0, 0]) => withFilter((face) => {
207
- const oc = getKernel().oc;
208
- const r = gcWithScope();
209
- const pnt = r(toOcPnt(point));
210
- const vtxMaker = r(new oc.BRepBuilderAPI_MakeVertex(pnt));
211
- const vtx = vtxMaker.Vertex();
212
- const distTool = r(new oc.BRepExtrema_DistShapeShape_1());
213
- distTool.LoadS1(vtx);
214
- distTool.LoadS2(face.wrapped);
215
- const progress = r(new oc.Message_ProgressRange_1());
216
- distTool.Perform(progress);
217
- const d = distTool.Value();
218
- return Math.abs(d - distance) < 1e-6;
219
- })
220
- };
221
- }
222
- function wireFinder() {
223
- return createWireFinder([]);
224
- }
225
- function createWireFinder(filters) {
226
- const base = createFinder("wire", filters);
227
- const withFilter = (pred) => createWireFinder([...filters, pred]);
228
- return {
229
- ...base,
230
- when: (pred) => createWireFinder([...filters, pred]),
231
- inList: (elements) => createWireFinder([...base.inList(elements)._filters]),
232
- not: (fn) => createWireFinder([...base.not(fn)._filters]),
233
- either: (fns) => createWireFinder([
234
- ...base.either(fns)._filters
235
- ]),
236
- isClosed: () => withFilter((wire) => curveIsClosed(wire)),
237
- isOpen: () => withFilter((wire) => !curveIsClosed(wire)),
238
- ofEdgeCount: (count) => withFilter((wire) => {
239
- let edgeCount = 0;
240
- for (const _raw of iterTopo(wire.wrapped, "edge")) {
241
- edgeCount++;
242
- }
243
- return edgeCount === count;
244
- })
245
- };
246
- }
247
- function vertexFinder() {
248
- return createVertexFinder([]);
249
- }
250
- function createVertexFinder(filters) {
251
- const base = createFinder("vertex", filters);
252
- const withFilter = (pred) => createVertexFinder([...filters, pred]);
253
- return {
254
- ...base,
255
- when: (pred) => createVertexFinder([...filters, pred]),
256
- inList: (elements) => createVertexFinder([...base.inList(elements)._filters]),
257
- not: (fn) => createVertexFinder([
258
- ...base.not(fn)._filters
259
- ]),
260
- either: (fns) => createVertexFinder([
261
- ...base.either(fns)._filters
262
- ]),
263
- nearestTo: (point) => {
264
- const newFilters = [...filters];
265
- const finderWithNearestTo = createVertexFinderWithNearest(newFilters, point);
266
- return finderWithNearestTo;
267
- },
268
- atPosition: (point, tolerance = 1e-4) => withFilter((vertex) => {
269
- const pos = vertexPosition(vertex);
270
- return vecDistance(pos, point) < tolerance;
271
- }),
272
- withinBox: (min, max) => withFilter((vertex) => {
273
- const pos = vertexPosition(vertex);
274
- return pos[0] >= min[0] - 1e-6 && pos[0] <= max[0] + 1e-6 && pos[1] >= min[1] - 1e-6 && pos[1] <= max[1] + 1e-6 && pos[2] >= min[2] - 1e-6 && pos[2] <= max[2] + 1e-6;
275
- }),
276
- atDistance: (distance, point = [0, 0, 0], tolerance = 1e-4) => withFilter((vertex) => {
277
- const pos = vertexPosition(vertex);
278
- return Math.abs(vecDistance(pos, point) - distance) < tolerance;
279
- })
280
- };
281
- }
282
- function createVertexFinderWithNearest(filters, nearestPoint) {
283
- const baseFinder = createVertexFinder(filters);
284
- const findAllNearest = (shape) => {
285
- const candidates = baseFinder.findAll(shape);
286
- if (candidates.length === 0) return [];
287
- let bestIdx = 0;
288
- let bestDist = vecDistance(vertexPosition(candidates[0]), nearestPoint);
289
- for (let i = 1; i < candidates.length; i++) {
290
- const d = vecDistance(vertexPosition(candidates[i]), nearestPoint);
291
- if (d < bestDist) {
292
- bestDist = d;
293
- bestIdx = i;
294
- }
295
- }
296
- return [candidates[bestIdx]];
297
- };
298
- const findUniqueNearest = (shape) => {
299
- const nearest = findAllNearest(shape);
300
- if (nearest.length === 0) {
301
- return err(
302
- queryError("FINDER_NOT_UNIQUE", "Finder expected a unique match but found 0 element(s)")
303
- );
304
- }
305
- return ok(nearest[0]);
306
- };
307
- return {
308
- ...baseFinder,
309
- findAll: findAllNearest,
310
- findUnique: findUniqueNearest
311
- };
312
- }
313
- const PI_2 = 2 * Math.PI;
314
- const positiveHalfAngle = (angle) => {
315
- const limitedAngle = angle % PI_2;
316
- const coterminalAngle = limitedAngle < 0 ? limitedAngle + PI_2 : limitedAngle;
317
- if (coterminalAngle < Math.PI) return coterminalAngle;
318
- if (coterminalAngle === Math.PI) return 0;
319
- return Math.abs(coterminalAngle - PI_2);
320
- };
321
- function blueprintCorners(blueprint) {
322
- return blueprint.curves.map((curve, index) => ({
323
- firstCurve: curve,
324
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
325
- secondCurve: blueprint.curves[(index + 1) % blueprint.curves.length],
326
- point: curve.lastPoint
327
- }));
328
- }
329
- function cornerFinder() {
330
- return createCornerFinder([]);
331
- }
332
- function createCornerFinder(filters) {
333
- const withFilter = (pred) => createCornerFinder([...filters, pred]);
334
- const shouldKeep = (corner) => filters.every((f) => f(corner));
335
- return {
336
- shouldKeep,
337
- when: (pred) => withFilter(pred),
338
- inList: (points) => withFilter((corner) => points.some((p) => samePoint(p, corner.point))),
339
- atDistance: (distance, point = [0, 0]) => withFilter((corner) => Math.abs(distance2d(point, corner.point) - distance) < 1e-9),
340
- atPoint: (point) => withFilter((corner) => samePoint(point, corner.point)),
341
- inBox: (corner1, corner2) => {
342
- const minX = Math.min(corner1[0], corner2[0]);
343
- const maxX = Math.max(corner1[0], corner2[0]);
344
- const minY = Math.min(corner1[1], corner2[1]);
345
- const maxY = Math.max(corner1[1], corner2[1]);
346
- return withFilter((corner) => {
347
- const [x, y] = corner.point;
348
- return x >= minX && x <= maxX && y >= minY && y <= maxY;
349
- });
350
- },
351
- ofAngle: (angle) => withFilter((corner) => {
352
- const tgt1 = corner.firstCurve.tangentAt(1);
353
- const tgt2 = corner.secondCurve.tangentAt(0);
354
- return Math.abs(positiveHalfAngle(angle2d(tgt1, tgt2)) - positiveHalfAngle(DEG2RAD * angle)) < 1e-9;
355
- }),
356
- not: (fn) => {
357
- const inner = fn(createCornerFinder([]));
358
- return withFilter((corner) => !inner.shouldKeep(corner));
359
- },
360
- either: (fns) => {
361
- const builtFinders = fns.map((fn) => fn(createCornerFinder([])));
362
- return withFilter((corner) => builtFinders.some((f) => f.shouldKeep(corner)));
363
- },
364
- find: (blueprint) => blueprintCorners(blueprint).filter(shouldKeep)
365
- };
366
- }
367
- function getSingleFace(f, shape) {
368
- if (typeof f === "object" && "_topoKind" in f) {
369
- return f.findUnique(shape);
370
- }
371
- if (typeof f !== "function" && isFace(f)) return ok(f);
372
- const fnResult = f(faceFinder());
373
- return fnResult.findUnique(shape);
374
- }
375
- export {
376
- PRECISION_INTERSECTION as P,
377
- subtract2d as a,
378
- add2d as b,
379
- cornerFinder as c,
380
- crossProduct2d as d,
381
- edgeFinder as e,
382
- faceFinder as f,
383
- getSingleFace as g,
384
- scalarMultiply2d as h,
385
- distance2d as i,
386
- cartesianToPolar as j,
387
- polarAngle2d as k,
388
- PRECISION_OFFSET as l,
389
- squareDistance2d as m,
390
- normalize2d as n,
391
- polarToCartesian as p,
392
- rotate2d as r,
393
- samePoint as s,
394
- vertexFinder as v,
395
- wireFinder as w
396
- };