1
var t = db.geo_s2overlappingpolys
4
t.ensureIndex( { geo : "2dsphere" } );
6
var minError = 0.8e-13;
8
var canonPoly = {type: "Polygon",
10
[[-1.0, -1.0], [1.0, -1.0], [1.0, 1.0], [-1.0, 1.0], [-1.0, -1.0]]
12
t.insert({geo: canonPoly});
14
// Test 1: If a poly completely encloses the canonPoly, we expect the canonPoly
15
// to be returned for both $within and $geoIntersect
17
var outerPoly = {type: "Polygon",
19
[[-2.0, -2.0], [2.0, -2.0], [2.0, 2.0], [-2.0, 2.0], [-2.0, -2.0]]
21
var result = t.find({geo: {$within: {$geometry: outerPoly}}});
22
assert.eq(result.count(), 1);
23
result = t.find({geo: {$geoIntersects: {$geometry: outerPoly}}});
24
assert.eq(result.count(), 1);
27
// Test 2: If a poly that covers half of the canonPoly, we expect that it should
28
// geoIntersect, but should not be within.
30
var partialPoly = {type: "Polygon",
32
[[-2.0, -2.0], [2.0, -2.0], [2.0, 0.0], [-2.0, 0.0], [-2.0, -2.0]]
35
//Should not be within
36
result = t.find({geo: {$within: {$geometry: partialPoly}}});
37
assert.eq(result.count(), 0);
39
//This should however count as a geoIntersect
40
result = t.find({geo: {$geoIntersects: {$geometry: partialPoly}}});
41
assert.eq(result.count(), 1);
44
// Test 3: Polygons that intersect at a point or an edge have undefined
45
// behaviour in s2 The s2 library we're using appears to have
46
// the following behaviour.
48
// Case (a): Polygons that intersect at one point (not a vertex).
49
// behaviour: geoIntersects.
51
var sharedPointPoly = {type: "Polygon",
53
[[0.0, -2.0], [0.0, -1.0], [1.0, -2.0], [0.0, -2.0]]
56
result = t.find({geo: {$geoIntersects: {$geometry: sharedPointPoly}}});
57
assert.eq(result.count(), 1);
59
// Case (b): Polygons that intersect at one point (a vertex).
60
// behaviour: not geoIntersect
62
var sharedVertexPoly = {type: "Polygon",
64
[[0.0, -2.0], [1.0, -1.0], [1.0, -2.0], [0.0, -2.0]]
67
result = t.find({geo: {$geoIntersects: {$geometry: sharedVertexPoly}}});
68
assert.eq(result.count(), 0);
70
// Case (c): Polygons that intesersect at one point that is very close to a
71
// vertex should have the same behaviour as Case (b).
73
var almostSharedVertexPoly = {type: "Polygon",
75
[[0.0, -2.0], [1.0 - minError, -1.0], [1.0, -2.0], [0.0, -2.0]]
78
result = t.find({geo: {$geoIntersects: {$geometry: almostSharedVertexPoly}}});
79
assert.eq(result.count(), 0);
82
// Case (d): Polygons that intesersect at one point that is not quite as close
83
// to a vertex should behave as though it were not a vertex, and should
86
var notCloseEnoughSharedVertexPoly = {type: "Polygon",
88
[[0.0, -2.0], [1.0 - (10 * minError), -1.0], [1.0, -2.0], [0.0, -2.0]]
91
result = t.find({geo: {$geoIntersects: {$geometry: notCloseEnoughSharedVertexPoly}}});
92
assert.eq(result.count(), 1);
94
// Case (e): Polygons that come very close to having a point intersection
95
// on a non-vertex coordinate should intersect.
97
var almostSharedPointPoly = {type: "Polygon",
99
[[0.0, -2.0], [0.0, (-1.0 - minError)], [1.0, -2.0], [0.0, -2.0]]
102
result = t.find({geo: {$geoIntersects: {$geometry: almostSharedPointPoly}}});
103
assert.eq(result.count(), 1);
106
// Case (f): If we increase the error a little, it should no longer act
107
// as though it's intersecting.
108
// NOTE: I think this error bound seems odd. Going to 0.000152297 will break this test.
109
// I've confirmed there is an error bound, but it's a lot larger than we experienced above.
110
var errorBound = 0.000152298
111
var notCloseEnoughSharedPointPoly = {type: "Polygon",
113
[[0.0, -2.0], [0.0, -1.0 - errorBound], [1.0, -2.0], [0.0, -2.0]]
116
result = t.find({geo: {$geoIntersects: {$geometry: notCloseEnoughSharedPointPoly}}});
117
assert.eq(result.count(), 0);
119
/* Test 3: Importantly, polygons with shared edges have undefined intersection
120
* under s2. Therefore these test serve more to make sure nothing changes than
121
* to confirm an expected behaviour.
124
// Case 1: A polygon who shares an edge with another polygon, where the searching
125
// polygon's edge is fully covered by the canon polygon's edge.
126
// Result: No intersection.
127
var fullyCoveredEdgePoly = {type: "Polygon",
129
[[-2.0, -0.5], [-1.0, -0.5], [-1.0, 0.5], [-2.0, 0.5], [-2.0, -0.5]]
132
result = t.find({geo: {$geoIntersects: {$geometry: fullyCoveredEdgePoly}}});
133
assert.eq(result.count(), 0);
135
// Case 2: A polygon who shares an edge with another polygon, where the searching
136
// polygon's edge fully covers the canon polygon's edge.
137
// Result: Intersection.
138
var coveringEdgePoly = {type: "Polygon",
140
[[-2.0, -1.5], [-1.0, -1.5], [-1.0, 1.5], [-2.0, 1.5], [-2.0, -1.5]]
143
result = t.find({geo: {$geoIntersects: {$geometry: coveringEdgePoly}}});
144
assert.eq(result.count(), 1);
146
// Case 2a: same as Case 2, except pulled slightly away from the polygon.
147
// Result: Intersection.
148
// NOTE: Scales of errors?
149
var closebyCoveringEdgePoly = {type: "Polygon",
151
[[-2.0, -1.5], [-1.0 - (minError / 1000), -1.5], [-1.0 - (minError / 1000), 1.5], [-2.0, 1.5], [-2.0, -1.5]]
154
result = t.find({geo: {$geoIntersects: {$geometry: closebyCoveringEdgePoly}}});
155
assert.eq(result.count(), 1);
157
// Case 2b: same as Case 4, except pulled slightly away from the polygon, so that it's not intersecting.
158
// Result: No Intersection.
159
// NOTE: Scales of errors?
160
var notCloseEnoughCoveringEdgePoly = {type: "Polygon",
162
[[-2.0, -1.5], [-1.0 - (minError / 100), -1.5], [-1.0 - (minError / 100), 1.5], [-2.0, 1.5], [-2.0, -1.5]]
165
result = t.find({geo: {$geoIntersects: {$geometry: notCloseEnoughCoveringEdgePoly}}});
166
assert.eq(result.count(), 0);
168
// Case 3: A polygon who shares an edge with another polygon, where the searching
169
// polygon's edge partially covers by the canon polygon's edge.
170
// Result: No intersection.
171
var partiallyCoveringEdgePoly = {type: "Polygon",
173
[[-2.0, -1.5], [-1.0, -1.5], [-1.0, 0.5], [-2.0, 0.5], [-2.0, -1.5]]
176
result = t.find({geo: {$geoIntersects: {$geometry: partiallyCoveringEdgePoly}}});
177
assert.eq(result.count(), 0);
180
//Polygons that intersect at three non-co-linear points should geoIntersect
181
var sharedPointsPoly = {type: "Polygon",
183
[[0.0, -3.0], [0.0, -1.0], [2.0, -2.0], [1.0, 0.0], [2.0, 2.0], [0.0, 1.0], [0.0, 3.0], [3.0, 3.0], [3.0, -3.0], [0.0, -3.0]]
186
result = t.find({geo: {$geoIntersects: {$geometry: sharedPointsPoly}}});
187
assert.eq(result.count(), 1);
189
//If a polygon contains a hole, and another polygon is within that hole, it should not be within or intersect.
191
var bigHolePoly = {type: "Polygon",
193
[[-3.0, -3.0], [3.0, -3.0], [3.0, 3.0], [-3.0, 3.0], [-3.0, -3.0]],
194
[[-2.0, -2.0], [2.0, -2.0], [2.0, 2.0], [-2.0, 2.0], [-2.0, -2.0]]
196
result = t.find({geo: {$within: {$geometry: bigHolePoly}}});
197
assert.eq(result.count(), 0);
198
result = t.find({geo: {$geoIntersects: {$geometry: bigHolePoly}}});
199
assert.eq(result.count(), 0);
201
// If a polygon has a hole, and another polygon is contained partially by that hole, it should be an intersection
204
var internalOverlapPoly = {type: "Polygon",
206
[[-3.0, -3.0], [3.0, -3.0], [3.0, 3.0], [-3.0, 3.0], [-3.0, -3.0]],
207
[[-2.0, 0.0], [2.0, 0.0], [2.0, 2.0], [-2.0, 2.0], [-2.0, 0.0]]
210
result = t.find({geo: {$geoIntersects: {$geometry: internalOverlapPoly}}});
211
assert.eq(result.count(), 1);
212
result = t.find({geo: {$within: {$geometry: internalOverlapPoly}}});
213
assert.eq(result.count(), 0);