rgeo 0.2.9 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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