1 | import {abs, acos, cos, degrees, epsilon, epsilon2, pi, radians} from "./math.js";
|
2 | import {cartesian, cartesianCross, cartesianDot, cartesianEqual, cartesianNormalizeInPlace, spherical} from "./cartesian.js";
|
3 |
|
4 | export function intersectSegment(from, to) {
|
5 | this.from = from, this.to = to;
|
6 | this.normal = cartesianCross(from, to);
|
7 | this.fromNormal = cartesianCross(this.normal, from);
|
8 | this.toNormal = cartesianCross(this.normal, to);
|
9 | this.l = acos(cartesianDot(from, to));
|
10 | }
|
11 |
|
12 |
|
13 | export function intersect(a, b) {
|
14 | if (cartesianEqual(a.from, b.from) || cartesianEqual(a.from, b.to))
|
15 | return a.from;
|
16 | if (cartesianEqual(a.to, b.from) || cartesianEqual(a.to, b.to))
|
17 | return a.to;
|
18 |
|
19 | var lc = (a.l + b.l < pi) ? cos(a.l + b.l) - epsilon : -1;
|
20 | if (cartesianDot(a.from, b.from) < lc
|
21 | || cartesianDot(a.from, b.to) < lc
|
22 | || cartesianDot(a.to, b.from) < lc
|
23 | || cartesianDot(a.to, b.to) < lc)
|
24 | return;
|
25 |
|
26 | var axb = cartesianCross(a.normal, b.normal);
|
27 | cartesianNormalizeInPlace(axb);
|
28 |
|
29 | var a0 = cartesianDot(axb, a.fromNormal),
|
30 | a1 = cartesianDot(axb, a.toNormal),
|
31 | b0 = cartesianDot(axb, b.fromNormal),
|
32 | b1 = cartesianDot(axb, b.toNormal);
|
33 |
|
34 |
|
35 |
|
36 | if (
|
37 | (a0 > 0 && a1 < 0 && b0 > 0 && b1 < 0) ||
|
38 | (a0 >= 0 &&
|
39 | a1 <= 0 &&
|
40 | b0 >= 0 &&
|
41 | b1 <= 0 &&
|
42 | (cartesianEqual(axb, a.from) ||
|
43 | cartesianEqual(axb, a.to) ||
|
44 | cartesianEqual(axb, b.from) ||
|
45 | cartesianEqual(axb, b.to)))
|
46 | )
|
47 | return axb;
|
48 |
|
49 |
|
50 | axb[0] = -axb[0];
|
51 | axb[1] = -axb[1];
|
52 | axb[2] = -axb[2];
|
53 | a0 = -a0;
|
54 | a1 = -a1;
|
55 | b0 = -b0;
|
56 | b1 = -b1;
|
57 |
|
58 | if (
|
59 | (a0 > 0 && a1 < 0 && b0 > 0 && b1 < 0) ||
|
60 | (a0 >= 0 &&
|
61 | a1 <= 0 &&
|
62 | b0 >= 0 &&
|
63 | b1 <= 0 &&
|
64 | (cartesianEqual(axb, a.from) ||
|
65 | cartesianEqual(axb, a.to) ||
|
66 | cartesianEqual(axb, b.from) ||
|
67 | cartesianEqual(axb, b.to)))
|
68 | )
|
69 | return axb;
|
70 | }
|
71 |
|
72 | export function intersectPointOnLine(p, a) {
|
73 | var a0 = cartesianDot(p, a.fromNormal),
|
74 | a1 = cartesianDot(p, a.toNormal);
|
75 | p = cartesianDot(p, a.normal);
|
76 |
|
77 | return abs(p) < epsilon2 && (a0 > -epsilon2 && a1 < epsilon2 || a0 < epsilon2 && a1 > -epsilon2);
|
78 | }
|
79 |
|
80 | export var intersectCoincident = {};
|
81 |
|
82 | export default function(a, b) {
|
83 | var ca = a.map(p => cartesian(p.map(d => d * radians))),
|
84 | cb = b.map(p => cartesian(p.map(d => d * radians)));
|
85 | var i = intersect(
|
86 | new intersectSegment(ca[0], ca[1]),
|
87 | new intersectSegment(cb[0], cb[1])
|
88 | );
|
89 | return !i ? i : spherical(i).map(d => d * degrees);
|
90 | }
|