ffi-geos 1.2.1 → 1.2.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.
Files changed (49) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +20 -0
  3. data/.travis.yml +7 -3
  4. data/Gemfile +1 -1
  5. data/Guardfile +4 -5
  6. data/ffi-geos.gemspec +1 -1
  7. data/lib/ffi-geos.rb +212 -196
  8. data/lib/ffi-geos/buffer_params.rb +9 -20
  9. data/lib/ffi-geos/coordinate_sequence.rb +342 -58
  10. data/lib/ffi-geos/geometry.rb +167 -178
  11. data/lib/ffi-geos/geometry_collection.rb +60 -12
  12. data/lib/ffi-geos/interrupt.rb +2 -4
  13. data/lib/ffi-geos/line_string.rb +146 -37
  14. data/lib/ffi-geos/linear_ring.rb +2 -3
  15. data/lib/ffi-geos/multi_line_string.rb +1 -2
  16. data/lib/ffi-geos/multi_point.rb +0 -1
  17. data/lib/ffi-geos/multi_polygon.rb +0 -1
  18. data/lib/ffi-geos/point.rb +69 -14
  19. data/lib/ffi-geos/polygon.rb +110 -21
  20. data/lib/ffi-geos/prepared_geometry.rb +11 -12
  21. data/lib/ffi-geos/strtree.rb +41 -52
  22. data/lib/ffi-geos/tools.rb +15 -18
  23. data/lib/ffi-geos/utils.rb +27 -44
  24. data/lib/ffi-geos/version.rb +1 -3
  25. data/lib/ffi-geos/wkb_reader.rb +4 -9
  26. data/lib/ffi-geos/wkb_writer.rb +14 -18
  27. data/lib/ffi-geos/wkt_reader.rb +2 -5
  28. data/lib/ffi-geos/wkt_writer.rb +17 -22
  29. data/test/.rubocop.yml +36 -0
  30. data/test/coordinate_sequence_tests.rb +263 -14
  31. data/test/geometry_collection_tests.rb +412 -1
  32. data/test/geometry_tests.rb +156 -86
  33. data/test/interrupt_tests.rb +2 -4
  34. data/test/line_string_tests.rb +212 -23
  35. data/test/linear_ring_tests.rb +1 -2
  36. data/test/misc_tests.rb +28 -29
  37. data/test/multi_line_string_tests.rb +0 -1
  38. data/test/point_tests.rb +158 -1
  39. data/test/polygon_tests.rb +284 -1
  40. data/test/prepared_geometry_tests.rb +1 -3
  41. data/test/strtree_tests.rb +9 -10
  42. data/test/test_helper.rb +49 -18
  43. data/test/tools_tests.rb +1 -3
  44. data/test/utils_tests.rb +22 -22
  45. data/test/wkb_reader_tests.rb +10 -9
  46. data/test/wkb_writer_tests.rb +5 -13
  47. data/test/wkt_reader_tests.rb +1 -2
  48. data/test/wkt_writer_tests.rb +9 -14
  49. metadata +6 -3
@@ -1,4 +1,3 @@
1
- # encoding: UTF-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require 'test_helper'
@@ -131,8 +130,8 @@ class CoordinateSequenceTests < Minitest::Test
131
130
  end
132
131
 
133
132
  def test_to_point
134
- cs = Geos::CoordinateSequence.new([5,7])
135
- assert_equal('POINT (5 7)', write(cs.to_point, :trim => true))
133
+ cs = Geos::CoordinateSequence.new([ 5, 7 ])
134
+ assert_equal('POINT (5 7)', write(cs.to_point, trim: true))
136
135
  end
137
136
 
138
137
  def test_to_to_linear_ring
@@ -144,21 +143,21 @@ class CoordinateSequenceTests < Minitest::Test
144
143
  [ 0, 0 ]
145
144
  ])
146
145
 
147
- assert_equal('LINEARRING (0 0, 0 5, 5 5, 5 0, 0 0)', write(cs.to_linear_ring, :trim => true))
146
+ assert_equal('LINEARRING (0 0, 0 5, 5 5, 5 0, 0 0)', write(cs.to_linear_ring, trim: true))
148
147
  end
149
148
 
150
149
  def test_empty
151
150
  cs = Geos::CoordinateSequence.new
152
151
  assert_geom_empty(cs)
153
152
 
154
- cs = Geos::CoordinateSequence.new([4,1])
153
+ cs = Geos::CoordinateSequence.new([ 4, 1 ])
155
154
  refute_geom_empty(cs)
156
155
  end
157
156
 
158
157
  def test_to_empty_linear_ring
159
158
  cs = Geos::CoordinateSequence.new
160
159
 
161
- assert_equal('LINEARRING EMPTY', write(cs.to_linear_ring, :trim => true))
160
+ assert_equal('LINEARRING EMPTY', write(cs.to_linear_ring, trim: true))
162
161
  end
163
162
 
164
163
  def test_to_line_string
@@ -169,13 +168,13 @@ class CoordinateSequenceTests < Minitest::Test
169
168
  [ 5, 0 ]
170
169
  ])
171
170
 
172
- assert_equal('LINESTRING (0 0, 0 5, 5 5, 5 0)', write(cs.to_line_string, :trim => true))
171
+ assert_equal('LINESTRING (0 0, 0 5, 5 5, 5 0)', write(cs.to_line_string, trim: true))
173
172
  end
174
173
 
175
174
  def test_to_empty_line_string
176
175
  cs = Geos::CoordinateSequence.new
177
176
 
178
- assert_equal('LINESTRING EMPTY', write(cs.to_line_string, :trim => true))
177
+ assert_equal('LINESTRING EMPTY', write(cs.to_line_string, trim: true))
179
178
  end
180
179
 
181
180
  def test_to_polygon
@@ -187,21 +186,23 @@ class CoordinateSequenceTests < Minitest::Test
187
186
  [ 0, 0 ]
188
187
  ])
189
188
 
190
- assert_equal('POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))', write(cs.to_polygon, :trim => true))
189
+ assert_equal('POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))', write(cs.to_polygon, trim: true))
191
190
  end
192
191
 
193
192
  def test_to_empty_polygon
194
193
  cs = Geos::CoordinateSequence.new
195
194
 
196
- assert_equal('POLYGON EMPTY', write(cs.to_polygon, :trim => true))
195
+ assert_equal('POLYGON EMPTY', write(cs.to_polygon, trim: true))
197
196
  end
198
197
 
199
- def test_to_s
198
+ def test_to_s_2d
200
199
  cs = Geos::CoordinateSequence.new([[1, 2], [10, 11]])
201
- assert_equal("1.0 2.0, 10.0 11.0", cs.to_s)
200
+ assert_equal('1.0 2.0, 10.0 11.0', cs.to_s)
201
+ end
202
202
 
203
+ def test_to_s_3d
203
204
  cs = Geos::CoordinateSequence.new([[1, 2, 3], [10, 11, 12]])
204
- assert_equal("1.0 2.0 3.0, 10.0 11.0 12.0", cs.to_s)
205
+ assert_equal('1.0 2.0 3.0, 10.0 11.0 12.0', cs.to_s)
205
206
  end
206
207
 
207
208
  def test_get_by_proxy
@@ -265,7 +266,7 @@ class CoordinateSequenceTests < Minitest::Test
265
266
  end
266
267
 
267
268
  def test_options_hash
268
- cs = Geos::CoordinateSequence.new(:size => 10, :dimensions => 2)
269
+ cs = Geos::CoordinateSequence.new(size: 10, dimensions: 2)
269
270
 
270
271
  assert_equal(10, cs.size)
271
272
  assert_equal(2, cs.dimensions)
@@ -332,4 +333,252 @@ class CoordinateSequenceTests < Minitest::Test
332
333
  assert_geom_has_z(read('POINT (0 0 0)').coord_seq)
333
334
  refute_geom_has_z(read('POINT (0 0)').coord_seq)
334
335
  end
336
+
337
+ def test_x_max
338
+ cs = Geos::CoordinateSequence.new([ -10, -15 ], [ 0, 5 ], [ 10, 20 ])
339
+ assert_equal(10, cs.x_max)
340
+ end
341
+
342
+ def test_x_min
343
+ cs = Geos::CoordinateSequence.new([ -10, -15 ], [ 0, 5 ], [ 10, 20 ])
344
+ assert_equal(-10, cs.x_min)
345
+ end
346
+
347
+ def test_y_max
348
+ cs = Geos::CoordinateSequence.new([ -10, -15 ], [ 0, 5 ], [ 10, 20 ])
349
+ assert_equal(20, cs.y_max)
350
+ end
351
+
352
+ def test_y_min
353
+ cs = Geos::CoordinateSequence.new([ -10, -15 ], [ 0, 5 ], [ 10, 20 ])
354
+ assert_equal(-15, cs.y_min)
355
+ end
356
+
357
+ def test_z_max
358
+ cs = Geos::CoordinateSequence.new([ -10, -15 ], [ 0, 5 ], [ 10, 20 ])
359
+ assert(cs.z_max.nan?, " Expected NaN")
360
+
361
+ cs = Geos::CoordinateSequence.new([ -10, -15, -20 ], [ 0, 5, 10 ], [ 10, 20, 30 ])
362
+ assert_equal(30, cs.z_max)
363
+ end
364
+
365
+ def test_z_min
366
+ cs = Geos::CoordinateSequence.new([ -10, -15 ], [ 0, 5 ], [ 10, 20 ])
367
+ assert(cs.z_min.nan?, " Expected NaN")
368
+
369
+ cs = Geos::CoordinateSequence.new([ -10, -15, -20 ], [ 0, 5, 10 ], [ 10, 20, 30 ])
370
+ assert_equal(-20, cs.z_min)
371
+ end
372
+
373
+ def test_snap_to_grid_with_size
374
+ expected = [
375
+ [[-10.0, -15.0], [0.0, 5.0], [10.0, 20.0]],
376
+ [[-10.1, -15.1], [0.1, 5.1], [10.1, 20.1]],
377
+ [[-10.12, -15.12], [0.12, 5.12], [10.12, 20.12]],
378
+ [[-10.123, -15.123], [0.123, 5.123], [10.123, 20.123]],
379
+ [[-10.1235, -15.1235], [0.1235, 5.1235], [10.1235, 20.1235]],
380
+ [[-10.12346, -15.12346], [0.12346, 5.12346], [10.12346, 20.12346]],
381
+ [[-10.123457, -15.123457], [0.123457, 5.123457], [10.123457, 20.123457]],
382
+ [[-10.1234568, -15.1234568], [0.1234568, 5.1234568], [10.1234568, 20.1234568]],
383
+ [[-10.12345679, -15.12345679], [0.12345679, 5.12345679], [10.12345679, 20.12345679]]
384
+ ]
385
+
386
+ coordinates = [
387
+ [ -10.123456789, -15.123456789 ],
388
+ [ 0.123456789, 5.123456789 ],
389
+ [ 10.123456789, 20.123456789 ]
390
+ ]
391
+
392
+ 9.times do |i|
393
+ cs = Geos::CoordinateSequence.new(*coordinates)
394
+ cs.snap_to_grid!(10 ** -i)
395
+
396
+ # XXX - Ruby 1.8.7 sometimes sees the the float values as differing
397
+ # slightly, but not enough that it would matter for these tests.
398
+ # Test equality on the inspect Strings instead of the float values.
399
+ assert_equal(expected[i].inspect, cs.to_a.inspect)
400
+
401
+ cs = Geos::CoordinateSequence.new(*coordinates)
402
+ snapped = cs.snap_to_grid(10 ** -i)
403
+ assert_equal(coordinates, cs.to_a)
404
+ assert_equal(expected[i].inspect, snapped.to_a.inspect)
405
+ end
406
+ end
407
+
408
+ def test_snap_to_grid_with_hash
409
+ cs = Geos::CoordinateSequence.new(
410
+ [ 10, 10 ],
411
+ [ 20, 20 ],
412
+ [ 30, 30 ]
413
+ )
414
+ cs.snap_to_grid!(:size_x => 1, :size_y => 1, :offset_x => 12.5, :offset_y => 12.5)
415
+
416
+ assert_equal([
417
+ [ 9.5, 9.5 ],
418
+ [ 20.5, 20.5 ],
419
+ [ 30.5, 30.5 ]
420
+ ], cs.to_a)
421
+ end
422
+
423
+ def test_snap_to_grid_with_geometry_origin
424
+ cs = Geos::CoordinateSequence.new(
425
+ [ 10, 10 ],
426
+ [ 20, 20 ],
427
+ [ 30, 30 ]
428
+ )
429
+ cs.snap_to_grid!(:size => 1, :offset => read('LINESTRING (0 0, 25 25)'))
430
+
431
+ assert_equal([
432
+ [ 9.5, 9.5 ],
433
+ [ 20.5, 20.5 ],
434
+ [ 30.5, 30.5 ]
435
+ ], cs.to_a)
436
+ end
437
+
438
+ def test_snap_to_grid_with_z
439
+ cs = Geos::CoordinateSequence.new(
440
+ [ 10, 10, 10 ],
441
+ [ 20, 20, 20 ],
442
+ [ 30, 30, 30 ]
443
+ )
444
+ cs.snap_to_grid!(
445
+ :size_x => 1,
446
+ :size_y => 1,
447
+ :size_z => 1,
448
+
449
+ :offset_x => 12.5,
450
+ :offset_y => 12.5,
451
+ :offset_z => 12.5
452
+ )
453
+
454
+ assert_equal([
455
+ [ 9.5, 9.5, 9.5 ],
456
+ [ 20.5, 20.5, 20.5 ],
457
+ [ 30.5, 30.5, 30.5 ]
458
+ ], cs.to_a)
459
+ end
460
+
461
+ def test_snap_to_grid_remove_duplicate_points
462
+ coords = [
463
+ [-10.0, 0.0],
464
+ [-10.0, 5.0], [-10.0, 5.0],
465
+ [-10.0, 6.0], [-10.0, 6.0], [-10.0, 6.0],
466
+ [-10.0, 7.0], [-10.0, 7.0], [-10.0, 7.0],
467
+ [-10.0, 8.0], [-10.0, 8.0],
468
+ [-9.0, 8.0], [-9.0, 9.0],
469
+ [-10.0, 0.0]
470
+ ]
471
+
472
+ expected = [
473
+ [-10.0, 0.0],
474
+ [-10.0, 5.0],
475
+ [-10.0, 6.0],
476
+ [-10.0, 7.0],
477
+ [-10.0, 8.0],
478
+ [-9.0, 8.0],
479
+ [-9.0, 9.0],
480
+ [-10.0, 0.0]
481
+ ]
482
+
483
+ cs = Geos::CoordinateSequence.new(coords)
484
+ cs.snap_to_grid!
485
+
486
+ assert_equal(expected, cs.to_a)
487
+
488
+ cs = Geos::CoordinateSequence.new(coords)
489
+ cs2 = cs.snap_to_grid
490
+
491
+ assert_equal(coords, cs.to_a)
492
+ assert_equal(expected, cs2.to_a)
493
+ end
494
+
495
+ undef :affine_tester
496
+ def affine_tester(method, expected, coords, *args)
497
+ cs = Geos::CoordinateSequence.new(coords)
498
+ cs.send("#{method}!", *args)
499
+
500
+ expected.length.times do |i|
501
+ assert_in_delta(expected[i], cs.get_ordinate(0, i), TOLERANCE)
502
+ end
503
+
504
+ cs = Geos::CoordinateSequence.new(coords)
505
+ cs2 = cs.send(method, *args)
506
+
507
+ expected.length.times do |i|
508
+ assert_in_delta(coords[i], cs.get_ordinate(0, i), TOLERANCE)
509
+ assert_in_delta(expected[i], cs2.get_ordinate(0, i), TOLERANCE)
510
+ end
511
+ end
512
+
513
+ def test_rotate
514
+ affine_tester(:rotate, [ 29.0, 11.0 ], [ 1, 1 ], Math::PI / 2, [ 10.0, 20.0 ])
515
+ affine_tester(:rotate, [ -2.0, 0.0 ], [ 1, 1 ], -Math::PI / 2, [ -1.0, 2.0 ])
516
+ affine_tester(:rotate, [ 19.0, 1.0 ], [ 1, 1 ], Math::PI / 2, read('POINT(10 10)'))
517
+ affine_tester(:rotate, [ -0.5, 0.5 ], [ 1, 1 ], Math::PI / 2, read('LINESTRING(0 0, 1 0)'))
518
+ end
519
+
520
+ def test_rotate_x
521
+ affine_tester(:rotate_x, [ 1, -1, -1 ], [ 1, 1, 1 ], Math::PI)
522
+ affine_tester(:rotate_x, [ 1, -1, 1 ], [ 1, 1, 1 ], Math::PI / 2)
523
+ affine_tester(:rotate_x, [ 1, 1, -1 ], [ 1, 1, 1 ], Math::PI + Math::PI / 2)
524
+ affine_tester(:rotate_x, [ 1, 1, 1 ], [ 1, 1, 1 ], Math::PI * 2)
525
+ end
526
+
527
+ def test_rotate_y
528
+ affine_tester(:rotate_y, [ -1, 1, -1 ], [ 1, 1, 1 ], Math::PI)
529
+ affine_tester(:rotate_y, [ 1, 1, -1 ], [ 1, 1, 1 ], Math::PI / 2)
530
+ affine_tester(:rotate_y, [ -1, 1, 1 ], [ 1, 1, 1 ], Math::PI + Math::PI / 2)
531
+ affine_tester(:rotate_y, [ 1, 1, 1 ], [ 1, 1, 1 ], Math::PI * 2)
532
+ end
533
+
534
+ def test_rotate_z
535
+ affine_tester(:rotate_z, [ -1, -1 ], [ 1, 1 ], Math::PI)
536
+ affine_tester(:rotate_z, [ -1, 1 ], [ 1, 1 ], Math::PI / 2)
537
+ affine_tester(:rotate_z, [ 1, -1 ], [ 1, 1 ], Math::PI + Math::PI / 2)
538
+ affine_tester(:rotate_z, [ 1, 1 ], [ 1, 1 ], Math::PI * 2)
539
+ end
540
+
541
+ def test_scale
542
+ affine_tester(:scale, [ 5, 5 ], [ 1, 1 ], 5, 5)
543
+ affine_tester(:scale, [ 3, 2 ], [ 1, 1 ], 3, 2)
544
+ affine_tester(:scale, [ 40, 40, 40 ], [ 10, 20, -5 ], 4, 2, -8)
545
+ end
546
+
547
+ def test_scale_hash
548
+ affine_tester(:scale, [ 5, 5 ], [ 1, 1 ], :x => 5, :y => 5)
549
+ affine_tester(:scale, [ 3, 2 ], [ 1, 1 ], :x => 3, :y => 2)
550
+ affine_tester(:scale, [ 40, 40, 40 ], [ 10, 20, -5 ], :x => 4, :y => 2, :z => -8)
551
+ end
552
+
553
+ def test_trans_scale
554
+ affine_tester(:trans_scale, [ 2, 2 ], [ 1, 1 ], 1, 1, 1, 1)
555
+ affine_tester(:trans_scale, [ 3, 3 ], [ 2, 2 ], 1, 1, 1, 1)
556
+ affine_tester(:trans_scale, [ 0, 0 ], [ 1, 1 ], -1, -1, -1, -1)
557
+ affine_tester(:trans_scale, [ 1, 2 ], [ 1, 1 ], 0, 1, 1, 1)
558
+ affine_tester(:trans_scale, [ 2, 1 ], [ 1, 1 ], 1, 0, 1, 1)
559
+ affine_tester(:trans_scale, [ 0, 2 ], [ 1, 1 ], 1, 1, 0, 1)
560
+ affine_tester(:trans_scale, [ 2, 0 ], [ 1, 1 ], 1, 1, 1, 0)
561
+ affine_tester(:trans_scale, [ 3, 2 ], [ 1, 1 ], 2, 1, 1, 1)
562
+ affine_tester(:trans_scale, [ 2, 3 ], [ 1, 1 ], 1, 2, 1, 1)
563
+ affine_tester(:trans_scale, [ 4, 2 ], [ 1, 1 ], 1, 1, 2, 1)
564
+ affine_tester(:trans_scale, [ 2, 4 ], [ 1, 1 ], 1, 1, 1, 2)
565
+ affine_tester(:trans_scale, [ 15, 28 ], [ 1, 1 ], 2, 3, 5, 7)
566
+ affine_tester(:trans_scale, [ 15, 28, 1 ], [ 1, 1, 1 ], 2, 3, 5, 7)
567
+ end
568
+
569
+ def test_trans_scale_hash
570
+ affine_tester(:trans_scale, [ 2, 2 ], [ 1, 1 ], :delta_x => 1, :delta_y => 1, :x_factor => 1, :y_factor => 1)
571
+ affine_tester(:trans_scale, [ 15, 28, 1 ], [ 1, 1, 1 ], :delta_x => 2, :delta_y => 3, :x_factor => 5, :y_factor => 7)
572
+ affine_tester(:trans_scale, [ 3, 1, 1 ], [ 1, 1, 1 ], :delta_x => 2, :z_factor => 2)
573
+ end
574
+
575
+ def test_translate
576
+ affine_tester(:translate, [ 5, 12 ], [ 0, 0 ], 5, 12)
577
+ affine_tester(:translate, [ -3, -7, 3 ], [ 0, 0, 0 ], -3, -7, 3)
578
+ end
579
+
580
+ def test_translate_hash
581
+ affine_tester(:translate, [ 5, 12 ], [ 0, 0 ], :x => 5, :y => 12)
582
+ affine_tester(:translate, [ -3, -7, 3 ], [ 0, 0, 0 ], :x => -3, :y => -7, :z => 3)
583
+ end
335
584
  end
@@ -1,4 +1,3 @@
1
- # encoding: UTF-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require 'test_helper'
@@ -84,4 +83,416 @@ class GeometryCollectionTests < Minitest::Test
84
83
  geom = read('GEOMETRYCOLLECTION (POINT(1 2), LINESTRING(1 2, 3 4))')
85
84
  assert_equal(2, geom.num_geometries)
86
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), 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))'
177
+
178
+ 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))'
179
+
180
+ simple_bang_tester(:snap_to_grid, expected, wkt, 1)
181
+ end
182
+
183
+ def test_snap_to_grid_empty
184
+ assert(read('GEOMETRYCOLLECTION EMPTY').snap_to_grid!.empty?, 'Expected an empty GeometryCollection')
185
+ end
186
+
187
+ def test_snap_to_grid_with_srid
188
+ wkt = 'GEOMETRYCOLLECTION (
189
+ 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),
190
+ 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)),
191
+ POINT (10.12 10.12)
192
+ )'
193
+
194
+ 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))'
195
+
196
+ srid_copy_tester(:snap_to_grid, expected, 0, :zero, wkt, 1)
197
+ srid_copy_tester(:snap_to_grid, expected, 4326, :lenient, wkt, 1)
198
+ srid_copy_tester(:snap_to_grid, expected, 4326, :strict, wkt, 1)
199
+ end
200
+
201
+ def test_snap_to_grid_with_illegal_result
202
+ assert_raises(Geos::InvalidGeometryError) do
203
+ read('GEOMETRYCOLLECTION (POINT (0 2), LINESTRING (0 1, 0 11), POLYGON ((0 1, 0 1, 0 6, 0 6, 0 1)))').
204
+ snap_to_grid(1)
205
+ end
206
+ end
207
+
208
+ def test_rotate
209
+ writer.rounding_precision = 3
210
+
211
+ wkt = 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))'
212
+
213
+ affine_tester(:rotate,
214
+ 'GEOMETRYCOLLECTION (POINT (29 11), LINESTRING (30 10, 20 20), POLYGON ((30 10, 30 15, 25 15, 25 10, 30 10)))',
215
+ wkt,
216
+ Math::PI / 2,
217
+ [ 10.0, 20.0 ]
218
+ )
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
+
227
+ affine_tester(:rotate,
228
+ 'GEOMETRYCOLLECTION (POINT (19 1), LINESTRING (20 0, 10 10), POLYGON ((20 0, 20 5, 15 5, 15 0, 20 0)))',
229
+ wkt,
230
+ Math::PI / 2,
231
+ read('POINT(10 10)')
232
+ )
233
+
234
+ affine_tester(:rotate,
235
+ '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)))',
236
+ wkt,
237
+ Math::PI / 2,
238
+ read('LINESTRING(0 0, 1 0)')
239
+ )
240
+ end
241
+
242
+ def test_rotate_x
243
+ writer.rounding_precision = 3
244
+ writer.output_dimensions = 3
245
+
246
+ 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)))'
247
+
248
+ affine_tester(:rotate_x,
249
+ '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)))',
250
+ wkt,
251
+ Math::PI
252
+ )
253
+
254
+ affine_tester(:rotate_x,
255
+ '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)))',
256
+ wkt,
257
+ Math::PI / 2
258
+ )
259
+
260
+ affine_tester(:rotate_x,
261
+ '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)))',
262
+ wkt,
263
+ Math::PI + Math::PI / 2
264
+ )
265
+
266
+ affine_tester(:rotate_x,
267
+ wkt,
268
+ wkt,
269
+ Math::PI * 2
270
+ )
271
+ end
272
+
273
+ def test_rotate_y
274
+ writer.rounding_precision = 6
275
+ writer.output_dimensions = 3
276
+
277
+ 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)))'
278
+
279
+ affine_tester(:rotate_y,
280
+ '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)))',
281
+ wkt,
282
+ Math::PI
283
+ )
284
+
285
+ affine_tester(:rotate_y,
286
+ '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)))',
287
+ wkt,
288
+ Math::PI / 2
289
+ )
290
+
291
+ affine_tester(:rotate_y,
292
+ '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)))',
293
+ wkt,
294
+ Math::PI + Math::PI / 2
295
+ )
296
+
297
+ affine_tester(:rotate_y,
298
+ wkt,
299
+ wkt,
300
+ Math::PI * 2
301
+ )
302
+ end
303
+
304
+ def test_rotate_z
305
+ writer.rounding_precision = 3
306
+
307
+ wkt = 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))'
308
+
309
+ affine_tester(:rotate_z,
310
+ 'GEOMETRYCOLLECTION (POINT (-1 -1), LINESTRING (0 0, -10 -10), POLYGON ((0 0, -5 0, -5 -5, 0 -5, 0 0)))',
311
+ wkt,
312
+ Math::PI
313
+ )
314
+
315
+ affine_tester(:rotate_z,
316
+ 'GEOMETRYCOLLECTION (POINT (-1 1), LINESTRING (0 0, -10 10), POLYGON ((0 0, 0 5, -5 5, -5 0, 0 0)))',
317
+ wkt,
318
+ Math::PI / 2
319
+ )
320
+
321
+ affine_tester(:rotate_z,
322
+ 'GEOMETRYCOLLECTION (POINT (1 -1), LINESTRING (0 0, 10 -10), POLYGON ((0 0, 0 -5, 5 -5, 5 0, 0 0)))',
323
+ wkt,
324
+ Math::PI + Math::PI / 2
325
+ )
326
+
327
+ affine_tester(:rotate_z,
328
+ wkt,
329
+ wkt,
330
+ Math::PI * 2
331
+ )
332
+ end
333
+
334
+ def test_scale
335
+ affine_tester(:scale,
336
+ 'GEOMETRYCOLLECTION (POINT (5 5), LINESTRING (0 0, 50 50), POLYGON ((0 0, 25 0, 25 25, 0 25, 0 0)))',
337
+ 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))',
338
+ 5,
339
+ 5
340
+ )
341
+
342
+ affine_tester(:scale,
343
+ 'GEOMETRYCOLLECTION (POINT (3 2), LINESTRING (0 0, 30 20), POLYGON ((0 0, 15 0, 15 10, 0 10, 0 0)))',
344
+ 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))',
345
+ 3,
346
+ 2
347
+ )
348
+
349
+ writer.output_dimensions = 3
350
+ affine_tester(:scale,
351
+ '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)))',
352
+ '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)))',
353
+ 4,
354
+ 2,
355
+ -8
356
+ )
357
+ end
358
+
359
+ def test_scale_hash
360
+ affine_tester(:scale,
361
+ 'GEOMETRYCOLLECTION (POINT (5 5), LINESTRING (0 0, 50 50), POLYGON ((0 0, 25 0, 25 25, 0 25, 0 0)))',
362
+ 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))',
363
+ :x => 5,
364
+ :y => 5
365
+ )
366
+
367
+ affine_tester(:scale,
368
+ 'GEOMETRYCOLLECTION (POINT (3 2), LINESTRING (0 0, 30 20), POLYGON ((0 0, 15 0, 15 10, 0 10, 0 0)))',
369
+ 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))',
370
+ :x => 3,
371
+ :y => 2
372
+ )
373
+
374
+ writer.output_dimensions = 3
375
+ affine_tester(:scale,
376
+ '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)))',
377
+ '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)))',
378
+ :x => 4,
379
+ :y => 2,
380
+ :z => -8
381
+ )
382
+ end
383
+
384
+ def test_trans_scale
385
+ affine_tester(:trans_scale,
386
+ 'GEOMETRYCOLLECTION (POINT (3 3), LINESTRING (2 2, 12 12), POLYGON ((2 2, 7 2, 7 7, 2 7, 2 2)))',
387
+ 'GEOMETRYCOLLECTION (POINT (2 2), LINESTRING (1 1, 11 11), POLYGON ((1 1, 6 1, 6 6, 1 6, 1 1)))',
388
+ 1, 1, 1, 1)
389
+
390
+ wkt = 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))'
391
+
392
+ affine_tester(:trans_scale,
393
+ 'GEOMETRYCOLLECTION (POINT (2 2), LINESTRING (1 1, 11 11), POLYGON ((1 1, 6 1, 6 6, 1 6, 1 1)))',
394
+ wkt,
395
+ 1, 1, 1, 1)
396
+
397
+ affine_tester(:trans_scale,
398
+ 'GEOMETRYCOLLECTION (POINT (0 0), LINESTRING (1 1, -9 -9), POLYGON ((1 1, -4 1, -4 -4, 1 -4, 1 1)))',
399
+ wkt,
400
+ -1, -1, -1, -1)
401
+
402
+ affine_tester(:trans_scale,
403
+ 'GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (0 1, 10 11), POLYGON ((0 1, 5 1, 5 6, 0 6, 0 1)))',
404
+ wkt,
405
+ 0, 1, 1, 1)
406
+
407
+ affine_tester(:trans_scale,
408
+ 'GEOMETRYCOLLECTION (POINT (2 1), LINESTRING (1 0, 11 10), POLYGON ((1 0, 6 0, 6 5, 1 5, 1 0)))',
409
+ wkt,
410
+ 1, 0, 1, 1)
411
+
412
+ affine_tester(:trans_scale,
413
+ 'GEOMETRYCOLLECTION (POINT (3 2), LINESTRING (2 1, 12 11), POLYGON ((2 1, 7 1, 7 6, 2 6, 2 1)))',
414
+ wkt,
415
+ 2, 1, 1, 1)
416
+
417
+ affine_tester(:trans_scale,
418
+ 'GEOMETRYCOLLECTION (POINT (2 3), LINESTRING (1 2, 11 12), POLYGON ((1 2, 6 2, 6 7, 1 7, 1 2)))',
419
+ wkt,
420
+ 1, 2, 1, 1)
421
+
422
+ affine_tester(:trans_scale,
423
+ 'GEOMETRYCOLLECTION (POINT (4 2), LINESTRING (2 1, 22 11), POLYGON ((2 1, 12 1, 12 6, 2 6, 2 1)))',
424
+ wkt,
425
+ 1, 1, 2, 1)
426
+
427
+ affine_tester(:trans_scale,
428
+ 'GEOMETRYCOLLECTION (POINT (2 4), LINESTRING (1 2, 11 22), POLYGON ((1 2, 6 2, 6 12, 1 12, 1 2)))',
429
+ wkt,
430
+ 1, 1, 1, 2)
431
+
432
+ affine_tester(:trans_scale,
433
+ 'GEOMETRYCOLLECTION (POINT (15 28), LINESTRING (10 21, 60 91), POLYGON ((10 21, 35 21, 35 56, 10 56, 10 21)))',
434
+ wkt,
435
+ 2, 3, 5, 7)
436
+
437
+ writer.output_dimensions = 3
438
+ affine_tester(:trans_scale,
439
+ '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)))',
440
+ '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)))',
441
+ 2, 3, 5, 7)
442
+ end
443
+
444
+ def test_trans_scale_hash
445
+ affine_tester(:trans_scale,
446
+ 'GEOMETRYCOLLECTION (POINT (2 2), LINESTRING (1 1, 11 11), POLYGON ((1 1, 6 1, 6 6, 1 6, 1 1)))',
447
+ 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))',
448
+ :delta_x => 1, :delta_y => 1, :x_factor => 1, :y_factor => 1)
449
+
450
+ writer.output_dimensions = 3
451
+ affine_tester(:trans_scale,
452
+ '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)))',
453
+ '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)))',
454
+ :delta_x => 2, :delta_y => 3, :x_factor => 5, :y_factor => 7)
455
+
456
+ affine_tester(:trans_scale,
457
+ '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)))',
458
+ '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)))',
459
+ :delta_x => 2, :z_factor => 2)
460
+ end
461
+
462
+
463
+ def test_translate
464
+ affine_tester(:translate,
465
+ 'GEOMETRYCOLLECTION (POINT (6 13), LINESTRING (5 12, 15 22), POLYGON ((5 12, 10 12, 10 17, 5 17, 5 12)))',
466
+ 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))',
467
+ 5,
468
+ 12
469
+ )
470
+
471
+ writer.output_dimensions = 3
472
+ affine_tester(:translate,
473
+ '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)))',
474
+ '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)))',
475
+ -3,
476
+ -7,
477
+ 3
478
+ )
479
+ end
480
+
481
+ def test_translate_hash
482
+ affine_tester(:translate,
483
+ 'GEOMETRYCOLLECTION (POINT (6 13), LINESTRING (5 12, 15 22), POLYGON ((5 12, 10 12, 10 17, 5 17, 5 12)))',
484
+ 'GEOMETRYCOLLECTION (POINT (1 1), LINESTRING (0 0, 10 10), POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0)))',
485
+ :x => 5,
486
+ :y => 12
487
+ )
488
+
489
+ writer.output_dimensions = 3
490
+ affine_tester(:translate,
491
+ '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)))',
492
+ '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)))',
493
+ :x => -3,
494
+ :y => -7,
495
+ :z => 3
496
+ )
497
+ end
87
498
  end