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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1015 -134
- data/.travis.yml +3 -4
- data/FUNDING.yml +2 -0
- data/Gemfile +2 -2
- data/MIT-LICENSE +1 -1
- data/lib/ffi-geos.rb +37 -4
- data/lib/ffi-geos/geometry.rb +46 -10
- data/lib/ffi-geos/strtree.rb +25 -25
- data/lib/ffi-geos/utils.rb +12 -11
- data/lib/ffi-geos/version.rb +1 -1
- data/lib/ffi-geos/wkt_writer.rb +1 -4
- data/test/coordinate_sequence_tests.rb +2 -2
- data/test/geometry_collection_tests.rb +3 -2
- data/test/geometry_tests.rb +209 -22
- data/test/strtree_tests.rb +1 -0
- data/test/test_helper.rb +33 -25
- metadata +7 -6
data/.travis.yml
CHANGED
data/FUNDING.yml
ADDED
data/Gemfile
CHANGED
data/MIT-LICENSE
CHANGED
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 ||=
|
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 ||=
|
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
|
data/lib/ffi-geos/geometry.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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))
|
data/lib/ffi-geos/strtree.rb
CHANGED
@@ -23,18 +23,19 @@ module Geos
|
|
23
23
|
geoms_and_objects = nil # forward declaration
|
24
24
|
capacity = 10
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
args.first
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
36
|
-
|
37
|
-
|
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 =
|
141
|
-
|
142
|
-
|
143
|
-
memo
|
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
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
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
|
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)
|
data/lib/ffi-geos/utils.rb
CHANGED
@@ -30,17 +30,18 @@ module Geos
|
|
30
30
|
def create_point(*args)
|
31
31
|
options = extract_options!(args)
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
data/lib/ffi-geos/version.rb
CHANGED
data/lib/ffi-geos/wkt_writer.rb
CHANGED
@@ -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),
|
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
|
|
data/test/geometry_tests.rb
CHANGED
@@ -13,12 +13,36 @@ class GeometryTests < Minitest::Test
|
|
13
13
|
def test_intersection
|
14
14
|
comparison_tester(
|
15
15
|
:intersection,
|
16
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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(
|
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)),
|
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[
|
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[
|
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
|
-
'
|
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
|
-
|
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)))')
|