Skip to content

Commit 8a7f91b

Browse files
committed
Add error handling for incorrect input. Add more doco on inputs.
1 parent 44b8714 commit 8a7f91b

File tree

7 files changed

+91
-40
lines changed

7 files changed

+91
-40
lines changed

CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# 1.0.0
2+
- Add support for input validation to ensure rings are closed
3+

LICENSE

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2021 Rowan Winsemius
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy of
6+
this software and associated documentation files (the "Software"), to deal in
7+
the Software without restriction, including without limitation the rights to
8+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9+
the Software, and to permit persons to whom the Software is furnished to do so,
10+
subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,73 @@
1-
Based on the paper [Optimal Reliable Point-in-Polygon Test and
2-
Differential Coding Boolean Operations on Polygons](https://www.researchgate.net/publication/328261365_Optimal_Reliable_Point-in-Polygon_Test_and_Differential_Coding_Boolean_Operations_on_Polygons)
1+
A small library for detecting in a point lies inside a polygon
32

3+
**Features**
44
- Works on polygons with holes
5-
- Works with degenerate polyons
6-
- Reports 0 if on the edge
5+
- Works with degenerate/self-intersecting polyons
6+
- Returns `0` if on the edge
77
- Not effected by floating point errors
88

99

1010
### Usage
1111
Install via `npm install point-in-polygon-hao`
1212

1313
````
14-
const inside = require('point-in-polygon-hao')
15-
const polygon = [ [ [ 1, 1 ], [ 1, 2 ], [ 2, 2 ], [ 2, 1 ], [ 1, 1 ] ] ];
14+
import inside from 'point-in-polygon-hao'
15+
16+
const polygon = [
17+
[
18+
[1, 1],
19+
[1, 2],
20+
[2, 2],
21+
[2, 1],
22+
[1, 1]
23+
]
24+
];
25+
1626
inside([ 1.5, 1.5 ], polygon)
17-
// returns true
27+
// => true
1828
1929
inside([ 4.9, 1.2 ], polygon)
20-
// returns false
30+
// => false
2131
2232
inside([1, 2], polygon)
23-
// returns 0 to indicate on edge
33+
// => 0 to indicate on edge
2434
````
2535

36+
**Note:** The input polygon format aligns with the GeoJson specification for polygons. This means that the first and last coordinate in a polygon must be repeated, if not this library will throw an error.
37+
````
38+
const polygonWithHole = [
39+
[
40+
[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]
41+
],
42+
[
43+
[0.1, 0.1], [0.1, 0.9], [0.9, 0.9], [0.9, 0.1], [0.1, 0.1]
44+
]
45+
]
46+
````
47+
The library does not support multi-polygons.
2648

2749
### Comparisons
2850
Some rough comparisons to similar libraries.
2951
While `point-in-polygon` is slightly faster in most cases it does not support polygons with holes or degenerate polygons.
3052

53+
````
54+
// For a point in a much larger geometry (700+ vertices)
55+
point-in-poly-hao x 474,180 ops/sec ±0.55% (93 runs sampled)
56+
point-in-polygon x 489,649 ops/sec ±0.75% (91 runs sampled)
57+
robust-point-in-polygon x 376,268 ops/sec ±0.79% (89 runs sampled)
58+
````
59+
3160
````
3261
// For a point in bounding box check
3362
point-in-poly-hao x 29,365,704 ops/sec ±1.30% (90 runs sampled)
34-
turf-point-in-polygon x 7,142,567 ops/sec ±0.61% (93 runs sampled)
3563
point-in-polygon x 42,339,450 ops/sec ±0.78% (95 runs sampled)
3664
robust-point-in-polygon x 20,675,569 ops/sec ±0.65% (95 runs sampled)
3765
````
3866

39-
````
40-
// For a point in a much larger geometry (700+ vertices)
41-
point-in-poly-hao x 474,180 ops/sec ±0.55% (93 runs sampled)
42-
turf-point-in-polygon x 214,584 ops/sec ±0.74% (95 runs sampled)
43-
point-in-polygon x 489,649 ops/sec ±0.75% (91 runs sampled)
44-
robust-point-in-polygon x 376,268 ops/sec ±0.79% (89 runs sampled)
45-
````
67+
### Algorithm
68+
This library is based on the paper [Optimal Reliable Point-in-Polygon Test and
69+
Differential Coding Boolean Operations on Polygons](https://www.researchgate.net/publication/328261365_Optimal_Reliable_Point-in-Polygon_Test_and_Differential_Coding_Boolean_Operations_on_Polygons)
4670

4771
### Other notes
4872
* Works irrespective of winding order of polygon
49-
* Does not appear to be effected by flaoting point errors compared to `point-in-polygon`
73+
* Does not appear to be effected by floating point errors compared to `point-in-polygon` or `robust-point-in-polygon`

package.json

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "point-in-polygon-hao",
3-
"version": "0.0.7",
3+
"version": "1.0.0",
44
"description": "A point in polygon based on the paper Optimal Reliable Point-in-Polygon Test and Differential Coding Boolean Operations on Polygons",
55
"main": "dist/pointInPolygon.js",
66
"module": "src/index.js",
@@ -9,17 +9,17 @@
99
"scripts": {
1010
"bench": "npm run build && node test/bench.js",
1111
"build": "rollup -c",
12-
"test": "ava -v"
12+
"test": "ava"
13+
},
14+
"dependencies": {
1315
},
14-
"dependencies": {},
1516
"devDependencies": {
1617
"@turf/boolean-point-in-polygon": "^6.0.1",
17-
"ava": "^1.3.1",
18+
"ava": "^3.15.0",
1819
"benchmark": "^2.1.4",
1920
"eslint": "^5.15.3",
2021
"eslint-config-mourner": "^3.0.0",
2122
"esm": "^3.2.20",
22-
"jsts": "^2.0.3",
2323
"load-json-file": "^5.2.0",
2424
"point-in-polygon": "^1.0.1",
2525
"robust-point-in-polygon": "^1.0.3",
@@ -28,11 +28,12 @@
2828
},
2929
"ava": {
3030
"files": [
31-
"test/*spec.js"
31+
"test/*.spec.js"
3232
],
3333
"require": [
3434
"esm"
35-
]
35+
],
36+
"verbose": true
3637
},
3738
"keywords": [
3839
"point-in-polygon",

src/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ export default function pointInPolygon(p, polygon) {
2020
const contour = polygon[i]
2121

2222
currentP = contour[0]
23+
if (currentP[0] !== contour[contourLen][0] &&
24+
currentP[1] !== contour[contourLen][1]) {
25+
throw new Error('First and last coordinates in a ring must be the same')
26+
}
27+
2328
u1 = currentP[0] - x
2429
v1 = currentP[1] - y
2530

test/biggeom.spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import test from 'ava'
2-
const loadJsonFile = require('load-json-file')
3-
const path = require('path')
2+
import loadJsonFile from 'load-json-file'
3+
import path from 'path'
44

55
import inside from '../src/index'
66

test/test.spec.js

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import test from 'ava';
1+
import test from 'ava'
22
import inside from '../src/index'
33

44
const polygon = [[[1, 1], [1, 2], [2, 2], [2, 1], [1, 1]]];
@@ -57,18 +57,16 @@ test('is on edge of the outside', t => {
5757
t.is(inside([1.2, 1], polygonWithHole), 0)
5858
});
5959

60-
// https://github.com/substack/point-in-polygon/issues/2
61-
test('point-in-polygon issues solved', t => {
62-
const poly = [[[1, 1], [2, 1], [2, 2], [1, 2]]]
63-
t.is(inside([2, 2], poly), 0)
64-
t.is(inside([1, 1], poly), 0)
65-
});
6660

67-
// https://github.com/mikolalysenko/robust-point-in-polygon/issues/3
68-
test('robust-point-in-polygon issues solved', t => {
61+
test('error is thrown when not the same first and last coords', t => {
6962
const poly = [[[0, 0], [1, 0], [1, 1]]]
70-
t.is(inside([1, 1], poly), 0)
71-
const anotherPoly = [[[1, 1], [1, 2], [2, 3], [2, 2]]]
72-
t.is(inside([1, 1], anotherPoly), 0)
73-
t.is(inside([2, 3], anotherPoly), 0)
63+
64+
const fn = () => {
65+
inside([1, 1], poly)
66+
};
67+
68+
const error = t.throws(() => {
69+
fn()
70+
}, {instanceOf: Error})
71+
t.is(error.message, 'First and last coordinates in a ring must be the same');
7472
});

0 commit comments

Comments
 (0)