UNPKG

1.67 kBJavaScriptView Raw
1import processPolygon from 'point-in-big-polygon'
2import { ringArea as ringAreaSpherical } from 'topojson/lib/topojson/spherical.js'
3import { ringArea as ringAreaCartesian } from 'topojson/lib/topojson/cartesian.js'
4
5/**
6 * Modifies the point order of the given polygon rings such that the first ring is ordered
7 * clockwise and all others anti-clockwise. Modification happens in-place.
8 *
9 * @param {Array} rings - Polygon rings to reorder (in-place)
10 * @param {boolean} [isCartesian=false] - whether coordinates are cartesian or spherical degrees
11 */
12export function ensureClockwisePolygon (rings, isCartesian = false) {
13 // first ring = exterior, clockwise
14 // other rings = interior, anti-clockwise
15 let ringAreaFn = isCartesian ? ringAreaCartesian : ringAreaSpherical
16 for (let i = 0; i < rings.length; i++) {
17 let area = ringAreaFn(rings[i])
18 if ((i === 0 && area < 0) || (i > 0 && area > 0)) {
19 rings[i].reverse()
20 }
21 }
22}
23
24/**
25 * Preprocesses an array of polygons to answer the point-in-polygon question efficiently.
26 *
27 * @param {Array} polygons - A list of polygons where the exterior ring of each polygon is in clockwise and the interior rings in anti-clockwise order.
28 * @return {function} A function classify(point) which returns the index of the first found polygon containing point, or -1 if not in any polygon.
29 */
30export function getPointInPolygonsFn (polygons) {
31 let classifiers = polygons.map(processPolygon)
32 let npolys = polygons.length
33
34 return point => {
35 for (let i = 0; i < npolys; i++) {
36 if (classifiers[i](point) <= 0) {
37 return i
38 }
39 }
40 return -1
41 }
42}