ffi-geos 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -4,10 +4,9 @@ language: ruby
4
4
  dist: trusty
5
5
 
6
6
  rvm:
7
- - 2.7.0
8
- - 2.6.5
9
- - 2.5.7
10
- - 2.4.9
7
+ - '2.7'
8
+ - '2.6'
9
+ - '2.5'
11
10
  - jruby-head
12
11
 
13
12
  addons:
data/FUNDING.yml ADDED
@@ -0,0 +1,2 @@
1
+ github:
2
+ - dark-panda
data/Gemfile CHANGED
@@ -8,8 +8,8 @@ gem 'guard'
8
8
  gem 'guard-minitest'
9
9
  gem 'minitest'
10
10
  gem 'minitest-reporters'
11
- gem 'rake', '~> 10.0'
12
- gem 'rdoc', '~> 3.12'
11
+ gem 'rake'
12
+ gem 'rdoc'
13
13
  gem 'rubocop', require: false
14
14
  gem 'simplecov', '~> 0.17.0', require: false
15
15
 
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010-2020 J Smith <dark.panda@gmail.com>
1
+ Copyright (c) 2010-2021 J Smith <dark.panda@gmail.com>
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person
4
4
  obtaining a copy of this software and associated documentation
data/lib/ffi-geos.rb CHANGED
@@ -50,7 +50,7 @@ module Geos
50
50
 
51
51
  module FFIGeos
52
52
  def self.search_paths
53
- @search_paths ||= begin
53
+ @search_paths ||= \
54
54
  if ENV['GEOS_LIBRARY_PATH']
55
55
  [ENV['GEOS_LIBRARY_PATH']]
56
56
  elsif FFI::Platform::IS_WINDOWS
@@ -58,7 +58,6 @@ module Geos
58
58
  else
59
59
  ['/usr/local/{lib64,lib}', '/opt/local/{lib64,lib}', '/usr/{lib64,lib}', '/usr/lib/{x86_64,i386}-linux-gnu']
60
60
  end
61
- end
62
61
  end
63
62
 
64
63
  def self.find_lib(lib)
@@ -72,10 +71,9 @@ module Geos
72
71
  end
73
72
 
74
73
  def self.geos_library_path
75
- @geos_library_path ||= begin
74
+ @geos_library_path ||= \
76
75
  # On MingW the libraries have version numbers
77
76
  find_lib('{lib,}geos_c{,-?}')
78
- end
79
77
  end
80
78
 
81
79
  # For backwards compatibility with older ffi-geos versions where this
@@ -406,6 +404,11 @@ module Geos
406
404
  :pointer, :pointer, :pointer, :pointer
407
405
  ],
408
406
 
407
+ GEOSIntersectionPrec_r: [
408
+ # *geom, *handle, *geom_a, *geom_b, precision
409
+ :pointer, :pointer, :pointer, :pointer, :double
410
+ ],
411
+
409
412
  GEOSBufferWithParams_r: [
410
413
  # *geom, *handle, *geom, *params, width
411
414
  :pointer, :pointer, :pointer, :pointer, :double
@@ -442,11 +445,21 @@ module Geos
442
445
  :pointer, :pointer, :pointer, :pointer
443
446
  ],
444
447
 
448
+ GEOSDifferencePrec_r: [
449
+ # *geom, *handle, *geom_a, *geom_b, precision
450
+ :pointer, :pointer, :pointer, :pointer, :double
451
+ ],
452
+
445
453
  GEOSSymDifference_r: [
446
454
  # *geom, *handle, *geom_a, *geom_b
447
455
  :pointer, :pointer, :pointer, :pointer
448
456
  ],
449
457
 
458
+ GEOSSymDifferencePrec_r: [
459
+ # *geom, *handle, *geom_a, *geom_b, precision
460
+ :pointer, :pointer, :pointer, :pointer, :double
461
+ ],
462
+
450
463
  GEOSBoundary_r: [
451
464
  # *geom, *handle, *geom
452
465
  :pointer, :pointer, :pointer
@@ -457,6 +470,11 @@ module Geos
457
470
  :pointer, :pointer, :pointer, :pointer
458
471
  ],
459
472
 
473
+ GEOSUnionPrec_r: [
474
+ # *geom, *handle, *geom_a, *geom_b, precision
475
+ :pointer, :pointer, :pointer, :pointer, :double
476
+ ],
477
+
460
478
  GEOSCoverageUnion_r: [
461
479
  # *geom, *handle, *geom
462
480
  :pointer, :pointer, :pointer
@@ -467,6 +485,11 @@ module Geos
467
485
  :pointer, :pointer, :pointer
468
486
  ],
469
487
 
488
+ GEOSUnaryUnionPrec_r: [
489
+ # *geom, *handle, *geom, precision
490
+ :pointer, :pointer, :pointer, :double
491
+ ],
492
+
470
493
  GEOSNode_r: [
471
494
  # *geom, *handle, *geom
472
495
  :pointer, :pointer, :pointer
@@ -798,6 +821,16 @@ module Geos
798
821
  :pointer, :pointer, :pointer
799
822
  ],
800
823
 
824
+ GEOSMaximumInscribedCircle_r: [
825
+ # *geom, *handle, *geom, tolerance
826
+ :pointer, :pointer, :pointer, :double
827
+ ],
828
+
829
+ GEOSLargestEmptyCircle_r: [
830
+ # *geom, *handle, *geom, *geom, tolerance
831
+ :pointer, :pointer, :pointer, :pointer, :double
832
+ ],
833
+
801
834
  GEOSMinimumWidth_r: [
802
835
  # *geom, *handle, *geom
803
836
  :pointer, :pointer, :pointer
@@ -83,9 +83,14 @@ module Geos
83
83
  CoordinateSequence.new(FFIGeos.GEOSGeom_getCoordSeq_r(Geos.current_handle_pointer, ptr), false, self)
84
84
  end
85
85
 
86
- def intersection(geom)
86
+ def intersection(geom, precision: nil)
87
87
  check_geometry(geom)
88
- cast_geometry_ptr(FFIGeos.GEOSIntersection_r(Geos.current_handle_pointer, ptr, geom.ptr), srid_copy: pick_srid_from_geoms(srid, geom.srid))
88
+
89
+ if precision
90
+ cast_geometry_ptr(FFIGeos.GEOSIntersectionPrec_r(Geos.current_handle_pointer, ptr, geom.ptr, precision), srid_copy: pick_srid_from_geoms(srid, geom.srid))
91
+ else
92
+ cast_geometry_ptr(FFIGeos.GEOSIntersection_r(Geos.current_handle_pointer, ptr, geom.ptr), srid_copy: pick_srid_from_geoms(srid, geom.srid))
93
+ end
89
94
  end
90
95
 
91
96
  if FFIGeos.respond_to?(:GEOSBufferWithParams_r)
@@ -139,14 +144,24 @@ module Geos
139
144
  cast_geometry_ptr(FFIGeos.GEOSConvexHull_r(Geos.current_handle_pointer, ptr), srid_copy: srid)
140
145
  end
141
146
 
142
- def difference(geom)
147
+ def difference(geom, precision: nil)
143
148
  check_geometry(geom)
144
- cast_geometry_ptr(FFIGeos.GEOSDifference_r(Geos.current_handle_pointer, ptr, geom.ptr), srid_copy: pick_srid_from_geoms(srid, geom.srid))
149
+
150
+ if precision
151
+ cast_geometry_ptr(FFIGeos.GEOSDifferencePrec_r(Geos.current_handle_pointer, ptr, geom.ptr, precision), srid_copy: pick_srid_from_geoms(srid, geom.srid))
152
+ else
153
+ cast_geometry_ptr(FFIGeos.GEOSDifference_r(Geos.current_handle_pointer, ptr, geom.ptr), srid_copy: pick_srid_from_geoms(srid, geom.srid))
154
+ end
145
155
  end
146
156
 
147
- def sym_difference(geom)
157
+ def sym_difference(geom, precision: nil)
148
158
  check_geometry(geom)
149
- cast_geometry_ptr(FFIGeos.GEOSSymDifference_r(Geos.current_handle_pointer, ptr, geom.ptr), srid_copy: pick_srid_from_geoms(srid, geom.srid))
159
+
160
+ if precision
161
+ cast_geometry_ptr(FFIGeos.GEOSSymDifferencePrec_r(Geos.current_handle_pointer, ptr, geom.ptr, precision), srid_copy: pick_srid_from_geoms(srid, geom.srid))
162
+ else
163
+ cast_geometry_ptr(FFIGeos.GEOSSymDifference_r(Geos.current_handle_pointer, ptr, geom.ptr), srid_copy: pick_srid_from_geoms(srid, geom.srid))
164
+ end
150
165
  end
151
166
  alias symmetric_difference sym_difference
152
167
 
@@ -157,10 +172,15 @@ module Geos
157
172
  # Calling without a geom argument is equivalent to calling unary_union when
158
173
  # using GEOS 3.3+ and is equivalent to calling union_cascaded in older
159
174
  # versions.
160
- def union(geom = nil)
175
+ def union(geom = nil, precision: nil)
161
176
  if geom
162
177
  check_geometry(geom)
163
- cast_geometry_ptr(FFIGeos.GEOSUnion_r(Geos.current_handle_pointer, ptr, geom.ptr), srid_copy: pick_srid_from_geoms(srid, geom.srid))
178
+
179
+ if precision
180
+ cast_geometry_ptr(FFIGeos.GEOSUnionPrec_r(Geos.current_handle_pointer, ptr, geom.ptr, precision), srid_copy: pick_srid_from_geoms(srid, geom.srid))
181
+ else
182
+ cast_geometry_ptr(FFIGeos.GEOSUnion_r(Geos.current_handle_pointer, ptr, geom.ptr), srid_copy: pick_srid_from_geoms(srid, geom.srid))
183
+ end
164
184
  elsif respond_to?(:unary_union)
165
185
  unary_union
166
186
  else
@@ -181,8 +201,12 @@ module Geos
181
201
 
182
202
  if FFIGeos.respond_to?(:GEOSUnaryUnion_r)
183
203
  # Available in GEOS 3.3+
184
- def unary_union
185
- cast_geometry_ptr(FFIGeos.GEOSUnaryUnion_r(Geos.current_handle_pointer, ptr), srid_copy: srid)
204
+ def unary_union(precision = nil)
205
+ if precision
206
+ cast_geometry_ptr(FFIGeos.GEOSUnaryUnionPrec_r(Geos.current_handle_pointer, ptr, precision), srid_copy: srid)
207
+ else
208
+ cast_geometry_ptr(FFIGeos.GEOSUnaryUnion_r(Geos.current_handle_pointer, ptr), srid_copy: srid)
209
+ end
186
210
  end
187
211
  end
188
212
 
@@ -695,6 +719,18 @@ module Geos
695
719
  end
696
720
  end
697
721
 
722
+ if FFIGeos.respond_to?(:GEOSMaximumInscribedCircle_r)
723
+ def maximum_inscribed_circle(precision)
724
+ cast_geometry_ptr(FFIGeos.GEOSMaximumInscribedCircle_r(Geos.current_handle_pointer, ptr, precision))
725
+ end
726
+ end
727
+
728
+ if FFIGeos.respond_to?(:GEOSLargestEmptyCircle_r)
729
+ def largest_empty_circle(precision, boundary: nil)
730
+ cast_geometry_ptr(FFIGeos.GEOSLargestEmptyCircle_r(Geos.current_handle_pointer, ptr, boundary ? boundary.ptr : nil, precision))
731
+ end
732
+ end
733
+
698
734
  if FFIGeos.respond_to?(:GEOSMinimumWidth_r)
699
735
  def minimum_width
700
736
  cast_geometry_ptr(FFIGeos.GEOSMinimumWidth_r(Geos.current_handle_pointer, ptr))
@@ -23,18 +23,19 @@ module Geos
23
23
  geoms_and_objects = nil # forward declaration
24
24
  capacity = 10
25
25
 
26
- if args.first.is_a?(Integer)
27
- capacity = args.first
28
- elsif args.first.is_a?(Array)
29
- geoms_and_objects = if args.first.first.is_a?(Array)
30
- args.first
31
- else
32
- args
33
- end
26
+ case args.first
27
+ when Integer
28
+ capacity = args.first
29
+ when Array
30
+ geoms_and_objects = if args.first.first.is_a?(Array)
31
+ args.first
32
+ else
33
+ args
34
+ end
34
35
 
35
- geoms_and_objects.each do |geom, _obj|
36
- check_geometry(geom)
37
- end
36
+ geoms_and_objects.each do |geom, _obj|
37
+ check_geometry(geom)
38
+ end
38
39
  end
39
40
 
40
41
  raise ArgumentError, 'STRtree capacity must be greater than 0' if capacity <= 0
@@ -97,7 +98,7 @@ module Geos
97
98
  def remove(geom, item)
98
99
  check_geometry(geom)
99
100
 
100
- key = if storage = @storage.detect { |_k, v| v[:item] == item }
101
+ key = if (storage = @storage.detect { |_k, v| v[:item] == item })
101
102
  storage[0]
102
103
  end
103
104
 
@@ -137,16 +138,17 @@ module Geos
137
138
 
138
139
  def query(geom, ret = :item)
139
140
  query_all(geom).collect { |storage|
140
- item = if ret.is_a?(Array)
141
- storage.inject({}) do |memo, k|
142
- memo.tap do
143
- memo[k] = storage[k]
141
+ item = case ret
142
+ when Array
143
+ storage.inject({}) do |memo, k|
144
+ memo.tap do
145
+ memo[k] = storage[k]
146
+ end
144
147
  end
145
- end
146
- elsif ret == :all
147
- storage
148
- else
149
- storage[ret]
148
+ when :all
149
+ storage
150
+ else
151
+ storage[ret]
150
152
  end
151
153
 
152
154
  item.tap do
@@ -164,10 +166,8 @@ module Geos
164
166
  end
165
167
  alias query_geoms query_geometries
166
168
 
167
- def iterate
168
- @storage.each_value do |v|
169
- yield(v)
170
- end
169
+ def iterate(&block)
170
+ @storage.each_value(&block)
171
171
  end
172
172
 
173
173
  if FFIGeos.respond_to?(:GEOSSTRtree_nearest_generic_r)
@@ -30,17 +30,18 @@ module Geos
30
30
  def create_point(*args)
31
31
  options = extract_options!(args)
32
32
 
33
- if args.length == 1
34
- cs = args.first
35
- elsif args.length == 2
36
- cs = CoordinateSequence.new(1, 2)
37
- cs.x[0] = args[0].to_f
38
- cs.y[0] = args[1].to_f
39
- elsif args.length == 3
40
- cs = CoordinateSequence.new(1, 3)
41
- cs.x[0], cs.y[0], cs.z[0] = args.map(&:to_f)
42
- else
43
- raise ArgumentError, "Wrong number of arguments (#{args.length} for 1-3)"
33
+ case args.length
34
+ when 1
35
+ cs = args.first
36
+ when 2
37
+ cs = CoordinateSequence.new(1, 2)
38
+ cs.x[0] = args[0].to_f
39
+ cs.y[0] = args[1].to_f
40
+ when 3
41
+ cs = CoordinateSequence.new(1, 3)
42
+ cs.x[0], cs.y[0], cs.z[0] = args.map(&:to_f)
43
+ else
44
+ raise ArgumentError, "Wrong number of arguments (#{args.length} for 1-3)"
44
45
  end
45
46
 
46
47
  raise ArgumentError, 'IllegalArgumentException: Point coordinate list must contain a single element' if cs.length != 1
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Geos
4
- VERSION = '2.1.0'
4
+ VERSION = '2.2.0'
5
5
  end
@@ -2,10 +2,7 @@
2
2
 
3
3
  module Geos
4
4
  class WktWriter
5
- attr_reader :ptr
6
- attr_reader :old_3d
7
- attr_reader :rounding_precision
8
- attr_reader :trim
5
+ attr_reader :ptr, :old_3d, :rounding_precision, :trim
9
6
 
10
7
  def initialize(options = {})
11
8
  options = {
@@ -284,7 +284,7 @@ class CoordinateSequenceTests < Minitest::Test
284
284
 
285
285
  assert_kind_of(Enumerable, cs.x.each)
286
286
  assert_kind_of(Enumerable, cs.x.to_enum)
287
- assert_equal(cs.x, cs.x.each {})
287
+ assert_equal(cs.x, cs.x.each(&EMPTY_BLOCK))
288
288
  end
289
289
 
290
290
  def test_options_hash
@@ -299,7 +299,7 @@ class CoordinateSequenceTests < Minitest::Test
299
299
 
300
300
  assert_kind_of(Enumerable, cs.each)
301
301
  assert_kind_of(Enumerable, cs.to_enum)
302
- assert_equal(cs, cs.each {})
302
+ assert_equal(cs, cs.each(&EMPTY_BLOCK))
303
303
  end
304
304
 
305
305
  def test_array_like_access
@@ -16,7 +16,7 @@ class GeometryCollectionTests < Minitest::Test
16
16
  geom = read('GEOMETRYCOLLECTION(POINT(0 0))')
17
17
  assert_kind_of(Enumerable, geom.each)
18
18
  assert_kind_of(Enumerable, geom.to_enum)
19
- assert_equal(geom, geom.each {})
19
+ assert_equal(geom, geom.each(&EMPTY_BLOCK))
20
20
  end
21
21
 
22
22
  def test_geometry_collection_array
@@ -173,7 +173,8 @@ class GeometryCollectionTests < Minitest::Test
173
173
  end
174
174
 
175
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))'
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))'
177
178
 
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))'
179
180
 
@@ -13,12 +13,36 @@ class GeometryTests < Minitest::Test
13
13
  def test_intersection
14
14
  comparison_tester(
15
15
  :intersection,
16
- '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,
17
21
  'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))',
18
22
  'POLYGON ((5 5, 15 5, 15 15, 5 15, 5 5))'
19
23
  )
20
24
  end
21
25
 
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
+ )
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
+
22
46
  def test_buffer
23
47
  simple_tester(
24
48
  :buffer,
@@ -182,26 +206,50 @@ class GeometryTests < Minitest::Test
182
206
 
183
207
  comparison_tester(
184
208
  :difference,
185
- '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,
186
214
  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
187
215
  'LINESTRING(5 -10, 5 10)'
188
216
  )
189
217
 
190
218
  comparison_tester(
191
219
  :difference,
192
- '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,
193
225
  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
194
226
  'LINESTRING(10 0, 20 0)'
195
227
  )
196
228
 
197
229
  comparison_tester(
198
230
  :difference,
199
- '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,
200
236
  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
201
237
  'POLYGON((5 -5, 5 5, 15 5, 15 -5, 5 -5))'
202
238
  )
203
239
  end
204
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
+
205
253
  def test_sym_difference
206
254
  %w{ sym_difference symmetric_difference }.each do |method|
207
255
  comparison_tester(
@@ -255,27 +303,51 @@ class GeometryTests < Minitest::Test
255
303
 
256
304
  comparison_tester(
257
305
  method,
258
- '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,
259
311
  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
260
312
  'LINESTRING(5 -10, 5 10)'
261
313
  )
262
314
 
263
315
  comparison_tester(
264
316
  method,
265
- '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,
266
322
  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
267
323
  'LINESTRING(10 0, 20 0)'
268
324
  )
269
325
 
270
326
  comparison_tester(
271
327
  method,
272
- '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,
273
333
  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
274
334
  'POLYGON((5 -5, 5 5, 15 5, 15 -5, 5 -5))'
275
335
  )
276
336
  end
277
337
  end
278
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
+
279
351
  def test_boundary
280
352
  simple_tester(
281
353
  :boundary,
@@ -348,32 +420,59 @@ class GeometryTests < Minitest::Test
348
420
 
349
421
  comparison_tester(
350
422
  :union,
351
- '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,
352
428
  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
353
429
  'LINESTRING(5 -10, 5 10)'
354
430
  )
355
431
 
356
432
  comparison_tester(
357
433
  :union,
358
- '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,
359
439
  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
360
440
  'LINESTRING(10 0, 20 0)'
361
441
  )
362
442
 
363
443
  comparison_tester(
364
444
  :union,
365
- '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,
366
450
  'POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))',
367
451
  'POLYGON((5 -5, 5 5, 15 5, 15 -5, 5 -5))'
368
452
  )
369
453
  end
370
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
+
371
466
  def test_union_cascaded
372
467
  skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:union_cascaded)
373
468
 
374
469
  simple_tester(
375
470
  :union_cascaded,
376
- '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,
377
476
  'MULTIPOLYGON(
378
477
  ((0 0, 1 0, 1 1, 0 1, 0 0)),
379
478
  ((10 10, 10 14, 14 14, 14 10, 10 10),
@@ -388,7 +487,11 @@ class GeometryTests < Minitest::Test
388
487
 
389
488
  simple_tester(
390
489
  :union_cascaded,
391
- 'POLYGON ((0 0, 0 1, 1 1, 2 1, 2 0, 1 0, 0 0))',
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,
392
495
  'MULTIPOLYGON(
393
496
  ((0 0, 0 1, 1 1, 1 0, 0 0)),
394
497
  ((1 0, 1 1, 2 1, 2 0, 1 0))
@@ -401,7 +504,11 @@ class GeometryTests < Minitest::Test
401
504
 
402
505
  simple_tester(
403
506
  :unary_union,
404
- '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,
405
512
  'MULTIPOLYGON(
406
513
  ((0 0, 1 0, 1 1, 0 1, 0 0)),
407
514
  ((10 10, 10 14, 14 14, 14 10, 10 10),
@@ -411,6 +518,22 @@ class GeometryTests < Minitest::Test
411
518
  )
412
519
  end
413
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
+
414
537
  def test_node
415
538
  skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:node)
416
539
 
@@ -424,7 +547,11 @@ class GeometryTests < Minitest::Test
424
547
  def test_union_without_arguments
425
548
  simple_tester(
426
549
  :union,
427
- '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,
428
555
  'MULTIPOLYGON(
429
556
  ((0 0, 1 0, 1 1, 0 1, 0 0)),
430
557
  ((10 10, 10 14, 14 14, 14 10, 10 10),
@@ -1230,7 +1357,11 @@ class GeometryTests < Minitest::Test
1230
1357
  cs = geom_1.nearest_points(geom_2)
1231
1358
  result = cs.to_s if cs
1232
1359
 
1233
- assert_equal(expected, result)
1360
+ if expected.nil?
1361
+ assert_nil(result)
1362
+ else
1363
+ assert_equal(expected, result)
1364
+ end
1234
1365
  }
1235
1366
 
1236
1367
  tester[
@@ -1424,7 +1555,14 @@ class GeometryTests < Minitest::Test
1424
1555
 
1425
1556
  geom = read('POLYGON((0 0, 1 1, 0 1, 1 0, 0 0))')
1426
1557
 
1427
- assert_equal('MULTIPOLYGON (((0 0, 0.5 0.5, 1 0, 0 0)), ((0.5 0.5, 0 1, 1 1, 0.5 0.5)))', write(geom.make_valid))
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
+ )
1428
1566
  end
1429
1567
 
1430
1568
  def test_shared_paths
@@ -1482,7 +1620,7 @@ class GeometryTests < Minitest::Test
1482
1620
  geom = read('LINESTRING(0 0, 10 10))')
1483
1621
  assert_kind_of(Enumerable, geom.each)
1484
1622
  assert_kind_of(Enumerable, geom.to_enum)
1485
- assert_equal(geom, geom.each {})
1623
+ assert_equal(geom, geom.each(&EMPTY_BLOCK))
1486
1624
  end
1487
1625
 
1488
1626
  def test_normalize
@@ -1668,7 +1806,9 @@ class GeometryTests < Minitest::Test
1668
1806
 
1669
1807
  # polygon with a hole
1670
1808
  tester[
1671
- '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)))',
1672
1812
  'POLYGON((0 0, 8.5 1, 10 10, 0.5 9, 0 0),(2 2, 3 8, 7 8, 8 2, 2 2)))',
1673
1813
  0
1674
1814
  ]
@@ -1701,7 +1841,14 @@ class GeometryTests < Minitest::Test
1701
1841
 
1702
1842
  geom = 'MULTIPOINT(0 0, 100 0, 100 100, 0 100)'
1703
1843
 
1704
- 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
+ ]
1705
1852
 
1706
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]
1707
1854
 
@@ -1712,7 +1859,15 @@ class GeometryTests < Minitest::Test
1712
1859
 
1713
1860
  # Allows a tolerance for the first argument
1714
1861
  @writer.rounding_precision = 3
1715
- 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
+ ]
1716
1871
  end
1717
1872
 
1718
1873
  def test_precision
@@ -1785,11 +1940,37 @@ class GeometryTests < Minitest::Test
1785
1940
  tester['LINESTRING (200 200, 200 100)', 'POLYGON ((100 100, 300 100, 200 200, 100 100))']
1786
1941
  tester[
1787
1942
  'LINESTRING (-112.712119 33.575919, -112.712127 33.575885)',
1788
- '0106000000010000000103000000010000001a00000035d42824992d5cc01b834e081dca404073b9c150872d5cc03465a71fd4c940400ec00644882d5cc03b8a73d4d1c94040376dc669882d5cc0bf9cd9aed0c940401363997e892d5cc002f4fbfecdc94040ca4e3fa88b2d5cc0a487a1d5c9c940408f1ce90c8c2d5cc0698995d1c8c94040fab836548c2d5cc0bd175fb4c7c940409f1f46088f2d5cc0962023a0c2c940407b15191d902d5cc068041bd7bfc940400397c79a912d5cc0287d21e4bcc940403201bf46922d5cc065e3c116bbc940409d9d0c8e922d5cc0060fd3beb9c940400ef7915b932d5cc09012bbb6b7c940404fe61f7d932d5cc0e4a08499b6c94040fc71fbe5932d5cc0ea9106b7b5c94040eaec6470942d5cc0c2323674b3c94040601dc70f952d5cc043588d25acc94040aea06989952d5cc03ecf9f36aac94040307f85cc952d5cc0e5eb32fca7c94040dd0a6135962d5cc01b615111a7c9404048a7ae7c962d5cc00a2aaa7ea5c94040f4328ae5962d5cc05eb87361a4c94040c49448a2972d5cc04d81cccea2c940407c80eecb992d5cc06745d4449fc9404035d42824992d5cc01b834e081dca4040'
1943
+ '0106000000010000000103000000010000001a00000035d42824992d5cc01b834e081dca404073b9c150872d5cc03465a71fd4c940400ec00644882d5cc03b8a' \
1944
+ '73d4d1c94040376dc669882d5cc0bf9cd9aed0c940401363997e892d5cc002f4fbfecdc94040ca4e3fa88b2d5cc0a487a1d5c9c940408f1ce90c8c2d5cc06989' \
1945
+ '95d1c8c94040fab836548c2d5cc0bd175fb4c7c940409f1f46088f2d5cc0962023a0c2c940407b15191d902d5cc068041bd7bfc940400397c79a912d5cc0287d' \
1946
+ '21e4bcc940403201bf46922d5cc065e3c116bbc940409d9d0c8e922d5cc0060fd3beb9c940400ef7915b932d5cc09012bbb6b7c940404fe61f7d932d5cc0e4a0' \
1947
+ '8499b6c94040fc71fbe5932d5cc0ea9106b7b5c94040eaec6470942d5cc0c2323674b3c94040601dc70f952d5cc043588d25acc94040aea06989952d5cc03ecf' \
1948
+ '9f36aac94040307f85cc952d5cc0e5eb32fca7c94040dd0a6135962d5cc01b615111a7c9404048a7ae7c962d5cc00a2aaa7ea5c94040f4328ae5962d5cc05eb8' \
1949
+ '7361a4c94040c49448a2972d5cc04d81cccea2c940407c80eecb992d5cc06745d4449fc9404035d42824992d5cc01b834e081dca4040'
1789
1950
  ]
1790
1951
  tester['LINESTRING EMPTY', 'POLYGON EMPTY']
1791
1952
  end
1792
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
+
1793
1974
  def test_minimum_width
1794
1975
  skip unless ENV['FORCE_TESTS'] || Geos::Geometry.method_defined?(:minimum_width)
1795
1976
 
@@ -1856,7 +2037,13 @@ class GeometryTests < Minitest::Test
1856
2037
  simple_tester(:reverse, 'POINT (3 5)', 'POINT (3 5)')
1857
2038
  simple_tester(:reverse, 'MULTIPOINT (100 100, 10 100, 30 100)', 'MULTIPOINT (100 100, 10 100, 30 100)')
1858
2039
  simple_tester(:reverse, 'LINESTRING (200 200, 200 100)', 'LINESTRING (200 100, 200 200)')
1859
- simple_tester(:reverse, 'MULTILINESTRING ((1 1, 2 2), (3 3, 4 4))', 'MULTILINESTRING ((4 4, 3 3), (2 2, 1 1))')
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
+
1860
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))')
1861
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)))')
1862
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)))')