UNPKG

2.67 kBJavaScriptView Raw
1import {abs, acos, cos, degrees, epsilon, epsilon2, pi, radians} from "./math.js";
2import {cartesian, cartesianCross, cartesianDot, cartesianEqual, cartesianNormalizeInPlace, spherical} from "./cartesian.js";
3
4export 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// >> here a and b are segments processed by intersectSegment
13export 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 // check if the candidate lies on both segments
35 // or is almost equal to one of the four points
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 // same test for the antipode
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
72export 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
80export var intersectCoincident = {};
81
82export 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}