rgeo 0.2.9 → 0.3.0

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 (67) hide show
  1. data/History.rdoc +11 -0
  2. data/README.rdoc +3 -3
  3. data/Spatial_Programming_With_RGeo.rdoc +19 -8
  4. data/Version +1 -1
  5. data/ext/geos_c_impl/factory.c +1 -0
  6. data/ext/geos_c_impl/factory.h +1 -0
  7. data/ext/geos_c_impl/geometry.c +4 -5
  8. data/ext/geos_c_impl/geometry_collection.c +15 -0
  9. data/ext/geos_c_impl/line_string.c +10 -0
  10. data/ext/geos_c_impl/point.c +2 -0
  11. data/ext/geos_c_impl/polygon.c +4 -0
  12. data/lib/rgeo/cartesian/feature_classes.rb +23 -17
  13. data/lib/rgeo/cartesian/feature_methods.rb +20 -1
  14. data/lib/rgeo/feature.rb +1 -0
  15. data/lib/rgeo/feature/curve.rb +1 -2
  16. data/lib/rgeo/feature/geometry_collection.rb +1 -1
  17. data/lib/rgeo/feature/line.rb +1 -1
  18. data/lib/rgeo/feature/line_string.rb +1 -2
  19. data/lib/rgeo/feature/linear_ring.rb +1 -2
  20. data/lib/rgeo/feature/mixins.rb +198 -0
  21. data/lib/rgeo/feature/multi_curve.rb +1 -2
  22. data/lib/rgeo/feature/multi_line_string.rb +1 -2
  23. data/lib/rgeo/feature/multi_point.rb +1 -2
  24. data/lib/rgeo/feature/multi_polygon.rb +1 -2
  25. data/lib/rgeo/feature/multi_surface.rb +1 -2
  26. data/lib/rgeo/feature/point.rb +1 -2
  27. data/lib/rgeo/feature/polygon.rb +1 -3
  28. data/lib/rgeo/feature/surface.rb +1 -2
  29. data/lib/rgeo/feature/types.rb +27 -0
  30. data/lib/rgeo/geographic/projected_feature_classes.rb +31 -4
  31. data/lib/rgeo/geographic/projected_feature_methods.rb +2 -1
  32. data/lib/rgeo/geographic/spherical_feature_classes.rb +30 -3
  33. data/lib/rgeo/geos.rb +22 -0
  34. data/lib/rgeo/geos/factory.rb +11 -5
  35. data/lib/rgeo/geos/ffi_classes.rb +655 -0
  36. data/lib/rgeo/geos/ffi_factory.rb +503 -0
  37. data/lib/rgeo/geos/impl_additions.rb +1 -1
  38. data/lib/rgeo/geos/interface.rb +63 -8
  39. data/lib/rgeo/geos/zm_factory.rb +10 -4
  40. data/test/common/geometry_collection_tests.rb +1 -3
  41. data/test/coord_sys/tc_ogc_cs.rb +13 -2
  42. data/test/coord_sys/tc_proj4_srs_data.rb +1 -1
  43. data/test/{geos → geos_capi}/tc_factory.rb +2 -2
  44. data/test/{geos → geos_capi}/tc_geometry_collection.rb +2 -2
  45. data/test/{geos → geos_capi}/tc_line_string.rb +2 -2
  46. data/test/{geos → geos_capi}/tc_misc.rb +6 -2
  47. data/test/{geos → geos_capi}/tc_multi_line_string.rb +2 -2
  48. data/test/{geos → geos_capi}/tc_multi_point.rb +2 -2
  49. data/test/{geos → geos_capi}/tc_multi_polygon.rb +2 -2
  50. data/test/{geos → geos_capi}/tc_parsing_unparsing.rb +2 -2
  51. data/test/{geos → geos_capi}/tc_point.rb +2 -2
  52. data/test/{geos → geos_capi}/tc_polygon.rb +2 -2
  53. data/test/{geos → geos_capi}/tc_zmfactory.rb +2 -2
  54. data/test/geos_ffi/tc_factory.rb +91 -0
  55. data/test/geos_ffi/tc_geometry_collection.rb +62 -0
  56. data/test/geos_ffi/tc_line_string.rb +62 -0
  57. data/test/geos_ffi/tc_misc.rb +69 -0
  58. data/test/geos_ffi/tc_multi_line_string.rb +62 -0
  59. data/test/geos_ffi/tc_multi_point.rb +62 -0
  60. data/test/geos_ffi/tc_multi_polygon.rb +64 -0
  61. data/test/geos_ffi/tc_parsing_unparsing.rb +81 -0
  62. data/test/geos_ffi/tc_point.rb +87 -0
  63. data/test/geos_ffi/tc_polygon.rb +86 -0
  64. data/test/geos_ffi/tc_zmfactory.rb +86 -0
  65. data/test/tc_mixins.rb +188 -0
  66. data/test/tc_types.rb +77 -0
  67. metadata +54 -25
@@ -71,7 +71,8 @@ module RGeo
71
71
 
72
72
 
73
73
  def boundary
74
- factory.unproject(projection.boundary)
74
+ boundary_ = projection.boundary
75
+ boundary_ ? factory.unproject(boundary_) : nil
75
76
  end
76
77
 
77
78
 
@@ -100,6 +100,9 @@ module RGeo
100
100
  alias_method :lat, :y
101
101
 
102
102
 
103
+ Feature::MixinCollection::GLOBAL.for_type(Feature::Point).include_in_class(self, true)
104
+
105
+
103
106
  end
104
107
 
105
108
 
@@ -113,6 +116,9 @@ module RGeo
113
116
  include SphericalLineStringMethods
114
117
 
115
118
 
119
+ Feature::MixinCollection::GLOBAL.for_type(Feature::LineString).include_in_class(self, true)
120
+
121
+
116
122
  end
117
123
 
118
124
 
@@ -127,6 +133,9 @@ module RGeo
127
133
  include SphericalLineStringMethods
128
134
 
129
135
 
136
+ Feature::MixinCollection::GLOBAL.for_type(Feature::Line).include_in_class(self, true)
137
+
138
+
130
139
  end
131
140
 
132
141
 
@@ -141,6 +150,9 @@ module RGeo
141
150
  include SphericalLineStringMethods
142
151
 
143
152
 
153
+ Feature::MixinCollection::GLOBAL.for_type(Feature::LinearRing).include_in_class(self, true)
154
+
155
+
144
156
  end
145
157
 
146
158
 
@@ -153,6 +165,9 @@ module RGeo
153
165
  include SphericalGeometryMethods
154
166
 
155
167
 
168
+ Feature::MixinCollection::GLOBAL.for_type(Feature::Polygon).include_in_class(self, true)
169
+
170
+
156
171
  end
157
172
 
158
173
 
@@ -165,45 +180,57 @@ module RGeo
165
180
  include SphericalGeometryMethods
166
181
 
167
182
 
183
+ Feature::MixinCollection::GLOBAL.for_type(Feature::GeometryCollection).include_in_class(self, true)
184
+
185
+
168
186
  end
169
187
 
170
188
 
171
189
  class SphericalMultiPointImpl # :nodoc:
172
190
 
173
191
 
174
- include Feature::GeometryCollection
192
+ include Feature::MultiPoint
175
193
  include ImplHelper::BasicGeometryMethods
176
194
  include ImplHelper::BasicGeometryCollectionMethods
177
195
  include ImplHelper::BasicMultiPointMethods
178
196
  include SphericalGeometryMethods
179
197
 
180
198
 
199
+ Feature::MixinCollection::GLOBAL.for_type(Feature::MultiPoint).include_in_class(self, true)
200
+
201
+
181
202
  end
182
203
 
183
204
 
184
205
  class SphericalMultiLineStringImpl # :nodoc:
185
206
 
186
207
 
187
- include Feature::GeometryCollection
208
+ include Feature::MultiLineString
188
209
  include ImplHelper::BasicGeometryMethods
189
210
  include ImplHelper::BasicGeometryCollectionMethods
190
211
  include ImplHelper::BasicMultiLineStringMethods
191
212
  include SphericalGeometryMethods
192
213
 
193
214
 
215
+ Feature::MixinCollection::GLOBAL.for_type(Feature::MultiLineString).include_in_class(self, true)
216
+
217
+
194
218
  end
195
219
 
196
220
 
197
221
  class SphericalMultiPolygonImpl # :nodoc:
198
222
 
199
223
 
200
- include Feature::GeometryCollection
224
+ include Feature::MultiPolygon
201
225
  include ImplHelper::BasicGeometryMethods
202
226
  include ImplHelper::BasicGeometryCollectionMethods
203
227
  include ImplHelper::BasicMultiPolygonMethods
204
228
  include SphericalGeometryMethods
205
229
 
206
230
 
231
+ Feature::MixinCollection::GLOBAL.for_type(Feature::MultiPolygon).include_in_class(self, true)
232
+
233
+
207
234
  end
208
235
 
209
236
 
data/lib/rgeo/geos.rb CHANGED
@@ -68,5 +68,27 @@ begin
68
68
  require 'rgeo/geos/geos_c_impl'
69
69
  rescue ::LoadError; end
70
70
  require 'rgeo/geos/impl_additions'
71
+ require 'rgeo/geos/ffi_factory'
72
+ require 'rgeo/geos/ffi_classes'
71
73
  require 'rgeo/geos/zm_factory'
72
74
  require 'rgeo/geos/zm_impl'
75
+
76
+ # :stopdoc:
77
+
78
+ # Determine native interface support.
79
+ begin
80
+ require 'ffi-geos'
81
+ ::RGeo::Geos::FFI_SUPPORTED = true
82
+ rescue ::LoadError
83
+ ::RGeo::Geos::FFI_SUPPORTED = false
84
+ rescue
85
+ ::RGeo::Geos::FFI_SUPPORTED = false
86
+ end
87
+ ::RGeo::Geos::CAPI_SUPPORTED = ::RGeo::Geos::Factory.respond_to?(:_create) ? true : false
88
+ if ::RGeo::Geos::CAPI_SUPPORTED
89
+ ::RGeo::Geos.preferred_native_interface = :capi
90
+ elsif ::RGeo::Geos::FFI_SUPPORTED
91
+ ::RGeo::Geos.preferred_native_interface = :ffi
92
+ end
93
+
94
+ # :startdoc:
@@ -39,7 +39,7 @@ module RGeo
39
39
  module Geos
40
40
 
41
41
 
42
- # This the GEOS implementation of ::RGeo::Feature::Factory.
42
+ # This the GEOS CAPI implementation of ::RGeo::Feature::Factory.
43
43
 
44
44
  class Factory
45
45
 
@@ -50,8 +50,8 @@ module RGeo
50
50
  class << self
51
51
 
52
52
 
53
- # Create a new factory. Returns nil if the GEOS implementation is
54
- # not supported.
53
+ # Create a new factory. Returns nil if the GEOS CAPI implementation
54
+ # is not supported.
55
55
  #
56
56
  # See ::RGeo::Geos.factory for a list of supported options.
57
57
 
@@ -61,7 +61,7 @@ module RGeo
61
61
 
62
62
  # Get flags to pass to the C extension
63
63
  flags_ = 0
64
- flags_ |= 1 if opts_[:lenient_multi_polygon_assertions]
64
+ flags_ |= 1 if opts_[:lenient_multi_polygon_assertions] || opts_[:uses_lenient_multi_polygon_assertions]
65
65
  flags_ |= 2 if opts_[:has_z_coordinate]
66
66
  flags_ |= 4 if opts_[:has_m_coordinate]
67
67
  if flags_ & 6 == 6
@@ -163,7 +163,9 @@ module RGeo
163
163
  # Factory equivalence test.
164
164
 
165
165
  def eql?(rhs_)
166
- rhs_.is_a?(Factory) && rhs_.srid == _srid && rhs_._buffer_resolution == _buffer_resolution && rhs_._flags == _flags && rhs_.proj4 == @proj4
166
+ rhs_.is_a?(Factory) && rhs_.srid == _srid &&
167
+ rhs_._buffer_resolution == _buffer_resolution && rhs_._flags == _flags &&
168
+ rhs_.proj4 == @proj4
167
169
  end
168
170
  alias_method :==, :eql?
169
171
 
@@ -200,6 +202,10 @@ module RGeo
200
202
  _flags & 0x4 != 0
201
203
  when :is_cartesian
202
204
  true
205
+ when :uses_lenient_multi_polygon_assertions
206
+ _flags & 0x1 != 0
207
+ when :buffer_resolution
208
+ _buffer_resolution
203
209
  else
204
210
  nil
205
211
  end
@@ -0,0 +1,655 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # FFI-GEOS geometry implementation
4
+ #
5
+ # -----------------------------------------------------------------------------
6
+ # Copyright 2010 Daniel Azuma
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are met:
12
+ #
13
+ # * Redistributions of source code must retain the above copyright notice,
14
+ # this list of conditions and the following disclaimer.
15
+ # * Redistributions in binary form must reproduce the above copyright notice,
16
+ # this list of conditions and the following disclaimer in the documentation
17
+ # and/or other materials provided with the distribution.
18
+ # * Neither the name of the copyright holder, nor the names of any other
19
+ # contributors to this software, may be used to endorse or promote products
20
+ # derived from this software without specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
+ # POSSIBILITY OF SUCH DAMAGE.
33
+ # -----------------------------------------------------------------------------
34
+ ;
35
+
36
+
37
+ module RGeo
38
+
39
+ module Geos
40
+
41
+
42
+ module FFIUtils # :nodoc:
43
+
44
+ class << self
45
+
46
+
47
+ def coord_seqs_equal?(cs1_, cs2_, check_z_)
48
+ len1_ = cs1_.length
49
+ len2_ = cs2_.length
50
+ if len1_ == len2_
51
+ (0...len1_).each do |i_|
52
+ return false unless cs1_.get_x(i_) == cs2_.get_x(i_) &&
53
+ cs1_.get_y(i_) == cs2_.get_y(i_) &&
54
+ (!check_z_ || cs1_.get_z(i_) == cs2_.get_z(i_))
55
+ end
56
+ true
57
+ else
58
+ false
59
+ end
60
+ end
61
+
62
+
63
+ def compute_dimension(geom_)
64
+ result_ = -1
65
+ case geom_.type_id
66
+ when ::Geos::GeomTypes::GEOS_POINT
67
+ result_ = 0
68
+ when ::Geos::GeomTypes::GEOS_MULTIPOINT
69
+ result_ = 0 unless geom_.empty?
70
+ when ::Geos::GeomTypes::GEOS_LINESTRING, ::Geos::GeomTypes::GEOS_LINEARRING
71
+ result_ = 1
72
+ when ::Geos::GeomTypes::GEOS_MULTILINESTRING
73
+ result_ = 1 unless geom_.empty?
74
+ when ::Geos::GeomTypes::GEOS_POLYGON
75
+ result_ = 2
76
+ when ::Geos::GeomTypes::GEOS_MULTIPOLYGON
77
+ result_ = 2 unless geom_.empty?
78
+ when ::Geos::GeomTypes::GEOS_GEOMETRYCOLLECTION
79
+ geom_.each do |g_|
80
+ dim_ = compute_dimension(g_)
81
+ result_ = dim_ if result_ < dim_
82
+ end
83
+ end
84
+ result_
85
+ end
86
+
87
+
88
+ end
89
+
90
+ end
91
+
92
+
93
+ class FFIGeometryImpl # :nodoc:
94
+
95
+ include Feature::Instance
96
+
97
+ Feature::MixinCollection::GLOBAL.for_type(Feature::Geometry).include_in_class(self)
98
+
99
+
100
+ def initialize(factory_, fg_geom_, klasses_)
101
+ @factory = factory_
102
+ @fg_geom = fg_geom_
103
+ @_klasses = klasses_
104
+ fg_geom_.srid = factory_.srid
105
+ end
106
+
107
+
108
+ def inspect
109
+ "#<#{self.class}:0x#{object_id.to_s(16)} #{as_text.inspect}>"
110
+ end
111
+
112
+
113
+ attr_reader :factory
114
+ attr_reader :fg_geom
115
+
116
+ attr_reader :_klasses # :nodoc:
117
+
118
+
119
+ def initialize_copy(orig_)
120
+ @factory = orig_.factory
121
+ @fg_geom = orig_.fg_geom.clone
122
+ @fg_geom.srid = orig_.fg_geom.srid
123
+ @_klasses = orig_._klasses
124
+ end
125
+
126
+
127
+ def srid
128
+ @fg_geom.srid
129
+ end
130
+
131
+
132
+ def dimension
133
+ FFIUtils.compute_dimension(@fg_geom)
134
+ end
135
+
136
+
137
+ def geometry_type
138
+ Feature::Geometry
139
+ end
140
+
141
+
142
+ def envelope
143
+ fg_geom_ = @fg_geom.envelope
144
+ # GEOS returns an "empty" point for an empty collection's envelope.
145
+ # We don't allow that type, so we replace it with an empty collection.
146
+ if fg_geom_.type_id == ::Geos::GeomTypes::GEOS_POINT && fg_geom_.empty?
147
+ fg_geom_ = ::Geos::Utils.create_geometry_collection
148
+ end
149
+ @factory.wrap_fg_geom(fg_geom_)
150
+ end
151
+
152
+
153
+ def boundary
154
+ if self.class == FFIGeometryCollectionImpl
155
+ nil
156
+ else
157
+ @factory.wrap_fg_geom(@fg_geom.boundary)
158
+ end
159
+ end
160
+
161
+
162
+ def as_text
163
+ @factory._generate_wkt(self)
164
+ end
165
+ alias_method :to_s, :as_text
166
+
167
+
168
+ def as_binary
169
+ @factory._generate_wkb(self)
170
+ end
171
+
172
+
173
+ def is_empty?
174
+ @fg_geom.empty?
175
+ end
176
+
177
+
178
+ def is_simple?
179
+ @fg_geom.simple?
180
+ end
181
+
182
+
183
+ def equals?(rhs_)
184
+ fg_ = factory._convert_to_fg_geometry(rhs_)
185
+ # GEOS has a bug where empty geometries are not spatially equal
186
+ # to each other. Work around this case first.
187
+ return true if fg_.empty? && @fg_geom.empty?
188
+ fg_ ? @fg_geom.eql?(fg_) : false
189
+ end
190
+ alias_method :==, :equals?
191
+
192
+
193
+ def disjoint?(rhs_)
194
+ fg_ = factory._convert_to_fg_geometry(rhs_)
195
+ fg_ ? @fg_geom.disjoint?(fg_) : false
196
+ end
197
+
198
+
199
+ def intersects?(rhs_)
200
+ fg_ = factory._convert_to_fg_geometry(rhs_)
201
+ fg_ ? @fg_geom.intersects?(fg_) : false
202
+ end
203
+
204
+
205
+ def touches?(rhs_)
206
+ fg_ = factory._convert_to_fg_geometry(rhs_)
207
+ fg_ ? @fg_geom.touches?(fg_) : false
208
+ end
209
+
210
+
211
+ def crosses?(rhs_)
212
+ fg_ = factory._convert_to_fg_geometry(rhs_)
213
+ fg_ ? @fg_geom.crosses?(fg_) : false
214
+ end
215
+
216
+
217
+ def within?(rhs_)
218
+ fg_ = factory._convert_to_fg_geometry(rhs_)
219
+ fg_ ? @fg_geom.within?(fg_) : false
220
+ end
221
+
222
+
223
+ def contains?(rhs_)
224
+ fg_ = factory._convert_to_fg_geometry(rhs_)
225
+ fg_ ? @fg_geom.contains?(fg_) : false
226
+ end
227
+
228
+
229
+ def overlaps?(rhs_)
230
+ fg_ = factory._convert_to_fg_geometry(rhs_)
231
+ fg_ ? @fg_geom.overlaps?(fg_) : false
232
+ end
233
+
234
+
235
+ def relate(rhs_, pattern_)
236
+ fg_ = factory._convert_to_fg_geometry(rhs_)
237
+ fg_ ? @fg_geom.relate_pattern(fg_, pattern_) : nil
238
+ end
239
+
240
+
241
+ def distance(rhs_)
242
+ fg_ = factory._convert_to_fg_geometry(rhs_)
243
+ fg_ ? @fg_geom.distance(fg_) : nil
244
+ end
245
+
246
+
247
+ def buffer(distance_)
248
+ @factory.wrap_fg_geom(@fg_geom.buffer(distance_, @factory.buffer_resolution))
249
+ end
250
+
251
+
252
+ def convex_hull
253
+ @factory.wrap_fg_geom(@fg_geom.convex_hull)
254
+ end
255
+
256
+
257
+ def intersection(rhs_)
258
+ fg_ = factory._convert_to_fg_geometry(rhs_)
259
+ fg_ ? @factory.wrap_fg_geom(@fg_geom.intersection(fg_)) : nil
260
+ end
261
+
262
+
263
+ def union(rhs_)
264
+ fg_ = factory._convert_to_fg_geometry(rhs_)
265
+ fg_ ? @factory.wrap_fg_geom(@fg_geom.union(fg_)) : nil
266
+ end
267
+
268
+
269
+ def difference(rhs_)
270
+ fg_ = factory._convert_to_fg_geometry(rhs_)
271
+ fg_ ? @factory.wrap_fg_geom(@fg_geom.difference(fg_)) : nil
272
+ end
273
+
274
+
275
+ def sym_difference(rhs_)
276
+ fg_ = factory._convert_to_fg_geometry(rhs_)
277
+ fg_ ? @factory.wrap_fg_geom(@fg_geom.sym_difference(fg_)) : nil
278
+ end
279
+
280
+
281
+ def _detach_fg_geom # :nodoc:
282
+ fg_ = @fg_geom
283
+ @fg_geom = nil
284
+ fg_
285
+ end
286
+
287
+
288
+ end
289
+
290
+
291
+ class FFIPointImpl < FFIGeometryImpl # :nodoc:
292
+
293
+ Feature::MixinCollection::GLOBAL.for_type(Feature::Point).include_in_class(self)
294
+
295
+
296
+ def x
297
+ @fg_geom.coord_seq.get_x(0)
298
+ end
299
+
300
+
301
+ def y
302
+ @fg_geom.coord_seq.get_y(0)
303
+ end
304
+
305
+
306
+ def z
307
+ if @factory.property(:has_z_coordinate)
308
+ @fg_geom.coord_seq.get_z(0)
309
+ else
310
+ nil
311
+ end
312
+ end
313
+
314
+
315
+ def m
316
+ if @factory.property(:has_m_coordinate)
317
+ @fg_geom.coord_seq.get_z(0)
318
+ else
319
+ nil
320
+ end
321
+ end
322
+
323
+
324
+ def geometry_type
325
+ Feature::Point
326
+ end
327
+
328
+
329
+ def eql?(rhs_)
330
+ rhs_.class == self.class && rhs_.factory.eql?(@factory) &&
331
+ FFIUtils.coord_seqs_equal?(rhs_.fg_geom.coord_seq, @fg_geom.coord_seq, @factory._has_3d)
332
+ end
333
+
334
+
335
+ end
336
+
337
+
338
+ class FFILineStringImpl < FFIGeometryImpl # :nodoc:
339
+
340
+
341
+ Feature::MixinCollection::GLOBAL.for_type(Feature::Curve).include_in_class(self)
342
+ Feature::MixinCollection::GLOBAL.for_type(Feature::LineString).include_in_class(self)
343
+
344
+
345
+ def geometry_type
346
+ Feature::LineString
347
+ end
348
+
349
+
350
+ def length
351
+ @fg_geom.length
352
+ end
353
+
354
+
355
+ def num_points
356
+ @fg_geom.num_points
357
+ end
358
+
359
+
360
+ def point_n(n_)
361
+ if n_ >= 0 && n_ < @fg_geom.num_points
362
+ coord_seq_ = @fg_geom.coord_seq
363
+ x_ = coord_seq_.get_x(n_)
364
+ y_ = coord_seq_.get_y(n_)
365
+ extra_ = @factory._has_3d ? [coord_seq_.get_z(n_)] : []
366
+ @factory.point(x_, y_, *extra_)
367
+ else
368
+ nil
369
+ end
370
+ end
371
+
372
+
373
+ def start_point
374
+ point_n(0)
375
+ end
376
+
377
+
378
+ def end_point
379
+ point_n(@fg_geom.num_points - 1)
380
+ end
381
+
382
+
383
+ def points
384
+ coord_seq_ = @fg_geom.coord_seq
385
+ has_3d_ = @factory._has_3d
386
+ ::Array.new(@fg_geom.num_points) do |n_|
387
+ x_ = coord_seq_.get_x(n_)
388
+ y_ = coord_seq_.get_y(n_)
389
+ extra_ = has_3d_ ? [coord_seq_.get_z(n_)] : []
390
+ @factory.point(x_, y_, *extra_)
391
+ end
392
+ end
393
+
394
+
395
+ def is_closed?
396
+ @fg_geom.closed?
397
+ end
398
+
399
+
400
+ def is_ring?
401
+ @fg_geom.ring?
402
+ end
403
+
404
+
405
+ def eql?(rhs_)
406
+ rhs_.class == self.class && rhs_.factory.eql?(@factory) &&
407
+ FFIUtils.coord_seqs_equal?(rhs_.fg_geom.coord_seq, @fg_geom.coord_seq, @factory._has_3d)
408
+ end
409
+
410
+
411
+ end
412
+
413
+
414
+ class FFILinearRingImpl < FFILineStringImpl # :nodoc:
415
+
416
+
417
+ Feature::MixinCollection::GLOBAL.for_type(Feature::LinearRing).include_in_class(self)
418
+
419
+
420
+ def geometry_type
421
+ Feature::LinearRing
422
+ end
423
+
424
+
425
+ end
426
+
427
+
428
+ class FFILineImpl < FFILineStringImpl # :nodoc:
429
+
430
+
431
+ Feature::MixinCollection::GLOBAL.for_type(Feature::Line).include_in_class(self)
432
+
433
+
434
+ def geometry_type
435
+ Feature::Line
436
+ end
437
+
438
+
439
+ end
440
+
441
+
442
+ class FFIPolygonImpl < FFIGeometryImpl # :nodoc:
443
+
444
+
445
+ Feature::MixinCollection::GLOBAL.for_type(Feature::Surface).include_in_class(self)
446
+ Feature::MixinCollection::GLOBAL.for_type(Feature::Polygon).include_in_class(self)
447
+
448
+
449
+ def geometry_type
450
+ Feature::Polygon
451
+ end
452
+
453
+
454
+ def area
455
+ @fg_geom.area
456
+ end
457
+
458
+
459
+ def centroid
460
+ @factory.wrap_fg_geom(@fg_geom.centroid, FFIPointImpl)
461
+ end
462
+
463
+
464
+ def point_on_surface
465
+ @factory.wrap_fg_geom(@fg_geom.point_on_surface, FFIPointImpl)
466
+ end
467
+
468
+
469
+ def exterior_ring
470
+ @factory.wrap_fg_geom(@fg_geom.exterior_ring, FFILinearRingImpl)
471
+ end
472
+
473
+
474
+ def num_interior_rings
475
+ @fg_geom.num_interior_rings
476
+ end
477
+
478
+
479
+ def interior_ring_n(n_)
480
+ if n_ >= 0 && n_ < @fg_geom.num_interior_rings
481
+ @factory.wrap_fg_geom(@fg_geom.interior_ring_n(n_), FFILinearRingImpl)
482
+ else
483
+ nil
484
+ end
485
+ end
486
+
487
+
488
+ def interior_rings
489
+ ::Array.new(@fg_geom.num_interior_rings) do |n_|
490
+ @factory.wrap_fg_geom(@fg_geom.interior_ring_n(n_), FFILinearRingImpl)
491
+ end
492
+ end
493
+
494
+
495
+ def eql?(rhs_)
496
+ if rhs_.class == self.class && rhs_.factory.eql?(@factory) &&
497
+ rhs_.exterior_ring.eql?(self.exterior_ring)
498
+ then
499
+ sn_ = @fg_geom.num_interior_rings
500
+ rn_ = rhs_.num_interior_rings
501
+ if sn_ == rn_
502
+ sn_.times do |i_|
503
+ return false unless interior_ring_n(i_).eql?(rhs_.interior_ring_n(i_))
504
+ end
505
+ return true
506
+ end
507
+ end
508
+ false
509
+ end
510
+
511
+
512
+ end
513
+
514
+
515
+ class FFIGeometryCollectionImpl < FFIGeometryImpl # :nodoc:
516
+
517
+
518
+ Feature::MixinCollection::GLOBAL.for_type(Feature::GeometryCollection).include_in_class(self)
519
+
520
+
521
+ def geometry_type
522
+ Feature::GeometryCollection
523
+ end
524
+
525
+
526
+ def eql?(rhs_)
527
+ if rhs_.class == self.class && rhs_.factory.eql?(@factory)
528
+ size_ = @fg_geom.num_geometries
529
+ if size_ == rhs_.num_geometries
530
+ size_.times do |n_|
531
+ return false unless geometry_n(n_).eql?(rhs_.geometry_n(n_))
532
+ end
533
+ return true
534
+ end
535
+ end
536
+ false
537
+ end
538
+
539
+
540
+ def num_geometries
541
+ @fg_geom.num_geometries
542
+ end
543
+ alias_method :size, :num_geometries
544
+
545
+
546
+ def geometry_n(n_)
547
+ if n_ >= 0 && n_ < @fg_geom.num_geometries
548
+ @factory.wrap_fg_geom(@fg_geom.get_geometry_n(n_),
549
+ @_klasses ? @_klasses[n_] : nil)
550
+ else
551
+ nil
552
+ end
553
+ end
554
+
555
+
556
+ def [](n_)
557
+ n_ += @fg_geom.num_geometries if n_ < 0
558
+ if n_ >= 0 && n_ < @fg_geom.num_geometries
559
+ @factory.wrap_fg_geom(@fg_geom.get_geometry_n(n_),
560
+ @_klasses ? @_klasses[n_] : nil)
561
+ else
562
+ nil
563
+ end
564
+ end
565
+
566
+
567
+ def each
568
+ @fg_geom.num_geometries.times do |n_|
569
+ yield @factory.wrap_fg_geom(@fg_geom.get_geometry_n(n_),
570
+ @_klasses ? @_klasses[n_] : nil)
571
+ end
572
+ end
573
+
574
+ include ::Enumerable
575
+
576
+
577
+ end
578
+
579
+
580
+ class FFIMultiPointImpl < FFIGeometryCollectionImpl # :nodoc:
581
+
582
+
583
+ Feature::MixinCollection::GLOBAL.for_type(Feature::MultiPoint).include_in_class(self)
584
+
585
+
586
+ def geometry_type
587
+ Feature::MultiPoint
588
+ end
589
+
590
+
591
+ end
592
+
593
+
594
+ class FFIMultiLineStringImpl < FFIGeometryCollectionImpl # :nodoc:
595
+
596
+
597
+ Feature::MixinCollection::GLOBAL.for_type(Feature::MultiCurve).include_in_class(self)
598
+ Feature::MixinCollection::GLOBAL.for_type(Feature::MultiLineString).include_in_class(self)
599
+
600
+
601
+ def geometry_type
602
+ Feature::MultiLineString
603
+ end
604
+
605
+
606
+ def length
607
+ @fg_geom.length
608
+ end
609
+
610
+
611
+ def is_closed?
612
+ size_ = num_geometries
613
+ size_.times do |n_|
614
+ return false unless @fg_geom.get_geometry_n(n_).closed?
615
+ end
616
+ true
617
+ end
618
+
619
+
620
+ end
621
+
622
+
623
+ class FFIMultiPolygonImpl < FFIGeometryCollectionImpl # :nodoc:
624
+
625
+
626
+ Feature::MixinCollection::GLOBAL.for_type(Feature::MultiSurface).include_in_class(self)
627
+ Feature::MixinCollection::GLOBAL.for_type(Feature::MultiPolygon).include_in_class(self)
628
+
629
+
630
+ def geometry_type
631
+ Feature::MultiPolygon
632
+ end
633
+
634
+
635
+ def area
636
+ @fg_geom.area
637
+ end
638
+
639
+
640
+ def centroid
641
+ @factory.wrap_fg_geom(@fg_geom.centroid, FFIPointImpl)
642
+ end
643
+
644
+
645
+ def point_on_surface
646
+ @factory.wrap_fg_geom(@fg_geom.point_on_surface, FFIPointImpl)
647
+ end
648
+
649
+
650
+ end
651
+
652
+
653
+ end
654
+
655
+ end