Skip to content

Commit

Permalink
Add optional epsilon to pointOnLine, pointOnPolygon, and pointWithLine.
Browse files Browse the repository at this point in the history
Fixes #19.
  • Loading branch information
HarryStevens committed Nov 28, 2020
1 parent 746dfab commit d1e08aa
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 16 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ A JavaScript library for doing geometry. [![Build Status](https://travis-ci.org/
### Web browser
In vanilla, a `geometric` global is exported. You can use the latest version from unpkg.
```html
<script src="https://unpkg.com/geometric@2.2.4/build/geometric.js"></script>
<script src="https://unpkg.com/geometric@2.2.4/build/geometric.min.js"></script>
<script src="https://unpkg.com/geometric@2.2.5/build/geometric.js"></script>
<script src="https://unpkg.com/geometric@2.2.5/build/geometric.min.js"></script>
```
If you'd rather host it yourself, download the latest release from the [`build` directory](https://github.com/HarryStevens/geometric/tree/master/build).

Expand Down Expand Up @@ -143,19 +143,19 @@ Returns a boolean representing whether a <i>line</i> intersects a <i>polygon</i>

Returns a boolean representing whether a <i>point</i> is inside of a <i>polygon</i>. Uses [ray casting](https://en.wikipedia.org/wiki/Point_in_polygon#Ray_casting_algorithm).

<a name="pointOnPolygon" href="#pointOnPolygon">#</a> geometric.<b>pointOnPolygon</b>(<i>point</i>, <i>polygon</i>) · [Source](https://github.com/HarryStevens/geometric/blob/master/src/relationships/pointOnPolygon.js "Source"), [Example](https://observablehq.com/@harrystevens/geometric-pointonpolygon "Example")
<a name="pointOnPolygon" href="#pointOnPolygon">#</a> geometric.<b>pointOnPolygon</b>(<i>point</i>, <i>polygon</i>[, <i>epsilon</i>]) · [Source](https://github.com/HarryStevens/geometric/blob/master/src/relationships/pointOnPolygon.js "Source"), [Example](https://observablehq.com/@harrystevens/geometric-pointonpolygon "Example")

Returns a boolean representing whether a <i>point</i> is located on one of the edges of a <i>polygon</i>.
Returns a boolean representing whether a <i>point</i> is located on one of the edges of a <i>polygon</i>. An optional <i>epsilon</i> number, such as 1e-6, can be passed to reduce the precision with which the relationship is measured.

<a name="pointOnLine" href="#pointOnLine">#</a> geometric.<b>pointOnLine</b>(<i>point</i>, <i>line</i>) · [Source](https://github.com/HarryStevens/geometric/blob/master/src/relationships/pointOnLine.js#L17 "Source"), [Example](https://observablehq.com/@harrystevens/geometric-pointonline-geometric-pointwithline "Example")

Returns a boolean representing whether a <i>point</i> is collinear with a <i>line</i> and is also located on the line segment. See also [pointWithLine](#pointWithLine).
Returns a boolean representing whether a <i>point</i> is collinear with a <i>line</i> and is also located on the line segment. An optional <i>epsilon</i> number, such as 1e-6, can be passed to reduce the precision with which the relationship is measured. See also [pointWithLine](#pointWithLine).

[<img width="150" src="https://raw.githubusercontent.com/HarryStevens/geometric/master/img/point-on-with-line.png" />](https://observablehq.com/d/c463ce4b7cbcd048)

<a name="pointWithLine" href="#pointWithLine">#</a> geometric.<b>pointWithLine</b>(<i>point</i>, <i>line</i>) · [Source](https://github.com/HarryStevens/geometric/blob/master/src/relationships/pointOnLine.js#L21 "Source"), [Example](https://observablehq.com/@harrystevens/geometric-pointonline-geometric-pointwithline "Example")
<a name="pointWithLine" href="#pointWithLine">#</a> geometric.<b>pointWithLine</b>(<i>point</i>, <i>line</i>[, <i>epsilon</i>]) · [Source](https://github.com/HarryStevens/geometric/blob/master/src/relationships/pointOnLine.js#L21 "Source"), [Example](https://observablehq.com/@harrystevens/geometric-pointonline-geometric-pointwithline "Example")

Returns a boolean representing whether a <i>point</i> is collinear with a <i>line</i>. See also [pointOnLine](#pointOnLine).
Returns a boolean representing whether a <i>point</i> is collinear with a <i>line</i>. An optional <i>epsilon</i> number, such as 1e-6, can be passed to reduce the precision with which the relationship is measured. See also [pointOnLine](#pointOnLine).

<a name="pointLeftofLine" href="#pointLeftofLine">#</a> geometric.<b>pointLeftofLine</b>(<i>point</i>, <i>line</i>) · [Source](https://github.com/HarryStevens/geometric/blob/master/src/relationships/pointOnLine.js#L9 "Source"), [Example](https://observablehq.com/@harrystevens/geometric-pointleftofline-geometric-pointrightofline-g "Example")

Expand Down
6 changes: 4 additions & 2 deletions build/geometric.js
Original file line number Diff line number Diff line change
Expand Up @@ -412,11 +412,13 @@
return cross(point, t[1], t[0]) > 0;
}
function pointOnLine(point, line) {
var epsilon = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
var l = lineLength(line);
return pointWithLine(point, line) && lineLength([line[0], point]) <= l && lineLength([line[1], point]) <= l;
return pointWithLine(point, line, epsilon) && lineLength([line[0], point]) <= l && lineLength([line[1], point]) <= l;
}
function pointWithLine(point, line) {
return cross(point, line[0], line[1]) === 0;
var epsilon = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
return Math.abs(cross(point, line[0], line[1])) <= epsilon;
}

// Returns a boolean.
Expand Down
1 change: 0 additions & 1 deletion build/geometric.min.js

This file was deleted.

Binary file removed build/geometric.zip
Binary file not shown.
8 changes: 4 additions & 4 deletions src/relationships/pointOnLine.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ export function pointRightofLine(point, line){
const t = topPointFirst(line);
return cross(point, t[1], t[0]) > 0;
}
export function pointOnLine(point, line){
export function pointOnLine(point, line, epsilon = 0){
const l = lineLength(line);
return pointWithLine(point, line) && lineLength([line[0], point]) <= l && lineLength([line[1], point]) <= l;
return pointWithLine(point, line, epsilon) && lineLength([line[0], point]) <= l && lineLength([line[1], point]) <= l;
}
export function pointWithLine(point, line){
return cross(point, line[0], line[1]) === 0;
export function pointWithLine(point, line, epsilon = 0){
return Math.abs(cross(point, line[0], line[1])) <= epsilon;
}
4 changes: 2 additions & 2 deletions src/relationships/pointOnPolygon.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { pointOnLine } from "./pointOnLine";

// Determines whether a point is located on one of the edges of a polygon.
// Returns a boolean.
export function pointOnPolygon(point, polygon){
export function pointOnPolygon(point, polygon, epsilon = 0){
let on = false;
const closed = close(polygon);

for (let i = 0, l = closed.length - 1; i < l; i++){
if (pointOnLine(point, [closed[i], closed[i + 1]])){
if (pointOnLine(point, [closed[i], closed[i + 1]], epsilon)){
on = true;
break;
}
Expand Down
12 changes: 12 additions & 0 deletions test/pointOnLine-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,17 @@ tape("pointWithLine(point, line) determines whether a point is collinear with a
// The point can be located outside of the line segment
test.equal(geometric.pointWithLine([1, 100], line), true);

test.end();
});

tape("pointWithLine takes an epsilon test", function(test){
// See https://github.com/HarryStevens/geometric/issues/19
var relationships = [{"point":[-50.94850158691406,-3.027209166609623],"line":[[-49.69850158691406,-3.0271999835968018],[-51.19850158687358,-3.027211003212187]]},{"point":[-46.8047,-12.1569],"line":[[-46.2164,-12.0707],[-47.700552783102914,-12.288163827814842]]},{"point":[-45.41063565015793,-6.862901151180267],"line":[[-44.59149932861328,-7.436500072479248],[-45.82020378894317,-6.576101705927197]]},{"point":[-46.22977195704452,-6.289302240145567],"line":[[-44.59149932861328,-7.436500072479248],[-45.82020378894317,-6.576101705927197]]},{"point":[-33.12336051464081,-15.46659255027771],"line":[[-33.942501068115234,-14.892999649047852],[-32.713790276416105,-15.753388973924736]]},{"point":[-32.30421998684139,-16.040185433528965],"line":[[-33.942501068115234,-14.892999649047852],[-32.713790276416105,-15.753388973924736]]},{"point":[-33.94243496656418,-14.89300149679184],"line":[[-33.12329864501953,-15.46660041809082],[-34.35200310534942,-14.60620205153877]]},{"point":[-34.76157127345077,-14.319402585757139],"line":[[-33.12329864501953,-15.46660041809082],[-34.35200310534942,-14.60620205153877]]},{"point":[-33.94245994091034,-14.892992734909058],"line":[[-34.761600494384766,-14.3193998336792],[-33.53288970268564,-15.179789158556083]]},{"point":[-33.12331941311092,-15.466585618160314],"line":[[-34.761600494384766,-14.3193998336792],[-33.53288970268564,-15.179789158556083]]},{"point":[-34.76163738965988,-14.31940072774887],"line":[[-33.942501068115234,-14.892999649047852],[-35.17120552844512,-14.0326012824958]]}];

relationships.forEach(relationship => {
test.equal(geometric.pointWithLine(relationship.point, relationship.line), false);
test.equal(geometric.pointWithLine(relationship.point, relationship.line, 1e-6), true);
});

test.end();
});

0 comments on commit d1e08aa

Please sign in to comment.