Skip to content

Commit 12b43c6

Browse files
committed
special case of polygon for rectangles
1 parent c0a94f7 commit 12b43c6

File tree

2 files changed

+52
-6
lines changed

2 files changed

+52
-6
lines changed

src/lib/polygon.js

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ var dot = require('./matrix').dot;
1414
* Turn an array of [x, y] pairs into a polygon object
1515
* that can test if points are inside it
1616
*
17-
* @param pts Array of [x, y] pairs
17+
* @param ptsIn Array of [x, y] pairs
1818
*
1919
* @returns polygon Object {xmin, xmax, ymin, ymax, pts, contains}
2020
* (x|y)(min|max) are the bounding rect of the polygon
@@ -43,6 +43,47 @@ polygon.tester = function tester(ptsIn) {
4343
ymax = Math.max(ymax, pts[i][1]);
4444
}
4545

46+
// do we have a rectangle? Handle this here, so we can use the same
47+
// tester for the rectangular case without sacrificing speed
48+
49+
var isRect = false,
50+
rectFirstEdgeTest;
51+
52+
function onFirstVert(pt) { return pt[0] === pts[0][0]; }
53+
function onFirstHorz(pt) { return pt[1] === pts[0][1]; }
54+
55+
if(pts.length === 5) {
56+
if(pts[0][0] === pts[1][0]) { // vert, horz, vert, horz
57+
if(pts[2][0] === pts[3][0] &&
58+
pts[0][1] === pts[3][1] &&
59+
pts[1][1] === pts[2][1]) {
60+
isRect = true;
61+
rectFirstEdgeTest = onFirstVert;
62+
}
63+
}
64+
else if(pts[0][1] === pts[1][1]) { // horz, vert, horz, vert
65+
if(pts[2][1] === pts[3][1] &&
66+
pts[0][0] === pts[3][0] &&
67+
pts[1][0] === pts[2][0]) {
68+
isRect = true;
69+
rectFirstEdgeTest = onFirstHorz;
70+
}
71+
}
72+
}
73+
74+
function rectContains(pt, omitFirstEdge) {
75+
var x = pt[0],
76+
y = pt[1];
77+
78+
if(x < xmin || x > xmax || y < ymin || y > ymax) {
79+
// pt is outside the bounding box of polygon
80+
return false;
81+
}
82+
if(omitFirstEdge && rectFirstEdgeTest(pt)) return false;
83+
84+
return true;
85+
}
86+
4687
function contains(pt, omitFirstEdge) {
4788
var x = pt[0],
4889
y = pt[1];
@@ -115,7 +156,8 @@ polygon.tester = function tester(ptsIn) {
115156
ymin: ymin,
116157
ymax: ymax,
117158
pts: pts,
118-
contains: contains
159+
contains: isRect ? rectContains : contains,
160+
isRect: isRect
119161
};
120162
};
121163

test/jasmine/tests/polygon_test.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,8 @@ describe('polygon.tester', function() {
6464
});
6565

6666
it('should prepare a polygon object correctly', function() {
67-
var polyPts = [
68-
[[0, 0], [0, 1], [1, 1], [1, 0]],
69-
[[-2.34, -0.67], [0.12345, 1.2345], [1.3456, 1.4567], [1.5678, 0.21345]]
70-
];
67+
var polyPts = [squareCW, squareCCW, bowtie, squareish, equilateralTriangle,
68+
zigzag, donut, donut2];
7169

7270
polyPts.forEach(function(polyPt) {
7371
var poly = polygonTester(polyPt),
@@ -93,6 +91,12 @@ describe('polygon.tester', function() {
9391

9492
polyPts.forEach(function(polyPt) {
9593
var poly = polygonTester(polyPt);
94+
95+
var isRect = polyPt === squareCW || polyPt === squareCCW;
96+
expect(poly.isRect).toBe(isRect);
97+
// to make sure we're only using the bounds and first pt, delete the rest
98+
if(isRect) poly.pts.splice(1, poly.pts.length);
99+
96100
poly.pts.forEach(function(pt1, i) {
97101
if(!i) return;
98102
var pt0 = poly.pts[i - 1],

0 commit comments

Comments
 (0)