UNPKG

point-in-big-polygon

Version:
151 lines (138 loc) 3.26 kB
module.exports = preprocessPolygon var orient = require('robust-orientation')[3] var makeSlabs = require('slab-decomposition') var makeIntervalTree = require('interval-tree-1d') var bsearch = require('binary-search-bounds') function visitInterval() { return true } function intervalSearch(table) { return function(x, y) { var tree = table[x] if(tree) { return !!tree.queryPoint(y, visitInterval) } return false } } function buildVerticalIndex(segments) { var table = {} for(var i=0; i<segments.length; ++i) { var s = segments[i] var x = s[0][0] var y0 = s[0][1] var y1 = s[1][1] var p = [ Math.min(y0, y1), Math.max(y0, y1) ] if(x in table) { table[x].push(p) } else { table[x] = [ p ] } } var intervalTable = {} var keys = Object.keys(table) for(var i=0; i<keys.length; ++i) { var segs = table[keys[i]] intervalTable[keys[i]] = makeIntervalTree(segs) } return intervalSearch(intervalTable) } function buildSlabSearch(slabs, coordinates) { return function(p) { var bucket = bsearch.le(coordinates, p[0]) if(bucket < 0) { return 1 } var root = slabs[bucket] if(!root) { if(bucket > 0 && coordinates[bucket] === p[0]) { root = slabs[bucket-1] } else { return 1 } } var lastOrientation = 1 while(root) { var s = root.key var o = orient(p, s[0], s[1]) if(s[0][0] < s[1][0]) { if(o < 0) { root = root.left } else if(o > 0) { lastOrientation = -1 root = root.right } else { return 0 } } else { if(o > 0) { root = root.left } else if(o < 0) { lastOrientation = 1 root = root.right } else { return 0 } } } return lastOrientation } } function classifyEmpty(p) { return 1 } function createClassifyVertical(testVertical) { return function classify(p) { if(testVertical(p[0], p[1])) { return 0 } return 1 } } function createClassifyPointDegen(testVertical, testNormal) { return function classify(p) { if(testVertical(p[0], p[1])) { return 0 } return testNormal(p) } } function preprocessPolygon(loops) { //Compute number of loops var numLoops = loops.length //Unpack segments var segments = [] var vsegments = [] var ptr = 0 for(var i=0; i<numLoops; ++i) { var loop = loops[i] var numVertices = loop.length for(var s=numVertices-1,t=0; t<numVertices; s=(t++)) { var a = loop[s] var b = loop[t] if(a[0] === b[0]) { vsegments.push([a,b]) } else { segments.push([a,b]) } } } //Degenerate case: All loops are empty if(segments.length === 0) { if(vsegments.length === 0) { return classifyEmpty } else { return createClassifyVertical(buildVerticalIndex(vsegments)) } } //Build slab decomposition var slabs = makeSlabs(segments) var testSlab = buildSlabSearch(slabs.slabs, slabs.coordinates) if(vsegments.length === 0) { return testSlab } else { return createClassifyPointDegen( buildVerticalIndex(vsegments), testSlab) } }