UNPKG

2d-polygon-self-intersections

Version:

This library may not be fast, but it is robust. Robust in the fact that it will find all of the self-intersections in a polygon - minus of course shared endpoints.

82 lines (67 loc) 1.69 kB
var isect = require('exact-segment-intersect'); var float = require('robust-estimate-float'); module.exports = selfIntersections; function cmp(a, b) { return a[0] === b[0] && a[1] === b[1]; } var pc = [0, 0]; var pn = [0, 0]; var oc = [0, 0]; var on = [0, 0]; function arrayOrObject(v, ret) { if (Array.isArray(v)) { ret[0] = v[0]; ret[1] = v[1]; } else { ret[0] = v.x; ret[1] = v.y; } } function selfIntersections(poly, filterFn) { var seen = {}; var l = poly.length; var isects = []; for (var o=0; o<l; o++) { var s0 = poly[o]; var e0 = poly[(o+1) % l]; arrayOrObject(s0, oc); arrayOrObject(e0, on); for (var p=0; p<l; p++) { if (o === p) { continue; } var s1 = poly[p] var e1 = poly[(p+1) % l]; arrayOrObject(s1, pc); arrayOrObject(e1, pn); if (cmp(pc, oc) || cmp(pc, on) || cmp(pn, oc) || cmp(pn, on)) { continue; } var r = isect(oc, on, pc, pn); // since these are homogeneous vectors, if the last component `w` is 0 // then we've done something wrong var wraw = r[2]; if (wraw.length === 1 && !wraw[0]) { continue; } var w = float(r[2]); r[0] = float(r[0]) / w; r[1] = float(r[1]) / w; r.pop(); if (cmp(r, oc) || cmp(r, on) || cmp(r, pc) || cmp(r, pn)) { continue; } var key = r+''; var unique = !seen[key]; if (unique) { seen[key] = true; } var collect = unique; if (filterFn) { collect = filterFn(r, o, s0, e0, p, s1, e1, unique); } if (collect) { isects.push(r); } } } return isects; }