diff --git a/libs/lineclip.js b/libs/lineclip.js index b43da33b..df92c5fe 100644 --- a/libs/lineclip.js +++ b/libs/lineclip.js @@ -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; -} \ No newline at end of file +"use strict";function lineclip(t,e,n){var r,i,o,u,s,h=t.length,c=bitCode(t[0],e),f=[];for(n||(n=[]),r=1;re[2]&&(n|=2),t[1]e[3]&&(n|=8),n} \ No newline at end of file