@mlightcad/geometry-engine 3.13.0 → 3.14.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/geometry-engine.umd.cjs +1 -1
- package/lib/geometry/AcGeCircArc2d.d.ts +103 -0
- package/lib/geometry/AcGeCircArc2d.d.ts.map +1 -1
- package/lib/geometry/AcGeCircArc2d.js +174 -38
- package/lib/geometry/AcGeCircArc2d.js.map +1 -1
- package/lib/geometry/AcGeCircArc2dFactory.d.ts +57 -0
- package/lib/geometry/AcGeCircArc2dFactory.d.ts.map +1 -0
- package/lib/geometry/AcGeCircArc2dFactory.js +209 -0
- package/lib/geometry/AcGeCircArc2dFactory.js.map +1 -0
- package/lib/geometry/AcGeCircArc3d.d.ts +10 -1
- package/lib/geometry/AcGeCircArc3d.d.ts.map +1 -1
- package/lib/geometry/AcGeCircArc3d.js +45 -50
- package/lib/geometry/AcGeCircArc3d.js.map +1 -1
- package/lib/geometry/AcGeCircArcUtil.d.ts +55 -0
- package/lib/geometry/AcGeCircArcUtil.d.ts.map +1 -0
- package/lib/geometry/AcGeCircArcUtil.js +120 -0
- package/lib/geometry/AcGeCircArcUtil.js.map +1 -0
- package/lib/geometry/AcGeCurveIntersect.d.ts +64 -0
- package/lib/geometry/AcGeCurveIntersect.d.ts.map +1 -0
- package/lib/geometry/AcGeCurveIntersect.js +941 -0
- package/lib/geometry/AcGeCurveIntersect.js.map +1 -0
- package/lib/geometry/index.d.ts +4 -0
- package/lib/geometry/index.d.ts.map +1 -1
- package/lib/geometry/index.js +2 -0
- package/lib/geometry/index.js.map +1 -1
- package/lib/index.d.ts +3 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/lib/util/AcGeMathUtil.d.ts +7 -1
- package/lib/util/AcGeMathUtil.d.ts.map +1 -1
- package/lib/util/AcGeMathUtil.js +11 -1
- package/lib/util/AcGeMathUtil.js.map +1 -1
- package/lib/util/index.d.ts +1 -1
- package/lib/util/index.d.ts.map +1 -1
- package/lib/util/index.js +1 -1
- package/lib/util/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,941 @@
|
|
|
1
|
+
var __values = (this && this.__values) || function(o) {
|
|
2
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
3
|
+
if (m) return m.call(o);
|
|
4
|
+
if (o && typeof o.length === "number") return {
|
|
5
|
+
next: function () {
|
|
6
|
+
if (o && i >= o.length) o = void 0;
|
|
7
|
+
return { value: o && o[i++], done: !o };
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
11
|
+
};
|
|
12
|
+
import { AcGeBox3d, AcGePlane, AcGePoint3d, AcGeVector3d } from '../math';
|
|
13
|
+
import { AcGeMathUtil, AcGeTol, DEFAULT_TOL, FLOAT_TOL, TAU } from '../util';
|
|
14
|
+
import { AcGeCircArc3d } from './AcGeCircArc3d';
|
|
15
|
+
import { AcGeEllipseArc3d } from './AcGeEllipseArc3d';
|
|
16
|
+
var SPLINE_SAMPLE_COUNT = 128;
|
|
17
|
+
var PLANAR_SAMPLE_COUNT = 96;
|
|
18
|
+
var POINT_TOL = DEFAULT_TOL.equalPointTol;
|
|
19
|
+
var REFINE_TOL = POINT_TOL * 8;
|
|
20
|
+
/**
|
|
21
|
+
* Finds intersection points between two sets of curve primitives.
|
|
22
|
+
*
|
|
23
|
+
* `extendA` / `extendB` correspond to ObjectARX `AcDb::Intersect` flags for
|
|
24
|
+
* the two operands. A primitive is only extended when `extendable` is not
|
|
25
|
+
* `false`. Overlapping coincident curves do not produce a continuum of points.
|
|
26
|
+
*
|
|
27
|
+
* When `projPlane` is provided, both operands are projected onto that plane
|
|
28
|
+
* first (apparent intersection). Result points lie on the plane.
|
|
29
|
+
*
|
|
30
|
+
* @param a - Primitives from the first operand
|
|
31
|
+
* @param b - Primitives from the second operand
|
|
32
|
+
* @param extendA - Extend the first operand when its primitives allow it
|
|
33
|
+
* @param extendB - Extend the second operand when its primitives allow it
|
|
34
|
+
* @param projPlane - Optional projection plane for apparent intersection
|
|
35
|
+
* @returns Intersection points in WCS, de-duplicated by the equal-point tolerance
|
|
36
|
+
*/
|
|
37
|
+
export function acgeIntersectCurves(a, b, extendA, extendB, projPlane) {
|
|
38
|
+
var e_1, _a, e_2, _b;
|
|
39
|
+
if (extendA === void 0) { extendA = false; }
|
|
40
|
+
if (extendB === void 0) { extendB = false; }
|
|
41
|
+
var left = flattenPrimitives(a, extendA, projPlane);
|
|
42
|
+
var right = flattenPrimitives(b, extendB, projPlane);
|
|
43
|
+
var points = [];
|
|
44
|
+
try {
|
|
45
|
+
for (var left_1 = __values(left), left_1_1 = left_1.next(); !left_1_1.done; left_1_1 = left_1.next()) {
|
|
46
|
+
var pa = left_1_1.value;
|
|
47
|
+
try {
|
|
48
|
+
for (var right_1 = (e_2 = void 0, __values(right)), right_1_1 = right_1.next(); !right_1_1.done; right_1_1 = right_1.next()) {
|
|
49
|
+
var pb = right_1_1.value;
|
|
50
|
+
if (!boxesMayIntersect(pa, pb))
|
|
51
|
+
continue;
|
|
52
|
+
appendPoints(points, intersectPrepared(pa, pb));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
56
|
+
finally {
|
|
57
|
+
try {
|
|
58
|
+
if (right_1_1 && !right_1_1.done && (_b = right_1.return)) _b.call(right_1);
|
|
59
|
+
}
|
|
60
|
+
finally { if (e_2) throw e_2.error; }
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
65
|
+
finally {
|
|
66
|
+
try {
|
|
67
|
+
if (left_1_1 && !left_1_1.done && (_a = left_1.return)) _a.call(left_1);
|
|
68
|
+
}
|
|
69
|
+
finally { if (e_1) throw e_1.error; }
|
|
70
|
+
}
|
|
71
|
+
return dedupePoints(points);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Returns a transformed copy of a curve primitive.
|
|
75
|
+
*/
|
|
76
|
+
export function acgeTransformIntersectPrimitive(primitive, matrix) {
|
|
77
|
+
var cloned = acgeCloneIntersectPrimitive(primitive);
|
|
78
|
+
switch (cloned.kind) {
|
|
79
|
+
case 'line':
|
|
80
|
+
cloned.line.transform(matrix);
|
|
81
|
+
return cloned;
|
|
82
|
+
case 'circArc':
|
|
83
|
+
cloned.arc.transform(matrix);
|
|
84
|
+
return cloned;
|
|
85
|
+
case 'ellipseArc':
|
|
86
|
+
cloned.arc.transform(matrix);
|
|
87
|
+
return cloned;
|
|
88
|
+
case 'spline':
|
|
89
|
+
cloned.spline.transform(matrix);
|
|
90
|
+
return cloned;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Returns a deep-cloned curve primitive.
|
|
95
|
+
*/
|
|
96
|
+
export function acgeCloneIntersectPrimitive(primitive) {
|
|
97
|
+
switch (primitive.kind) {
|
|
98
|
+
case 'line':
|
|
99
|
+
return {
|
|
100
|
+
kind: 'line',
|
|
101
|
+
line: primitive.line.clone(),
|
|
102
|
+
extent: primitive.extent,
|
|
103
|
+
extendable: primitive.extendable
|
|
104
|
+
};
|
|
105
|
+
case 'circArc':
|
|
106
|
+
return {
|
|
107
|
+
kind: 'circArc',
|
|
108
|
+
arc: primitive.arc.clone(),
|
|
109
|
+
extendable: primitive.extendable
|
|
110
|
+
};
|
|
111
|
+
case 'ellipseArc':
|
|
112
|
+
return {
|
|
113
|
+
kind: 'ellipseArc',
|
|
114
|
+
arc: primitive.arc.clone(),
|
|
115
|
+
extendable: primitive.extendable
|
|
116
|
+
};
|
|
117
|
+
case 'spline':
|
|
118
|
+
return {
|
|
119
|
+
kind: 'spline',
|
|
120
|
+
spline: primitive.spline.clone(),
|
|
121
|
+
extendable: primitive.extendable
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function flattenPrimitives(primitives, extend, projPlane) {
|
|
126
|
+
var e_3, _a;
|
|
127
|
+
var result = [];
|
|
128
|
+
try {
|
|
129
|
+
for (var primitives_1 = __values(primitives), primitives_1_1 = primitives_1.next(); !primitives_1_1.done; primitives_1_1 = primitives_1.next()) {
|
|
130
|
+
var primitive = primitives_1_1.value;
|
|
131
|
+
var shouldExtend = extend && primitive.extendable !== false;
|
|
132
|
+
switch (primitive.kind) {
|
|
133
|
+
case 'line': {
|
|
134
|
+
var line = projectLine(primitive.line, projPlane);
|
|
135
|
+
if (!line)
|
|
136
|
+
break;
|
|
137
|
+
var extent = shouldExtend ? 'unbounded' : primitive.extent;
|
|
138
|
+
result.push(prepareLine(line.start, line.end, extent));
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
case 'circArc': {
|
|
142
|
+
var expanded = expandCircArc(primitive.arc, shouldExtend);
|
|
143
|
+
if (projPlane && !planesParallel(expanded.normal, projPlane.normal)) {
|
|
144
|
+
var projected = projectCircleOntoPlane(expanded, projPlane);
|
|
145
|
+
if ((projected === null || projected === void 0 ? void 0 : projected.kind) === 'circArc') {
|
|
146
|
+
result.push(prepareCircArc(projected.arc, isFullCircArc(projected.arc)));
|
|
147
|
+
}
|
|
148
|
+
else if ((projected === null || projected === void 0 ? void 0 : projected.kind) === 'ellipseArc') {
|
|
149
|
+
result.push(prepareEllipseArc(projected.arc, isFullEllipseArc(projected.arc)));
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
appendSampledCurve(result, sampleCircArc(expanded, isFullCircArc(expanded)), isFullCircArc(expanded), projPlane);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
var projected = projectCircArc(expanded, projPlane);
|
|
157
|
+
if (projected) {
|
|
158
|
+
result.push(prepareCircArc(projected, isFullCircArc(projected)));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
case 'ellipseArc': {
|
|
164
|
+
var expanded = expandEllipseArc(primitive.arc, shouldExtend);
|
|
165
|
+
if (projPlane && !planesParallel(expanded.normal, projPlane.normal)) {
|
|
166
|
+
appendSampledCurve(result, sampleEllipseArc(expanded, isFullEllipseArc(expanded)), isFullEllipseArc(expanded), projPlane);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
var projected = projectEllipseArc(expanded, projPlane);
|
|
170
|
+
if (projected) {
|
|
171
|
+
result.push(prepareEllipseArc(projected, isFullEllipseArc(projected)));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
case 'spline': {
|
|
177
|
+
if (projPlane) {
|
|
178
|
+
appendSampledCurve(result, primitive.spline.getPoints(SPLINE_SAMPLE_COUNT), primitive.spline.closed, projPlane);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
result.push(prepareSpline(primitive.spline));
|
|
182
|
+
}
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
189
|
+
finally {
|
|
190
|
+
try {
|
|
191
|
+
if (primitives_1_1 && !primitives_1_1.done && (_a = primitives_1.return)) _a.call(primitives_1);
|
|
192
|
+
}
|
|
193
|
+
finally { if (e_3) throw e_3.error; }
|
|
194
|
+
}
|
|
195
|
+
return result;
|
|
196
|
+
}
|
|
197
|
+
function prepareLine(start, end, extent) {
|
|
198
|
+
var dir = new AcGeVector3d().subVectors(end, start);
|
|
199
|
+
return {
|
|
200
|
+
kind: 'line',
|
|
201
|
+
start: start,
|
|
202
|
+
dir: dir,
|
|
203
|
+
extent: extent,
|
|
204
|
+
box: extent === 'bounded'
|
|
205
|
+
? new AcGeBox3d().setFromPoints([start, end])
|
|
206
|
+
: undefined
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function prepareCircArc(arc, full) {
|
|
210
|
+
return {
|
|
211
|
+
kind: 'circArc',
|
|
212
|
+
arc: arc,
|
|
213
|
+
full: full || isFullCircArc(arc),
|
|
214
|
+
box: arc.box
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function prepareEllipseArc(arc, full) {
|
|
218
|
+
return {
|
|
219
|
+
kind: 'ellipseArc',
|
|
220
|
+
arc: arc,
|
|
221
|
+
full: full || isFullEllipseArc(arc),
|
|
222
|
+
box: arc.box
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
function prepareSpline(spline) {
|
|
226
|
+
var e_4, _a;
|
|
227
|
+
var samples = [];
|
|
228
|
+
var points = spline.getPoints(SPLINE_SAMPLE_COUNT);
|
|
229
|
+
if (points.length >= 2) {
|
|
230
|
+
var count = spline.closed ? points.length : points.length - 1;
|
|
231
|
+
for (var i = 0; i < count; i++) {
|
|
232
|
+
var start = points[i];
|
|
233
|
+
var end = points[(i + 1) % points.length];
|
|
234
|
+
if (start.distanceToSquared(end) < POINT_TOL * POINT_TOL)
|
|
235
|
+
continue;
|
|
236
|
+
samples.push(prepareLine(start.clone(), end.clone(), 'bounded'));
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
var box = new AcGeBox3d();
|
|
240
|
+
try {
|
|
241
|
+
for (var samples_1 = __values(samples), samples_1_1 = samples_1.next(); !samples_1_1.done; samples_1_1 = samples_1.next()) {
|
|
242
|
+
var sample = samples_1_1.value;
|
|
243
|
+
if (sample.box)
|
|
244
|
+
box.union(sample.box);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
248
|
+
finally {
|
|
249
|
+
try {
|
|
250
|
+
if (samples_1_1 && !samples_1_1.done && (_a = samples_1.return)) _a.call(samples_1);
|
|
251
|
+
}
|
|
252
|
+
finally { if (e_4) throw e_4.error; }
|
|
253
|
+
}
|
|
254
|
+
return {
|
|
255
|
+
kind: 'spline',
|
|
256
|
+
spline: spline,
|
|
257
|
+
samples: samples,
|
|
258
|
+
box: samples.length > 0 ? box : undefined
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
function expandCircArc(arc, extend) {
|
|
262
|
+
if (!extend || isFullCircArc(arc))
|
|
263
|
+
return arc;
|
|
264
|
+
return new AcGeCircArc3d(arc.center, arc.radius, 0, TAU, arc.normal, arc.refVec);
|
|
265
|
+
}
|
|
266
|
+
function expandEllipseArc(arc, extend) {
|
|
267
|
+
if (!extend || isFullEllipseArc(arc))
|
|
268
|
+
return arc;
|
|
269
|
+
return new AcGeEllipseArc3d(arc.center, arc.normal, arc.majorAxis, arc.majorAxisRadius, arc.minorAxisRadius, 0, TAU);
|
|
270
|
+
}
|
|
271
|
+
function projectLine(line, plane) {
|
|
272
|
+
if (!plane) {
|
|
273
|
+
return { start: line.startPoint.clone(), end: line.endPoint.clone() };
|
|
274
|
+
}
|
|
275
|
+
var start = projectPointToPlane(line.startPoint, plane);
|
|
276
|
+
var end = projectPointToPlane(line.endPoint, plane);
|
|
277
|
+
if (start.distanceToSquared(end) < POINT_TOL * POINT_TOL)
|
|
278
|
+
return null;
|
|
279
|
+
return { start: start, end: end };
|
|
280
|
+
}
|
|
281
|
+
function projectCircArc(arc, plane) {
|
|
282
|
+
if (!plane)
|
|
283
|
+
return arc;
|
|
284
|
+
var center = projectPointToPlane(arc.center, plane);
|
|
285
|
+
return new AcGeCircArc3d(center, arc.radius, arc.startAngle, arc.endAngle, plane.normal.clone(), projectDirectionToPlane(arc.refVec, plane.normal));
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Orthogonal projection of a circular arc onto `plane`. Parallel planes keep a
|
|
289
|
+
* circle; a tilted circle becomes an ellipse. A circle whose plane is
|
|
290
|
+
* perpendicular to `plane` degenerates to a segment and returns null so the
|
|
291
|
+
* caller can sample.
|
|
292
|
+
*/
|
|
293
|
+
function projectCircleOntoPlane(arc, plane) {
|
|
294
|
+
var center = projectPointToPlane(arc.center, plane);
|
|
295
|
+
var n = arc.normal.clone();
|
|
296
|
+
if (n.lengthSq() < POINT_TOL * POINT_TOL)
|
|
297
|
+
return null;
|
|
298
|
+
n.normalize();
|
|
299
|
+
var p = plane.normal.clone();
|
|
300
|
+
if (p.lengthSq() < POINT_TOL * POINT_TOL)
|
|
301
|
+
return null;
|
|
302
|
+
p.normalize();
|
|
303
|
+
var cos = n.dot(p);
|
|
304
|
+
var absCos = Math.abs(cos);
|
|
305
|
+
if (absCos > 1 - 1e-8) {
|
|
306
|
+
return {
|
|
307
|
+
kind: 'circArc',
|
|
308
|
+
arc: new AcGeCircArc3d(center, arc.radius, arc.startAngle, arc.endAngle, p, projectDirectionToPlane(arc.refVec, p))
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
if (absCos < 1e-8)
|
|
312
|
+
return null;
|
|
313
|
+
var hinge = new AcGeVector3d().crossVectors(n, p);
|
|
314
|
+
if (hinge.lengthSq() < POINT_TOL * POINT_TOL)
|
|
315
|
+
return null;
|
|
316
|
+
hinge.normalize();
|
|
317
|
+
var ellipse = new AcGeEllipseArc3d(center, p, hinge, arc.radius, arc.radius * absCos, 0, TAU);
|
|
318
|
+
if (isFullCircArc(arc)) {
|
|
319
|
+
return { kind: 'ellipseArc', arc: ellipse };
|
|
320
|
+
}
|
|
321
|
+
var start = projectPointToPlane(arc.startPoint, plane);
|
|
322
|
+
var end = projectPointToPlane(arc.endPoint, plane);
|
|
323
|
+
var mid = projectPointToPlane(arc.midPoint, plane);
|
|
324
|
+
var startAngle = ellipseArcAngle(ellipse, start);
|
|
325
|
+
var endAngle = ellipseArcAngle(ellipse, end);
|
|
326
|
+
var midAngle = ellipseArcAngle(ellipse, mid);
|
|
327
|
+
var tMid = AcGeMathUtil.normalizeAngle(midAngle - startAngle);
|
|
328
|
+
var tEnd = AcGeMathUtil.normalizeAngle(endAngle - startAngle);
|
|
329
|
+
var sweepEnd = tMid <= tEnd || tEnd < 1e-8 ? startAngle + tEnd : startAngle + tEnd + TAU;
|
|
330
|
+
return {
|
|
331
|
+
kind: 'ellipseArc',
|
|
332
|
+
arc: new AcGeEllipseArc3d(center, p, hinge, arc.radius, arc.radius * absCos, startAngle, sweepEnd)
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
function projectEllipseArc(arc, plane) {
|
|
336
|
+
if (!plane)
|
|
337
|
+
return arc;
|
|
338
|
+
var center = projectPointToPlane(arc.center, plane);
|
|
339
|
+
var major = projectDirectionToPlane(arc.majorAxis, plane.normal);
|
|
340
|
+
if (major.lengthSq() < POINT_TOL * POINT_TOL)
|
|
341
|
+
return null;
|
|
342
|
+
return new AcGeEllipseArc3d(center, plane.normal.clone(), major, arc.majorAxisRadius, arc.minorAxisRadius, arc.startAngle, arc.endAngle);
|
|
343
|
+
}
|
|
344
|
+
function appendSampledCurve(result, samples, closed, projPlane) {
|
|
345
|
+
if (samples.length < 2)
|
|
346
|
+
return;
|
|
347
|
+
var points = projPlane
|
|
348
|
+
? samples.map(function (point) { return projectPointToPlane(point, projPlane); })
|
|
349
|
+
: samples;
|
|
350
|
+
var count = closed ? points.length : points.length - 1;
|
|
351
|
+
for (var i = 0; i < count; i++) {
|
|
352
|
+
var start = points[i];
|
|
353
|
+
var end = points[(i + 1) % points.length];
|
|
354
|
+
if (start.distanceToSquared(end) < POINT_TOL * POINT_TOL)
|
|
355
|
+
continue;
|
|
356
|
+
result.push(prepareLine(start.clone(), end.clone(), 'bounded'));
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
function sampleCircArc(arc, full) {
|
|
360
|
+
if (full || isFullCircArc(arc)) {
|
|
361
|
+
return new AcGeCircArc3d(arc.center, arc.radius, 0, TAU, arc.normal, arc.refVec).getPoints(PLANAR_SAMPLE_COUNT);
|
|
362
|
+
}
|
|
363
|
+
return arc.getPoints(PLANAR_SAMPLE_COUNT);
|
|
364
|
+
}
|
|
365
|
+
function sampleEllipseArc(arc, full) {
|
|
366
|
+
if (full || isFullEllipseArc(arc)) {
|
|
367
|
+
return new AcGeEllipseArc3d(arc.center, arc.normal, arc.majorAxis, arc.majorAxisRadius, arc.minorAxisRadius, 0, TAU).getPoints(PLANAR_SAMPLE_COUNT);
|
|
368
|
+
}
|
|
369
|
+
return arc.getPoints(PLANAR_SAMPLE_COUNT);
|
|
370
|
+
}
|
|
371
|
+
function boxesMayIntersect(a, b) {
|
|
372
|
+
if (!a.box || !b.box)
|
|
373
|
+
return true;
|
|
374
|
+
return a.box.intersectsBox(b.box);
|
|
375
|
+
}
|
|
376
|
+
function intersectPrepared(a, b) {
|
|
377
|
+
if (a.kind === 'spline' && b.kind === 'spline') {
|
|
378
|
+
return intersectSplineSpline(a, b);
|
|
379
|
+
}
|
|
380
|
+
if (a.kind === 'spline')
|
|
381
|
+
return intersectSplineOther(a, b);
|
|
382
|
+
if (b.kind === 'spline')
|
|
383
|
+
return intersectSplineOther(b, a);
|
|
384
|
+
if (a.kind === 'line' && b.kind === 'line')
|
|
385
|
+
return intersectLineLine(a, b);
|
|
386
|
+
if (a.kind === 'line' && b.kind === 'circArc') {
|
|
387
|
+
return intersectLineCircArc(a, b.arc, b.full);
|
|
388
|
+
}
|
|
389
|
+
if (b.kind === 'line' && a.kind === 'circArc') {
|
|
390
|
+
return intersectLineCircArc(b, a.arc, a.full);
|
|
391
|
+
}
|
|
392
|
+
if (a.kind === 'line' && b.kind === 'ellipseArc') {
|
|
393
|
+
return intersectLineEllipseArc(a, b.arc, b.full);
|
|
394
|
+
}
|
|
395
|
+
if (b.kind === 'line' && a.kind === 'ellipseArc') {
|
|
396
|
+
return intersectLineEllipseArc(b, a.arc, a.full);
|
|
397
|
+
}
|
|
398
|
+
if (a.kind === 'circArc' && b.kind === 'circArc') {
|
|
399
|
+
return intersectCircCirc(a.arc, a.full, b.arc, b.full);
|
|
400
|
+
}
|
|
401
|
+
if (a.kind === 'circArc' && b.kind === 'ellipseArc') {
|
|
402
|
+
return intersectCircEllipse(a.arc, a.full, b.arc, b.full);
|
|
403
|
+
}
|
|
404
|
+
if (a.kind === 'ellipseArc' && b.kind === 'circArc') {
|
|
405
|
+
return intersectCircEllipse(b.arc, b.full, a.arc, a.full);
|
|
406
|
+
}
|
|
407
|
+
if (a.kind === 'ellipseArc' && b.kind === 'ellipseArc') {
|
|
408
|
+
return intersectEllipseEllipse(a.arc, a.full, b.arc, b.full);
|
|
409
|
+
}
|
|
410
|
+
return [];
|
|
411
|
+
}
|
|
412
|
+
function intersectSplineOther(spline, other) {
|
|
413
|
+
var e_5, _a;
|
|
414
|
+
var hits = [];
|
|
415
|
+
try {
|
|
416
|
+
for (var _b = __values(spline.samples), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
417
|
+
var sample = _c.value;
|
|
418
|
+
if (!boxesMayIntersect(sample, other))
|
|
419
|
+
continue;
|
|
420
|
+
appendPoints(hits, intersectPrepared(sample, other));
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
|
424
|
+
finally {
|
|
425
|
+
try {
|
|
426
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
427
|
+
}
|
|
428
|
+
finally { if (e_5) throw e_5.error; }
|
|
429
|
+
}
|
|
430
|
+
return refineSplineHits(spline.spline, hits, other);
|
|
431
|
+
}
|
|
432
|
+
function intersectSplineSpline(a, b) {
|
|
433
|
+
var e_6, _a, e_7, _b, e_8, _c;
|
|
434
|
+
var hits = [];
|
|
435
|
+
try {
|
|
436
|
+
for (var _d = __values(a.samples), _e = _d.next(); !_e.done; _e = _d.next()) {
|
|
437
|
+
var sa = _e.value;
|
|
438
|
+
try {
|
|
439
|
+
for (var _f = (e_7 = void 0, __values(b.samples)), _g = _f.next(); !_g.done; _g = _f.next()) {
|
|
440
|
+
var sb = _g.value;
|
|
441
|
+
if (!boxesMayIntersect(sa, sb))
|
|
442
|
+
continue;
|
|
443
|
+
appendPoints(hits, intersectLineLine(sa, sb));
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
catch (e_7_1) { e_7 = { error: e_7_1 }; }
|
|
447
|
+
finally {
|
|
448
|
+
try {
|
|
449
|
+
if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
|
|
450
|
+
}
|
|
451
|
+
finally { if (e_7) throw e_7.error; }
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
catch (e_6_1) { e_6 = { error: e_6_1 }; }
|
|
456
|
+
finally {
|
|
457
|
+
try {
|
|
458
|
+
if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
|
|
459
|
+
}
|
|
460
|
+
finally { if (e_6) throw e_6.error; }
|
|
461
|
+
}
|
|
462
|
+
var points = [];
|
|
463
|
+
try {
|
|
464
|
+
for (var hits_1 = __values(hits), hits_1_1 = hits_1.next(); !hits_1_1.done; hits_1_1 = hits_1.next()) {
|
|
465
|
+
var hit = hits_1_1.value;
|
|
466
|
+
var pa = a.spline.nearestPoint(hit, SPLINE_SAMPLE_COUNT);
|
|
467
|
+
var pb = b.spline.nearestPoint(hit, SPLINE_SAMPLE_COUNT);
|
|
468
|
+
if (pa.distanceTo(pb) <= REFINE_TOL)
|
|
469
|
+
points.push(pa);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
catch (e_8_1) { e_8 = { error: e_8_1 }; }
|
|
473
|
+
finally {
|
|
474
|
+
try {
|
|
475
|
+
if (hits_1_1 && !hits_1_1.done && (_c = hits_1.return)) _c.call(hits_1);
|
|
476
|
+
}
|
|
477
|
+
finally { if (e_8) throw e_8.error; }
|
|
478
|
+
}
|
|
479
|
+
return points;
|
|
480
|
+
}
|
|
481
|
+
function refineSplineHits(spline, hits, other) {
|
|
482
|
+
var e_9, _a;
|
|
483
|
+
var points = [];
|
|
484
|
+
try {
|
|
485
|
+
for (var hits_2 = __values(hits), hits_2_1 = hits_2.next(); !hits_2_1.done; hits_2_1 = hits_2.next()) {
|
|
486
|
+
var hit = hits_2_1.value;
|
|
487
|
+
var refined = spline.nearestPoint(hit, SPLINE_SAMPLE_COUNT);
|
|
488
|
+
if (distanceToPrepared(other, refined) <= REFINE_TOL) {
|
|
489
|
+
points.push(refined);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
catch (e_9_1) { e_9 = { error: e_9_1 }; }
|
|
494
|
+
finally {
|
|
495
|
+
try {
|
|
496
|
+
if (hits_2_1 && !hits_2_1.done && (_a = hits_2.return)) _a.call(hits_2);
|
|
497
|
+
}
|
|
498
|
+
finally { if (e_9) throw e_9.error; }
|
|
499
|
+
}
|
|
500
|
+
return points;
|
|
501
|
+
}
|
|
502
|
+
function distanceToPrepared(primitive, point) {
|
|
503
|
+
if (primitive.kind === 'line') {
|
|
504
|
+
var dirLenSq = primitive.dir.lengthSq();
|
|
505
|
+
if (dirLenSq < POINT_TOL * POINT_TOL)
|
|
506
|
+
return Number.POSITIVE_INFINITY;
|
|
507
|
+
var t = new AcGeVector3d().subVectors(point, primitive.start).dot(primitive.dir) /
|
|
508
|
+
dirLenSq;
|
|
509
|
+
if (!isParamOnExtent(t, primitive.extent))
|
|
510
|
+
return Number.POSITIVE_INFINITY;
|
|
511
|
+
return pointOnLine(primitive.start, primitive.dir, t).distanceTo(point);
|
|
512
|
+
}
|
|
513
|
+
if (primitive.kind === 'circArc') {
|
|
514
|
+
if (!isPointOnCircle(point, primitive.arc)) {
|
|
515
|
+
var plane = planeFromNormalAndPoint(primitive.arc.normal, primitive.arc.center);
|
|
516
|
+
var planar = Math.abs(plane.distanceToPoint(point));
|
|
517
|
+
var radial = Math.abs(point.distanceTo(primitive.arc.center) - primitive.arc.radius);
|
|
518
|
+
var off = Math.hypot(planar, radial);
|
|
519
|
+
if (off > REFINE_TOL)
|
|
520
|
+
return off;
|
|
521
|
+
}
|
|
522
|
+
return isAngleOnCircArc(primitive.arc, circArcAngle(primitive.arc, point), primitive.full)
|
|
523
|
+
? 0
|
|
524
|
+
: Number.POSITIVE_INFINITY;
|
|
525
|
+
}
|
|
526
|
+
if (primitive.kind === 'ellipseArc') {
|
|
527
|
+
return isPointOnEllipse(point, primitive.arc, primitive.full)
|
|
528
|
+
? 0
|
|
529
|
+
: Math.abs(ellipseImplicit(primitive.arc, point));
|
|
530
|
+
}
|
|
531
|
+
return Number.POSITIVE_INFINITY;
|
|
532
|
+
}
|
|
533
|
+
function intersectLineLine(a, b) {
|
|
534
|
+
var d1 = a.dir;
|
|
535
|
+
var d2 = b.dir;
|
|
536
|
+
var len1Sq = d1.lengthSq();
|
|
537
|
+
var len2Sq = d2.lengthSq();
|
|
538
|
+
if (len1Sq < POINT_TOL * POINT_TOL || len2Sq < POINT_TOL * POINT_TOL) {
|
|
539
|
+
return [];
|
|
540
|
+
}
|
|
541
|
+
var w0 = new AcGeVector3d().subVectors(a.start, b.start);
|
|
542
|
+
var aa = d1.dot(d1);
|
|
543
|
+
var bb = d1.dot(d2);
|
|
544
|
+
var cc = d2.dot(d2);
|
|
545
|
+
var dd = d1.dot(w0);
|
|
546
|
+
var ee = d2.dot(w0);
|
|
547
|
+
var denom = aa * cc - bb * bb;
|
|
548
|
+
if (Math.abs(denom) < FLOAT_TOL * FLOAT_TOL * aa * cc) {
|
|
549
|
+
return [];
|
|
550
|
+
}
|
|
551
|
+
var t = (bb * ee - cc * dd) / denom;
|
|
552
|
+
var s = (aa * ee - bb * dd) / denom;
|
|
553
|
+
if (!isParamOnExtent(t, a.extent) || !isParamOnExtent(s, b.extent)) {
|
|
554
|
+
return [];
|
|
555
|
+
}
|
|
556
|
+
var p = pointOnLine(a.start, d1, t);
|
|
557
|
+
var q = pointOnLine(b.start, d2, s);
|
|
558
|
+
if (p.distanceTo(q) > POINT_TOL)
|
|
559
|
+
return [];
|
|
560
|
+
return [p];
|
|
561
|
+
}
|
|
562
|
+
function intersectLineCircArc(line, arc, full) {
|
|
563
|
+
var plane = planeFromNormalAndPoint(arc.normal, arc.center);
|
|
564
|
+
var hit = intersectLineWithPlane(line, plane);
|
|
565
|
+
if (hit === 'coplanar') {
|
|
566
|
+
return intersectCoplanarLineCircle(line, arc, full);
|
|
567
|
+
}
|
|
568
|
+
if (!hit)
|
|
569
|
+
return [];
|
|
570
|
+
if (!isPointOnCircle(hit, arc))
|
|
571
|
+
return [];
|
|
572
|
+
if (!isAngleOnCircArc(arc, circArcAngle(arc, hit), full))
|
|
573
|
+
return [];
|
|
574
|
+
return [hit];
|
|
575
|
+
}
|
|
576
|
+
function intersectCoplanarLineCircle(line, arc, full) {
|
|
577
|
+
var e_10, _a;
|
|
578
|
+
var f = new AcGeVector3d().subVectors(line.start, arc.center);
|
|
579
|
+
var a = line.dir.dot(line.dir);
|
|
580
|
+
if (a < POINT_TOL * POINT_TOL)
|
|
581
|
+
return [];
|
|
582
|
+
var b = 2 * line.dir.dot(f);
|
|
583
|
+
var c = f.dot(f) - arc.radius * arc.radius;
|
|
584
|
+
var points = [];
|
|
585
|
+
try {
|
|
586
|
+
for (var _b = __values(solveQuadratic(a, b, c)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
587
|
+
var t = _c.value;
|
|
588
|
+
if (!isParamOnExtent(t, line.extent))
|
|
589
|
+
continue;
|
|
590
|
+
var point = pointOnLine(line.start, line.dir, t);
|
|
591
|
+
if (!isAngleOnCircArc(arc, circArcAngle(arc, point), full))
|
|
592
|
+
continue;
|
|
593
|
+
points.push(point);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
catch (e_10_1) { e_10 = { error: e_10_1 }; }
|
|
597
|
+
finally {
|
|
598
|
+
try {
|
|
599
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
600
|
+
}
|
|
601
|
+
finally { if (e_10) throw e_10.error; }
|
|
602
|
+
}
|
|
603
|
+
return points;
|
|
604
|
+
}
|
|
605
|
+
function intersectLineEllipseArc(line, arc, full) {
|
|
606
|
+
var plane = planeFromNormalAndPoint(arc.normal, arc.center);
|
|
607
|
+
var hit = intersectLineWithPlane(line, plane);
|
|
608
|
+
if (hit === 'coplanar') {
|
|
609
|
+
return intersectCoplanarLineEllipse(line, arc, full);
|
|
610
|
+
}
|
|
611
|
+
if (!hit)
|
|
612
|
+
return [];
|
|
613
|
+
if (!isPointOnEllipse(hit, arc, full))
|
|
614
|
+
return [];
|
|
615
|
+
return [hit];
|
|
616
|
+
}
|
|
617
|
+
function intersectCoplanarLineEllipse(line, arc, full) {
|
|
618
|
+
var e_11, _a;
|
|
619
|
+
var u = arc.majorAxis;
|
|
620
|
+
var v = arc.minorAxis;
|
|
621
|
+
var a = arc.majorAxisRadius;
|
|
622
|
+
var b = arc.minorAxisRadius;
|
|
623
|
+
if (a < POINT_TOL || b < POINT_TOL)
|
|
624
|
+
return [];
|
|
625
|
+
var startOffset = new AcGeVector3d().subVectors(line.start, arc.center);
|
|
626
|
+
var x0 = startOffset.dot(u);
|
|
627
|
+
var y0 = startOffset.dot(v);
|
|
628
|
+
var dx = line.dir.dot(u);
|
|
629
|
+
var dy = line.dir.dot(v);
|
|
630
|
+
var A = (dx * dx) / (a * a) + (dy * dy) / (b * b);
|
|
631
|
+
var B = (2 * x0 * dx) / (a * a) + (2 * y0 * dy) / (b * b);
|
|
632
|
+
var C = (x0 * x0) / (a * a) + (y0 * y0) / (b * b) - 1;
|
|
633
|
+
var points = [];
|
|
634
|
+
try {
|
|
635
|
+
for (var _b = __values(solveQuadratic(A, B, C)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
636
|
+
var t = _c.value;
|
|
637
|
+
if (!isParamOnExtent(t, line.extent))
|
|
638
|
+
continue;
|
|
639
|
+
var point = pointOnLine(line.start, line.dir, t);
|
|
640
|
+
if (!isAngleOnEllipseArc(arc, ellipseArcAngle(arc, point), full))
|
|
641
|
+
continue;
|
|
642
|
+
points.push(point);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
catch (e_11_1) { e_11 = { error: e_11_1 }; }
|
|
646
|
+
finally {
|
|
647
|
+
try {
|
|
648
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
649
|
+
}
|
|
650
|
+
finally { if (e_11) throw e_11.error; }
|
|
651
|
+
}
|
|
652
|
+
return points;
|
|
653
|
+
}
|
|
654
|
+
function intersectCircCirc(a, fullA, b, fullB) {
|
|
655
|
+
if (planesParallel(a.normal, b.normal)) {
|
|
656
|
+
var planeA = planeFromNormalAndPoint(a.normal, a.center);
|
|
657
|
+
if (Math.abs(planeA.distanceToPoint(b.center)) > POINT_TOL)
|
|
658
|
+
return [];
|
|
659
|
+
return filterCircPoints(intersectCoplanarCircles(a, b), a, fullA, b, fullB);
|
|
660
|
+
}
|
|
661
|
+
var line = planePlaneIntersectionLine(planeFromNormalAndPoint(a.normal, a.center), planeFromNormalAndPoint(b.normal, b.center));
|
|
662
|
+
if (!line)
|
|
663
|
+
return [];
|
|
664
|
+
var prepared = prepareLine(line.point.clone(), new AcGePoint3d().addVectors(line.point, line.dir), 'unbounded');
|
|
665
|
+
var onA = intersectLineCircArc(prepared, a, fullA);
|
|
666
|
+
return onA.filter(function (point) {
|
|
667
|
+
if (!isPointOnCircle(point, b))
|
|
668
|
+
return false;
|
|
669
|
+
return isAngleOnCircArc(b, circArcAngle(b, point), fullB);
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
function intersectCoplanarCircles(a, b) {
|
|
673
|
+
var offset = new AcGeVector3d().subVectors(b.center, a.center);
|
|
674
|
+
var dist = offset.length();
|
|
675
|
+
var r1 = a.radius;
|
|
676
|
+
var r2 = b.radius;
|
|
677
|
+
if (dist < POINT_TOL && AcGeTol.equal(r1, r2, POINT_TOL))
|
|
678
|
+
return [];
|
|
679
|
+
if (dist > r1 + r2 + POINT_TOL)
|
|
680
|
+
return [];
|
|
681
|
+
if (dist + Math.min(r1, r2) + POINT_TOL < Math.max(r1, r2))
|
|
682
|
+
return [];
|
|
683
|
+
var dir = dist < POINT_TOL ? perpInPlane(a.normal) : offset.clone().normalize();
|
|
684
|
+
var x = (r1 * r1 - r2 * r2 + dist * dist) / (2 * Math.max(dist, POINT_TOL));
|
|
685
|
+
var hSq = r1 * r1 - x * x;
|
|
686
|
+
var p = new AcGePoint3d().copy(a.center).addScaledVector(dir, x);
|
|
687
|
+
if (hSq < -POINT_TOL * POINT_TOL)
|
|
688
|
+
return [];
|
|
689
|
+
if (hSq < POINT_TOL * POINT_TOL)
|
|
690
|
+
return [p];
|
|
691
|
+
var h = Math.sqrt(Math.max(0, hSq));
|
|
692
|
+
var perp = new AcGeVector3d().crossVectors(a.normal, dir).normalize();
|
|
693
|
+
return [
|
|
694
|
+
new AcGePoint3d().copy(p).addScaledVector(perp, h),
|
|
695
|
+
new AcGePoint3d().copy(p).addScaledVector(perp, -h)
|
|
696
|
+
];
|
|
697
|
+
}
|
|
698
|
+
function intersectCircEllipse(circle, fullCircle, ellipse, fullEllipse) {
|
|
699
|
+
if (!planesParallel(circle.normal, ellipse.normal)) {
|
|
700
|
+
var line = planePlaneIntersectionLine(planeFromNormalAndPoint(circle.normal, circle.center), planeFromNormalAndPoint(ellipse.normal, ellipse.center));
|
|
701
|
+
if (!line)
|
|
702
|
+
return [];
|
|
703
|
+
var prepared = prepareLine(line.point.clone(), new AcGePoint3d().addVectors(line.point, line.dir), 'unbounded');
|
|
704
|
+
return intersectLineCircArc(prepared, circle, fullCircle).filter(function (point) {
|
|
705
|
+
return isPointOnEllipse(point, ellipse, fullEllipse);
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
return intersectPlanarImplicit(sampleCircArc(circle, fullCircle), isFullCircArc(circle) || fullCircle, function (point) { return ellipseImplicit(ellipse, point); }, function (point) {
|
|
709
|
+
return isAngleOnCircArc(circle, circArcAngle(circle, point), fullCircle) &&
|
|
710
|
+
isPointOnEllipse(point, ellipse, fullEllipse);
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
function intersectEllipseEllipse(a, fullA, b, fullB) {
|
|
714
|
+
if (!planesParallel(a.normal, b.normal)) {
|
|
715
|
+
var line = planePlaneIntersectionLine(planeFromNormalAndPoint(a.normal, a.center), planeFromNormalAndPoint(b.normal, b.center));
|
|
716
|
+
if (!line)
|
|
717
|
+
return [];
|
|
718
|
+
var prepared = prepareLine(line.point.clone(), new AcGePoint3d().addVectors(line.point, line.dir), 'unbounded');
|
|
719
|
+
return intersectLineEllipseArc(prepared, a, fullA).filter(function (point) {
|
|
720
|
+
return isPointOnEllipse(point, b, fullB);
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
return intersectPlanarImplicit(sampleEllipseArc(a, fullA), isFullEllipseArc(a) || fullA, function (point) { return ellipseImplicit(b, point); }, function (point) {
|
|
724
|
+
return isAngleOnEllipseArc(a, ellipseArcAngle(a, point), fullA) &&
|
|
725
|
+
isPointOnEllipse(point, b, fullB);
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
function intersectPlanarImplicit(samples, closed, implicit, accept) {
|
|
729
|
+
var points = [];
|
|
730
|
+
var count = closed ? samples.length : samples.length - 1;
|
|
731
|
+
for (var i = 0; i < count; i++) {
|
|
732
|
+
var p0 = samples[i];
|
|
733
|
+
var p1 = samples[(i + 1) % samples.length];
|
|
734
|
+
var e0 = implicit(p0);
|
|
735
|
+
var e1 = implicit(p1);
|
|
736
|
+
if (Math.abs(e0) <= POINT_TOL) {
|
|
737
|
+
if (accept(p0))
|
|
738
|
+
points.push(p0.clone());
|
|
739
|
+
continue;
|
|
740
|
+
}
|
|
741
|
+
if (e0 * e1 > 0)
|
|
742
|
+
continue;
|
|
743
|
+
var lo = 0;
|
|
744
|
+
var hi = 1;
|
|
745
|
+
var loVal = e0;
|
|
746
|
+
for (var step = 0; step < 40; step++) {
|
|
747
|
+
var mid = (lo + hi) / 2;
|
|
748
|
+
var midPoint = new AcGePoint3d().lerpVectors(p0, p1, mid);
|
|
749
|
+
var midVal = implicit(midPoint);
|
|
750
|
+
if (loVal * midVal <= 0) {
|
|
751
|
+
hi = mid;
|
|
752
|
+
}
|
|
753
|
+
else {
|
|
754
|
+
lo = mid;
|
|
755
|
+
loVal = midVal;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
var hit = new AcGePoint3d().lerpVectors(p0, p1, (lo + hi) / 2);
|
|
759
|
+
if (accept(hit))
|
|
760
|
+
points.push(hit);
|
|
761
|
+
}
|
|
762
|
+
return points;
|
|
763
|
+
}
|
|
764
|
+
function intersectLineWithPlane(line, plane) {
|
|
765
|
+
var denom = plane.normal.dot(line.dir);
|
|
766
|
+
var dist = plane.distanceToPoint(line.start);
|
|
767
|
+
if (AcGeTol.equalToZero(denom, POINT_TOL * Math.max(1, line.dir.length()))) {
|
|
768
|
+
return AcGeTol.equalToZero(dist, POINT_TOL) ? 'coplanar' : null;
|
|
769
|
+
}
|
|
770
|
+
var t = -dist / denom;
|
|
771
|
+
if (!isParamOnExtent(t, line.extent))
|
|
772
|
+
return null;
|
|
773
|
+
return pointOnLine(line.start, line.dir, t);
|
|
774
|
+
}
|
|
775
|
+
function planePlaneIntersectionLine(a, b) {
|
|
776
|
+
var dir = new AcGeVector3d().crossVectors(a.normal, b.normal);
|
|
777
|
+
if (dir.lengthSq() < POINT_TOL * POINT_TOL)
|
|
778
|
+
return null;
|
|
779
|
+
dir.normalize();
|
|
780
|
+
var n1 = a.normal;
|
|
781
|
+
var n2 = b.normal;
|
|
782
|
+
var det = n1.dot(n1) * n2.dot(n2) - Math.pow(n1.dot(n2), 2);
|
|
783
|
+
if (Math.abs(det) < FLOAT_TOL)
|
|
784
|
+
return null;
|
|
785
|
+
var c1 = -a.constant;
|
|
786
|
+
var c2 = -b.constant;
|
|
787
|
+
var x = (n2.dot(n2) * c1 - n1.dot(n2) * c2) / det;
|
|
788
|
+
var y = (n1.dot(n1) * c2 - n1.dot(n2) * c1) / det;
|
|
789
|
+
var point = new AcGePoint3d().addScaledVector(n1, x).addScaledVector(n2, y);
|
|
790
|
+
return { point: point, dir: dir };
|
|
791
|
+
}
|
|
792
|
+
function isParamOnExtent(t, extent) {
|
|
793
|
+
if (extent === 'unbounded')
|
|
794
|
+
return true;
|
|
795
|
+
if (extent === 'ray')
|
|
796
|
+
return t >= -POINT_TOL;
|
|
797
|
+
return t >= -POINT_TOL && t <= 1 + POINT_TOL;
|
|
798
|
+
}
|
|
799
|
+
function pointOnLine(start, dir, t) {
|
|
800
|
+
return new AcGePoint3d().copy(start).addScaledVector(dir, t);
|
|
801
|
+
}
|
|
802
|
+
function projectPointToPlane(point, plane) {
|
|
803
|
+
var target = new AcGePoint3d();
|
|
804
|
+
plane.projectPoint(point, target);
|
|
805
|
+
return target;
|
|
806
|
+
}
|
|
807
|
+
function projectDirectionToPlane(dir, planeNormal) {
|
|
808
|
+
var projected = dir
|
|
809
|
+
.clone()
|
|
810
|
+
.addScaledVector(planeNormal, -dir.dot(planeNormal));
|
|
811
|
+
if (projected.lengthSq() < POINT_TOL * POINT_TOL) {
|
|
812
|
+
return perpInPlane(planeNormal);
|
|
813
|
+
}
|
|
814
|
+
return projected.normalize();
|
|
815
|
+
}
|
|
816
|
+
function planeFromNormalAndPoint(normal, point) {
|
|
817
|
+
return new AcGePlane().setFromNormalAndCoplanarPoint(normal, point);
|
|
818
|
+
}
|
|
819
|
+
function planesParallel(a, b) {
|
|
820
|
+
return (new AcGeVector3d().crossVectors(a, b).lengthSq() < POINT_TOL * POINT_TOL);
|
|
821
|
+
}
|
|
822
|
+
function circArcAngle(arc, point) {
|
|
823
|
+
var vec = new AcGeVector3d().subVectors(point, arc.center);
|
|
824
|
+
var ortho = new AcGeVector3d().crossVectors(arc.normal, arc.refVec);
|
|
825
|
+
return Math.atan2(vec.dot(ortho), vec.dot(arc.refVec));
|
|
826
|
+
}
|
|
827
|
+
function ellipseArcAngle(arc, point) {
|
|
828
|
+
var offset = new AcGeVector3d().subVectors(point, arc.center);
|
|
829
|
+
var x = offset.dot(arc.majorAxis) / arc.majorAxisRadius;
|
|
830
|
+
var y = offset.dot(arc.minorAxis) / arc.minorAxisRadius;
|
|
831
|
+
return Math.atan2(y, x);
|
|
832
|
+
}
|
|
833
|
+
function isFullCircArc(arc) {
|
|
834
|
+
return arc.closed || Math.abs(arc.deltaAngle - TAU) < 1e-10;
|
|
835
|
+
}
|
|
836
|
+
function isFullEllipseArc(arc) {
|
|
837
|
+
return (arc.closed ||
|
|
838
|
+
Math.abs(arc.endAngle - arc.startAngle) < 1e-10 ||
|
|
839
|
+
Math.abs(arc.deltaAngle - TAU) < 1e-10);
|
|
840
|
+
}
|
|
841
|
+
function isAngleOnCircArc(arc, angle, full) {
|
|
842
|
+
if (full || isFullCircArc(arc))
|
|
843
|
+
return true;
|
|
844
|
+
var t = AcGeMathUtil.normalizeAngle(angle - arc.startAngle);
|
|
845
|
+
return t <= arc.deltaAngle + 1e-8;
|
|
846
|
+
}
|
|
847
|
+
function isAngleOnEllipseArc(arc, angle, full) {
|
|
848
|
+
if (full || isFullEllipseArc(arc))
|
|
849
|
+
return true;
|
|
850
|
+
var t = AcGeMathUtil.normalizeAngle(angle - arc.startAngle);
|
|
851
|
+
return t <= arc.deltaAngle + 1e-8;
|
|
852
|
+
}
|
|
853
|
+
function isPointOnCircle(point, arc) {
|
|
854
|
+
var plane = planeFromNormalAndPoint(arc.normal, arc.center);
|
|
855
|
+
if (Math.abs(plane.distanceToPoint(point)) > POINT_TOL)
|
|
856
|
+
return false;
|
|
857
|
+
return Math.abs(point.distanceTo(arc.center) - arc.radius) <= POINT_TOL;
|
|
858
|
+
}
|
|
859
|
+
function ellipseImplicit(arc, point) {
|
|
860
|
+
var offset = new AcGeVector3d().subVectors(point, arc.center);
|
|
861
|
+
var x = offset.dot(arc.majorAxis) / arc.majorAxisRadius;
|
|
862
|
+
var y = offset.dot(arc.minorAxis) / arc.minorAxisRadius;
|
|
863
|
+
return x * x + y * y - 1;
|
|
864
|
+
}
|
|
865
|
+
function isPointOnEllipse(point, arc, full) {
|
|
866
|
+
var plane = planeFromNormalAndPoint(arc.normal, arc.center);
|
|
867
|
+
if (Math.abs(plane.distanceToPoint(point)) > POINT_TOL)
|
|
868
|
+
return false;
|
|
869
|
+
if (Math.abs(ellipseImplicit(arc, point)) > 1e-4)
|
|
870
|
+
return false;
|
|
871
|
+
return isAngleOnEllipseArc(arc, ellipseArcAngle(arc, point), full);
|
|
872
|
+
}
|
|
873
|
+
function filterCircPoints(points, a, fullA, b, fullB) {
|
|
874
|
+
return points.filter(function (point) {
|
|
875
|
+
return isAngleOnCircArc(a, circArcAngle(a, point), fullA) &&
|
|
876
|
+
isAngleOnCircArc(b, circArcAngle(b, point), fullB);
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
function perpInPlane(normal) {
|
|
880
|
+
var axis = Math.abs(normal.x) < 0.9 ? AcGeVector3d.X_AXIS : AcGeVector3d.Y_AXIS;
|
|
881
|
+
var perp = new AcGeVector3d().crossVectors(normal, axis);
|
|
882
|
+
if (perp.lengthSq() < POINT_TOL * POINT_TOL) {
|
|
883
|
+
perp.crossVectors(normal, AcGeVector3d.Z_AXIS);
|
|
884
|
+
}
|
|
885
|
+
return perp.normalize();
|
|
886
|
+
}
|
|
887
|
+
function solveQuadratic(a, b, c) {
|
|
888
|
+
if (Math.abs(a) < FLOAT_TOL) {
|
|
889
|
+
if (Math.abs(b) < FLOAT_TOL)
|
|
890
|
+
return [];
|
|
891
|
+
return [-c / b];
|
|
892
|
+
}
|
|
893
|
+
var disc = b * b - 4 * a * c;
|
|
894
|
+
if (disc < -POINT_TOL)
|
|
895
|
+
return [];
|
|
896
|
+
if (disc < POINT_TOL)
|
|
897
|
+
return [-b / (2 * a)];
|
|
898
|
+
var sqrtDisc = Math.sqrt(Math.max(0, disc));
|
|
899
|
+
return [(-b - sqrtDisc) / (2 * a), (-b + sqrtDisc) / (2 * a)];
|
|
900
|
+
}
|
|
901
|
+
function appendPoints(target, points) {
|
|
902
|
+
var e_12, _a;
|
|
903
|
+
try {
|
|
904
|
+
for (var points_1 = __values(points), points_1_1 = points_1.next(); !points_1_1.done; points_1_1 = points_1.next()) {
|
|
905
|
+
var point = points_1_1.value;
|
|
906
|
+
target.push(point);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
catch (e_12_1) { e_12 = { error: e_12_1 }; }
|
|
910
|
+
finally {
|
|
911
|
+
try {
|
|
912
|
+
if (points_1_1 && !points_1_1.done && (_a = points_1.return)) _a.call(points_1);
|
|
913
|
+
}
|
|
914
|
+
finally { if (e_12) throw e_12.error; }
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
function dedupePoints(points) {
|
|
918
|
+
var e_13, _a;
|
|
919
|
+
var unique = [];
|
|
920
|
+
var _loop_1 = function (point) {
|
|
921
|
+
if (unique.some(function (existing) { return existing.distanceTo(point) <= POINT_TOL; })) {
|
|
922
|
+
return "continue";
|
|
923
|
+
}
|
|
924
|
+
unique.push(point);
|
|
925
|
+
};
|
|
926
|
+
try {
|
|
927
|
+
for (var points_2 = __values(points), points_2_1 = points_2.next(); !points_2_1.done; points_2_1 = points_2.next()) {
|
|
928
|
+
var point = points_2_1.value;
|
|
929
|
+
_loop_1(point);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
catch (e_13_1) { e_13 = { error: e_13_1 }; }
|
|
933
|
+
finally {
|
|
934
|
+
try {
|
|
935
|
+
if (points_2_1 && !points_2_1.done && (_a = points_2.return)) _a.call(points_2);
|
|
936
|
+
}
|
|
937
|
+
finally { if (e_13) throw e_13.error; }
|
|
938
|
+
}
|
|
939
|
+
return unique;
|
|
940
|
+
}
|
|
941
|
+
//# sourceMappingURL=AcGeCurveIntersect.js.map
|