ffi-geos 1.2.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +4851 -0
  3. data/.travis.yml +24 -9
  4. data/FUNDING.yml +2 -0
  5. data/Gemfile +12 -16
  6. data/Guardfile +6 -8
  7. data/MIT-LICENSE +1 -1
  8. data/README.rdoc +2 -20
  9. data/Rakefile +4 -2
  10. data/ffi-geos.gemspec +13 -14
  11. data/lib/ffi-geos.rb +342 -244
  12. data/lib/ffi-geos/buffer_params.rb +9 -20
  13. data/lib/ffi-geos/coordinate_sequence.rb +351 -65
  14. data/lib/ffi-geos/geometry.rb +267 -191
  15. data/lib/ffi-geos/geometry_collection.rb +74 -12
  16. data/lib/ffi-geos/interrupt.rb +11 -16
  17. data/lib/ffi-geos/line_string.rb +157 -33
  18. data/lib/ffi-geos/linear_ring.rb +2 -3
  19. data/lib/ffi-geos/multi_line_string.rb +1 -2
  20. data/lib/ffi-geos/multi_point.rb +0 -1
  21. data/lib/ffi-geos/multi_polygon.rb +0 -1
  22. data/lib/ffi-geos/point.rb +70 -15
  23. data/lib/ffi-geos/polygon.rb +124 -21
  24. data/lib/ffi-geos/prepared_geometry.rb +11 -12
  25. data/lib/ffi-geos/strtree.rb +64 -77
  26. data/lib/ffi-geos/tools.rb +16 -19
  27. data/lib/ffi-geos/utils.rb +36 -60
  28. data/lib/ffi-geos/version.rb +1 -3
  29. data/lib/ffi-geos/wkb_reader.rb +4 -9
  30. data/lib/ffi-geos/wkb_writer.rb +15 -20
  31. data/lib/ffi-geos/wkt_reader.rb +2 -5
  32. data/lib/ffi-geos/wkt_writer.rb +20 -31
  33. data/sonar-project.properties +16 -0
  34. data/test/.rubocop.yml +36 -0
  35. data/test/coordinate_sequence_tests.rb +322 -52
  36. data/test/geometry_collection_tests.rb +388 -4
  37. data/test/geometry_tests.rb +466 -121
  38. data/test/interrupt_tests.rb +9 -12
  39. data/test/line_string_tests.rb +213 -25
  40. data/test/linear_ring_tests.rb +1 -3
  41. data/test/misc_tests.rb +28 -30
  42. data/test/multi_line_string_tests.rb +0 -2
  43. data/test/point_tests.rb +158 -2
  44. data/test/polygon_tests.rb +283 -2
  45. data/test/prepared_geometry_tests.rb +8 -11
  46. data/test/strtree_tests.rb +14 -15
  47. data/test/test_helper.rb +75 -51
  48. data/test/tools_tests.rb +1 -4
  49. data/test/utils_tests.rb +85 -76
  50. data/test/wkb_reader_tests.rb +18 -18
  51. data/test/wkb_writer_tests.rb +15 -22
  52. data/test/wkt_reader_tests.rb +1 -4
  53. data/test/wkt_writer_tests.rb +8 -17
  54. metadata +11 -7
@@ -1,7 +1,5 @@
1
- # encoding: UTF-8
2
1
  # frozen_string_literal: true
3
2
 
4
- $: << File.dirname(__FILE__)
5
3
  require 'test_helper'
6
4
 
7
5
  class GeometryCollectionTests < Minitest::Test
@@ -18,7 +16,7 @@ class GeometryCollectionTests < Minitest::Test
18
16
  geom = read('GEOMETRYCOLLECTION(POINT(0 0))')
19
17
  assert_kind_of(Enumerable, geom.each)
20
18
  assert_kind_of(Enumerable, geom.to_enum)
21
- assert_equal(geom, geom.each {})
19
+ assert_equal(geom, geom.each(&EMPTY_BLOCK))
22
20
  end
23
21
 
24
22
  def test_geometry_collection_array
@@ -40,7 +38,7 @@ class GeometryCollectionTests < Minitest::Test
40
38
  'POINT (10 20)'
41
39
  ], geom[0, 2].collect { |g| write(g) })
42
40
 
43
- assert_equal(nil, geom[0, -1])
41
+ assert_nil(geom[0, -1])
44
42
  assert_equal([], geom[-1, 0])
45
43
  assert_equal([
46
44
  'POINT (10 20)',
@@ -85,4 +83,390 @@ class GeometryCollectionTests < Minitest::Test
85
83
  geom = read('GEOMETRYCOLLECTION (POINT(1 2), LINESTRING(1 2, 3 4))')
86
84
  assert_equal(2, geom.num_geometries)
87
85
  end
86
+
87
+ def test_x_max
88
+ geom = read('GEOMETRYCOLLECTION (
89
+ POLYGON ((0 0, 5 0, 8 9, -10 5, 0 0)),
90
+ LINESTRING (0 0, 5 0, 8 9, -10 5, 0 0),
91
+ POINT(3 12)
92
+ )')
93
+
94
+ assert_equal(8, geom.x_max)
95
+ end
96
+
97
+ def test_x_min
98
+ geom = read('GEOMETRYCOLLECTION (
99
+ POLYGON ((0 0, 5 0, 8 9, -10 5, 0 0)),
100
+ LINESTRING (0 0, 5 0, 8 9, -10 5, 0 0),
101
+ POINT(3 12)
102
+ )')
103
+
104
+ assert_equal(-10, geom.x_min)
105
+ end
106
+
107
+ def test_y_max
108
+ geom = read('GEOMETRYCOLLECTION (
109
+ POLYGON ((0 0, 5 0, 8 9, -10 5, 0 0)),
110
+ LINESTRING (0 0, 5 0, 8 9, -10 5, 0 0),
111
+ POINT(3 12)
112
+ )')
113
+
114
+ assert_equal(12, geom.y_max)
115
+ end
116
+
117
+ def test_y_min
118
+ geom = read('GEOMETRYCOLLECTION (
119
+ POLYGON ((0 0, 5 0, 8 9, -10 5, 0 0)),
120
+ LINESTRING (0 0, 5 0, 8 9, -10 5, 0 0),
121
+ POINT(3 12)
122
+ )')
123
+
124
+ assert_equal(0, geom.y_min)
125
+ end
126
+
127
+ def test_z_max
128
+ geom = read('GEOMETRYCOLLECTION (
129
+ POLYGON ((0 0, 5 0, 8 9, -10 5, 0 0)),
130
+ LINESTRING (0 0, 5 0, 8 9, -10 5, 0 0),
131
+ POINT(3 12)
132
+ )')
133
+ assert_equal(0, geom.z_max)
134
+
135
+ geom = read('GEOMETRYCOLLECTION Z (
136
+ POLYGON Z ((0 0 0, 5 0 3, 8 9 4, -10 5 3, 0 0 0)),
137
+ LINESTRING Z (0 0 0, 5 0 3, 8 9 4, -10 5 3, 0 0 0),
138
+ POINT Z (3 12 6)
139
+ )')
140
+ assert_equal(6, geom.z_max)
141
+
142
+ # GEOS lets you mix dimensionality, while PostGIS doesn't.
143
+ geom = read('GEOMETRYCOLLECTION (
144
+ POLYGON ((0 0, 5 0, 8 9, -10 5, 0 0)),
145
+ LINESTRING (0 0, 5 0, 8 9, -10 5, 0 0),
146
+ POINT(3 12 10)
147
+ )')
148
+ assert_equal(10, geom.z_max)
149
+ end
150
+
151
+ def test_z_min
152
+ geom = read('GEOMETRYCOLLECTION (
153
+ POLYGON ((0 0, 5 0, 8 9, -10 5, 0 0)),
154
+ LINESTRING (0 0, 5 0, 8 9, -10 5, 0 0),
155
+ POINT(3 12)
156
+ )')
157
+ assert_equal(0, geom.z_min)
158
+
159
+ geom = read('GEOMETRYCOLLECTION Z (
160
+ POLYGON Z ((0 0 0, 5 0 3, 8 9 4, -10 5 3, 0 0 0)),
161
+ LINESTRING Z (0 0 0, 5 0 3, 8 9 4, -10 5 3, 0 0 0),
162
+ POINT Z (3 12 6)
163
+ )')
164
+ assert_equal(0, geom.z_min)
165
+
166
+ # GEOS lets you mix dimensionality, while PostGIS doesn't.
167
+ geom = read('GEOMETRYCOLLECTION (
168
+ POLYGON ((0 0, 5 0, 8 9, -10 5, 0 0)),
169
+ LINESTRING (0 0, 5 0, 8 9, -10 5, 0 0),
170
+ POINT(3 12 -10)
171
+ )')
172
+ assert_equal(-10, geom.z_min)
173
+ end
174
+
175
+ def test_snap_to_grid
176
+ wkt = 'GEOMETRYCOLLECTION (LINESTRING (-10.12 0, -10.12 5, -10.12 5, -10.12 6, -10.12 6, -10.12 6, -10.12 7, -10.12 7, -10.12 7, -10.12 8, -10.12 8, -9 8, -9 9, -10.12 0), ' \
177
+ 'POLYGON ((-10.12 0, -10.12 5, -10.12 5, -10.12 6, -10.12 6, -10.12 6, -10.12 7, -10.12 7, -10.12 7, -10.12 8, -10.12 8, -9 8, -9 9, -10.12 0)), POINT (10.12 10.12))'
178
+
179
+ expected = 'GEOMETRYCOLLECTION (LINESTRING (-10 0, -10 5, -10 5, -10 6, -10 6, -10 6, -10 7, -10 7, -10 7, -10 8, -10 8, -9 8, -9 9, -10 0), POLYGON ((-10 0, -10 5, -10 5, -10 6, -10 6, -10 6, -10 7, -10 7, -10 7, -10 8, -10 8, -9 8, -9 9, -10 0)), POINT (10 10))'
180
+
181
+ simple_bang_tester(:snap_to_grid, expected, wkt, 1)
182
+ end
183
+
184
+ def test_snap_to_grid_empty
185
+ assert(read('GEOMETRYCOLLECTION EMPTY').snap_to_grid!.empty?, 'Expected an empty GeometryCollection')
186
+ end
187
+
188
+ def test_snap_to_grid_with_srid
189
+ wkt = 'GEOMETRYCOLLECTION (
190
+ LINESTRING (-10.12 0, -10.12 5, -10.12 5, -10.12 6, -10.12 6, -10.12 6, -10.12 7, -10.12 7, -10.12 7, -10.12 8, -10.12 8, -9 8, -9 9, -10.12 0),
191
+ POLYGON ((-10.12 0, -10.12 5, -10.12 5, -10.12 6, -10.12 6, -10.12 6, -10.12 7, -10.12 7, -10.12 7, -10.12 8, -10.12 8, -9 8, -9 9, -10.12 0)),
192
+ POINT (10.12 10.12)
193
+ )'
194
+
195
+ expected = 'GEOMETRYCOLLECTION (LINESTRING (-10 0, -10 5, -10 5, -10 6, -10 6, -10 6, -10 7, -10 7, -10 7, -10 8, -10 8, -9 8, -9 9, -10 0), POLYGON ((-10 0, -10 5, -10 5, -10 6, -10 6, -10 6, -10 7, -10 7, -10 7, -10 8, -10 8, -9 8, -9 9, -10 0)), POINT (10 10))'
196
+
197
+ srid_copy_tester(:snap_to_grid, expected, 0, :zero, wkt, 1)
198
+ srid_copy_tester(:snap_to_grid, expected, 4326, :lenient, wkt, 1)
199
+ srid_copy_tester(:snap_to_grid, expected, 4326, :strict, wkt, 1)
200
+ end
201
+
202
+ def test_snap_to_grid_with_illegal_result
203
+ assert_raises(Geos::InvalidGeometryError) do
204
+ read('GEOMETRYCOLLECTION (POINT (0 2), LINESTRING (0 1, 0 11), POLYGON ((0 1, 0 1, 0 6, 0 6, 0 1)))')
205
+ .snap_to_grid(1)
206
+ end
207
+ end
208
+
209
+ def test_rotate
210
+ writer.rounding_precision = 3
211
+
212
+ wkt = 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))'
213
+
214
+ affine_tester(:rotate,
215
+ 'GEOMETRYCOLLECTION (POINT (29 11), LINESTRING (30 10, 20 20), POLYGON ((30 10, 30 15, 25 15, 25 10, 30 10)))',
216
+ wkt,
217
+ Math::PI / 2,
218
+ [10.0, 20.0])
219
+
220
+ affine_tester(:rotate,
221
+ 'GEOMETRYCOLLECTION (POINT (-2 0), LINESTRING (-3 1, 7 -9), POLYGON ((-3 1, -3 -4, 2 -4, 2 1, -3 1)))',
222
+ wkt,
223
+ -Math::PI / 2,
224
+ [-1.0, 2.0])
225
+
226
+ affine_tester(:rotate,
227
+ 'GEOMETRYCOLLECTION (POINT (19 1), LINESTRING (20 0, 10 10), POLYGON ((20 0, 20 5, 15 5, 15 0, 20 0)))',
228
+ wkt,
229
+ Math::PI / 2,
230
+ read('POINT(10 10)'))
231
+
232
+ affine_tester(:rotate,
233
+ 'GEOMETRYCOLLECTION (POINT (-0.5 0.5), LINESTRING (0.5 -0.5, -9.5 9.5), POLYGON ((0.5 -0.5, 0.5 4.5, -4.5 4.5, -4.5 -0.5, 0.5 -0.5)))',
234
+ wkt,
235
+ Math::PI / 2,
236
+ read('LINESTRING(0 0, 1 0)'))
237
+ end
238
+
239
+ def test_rotate_x
240
+ writer.rounding_precision = 3
241
+ writer.output_dimensions = 3
242
+
243
+ wkt = 'GEOMETRYCOLLECTION Z (POINT Z (1 1 1), LINESTRING Z (1 1 1, 10 10 10), POLYGON Z ((0 0 0, 5 0 0, 5 5 0, 0 5 0, 0 0 0)))'
244
+
245
+ affine_tester(:rotate_x,
246
+ 'GEOMETRYCOLLECTION Z (POINT Z (1 -1 -1), LINESTRING Z (1 -1 -1, 10 -10 -10), POLYGON Z ((0 0 0, 5 0 0, 5 -5 0, 0 -5 0, 0 0 0)))',
247
+ wkt,
248
+ Math::PI)
249
+
250
+ affine_tester(:rotate_x,
251
+ 'GEOMETRYCOLLECTION Z (POINT Z (1 -1 1), LINESTRING Z (1 -1 1, 10 -10 10), POLYGON Z ((0 0 0, 5 0 0, 5 0 5, 0 0 5, 0 0 0)))',
252
+ wkt,
253
+ Math::PI / 2)
254
+
255
+ affine_tester(:rotate_x,
256
+ 'GEOMETRYCOLLECTION Z (POINT Z (1 1 -1), LINESTRING Z (1 1 -1, 10 10 -10), POLYGON Z ((0 0 0, 5 0 0, 5 0 -5, 0 0 -5, 0 0 0)))',
257
+ wkt,
258
+ Math::PI + Math::PI / 2)
259
+
260
+ affine_tester(:rotate_x,
261
+ wkt,
262
+ wkt,
263
+ Math::PI * 2)
264
+ end
265
+
266
+ def test_rotate_y
267
+ writer.rounding_precision = 6
268
+ writer.output_dimensions = 3
269
+
270
+ wkt = 'GEOMETRYCOLLECTION Z (POINT Z (1 1 1), LINESTRING Z (1 1 1, 10 10 10), POLYGON Z ((0 0 0, 5 0 0, 5 5 0, 0 5 0, 0 0 0)))'
271
+
272
+ affine_tester(:rotate_y,
273
+ 'GEOMETRYCOLLECTION Z (POINT Z (-1 1 -1), LINESTRING Z (-1 1 -1, -10 10 -10), POLYGON Z ((0 0 0, -5 0 0, -5 5 0, 0 5 0, 0 0 0)))',
274
+ wkt,
275
+ Math::PI)
276
+
277
+ affine_tester(:rotate_y,
278
+ 'GEOMETRYCOLLECTION Z (POINT Z (1 1 -1), LINESTRING Z (1 1 -1, 10 10 -10), POLYGON Z ((0 0 0, 0 0 -5, 0 5 -5, 0 5 0, 0 0 0)))',
279
+ wkt,
280
+ Math::PI / 2)
281
+
282
+ affine_tester(:rotate_y,
283
+ 'GEOMETRYCOLLECTION Z (POINT Z (-1 1 1), LINESTRING Z (-1 1 1, -10 10 10), POLYGON Z ((0 0 0, 0 0 5, 0 5 5, 0 5 0, 0 0 0)))',
284
+ wkt,
285
+ Math::PI + Math::PI / 2)
286
+
287
+ affine_tester(:rotate_y,
288
+ wkt,
289
+ wkt,
290
+ Math::PI * 2)
291
+ end
292
+
293
+ def test_rotate_z
294
+ writer.rounding_precision = 3
295
+
296
+ wkt = 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))'
297
+
298
+ affine_tester(:rotate_z,
299
+ 'GEOMETRYCOLLECTION (POINT (-1 -1), LINESTRING (0 0, -10 -10), POLYGON ((0 0, -5 0, -5 -5, 0 -5, 0 0)))',
300
+ wkt,
301
+ Math::PI)
302
+
303
+ affine_tester(:rotate_z,
304
+ 'GEOMETRYCOLLECTION (POINT (-1 1), LINESTRING (0 0, -10 10), POLYGON ((0 0, 0 5, -5 5, -5 0, 0 0)))',
305
+ wkt,
306
+ Math::PI / 2)
307
+
308
+ affine_tester(:rotate_z,
309
+ 'GEOMETRYCOLLECTION (POINT (1 -1), LINESTRING (0 0, 10 -10), POLYGON ((0 0, 0 -5, 5 -5, 5 0, 0 0)))',
310
+ wkt,
311
+ Math::PI + Math::PI / 2)
312
+
313
+ affine_tester(:rotate_z,
314
+ wkt,
315
+ wkt,
316
+ Math::PI * 2)
317
+ end
318
+
319
+ def test_scale
320
+ affine_tester(:scale,
321
+ 'GEOMETRYCOLLECTION (POINT (5 5), LINESTRING (0 0, 50 50), POLYGON ((0 0, 25 0, 25 25, 0 25, 0 0)))',
322
+ 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))',
323
+ 5,
324
+ 5)
325
+
326
+ affine_tester(:scale,
327
+ 'GEOMETRYCOLLECTION (POINT (3 2), LINESTRING (0 0, 30 20), POLYGON ((0 0, 15 0, 15 10, 0 10, 0 0)))',
328
+ 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))',
329
+ 3,
330
+ 2)
331
+
332
+ writer.output_dimensions = 3
333
+ affine_tester(:scale,
334
+ 'GEOMETRYCOLLECTION Z (POINT Z (4 2 -8), LINESTRING Z (4 2 -8, 40 20 -80), POLYGON Z ((0 0 0, 20 0 0, 20 10 0, 0 10 0, 0 0 0)))',
335
+ 'GEOMETRYCOLLECTION Z (POINT Z (1 1 1), LINESTRING Z (1 1 1, 10 10 10), POLYGON Z ((0 0 0, 5 0 0, 5 5 0, 0 5 0, 0 0 0)))',
336
+ 4,
337
+ 2,
338
+ -8)
339
+ end
340
+
341
+ def test_scale_hash
342
+ affine_tester(:scale,
343
+ 'GEOMETRYCOLLECTION (POINT (5 5), LINESTRING (0 0, 50 50), POLYGON ((0 0, 25 0, 25 25, 0 25, 0 0)))',
344
+ 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))',
345
+ x: 5,
346
+ y: 5)
347
+
348
+ affine_tester(:scale,
349
+ 'GEOMETRYCOLLECTION (POINT (3 2), LINESTRING (0 0, 30 20), POLYGON ((0 0, 15 0, 15 10, 0 10, 0 0)))',
350
+ 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))',
351
+ x: 3,
352
+ y: 2)
353
+
354
+ writer.output_dimensions = 3
355
+ affine_tester(:scale,
356
+ 'GEOMETRYCOLLECTION Z (POINT Z (4 2 -8), LINESTRING Z (4 2 -8, 40 20 -80), POLYGON Z ((0 0 0, 20 0 0, 20 10 0, 0 10 0, 0 0 0)))',
357
+ 'GEOMETRYCOLLECTION Z (POINT Z (1 1 1), LINESTRING Z (1 1 1, 10 10 10), POLYGON Z ((0 0 0, 5 0 0, 5 5 0, 0 5 0, 0 0 0)))',
358
+ x: 4,
359
+ y: 2,
360
+ z: -8)
361
+ end
362
+
363
+ def test_trans_scale
364
+ affine_tester(:trans_scale,
365
+ 'GEOMETRYCOLLECTION (POINT (3 3), LINESTRING (2 2, 12 12), POLYGON ((2 2, 7 2, 7 7, 2 7, 2 2)))',
366
+ 'GEOMETRYCOLLECTION (POINT (2 2), LINESTRING (1 1, 11 11), POLYGON ((1 1, 6 1, 6 6, 1 6, 1 1)))',
367
+ 1, 1, 1, 1)
368
+
369
+ wkt = 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))'
370
+
371
+ affine_tester(:trans_scale,
372
+ 'GEOMETRYCOLLECTION (POINT (2 2), LINESTRING (1 1, 11 11), POLYGON ((1 1, 6 1, 6 6, 1 6, 1 1)))',
373
+ wkt,
374
+ 1, 1, 1, 1)
375
+
376
+ affine_tester(:trans_scale,
377
+ 'GEOMETRYCOLLECTION (POINT (0 0), LINESTRING (1 1, -9 -9), POLYGON ((1 1, -4 1, -4 -4, 1 -4, 1 1)))',
378
+ wkt,
379
+ -1, -1, -1, -1)
380
+
381
+ affine_tester(:trans_scale,
382
+ 'GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (0 1, 10 11), POLYGON ((0 1, 5 1, 5 6, 0 6, 0 1)))',
383
+ wkt,
384
+ 0, 1, 1, 1)
385
+
386
+ affine_tester(:trans_scale,
387
+ 'GEOMETRYCOLLECTION (POINT (2 1), LINESTRING (1 0, 11 10), POLYGON ((1 0, 6 0, 6 5, 1 5, 1 0)))',
388
+ wkt,
389
+ 1, 0, 1, 1)
390
+
391
+ affine_tester(:trans_scale,
392
+ 'GEOMETRYCOLLECTION (POINT (3 2), LINESTRING (2 1, 12 11), POLYGON ((2 1, 7 1, 7 6, 2 6, 2 1)))',
393
+ wkt,
394
+ 2, 1, 1, 1)
395
+
396
+ affine_tester(:trans_scale,
397
+ 'GEOMETRYCOLLECTION (POINT (2 3), LINESTRING (1 2, 11 12), POLYGON ((1 2, 6 2, 6 7, 1 7, 1 2)))',
398
+ wkt,
399
+ 1, 2, 1, 1)
400
+
401
+ affine_tester(:trans_scale,
402
+ 'GEOMETRYCOLLECTION (POINT (4 2), LINESTRING (2 1, 22 11), POLYGON ((2 1, 12 1, 12 6, 2 6, 2 1)))',
403
+ wkt,
404
+ 1, 1, 2, 1)
405
+
406
+ affine_tester(:trans_scale,
407
+ 'GEOMETRYCOLLECTION (POINT (2 4), LINESTRING (1 2, 11 22), POLYGON ((1 2, 6 2, 6 12, 1 12, 1 2)))',
408
+ wkt,
409
+ 1, 1, 1, 2)
410
+
411
+ affine_tester(:trans_scale,
412
+ 'GEOMETRYCOLLECTION (POINT (15 28), LINESTRING (10 21, 60 91), POLYGON ((10 21, 35 21, 35 56, 10 56, 10 21)))',
413
+ wkt,
414
+ 2, 3, 5, 7)
415
+
416
+ writer.output_dimensions = 3
417
+ affine_tester(:trans_scale,
418
+ 'GEOMETRYCOLLECTION Z (POINT Z (15 28 1), LINESTRING Z (15 28 1, 60 91 10), POLYGON Z ((10 21 0, 35 21 0, 35 56 0, 10 56 0, 10 21 0)))',
419
+ 'GEOMETRYCOLLECTION Z (POINT Z (1 1 1), LINESTRING Z (1 1 1, 10 10 10), POLYGON Z ((0 0 0, 5 0 0, 5 5 0, 0 5 0, 0 0 0)))',
420
+ 2, 3, 5, 7)
421
+ end
422
+
423
+ def test_trans_scale_hash
424
+ affine_tester(:trans_scale,
425
+ 'GEOMETRYCOLLECTION (POINT (2 2), LINESTRING (1 1, 11 11), POLYGON ((1 1, 6 1, 6 6, 1 6, 1 1)))',
426
+ 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))',
427
+ delta_x: 1, delta_y: 1, x_factor: 1, y_factor: 1)
428
+
429
+ writer.output_dimensions = 3
430
+ affine_tester(:trans_scale,
431
+ 'GEOMETRYCOLLECTION Z (POINT Z (15 28 1), LINESTRING Z (15 28 1, 60 91 10), POLYGON Z ((10 21 0, 35 21 0, 35 56 0, 10 56 0, 10 21 0)))',
432
+ 'GEOMETRYCOLLECTION Z (POINT Z (1 1 1), LINESTRING Z (1 1 1, 10 10 10), POLYGON Z ((0 0 0, 5 0 0, 5 5 0, 0 5 0, 0 0 0)))',
433
+ delta_x: 2, delta_y: 3, x_factor: 5, y_factor: 7)
434
+
435
+ affine_tester(:trans_scale,
436
+ 'GEOMETRYCOLLECTION Z (POINT Z (3 1 1), LINESTRING Z (3 1 1, 12 10 10), POLYGON Z ((2 0 0, 7 0 0, 7 5 0, 2 5 0, 2 0 0)))',
437
+ 'GEOMETRYCOLLECTION Z (POINT Z (1 1 1), LINESTRING Z (1 1 1, 10 10 10), POLYGON Z ((0 0 0, 5 0 0, 5 5 0, 0 5 0, 0 0 0)))',
438
+ delta_x: 2, z_factor: 2)
439
+ end
440
+
441
+ def test_translate
442
+ affine_tester(:translate,
443
+ 'GEOMETRYCOLLECTION (POINT (6 13), LINESTRING (5 12, 15 22), POLYGON ((5 12, 10 12, 10 17, 5 17, 5 12)))',
444
+ 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))',
445
+ 5,
446
+ 12)
447
+
448
+ writer.output_dimensions = 3
449
+ affine_tester(:translate,
450
+ 'GEOMETRYCOLLECTION Z (POINT Z (-2 -6 4), LINESTRING Z (-2 -6 4, 7 3 13), POLYGON Z ((-3 -7 3, 2 -7 3, 2 -2 3, -3 -2 3, -3 -7 3)))',
451
+ 'GEOMETRYCOLLECTION Z (POINT Z (1 1 1), LINESTRING Z (1 1 1, 10 10 10), POLYGON Z ((0 0 0, 5 0 0, 5 5 0, 0 5 0, 0 0 0)))',
452
+ -3,
453
+ -7,
454
+ 3)
455
+ end
456
+
457
+ def test_translate_hash
458
+ affine_tester(:translate,
459
+ 'GEOMETRYCOLLECTION (POINT (6 13), LINESTRING (5 12, 15 22), POLYGON ((5 12, 10 12, 10 17, 5 17, 5 12)))',
460
+ 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))',
461
+ x: 5,
462
+ y: 12)
463
+
464
+ writer.output_dimensions = 3
465
+ affine_tester(:translate,
466
+ 'GEOMETRYCOLLECTION Z (POINT Z (-2 -6 4), LINESTRING Z (-2 -6 4, 7 3 13), POLYGON Z ((-3 -7 3, 2 -7 3, 2 -2 3, -3 -2 3, -3 -7 3)))',
467
+ 'GEOMETRYCOLLECTION Z (POINT Z (1 1 1), LINESTRING Z (1 1 1, 10 10 10), POLYGON Z ((0 0 0, 5 0 0, 5 5 0, 0 5 0, 0 0 0)))',
468
+ x: -3,
469
+ y: -7,
470
+ z: 3)
471
+ end
88
472
  end
@@ -1,7 +1,5 @@
1
- # encoding: UTF-8
2
1
  # frozen_string_literal: true
3
2
 
4
- $: << File.dirname(__FILE__)
5
3
  require 'test_helper'
6
4
 
7
5
  class GeometryTests < Minitest::Test
@@ -15,15 +13,37 @@ class GeometryTests < Minitest::Test
15
13
  def test_intersection
16
14
  comparison_tester(
17
15
  :intersection,
18
- 'POLYGON ((5 10, 10 10, 10 5, 5 5, 5 10))',
16
+ if Geos::GEOS_VERSION > '3.9.0'
17
+ 'POLYGON ((10 10, 10 5, 5 5, 5 10, 10 10))'
18
+ else
19
+ 'POLYGON ((5 10, 10 10, 10 5, 5 5, 5 10))'
20
+ end,
19
21
  'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))',
20
22
  'POLYGON ((5 5, 15 5, 15 15, 5 15, 5 5))'
21
23
  )
22
24
  end
23
25
 
24
- def test_buffer
25
- writer.rounding_precision = 2
26
+ def test_intersection_with_precision
27
+ skip unless ENV['FORCE_TESTS'] || Geos::FFIGeos.respond_to?(:GEOSIntersectionPrec_r)
28
+
29
+ comparison_tester(
30
+ :intersection,
31
+ 'GEOMETRYCOLLECTION (POLYGON ((1 2, 1 1, 0.5 1, 1 2)), POLYGON ((9.5 1, 2 1, 2 2, 9 2, 9.5 1)), LINESTRING (1 1, 2 1), LINESTRING (2 2, 1 2))',
32
+ 'MULTIPOLYGON(((0 0,5 10,10 0,0 0),(1 1,1 2,2 2,2 1,1 1),(100 100,100 102,102 102,102 100,100 100)))',
33
+ 'POLYGON((0 1,0 2,10 2,10 1,0 1))',
34
+ precision: 0
35
+ )
26
36
 
37
+ comparison_tester(
38
+ :intersection,
39
+ 'GEOMETRYCOLLECTION (LINESTRING (2 0, 4 0), POINT (0 0), POINT (10 0))',
40
+ 'LINESTRING(0 0, 10 0)',
41
+ 'LINESTRING(9 0, 12 0, 12 20, 4 0, 2 0, 2 10, 0 10, 0 -10)',
42
+ precision: 2
43
+ )
44
+ end
45
+
46
+ def test_buffer
27
47
  simple_tester(
28
48
  :buffer,
29
49
  'POLYGON EMPTY',
@@ -31,95 +51,95 @@ class GeometryTests < Minitest::Test
31
51
  0
32
52
  )
33
53
 
34
- simple_tester(
54
+ snapped_tester(
35
55
  :buffer,
36
- 'POLYGON ((10 0, 9.8 -2, 9.2 -3.8, 8.3 -5.6, 7.1 -7.1, 5.6 -8.3, 3.8 -9.2, 2 -9.8, 1.6e-14 -10, -2 -9.8, -3.8 -9.2, -5.6 -8.3, -7.1 -7.1, -8.3 -5.6, -9.2 -3.8, -9.8 -2, -10 -3.2e-14, -9.8 2, -9.2 3.8, -8.3 5.6, -7.1 7.1, -5.6 8.3, -3.8 9.2, -2 9.8, -3.7e-14 10, 2 9.8, 3.8 9.2, 5.6 8.3, 7.1 7.1, 8.3 5.6, 9.2 3.8, 9.8 2, 10 0))',
56
+ 'POLYGON ((10 0, 10 -2, 9 -4, 8 -6, 7 -7, 6 -8, 4 -9, 2 -10, 0 -10, -2 -10, -4 -9, -6 -8, -7 -7, -8 -6, -9 -4, -10 -2, -10 0, -10 2, -9 4, -8 6, -7 7, -6 8, -4 9, -2 10, 0 10, 2 10, 4 9, 6 8, 7 7, 8 6, 9 4, 10 2, 10 0))',
37
57
  'POINT(0 0)',
38
58
  10
39
59
  )
40
60
 
41
61
  # One segment per quadrant
42
- simple_tester(
62
+ snapped_tester(
43
63
  :buffer,
44
- 'POLYGON ((10 0, 1.6e-14 -10, -10 -3.2e-14, -4.6e-14 10, 10 0))',
64
+ 'POLYGON ((10 0, 0 -10, -10 0, 0 10, 10 0))',
45
65
  'POINT(0 0)',
46
66
  10,
47
- { :quad_segs => 1 }
67
+ quad_segs: 1
48
68
  )
49
69
 
50
70
  # End cap styles
51
- simple_tester(
71
+ snapped_tester(
52
72
  :buffer,
53
- 'POLYGON ((1e+02 10, 1.1e+02 0, 1e+02 -10, 0 -10, -10 1.2e-15, 0 10, 1e+02 10))',
73
+ 'POLYGON ((100 10, 110 0, 100 -10, 0 -10, -10 0, 0 10, 100 10))',
54
74
  'LINESTRING(0 0, 100 0)',
55
75
  10,
56
- { :quad_segs => 1, :endcap => :round }
76
+ quad_segs: 1, endcap: :round
57
77
  )
58
78
 
59
- simple_tester(
79
+ snapped_tester(
60
80
  :buffer,
61
- 'POLYGON ((1e+02 10, 1e+02 -10, 0 -10, 0 10, 1e+02 10))',
81
+ 'POLYGON ((100 10, 100 -10, 0 -10, 0 10, 100 10))',
62
82
  'LINESTRING(0 0, 100 0)',
63
83
  10,
64
- { :quad_segs => 1, :endcap => :flat }
84
+ quad_segs: 1, endcap: :flat
65
85
  )
66
86
 
67
- simple_tester(
87
+ snapped_tester(
68
88
  :buffer,
69
- 'POLYGON ((1e+02 10, 1.1e+02 10, 1.1e+02 -10, 0 -10, -10 -10, -10 10, 1e+02 10))',
89
+ 'POLYGON ((100 10, 110 10, 110 -10, 0 -10, -10 -10, -10 10, 100 10))',
70
90
  'LINESTRING(0 0, 100 0)',
71
91
  10,
72
- { :quad_segs => 1, :endcap => :square }
92
+ quad_segs: 1, endcap: :square
73
93
  )
74
94
 
75
95
  # Join styles
76
- simple_tester(
96
+ snapped_tester(
77
97
  :buffer,
78
- 'POLYGON ((90 10, 90 1e+02, 93 1.1e+02, 1e+02 1.1e+02, 1.1e+02 1.1e+02, 1.1e+02 1e+02, 1.1e+02 0, 1.1e+02 -7.1, 1e+02 -10, 0 -10, -7.1 -7.1, -10 1.2e-15, -7.1 7.1, 0 10, 90 10))',
98
+ 'POLYGON ((90 10, 90 100, 93 107, 100 110, 107 107, 110 100, 110 0, 107 -7, 100 -10, 0 -10, -7 -7, -10 0, -7 7, 0 10, 90 10))',
79
99
  'LINESTRING(0 0, 100 0, 100 100)',
80
100
  10,
81
- { :quad_segs => 2, :join => :round }
101
+ quad_segs: 2, join: :round
82
102
  )
83
103
 
84
- simple_tester(
104
+ snapped_tester(
85
105
  :buffer,
86
- 'POLYGON ((90 10, 90 1e+02, 93 1.1e+02, 1e+02 1.1e+02, 1.1e+02 1.1e+02, 1.1e+02 1e+02, 1.1e+02 0, 1e+02 -10, 0 -10, -7.1 -7.1, -10 1.2e-15, -7.1 7.1, 0 10, 90 10))',
106
+ 'POLYGON ((90 10, 90 100, 93 107, 100 110, 107 107, 110 100, 110 0, 100 -10, 0 -10, -7 -7, -10 0, -7 7, 0 10, 90 10))',
87
107
  'LINESTRING(0 0, 100 0, 100 100)',
88
108
  10,
89
- { :quad_segs => 2, :join => :bevel }
109
+ quad_segs: 2, join: :bevel
90
110
  )
91
111
 
92
- simple_tester(
112
+ snapped_tester(
93
113
  :buffer,
94
- 'POLYGON ((90 10, 90 1e+02, 93 1.1e+02, 1e+02 1.1e+02, 1.1e+02 1.1e+02, 1.1e+02 1e+02, 1.1e+02 -10, 0 -10, -7.1 -7.1, -10 1.2e-15, -7.1 7.1, 0 10, 90 10))',
114
+ 'POLYGON ((90 10, 90 100, 93 107, 100 110, 107 107, 110 100, 110 -10, 0 -10, -7 -7, -10 0, -7 7, 0 10, 90 10))',
95
115
  'LINESTRING(0 0, 100 0, 100 100)',
96
116
  10,
97
- { :quad_segs => 2, :join => :mitre }
117
+ quad_segs: 2, join: :mitre
98
118
  )
99
119
 
100
- simple_tester(
120
+ snapped_tester(
101
121
  :buffer,
102
- 'POLYGON ((90 10, 90 1e+02, 93 1.1e+02, 1e+02 1.1e+02, 1.1e+02 1.1e+02, 1.1e+02 1e+02, 1.1e+02 -5, 1e+02 -9.1, 0 -10, -7.1 -7.1, -10 1.2e-15, -7.1 7.1, 0 10, 90 10))',
122
+ 'POLYGON ((90 10, 90 100, 93 107, 100 110, 107 107, 110 100, 109 -5, 105 -9, 0 -10, -7 -7, -10 0, -7 7, 0 10, 90 10))',
103
123
  'LINESTRING(0 0, 100 0, 100 100)',
104
124
  10,
105
- { :quad_segs => 2, :join => :mitre, :mitre_limit => 1.0 }
125
+ quad_segs: 2, join: :mitre, mitre_limit: 1.0
106
126
  )
107
127
 
108
128
  # Single-sided buffering
109
- simple_tester(
129
+ snapped_tester(
110
130
  :buffer,
111
- 'POLYGON ((1e+02 0, 0 0, 0 10, 1e+02 10, 1e+02 0))',
131
+ 'POLYGON ((100 0, 0 0, 0 10, 100 10, 100 0))',
112
132
  'LINESTRING(0 0, 100 0)',
113
133
  10,
114
- { :single_sided => true }
134
+ single_sided: true
115
135
  )
116
136
 
117
- simple_tester(
137
+ snapped_tester(
118
138
  :buffer,
119
- 'POLYGON ((0 0, 1e+02 0, 1e+02 -10, 0 -10, 0 0))',
139
+ 'POLYGON ((0 0, 100 0, 100 -10, 0 -10, 0 0))',
120
140
  'LINESTRING(0 0, 100 0)',
121
141
  -10,
122
- { :single_sided => true }
142
+ single_sided: true
123
143
  )
124
144
  end
125
145
 
@@ -137,7 +157,7 @@ class GeometryTests < Minitest::Test
137
157
  def test_difference
138
158
  comparison_tester(
139
159
  :difference,
140
- 'GEOMETRYCOLLECTION EMPTY',
160
+ EMPTY_GEOMETRY,
141
161
  'POINT(0 0)',
142
162
  'POINT(0 0)'
143
163
  )
@@ -158,7 +178,7 @@ class GeometryTests < Minitest::Test
158
178
 
159
179
  comparison_tester(
160
180
  :difference,
161
- 'GEOMETRYCOLLECTION EMPTY',
181
+ EMPTY_GEOMETRY,
162
182
  'POINT(5 0)',
163
183
  'LINESTRING(0 0, 10 0)'
164
184
  )
@@ -186,31 +206,55 @@ class GeometryTests < Minitest::Test
186
206
 
187
207
  comparison_tester(
188
208
  :difference,
189
- 'POLYGON ((5 0, 0 0, 0 10, 5 10, 10 10, 10 0, 5 0))',
209
+ if Geos::GEOS_VERSION > '3.9.0'
210
+ 'POLYGON ((0 10, 5 10, 10 10, 10 0, 5 0, 0 0, 0 10))'
211
+ else
212
+ 'POLYGON ((0 0, 0 10, 5 10, 10 10, 10 0, 5 0, 0 0))'
213
+ end,
190
214
  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
191
215
  'LINESTRING(5 -10, 5 10)'
192
216
  )
193
217
 
194
218
  comparison_tester(
195
219
  :difference,
196
- 'POLYGON ((10 0, 0 0, 0 10, 10 10, 10 0))',
220
+ if Geos::GEOS_VERSION > '3.9.0'
221
+ 'POLYGON ((0 10, 10 10, 10 0, 0 0, 0 10))'
222
+ else
223
+ 'POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))'
224
+ end,
197
225
  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
198
226
  'LINESTRING(10 0, 20 0)'
199
227
  )
200
228
 
201
229
  comparison_tester(
202
230
  :difference,
203
- 'POLYGON ((5 0, 0 0, 0 10, 10 10, 10 5, 5 5, 5 0))',
231
+ if Geos::GEOS_VERSION > '3.9.0'
232
+ 'POLYGON ((0 10, 10 10, 10 5, 5 5, 5 0, 0 0, 0 10))'
233
+ else
234
+ 'POLYGON ((0 0, 0 10, 10 10, 10 5, 5 5, 5 0, 0 0))'
235
+ end,
204
236
  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
205
237
  'POLYGON((5 -5, 5 5, 15 5, 15 -5, 5 -5))'
206
238
  )
207
239
  end
208
240
 
241
+ def test_difference_with_precision
242
+ skip unless ENV['FORCE_TESTS'] || Geos::FFIGeos.respond_to?(:GEOSDifferencePrec_r)
243
+
244
+ comparison_tester(
245
+ :difference,
246
+ 'MULTILINESTRING ((2 8, 4 8), (6 8, 10 8))',
247
+ 'LINESTRING (2 8, 10 8)',
248
+ 'LINESTRING (3.9 8.1, 6.1 7.9)',
249
+ precision: 2
250
+ )
251
+ end
252
+
209
253
  def test_sym_difference
210
254
  %w{ sym_difference symmetric_difference }.each do |method|
211
255
  comparison_tester(
212
256
  method,
213
- 'GEOMETRYCOLLECTION EMPTY',
257
+ EMPTY_GEOMETRY,
214
258
  'POINT(0 0)',
215
259
  'POINT(0 0)'
216
260
  )
@@ -259,27 +303,51 @@ class GeometryTests < Minitest::Test
259
303
 
260
304
  comparison_tester(
261
305
  method,
262
- 'GEOMETRYCOLLECTION (LINESTRING (5 -10, 5 0), POLYGON ((5 0, 0 0, 0 10, 5 10, 10 10, 10 0, 5 0)))',
306
+ if Geos::GEOS_VERSION > '3.9.0'
307
+ 'GEOMETRYCOLLECTION (POLYGON ((0 10, 5 10, 10 10, 10 0, 5 0, 0 0, 0 10)), LINESTRING (5 -10, 5 0))'
308
+ else
309
+ 'GEOMETRYCOLLECTION (LINESTRING (5 -10, 5 0), POLYGON ((0 0, 0 10, 5 10, 10 10, 10 0, 5 0, 0 0)))'
310
+ end,
263
311
  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
264
312
  'LINESTRING(5 -10, 5 10)'
265
313
  )
266
314
 
267
315
  comparison_tester(
268
316
  method,
269
- 'GEOMETRYCOLLECTION (LINESTRING (10 0, 20 0), POLYGON ((10 0, 0 0, 0 10, 10 10, 10 0)))',
317
+ if Geos::GEOS_VERSION > '3.9.0'
318
+ 'GEOMETRYCOLLECTION (POLYGON ((0 10, 10 10, 10 0, 0 0, 0 10)), LINESTRING (10 0, 20 0))'
319
+ else
320
+ 'GEOMETRYCOLLECTION (LINESTRING (10 0, 20 0), POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0)))'
321
+ end,
270
322
  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
271
323
  'LINESTRING(10 0, 20 0)'
272
324
  )
273
325
 
274
326
  comparison_tester(
275
327
  method,
276
- 'MULTIPOLYGON (((5 0, 0 0, 0 10, 10 10, 10 5, 5 5, 5 0)), ((5 0, 10 0, 10 5, 15 5, 15 -5, 5 -5, 5 0)))',
328
+ if Geos::GEOS_VERSION > '3.9.0'
329
+ 'MULTIPOLYGON (((0 10, 10 10, 10 5, 5 5, 5 0, 0 0, 0 10)), ((10 0, 10 5, 15 5, 15 -5, 5 -5, 5 0, 10 0)))'
330
+ else
331
+ 'MULTIPOLYGON (((0 0, 0 10, 10 10, 10 5, 5 5, 5 0, 0 0)), ((5 0, 10 0, 10 5, 15 5, 15 -5, 5 -5, 5 0)))'
332
+ end,
277
333
  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
278
334
  'POLYGON((5 -5, 5 5, 15 5, 15 -5, 5 -5))'
279
335
  )
280
336
  end
281
337
  end
282
338
 
339
+ def test_sym_difference_with_precision
340
+ skip unless ENV['FORCE_TESTS'] || Geos::FFIGeos.respond_to?(:GEOSSymDifferencePrec_r)
341
+
342
+ comparison_tester(
343
+ :sym_difference,
344
+ 'GEOMETRYCOLLECTION (POLYGON ((0 10, 6 10, 10 10, 10 0, 6 0, 0 0, 0 10)), LINESTRING (6 -10, 6 0))',
345
+ 'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
346
+ 'LINESTRING(5 -10, 5 10)',
347
+ precision: 2
348
+ )
349
+ end
350
+
283
351
  def test_boundary
284
352
  simple_tester(
285
353
  :boundary,
@@ -352,32 +420,59 @@ class GeometryTests < Minitest::Test
352
420
 
353
421
  comparison_tester(
354
422
  :union,
355
- 'GEOMETRYCOLLECTION (LINESTRING (5 -10, 5 0), POLYGON ((5 0, 0 0, 0 10, 5 10, 10 10, 10 0, 5 0)))',
423
+ if Geos::GEOS_VERSION > '3.9.0'
424
+ 'GEOMETRYCOLLECTION (POLYGON ((0 10, 5 10, 10 10, 10 0, 5 0, 0 0, 0 10)), LINESTRING (5 -10, 5 0))'
425
+ else
426
+ 'GEOMETRYCOLLECTION (LINESTRING (5 -10, 5 0), POLYGON ((0 0, 0 10, 5 10, 10 10, 10 0, 5 0, 0 0)))'
427
+ end,
356
428
  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
357
429
  'LINESTRING(5 -10, 5 10)'
358
430
  )
359
431
 
360
432
  comparison_tester(
361
433
  :union,
362
- 'GEOMETRYCOLLECTION (LINESTRING (10 0, 20 0), POLYGON ((10 0, 0 0, 0 10, 10 10, 10 0)))',
434
+ if Geos::GEOS_VERSION > '3.9.0'
435
+ 'GEOMETRYCOLLECTION (POLYGON ((0 10, 10 10, 10 0, 0 0, 0 10)), LINESTRING (10 0, 20 0))'
436
+ else
437
+ 'GEOMETRYCOLLECTION (LINESTRING (10 0, 20 0), POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0)))'
438
+ end,
363
439
  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
364
440
  'LINESTRING(10 0, 20 0)'
365
441
  )
366
442
 
367
443
  comparison_tester(
368
444
  :union,
369
- 'POLYGON ((5 0, 0 0, 0 10, 10 10, 10 5, 15 5, 15 -5, 5 -5, 5 0))',
445
+ if Geos::GEOS_VERSION > '3.9.0'
446
+ 'POLYGON ((0 10, 10 10, 10 5, 15 5, 15 -5, 5 -5, 5 0, 0 0, 0 10))'
447
+ else
448
+ 'POLYGON ((0 0, 0 10, 10 10, 10 5, 15 5, 15 -5, 5 -5, 5 0, 0 0))'
449
+ end,
370
450
  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
371
451
  'POLYGON((5 -5, 5 5, 15 5, 15 -5, 5 -5))'
372
452
  )
373
453
  end
374
454
 
455
+ def test_union_with_precision
456
+ skip unless ENV['FORCE_TESTS'] || Geos::FFIGeos.respond_to?(:GEOSUnionPrec_r)
457
+
458
+ geom_a = read('POINT (1.9 8.2)')
459
+ geom_b = read('POINT (4.1 9.8)')
460
+
461
+ result = geom_a.union(geom_b, precision: 2)
462
+
463
+ assert_equal('MULTIPOINT (2 8, 4 10)', write(result))
464
+ end
465
+
375
466
  def test_union_cascaded
376
467
  skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:union_cascaded)
377
468
 
378
469
  simple_tester(
379
470
  :union_cascaded,
380
- 'POLYGON ((1 0, 0 0, 0 1, 0 11, 10 11, 10 14, 14 14, 14 10, 11 10, 11 0, 1 0), (11 11, 12 11, 12 12, 11 12, 11 11))',
471
+ if Geos::GEOS_VERSION > '3.9.0'
472
+ 'POLYGON ((0 0, 0 1, 0 11, 10 11, 10 14, 14 14, 14 10, 11 10, 11 0, 1 0, 0 0), (12 12, 11 12, 11 11, 12 11, 12 12))'
473
+ else
474
+ 'POLYGON ((1 0, 0 0, 0 1, 0 11, 10 11, 10 14, 14 14, 14 10, 11 10, 11 0, 1 0), (11 11, 12 11, 12 12, 11 12, 11 11))'
475
+ end,
381
476
  'MULTIPOLYGON(
382
477
  ((0 0, 1 0, 1 1, 0 1, 0 0)),
383
478
  ((10 10, 10 14, 14 14, 14 10, 10 10),
@@ -387,12 +482,33 @@ class GeometryTests < Minitest::Test
387
482
  )
388
483
  end
389
484
 
485
+ def test_coverage_union
486
+ skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:coverage_union)
487
+
488
+ simple_tester(
489
+ :union_cascaded,
490
+ if Geos::GEOS_VERSION > '3.9.0'
491
+ 'POLYGON ((0 1, 1 1, 2 1, 2 0, 1 0, 0 0, 0 1))'
492
+ else
493
+ 'POLYGON ((0 0, 0 1, 1 1, 2 1, 2 0, 1 0, 0 0))'
494
+ end,
495
+ 'MULTIPOLYGON(
496
+ ((0 0, 0 1, 1 1, 1 0, 0 0)),
497
+ ((1 0, 1 1, 2 1, 2 0, 1 0))
498
+ ))'
499
+ )
500
+ end
501
+
390
502
  def test_unary_union
391
503
  skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:unary_union)
392
504
 
393
505
  simple_tester(
394
506
  :unary_union,
395
- 'POLYGON ((1 0, 0 0, 0 1, 0 11, 10 11, 10 14, 14 14, 14 10, 11 10, 11 0, 1 0), (11 11, 12 11, 12 12, 11 12, 11 11))',
507
+ if Geos::GEOS_VERSION > '3.9.0'
508
+ 'POLYGON ((0 0, 0 1, 0 11, 10 11, 10 14, 14 14, 14 10, 11 10, 11 0, 1 0, 0 0), (12 12, 11 12, 11 11, 12 11, 12 12))'
509
+ else
510
+ 'POLYGON ((1 0, 0 0, 0 1, 0 11, 10 11, 10 14, 14 14, 14 10, 11 10, 11 0, 1 0), (11 11, 12 11, 12 12, 11 12, 11 11))'
511
+ end,
396
512
  'MULTIPOLYGON(
397
513
  ((0 0, 1 0, 1 1, 0 1, 0 0)),
398
514
  ((10 10, 10 14, 14 14, 14 10, 10 10),
@@ -402,6 +518,22 @@ class GeometryTests < Minitest::Test
402
518
  )
403
519
  end
404
520
 
521
+ def test_unary_union_with_precision
522
+ skip unless ENV['FORCE_TESTS'] || Geos::FFIGeos.respond_to?(:GEOSUnaryUnionPrec_r)
523
+
524
+ simple_tester(
525
+ :unary_union,
526
+ 'POLYGON ((0 0, 0 12, 9 12, 9 15, 15 15, 15 9, 12 9, 12 0, 0 0))',
527
+ 'MULTIPOLYGON(
528
+ ((0 0, 1 0, 1 1, 0 1, 0 0)),
529
+ ((10 10, 10 14, 14 14, 14 10, 10 10),
530
+ (11 11, 11 12, 12 12, 12 11, 11 11)),
531
+ ((0 0, 11 0, 11 11, 0 11, 0 0))
532
+ ))',
533
+ 3
534
+ )
535
+ end
536
+
405
537
  def test_node
406
538
  skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:node)
407
539
 
@@ -415,7 +547,11 @@ class GeometryTests < Minitest::Test
415
547
  def test_union_without_arguments
416
548
  simple_tester(
417
549
  :union,
418
- 'POLYGON ((1 0, 0 0, 0 1, 0 11, 10 11, 10 14, 14 14, 14 10, 11 10, 11 0, 1 0), (11 11, 12 11, 12 12, 11 12, 11 11))',
550
+ if Geos::GEOS_VERSION > '3.9.0'
551
+ 'POLYGON ((0 0, 0 1, 0 11, 10 11, 10 14, 14 14, 14 10, 11 10, 11 0, 1 0, 0 0), (12 12, 11 12, 11 11, 12 11, 12 12))'
552
+ else
553
+ 'POLYGON ((1 0, 0 0, 0 1, 0 11, 10 11, 10 14, 14 14, 14 10, 11 10, 11 0, 1 0), (11 11, 12 11, 12 12, 11 12, 11 11))'
554
+ end,
419
555
  'MULTIPOLYGON(
420
556
  ((0 0, 1 0, 1 1, 0 1, 0 0)),
421
557
  ((10 10, 10 14, 14 14, 14 10, 10 10),
@@ -511,10 +647,7 @@ class GeometryTests < Minitest::Test
511
647
  'LINESTRING(0 0, 10 10)'
512
648
  )
513
649
 
514
- writer.trim = true
515
- writer.rounding_precision = 0
516
-
517
- simple_tester(
650
+ snapped_tester(
518
651
  method,
519
652
  'POINT (5 4)',
520
653
  'POLYGON((0 0, 0 10, 5 5, 10 10, 10 0, 0 0))'
@@ -522,6 +655,17 @@ class GeometryTests < Minitest::Test
522
655
  end
523
656
  end
524
657
 
658
+ def test_minimum_bounding_circle
659
+ skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:minimum_bounding_circle)
660
+
661
+ geom = read('LINESTRING(0 10, 0 20)')
662
+
663
+ assert_equal(
664
+ 'POLYGON ((5 15, 5 14, 5 13, 4 12, 4 11, 3 11, 2 10, 1 10, 0 10, -1 10, -2 10, -3 11, -4 11, -4 12, -5 13, -5 14, -5 15, -5 16, -5 17, -4 18, -4 19, -3 19, -2 20, -1 20, 0 20, 1 20, 2 20, 3 19, 4 19, 4 18, 5 17, 5 16, 5 15))',
665
+ write(geom.minimum_bounding_circle.snap_to_grid(1))
666
+ )
667
+ end
668
+
525
669
  def test_envelope
526
670
  simple_tester(
527
671
  :envelope,
@@ -656,7 +800,7 @@ class GeometryTests < Minitest::Test
656
800
  tests.each do |test|
657
801
  expected, method, args = test
658
802
  if ENV['FORCE_TESTS'] || geom_a.respond_to?(method)
659
- value = geom_a.send(method, *([ geom_b ] + Array(args)))
803
+ value = geom_a.send(method, *([geom_b] + Array(args)))
660
804
  assert_equal(expected, value)
661
805
  end
662
806
  end
@@ -795,10 +939,10 @@ class GeometryTests < Minitest::Test
795
939
  def test_valid_reason
796
940
  skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:valid_reason)
797
941
 
798
- assert_equal("Valid Geometry", read('POINT(0 0)').valid_reason)
799
- assert_equal("Invalid Coordinate[0 nan]", read('POINT(0 NaN)').valid_reason)
800
- assert_equal("Invalid Coordinate[0 nan]", read('POINT(0 nan)').valid_reason)
801
- assert_equal("Self-intersection[2.5 5]", read('POLYGON((0 0, 0 5, 5 5, 5 10, 0 0))').valid_reason)
942
+ assert_equal('Valid Geometry', read('POINT(0 0)').valid_reason)
943
+ assert_equal('Invalid Coordinate[0 nan]', read('POINT(0 NaN)').valid_reason)
944
+ assert_equal('Invalid Coordinate[0 nan]', read('POINT(0 nan)').valid_reason)
945
+ assert_equal('Self-intersection[2.5 5]', read('POLYGON((0 0, 0 5, 5 5, 5 10, 0 0))').valid_reason)
802
946
  end
803
947
 
804
948
  def test_valid_detail
@@ -811,14 +955,16 @@ class GeometryTests < Minitest::Test
811
955
  }
812
956
 
813
957
  assert_nil(read('POINT(0 0)').valid_detail)
814
- tester["Invalid Coordinate", 'POINT (0 nan)', 'POINT(0 NaN)', 0]
815
- tester["Self-intersection", 'POINT (2.5 5)', 'POLYGON((0 0, 0 5, 5 5, 5 10, 0 0))', 0]
958
+ tester['Invalid Coordinate', 'POINT (0 nan)', 'POINT(0 NaN)', 0]
959
+ tester['Self-intersection', 'POINT (2.5 5)', 'POLYGON((0 0, 0 5, 5 5, 5 10, 0 0))', 0]
816
960
 
817
- tester["Ring Self-intersection", 'POINT (0 0)', 'POLYGON((0 0, -10 10, 10 10, 0 0, 4 5, -4 5, 0 0)))', 0]
961
+ tester['Ring Self-intersection', 'POINT (0 0)', 'POLYGON((0 0, -10 10, 10 10, 0 0, 4 5, -4 5, 0 0)))', 0]
818
962
 
819
- assert_nil(read('POLYGON((0 0, -10 10, 10 10, 0 0, 4 5, -4 5, 0 0)))').valid_detail(
820
- :allow_selftouching_ring_forming_hole
821
- ))
963
+ assert_nil(
964
+ read('POLYGON((0 0, -10 10, 10 10, 0 0, 4 5, -4 5, 0 0)))').valid_detail(
965
+ :allow_selftouching_ring_forming_hole
966
+ )
967
+ )
822
968
  end
823
969
 
824
970
  def test_simple
@@ -847,8 +993,7 @@ class GeometryTests < Minitest::Test
847
993
  simple_tester(:num_geometries, 2, 'MULTIPOLYGON(
848
994
  ((0 0, 1 0, 1 1, 0 1, 0 0)),
849
995
  ((10 10, 10 14, 14 14, 14 10, 10 10),
850
- (11 11, 11 12, 12 12, 12 11, 11 11)))'
851
- )
996
+ (11 11, 11 12, 12 12, 12 11, 11 11)))')
852
997
  simple_tester(:num_geometries, 6, 'GEOMETRYCOLLECTION (
853
998
  MULTIPOLYGON (
854
999
  ((0 0, 1 0, 1 1, 0 1, 0 0)),
@@ -859,8 +1004,7 @@ class GeometryTests < Minitest::Test
859
1004
  MULTILINESTRING ((0 0, 2 3), (10 10, 3 4)),
860
1005
  LINESTRING (0 0, 2 3),
861
1006
  MULTIPOINT (0 0, 2 3),
862
- POINT (9 0))'
863
- )
1007
+ POINT (9 0))')
864
1008
  end
865
1009
 
866
1010
  # get_geometry_n is segfaulting in the binary GEOS build
@@ -881,8 +1025,7 @@ class GeometryTests < Minitest::Test
881
1025
  simple_tester(:num_interior_rings, 2, 'POLYGON (
882
1026
  (10 10, 10 14, 14 14, 14 10, 10 10),
883
1027
  (11 11, 11 12, 12 12, 12 11, 11 11),
884
- (13 11, 13 12, 13.5 12, 13.5 11, 13 11))'
885
- )
1028
+ (13 11, 13 12, 13.5 12, 13.5 11, 13 11))')
886
1029
 
887
1030
  assert_raises(NoMethodError) do
888
1031
  read('POINT (0 0)').num_interior_rings
@@ -959,7 +1102,7 @@ class GeometryTests < Minitest::Test
959
1102
  def test_interior_rings
960
1103
  array_tester(
961
1104
  :interior_rings,
962
- [ 'LINEARRING (11 11, 11 12, 12 12, 12 11, 11 11)' ],
1105
+ ['LINEARRING (11 11, 11 12, 12 12, 12 11, 11 11)'],
963
1106
  'POLYGON(
964
1107
  (10 10, 10 14, 14 14, 14 10, 10 10),
965
1108
  (11 11, 11 12, 12 12, 12 11, 11 11)
@@ -1024,12 +1167,12 @@ class GeometryTests < Minitest::Test
1024
1167
 
1025
1168
  def test_dimensions
1026
1169
  types = {
1027
- :dontcare => -3,
1028
- :non_empty => -2,
1029
- :empty => -1,
1030
- :point => 0,
1031
- :curve => 1,
1032
- :surface => 2
1170
+ dontcare: -3,
1171
+ non_empty: -2,
1172
+ empty: -1,
1173
+ point: 0,
1174
+ curve: 1,
1175
+ surface: 2
1033
1176
  }
1034
1177
 
1035
1178
  simple_tester(:dimensions, types[:point], 'POINT(0 0)')
@@ -1162,12 +1305,22 @@ class GeometryTests < Minitest::Test
1162
1305
  simple_tester(:distance, 2.0, geom, read('LINESTRING (3 0 , 10 0)'))
1163
1306
  end
1164
1307
 
1308
+ def test_distance_indexed
1309
+ skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:distance_indexed)
1310
+
1311
+ geom_a = read('POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))')
1312
+ geom_b = read('POLYGON ((20 30, 10 10, 13 14, 7 8, 20 30))')
1313
+
1314
+ assert_in_delta(9.219544457292887, geom_a.distance_indexed(geom_b), TOLERANCE)
1315
+ assert_in_delta(9.219544457292887, geom_b.distance_indexed(geom_a), TOLERANCE)
1316
+ end
1317
+
1165
1318
  def test_hausdorff_distance
1166
1319
  skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:hausdorff_distance)
1167
1320
 
1168
- tester = lambda { |expected, g1, g2|
1169
- geom_1 = read(g1)
1170
- geom_2 = read(g2)
1321
+ tester = lambda { |expected, g_1, g_2|
1322
+ geom_1 = read(g_1)
1323
+ geom_2 = read(g_2)
1171
1324
  assert_in_delta(expected, geom_1.hausdorff_distance(geom_2), TOLERANCE)
1172
1325
  }
1173
1326
 
@@ -1181,9 +1334,9 @@ class GeometryTests < Minitest::Test
1181
1334
  def test_hausdorff_distance_with_densify_fract
1182
1335
  skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:hausdorff_distance)
1183
1336
 
1184
- tester = lambda { |expected, g1, g2|
1185
- geom_1 = read(g1)
1186
- geom_2 = read(g2)
1337
+ tester = lambda { |expected, g_1, g_2|
1338
+ geom_1 = read(g_1)
1339
+ geom_2 = read(g_2)
1187
1340
  assert_in_delta(expected, geom_1.hausdorff_distance(geom_2, 0.001), TOLERANCE)
1188
1341
  }
1189
1342
 
@@ -1197,17 +1350,18 @@ class GeometryTests < Minitest::Test
1197
1350
  def test_nearest_points
1198
1351
  skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:nearest_points)
1199
1352
 
1200
- tester = lambda { |expected, g1, g2|
1201
- geom_1 = read(g1)
1202
- geom_2 = read(g2)
1353
+ tester = lambda { |expected, g_1, g_2|
1354
+ geom_1 = read(g_1)
1355
+ geom_2 = read(g_2)
1203
1356
 
1204
1357
  cs = geom_1.nearest_points(geom_2)
1358
+ result = cs.to_s if cs
1205
1359
 
1206
- result = if cs
1207
- cs.to_s
1360
+ if expected.nil?
1361
+ assert_nil(result)
1362
+ else
1363
+ assert_equal(expected, result)
1208
1364
  end
1209
-
1210
- assert_equal(expected, result)
1211
1365
  }
1212
1366
 
1213
1367
  tester[
@@ -1217,7 +1371,11 @@ class GeometryTests < Minitest::Test
1217
1371
  ]
1218
1372
 
1219
1373
  tester[
1220
- '5.0 5.0 NaN, 8.0 8.0 NaN',
1374
+ if Geos::GEOS_VERSION > '3.8'
1375
+ '5.0 5.0, 8.0 8.0'
1376
+ else
1377
+ '5.0 5.0 NaN, 8.0 8.0 NaN'
1378
+ end,
1221
1379
  'POLYGON((1 1, 1 5, 5 5, 5 1, 1 1))',
1222
1380
  'POLYGON((8 8, 9 9, 9 10, 8 8))'
1223
1381
  ]
@@ -1249,11 +1407,46 @@ class GeometryTests < Minitest::Test
1249
1407
  assert_equal(2, polygonized.length)
1250
1408
  assert_equal(
1251
1409
  'POLYGON ((185 221, 88 275, 180 316, 292 281, 185 221))',
1252
- write(polygonized[0])
1410
+ write(polygonized[0].snap_to_grid(0.1))
1253
1411
  )
1254
1412
  assert_equal(
1255
1413
  'POLYGON ((189 98, 83 187, 185 221, 325 168, 189 98))',
1256
- write(polygonized[1])
1414
+ write(polygonized[1].snap_to_grid(0.1))
1415
+ )
1416
+ end
1417
+
1418
+ def test_polygonize_with_geometry_arguments
1419
+ skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:polygonize)
1420
+
1421
+ geom_a = read('LINESTRING (100 100, 100 300, 300 300, 300 100, 100 100)')
1422
+ geom_b = read('LINESTRING (150 150, 150 250, 250 250, 250 150, 150 150)')
1423
+
1424
+ polygonized = geom_a.polygonize(geom_b)
1425
+ assert_equal(2, polygonized.length)
1426
+ assert_equal(
1427
+ 'POLYGON ((100 100, 100 300, 300 300, 300 100, 100 100), (150 150, 250 150, 250 250, 150 250, 150 150))',
1428
+ write(polygonized[0].snap_to_grid(0.1))
1429
+ )
1430
+ assert_equal(
1431
+ 'POLYGON ((150 150, 150 250, 250 250, 250 150, 150 150))',
1432
+ write(polygonized[1].snap_to_grid(0.1))
1433
+ )
1434
+ end
1435
+
1436
+ def test_polygonize_valid
1437
+ skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:polygonize_valid)
1438
+
1439
+ geom_a = read(
1440
+ 'GEOMETRYCOLLECTION(
1441
+ LINESTRING (100 100, 100 300, 300 300, 300 100, 100 100),
1442
+ LINESTRING (150 150, 150 250, 250 250, 250 150, 150 150)
1443
+ )'
1444
+ )
1445
+
1446
+ polygonized = geom_a.polygonize_valid
1447
+ assert_equal(
1448
+ 'POLYGON ((100 100, 100 300, 300 300, 300 100, 100 100), (150 150, 250 150, 250 250, 150 250, 150 150))',
1449
+ write(polygonized.snap_to_grid(0.1))
1257
1450
  )
1258
1451
  end
1259
1452
 
@@ -1288,7 +1481,8 @@ class GeometryTests < Minitest::Test
1288
1481
  LINESTRING(185 221, 292 281, 180 316),
1289
1482
  LINESTRING(189 98, 83 187, 185 221),
1290
1483
  LINESTRING(189 98, 325 168, 185 221)
1291
- )')
1484
+ )'
1485
+ )
1292
1486
 
1293
1487
  polygonized = geom_a.polygonize_full
1294
1488
 
@@ -1348,6 +1542,29 @@ class GeometryTests < Minitest::Test
1348
1542
  end
1349
1543
  end
1350
1544
 
1545
+ def test_build_area
1546
+ skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:build_area)
1547
+
1548
+ geom = read('GEOMETRYCOLLECTION (LINESTRING(0 0, 0 1, 1 1), LINESTRING (1 1, 1 0, 0 0))')
1549
+
1550
+ assert_equal('POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))', write(geom.build_area))
1551
+ end
1552
+
1553
+ def test_make_valid
1554
+ skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:make_valid)
1555
+
1556
+ geom = read('POLYGON((0 0, 1 1, 0 1, 1 0, 0 0))')
1557
+
1558
+ assert_equal(
1559
+ if Geos::GEOS_VERSION > '3.9.0'
1560
+ 'MULTIPOLYGON (((1 0, 0 0, 0.5 0.5, 1 0)), ((1 1, 0.5 0.5, 0 1, 1 1)))'
1561
+ else
1562
+ 'MULTIPOLYGON (((0 0, 0.5 0.5, 1 0, 0 0)), ((0.5 0.5, 0 1, 1 1, 0.5 0.5)))'
1563
+ end,
1564
+ write(geom.make_valid)
1565
+ )
1566
+ end
1567
+
1351
1568
  def test_shared_paths
1352
1569
  skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:shared_paths)
1353
1570
 
@@ -1403,7 +1620,7 @@ class GeometryTests < Minitest::Test
1403
1620
  geom = read('LINESTRING(0 0, 10 10))')
1404
1621
  assert_kind_of(Enumerable, geom.each)
1405
1622
  assert_kind_of(Enumerable, geom.to_enum)
1406
- assert_equal(geom, geom.each {})
1623
+ assert_equal(geom, geom.each(&EMPTY_BLOCK))
1407
1624
  end
1408
1625
 
1409
1626
  def test_normalize
@@ -1438,9 +1655,9 @@ class GeometryTests < Minitest::Test
1438
1655
  geom_a = read('POINT(1.0 1.0)')
1439
1656
  geom_b = read('POINT(2.0 2.0)')
1440
1657
 
1441
- assert(geom_a == geom_a, "Expected geoms to be equal using ==")
1442
- refute(geom_a == geom_b, "Expected geoms to not be equal using ==")
1443
- refute(geom_a == "test", "Expected geoms to not be equal using ==")
1658
+ assert(geom_a == geom_a, 'Expected geoms to be equal using ==')
1659
+ refute(geom_a == geom_b, 'Expected geoms to not be equal using ==')
1660
+ refute(geom_a == 'test', 'Expected geoms to not be equal using ==')
1444
1661
  end
1445
1662
 
1446
1663
  def test_eql_exact
@@ -1517,7 +1734,7 @@ class GeometryTests < Minitest::Test
1517
1734
  assert_raises(Geos::MixedSRIDsError) do
1518
1735
  Geos.srid_copy_policy = :strict
1519
1736
  geom_c = geom.intersection(geom_b)
1520
- assert_equal(231231, geom_c.srid)
1737
+ assert_equal(231_231, geom_c.srid)
1521
1738
  end
1522
1739
  ensure
1523
1740
  Geos.srid_copy_policy = :default
@@ -1573,23 +1790,25 @@ class GeometryTests < Minitest::Test
1573
1790
 
1574
1791
  # empty polygon
1575
1792
  tester['GEOMETRYCOLLECTION EMPTY', 'POLYGON EMPTY', 0]
1576
- tester['MULTILINESTRING EMPTY', 'POLYGON EMPTY', 0, { :only_edges => true }]
1793
+ tester['MULTILINESTRING EMPTY', 'POLYGON EMPTY', 0, only_edges: true]
1577
1794
 
1578
1795
  # single point
1579
1796
  tester['GEOMETRYCOLLECTION EMPTY', 'POINT (0 0)', 0]
1580
- tester['MULTILINESTRING EMPTY', 'POINT (0 0)', 0, { :only_edges => true }]
1797
+ tester['MULTILINESTRING EMPTY', 'POINT (0 0)', 0, only_edges: true]
1581
1798
 
1582
1799
  # three collinear points
1583
1800
  tester['GEOMETRYCOLLECTION EMPTY', 'MULTIPOINT(0 0, 5 0, 10 0)', 0]
1584
- tester['MULTILINESTRING ((5 0, 10 0), (0 0, 5 0))', 'MULTIPOINT(0 0, 5 0, 10 0)', 0, { :only_edges => true }]
1801
+ tester['MULTILINESTRING ((5 0, 10 0), (0 0, 5 0))', 'MULTIPOINT(0 0, 5 0, 10 0)', 0, only_edges: true]
1585
1802
 
1586
1803
  # three points
1587
1804
  tester['GEOMETRYCOLLECTION (POLYGON ((0 0, 10 10, 5 0, 0 0)))', 'MULTIPOINT(0 0, 5 0, 10 10)', 0]
1588
- tester['MULTILINESTRING ((5 0, 10 10), (0 0, 10 10), (0 0, 5 0))', 'MULTIPOINT(0 0, 5 0, 10 10)', 0, { :only_edges => true }]
1805
+ tester['MULTILINESTRING ((5 0, 10 10), (0 0, 10 10), (0 0, 5 0))', 'MULTIPOINT(0 0, 5 0, 10 10)', 0, only_edges: true]
1589
1806
 
1590
1807
  # polygon with a hole
1591
1808
  tester[
1592
- 'GEOMETRYCOLLECTION (POLYGON ((8 2, 10 10, 8.5 1, 8 2)), POLYGON ((7 8, 10 10, 8 2, 7 8)), POLYGON ((3 8, 10 10, 7 8, 3 8)), POLYGON ((2 2, 8 2, 8.5 1, 2 2)), POLYGON ((2 2, 7 8, 8 2, 2 2)), POLYGON ((2 2, 3 8, 7 8, 2 2)), POLYGON ((0.5 9, 10 10, 3 8, 0.5 9)), POLYGON ((0.5 9, 3 8, 2 2, 0.5 9)), POLYGON ((0 0, 2 2, 8.5 1, 0 0)), POLYGON ((0 0, 0.5 9, 2 2, 0 0)))',
1809
+ 'GEOMETRYCOLLECTION (POLYGON ((8 2, 10 10, 8.5 1, 8 2)), POLYGON ((7 8, 10 10, 8 2, 7 8)), POLYGON ((3 8, 10 10, 7 8, 3 8)), ' \
1810
+ 'POLYGON ((2 2, 8 2, 8.5 1, 2 2)), POLYGON ((2 2, 7 8, 8 2, 2 2)), POLYGON ((2 2, 3 8, 7 8, 2 2)), POLYGON ((0.5 9, 10 10, 3 8, 0.5 9)), ' \
1811
+ 'POLYGON ((0.5 9, 3 8, 2 2, 0.5 9)), POLYGON ((0 0, 2 2, 8.5 1, 0 0)), POLYGON ((0 0, 0.5 9, 2 2, 0 0)))',
1593
1812
  'POLYGON((0 0, 8.5 1, 10 10, 0.5 9, 0 0),(2 2, 3 8, 7 8, 8 2, 2 2)))',
1594
1813
  0
1595
1814
  ]
@@ -1597,16 +1816,15 @@ class GeometryTests < Minitest::Test
1597
1816
  tester[
1598
1817
  'MULTILINESTRING ((8.5 1, 10 10), (8 2, 10 10), (8 2, 8.5 1), (7 8, 10 10), (7 8, 8 2), (3 8, 10 10), (3 8, 7 8), (2 2, 8.5 1), (2 2, 8 2), (2 2, 7 8), (2 2, 3 8), (0.5 9, 10 10), (0.5 9, 3 8), (0.5 9, 2 2), (0 0, 8.5 1), (0 0, 2 2), (0 0, 0.5 9))',
1599
1818
  'POLYGON((0 0, 8.5 1, 10 10, 0.5 9, 0 0),(2 2, 3 8, 7 8, 8 2, 2 2)))',
1600
- 0, {
1601
- :only_edges => true
1602
- }
1819
+ 0,
1820
+ only_edges: true
1603
1821
  ]
1604
1822
 
1605
1823
  # four points with a tolerance making one collapse
1606
- tester['MULTILINESTRING ((10 0, 10 10), (0 0, 10 10), (0 0, 10 0))', 'MULTIPOINT(0 0, 10 0, 10 10, 11 10)', 2.0, { :only_edges => true }]
1824
+ tester['MULTILINESTRING ((10 0, 10 10), (0 0, 10 10), (0 0, 10 0))', 'MULTIPOINT(0 0, 10 0, 10 10, 11 10)', 2.0, only_edges: true]
1607
1825
 
1608
1826
  # tolerance as an option
1609
- tester['MULTILINESTRING ((10 0, 10 10), (0 0, 10 10), (0 0, 10 0))', 'MULTIPOINT(0 0, 10 0, 10 10, 11 10)', { :tolerance => 2.0, :only_edges => true }]
1827
+ tester['MULTILINESTRING ((10 0, 10 10), (0 0, 10 10), (0 0, 10 0))', 'MULTIPOINT(0 0, 10 0, 10 10, 11 10)', tolerance: 2.0, only_edges: true]
1610
1828
  end
1611
1829
 
1612
1830
  def test_voronoi_diagram
@@ -1623,18 +1841,33 @@ class GeometryTests < Minitest::Test
1623
1841
 
1624
1842
  geom = 'MULTIPOINT(0 0, 100 0, 100 100, 0 100)'
1625
1843
 
1626
- tester['GEOMETRYCOLLECTION (POLYGON ((50 200, 200 200, 200 50, 50 50, 50 200)), POLYGON ((-100 50, -100 200, 50 200, 50 50, -100 50)), POLYGON ((50 -100, -100 -100, -100 50, 50 50, 50 -100)), POLYGON ((200 50, 200 -100, 50 -100, 50 50, 200 50)))', geom]
1844
+ tester[
1845
+ if Geos::GEOS_VERSION > '3.9.0'
1846
+ 'GEOMETRYCOLLECTION (POLYGON ((200 200, 200 50, 50 50, 50 200, 200 200)), POLYGON ((-100 200, 50 200, 50 50, -100 50, -100 200)), POLYGON ((-100 -100, -100 50, 50 50, 50 -100, -100 -100)), POLYGON ((200 -100, 50 -100, 50 50, 200 50, 200 -100)))'
1847
+ else
1848
+ 'GEOMETRYCOLLECTION (POLYGON ((50 200, 200 200, 200 50, 50 50, 50 200)), POLYGON ((-100 50, -100 200, 50 200, 50 50, -100 50)), POLYGON ((50 -100, -100 -100, -100 50, 50 50, 50 -100)), POLYGON ((200 50, 200 -100, 50 -100, 50 50, 200 50)))'
1849
+ end,
1850
+ geom
1851
+ ]
1627
1852
 
1628
- tester['MULTILINESTRING ((50 50, 50 200), (200 50, 50 50), (50 50, -100 50), (50 50, 50 -100))', geom, { :tolerance => 0, :only_edges => true }]
1853
+ tester['MULTILINESTRING ((50 50, 50 200), (200 50, 50 50), (50 50, -100 50), (50 50, 50 -100))', geom, tolerance: 0, only_edges: true]
1629
1854
 
1630
- tester['MULTILINESTRING ((50 50, 50 1100), (1100 50, 50 50), (50 50, -1000 50), (50 50, 50 -1000))', geom, {
1631
- :only_edges => true,
1632
- :envelope => read(geom).buffer(1000)
1633
- }]
1855
+ tester['MULTILINESTRING ((50 50, 50 1100), (1100 50, 50 50), (50 50, -1000 50), (50 50, 50 -1000))', geom,
1856
+ only_edges: true,
1857
+ envelope: read(geom).buffer(1000)
1858
+ ]
1634
1859
 
1635
1860
  # Allows a tolerance for the first argument
1636
1861
  @writer.rounding_precision = 3
1637
- tester['GEOMETRYCOLLECTION (POLYGON ((290 252, 290 140, 185 140, 185 215, 188 235, 290 252)), POLYGON ((80 215, 80 340, 101 340, 188 235, 185 215, 80 215)), POLYGON ((185 140, 80 140, 80 215, 185 215, 185 140)), POLYGON ((101 340, 290 340, 290 252, 188 235, 101 340)))', "MULTIPOINT ((150 210), (210 270), (150 220), (220 210), (215 269))", 10]
1862
+ tester[
1863
+ if Geos::GEOS_VERSION > '3.9.0'
1864
+ 'GEOMETRYCOLLECTION (POLYGON ((290 140, 185 140, 185 215, 188 235, 290 252, 290 140)), POLYGON ((80 340, 101 340, 188 235, 185 215, 80 215, 80 340)), POLYGON ((80 140, 80 215, 185 215, 185 140, 80 140)), POLYGON ((290 340, 290 252, 188 235, 101 340, 290 340)))'
1865
+ else
1866
+ 'GEOMETRYCOLLECTION (POLYGON ((290 252, 290 140, 185 140, 185 215, 188 235, 290 252)), POLYGON ((80 215, 80 340, 101 340, 188 235, 185 215, 80 215)), POLYGON ((185 140, 80 140, 80 215, 185 215, 185 140)), POLYGON ((101 340, 290 340, 290 252, 188 235, 101 340)))'
1867
+ end,
1868
+ 'MULTIPOINT ((150 210), (210 270), (150 220), (220 210), (215 269))',
1869
+ 10
1870
+ ]
1638
1871
  end
1639
1872
 
1640
1873
  def test_precision
@@ -1659,7 +1892,7 @@ class GeometryTests < Minitest::Test
1659
1892
  geom_with_precision = geom.with_precision(5.0)
1660
1893
  assert_equal('LINESTRING EMPTY', write(geom_with_precision))
1661
1894
 
1662
- geom_with_precision = geom.with_precision(5.0, :keep_collapsed => true)
1895
+ geom_with_precision = geom.with_precision(5.0, keep_collapsed: true)
1663
1896
  assert_equal('LINESTRING (0 0, 0 0)', write(geom_with_precision))
1664
1897
  end
1665
1898
 
@@ -1707,11 +1940,37 @@ class GeometryTests < Minitest::Test
1707
1940
  tester['LINESTRING (200 200, 200 100)', 'POLYGON ((100 100, 300 100, 200 200, 100 100))']
1708
1941
  tester[
1709
1942
  'LINESTRING (-112.712119 33.575919, -112.712127 33.575885)',
1710
- '0106000000010000000103000000010000001a00000035d42824992d5cc01b834e081dca404073b9c150872d5cc03465a71fd4c940400ec00644882d5cc03b8a73d4d1c94040376dc669882d5cc0bf9cd9aed0c940401363997e892d5cc002f4fbfecdc94040ca4e3fa88b2d5cc0a487a1d5c9c940408f1ce90c8c2d5cc0698995d1c8c94040fab836548c2d5cc0bd175fb4c7c940409f1f46088f2d5cc0962023a0c2c940407b15191d902d5cc068041bd7bfc940400397c79a912d5cc0287d21e4bcc940403201bf46922d5cc065e3c116bbc940409d9d0c8e922d5cc0060fd3beb9c940400ef7915b932d5cc09012bbb6b7c940404fe61f7d932d5cc0e4a08499b6c94040fc71fbe5932d5cc0ea9106b7b5c94040eaec6470942d5cc0c2323674b3c94040601dc70f952d5cc043588d25acc94040aea06989952d5cc03ecf9f36aac94040307f85cc952d5cc0e5eb32fca7c94040dd0a6135962d5cc01b615111a7c9404048a7ae7c962d5cc00a2aaa7ea5c94040f4328ae5962d5cc05eb87361a4c94040c49448a2972d5cc04d81cccea2c940407c80eecb992d5cc06745d4449fc9404035d42824992d5cc01b834e081dca4040'
1943
+ '0106000000010000000103000000010000001a00000035d42824992d5cc01b834e081dca404073b9c150872d5cc03465a71fd4c940400ec00644882d5cc03b8a' \
1944
+ '73d4d1c94040376dc669882d5cc0bf9cd9aed0c940401363997e892d5cc002f4fbfecdc94040ca4e3fa88b2d5cc0a487a1d5c9c940408f1ce90c8c2d5cc06989' \
1945
+ '95d1c8c94040fab836548c2d5cc0bd175fb4c7c940409f1f46088f2d5cc0962023a0c2c940407b15191d902d5cc068041bd7bfc940400397c79a912d5cc0287d' \
1946
+ '21e4bcc940403201bf46922d5cc065e3c116bbc940409d9d0c8e922d5cc0060fd3beb9c940400ef7915b932d5cc09012bbb6b7c940404fe61f7d932d5cc0e4a0' \
1947
+ '8499b6c94040fc71fbe5932d5cc0ea9106b7b5c94040eaec6470942d5cc0c2323674b3c94040601dc70f952d5cc043588d25acc94040aea06989952d5cc03ecf' \
1948
+ '9f36aac94040307f85cc952d5cc0e5eb32fca7c94040dd0a6135962d5cc01b615111a7c9404048a7ae7c962d5cc00a2aaa7ea5c94040f4328ae5962d5cc05eb8' \
1949
+ '7361a4c94040c49448a2972d5cc04d81cccea2c940407c80eecb992d5cc06745d4449fc9404035d42824992d5cc01b834e081dca4040'
1711
1950
  ]
1712
1951
  tester['LINESTRING EMPTY', 'POLYGON EMPTY']
1713
1952
  end
1714
1953
 
1954
+ def test_maximum_inscribed_circle
1955
+ skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:maximum_inscribed_circle)
1956
+
1957
+ geom = read('POLYGON ((100 200, 200 200, 200 100, 100 100, 100 200))')
1958
+ output = geom.maximum_inscribed_circle(0.001)
1959
+ assert_equal('LINESTRING (150 150, 150 200)', write(output))
1960
+ end
1961
+
1962
+ def test_largest_empty_circle
1963
+ skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:largest_empty_circle)
1964
+
1965
+ geom = read('MULTIPOINT ((100 100), (100 200), (200 200), (200 100))')
1966
+ output = geom.largest_empty_circle(0.001)
1967
+ assert_equal('LINESTRING (150 150, 100 100)', write(output))
1968
+
1969
+ geom = read('MULTIPOINT ((100 100), (100 200), (200 200), (200 100))')
1970
+ output = geom.largest_empty_circle(0.001, boundary: read('MULTIPOINT ((100 100), (100 200), (200 200), (200 100))'))
1971
+ assert_equal('LINESTRING (100 100, 100 100)', write(output))
1972
+ end
1973
+
1715
1974
  def test_minimum_width
1716
1975
  skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:minimum_width)
1717
1976
 
@@ -1723,4 +1982,90 @@ class GeometryTests < Minitest::Test
1723
1982
  output = geom.minimum_width
1724
1983
  assert_equal('LINESTRING (5 5, 0 10)', write(output))
1725
1984
  end
1985
+
1986
+ def test_dump_points
1987
+ geom = read('GEOMETRYCOLLECTION(
1988
+ MULTILINESTRING((0 0, 10 10, 20 20), (100 100, 200 200, 300 300)),
1989
+
1990
+ POINT(10 10),
1991
+
1992
+ POLYGON((0 0, 5 0, 5 5, 0 5, 0 0), (1 1, 4 1, 4 4, 1 4, 1 1))
1993
+ )')
1994
+
1995
+ assert_equal([
1996
+ [
1997
+ [
1998
+ Geos.create_point(0, 0),
1999
+ Geos.create_point(10, 10),
2000
+ Geos.create_point(20, 20)
2001
+ ],
2002
+
2003
+ [
2004
+ Geos.create_point(100, 100),
2005
+ Geos.create_point(200, 200),
2006
+ Geos.create_point(300, 300)
2007
+ ]
2008
+ ],
2009
+
2010
+ [
2011
+ Geos.create_point(10, 10)
2012
+ ],
2013
+
2014
+ [
2015
+ [
2016
+ Geos.create_point(0, 0),
2017
+ Geos.create_point(5, 0),
2018
+ Geos.create_point(5, 5),
2019
+ Geos.create_point(0, 5),
2020
+ Geos.create_point(0, 0)
2021
+ ],
2022
+
2023
+ [
2024
+ Geos.create_point(1, 1),
2025
+ Geos.create_point(4, 1),
2026
+ Geos.create_point(4, 4),
2027
+ Geos.create_point(1, 4),
2028
+ Geos.create_point(1, 1)
2029
+ ]
2030
+ ]
2031
+ ], geom.dump_points)
2032
+ end
2033
+
2034
+ def test_reverse
2035
+ skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:reverse)
2036
+
2037
+ simple_tester(:reverse, 'POINT (3 5)', 'POINT (3 5)')
2038
+ simple_tester(:reverse, 'MULTIPOINT (100 100, 10 100, 30 100)', 'MULTIPOINT (100 100, 10 100, 30 100)')
2039
+ simple_tester(:reverse, 'LINESTRING (200 200, 200 100)', 'LINESTRING (200 100, 200 200)')
2040
+
2041
+ if Geos::GEOS_VERSION >= '3.8.1'
2042
+ simple_tester(:reverse, 'MULTILINESTRING ((3 3, 4 4), (1 1, 2 2))', 'MULTILINESTRING ((4 4, 3 3), (2 2, 1 1))')
2043
+ else
2044
+ simple_tester(:reverse, 'MULTILINESTRING ((1 1, 2 2), (3 3, 4 4))', 'MULTILINESTRING ((4 4, 3 3), (2 2, 1 1))')
2045
+ end
2046
+
2047
+ simple_tester(:reverse, 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1))', 'POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))')
2048
+ simple_tester(:reverse, 'MULTIPOLYGON (((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1)), ((100 100, 100 200, 200 200, 100 100)))', 'MULTIPOLYGON (((0 0, 0 10, 10 10, 10 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1)), ((100 100, 200 200, 100 200, 100 100)))')
2049
+ simple_tester(:reverse, 'GEOMETRYCOLLECTION (LINESTRING (1 1, 2 2), GEOMETRYCOLLECTION (LINESTRING (3 5, 2 9)))', 'GEOMETRYCOLLECTION (LINESTRING (2 2, 1 1), GEOMETRYCOLLECTION(LINESTRING (2 9, 3 5)))')
2050
+ simple_tester(:reverse, 'POINT EMPTY', 'POINT EMPTY')
2051
+ simple_tester(:reverse, 'LINESTRING EMPTY', 'LINESTRING EMPTY')
2052
+ simple_tester(:reverse, 'LINEARRING EMPTY', 'LINEARRING EMPTY')
2053
+ simple_tester(:reverse, 'POLYGON EMPTY', 'POLYGON EMPTY')
2054
+ simple_tester(:reverse, 'MULTIPOINT EMPTY', 'MULTIPOINT EMPTY')
2055
+ simple_tester(:reverse, 'MULTILINESTRING EMPTY', 'MULTILINESTRING EMPTY')
2056
+ simple_tester(:reverse, 'MULTIPOLYGON EMPTY', 'MULTIPOLYGON EMPTY')
2057
+ simple_tester(:reverse, 'GEOMETRYCOLLECTION EMPTY', 'GEOMETRYCOLLECTION EMPTY')
2058
+ end
2059
+
2060
+ def test_frechet_distance
2061
+ skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:frechet_distance)
2062
+
2063
+ assert_in_delta(read('LINESTRING (0 0, 100 0)').frechet_distance(read('LINESTRING (0 0, 50 50, 100 0)')), 70.7106781186548, TOLERANCE)
2064
+ end
2065
+
2066
+ def test_frechet_distance_with_densify
2067
+ skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:frechet_distance)
2068
+
2069
+ assert_in_delta(read('LINESTRING (0 0, 100 0)').frechet_distance(read('LINESTRING (0 0, 50 50, 100 0)'), 0.5), 50.0, TOLERANCE)
2070
+ end
1726
2071
  end