rgeo 0.1.18 → 0.1.19

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 (50) hide show
  1. data/History.rdoc +11 -0
  2. data/README.rdoc +17 -30
  3. data/Version +1 -1
  4. data/ext/geos_c_impl/factory.c +4 -9
  5. data/ext/geos_c_impl/factory.h +8 -8
  6. data/ext/geos_c_impl/geometry.c +19 -2
  7. data/ext/geos_c_impl/geometry_collection.c +1 -1
  8. data/ext/geos_c_impl/polygon.c +2 -2
  9. data/lib/active_record/connection_adapters/mysql2spatial_adapter.rb +8 -6
  10. data/lib/active_record/connection_adapters/mysqlspatial_adapter.rb +8 -6
  11. data/lib/rgeo/active_record/arel_modifications.rb +4 -0
  12. data/lib/rgeo/active_record/base_modifications.rb +37 -2
  13. data/lib/rgeo/active_record/mysql_common.rb +2 -2
  14. data/lib/rgeo/cartesian.rb +6 -22
  15. data/lib/rgeo/cartesian/analysis.rb +3 -0
  16. data/lib/rgeo/cartesian/bounding_box.rb +337 -0
  17. data/lib/rgeo/cartesian/feature_classes.rb +11 -11
  18. data/lib/rgeo/cartesian/feature_methods.rb +5 -0
  19. data/lib/rgeo/cartesian/interface.rb +21 -4
  20. data/lib/rgeo/features/geometry.rb +0 -15
  21. data/lib/rgeo/geography/interface.rb +33 -6
  22. data/lib/rgeo/geography/simple_mercator/feature_classes.rb +30 -17
  23. data/lib/rgeo/geography/simple_mercator/feature_methods.rb +1 -1
  24. data/lib/rgeo/geography/simple_spherical/feature_classes.rb +38 -11
  25. data/lib/rgeo/geos.rb +2 -0
  26. data/lib/rgeo/geos/factory.rb +37 -21
  27. data/lib/rgeo/geos/impl_additions.rb +20 -0
  28. data/lib/rgeo/geos/interface.rb +17 -8
  29. data/lib/rgeo/geos/zm_factory.rb +241 -0
  30. data/lib/rgeo/geos/zm_impl.rb +432 -0
  31. data/lib/rgeo/impl_helpers/basic_geometry_collection_methods.rb +39 -0
  32. data/lib/rgeo/impl_helpers/basic_geometry_methods.rb +0 -5
  33. data/lib/rgeo/impl_helpers/basic_line_string_methods.rb +10 -1
  34. data/lib/rgeo/impl_helpers/basic_point_methods.rb +1 -13
  35. data/lib/rgeo/impl_helpers/basic_polygon_methods.rb +10 -0
  36. data/tests/common/geometry_collection_tests.rb +16 -0
  37. data/tests/common/point_tests.rb +27 -1
  38. data/tests/geos/tc_point.rb +2 -0
  39. data/tests/geos/tc_zmfactory.rb +85 -0
  40. data/tests/simple_cartesian/tc_geometry_collection.rb +1 -0
  41. data/tests/simple_cartesian/tc_point.rb +2 -1
  42. data/tests/simple_mercator/tc_point.rb +2 -0
  43. data/tests/simple_spherical/tc_geometry_collection.rb +2 -0
  44. data/tests/simple_spherical/tc_point.rb +2 -1
  45. data/tests/tc_oneoff.rb +0 -1
  46. data/tests/wkrep/tc_wkb_generator.rb +4 -4
  47. data/tests/wkrep/tc_wkb_parser.rb +2 -2
  48. data/tests/wkrep/tc_wkt_generator.rb +4 -4
  49. data/tests/wkrep/tc_wkt_parser.rb +5 -5
  50. metadata +23 -3
@@ -50,6 +50,26 @@ module RGeo
50
50
  end
51
51
 
52
52
 
53
+ class Factory
54
+
55
+
56
+ # :stopdoc:
57
+ IMPL_CLASSES = {
58
+ Features::Point => PointImpl,
59
+ Features::LineString => LineStringImpl,
60
+ Features::LinearRing => LinearRingImpl,
61
+ Features::Line => LineImpl,
62
+ Features::GeometryCollection => GeometryCollectionImpl,
63
+ Features::MultiPoint => MultiPointImpl,
64
+ Features::MultiLineString => MultiLineStringImpl,
65
+ Features::MultiPolygon => MultiPolygonImpl,
66
+ }
67
+ # :startdoc:
68
+
69
+
70
+ end
71
+
72
+
53
73
  end
54
74
 
55
75
  end
@@ -55,13 +55,20 @@ module RGeo
55
55
  # factory is a GEOS factory.
56
56
 
57
57
  def is_geos?(object_)
58
- supported? ? Factory === object_ || GeometryImpl === object_ : false
58
+ supported? && (Factory === object_ || GeometryImpl === object_ || ZMFactory === object_ || ZMGeometryImpl === object_)
59
59
  end
60
60
 
61
61
 
62
62
  # Returns a factory for the GEOS implementation.
63
63
  # Returns nil if the GEOS implementation is not supported.
64
64
  #
65
+ # Note that GEOS does not natively support 4-dimensional data
66
+ # (i.e. both z and m values). However, RGeo's GEOS wrapper does
67
+ # provide a 4-dimensional factory that utilizes an extra native
68
+ # GEOS object to handle the extra coordinate. Hence, a factory
69
+ # configured with both Z and M support will work, but will be
70
+ # slower than a 2-dimensional or 3-dimensional factory.
71
+ #
65
72
  # Options include:
66
73
  #
67
74
  # <tt>:lenient_multi_polygon_assertions</tt>::
@@ -83,17 +90,19 @@ module RGeo
83
90
  # Default is 0.
84
91
  # <tt>:support_z_coordinate</tt>::
85
92
  # Support <tt>z_coordinate</tt>. Default is false.
86
- # Note that GEOS factories cannot support both
87
- # <tt>z_coordinate</tt> and <tt>m_coordinate</tt>. They may at
88
- # most support one or the other.
89
93
  # <tt>:support_m_coordinate</tt>::
90
94
  # Support <tt>m_coordinate</tt>. Default is false.
91
- # Note that GEOS factories cannot support both
92
- # <tt>z_coordinate</tt> and <tt>m_coordinate</tt>. They may at
93
- # most support one or the other.
94
95
 
95
96
  def factory(opts_={})
96
- supported? ? Factory.create(opts_) : nil
97
+ if supported?
98
+ if opts_[:support_z_coordinate] && opts_[:support_m_coordinate]
99
+ ZMFactory.new(opts_)
100
+ else
101
+ Factory.create(opts_)
102
+ end
103
+ else
104
+ nil
105
+ end
97
106
  end
98
107
 
99
108
 
@@ -0,0 +1,241 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # GEOS zm factory 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
+ # A factory for Geos that handles both Z and M.
43
+
44
+ class ZMFactory
45
+
46
+ include Features::Factory::Instance
47
+
48
+
49
+ class << self
50
+
51
+
52
+ # Create a new factory. Returns nil if the GEOS implementation is
53
+ # not supported.
54
+
55
+ def create(opts_={})
56
+ return nil unless Geos.supported?
57
+ new(opts_)
58
+ end
59
+
60
+
61
+ end
62
+
63
+
64
+ def initialize(opts_={}) # :nodoc:
65
+ @zfactory = Factory.create(:support_z_coordinate => true, :lenient_multi_polygon_assertions => opts_[:lenient_multi_polygon_assertions], :buffer_resolution => opts_[:buffer_resolution], :srid => opts_[:srid])
66
+ @mfactory = Factory.create(:support_m_coordinate => true, :lenient_multi_polygon_assertions => opts_[:lenient_multi_polygon_assertions], :buffer_resolution => opts_[:buffer_resolution], :srid => opts_[:srid])
67
+ end
68
+
69
+
70
+ # Returns the SRID of geometries created by this factory.
71
+
72
+ def srid
73
+ @zfactory._srid
74
+ end
75
+
76
+
77
+ # Returns the resolution used by buffer calculations on geometries
78
+ # created by this factory
79
+
80
+ def buffer_resolution
81
+ @zfactory._buffer_resolution
82
+ end
83
+
84
+
85
+ # Returns true if this factory is lenient with MultiPolygon assertions
86
+
87
+ def lenient_multi_polygon_assertions?
88
+ @zfactory.lenient_multi_polygon_assertions?
89
+ end
90
+
91
+
92
+ # Returns the z-only factory corresponding to this factory.
93
+
94
+ def z_factory
95
+ @zfactory
96
+ end
97
+
98
+
99
+ # Returns the m-only factory corresponding to this factory.
100
+
101
+ def m_factory
102
+ @mfactory
103
+ end
104
+
105
+
106
+ # Factory equivalence test.
107
+
108
+ def eql?(rhs_)
109
+ rhs_.is_a?(ZMFactory) && rhs_.z_factory == @zfactory
110
+ end
111
+ alias_method :==, :eql?
112
+
113
+
114
+ # See ::RGeo::Features::Factory#has_capability?
115
+
116
+ def has_capability?(name_)
117
+ case name_
118
+ when :z_coordinate, :m_coordinate
119
+ true
120
+ else
121
+ @zfactory.has_capability?(name_)
122
+ end
123
+ end
124
+
125
+
126
+ # See ::RGeo::Features::Factory#parse_wkt
127
+
128
+ def parse_wkt(str_)
129
+ WKRep::WKTParser.new(:default_factory => self).parse(str_)
130
+ end
131
+
132
+
133
+ # See ::RGeo::Features::Factory#parse_wkb
134
+
135
+ def parse_wkb(str_)
136
+ WKRep::WKBParser.new(:default_factory => self).parse(str_)
137
+ end
138
+
139
+
140
+ # See ::RGeo::Features::Factory#point
141
+
142
+ def point(x_, y_, z_=0, m_=0)
143
+ ZMPointImpl.create(self, @zfactory.point(x_, y_, z_), @mfactory.point(x_, y_, m_))
144
+ end
145
+
146
+
147
+ # See ::RGeo::Features::Factory#line_string
148
+
149
+ def line_string(points_)
150
+ ZMLineStringImpl.create(self, @zfactory.line_string(points_), @mfactory.line_string(points_))
151
+ end
152
+
153
+
154
+ # See ::RGeo::Features::Factory#line
155
+
156
+ def line(start_, end_)
157
+ ZMLineStringImpl.create(self, @zfactory.line(start_, end_), @mfactory.line(start_, end_))
158
+ end
159
+
160
+
161
+ # See ::RGeo::Features::Factory#linear_ring
162
+
163
+ def linear_ring(points_)
164
+ ZMLineStringImpl.create(self, @zfactory.linear_ring(points_), @mfactory.linear_ring(points_))
165
+ end
166
+
167
+
168
+ # See ::RGeo::Features::Factory#polygon
169
+
170
+ def polygon(outer_ring_, inner_rings_=nil)
171
+ ZMPolygonImpl.create(self, @zfactory.polygon(outer_ring_, inner_rings_), @mfactory.polygon(outer_ring_, inner_rings_))
172
+ end
173
+
174
+
175
+ # See ::RGeo::Features::Factory#collection
176
+
177
+ def collection(elems_)
178
+ ZMGeometryCollectionImpl.create(self, @zfactory.collection(elems_), @mfactory.collection(elems_))
179
+ end
180
+
181
+
182
+ # See ::RGeo::Features::Factory#multi_point
183
+
184
+ def multi_point(elems_)
185
+ ZMGeometryCollectionImpl.create(self, @zfactory.multi_point(elems_), @mfactory.multi_point(elems_))
186
+ end
187
+
188
+
189
+ # See ::RGeo::Features::Factory#multi_line_string
190
+
191
+ def multi_line_string(elems_)
192
+ ZMMultiLineStringImpl.create(self, @zfactory.multi_line_string(elems_), @mfactory.multi_line_string(elems_))
193
+ end
194
+
195
+
196
+ # See ::RGeo::Features::Factory#multi_polygon
197
+
198
+ def multi_polygon(elems_)
199
+ ZMMultiPolygonImpl.create(self, @zfactory.multi_polygon(elems_), @mfactory.multi_polygon(elems_))
200
+ end
201
+
202
+
203
+ # See ::RGeo::Features::Factory#override_cast
204
+
205
+ def override_cast(original_, ntype_, flags_)
206
+ return nil unless Geos.supported?
207
+ keep_subtype_ = flags_[:keep_subtype]
208
+ force_new_ = flags_[:force_new]
209
+ type_ = original_.geometry_type
210
+ ntype_ = type_ if keep_subtype_ && type_.include?(ntype_)
211
+ case original_
212
+ when ZMGeometryImpl
213
+ # Optimization if we're just changing factories, but to
214
+ # another ZM factory.
215
+ if original_.factory != self && ntype_ == type_
216
+ zresult_ = original_.z_geometry.dup
217
+ zresult_._set_factory(@zfactory)
218
+ mresult_ = original_.m_geometry.dup
219
+ mresult_._set_factory(@mfactory)
220
+ return original_.class.create(self, zresult_, mresult_)
221
+ end
222
+ # LineString conversion optimization.
223
+ if (original_.factory != self || ntype_ != type_) &&
224
+ type_.subtype_of?(Features::LineString) && ntype_.subtype_of?(Features:LineString)
225
+ then
226
+ klass_ = Factory::IMPL_CLASSES[ntype_]
227
+ zresult_ = klass_._copy_from(@zfactory, original_.z_geometry)
228
+ mresult_ = klass_._copy_from(@mfactory, original_.m_geometry)
229
+ return ZMLineStringImpl.create(self, zresult_, mresult_)
230
+ end
231
+ end
232
+ false
233
+ end
234
+
235
+
236
+ end
237
+
238
+
239
+ end
240
+
241
+ end
@@ -0,0 +1,432 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # GEOS implementation additions written in Ruby
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
+ class ZMGeometryImpl # :nodoc:
43
+
44
+ include Features::Type::Instance
45
+
46
+
47
+ def initialize(factory_, zgeometry_, mgeometry_)
48
+ @factory = factory_
49
+ @zgeometry = zgeometry_
50
+ @mgeometry = mgeometry_
51
+ end
52
+
53
+
54
+ def inspect # :nodoc:
55
+ "#<#{self.class}:0x#{object_id.to_s(16)} #{as_text.inspect}>"
56
+ end
57
+
58
+ def to_s # :nodoc:
59
+ as_text
60
+ end
61
+
62
+
63
+ def factory
64
+ @factory
65
+ end
66
+
67
+
68
+ def z_geometry
69
+ @zgeometry
70
+ end
71
+
72
+
73
+ def m_geometry
74
+ @mgeometry
75
+ end
76
+
77
+
78
+ def eql?(rhs_)
79
+ rhs_.is_a?(self.class) && @factory.eql?(rhs_.factory) && @zgeometry.eql?(rhs_.z_geometry) && @mgeometry.eql?(rhs_.m_geometry)
80
+ end
81
+
82
+
83
+ def dimension
84
+ @zgeometry.dimension
85
+ end
86
+
87
+
88
+ def geometry_type
89
+ @zgeometry.geometry_type
90
+ end
91
+
92
+
93
+ def srid
94
+ @factory.srid
95
+ end
96
+
97
+
98
+ def envelope
99
+ ZMGeometryImpl.create(@factory, @zgeometry.envelope, @mgeometry.envelope)
100
+ end
101
+
102
+
103
+ def as_text
104
+ WKRep::WKTGenerator.new.generate(self)
105
+ end
106
+
107
+
108
+ def as_binary
109
+ WKRep::WKBGenerator.new.generate(self)
110
+ end
111
+
112
+
113
+ def is_empty?
114
+ @zgeometry.is_empty?
115
+ end
116
+
117
+
118
+ def is_simple?
119
+ @zgeometry.is_simple?
120
+ end
121
+
122
+
123
+ def boundary
124
+ ZMGeometryImpl.create(@factory, @zgeometry.boundary, @mgeometry.boundary)
125
+ end
126
+
127
+
128
+ def equals?(rhs_)
129
+ @zgeometry.equals?(rhs_)
130
+ end
131
+
132
+
133
+ def disjoint?(rhs_)
134
+ @zgeometry.disjoint?(rhs_)
135
+ end
136
+
137
+
138
+ def intersects?(rhs_)
139
+ @zgeometry.intersects?(rhs_)
140
+ end
141
+
142
+
143
+ def touches?(rhs_)
144
+ @zgeometry.touches?(rhs_)
145
+ end
146
+
147
+
148
+ def crosses?(rhs_)
149
+ @zgeometry.crosses?(rhs_)
150
+ end
151
+
152
+
153
+ def within?(rhs_)
154
+ @zgeometry.within?(rhs_)
155
+ end
156
+
157
+
158
+ def contains?(rhs_)
159
+ @zgeometry.contains?(rhs_)
160
+ end
161
+
162
+
163
+ def overlaps?(rhs_)
164
+ @zgeometry.overlaps?(rhs_)
165
+ end
166
+
167
+
168
+ def relate(rhs_, pattern_)
169
+ @zgeometry.relate(rhs_, pattern_)
170
+ end
171
+
172
+
173
+ def distance(rhs_)
174
+ @zgeometry.distance(rhs_)
175
+ end
176
+
177
+
178
+ def buffer(distance_)
179
+ ZMGeometryImpl.create(@factory, @zgeometry.buffer(distance_), @mgeometry.buffer(distance_))
180
+ end
181
+
182
+
183
+ def convex_hull
184
+ ZMGeometryImpl.create(@factory, @zgeometry.convex_hull, @mgeometry.convex_hull)
185
+ end
186
+
187
+
188
+ def intersection(rhs_)
189
+ ZMGeometryImpl.create(@factory, @zgeometry.intersection(rhs_), @mgeometry.intersection(rhs_))
190
+ end
191
+
192
+
193
+ def union(rhs_)
194
+ ZMGeometryImpl.create(@factory, @zgeometry.union(rhs_), @mgeometry.union(rhs_))
195
+ end
196
+
197
+
198
+ def difference(rhs_)
199
+ ZMGeometryImpl.create(@factory, @zgeometry.difference(rhs_), @mgeometry.difference(rhs_))
200
+ end
201
+
202
+
203
+ def sym_difference(rhs_)
204
+ ZMGeometryImpl.create(@factory, @zgeometry.sym_difference(rhs_), @mgeometry.sym_difference(rhs_))
205
+ end
206
+
207
+
208
+ alias_method :==, :equals?
209
+ alias_method :-, :difference
210
+ alias_method :+, :union
211
+ alias_method :*, :intersection
212
+
213
+ end
214
+
215
+
216
+ class ZMPointImpl < ZMGeometryImpl # :nodoc:
217
+
218
+
219
+ def x
220
+ @zgeometry.x
221
+ end
222
+
223
+
224
+ def y
225
+ @zgeometry.y
226
+ end
227
+
228
+
229
+ def z
230
+ @zgeometry.z
231
+ end
232
+
233
+
234
+ def m
235
+ @mgeometry.m
236
+ end
237
+
238
+
239
+ end
240
+
241
+
242
+ class ZMLineStringImpl < ZMGeometryImpl # :nodoc:
243
+
244
+
245
+ def length
246
+ @zgeometry.length
247
+ end
248
+
249
+
250
+ def start_point
251
+ point_n(0)
252
+ end
253
+
254
+
255
+ def end_point
256
+ point_n(num_points - 1)
257
+ end
258
+
259
+
260
+ def is_closed?
261
+ @zgeometry.is_closed?
262
+ end
263
+
264
+
265
+ def is_ring?
266
+ @zgeometry.is_ring?
267
+ end
268
+
269
+
270
+ def num_points
271
+ @zgeometry.num_points
272
+ end
273
+
274
+
275
+ def point_n(n_)
276
+ ZMPointImpl.create(@factory, @zgeometry.point_n(n_), @mgeometry.point_n(n_))
277
+ end
278
+
279
+
280
+ def points
281
+ result_ = []
282
+ zpoints_ = @zgeometry.points
283
+ mpoints_ = @mgeometry.points
284
+ zpoints_.size.times do |i_|
285
+ result_ << ZMPointImpl.create(@factory, zpoints_[i_], mpoints_[i_])
286
+ end
287
+ result_
288
+ end
289
+
290
+
291
+ end
292
+
293
+
294
+ class ZMPolygonImpl < ZMGeometryImpl # :nodoc:
295
+
296
+
297
+ def area
298
+ @zgeometry.area
299
+ end
300
+
301
+
302
+ def centroid
303
+ ZMPointImpl.create(@factory, @zgeometry.centroid, @mgeometry.centroid)
304
+ end
305
+
306
+
307
+ def point_on_surface
308
+ ZMPointImpl.create(@factory, @zgeometry.centroid, @mgeometry.centroid)
309
+ end
310
+
311
+
312
+ def exterior_ring
313
+ ZMLineStringImpl.create(@factory, @zgeometry.exterior_ring, @mgeometry.exterior_ring)
314
+ end
315
+
316
+
317
+ def num_interior_rings
318
+ @zgeometry.num_interior_rings
319
+ end
320
+
321
+
322
+ def interior_ring_n(n_)
323
+ ZMLineStringImpl.create(@factory, @zgeometry.interior_ring_n(n_), @mgeometry.interior_ring_n(n_))
324
+ end
325
+
326
+
327
+ def interior_rings
328
+ result_ = []
329
+ zrings_ = @zgeometry.interior_rings
330
+ mrings_ = @mgeometry.interior_rings
331
+ zrings_.size.times do |i_|
332
+ result_ << ZMLineStringImpl.create(@factory, zrings_[i_], mrings_[i_])
333
+ end
334
+ result_
335
+ end
336
+
337
+
338
+ end
339
+
340
+
341
+ class ZMGeometryCollectionImpl < ZMGeometryImpl # :nodoc:
342
+
343
+
344
+ include ::Enumerable
345
+
346
+
347
+ def num_geometries
348
+ @zgeometry.num_geometries
349
+ end
350
+ alias_method :size, :num_geometries
351
+
352
+
353
+ def geometry_n(n_)
354
+ ZMGeometryImpl.create(@factory, @zgeometry.geometry_n(n_), @mgeometry.geometry_n(n_))
355
+ end
356
+ alias_method :[], :geometry_n
357
+
358
+
359
+ def each
360
+ num_geometries.times do |i_|
361
+ yield geometry_n(i_)
362
+ end
363
+ end
364
+
365
+
366
+ end
367
+
368
+
369
+ class ZMMultiLineStringImpl < ZMGeometryCollectionImpl # :nodoc:
370
+
371
+
372
+ def length
373
+ @zgeometry.length
374
+ end
375
+
376
+
377
+ def is_closed?
378
+ @zgeometry.is_closed?
379
+ end
380
+
381
+
382
+ end
383
+
384
+
385
+ class ZMMultiPolygonImpl < ZMGeometryCollectionImpl # :nodoc:
386
+
387
+
388
+ def area
389
+ @zgeometry.area
390
+ end
391
+
392
+
393
+ def centroid
394
+ ZMPointImpl.create(@factory, @zgeometry.centroid, @mgeometry.centroid)
395
+ end
396
+
397
+
398
+ def point_on_surface
399
+ ZMPointImpl.create(@factory, @zgeometry.centroid, @mgeometry.centroid)
400
+ end
401
+
402
+
403
+ end
404
+
405
+
406
+ class ZMGeometryImpl # :nodoc:
407
+
408
+ TYPE_KLASSES = {
409
+ Features::Point => ZMPointImpl,
410
+ Features::LineString => ZMLineStringImpl,
411
+ Features::Line => ZMLineStringImpl,
412
+ Features::LinearRing => ZMLineStringImpl,
413
+ Features::Polygon => ZMPolygonImpl,
414
+ Features::GeometryCollection => ZMGeometryCollectionImpl,
415
+ Features::MultiPoint => ZMGeometryCollectionImpl,
416
+ Features::MultiLineString => ZMMultiLineStringImpl,
417
+ Features::MultiPolygon => ZMMultiPolygonImpl,
418
+ }
419
+
420
+
421
+ def self.create(factory_, zgeometry_, mgeometry_)
422
+ klass_ = self == ZMGeometryImpl ? TYPE_KLASSES[zgeometry_.geometry_type] : self
423
+ klass_ && zgeometry_ && mgeometry_ ? klass_.new(factory_, zgeometry_, mgeometry_) : nil
424
+ end
425
+
426
+
427
+ end
428
+
429
+
430
+ end
431
+
432
+ end