Updated Some Libraries

This commit is contained in:
Onyx Azryn 2020-10-10 14:27:11 -05:00
parent d44cca032e
commit d2972c0871
11 changed files with 24 additions and 332 deletions

View file

@ -1,103 +1 @@
'use strict';
// lineclip by mourner, https://github.com/mapbox/lineclip
// Cohen-Sutherland line clippign algorithm, adapted to efficiently
// handle polylines rather than just segments
function lineclip(points, bbox, result) {
var len = points.length,
codeA = bitCode(points[0], bbox),
part = [],
i, a, b, codeB, lastCode;
if (!result) result = [];
for (i = 1; i < len; i++) {
a = points[i - 1];
b = points[i];
codeB = lastCode = bitCode(b, bbox);
while (true) {
if (!(codeA | codeB)) { // accept
part.push(a);
if (codeB !== lastCode) { // segment went outside
part.push(b);
if (i < len - 1) { // start a new line
result.push(part);
part = [];
}
} else if (i === len - 1) {
part.push(b);
}
break;
} else if (codeA & codeB) { // trivial reject
break;
} else if (codeA) { // a outside, intersect with clip edge
a = intersect(a, b, codeA, bbox);
codeA = bitCode(a, bbox);
} else { // b outside
b = intersect(a, b, codeB, bbox);
codeB = bitCode(b, bbox);
}
}
codeA = lastCode;
}
if (part.length) result.push(part);
return result;
}
// Sutherland-Hodgeman polygon clipping algorithm
function polygonclip(points, bbox, secure = 0) {
var result, edge, prev, prevInside, inter, i, p, inside;
// clip against each side of the clip rectangle
for (edge = 1; edge <= 8; edge *= 2) {
result = [];
prev = points[points.length-1];
prevInside = !(bitCode(prev, bbox) & edge);
for (i = 0; i < points.length; i++) {
p = points[i];
inside = !(bitCode(p, bbox) & edge);
inter = inside !== prevInside; // segment goes through the clip window
const pi = intersect(prev, p, edge, bbox);
if (inter) result.push(pi); // add an intersection point
if (secure && inter) result.push(pi, pi); // add additional intersection points to secure correct d3 curve
if (inside) result.push(p); // add a point if it's inside
prev = p;
prevInside = inside;
}
points = result;
if (!points.length) break;
}
//result.forEach(p => debug.append("circle").attr("cx", p[0]).attr("cy", p[1]).attr("r", .6).attr("fill", "red"));
return result;
}
// intersect a segment against one of the 4 lines that make up the bbox
function intersect(a, b, edge, bbox) {
return edge & 8 ? [a[0] + (b[0] - a[0]) * (bbox[3] - a[1]) / (b[1] - a[1]), bbox[3]] : // top
edge & 4 ? [a[0] + (b[0] - a[0]) * (bbox[1] - a[1]) / (b[1] - a[1]), bbox[1]] : // bottom
edge & 2 ? [bbox[2], a[1] + (b[1] - a[1]) * (bbox[2] - a[0]) / (b[0] - a[0])] : // right
edge & 1 ? [bbox[0], a[1] + (b[1] - a[1]) * (bbox[0] - a[0]) / (b[0] - a[0])] : null; // left
}
// bit code reflects the point position relative to the bbox:
// left mid right
// top 1001 1000 1010
// mid 0001 0000 0010
// bottom 0101 0100 0110
function bitCode(p, bbox) {
var code = 0;
if (p[0] < bbox[0]) code |= 1; // left
else if (p[0] > bbox[2]) code |= 2; // right
if (p[1] < bbox[1]) code |= 4; // bottom
else if (p[1] > bbox[3]) code |= 8; // top
return code;
}
"use strict";function lineclip(e,i,n){var t,l,o,r,p,u=e.length,c=bitCode(e[0],i),s=[];for(n||(n=[]),t=1;t<u;t++){for(l=e[t-1],r=p=bitCode(o=e[t],i);;){if(!(c|r)){s.push(l),r!==p?(s.push(o),t<u-1&&(n.push(s),s=[])):t===u-1&&s.push(o);break}if(c&r)break;c?c=bitCode(l=intersect(l,o,c,i),i):r=bitCode(o=intersect(l,o,r,i),i)}c=p}return s.length&&n.push(s),n}function polygonclip(e,i){var n,t,l,o,r,p,u;for(t=1;t<=8;t*=2){for(n=[],o=!(bitCode(l=e[e.length-1],i)&t),r=0;r<e.length;r++)(u=!(bitCode(p=e[r],i)&t))!==o&&n.push(intersect(l,p,t,i)),u&&n.push(p),l=p,o=u;if(!(e=n).length)break}return n}function intersect(e,i,n,t){return 8&n?[e[0]+(i[0]-e[0])*(t[3]-e[1])/(i[1]-e[1]),t[3]]:4&n?[e[0]+(i[0]-e[0])*(t[1]-e[1])/(i[1]-e[1]),t[1]]:2&n?[t[2],e[1]+(i[1]-e[1])*(t[2]-e[0])/(i[0]-e[0])]:1&n?[t[0],e[1]+(i[1]-e[1])*(t[0]-e[0])/(i[0]-e[0])]:null}function bitCode(e,i){var n=0;return e[0]<i[0]?n|=1:e[0]>i[2]&&(n|=2),e[1]<i[1]?n|=4:e[1]>i[3]&&(n|=8),n}module.exports=lineclip,lineclip.polyline=lineclip,lineclip.polygon=polygonclip;