123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- "use strict";
- // Cohen-Sutherland line clipping algorithm, adapted to efficiently
- // handle polylines rather than just segments
- Object.defineProperty(exports, "__esModule", { value: true });
- function lineclip(points, bbox, result) {
- var len = points.length, codeA = bitCode(points[0], bbox), part = [], i, codeB, lastCode;
- var a;
- var b;
- 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;
- }
- exports.lineclip = lineclip;
- // Sutherland-Hodgeman polygon clipping algorithm
- function polygonclip(points, bbox) {
- var result, edge, prev, prevInside, 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);
- // if segment goes through the clip window, add an intersection
- if (inside !== prevInside)
- result.push(intersect(prev, p, edge, bbox));
- if (inside)
- result.push(p); // add a point if it's inside
- prev = p;
- prevInside = inside;
- }
- points = result;
- if (!points.length)
- break;
- }
- return result;
- }
- exports.polygonclip = polygonclip;
- // 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])] // left
- : null;
- }
- // 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;
- }
|