// JavaScript implementations of point-in-polygon testing. // Adapted by Andrew Cameron from Dan Sunday's algorithm and C++ // implementation, whose copyright follows. // // Copyright 2000 softSurfer, 2012 Dan Sunday // This code may be freely used, distributed and modified for any purpose // providing that this copyright notice is included with it. // SoftSurfer makes no warranty for this code, and cannot be held // liable for any real or imagined damage resulting from its use. // Users of this code must verify correctness for their application. "use strict"; var isLeft = function (l0, l1, p) { return ((l1[0] - l0[0]) * (p[1] - l0[1]) - (p[0] - l0[0]) * (l1[1] - l0[1])); }; var inPoly = function (p, v, direction, axis) { var wn = 0; // winding number counter var dir = 0; if (direction > 0) { dir = 1; } else if (direction < 0) { dir = -1; } else { error('wat'); } if (axis != 0 && axis != 1) { error('wat'); } v.forEach(function (curPt, idx, arr) { var nextPt; if (idx < arr.length - 1) { nextPt = arr[idx + 1]; } else { nextPt = arr[0]; } if (dir * curPt[axis] <= dir * p[axis]) { if (dir * nextPt[axis] > dir * p[axis]) { if (isLeft(curPt, nextPt, p) > 0) { wn++; } } } else { if (dir * nextPt[axis] <= dir * p[axis]) { if (isLeft(curPt, nextPt, p) < 0) { wn--; } } } }); return wn; }; var countZones = function(polygons, points, binPoints) { var counts = {}; polygons.forEach(function (poly, idx, arr) { counts[poly.name] = 0; }, this); counts['undetermined'] = 0; points.forEach(function (pt, idx_pt, arr_pts) { if (!polygons.some(function (poly, idx_poly, arr_polys) { if (inPoly(pt, poly.path, 1, 0) != 0 || inPoly(pt, poly.path, -1, 0) != 0 || inPoly(pt, poly.path, 1, 1) != 0 || inPoly(pt, poly.path, -1, 1) != 0) { counts[poly.name] += 1; if (binPoints == true) { pt.push(poly.name); } return true; } else { return false; } }, this)) { // not found in any of the polygons counts['undetermined'] += 1; if (binPoints == true) { pt.push('undetermined'); } } }, this); return counts; };