From 957f62317b02913d3dae94f122d4738a7efd6e2a Mon Sep 17 00:00:00 2001 From: Onyx Azryn Date: Sat, 10 Oct 2020 14:43:31 -0500 Subject: [PATCH] Fixed Dependency --- libs/lineclip.js | 104 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/libs/lineclip.js b/libs/lineclip.js index 9b795518..b43da33b 100644 --- a/libs/lineclip.js +++ b/libs/lineclip.js @@ -1 +1,103 @@ -"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;ti[2]&&(n|=2),e[1]i[3]&&(n|=8),n}module.exports=lineclip,lineclip.polyline=lineclip,lineclip.polygon=polygonclip; \ No newline at end of file +'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; +} \ No newline at end of file