Skip to content

Commit f28576e

Browse files
committed
try to use polygon contains instead of point-in-polygon
1 parent 46709ab commit f28576e

File tree

4 files changed

+90
-81
lines changed

4 files changed

+90
-81
lines changed

package-lock.json

-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@
105105
"mouse-wheel": "^1.2.0",
106106
"native-promise-only": "^0.8.1",
107107
"parse-svg-path": "^0.1.2",
108-
"point-in-polygon": "^1.1.0",
109108
"polybooljs": "^1.2.0",
110109
"probe-image-size": "^7.2.3",
111110
"regl": "npm:@plotly/regl@^2.1.2",

src/components/selections/select.js

+11-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict';
22

33
var polybool = require('polybooljs');
4-
var pointInPolygon = require('point-in-polygon/nested');
54

65
var Registry = require('../../registry');
76
var dashStyle = require('../drawing').dashStyle;
@@ -32,7 +31,7 @@ var activateLastSelection = require('./draw').activateLastSelection;
3231

3332
var Lib = require('../../lib');
3433
var ascending = Lib.sorterAsc;
35-
var polygon = require('../../lib/polygon');
34+
var libPolygon = require('../../lib/polygon');
3635
var throttle = require('../../lib/throttle');
3736
var getFromId = require('../../plots/cartesian/axis_ids').getFromId;
3837
var clearGlCanvases = require('../../lib/clear_gl_canvases');
@@ -42,8 +41,9 @@ var redrawReglTraces = require('../../plot_api/subroutines').redrawReglTraces;
4241
var constants = require('./constants');
4342
var MINSELECT = constants.MINSELECT;
4443

45-
var filteredPolygon = polygon.filter;
46-
var polygonTester = polygon.tester;
44+
var filteredPolygon = libPolygon.filter;
45+
var polygonTester = libPolygon.tester;
46+
var polygonContains = libPolygon.contains;
4747

4848
var helpers = require('./helpers');
4949
var p2r = helpers.p2r;
@@ -596,7 +596,7 @@ function multiTester(list) {
596596
if(isPointSelectionDef(list[i])) {
597597
testers.push(newPointNumTester(list[i]));
598598
} else {
599-
var tester = polygon.tester(list[i]);
599+
var tester = polygonTester(list[i]);
600600
tester.subtract = !!list[i].subtract;
601601
testers.push(tester);
602602

@@ -1402,7 +1402,12 @@ function getSubtract(polygon, previousPolygons) {
14021402

14031403
// find out if a point of polygon is inside previous polygons
14041404
for(var k = 0; k < polygon.length; k++) {
1405-
if(pointInPolygon(polygon[k], previousPolygon)) {
1405+
if(polygonContains(previousPolygon, polygon[k], false, {
1406+
xmin: previousPolygon.xmin,
1407+
xmax: previousPolygon.xmax,
1408+
ymin: previousPolygon.ymin,
1409+
ymax: previousPolygon.ymax
1410+
})) {
14061411
subtract = !subtract;
14071412
break;
14081413
}

src/lib/polygon.js

+79-63
Original file line numberDiff line numberDiff line change
@@ -82,69 +82,12 @@ polygon.tester = function tester(ptsIn) {
8282
}
8383

8484
function contains(pt, omitFirstEdge) {
85-
var x = pt[0];
86-
var y = pt[1];
87-
88-
if(x === BADNUM || x < xmin || x > xmax || y === BADNUM || y < ymin || y > ymax) {
89-
// pt is outside the bounding box of polygon
90-
return false;
91-
}
92-
93-
var imax = pts.length;
94-
var x1 = pts[0][0];
95-
var y1 = pts[0][1];
96-
var crossings = 0;
97-
var i;
98-
var x0;
99-
var y0;
100-
var xmini;
101-
var ycross;
102-
103-
for(i = 1; i < imax; i++) {
104-
// find all crossings of a vertical line upward from pt with
105-
// polygon segments
106-
// crossings exactly at xmax don't count, unless the point is
107-
// exactly on the segment, then it counts as inside.
108-
x0 = x1;
109-
y0 = y1;
110-
x1 = pts[i][0];
111-
y1 = pts[i][1];
112-
xmini = Math.min(x0, x1);
113-
114-
if(x < xmini || x > Math.max(x0, x1) || y > Math.max(y0, y1)) {
115-
// outside the bounding box of this segment, it's only a crossing
116-
// if it's below the box.
117-
118-
continue;
119-
} else if(y < Math.min(y0, y1)) {
120-
// don't count the left-most point of the segment as a crossing
121-
// because we don't want to double-count adjacent crossings
122-
// UNLESS the polygon turns past vertical at exactly this x
123-
// Note that this is repeated below, but we can't factor it out
124-
// because
125-
if(x !== xmini) crossings++;
126-
} else {
127-
// inside the bounding box, check the actual line intercept
128-
129-
// vertical segment - we know already that the point is exactly
130-
// on the segment, so mark the crossing as exactly at the point.
131-
if(x1 === x0) ycross = y;
132-
// any other angle
133-
else ycross = y0 + (x - x0) * (y1 - y0) / (x1 - x0);
134-
135-
// exactly on the edge: counts as inside the polygon, unless it's the
136-
// first edge and we're omitting it.
137-
if(y === ycross) {
138-
if(i === 1 && omitFirstEdge) return false;
139-
return true;
140-
}
141-
142-
if(y <= ycross && x !== xmini) crossings++;
143-
}
144-
}
145-
146-
// if we've gotten this far, odd crossings means inside, even is outside
147-
return crossings % 2 === 1;
85+
return polygon.contains(pts, pt, omitFirstEdge, {
86+
xmin: xmin,
87+
xmax: xmax,
88+
ymin: ymin,
89+
ymax: ymax
90+
});
14891
}
14992

15093
// detect if poly is degenerate
@@ -169,6 +112,79 @@ polygon.tester = function tester(ptsIn) {
169112
};
170113
};
171114

115+
polygon.contains = function(pts, pt, omitFirstEdge, opts) {
116+
var x = pt[0];
117+
var y = pt[1];
118+
119+
if(opts) {
120+
var xmin = opts.xmin;
121+
var xmax = opts.xmax;
122+
var ymin = opts.ymin;
123+
var ymax = opts.ymax;
124+
125+
if(x === BADNUM || x < xmin || x > xmax || y === BADNUM || y < ymin || y > ymax) {
126+
// pt is outside the bounding box of polygon
127+
return false;
128+
}
129+
}
130+
131+
var imax = pts.length;
132+
var x1 = pts[0][0];
133+
var y1 = pts[0][1];
134+
var crossings = 0;
135+
var i;
136+
var x0;
137+
var y0;
138+
var xmini;
139+
var ycross;
140+
141+
for(i = 1; i < imax; i++) {
142+
// find all crossings of a vertical line upward from pt with
143+
// polygon segments
144+
// crossings exactly at xmax don't count, unless the point is
145+
// exactly on the segment, then it counts as inside.
146+
x0 = x1;
147+
y0 = y1;
148+
x1 = pts[i][0];
149+
y1 = pts[i][1];
150+
xmini = Math.min(x0, x1);
151+
152+
if(x < xmini || x > Math.max(x0, x1) || y > Math.max(y0, y1)) {
153+
// outside the bounding box of this segment, it's only a crossing
154+
// if it's below the box.
155+
156+
continue;
157+
} else if(y < Math.min(y0, y1)) {
158+
// don't count the left-most point of the segment as a crossing
159+
// because we don't want to double-count adjacent crossings
160+
// UNLESS the polygon turns past vertical at exactly this x
161+
// Note that this is repeated below, but we can't factor it out
162+
// because
163+
if(x !== xmini) crossings++;
164+
} else {
165+
// inside the bounding box, check the actual line intercept
166+
167+
// vertical segment - we know already that the point is exactly
168+
// on the segment, so mark the crossing as exactly at the point.
169+
if(x1 === x0) ycross = y;
170+
// any other angle
171+
else ycross = y0 + (x - x0) * (y1 - y0) / (x1 - x0);
172+
173+
// exactly on the edge: counts as inside the polygon, unless it's the
174+
// first edge and we're omitting it.
175+
if(y === ycross) {
176+
if(i === 1 && omitFirstEdge) return false;
177+
return true;
178+
}
179+
180+
if(y <= ycross && x !== xmini) crossings++;
181+
}
182+
}
183+
184+
// if we've gotten this far, odd crossings means inside, even is outside
185+
return crossings % 2 === 1;
186+
};
187+
172188
/**
173189
* Test if a segment of a points array is bent or straight
174190
*

0 commit comments

Comments
 (0)