rgeo 3.0.0.pre.rc.3 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +11 -3
- data/ext/geos_c_impl/extconf.rb +1 -0
- data/ext/geos_c_impl/factory.c +43 -5
- data/ext/geos_c_impl/factory.h +13 -2
- data/ext/geos_c_impl/geometry.c +178 -122
- data/ext/geos_c_impl/geometry_collection.c +17 -19
- data/ext/geos_c_impl/line_string.c +46 -36
- data/ext/geos_c_impl/point.c +0 -2
- data/ext/geos_c_impl/polygon.c +10 -11
- data/ext/geos_c_impl/polygon.h +1 -1
- data/ext/geos_c_impl/preface.h +3 -0
- data/ext/geos_c_impl/ruby_more.c +7 -0
- data/ext/geos_c_impl/ruby_more.h +8 -0
- data/lib/rgeo/cartesian/analysis.rb +5 -3
- data/lib/rgeo/cartesian/bounding_box.rb +74 -79
- data/lib/rgeo/cartesian/calculations.rb +20 -26
- data/lib/rgeo/cartesian/factory.rb +47 -49
- data/lib/rgeo/cartesian/planar_graph.rb +10 -16
- data/lib/rgeo/cartesian/sweepline_intersector.rb +1 -3
- data/lib/rgeo/cartesian/valid_op.rb +1 -3
- data/lib/rgeo/coord_sys/cs/entities.rb +91 -101
- data/lib/rgeo/coord_sys/cs/factories.rb +0 -2
- data/lib/rgeo/coord_sys/cs/wkt_parser.rb +70 -29
- data/lib/rgeo/feature/curve.rb +0 -1
- data/lib/rgeo/feature/factory.rb +25 -27
- data/lib/rgeo/feature/factory_generator.rb +3 -4
- data/lib/rgeo/feature/geometry.rb +41 -30
- data/lib/rgeo/feature/geometry_collection.rb +3 -4
- data/lib/rgeo/feature/line_string.rb +1 -2
- data/lib/rgeo/feature/linear_ring.rb +0 -1
- data/lib/rgeo/feature/multi_curve.rb +0 -1
- data/lib/rgeo/feature/multi_surface.rb +0 -1
- data/lib/rgeo/feature/point.rb +0 -1
- data/lib/rgeo/feature/polygon.rb +1 -2
- data/lib/rgeo/feature/surface.rb +0 -1
- data/lib/rgeo/feature/types.rb +69 -85
- data/lib/rgeo/geographic/factory.rb +87 -80
- data/lib/rgeo/geographic/interface.rb +44 -27
- data/lib/rgeo/geographic/projected_feature_methods.rb +2 -6
- data/lib/rgeo/geographic/projected_window.rb +35 -21
- data/lib/rgeo/geographic/simple_mercator_projector.rb +27 -15
- data/lib/rgeo/geographic/spherical_feature_methods.rb +8 -3
- data/lib/rgeo/geographic/spherical_math.rb +17 -20
- data/lib/rgeo/geos/capi_factory.rb +50 -50
- data/lib/rgeo/geos/ffi_factory.rb +50 -49
- data/lib/rgeo/geos/ffi_feature_methods.rb +72 -98
- data/lib/rgeo/geos/interface.rb +16 -16
- data/lib/rgeo/geos/utils.rb +5 -5
- data/lib/rgeo/geos/zm_factory.rb +50 -42
- data/lib/rgeo/geos/zm_feature_methods.rb +15 -9
- data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +4 -4
- data/lib/rgeo/impl_helper/basic_geometry_methods.rb +1 -2
- data/lib/rgeo/impl_helper/basic_line_string_methods.rb +18 -24
- data/lib/rgeo/impl_helper/basic_point_methods.rb +1 -3
- data/lib/rgeo/impl_helper/basic_polygon_methods.rb +15 -16
- data/lib/rgeo/impl_helper/utils.rb +3 -9
- data/lib/rgeo/impl_helper/valid_op.rb +12 -16
- data/lib/rgeo/version.rb +1 -1
- data/lib/rgeo/wkrep/wkb_generator.rb +42 -47
- data/lib/rgeo/wkrep/wkb_parser.rb +17 -18
- data/lib/rgeo/wkrep/wkt_generator.rb +23 -16
- data/lib/rgeo/wkrep/wkt_parser.rb +23 -13
- metadata +6 -6
@@ -9,11 +9,22 @@
|
|
9
9
|
module RGeo
|
10
10
|
module Geos
|
11
11
|
# This the FFI-GEOS implementation of RGeo::Feature::Factory.
|
12
|
-
|
13
12
|
class FFIFactory
|
14
13
|
include Feature::Factory::Instance
|
15
14
|
include ImplHelper::Utils
|
16
15
|
|
16
|
+
attr_reader :coordinate_dimension, :spatial_dimension, :_has_3d, :_auto_prepare
|
17
|
+
|
18
|
+
# Returns the SRID of geometries created by this factory.
|
19
|
+
attr_reader :srid
|
20
|
+
|
21
|
+
# Returns the resolution used by buffer calculations on geometries
|
22
|
+
# created by this factory
|
23
|
+
attr_reader :buffer_resolution
|
24
|
+
|
25
|
+
# See RGeo::Feature::Factory#coord_sys
|
26
|
+
attr_reader :coord_sys
|
27
|
+
|
17
28
|
# Create a new factory. Returns nil if the FFI-GEOS implementation
|
18
29
|
# is not supported.
|
19
30
|
#
|
@@ -22,9 +33,11 @@ module RGeo
|
|
22
33
|
def initialize(opts = {})
|
23
34
|
@has_z = opts[:has_z_coordinate] ? true : false
|
24
35
|
@has_m = opts[:has_m_coordinate] ? true : false
|
36
|
+
|
25
37
|
if @has_z && @has_m
|
26
38
|
raise Error::UnsupportedOperation, "GEOS cannot support both Z and M coordinates at the same time."
|
27
39
|
end
|
40
|
+
|
28
41
|
@coordinate_dimension = 2
|
29
42
|
@coordinate_dimension += 1 if @has_z
|
30
43
|
@coordinate_dimension += 1 if @has_m
|
@@ -43,6 +56,7 @@ module RGeo
|
|
43
56
|
@wkt_writer = nil
|
44
57
|
else
|
45
58
|
@wkt_writer = ::Geos::WktWriter.new
|
59
|
+
@wkt_writer.output_dimensions = 2
|
46
60
|
@wkt_writer.trim = true
|
47
61
|
@wkt_generator = nil
|
48
62
|
end
|
@@ -53,6 +67,7 @@ module RGeo
|
|
53
67
|
@wkb_writer = nil
|
54
68
|
else
|
55
69
|
@wkb_writer = ::Geos::WkbWriter.new
|
70
|
+
@wkb_writer.output_dimensions = 2
|
56
71
|
@wkb_generator = nil
|
57
72
|
end
|
58
73
|
|
@@ -81,7 +96,6 @@ module RGeo
|
|
81
96
|
@wkb_parser = nil
|
82
97
|
end
|
83
98
|
end
|
84
|
-
attr_reader :coordinate_dimension, :spatial_dimension
|
85
99
|
|
86
100
|
# Standard object inspection output
|
87
101
|
|
@@ -91,12 +105,12 @@ module RGeo
|
|
91
105
|
|
92
106
|
# Factory equivalence test.
|
93
107
|
|
94
|
-
def eql?(
|
95
|
-
|
96
|
-
@has_z ==
|
97
|
-
@has_m ==
|
98
|
-
@buffer_resolution ==
|
99
|
-
@coord_sys.eql?(
|
108
|
+
def eql?(other)
|
109
|
+
other.is_a?(self.class) && @srid == other.srid &&
|
110
|
+
@has_z == other.property(:has_z_coordinate) &&
|
111
|
+
@has_m == other.property(:has_m_coordinate) &&
|
112
|
+
@buffer_resolution == other.property(:buffer_resolution) &&
|
113
|
+
@coord_sys.eql?(other.coord_sys)
|
100
114
|
end
|
101
115
|
alias == eql?
|
102
116
|
|
@@ -125,11 +139,9 @@ module RGeo
|
|
125
139
|
end
|
126
140
|
|
127
141
|
def marshal_load(data) # :nodoc:
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
coord_sys = nil
|
132
|
-
end
|
142
|
+
cs_class = CoordSys::CONFIG.default_coord_sys_class
|
143
|
+
coord_sys = data["cs"]&.then { |cs| cs_class.create_from_wkt(cs) }
|
144
|
+
|
133
145
|
initialize(
|
134
146
|
has_z_coordinate: data["hasz"],
|
135
147
|
has_m_coordinate: data["hasm"],
|
@@ -160,11 +172,9 @@ module RGeo
|
|
160
172
|
end
|
161
173
|
|
162
174
|
def init_with(coder) # :nodoc:
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
coord_sys = nil
|
167
|
-
end
|
175
|
+
cs_class = CoordSys::CONFIG.default_coord_sys_class
|
176
|
+
coord_sys = coder["cs"]&.then { |cs| cs_class.create_from_wkt(cs) }
|
177
|
+
|
168
178
|
initialize(
|
169
179
|
has_z_coordinate: coder["has_z_coordinate"],
|
170
180
|
has_m_coordinate: coder["has_m_coordinate"],
|
@@ -179,15 +189,6 @@ module RGeo
|
|
179
189
|
)
|
180
190
|
end
|
181
191
|
|
182
|
-
# Returns the SRID of geometries created by this factory.
|
183
|
-
|
184
|
-
attr_reader :srid
|
185
|
-
|
186
|
-
# Returns the resolution used by buffer calculations on geometries
|
187
|
-
# created by this factory
|
188
|
-
|
189
|
-
attr_reader :buffer_resolution
|
190
|
-
|
191
192
|
# See RGeo::Feature::Factory#property
|
192
193
|
def property(name_)
|
193
194
|
case name_
|
@@ -296,10 +297,8 @@ module RGeo
|
|
296
297
|
inner_rings = inner_rings.to_a unless inner_rings.is_a?(Array)
|
297
298
|
return unless RGeo::Feature::LineString.check_type(outer_ring)
|
298
299
|
outer_ring = create_fg_linear_ring(outer_ring.points)
|
299
|
-
|
300
|
-
|
301
|
-
create_fg_linear_ring(r.points)
|
302
|
-
end
|
300
|
+
return unless inner_rings.all? { |r| RGeo::Feature::LineString.check_type(r) }
|
301
|
+
inner_rings = inner_rings.map { |r| create_fg_linear_ring(r.points) }
|
303
302
|
inner_rings.compact!
|
304
303
|
fg_geom = ::Geos::Utils.create_polygon(outer_ring, *inner_rings)
|
305
304
|
FFIPolygonImpl.new(self, fg_geom, nil)
|
@@ -328,11 +327,16 @@ module RGeo
|
|
328
327
|
def multi_point(elems)
|
329
328
|
elems = elems.to_a unless elems.is_a?(Array)
|
330
329
|
elems = elems.map do |elem|
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
330
|
+
RGeo::Feature.cast(
|
331
|
+
elem,
|
332
|
+
self,
|
333
|
+
RGeo::Feature::Point,
|
334
|
+
:force_new,
|
335
|
+
:keep_subtype
|
336
|
+
)
|
335
337
|
end
|
338
|
+
return unless elems.all?
|
339
|
+
elems = elems.map(&:detach_fg_geom)
|
336
340
|
klasses = Array.new(elems.size, FFIPointImpl)
|
337
341
|
fg_geom = ::Geos::Utils.create_collection(::Geos::GeomTypes::GEOS_MULTIPOINT, elems)
|
338
342
|
FFIMultiPointImpl.new(self, fg_geom, klasses)
|
@@ -367,13 +371,9 @@ module RGeo
|
|
367
371
|
FFIMultiPolygonImpl.new(self, fg_geom, klasses)
|
368
372
|
end
|
369
373
|
|
370
|
-
# See RGeo::Feature::Factory#coord_sys
|
371
|
-
|
372
|
-
attr_reader :coord_sys
|
373
|
-
|
374
374
|
# See RGeo::Feature::Factory#override_cast
|
375
375
|
|
376
|
-
def override_cast(
|
376
|
+
def override_cast(_original, _ntype, _flags)
|
377
377
|
false
|
378
378
|
# TODO
|
379
379
|
end
|
@@ -421,14 +421,13 @@ module RGeo
|
|
421
421
|
klass.new(self, fg_geom, klasses)
|
422
422
|
end
|
423
423
|
|
424
|
-
attr_reader :_has_3d # :nodoc:
|
425
|
-
attr_reader :_auto_prepare # :nodoc:
|
426
|
-
|
427
424
|
def convert_to_fg_geometry(obj, type = nil)
|
428
|
-
if type && obj.factory != self
|
429
|
-
|
430
|
-
|
431
|
-
|
425
|
+
obj = Feature.cast(obj, self, type) if type && obj.factory != self
|
426
|
+
|
427
|
+
geom = obj&.fg_geom
|
428
|
+
raise RGeo::Error::InvalidGeometry, "Unable to cast the geometry to the FFI Factory" if geom.nil?
|
429
|
+
|
430
|
+
geom
|
432
431
|
end
|
433
432
|
|
434
433
|
def generate_wkt(geom)
|
@@ -450,6 +449,7 @@ module RGeo
|
|
450
449
|
def write_for_marshal(geom)
|
451
450
|
if Utils.ffi_supports_set_output_dimension || !@_has_3d
|
452
451
|
wkb_writer = ::Geos::WkbWriter.new
|
452
|
+
wkb_writer.output_dimensions = 2
|
453
453
|
wkb_writer.output_dimensions = 3 if @_has_3d
|
454
454
|
wkb_writer.write(geom.fg_geom)
|
455
455
|
else
|
@@ -464,6 +464,7 @@ module RGeo
|
|
464
464
|
def write_for_psych(geom)
|
465
465
|
if Utils.ffi_supports_set_output_dimension || !@_has_3d
|
466
466
|
wkt_writer = ::Geos::WktWriter.new
|
467
|
+
wkt_writer.output_dimensions = 2
|
467
468
|
wkt_writer.trim = true
|
468
469
|
wkt_writer.output_dimensions = 3 if @_has_3d
|
469
470
|
wkt_writer.write(geom.fg_geom)
|
@@ -480,14 +481,14 @@ module RGeo
|
|
480
481
|
|
481
482
|
def create_fg_linear_ring(points)
|
482
483
|
size = points.size
|
483
|
-
return if size
|
484
|
+
return if size.between?(1, 2)
|
484
485
|
if size > 0 && points.first != points.last
|
485
486
|
points += [points.first]
|
486
487
|
size += 1
|
487
488
|
end
|
488
489
|
cs = ::Geos::CoordinateSequence.new(size, 3)
|
490
|
+
return unless points.all? { |p| RGeo::Feature::Point.check_type(p) }
|
489
491
|
points.each_with_index do |p, i|
|
490
|
-
return unless RGeo::Feature::Point.check_type(p)
|
491
492
|
cs.set_x(i, p.x)
|
492
493
|
cs.set_y(i, p.y)
|
493
494
|
if @has_z
|
@@ -13,6 +13,8 @@ module RGeo
|
|
13
13
|
module FFIGeometryMethods # :nodoc:
|
14
14
|
include Feature::Instance
|
15
15
|
|
16
|
+
attr_reader :factory, :fg_geom, :_klasses
|
17
|
+
|
16
18
|
def initialize(factory, fg_geom, klasses)
|
17
19
|
@factory = factory
|
18
20
|
@fg_geom = fg_geom
|
@@ -56,11 +58,6 @@ module RGeo
|
|
56
58
|
@_klasses = nil
|
57
59
|
end
|
58
60
|
|
59
|
-
attr_reader :factory
|
60
|
-
attr_reader :fg_geom
|
61
|
-
|
62
|
-
attr_reader :_klasses # :nodoc:
|
63
|
-
|
64
61
|
def initialize_copy(orig)
|
65
62
|
@factory = orig.factory
|
66
63
|
@fg_geom = orig.fg_geom.clone
|
@@ -94,9 +91,7 @@ module RGeo
|
|
94
91
|
end
|
95
92
|
|
96
93
|
def prepare!
|
97
|
-
if @_fg_prep.is_a?(Integer)
|
98
|
-
@_fg_prep = ::Geos::PreparedGeometry.new(@fg_geom)
|
99
|
-
end
|
94
|
+
@_fg_prep = ::Geos::PreparedGeometry.new(@fg_geom) if @_fg_prep.is_a?(Integer)
|
100
95
|
self
|
101
96
|
end
|
102
97
|
|
@@ -149,20 +144,21 @@ module RGeo
|
|
149
144
|
|
150
145
|
# (see RGeo::ImplHelper::ValidityCheck#make_valid)
|
151
146
|
# Only available since GEOS 3.8+
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
147
|
+
if ::Geos::FFIGeos.respond_to?(:GEOSMakeValid_r)
|
148
|
+
def make_valid
|
149
|
+
@factory.wrap_fg_geom(@fg_geom.make_valid, nil)
|
150
|
+
rescue ::Geos::GEOSException
|
151
|
+
raise Error::UnsupportedOperation
|
152
|
+
end
|
153
|
+
end
|
157
154
|
|
158
155
|
def equals?(rhs)
|
159
156
|
return false unless rhs.is_a?(RGeo::Feature::Instance)
|
160
157
|
fg = factory.convert_to_fg_geometry(rhs)
|
161
|
-
|
162
|
-
false
|
158
|
+
|
163
159
|
# GEOS has a bug where empty geometries are not spatially equal
|
164
160
|
# to each other. Work around this case first.
|
165
|
-
|
161
|
+
if fg.empty? && @fg_geom.empty?
|
166
162
|
true
|
167
163
|
else
|
168
164
|
@fg_geom.eql?(fg)
|
@@ -172,83 +168,54 @@ module RGeo
|
|
172
168
|
|
173
169
|
def disjoint?(rhs)
|
174
170
|
fg = factory.convert_to_fg_geometry(rhs)
|
175
|
-
if
|
176
|
-
|
177
|
-
prep ? prep.disjoint?(fg) : @fg_geom.disjoint?(fg)
|
178
|
-
else
|
179
|
-
false
|
180
|
-
end
|
171
|
+
prep = request_prepared if Utils.ffi_supports_prepared_level2
|
172
|
+
prep ? prep.disjoint?(fg) : @fg_geom.disjoint?(fg)
|
181
173
|
end
|
182
174
|
|
183
175
|
def intersects?(rhs)
|
184
176
|
fg = factory.convert_to_fg_geometry(rhs)
|
185
|
-
if
|
186
|
-
|
187
|
-
prep ? prep.intersects?(fg) : @fg_geom.intersects?(fg)
|
188
|
-
else
|
189
|
-
false
|
190
|
-
end
|
177
|
+
prep = request_prepared if Utils.ffi_supports_prepared_level1
|
178
|
+
prep ? prep.intersects?(fg) : @fg_geom.intersects?(fg)
|
191
179
|
end
|
192
180
|
|
193
181
|
def touches?(rhs)
|
194
182
|
fg = factory.convert_to_fg_geometry(rhs)
|
195
|
-
if
|
196
|
-
|
197
|
-
prep ? prep.touches?(fg) : @fg_geom.touches?(fg)
|
198
|
-
else
|
199
|
-
false
|
200
|
-
end
|
183
|
+
prep = request_prepared if Utils.ffi_supports_prepared_level2
|
184
|
+
prep ? prep.touches?(fg) : @fg_geom.touches?(fg)
|
201
185
|
end
|
202
186
|
|
203
187
|
def crosses?(rhs)
|
204
188
|
fg = factory.convert_to_fg_geometry(rhs)
|
205
|
-
if
|
206
|
-
|
207
|
-
prep ? prep.crosses?(fg) : @fg_geom.crosses?(fg)
|
208
|
-
else
|
209
|
-
false
|
210
|
-
end
|
189
|
+
prep = request_prepared if Utils.ffi_supports_prepared_level2
|
190
|
+
prep ? prep.crosses?(fg) : @fg_geom.crosses?(fg)
|
211
191
|
end
|
212
192
|
|
213
193
|
def within?(rhs)
|
214
194
|
fg = factory.convert_to_fg_geometry(rhs)
|
215
|
-
if
|
216
|
-
|
217
|
-
prep ? prep.within?(fg) : @fg_geom.within?(fg)
|
218
|
-
else
|
219
|
-
false
|
220
|
-
end
|
195
|
+
prep = request_prepared if Utils.ffi_supports_prepared_level2
|
196
|
+
prep ? prep.within?(fg) : @fg_geom.within?(fg)
|
221
197
|
end
|
222
198
|
|
223
199
|
def contains?(rhs)
|
224
200
|
fg = factory.convert_to_fg_geometry(rhs)
|
225
|
-
if
|
226
|
-
|
227
|
-
prep ? prep.contains?(fg) : @fg_geom.contains?(fg)
|
228
|
-
else
|
229
|
-
false
|
230
|
-
end
|
201
|
+
prep = request_prepared if Utils.ffi_supports_prepared_level1
|
202
|
+
prep ? prep.contains?(fg) : @fg_geom.contains?(fg)
|
231
203
|
end
|
232
204
|
|
233
205
|
def overlaps?(rhs)
|
234
206
|
fg = factory.convert_to_fg_geometry(rhs)
|
235
|
-
if
|
236
|
-
|
237
|
-
prep ? prep.overlaps?(fg) : @fg_geom.overlaps?(fg)
|
238
|
-
else
|
239
|
-
false
|
240
|
-
end
|
207
|
+
prep = request_prepared if Utils.ffi_supports_prepared_level2
|
208
|
+
prep ? prep.overlaps?(fg) : @fg_geom.overlaps?(fg)
|
241
209
|
end
|
242
210
|
|
243
211
|
def relate?(rhs, pattern)
|
244
212
|
fg = factory.convert_to_fg_geometry(rhs)
|
245
|
-
|
213
|
+
@fg_geom.relate_pattern(fg, pattern)
|
246
214
|
end
|
247
|
-
alias relate relate? # DEPRECATED
|
248
215
|
|
249
216
|
def distance(rhs)
|
250
217
|
fg = factory.convert_to_fg_geometry(rhs)
|
251
|
-
|
218
|
+
@fg_geom.distance(fg)
|
252
219
|
end
|
253
220
|
|
254
221
|
def buffer(distance)
|
@@ -261,14 +228,14 @@ module RGeo
|
|
261
228
|
|
262
229
|
def intersection(rhs)
|
263
230
|
fg = factory.convert_to_fg_geometry(rhs)
|
264
|
-
|
231
|
+
@factory.wrap_fg_geom(@fg_geom.intersection(fg), nil)
|
265
232
|
end
|
266
233
|
|
267
234
|
alias * intersection
|
268
235
|
|
269
236
|
def union(rhs)
|
270
237
|
fg = factory.convert_to_fg_geometry(rhs)
|
271
|
-
|
238
|
+
@factory.wrap_fg_geom(@fg_geom.union(fg), nil)
|
272
239
|
end
|
273
240
|
|
274
241
|
alias + union
|
@@ -280,18 +247,18 @@ module RGeo
|
|
280
247
|
|
281
248
|
def difference(rhs)
|
282
249
|
fg = factory.convert_to_fg_geometry(rhs)
|
283
|
-
|
250
|
+
@factory.wrap_fg_geom(@fg_geom.difference(fg), nil)
|
284
251
|
end
|
285
252
|
|
286
253
|
alias - difference
|
287
254
|
|
288
255
|
def sym_difference(rhs)
|
289
256
|
fg = factory.convert_to_fg_geometry(rhs)
|
290
|
-
|
257
|
+
@factory.wrap_fg_geom(@fg_geom.sym_difference(fg), nil)
|
291
258
|
end
|
292
259
|
|
293
|
-
def eql?(
|
294
|
-
rep_equals?(
|
260
|
+
def eql?(other)
|
261
|
+
rep_equals?(other)
|
295
262
|
end
|
296
263
|
|
297
264
|
def detach_fg_geom
|
@@ -343,7 +310,7 @@ module RGeo
|
|
343
310
|
end
|
344
311
|
|
345
312
|
def rep_equals?(rhs)
|
346
|
-
rhs.
|
313
|
+
rhs.instance_of?(self.class) && rhs.factory.eql?(@factory) &&
|
347
314
|
Utils.ffi_coord_seqs_equal?(rhs.fg_geom.coord_seq, @fg_geom.coord_seq, @factory._has_3d)
|
348
315
|
end
|
349
316
|
|
@@ -372,14 +339,15 @@ module RGeo
|
|
372
339
|
@fg_geom.num_points
|
373
340
|
end
|
374
341
|
|
375
|
-
def point_n(
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
342
|
+
def point_n(idx)
|
343
|
+
return unless idx >= 0 && idx < @fg_geom.num_points
|
344
|
+
|
345
|
+
coord_seq = @fg_geom.coord_seq
|
346
|
+
x = coord_seq.get_x(idx)
|
347
|
+
y = coord_seq.get_y(idx)
|
348
|
+
extra = @factory._has_3d ? [coord_seq.get_z(idx)] : []
|
349
|
+
|
350
|
+
@factory.point(x, y, *extra)
|
383
351
|
end
|
384
352
|
|
385
353
|
def start_point
|
@@ -410,7 +378,7 @@ module RGeo
|
|
410
378
|
end
|
411
379
|
|
412
380
|
def rep_equals?(rhs)
|
413
|
-
rhs.
|
381
|
+
rhs.instance_of?(self.class) && rhs.factory.eql?(@factory) &&
|
414
382
|
Utils.ffi_coord_seqs_equal?(rhs.fg_geom.coord_seq, @fg_geom.coord_seq, @factory._has_3d)
|
415
383
|
end
|
416
384
|
|
@@ -464,10 +432,10 @@ module RGeo
|
|
464
432
|
@fg_geom.num_interior_rings
|
465
433
|
end
|
466
434
|
|
467
|
-
def interior_ring_n(
|
468
|
-
|
469
|
-
|
470
|
-
|
435
|
+
def interior_ring_n(idx)
|
436
|
+
return unless idx >= 0 && idx < @fg_geom.num_interior_rings
|
437
|
+
|
438
|
+
@factory.wrap_fg_geom(@fg_geom.interior_ring_n(idx), FFILinearRingImpl)
|
471
439
|
end
|
472
440
|
|
473
441
|
def interior_rings
|
@@ -477,7 +445,7 @@ module RGeo
|
|
477
445
|
end
|
478
446
|
|
479
447
|
def rep_equals?(rhs)
|
480
|
-
if rhs.
|
448
|
+
if rhs.instance_of?(self.class) && rhs.factory.eql?(@factory) &&
|
481
449
|
rhs.exterior_ring.rep_equals?(exterior_ring)
|
482
450
|
sn = @fg_geom.num_interior_rings
|
483
451
|
rn = rhs.num_interior_rings
|
@@ -493,8 +461,10 @@ module RGeo
|
|
493
461
|
|
494
462
|
def hash
|
495
463
|
@hash ||= begin
|
496
|
-
hash = Utils.ffi_coord_seq_hash(
|
497
|
-
|
464
|
+
hash = Utils.ffi_coord_seq_hash(
|
465
|
+
@fg_geom.exterior_ring.coord_seq,
|
466
|
+
[@factory, geometry_type].hash
|
467
|
+
)
|
498
468
|
@fg_geom.interior_rings.inject(hash) do |h, r|
|
499
469
|
Utils.ffi_coord_seq_hash(r.coord_seq, h)
|
500
470
|
end
|
@@ -512,7 +482,7 @@ module RGeo
|
|
512
482
|
end
|
513
483
|
|
514
484
|
def rep_equals?(rhs)
|
515
|
-
if rhs.
|
485
|
+
if rhs.instance_of?(self.class) && rhs.factory.eql?(@factory)
|
516
486
|
size = @fg_geom.num_geometries
|
517
487
|
if size == rhs.num_geometries
|
518
488
|
size.times do |n|
|
@@ -529,19 +499,24 @@ module RGeo
|
|
529
499
|
end
|
530
500
|
alias size num_geometries
|
531
501
|
|
532
|
-
def geometry_n(
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
502
|
+
def geometry_n(idx)
|
503
|
+
return unless idx >= 0 && idx < @fg_geom.num_geometries
|
504
|
+
|
505
|
+
@factory.wrap_fg_geom(
|
506
|
+
@fg_geom.get_geometry_n(idx),
|
507
|
+
@_klasses ? @_klasses[idx] : nil
|
508
|
+
)
|
537
509
|
end
|
538
510
|
|
539
|
-
def [](
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
511
|
+
def [](idx)
|
512
|
+
idx += @fg_geom.num_geometries if idx < 0
|
513
|
+
|
514
|
+
return unless idx >= 0 && idx < @fg_geom.num_geometries
|
515
|
+
|
516
|
+
@factory.wrap_fg_geom(
|
517
|
+
@fg_geom.get_geometry_n(idx),
|
518
|
+
@_klasses ? @_klasses[idx] : nil
|
519
|
+
)
|
545
520
|
end
|
546
521
|
|
547
522
|
def hash
|
@@ -551,8 +526,7 @@ module RGeo
|
|
551
526
|
def each
|
552
527
|
if block_given?
|
553
528
|
@fg_geom.num_geometries.times do |n|
|
554
|
-
yield @factory.wrap_fg_geom(@fg_geom.get_geometry_n(n),
|
555
|
-
@_klasses ? @_klasses[n] : nil)
|
529
|
+
yield @factory.wrap_fg_geom(@fg_geom.get_geometry_n(n), @_klasses ? @_klasses[n] : nil)
|
556
530
|
end
|
557
531
|
self
|
558
532
|
else
|
data/lib/rgeo/geos/interface.rb
CHANGED
@@ -62,13 +62,12 @@ module RGeo
|
|
62
62
|
|
63
63
|
def version
|
64
64
|
unless defined?(@version)
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
65
|
+
@version =
|
66
|
+
if RGeo::Geos::CAPI_SUPPORTED
|
67
|
+
RGeo::Geos::CAPIFactory._geos_version.freeze
|
68
|
+
elsif RGeo::Geos::FFI_SUPPORTED
|
69
|
+
::Geos::FFIGeos.GEOSversion.sub(/-CAPI-.*$/, "").freeze
|
70
|
+
end
|
72
71
|
end
|
73
72
|
@version
|
74
73
|
end
|
@@ -163,15 +162,16 @@ module RGeo
|
|
163
162
|
# never automatically generates a prepared geometry (unless you
|
164
163
|
# generate one explicitly using the <tt>prepare!</tt> method).
|
165
164
|
def factory(opts = {})
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
165
|
+
return unless supported?
|
166
|
+
|
167
|
+
native_interface = opts[:native_interface] || Geos.preferred_native_interface
|
168
|
+
|
169
|
+
if opts[:has_z_coordinate] && opts[:has_m_coordinate]
|
170
|
+
ZMFactory.new(opts)
|
171
|
+
elsif native_interface == :ffi
|
172
|
+
FFIFactory.new(opts)
|
173
|
+
else
|
174
|
+
CAPIFactory.create(opts)
|
175
175
|
end
|
176
176
|
end
|
177
177
|
end
|
data/lib/rgeo/geos/utils.rb
CHANGED
@@ -49,17 +49,17 @@ module RGeo
|
|
49
49
|
result
|
50
50
|
end
|
51
51
|
|
52
|
-
def ffi_coord_seq_hash(
|
53
|
-
(0...
|
54
|
-
[hash,
|
52
|
+
def ffi_coord_seq_hash(coord_seq, init_hash = 0)
|
53
|
+
(0...coord_seq.length).inject(init_hash) do |hash, i|
|
54
|
+
[hash, coord_seq.get_x(i), coord_seq.get_y(i), coord_seq.get_z(i)].hash
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
|
-
def
|
58
|
+
def ffi_supports_prepared_level1
|
59
59
|
FFI_SUPPORTED && ::Geos::FFIGeos.respond_to?(:GEOSPreparedContains_r)
|
60
60
|
end
|
61
61
|
|
62
|
-
def
|
62
|
+
def ffi_supports_prepared_level2
|
63
63
|
FFI_SUPPORTED && ::Geos::FFIGeos.respond_to?(:GEOSPreparedDisjoint_r)
|
64
64
|
end
|
65
65
|
|