terraformer 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/lib/ext/array.rb +16 -0
- data/lib/ext/big_decimal.rb +12 -0
- data/lib/ext/big_math.rb +36 -0
- data/lib/ext/enumerable.rb +79 -0
- data/lib/ext/hash.rb +21 -0
- data/lib/terraformer/bounds.rb +7 -2
- data/lib/terraformer/circle.rb +50 -0
- data/lib/terraformer/convex_hull.rb +92 -0
- data/lib/terraformer/coordinate.rb +104 -15
- data/lib/terraformer/feature.rb +24 -0
- data/lib/terraformer/geodesic.rb +116 -0
- data/lib/terraformer/geometry/class_methods.rb +92 -0
- data/lib/terraformer/geometry.rb +41 -6
- data/lib/terraformer/line_string.rb +75 -0
- data/lib/terraformer/multi_line_string.rb +62 -0
- data/lib/terraformer/multi_point.rb +63 -0
- data/lib/terraformer/multi_polygon.rb +45 -0
- data/lib/terraformer/point.rb +49 -0
- data/lib/terraformer/polygon.rb +106 -0
- data/lib/terraformer/version.rb +1 -1
- data/lib/terraformer.rb +22 -53
- data/test/convex_hull_spec.rb +26 -0
- data/test/examples/circle.geojson +130 -130
- data/test/examples/line_string.geojson +1 -1
- data/test/examples/multi_point.geojson +1 -1
- data/test/examples/sf_county.geojson +1 -0
- data/test/examples/waldocanyon.geojson +1 -0
- data/test/geometry_spec.rb +1082 -0
- data/test/helper.rb +12 -0
- data/test/primitive_spec.rb +64 -0
- data/test/terraformer_spec.rb +42 -2
- metadata +21 -2
@@ -0,0 +1,1082 @@
|
|
1
|
+
require_relative './helper'
|
2
|
+
|
3
|
+
describe Terraformer::Geometry do
|
4
|
+
|
5
|
+
describe 'construction' do
|
6
|
+
|
7
|
+
describe Terraformer::Point do
|
8
|
+
|
9
|
+
it 'constructs from coordinate' do
|
10
|
+
c = Terraformer::Coordinate.new -122.6764, 45.5165
|
11
|
+
p = Terraformer::Point.new c
|
12
|
+
p.must_be_valid_geojson
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Terraformer::MultiPoint do
|
18
|
+
|
19
|
+
it 'constructs from coordinates' do
|
20
|
+
a = Terraformer::Coordinate.new -122.6764, 45.5165
|
21
|
+
b = a + [0.02, 0.02]
|
22
|
+
mp = Terraformer::MultiPoint.new a, b
|
23
|
+
mp.must_be_valid_geojson
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'constructs from Point objects' do
|
27
|
+
a = Terraformer::Coordinate.new -122.6764, 45.5165
|
28
|
+
b = a + [0.02, 0.02]
|
29
|
+
mp = Terraformer::MultiPoint.new a.to_point, b.to_point
|
30
|
+
mp.must_be_valid_geojson
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
describe Terraformer::LineString do
|
36
|
+
|
37
|
+
it 'constructs from coordinates' do
|
38
|
+
a = Terraformer::Coordinate.new -122.6764, 45.5165
|
39
|
+
b = a + [0.02, 0.02]
|
40
|
+
c = b + [0.1, -0.1]
|
41
|
+
ls = Terraformer::LineString.new a, b, c
|
42
|
+
ls.must_be_valid_geojson
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
describe Terraformer::MultiLineString do
|
48
|
+
|
49
|
+
it 'constructs from coordinates' do
|
50
|
+
a = Terraformer::Coordinate.new -122.6764, 45.5165
|
51
|
+
b = a + [0.02, 0.02]
|
52
|
+
c = b + [0.1, -0.1]
|
53
|
+
mls = Terraformer::MultiLineString.new a, b, c
|
54
|
+
mls.must_be_valid_geojson
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'constructs from coordinates arrays' do
|
58
|
+
a = Terraformer::Coordinate.new -122.6764, 45.5165
|
59
|
+
b = a + [0.02, 0.02]
|
60
|
+
c = b + [0.1, -0.1]
|
61
|
+
d = c + [1,1]
|
62
|
+
e = d + [0.02, 0.02]
|
63
|
+
f = e + [0.1, -0.1]
|
64
|
+
mls = Terraformer::MultiLineString.new [a, b, c], [d, e, f]
|
65
|
+
mls.must_be_valid_geojson
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'constructs from LineString objects' do
|
69
|
+
a = Terraformer::Coordinate.new -122.6764, 45.5165
|
70
|
+
b = a + [0.02, 0.02]
|
71
|
+
c = b + [0.1, -0.1]
|
72
|
+
d = c + [1,1]
|
73
|
+
e = d + [0.02, 0.02]
|
74
|
+
f = e + [0.1, -0.1]
|
75
|
+
ls_1 = Terraformer::LineString.new a, b, c
|
76
|
+
ls_2 = Terraformer::LineString.new d, e, f
|
77
|
+
mls = Terraformer::MultiLineString.new ls_1, ls_2
|
78
|
+
mls.must_be_valid_geojson
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
describe Terraformer::Polygon do
|
84
|
+
|
85
|
+
it 'constructs from coordinates' do
|
86
|
+
a = Terraformer::Coordinate.new -122.6764, 45.5165
|
87
|
+
b = a + [0, 0.02]
|
88
|
+
c = b + [0.02, 0]
|
89
|
+
d = c + [0, -0.02]
|
90
|
+
p = Terraformer::Polygon.new a, b, c, d, a
|
91
|
+
p.must_be_valid_geojson
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'constructs from coordinates array' do
|
95
|
+
a = Terraformer::Coordinate.new -122.6764, 45.5165
|
96
|
+
b = a + [0, 0.02]
|
97
|
+
c = b + [0.02, 0]
|
98
|
+
d = c + [0, -0.02]
|
99
|
+
p = Terraformer::Polygon.new [a, b, c, d, a]
|
100
|
+
p.must_be_valid_geojson
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'constructs with holes from coordinates arrays' do
|
104
|
+
a = Terraformer::Coordinate.new -122.6764, 45.5165
|
105
|
+
b = a + [0, 0.02]
|
106
|
+
c = b + [0.02, 0]
|
107
|
+
d = c + [0, -0.02]
|
108
|
+
hole = [
|
109
|
+
[ -122.67072200775145, 45.52438983143154 ],
|
110
|
+
[ -122.67072200775145, 45.53241707548722 ],
|
111
|
+
[ -122.6617956161499, 45.53241707548722 ],
|
112
|
+
[ -122.6617956161499, 45.52438983143154 ],
|
113
|
+
[ -122.67072200775145, 45.52438983143154 ]
|
114
|
+
].map {|c| Terraformer::Coordinate.new c}
|
115
|
+
p = Terraformer::Polygon.new [a, b, c, d, a], hole
|
116
|
+
p.must_be_valid_geojson
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
describe Terraformer::MultiPolygon do
|
122
|
+
|
123
|
+
it 'constructs from coordinates' do
|
124
|
+
a = Terraformer::Coordinate.new -122.6764, 45.5165
|
125
|
+
b = a + [0, 0.02]
|
126
|
+
c = b + [0.02, 0]
|
127
|
+
d = c + [0, -0.02]
|
128
|
+
mp = Terraformer::MultiPolygon.new a, b, c, d, a
|
129
|
+
mp.must_be_valid_geojson
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'constructs from coordinates array' do
|
133
|
+
a = Terraformer::Coordinate.new -122.6764, 45.5165
|
134
|
+
b = a + [0, 0.02]
|
135
|
+
c = b + [0.02, 0]
|
136
|
+
d = c + [0, -0.02]
|
137
|
+
mp = Terraformer::MultiPolygon.new [a, b, c, d, a]
|
138
|
+
mp.must_be_valid_geojson
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'constructs with holes from coordinates arrays' do
|
142
|
+
a = Terraformer::Coordinate.new -122.6764, 45.5165
|
143
|
+
b = a + [0, 0.02]
|
144
|
+
c = b + [0.02, 0]
|
145
|
+
d = c + [0, -0.02]
|
146
|
+
hole = [
|
147
|
+
[ -122.67072200775145, 45.52438983143154 ],
|
148
|
+
[ -122.67072200775145, 45.53241707548722 ],
|
149
|
+
[ -122.6617956161499, 45.53241707548722 ],
|
150
|
+
[ -122.6617956161499, 45.52438983143154 ],
|
151
|
+
[ -122.67072200775145, 45.52438983143154 ]
|
152
|
+
].map {|c| Terraformer::Coordinate.new c}
|
153
|
+
mp = Terraformer::MultiPolygon.new [a, b, c, d, a], hole
|
154
|
+
mp.must_be_valid_geojson
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'constructs from Polygon objects' do
|
158
|
+
a = Terraformer::Coordinate.new -122.6764, 45.5165
|
159
|
+
b = a + [0, 0.02]
|
160
|
+
c = b + [0.02, 0]
|
161
|
+
d = c + [0, -0.02]
|
162
|
+
p_1 = Terraformer::Polygon.new a, b, c, d, a
|
163
|
+
e = Terraformer::Coordinate.new -122.6764, 45.5165
|
164
|
+
f = a + [0, 0.02]
|
165
|
+
g = b + [0.02, 0]
|
166
|
+
h = c + [0, -0.02]
|
167
|
+
hole = [
|
168
|
+
[ -122.67072200775145, 45.52438983143154 ],
|
169
|
+
[ -122.67072200775145, 45.53241707548722 ],
|
170
|
+
[ -122.6617956161499, 45.53241707548722 ],
|
171
|
+
[ -122.6617956161499, 45.52438983143154 ],
|
172
|
+
[ -122.67072200775145, 45.52438983143154 ]
|
173
|
+
].map {|c| Terraformer::Coordinate.new c}
|
174
|
+
p_2 = Terraformer::Polygon.new [a, b, c, d, a], hole
|
175
|
+
mp = Terraformer::MultiPolygon.new p_1, p_2
|
176
|
+
mp.must_be_valid_geojson
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
|
183
|
+
describe 'intersects?' do
|
184
|
+
|
185
|
+
it 'raises on unsupported types' do
|
186
|
+
->{ PARSED_EXAMPLES[:point].intersects? PARSED_EXAMPLES[:polygon] }.must_raise ArgumentError
|
187
|
+
->{ PARSED_EXAMPLES[:multi_point].intersects? PARSED_EXAMPLES[:polygon] }.must_raise ArgumentError
|
188
|
+
->{ PARSED_EXAMPLES[:polygon].intersects? PARSED_EXAMPLES[:point] }.must_raise ArgumentError
|
189
|
+
->{ PARSED_EXAMPLES[:polygon].intersects? PARSED_EXAMPLES[:multi_point] }.must_raise ArgumentError
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'returns true for intersecting line strings' do
|
193
|
+
a = Terraformer::LineString.new [[0,0], [2,2]]
|
194
|
+
b = Terraformer::LineString.new [[0,2], [2,0]]
|
195
|
+
assert a.intersects? b
|
196
|
+
assert b.intersects? a
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'returns true for intersecting line string and multi line string' do
|
200
|
+
a = Terraformer::LineString.new [[0,0], [2,2]]
|
201
|
+
b = Terraformer::MultiLineString.new [[[0,2], [2,0]], [[3,0], [3,3]]]
|
202
|
+
assert a.intersects? b
|
203
|
+
assert b.intersects? a
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'returns true for intersecting line string and polygon' do
|
207
|
+
a = Terraformer.parse '{
|
208
|
+
"type": "LineString",
|
209
|
+
"coordinates": [
|
210
|
+
[
|
211
|
+
99.99803066253662,
|
212
|
+
-0.001394748687601125
|
213
|
+
],
|
214
|
+
[
|
215
|
+
99.99983310699463,
|
216
|
+
0
|
217
|
+
],
|
218
|
+
[
|
219
|
+
100.00056266784668,
|
220
|
+
0.0021886825556223905
|
221
|
+
]
|
222
|
+
]
|
223
|
+
}'
|
224
|
+
b = PARSED_EXAMPLES[:circle]
|
225
|
+
assert a.intersects? b
|
226
|
+
assert b.intersects? a
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'returns true for intersecting line string and multi polygon' do
|
230
|
+
a = Terraformer.parse '{
|
231
|
+
"type": "LineString",
|
232
|
+
"coordinates": [
|
233
|
+
[
|
234
|
+
-123.12103271484375,
|
235
|
+
37.67295135774715
|
236
|
+
],
|
237
|
+
[
|
238
|
+
-122.8656005859375,
|
239
|
+
37.77397129533325
|
240
|
+
],
|
241
|
+
[
|
242
|
+
-122.22976684570312,
|
243
|
+
37.790251927933284
|
244
|
+
],
|
245
|
+
[
|
246
|
+
-122.24075317382812,
|
247
|
+
37.95069515957719
|
248
|
+
]
|
249
|
+
]
|
250
|
+
}'
|
251
|
+
b = PARSED_EXAMPLES[:sf_county]
|
252
|
+
assert a.intersects? b
|
253
|
+
assert b.intersects? a
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'returns true for intersecting multi line strings' do
|
257
|
+
a = Terraformer.parse '{
|
258
|
+
"type": "MultiLineString",
|
259
|
+
"coordinates": [
|
260
|
+
[
|
261
|
+
[
|
262
|
+
-63.54492187500001,
|
263
|
+
-15.665354182093274
|
264
|
+
],
|
265
|
+
[
|
266
|
+
-66.95068359374999,
|
267
|
+
-18.22935133838667
|
268
|
+
],
|
269
|
+
[
|
270
|
+
-65.7421875,
|
271
|
+
-19.746024239625417
|
272
|
+
],
|
273
|
+
[
|
274
|
+
-63.7646484375,
|
275
|
+
-17.455472579972813
|
276
|
+
],
|
277
|
+
[
|
278
|
+
-63.03955078125,
|
279
|
+
-19.932041306115526
|
280
|
+
]
|
281
|
+
],
|
282
|
+
[
|
283
|
+
[
|
284
|
+
-61.9189453125,
|
285
|
+
-18.47960905583197
|
286
|
+
],
|
287
|
+
[
|
288
|
+
-62.62207031249999,
|
289
|
+
-16.53089842368168
|
290
|
+
],
|
291
|
+
[
|
292
|
+
-60.27099609375,
|
293
|
+
-16.467694748288956
|
294
|
+
],
|
295
|
+
[
|
296
|
+
-60.97412109375,
|
297
|
+
-14.83861155338482
|
298
|
+
]
|
299
|
+
]
|
300
|
+
]
|
301
|
+
}'
|
302
|
+
b = Terraformer.parse '{
|
303
|
+
"type": "LineString",
|
304
|
+
"coordinates": [
|
305
|
+
[
|
306
|
+
[
|
307
|
+
-65.819091796875,
|
308
|
+
-15.876809064146757
|
309
|
+
],
|
310
|
+
[
|
311
|
+
-63.96240234375,
|
312
|
+
-19.394067895396613
|
313
|
+
],
|
314
|
+
[
|
315
|
+
-61.292724609375,
|
316
|
+
-17.17228278169307
|
317
|
+
],
|
318
|
+
[
|
319
|
+
-61.84204101562499,
|
320
|
+
-14.976626651623738
|
321
|
+
]
|
322
|
+
],
|
323
|
+
[
|
324
|
+
[
|
325
|
+
-63.29223632812499,
|
326
|
+
-14.615478234145248
|
327
|
+
],
|
328
|
+
[
|
329
|
+
-62.41333007812499,
|
330
|
+
-19.921712747556207
|
331
|
+
],
|
332
|
+
[
|
333
|
+
-61.22680664062499,
|
334
|
+
-19.103648251663632
|
335
|
+
]
|
336
|
+
]
|
337
|
+
]
|
338
|
+
}'
|
339
|
+
assert a.intersects? b
|
340
|
+
assert b.intersects? a
|
341
|
+
end
|
342
|
+
|
343
|
+
it 'returns true for intersecting multi line string and polygon' do
|
344
|
+
a = Terraformer.parse '{
|
345
|
+
"type": "MultiLineString",
|
346
|
+
"coordinates": [
|
347
|
+
[
|
348
|
+
[
|
349
|
+
-63.54492187500001,
|
350
|
+
-15.665354182093274
|
351
|
+
],
|
352
|
+
[
|
353
|
+
-66.95068359374999,
|
354
|
+
-18.22935133838667
|
355
|
+
],
|
356
|
+
[
|
357
|
+
-65.7421875,
|
358
|
+
-19.746024239625417
|
359
|
+
],
|
360
|
+
[
|
361
|
+
-63.7646484375,
|
362
|
+
-17.455472579972813
|
363
|
+
],
|
364
|
+
[
|
365
|
+
-63.03955078125,
|
366
|
+
-19.932041306115526
|
367
|
+
]
|
368
|
+
],
|
369
|
+
[
|
370
|
+
[
|
371
|
+
-61.9189453125,
|
372
|
+
-18.47960905583197
|
373
|
+
],
|
374
|
+
[
|
375
|
+
-62.62207031249999,
|
376
|
+
-16.53089842368168
|
377
|
+
],
|
378
|
+
[
|
379
|
+
-60.27099609375,
|
380
|
+
-16.467694748288956
|
381
|
+
],
|
382
|
+
[
|
383
|
+
-60.97412109375,
|
384
|
+
-14.83861155338482
|
385
|
+
]
|
386
|
+
]
|
387
|
+
]
|
388
|
+
}'
|
389
|
+
b = Terraformer.parse '{
|
390
|
+
"type": "Polygon",
|
391
|
+
"coordinates": [
|
392
|
+
[
|
393
|
+
[
|
394
|
+
-63.94042968749999,
|
395
|
+
-16.625665127961494
|
396
|
+
],
|
397
|
+
[
|
398
|
+
-65.23681640625,
|
399
|
+
-18.26065335675836
|
400
|
+
],
|
401
|
+
[
|
402
|
+
-64.7314453125,
|
403
|
+
-19.49766416813904
|
404
|
+
],
|
405
|
+
[
|
406
|
+
-60.732421875,
|
407
|
+
-17.224758206624628
|
408
|
+
],
|
409
|
+
[
|
410
|
+
-61.61132812500001,
|
411
|
+
-15.64419660086606
|
412
|
+
],
|
413
|
+
[
|
414
|
+
-63.94042968749999,
|
415
|
+
-16.625665127961494
|
416
|
+
]
|
417
|
+
]
|
418
|
+
]
|
419
|
+
}'
|
420
|
+
assert a.intersects? b
|
421
|
+
assert b.intersects? a
|
422
|
+
end
|
423
|
+
|
424
|
+
it 'returns true for intersecting multi line string and multi polygon' do
|
425
|
+
a = Terraformer.parse '{
|
426
|
+
"type": "MultiLineString",
|
427
|
+
"coordinates": [
|
428
|
+
[
|
429
|
+
[
|
430
|
+
-63.54492187500001,
|
431
|
+
-15.665354182093274
|
432
|
+
],
|
433
|
+
[
|
434
|
+
-66.95068359374999,
|
435
|
+
-18.22935133838667
|
436
|
+
],
|
437
|
+
[
|
438
|
+
-65.7421875,
|
439
|
+
-19.746024239625417
|
440
|
+
],
|
441
|
+
[
|
442
|
+
-63.7646484375,
|
443
|
+
-17.455472579972813
|
444
|
+
],
|
445
|
+
[
|
446
|
+
-63.03955078125,
|
447
|
+
-19.932041306115526
|
448
|
+
]
|
449
|
+
],
|
450
|
+
[
|
451
|
+
[
|
452
|
+
-61.9189453125,
|
453
|
+
-18.47960905583197
|
454
|
+
],
|
455
|
+
[
|
456
|
+
-62.62207031249999,
|
457
|
+
-16.53089842368168
|
458
|
+
],
|
459
|
+
[
|
460
|
+
-60.27099609375,
|
461
|
+
-16.467694748288956
|
462
|
+
],
|
463
|
+
[
|
464
|
+
-60.97412109375,
|
465
|
+
-14.83861155338482
|
466
|
+
]
|
467
|
+
]
|
468
|
+
]
|
469
|
+
}'
|
470
|
+
b = Terraformer.parse '{
|
471
|
+
"type": "MultiPolygon",
|
472
|
+
"coordinates": [[
|
473
|
+
[
|
474
|
+
[
|
475
|
+
-63.94042968749999,
|
476
|
+
-16.625665127961494
|
477
|
+
],
|
478
|
+
[
|
479
|
+
-65.23681640625,
|
480
|
+
-18.26065335675836
|
481
|
+
],
|
482
|
+
[
|
483
|
+
-64.7314453125,
|
484
|
+
-19.49766416813904
|
485
|
+
],
|
486
|
+
[
|
487
|
+
-60.732421875,
|
488
|
+
-17.224758206624628
|
489
|
+
],
|
490
|
+
[
|
491
|
+
-61.61132812500001,
|
492
|
+
-15.64419660086606
|
493
|
+
],
|
494
|
+
[
|
495
|
+
-63.94042968749999,
|
496
|
+
-16.625665127961494
|
497
|
+
]
|
498
|
+
]],
|
499
|
+
[
|
500
|
+
[
|
501
|
+
[
|
502
|
+
-62.49023437499999,
|
503
|
+
-14.285677300182577
|
504
|
+
],
|
505
|
+
[
|
506
|
+
-62.314453125,
|
507
|
+
-15.432500881886043
|
508
|
+
],
|
509
|
+
[
|
510
|
+
-61.3037109375,
|
511
|
+
-15.262988555023204
|
512
|
+
],
|
513
|
+
[
|
514
|
+
-61.46850585937499,
|
515
|
+
-13.891411092746102
|
516
|
+
],
|
517
|
+
[
|
518
|
+
-62.49023437499999,
|
519
|
+
-14.285677300182577
|
520
|
+
]
|
521
|
+
]
|
522
|
+
]
|
523
|
+
]
|
524
|
+
}'
|
525
|
+
assert a.intersects? b
|
526
|
+
assert b.intersects? a
|
527
|
+
end
|
528
|
+
|
529
|
+
it 'returns true for intersecting polygons' do
|
530
|
+
a = Terraformer.parse '{
|
531
|
+
"type": "Polygon",
|
532
|
+
"coordinates": [
|
533
|
+
[
|
534
|
+
[
|
535
|
+
-91.20574951171874,
|
536
|
+
14.777538257344107
|
537
|
+
],
|
538
|
+
[
|
539
|
+
-91.19613647460938,
|
540
|
+
14.707149905394584
|
541
|
+
],
|
542
|
+
[
|
543
|
+
-91.13296508789062,
|
544
|
+
14.70449329599549
|
545
|
+
],
|
546
|
+
[
|
547
|
+
-91.11923217773436,
|
548
|
+
14.76691505925414
|
549
|
+
],
|
550
|
+
[
|
551
|
+
-91.20574951171874,
|
552
|
+
14.777538257344107
|
553
|
+
]
|
554
|
+
]
|
555
|
+
]
|
556
|
+
}'
|
557
|
+
b = Terraformer.parse '{
|
558
|
+
"type": "Polygon",
|
559
|
+
"coordinates": [
|
560
|
+
[
|
561
|
+
[
|
562
|
+
-91.24008178710938,
|
563
|
+
14.72308888264888
|
564
|
+
],
|
565
|
+
[
|
566
|
+
-91.22634887695312,
|
567
|
+
14.630095127973206
|
568
|
+
],
|
569
|
+
[
|
570
|
+
-91.14944458007812,
|
571
|
+
14.639396280953365
|
572
|
+
],
|
573
|
+
[
|
574
|
+
-91.16867065429688,
|
575
|
+
14.728401616219264
|
576
|
+
],
|
577
|
+
[
|
578
|
+
-91.24008178710938,
|
579
|
+
14.72308888264888
|
580
|
+
]
|
581
|
+
]
|
582
|
+
]
|
583
|
+
}'
|
584
|
+
assert a.intersects? b
|
585
|
+
assert b.intersects? a
|
586
|
+
end
|
587
|
+
|
588
|
+
it 'returns true for intersecting polygon and multi polygon' do
|
589
|
+
a = Terraformer.parse '{
|
590
|
+
"type": "Polygon",
|
591
|
+
"coordinates": [
|
592
|
+
[
|
593
|
+
[
|
594
|
+
-91.20574951171874,
|
595
|
+
14.777538257344107
|
596
|
+
],
|
597
|
+
[
|
598
|
+
-91.19613647460938,
|
599
|
+
14.707149905394584
|
600
|
+
],
|
601
|
+
[
|
602
|
+
-91.13296508789062,
|
603
|
+
14.70449329599549
|
604
|
+
],
|
605
|
+
[
|
606
|
+
-91.11923217773436,
|
607
|
+
14.76691505925414
|
608
|
+
],
|
609
|
+
[
|
610
|
+
-91.20574951171874,
|
611
|
+
14.777538257344107
|
612
|
+
]
|
613
|
+
]
|
614
|
+
]
|
615
|
+
}'
|
616
|
+
b = Terraformer.parse '{
|
617
|
+
"type": "MultiPolygon",
|
618
|
+
"coordinates": [
|
619
|
+
[
|
620
|
+
[
|
621
|
+
[
|
622
|
+
-91.24008178710938,
|
623
|
+
14.72308888264888
|
624
|
+
],
|
625
|
+
[
|
626
|
+
-91.22634887695312,
|
627
|
+
14.630095127973206
|
628
|
+
],
|
629
|
+
[
|
630
|
+
-91.14944458007812,
|
631
|
+
14.639396280953365
|
632
|
+
],
|
633
|
+
[
|
634
|
+
-91.16867065429688,
|
635
|
+
14.728401616219264
|
636
|
+
],
|
637
|
+
[
|
638
|
+
-91.24008178710938,
|
639
|
+
14.72308888264888
|
640
|
+
]
|
641
|
+
]
|
642
|
+
],
|
643
|
+
[
|
644
|
+
[
|
645
|
+
[
|
646
|
+
-91.13845825195312,
|
647
|
+
14.685896125376305
|
648
|
+
],
|
649
|
+
[
|
650
|
+
-91.14395141601562,
|
651
|
+
14.638067568954588
|
652
|
+
],
|
653
|
+
[
|
654
|
+
-91.10275268554688,
|
655
|
+
14.644711048453187
|
656
|
+
],
|
657
|
+
[
|
658
|
+
-91.10824584960938,
|
659
|
+
14.697851631083855
|
660
|
+
],
|
661
|
+
[
|
662
|
+
-91.13845825195312,
|
663
|
+
14.685896125376305
|
664
|
+
]
|
665
|
+
]
|
666
|
+
]
|
667
|
+
]
|
668
|
+
}'
|
669
|
+
assert a.intersects? b
|
670
|
+
assert b.intersects? a
|
671
|
+
end
|
672
|
+
|
673
|
+
it 'returns true for intersecting multi polygons' do
|
674
|
+
a = Terraformer.parse '{
|
675
|
+
"type": "MultiPolygon",
|
676
|
+
"coordinates": [[
|
677
|
+
[
|
678
|
+
[
|
679
|
+
-91.20574951171874,
|
680
|
+
14.777538257344107
|
681
|
+
],
|
682
|
+
[
|
683
|
+
-91.19613647460938,
|
684
|
+
14.707149905394584
|
685
|
+
],
|
686
|
+
[
|
687
|
+
-91.13296508789062,
|
688
|
+
14.70449329599549
|
689
|
+
],
|
690
|
+
[
|
691
|
+
-91.11923217773436,
|
692
|
+
14.76691505925414
|
693
|
+
],
|
694
|
+
[
|
695
|
+
-91.20574951171874,
|
696
|
+
14.777538257344107
|
697
|
+
]
|
698
|
+
]
|
699
|
+
],
|
700
|
+
[
|
701
|
+
[
|
702
|
+
[
|
703
|
+
-91.29364013671875,
|
704
|
+
14.889050404470884
|
705
|
+
],
|
706
|
+
[
|
707
|
+
-91.29776000976562,
|
708
|
+
14.753635331540442
|
709
|
+
],
|
710
|
+
[
|
711
|
+
-91.21810913085938,
|
712
|
+
14.743010965702727
|
713
|
+
],
|
714
|
+
[
|
715
|
+
-91.21261596679686,
|
716
|
+
14.800110827789874
|
717
|
+
],
|
718
|
+
[
|
719
|
+
-91.15081787109374,
|
720
|
+
14.862505109695116
|
721
|
+
],
|
722
|
+
[
|
723
|
+
-91.29364013671875,
|
724
|
+
14.889050404470884
|
725
|
+
]
|
726
|
+
]
|
727
|
+
]]
|
728
|
+
}'
|
729
|
+
b = Terraformer.parse '{
|
730
|
+
"type": "MultiPolygon",
|
731
|
+
"coordinates": [
|
732
|
+
[
|
733
|
+
[
|
734
|
+
[
|
735
|
+
-91.24008178710938,
|
736
|
+
14.72308888264888
|
737
|
+
],
|
738
|
+
[
|
739
|
+
-91.22634887695312,
|
740
|
+
14.630095127973206
|
741
|
+
],
|
742
|
+
[
|
743
|
+
-91.14944458007812,
|
744
|
+
14.639396280953365
|
745
|
+
],
|
746
|
+
[
|
747
|
+
-91.16867065429688,
|
748
|
+
14.728401616219264
|
749
|
+
],
|
750
|
+
[
|
751
|
+
-91.24008178710938,
|
752
|
+
14.72308888264888
|
753
|
+
]
|
754
|
+
]
|
755
|
+
],
|
756
|
+
[
|
757
|
+
[
|
758
|
+
[
|
759
|
+
-91.13845825195312,
|
760
|
+
14.685896125376305
|
761
|
+
],
|
762
|
+
[
|
763
|
+
-91.14395141601562,
|
764
|
+
14.638067568954588
|
765
|
+
],
|
766
|
+
[
|
767
|
+
-91.10275268554688,
|
768
|
+
14.644711048453187
|
769
|
+
],
|
770
|
+
[
|
771
|
+
-91.10824584960938,
|
772
|
+
14.697851631083855
|
773
|
+
],
|
774
|
+
[
|
775
|
+
-91.13845825195312,
|
776
|
+
14.685896125376305
|
777
|
+
]
|
778
|
+
]
|
779
|
+
]
|
780
|
+
]
|
781
|
+
}'
|
782
|
+
assert a.intersects? b
|
783
|
+
assert b.intersects? a
|
784
|
+
end
|
785
|
+
|
786
|
+
it 'returns false for non-intersecting line strings' do
|
787
|
+
a = Terraformer::LineString.new [[0,0],[8,8]]
|
788
|
+
b = Terraformer::LineString.new [[-1,-1],[-8,-8]]
|
789
|
+
refute a.intersects?(b)
|
790
|
+
end
|
791
|
+
|
792
|
+
it 'returns false for non-intersecting polygons' do
|
793
|
+
refute PARSED_EXAMPLES[:circle].intersects? PARSED_EXAMPLES[:sf_county]
|
794
|
+
end
|
795
|
+
|
796
|
+
# todo more false tests
|
797
|
+
|
798
|
+
end
|
799
|
+
|
800
|
+
describe 'contains?' do
|
801
|
+
|
802
|
+
it 'raises on unsupported types' do
|
803
|
+
->{ PARSED_EXAMPLES[:point].contains? PARSED_EXAMPLES[:polygon] }.must_raise ArgumentError
|
804
|
+
->{ PARSED_EXAMPLES[:multi_point].contains? PARSED_EXAMPLES[:polygon] }.must_raise ArgumentError
|
805
|
+
->{ PARSED_EXAMPLES[:line_string].contains? PARSED_EXAMPLES[:polygon] }.must_raise ArgumentError
|
806
|
+
->{ PARSED_EXAMPLES[:multi_line_string].contains? PARSED_EXAMPLES[:polygon] }.must_raise ArgumentError
|
807
|
+
# todo more?
|
808
|
+
end
|
809
|
+
|
810
|
+
it 'returns true for line strings that contain points' do
|
811
|
+
ls = PARSED_EXAMPLES[:line_string]
|
812
|
+
assert ls.contains? ls.point_at(1)
|
813
|
+
assert ls.contains? [100.5,0.5].to_c.to_point
|
814
|
+
end
|
815
|
+
|
816
|
+
it 'returns true for multi line strings that contain points' do
|
817
|
+
mls = PARSED_EXAMPLES[:multi_line_string]
|
818
|
+
assert mls.contains? mls.line_strings[0].point_at(1)
|
819
|
+
end
|
820
|
+
|
821
|
+
it 'returns true for polygons that contain points' do
|
822
|
+
p = Terraformer.parse '{
|
823
|
+
"type": "Point",
|
824
|
+
"coordinates": [
|
825
|
+
100.56060791015624,
|
826
|
+
0.6783899107121523
|
827
|
+
]
|
828
|
+
}'
|
829
|
+
assert PARSED_EXAMPLES[:polygon].contains? p
|
830
|
+
end
|
831
|
+
|
832
|
+
it 'returns true for polygons that contain polygons' do
|
833
|
+
pwh = PARSED_EXAMPLES[:polygon_with_holes]
|
834
|
+
p1 = Terraformer::Polygon.new pwh.line_strings[0].coordinates
|
835
|
+
p2 = pwh.holes[0]
|
836
|
+
assert p1.contains? p2
|
837
|
+
refute p2.contains? p1
|
838
|
+
end
|
839
|
+
|
840
|
+
it 'returns true for multi polygons that contain polygons' do
|
841
|
+
p = Terraformer.parse '{
|
842
|
+
"type": "Polygon",
|
843
|
+
"coordinates": [
|
844
|
+
[
|
845
|
+
[
|
846
|
+
102.3101806640625,
|
847
|
+
2.2625953010152453
|
848
|
+
],
|
849
|
+
[
|
850
|
+
102.3101806640625,
|
851
|
+
2.6632250332728296
|
852
|
+
],
|
853
|
+
[
|
854
|
+
102.83752441406249,
|
855
|
+
2.6632250332728296
|
856
|
+
],
|
857
|
+
[
|
858
|
+
102.83752441406249,
|
859
|
+
2.2625953010152453
|
860
|
+
],
|
861
|
+
[
|
862
|
+
102.3101806640625,
|
863
|
+
2.2625953010152453
|
864
|
+
]
|
865
|
+
]
|
866
|
+
]
|
867
|
+
}'
|
868
|
+
assert PARSED_EXAMPLES[:multi_polygon].contains? p
|
869
|
+
end
|
870
|
+
|
871
|
+
it 'returns false for polygons with holes and point inside hole' do
|
872
|
+
p = Terraformer.parse '{
|
873
|
+
"type": "Point",
|
874
|
+
"coordinates": [
|
875
|
+
100.5194091796875,
|
876
|
+
0.6028636315576017
|
877
|
+
]
|
878
|
+
}'
|
879
|
+
refute PARSED_EXAMPLES[:polygon_with_holes].contains? p
|
880
|
+
end
|
881
|
+
|
882
|
+
it 'returns false for polygons with holes and polygon inside hole' do
|
883
|
+
p = Terraformer.parse '{
|
884
|
+
"type": "Polygon",
|
885
|
+
"coordinates": [
|
886
|
+
[
|
887
|
+
[
|
888
|
+
100.40130615234375,
|
889
|
+
0.42159653727164975
|
890
|
+
],
|
891
|
+
[
|
892
|
+
100.40130615234375,
|
893
|
+
0.6509259386918139
|
894
|
+
],
|
895
|
+
[
|
896
|
+
100.6842041015625,
|
897
|
+
0.6509259386918139
|
898
|
+
],
|
899
|
+
[
|
900
|
+
100.6842041015625,
|
901
|
+
0.42159653727164975
|
902
|
+
],
|
903
|
+
[
|
904
|
+
100.40130615234375,
|
905
|
+
0.42159653727164975
|
906
|
+
]
|
907
|
+
]
|
908
|
+
]
|
909
|
+
}'
|
910
|
+
refute PARSED_EXAMPLES[:polygon_with_holes].contains? p
|
911
|
+
end
|
912
|
+
|
913
|
+
end
|
914
|
+
|
915
|
+
describe 'within?' do
|
916
|
+
|
917
|
+
it 'raises on unsupported types' do
|
918
|
+
->{ PARSED_EXAMPLES[:polygon].within? PARSED_EXAMPLES[:point] }.must_raise ArgumentError
|
919
|
+
->{ PARSED_EXAMPLES[:polygon].within? PARSED_EXAMPLES[:multi_point] }.must_raise ArgumentError
|
920
|
+
->{ PARSED_EXAMPLES[:polygon].within? PARSED_EXAMPLES[:line_string] }.must_raise ArgumentError
|
921
|
+
->{ PARSED_EXAMPLES[:polygon].within? PARSED_EXAMPLES[:multi_line_string] }.must_raise ArgumentError
|
922
|
+
# todo more?
|
923
|
+
end
|
924
|
+
|
925
|
+
it 'returns true for points within line strings' do
|
926
|
+
ls = PARSED_EXAMPLES[:line_string]
|
927
|
+
assert ls.point_at(1).within? ls
|
928
|
+
end
|
929
|
+
|
930
|
+
it 'returns true for points within multi line strings' do
|
931
|
+
mls = PARSED_EXAMPLES[:multi_line_string]
|
932
|
+
assert mls.line_strings[0].point_at(1).within? mls
|
933
|
+
end
|
934
|
+
|
935
|
+
it 'returns true for points within polygons' do
|
936
|
+
p = Terraformer.parse '{
|
937
|
+
"type": "Point",
|
938
|
+
"coordinates": [
|
939
|
+
100.56060791015624,
|
940
|
+
0.6783899107121523
|
941
|
+
]
|
942
|
+
}'
|
943
|
+
assert p.within? PARSED_EXAMPLES[:polygon]
|
944
|
+
end
|
945
|
+
|
946
|
+
it 'returns true for polygons within polygons' do
|
947
|
+
pwh = PARSED_EXAMPLES[:polygon_with_holes]
|
948
|
+
p1 = Terraformer::Polygon.new pwh.line_strings[0].coordinates
|
949
|
+
p2 = pwh.holes[0]
|
950
|
+
assert p2.within? p1
|
951
|
+
refute p1.within? p2
|
952
|
+
end
|
953
|
+
|
954
|
+
it 'returns true for polygons within multi polygons' do
|
955
|
+
p = Terraformer.parse '{
|
956
|
+
"type": "Polygon",
|
957
|
+
"coordinates": [
|
958
|
+
[
|
959
|
+
[
|
960
|
+
102.3101806640625,
|
961
|
+
2.2625953010152453
|
962
|
+
],
|
963
|
+
[
|
964
|
+
102.3101806640625,
|
965
|
+
2.6632250332728296
|
966
|
+
],
|
967
|
+
[
|
968
|
+
102.83752441406249,
|
969
|
+
2.6632250332728296
|
970
|
+
],
|
971
|
+
[
|
972
|
+
102.83752441406249,
|
973
|
+
2.2625953010152453
|
974
|
+
],
|
975
|
+
[
|
976
|
+
102.3101806640625,
|
977
|
+
2.2625953010152453
|
978
|
+
]
|
979
|
+
]
|
980
|
+
]
|
981
|
+
}'
|
982
|
+
assert p.within? PARSED_EXAMPLES[:multi_polygon]
|
983
|
+
end
|
984
|
+
|
985
|
+
it 'returns false for points within the hole of polygons with holes' do
|
986
|
+
p = Terraformer.parse '{
|
987
|
+
"type": "Point",
|
988
|
+
"coordinates": [
|
989
|
+
100.5194091796875,
|
990
|
+
0.6028636315576017
|
991
|
+
]
|
992
|
+
}'
|
993
|
+
refute p.within? PARSED_EXAMPLES[:polygon_with_holes]
|
994
|
+
end
|
995
|
+
|
996
|
+
it 'returns false for polygons within the hole of polygons with holes' do
|
997
|
+
p = Terraformer.parse '{
|
998
|
+
"type": "Polygon",
|
999
|
+
"coordinates": [
|
1000
|
+
[
|
1001
|
+
[
|
1002
|
+
100.40130615234375,
|
1003
|
+
0.42159653727164975
|
1004
|
+
],
|
1005
|
+
[
|
1006
|
+
100.40130615234375,
|
1007
|
+
0.6509259386918139
|
1008
|
+
],
|
1009
|
+
[
|
1010
|
+
100.6842041015625,
|
1011
|
+
0.6509259386918139
|
1012
|
+
],
|
1013
|
+
[
|
1014
|
+
100.6842041015625,
|
1015
|
+
0.42159653727164975
|
1016
|
+
],
|
1017
|
+
[
|
1018
|
+
100.40130615234375,
|
1019
|
+
0.42159653727164975
|
1020
|
+
]
|
1021
|
+
]
|
1022
|
+
]
|
1023
|
+
}'
|
1024
|
+
refute p.within? PARSED_EXAMPLES[:polygon_with_holes]
|
1025
|
+
end
|
1026
|
+
|
1027
|
+
end
|
1028
|
+
|
1029
|
+
describe Terraformer::Geometry::ClassMethods do
|
1030
|
+
|
1031
|
+
describe 'edge_intersects_edge?' do
|
1032
|
+
|
1033
|
+
it 'returns true for edges that intersect' do
|
1034
|
+
a = [[0,0], [2,2]].map &:to_c
|
1035
|
+
b = [[0,2], [2,0]].map &:to_c
|
1036
|
+
Terraformer::Geometry.edge_intersects_edge?(a[0], a[1], b[0], b[1]).must_equal true
|
1037
|
+
end
|
1038
|
+
|
1039
|
+
it 'returns false for edges that do not intersect' do
|
1040
|
+
a = [[0,2], [2,2]].map &:to_c
|
1041
|
+
b = [[0,0], [2,0]].map &:to_c
|
1042
|
+
Terraformer::Geometry.edge_intersects_edge?(a[0], a[1], b[0], b[1]).must_equal false
|
1043
|
+
end
|
1044
|
+
|
1045
|
+
end
|
1046
|
+
|
1047
|
+
describe 'arrays_intersect_arrays?' do
|
1048
|
+
|
1049
|
+
it 'returns true for lines that intersect' do
|
1050
|
+
a = [[0,0], [2,2]].map &:to_c
|
1051
|
+
b = [[0,2], [2,0]].map &:to_c
|
1052
|
+
Terraformer::Geometry.arrays_intersect_arrays?(a, b).must_equal true
|
1053
|
+
end
|
1054
|
+
|
1055
|
+
it 'returns false for lines that do not intersect' do
|
1056
|
+
a = [[0,2], [2,2]].map &:to_c
|
1057
|
+
b = [[0,0], [2,0]].map &:to_c
|
1058
|
+
Terraformer::Geometry.arrays_intersect_arrays?(a, b).must_equal false
|
1059
|
+
end
|
1060
|
+
|
1061
|
+
end
|
1062
|
+
|
1063
|
+
describe 'line_cotains_point?' do
|
1064
|
+
|
1065
|
+
it 'returns true for points on the line' do
|
1066
|
+
assert Terraformer::Geometry.line_contains_point? [[0,0].to_c, [4,4].to_c], [2,2].to_c
|
1067
|
+
end
|
1068
|
+
|
1069
|
+
it 'returns false for points that are not on the line' do
|
1070
|
+
refute Terraformer::Geometry.line_contains_point? [[0,0].to_c, [4,4].to_c], [0,2].to_c
|
1071
|
+
end
|
1072
|
+
|
1073
|
+
it 'returns true for points on the ends of the line' do
|
1074
|
+
assert Terraformer::Geometry.line_contains_point? [[0,0].to_c, [4,4].to_c], [0,0].to_c
|
1075
|
+
assert Terraformer::Geometry.line_contains_point? [[0,0].to_c, [4,4].to_c], [4,4].to_c
|
1076
|
+
end
|
1077
|
+
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
end
|
1081
|
+
|
1082
|
+
end
|