|
import pointEqual from "../pointEqual.js"; |
|
import {epsilon} from "../math.js"; |
|
|
|
function Intersection(point, points, other, entry) { |
|
this.x = point; |
|
this.z = points; |
|
this.o = other; |
|
this.e = entry; |
|
this.v = false; |
|
this.n = this.p = null; |
|
} |
|
|
|
|
|
|
|
|
|
export default function(segments, compareIntersection, startInside, interpolate, stream) { |
|
var subject = [], |
|
clip = [], |
|
i, |
|
n; |
|
|
|
segments.forEach(function(segment) { |
|
if ((n = segment.length - 1) <= 0) return; |
|
var n, p0 = segment[0], p1 = segment[n], x; |
|
|
|
if (pointEqual(p0, p1)) { |
|
if (!p0[2] && !p1[2]) { |
|
stream.lineStart(); |
|
for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]); |
|
stream.lineEnd(); |
|
return; |
|
} |
|
|
|
p1[0] += 2 * epsilon; |
|
} |
|
|
|
subject.push(x = new Intersection(p0, segment, null, true)); |
|
clip.push(x.o = new Intersection(p0, null, x, false)); |
|
subject.push(x = new Intersection(p1, segment, null, false)); |
|
clip.push(x.o = new Intersection(p1, null, x, true)); |
|
}); |
|
|
|
if (!subject.length) return; |
|
|
|
clip.sort(compareIntersection); |
|
link(subject); |
|
link(clip); |
|
|
|
for (i = 0, n = clip.length; i < n; ++i) { |
|
clip[i].e = startInside = !startInside; |
|
} |
|
|
|
var start = subject[0], |
|
points, |
|
point; |
|
|
|
while (1) { |
|
|
|
var current = start, |
|
isSubject = true; |
|
while (current.v) if ((current = current.n) === start) return; |
|
points = current.z; |
|
stream.lineStart(); |
|
do { |
|
current.v = current.o.v = true; |
|
if (current.e) { |
|
if (isSubject) { |
|
for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]); |
|
} else { |
|
interpolate(current.x, current.n.x, 1, stream); |
|
} |
|
current = current.n; |
|
} else { |
|
if (isSubject) { |
|
points = current.p.z; |
|
for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]); |
|
} else { |
|
interpolate(current.x, current.p.x, -1, stream); |
|
} |
|
current = current.p; |
|
} |
|
current = current.o; |
|
points = current.z; |
|
isSubject = !isSubject; |
|
} while (!current.v); |
|
stream.lineEnd(); |
|
} |
|
} |
|
|
|
function link(array) { |
|
if (!(n = array.length)) return; |
|
var n, |
|
i = 0, |
|
a = array[0], |
|
b; |
|
while (++i < n) { |
|
a.n = b = array[i]; |
|
b.p = a; |
|
a = b; |
|
} |
|
a.n = b = array[0]; |
|
b.p = a; |
|
} |
|
|