rgeo 0.1.18 → 0.1.19

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -42,12 +42,12 @@ module RGeo
42
42
 
43
43
 
44
44
  # Creates and returns a cartesian factory of the preferred
45
- # implementation.
45
+ # Cartesian implementation.
46
46
  #
47
47
  # The actual implementation returned depends on which ruby
48
48
  # interpreter is running and what libraries are available.
49
49
  # RGeo will try to provide a fully-functional and performant
50
- # implementation if possible. If not, the simple cartesian
50
+ # implementation if possible. If not, the simple Cartesian
51
51
  # implementation will be returned.
52
52
  #
53
53
  # The given options are passed to the factory's constructor.
@@ -64,8 +64,25 @@ module RGeo
64
64
  alias_method :factory, :preferred_factory
65
65
 
66
66
 
67
- # Returns a factory for the simple cartesian implementation.
68
- # This implementation is always available.
67
+ # Returns a factory for the simple Cartesian implementation. This
68
+ # implementation provides all SFS 1.1 types, and also allows Z and
69
+ # M coordinates. It does not depend on external libraries, and is
70
+ # thus always available, but it does not implement many of the more
71
+ # advanced geometric operations. These limitations are:
72
+ #
73
+ # * Relational operators such as Features::Geometry#intersects? are
74
+ # not implemented for most types.
75
+ # * Relational constructors such as Features::Geometry#union are
76
+ # not implemented for most types.
77
+ # * Buffer and convex hull calculations are not implemented for most
78
+ # types. Boundaries are available except for GeometryCollection.
79
+ # * Length calculations are available, but areas are not. Distances
80
+ # are available only between points.
81
+ # * Equality and simplicity evaluation are implemented for some but
82
+ # not all types.
83
+ # * Assertions for polygons and multipolygons are not implemented.
84
+ #
85
+ # Unimplemented operations will return nil if invoked.
69
86
  #
70
87
  # Options include:
71
88
  #
@@ -115,21 +115,6 @@ module RGeo
115
115
  end
116
116
 
117
117
 
118
- # Cast this geometry to the given type (which must be one of the
119
- # type modules in the Features module) and return the resulting
120
- # object. Returns nil if the cast fails because the types are not
121
- # compatible or the object does not satisfy the assertions for the
122
- # new type.
123
- #
124
- # Generally, this is only useful for casting general classes to
125
- # subclasses; e.g. a GeometryCollection to a MultiPoint, or a
126
- # LineString to a LinearRing.
127
-
128
- def cast(type_)
129
- raise Errors::MethodUnimplemented
130
- end
131
-
132
-
133
118
  # Returns true if this geometric object is objectively equivalent
134
119
  # to the given object.
135
120
 
@@ -44,13 +44,32 @@ module RGeo
44
44
  # Geographic features provided by this factory perform calculations
45
45
  # assuming a spherical earth. In other words, geodesics are treated
46
46
  # as great circle arcs, and size and geometric calculations are
47
- # treated accordingly. Distance and area calculations report results
48
- # in meters. This makes this implementation ideal for everyday
47
+ # treated accordingly. Distance calculations report results in
48
+ # meters. This makes this implementation ideal for everyday
49
49
  # calculations on the globe where accuracy within about 0.5 percent
50
50
  # is sufficient.
51
51
  #
52
- # Currently, this implementation is incomplete. Basic input/output
53
- # and a few geodesic functions are implemented, but many return nil.
52
+ # === Limitations
53
+ #
54
+ # This implementation does not implement many of the more advanced
55
+ # geometric operations. In particular:
56
+ #
57
+ # * Relational operators such as Features::Geometry#intersects? are
58
+ # not implemented for most types.
59
+ # * Relational constructors such as Features::Geometry#union are
60
+ # not implemented for most types.
61
+ # * Buffer, convex hull, and envelope calculations are not
62
+ # implemented for most types. Boundaries are available except for
63
+ # GeometryCollection.
64
+ # * Length calculations are available, but areas are not. Distances
65
+ # are available only between points.
66
+ # * Equality and simplicity evaluation are implemented for some but
67
+ # not all types.
68
+ # * Assertions for polygons and multipolygons are not implemented.
69
+ #
70
+ # Unimplemented operations will return nil if invoked.
71
+ #
72
+ # === SRID for simple_spherical
54
73
  #
55
74
  # Simple_spherical features report SRID=4326, indicating EPSG 4326
56
75
  # (i.e. the WGS84 spheroid and the lat/lon system commonly used by
@@ -72,7 +91,10 @@ module RGeo
72
91
  # than those generated by, e.g., PostGIS (unless you direct PostGIS
73
92
  # to use spherical geodesics).
74
93
  #
75
- # Options include:
94
+ # === Options
95
+ #
96
+ # You may use the following options when creating a simple_spherical
97
+ # factory:
76
98
  #
77
99
  # <tt>:lenient_multi_polygon_assertions</tt>::
78
100
  # If set to true, assertion checking on MultiPolygon is disabled.
@@ -119,6 +141,8 @@ module RGeo
119
141
  # Distance and area computations return results in meters, whereas
120
142
  # all coordinates are represented in degrees latitude and longitude.
121
143
  #
144
+ # === About the coordinate system
145
+ #
122
146
  # This is not a true projected spatial reference: point coordinates
123
147
  # are still represented in degrees latitude and longitude. However,
124
148
  # computations are done in the projected spatial reference. (That
@@ -149,7 +173,10 @@ module RGeo
149
173
  # visualization APIs, so we've decided to fudge on this in the
150
174
  # interest of being true to our expected application use cases.
151
175
  #
152
- # Options include:
176
+ # === Options
177
+ #
178
+ # You may use the following options when creating a simple_mercator
179
+ # factory:
153
180
  #
154
181
  # <tt>:lenient_multi_polygon_assertions</tt>::
155
182
  # If set to true, assertion checking on MultiPolygon is disabled.
@@ -46,8 +46,8 @@ module RGeo
46
46
 
47
47
  include ::RGeo::Features::Point
48
48
  include ::RGeo::ImplHelpers::BasicGeometryMethods
49
- include ::RGeo::Geography::SimpleMercator::GeometryMethods
50
49
  include ::RGeo::ImplHelpers::BasicPointMethods
50
+ include ::RGeo::Geography::SimpleMercator::GeometryMethods
51
51
 
52
52
 
53
53
  def _validate_geometry
@@ -70,17 +70,30 @@ module RGeo
70
70
  end
71
71
 
72
72
 
73
+ def canonical_x
74
+ x_ = @x % 360.0
75
+ x_ -= 360.0 if x_ >= 180.0
76
+ x_
77
+ end
78
+ alias_method :canonical_longitude, :canonical_x
79
+ alias_method :canonical_lon, :canonical_x
80
+
81
+
73
82
  def canonical_point
74
83
  if @x >= -180.0 && @x < 180.0
75
84
  self
76
85
  else
77
- x_ = @x % 360.0
78
- x_ -= 360.0 if x_ >= 180.0
79
- PointImpl.new(@factory, x_, @y)
86
+ PointImpl.new(@factory, canonical_x, @y)
80
87
  end
81
88
  end
82
89
 
83
90
 
91
+ alias_method :longitude, :x
92
+ alias_method :lon, :x
93
+ alias_method :latitude, :y
94
+ alias_method :lat, :y
95
+
96
+
84
97
  end
85
98
 
86
99
 
@@ -89,10 +102,10 @@ module RGeo
89
102
 
90
103
  include ::RGeo::Features::LineString
91
104
  include ::RGeo::ImplHelpers::BasicGeometryMethods
105
+ include ::RGeo::ImplHelpers::BasicLineStringMethods
92
106
  include ::RGeo::Geography::SimpleMercator::GeometryMethods
93
107
  include ::RGeo::Geography::SimpleMercator::NCurveMethods
94
108
  include ::RGeo::Geography::SimpleMercator::CurveMethods
95
- include ::RGeo::ImplHelpers::BasicLineStringMethods
96
109
  include ::RGeo::Geography::SimpleMercator::LineStringMethods
97
110
 
98
111
 
@@ -109,12 +122,12 @@ module RGeo
109
122
 
110
123
  include ::RGeo::Features::Line
111
124
  include ::RGeo::ImplHelpers::BasicGeometryMethods
125
+ include ::RGeo::ImplHelpers::BasicLineStringMethods
126
+ include ::RGeo::ImplHelpers::BasicLinearRingMethods
112
127
  include ::RGeo::Geography::SimpleMercator::GeometryMethods
113
128
  include ::RGeo::Geography::SimpleMercator::NCurveMethods
114
129
  include ::RGeo::Geography::SimpleMercator::CurveMethods
115
- include ::RGeo::ImplHelpers::BasicLineStringMethods
116
130
  include ::RGeo::Geography::SimpleMercator::LineStringMethods
117
- include ::RGeo::ImplHelpers::BasicLinearRingMethods
118
131
 
119
132
 
120
133
  def _make_projection(projection_factory_) # :nodoc:
@@ -130,12 +143,12 @@ module RGeo
130
143
 
131
144
  include ::RGeo::Features::Line
132
145
  include ::RGeo::ImplHelpers::BasicGeometryMethods
146
+ include ::RGeo::ImplHelpers::BasicLineStringMethods
147
+ include ::RGeo::ImplHelpers::BasicLineMethods
133
148
  include ::RGeo::Geography::SimpleMercator::GeometryMethods
134
149
  include ::RGeo::Geography::SimpleMercator::NCurveMethods
135
150
  include ::RGeo::Geography::SimpleMercator::CurveMethods
136
- include ::RGeo::ImplHelpers::BasicLineStringMethods
137
151
  include ::RGeo::Geography::SimpleMercator::LineStringMethods
138
- include ::RGeo::ImplHelpers::BasicLineMethods
139
152
 
140
153
 
141
154
  def _make_projection(projection_factory_) # :nodoc:
@@ -151,10 +164,10 @@ module RGeo
151
164
 
152
165
  include ::RGeo::Features::Polygon
153
166
  include ::RGeo::ImplHelpers::BasicGeometryMethods
167
+ include ::RGeo::ImplHelpers::BasicPolygonMethods
154
168
  include ::RGeo::Geography::SimpleMercator::GeometryMethods
155
169
  include ::RGeo::Geography::SimpleMercator::NSurfaceMethods
156
170
  include ::RGeo::Geography::SimpleMercator::SurfaceMethods
157
- include ::RGeo::ImplHelpers::BasicPolygonMethods
158
171
 
159
172
 
160
173
  def _validate_geometry
@@ -179,8 +192,8 @@ module RGeo
179
192
 
180
193
  include ::RGeo::Features::GeometryCollection
181
194
  include ::RGeo::ImplHelpers::BasicGeometryMethods
182
- include ::RGeo::Geography::SimpleMercator::GeometryMethods
183
195
  include ::RGeo::ImplHelpers::BasicGeometryCollectionMethods
196
+ include ::RGeo::Geography::SimpleMercator::GeometryMethods
184
197
  include ::RGeo::Geography::SimpleMercator::GeometryCollectionMethods
185
198
 
186
199
 
@@ -197,10 +210,10 @@ module RGeo
197
210
 
198
211
  include ::RGeo::Features::GeometryCollection
199
212
  include ::RGeo::ImplHelpers::BasicGeometryMethods
200
- include ::RGeo::Geography::SimpleMercator::GeometryMethods
201
213
  include ::RGeo::ImplHelpers::BasicGeometryCollectionMethods
202
- include ::RGeo::Geography::SimpleMercator::GeometryCollectionMethods
203
214
  include ::RGeo::ImplHelpers::BasicMultiPointMethods
215
+ include ::RGeo::Geography::SimpleMercator::GeometryMethods
216
+ include ::RGeo::Geography::SimpleMercator::GeometryCollectionMethods
204
217
 
205
218
 
206
219
  def _make_projection(projection_factory_) # :nodoc:
@@ -216,11 +229,11 @@ module RGeo
216
229
 
217
230
  include ::RGeo::Features::GeometryCollection
218
231
  include ::RGeo::ImplHelpers::BasicGeometryMethods
232
+ include ::RGeo::ImplHelpers::BasicGeometryCollectionMethods
233
+ include ::RGeo::ImplHelpers::BasicMultiLineStringMethods
219
234
  include ::RGeo::Geography::SimpleMercator::GeometryMethods
220
235
  include ::RGeo::Geography::SimpleMercator::NCurveMethods
221
- include ::RGeo::ImplHelpers::BasicGeometryCollectionMethods
222
236
  include ::RGeo::Geography::SimpleMercator::GeometryCollectionMethods
223
- include ::RGeo::ImplHelpers::BasicMultiLineStringMethods
224
237
 
225
238
 
226
239
  def _make_projection(projection_factory_) # :nodoc:
@@ -236,11 +249,11 @@ module RGeo
236
249
 
237
250
  include ::RGeo::Features::GeometryCollection
238
251
  include ::RGeo::ImplHelpers::BasicGeometryMethods
252
+ include ::RGeo::ImplHelpers::BasicGeometryCollectionMethods
253
+ include ::RGeo::ImplHelpers::BasicMultiPolygonMethods
239
254
  include ::RGeo::Geography::SimpleMercator::GeometryMethods
240
255
  include ::RGeo::Geography::SimpleMercator::NSurfaceMethods
241
- include ::RGeo::ImplHelpers::BasicGeometryCollectionMethods
242
256
  include ::RGeo::Geography::SimpleMercator::GeometryCollectionMethods
243
- include ::RGeo::ImplHelpers::BasicMultiPolygonMethods
244
257
 
245
258
 
246
259
  def _validate_geometry
@@ -144,7 +144,7 @@ module RGeo
144
144
  end
145
145
 
146
146
 
147
- def convex_hull()
147
+ def convex_hull
148
148
  factory.unproject(projection.convex_hull)
149
149
  end
150
150
 
@@ -46,8 +46,8 @@ module RGeo
46
46
 
47
47
  include ::RGeo::Features::Point
48
48
  include ::RGeo::ImplHelpers::BasicGeometryMethods
49
- include ::RGeo::Geography::SimpleSpherical::GeometryMethods
50
49
  include ::RGeo::ImplHelpers::BasicPointMethods
50
+ include ::RGeo::Geography::SimpleSpherical::GeometryMethods
51
51
 
52
52
 
53
53
  def _validate_geometry
@@ -75,6 +75,33 @@ module RGeo
75
75
  end
76
76
 
77
77
 
78
+ def equals?(rhs_)
79
+ return false unless rhs_.is_a?(self.class) && rhs_.factory == self.factory
80
+ case rhs_
81
+ when Features::Point
82
+ if @y == 90
83
+ rhs_.y == 90
84
+ elsif @y == -90
85
+ rhs_.y == -90
86
+ else
87
+ rhs_.x == @x && rhs_.y == @y
88
+ end
89
+ when Features::LineString
90
+ rhs_.num_points > 0 && rhs_.points.all?{ |elem_| equals?(elem_) }
91
+ when Features::GeometryCollection
92
+ rhs_.num_geometries > 0 && rhs_.all?{ |elem_| equals?(elem_) }
93
+ else
94
+ false
95
+ end
96
+ end
97
+
98
+
99
+ alias_method :longitude, :x
100
+ alias_method :lon, :x
101
+ alias_method :latitude, :y
102
+ alias_method :lat, :y
103
+
104
+
78
105
  end
79
106
 
80
107
 
@@ -83,8 +110,8 @@ module RGeo
83
110
 
84
111
  include ::RGeo::Features::LineString
85
112
  include ::RGeo::ImplHelpers::BasicGeometryMethods
86
- include ::RGeo::Geography::SimpleSpherical::GeometryMethods
87
113
  include ::RGeo::ImplHelpers::BasicLineStringMethods
114
+ include ::RGeo::Geography::SimpleSpherical::GeometryMethods
88
115
  include ::RGeo::Geography::SimpleSpherical::LineStringMethods
89
116
 
90
117
 
@@ -96,10 +123,10 @@ module RGeo
96
123
 
97
124
  include ::RGeo::Features::Line
98
125
  include ::RGeo::ImplHelpers::BasicGeometryMethods
99
- include ::RGeo::Geography::SimpleSpherical::GeometryMethods
100
126
  include ::RGeo::ImplHelpers::BasicLineStringMethods
101
- include ::RGeo::Geography::SimpleSpherical::LineStringMethods
102
127
  include ::RGeo::ImplHelpers::BasicLineMethods
128
+ include ::RGeo::Geography::SimpleSpherical::GeometryMethods
129
+ include ::RGeo::Geography::SimpleSpherical::LineStringMethods
103
130
 
104
131
 
105
132
  end
@@ -110,10 +137,10 @@ module RGeo
110
137
 
111
138
  include ::RGeo::Features::Line
112
139
  include ::RGeo::ImplHelpers::BasicGeometryMethods
113
- include ::RGeo::Geography::SimpleSpherical::GeometryMethods
114
140
  include ::RGeo::ImplHelpers::BasicLineStringMethods
115
- include ::RGeo::Geography::SimpleSpherical::LineStringMethods
116
141
  include ::RGeo::ImplHelpers::BasicLinearRingMethods
142
+ include ::RGeo::Geography::SimpleSpherical::GeometryMethods
143
+ include ::RGeo::Geography::SimpleSpherical::LineStringMethods
117
144
 
118
145
 
119
146
  end
@@ -124,8 +151,8 @@ module RGeo
124
151
 
125
152
  include ::RGeo::Features::Polygon
126
153
  include ::RGeo::ImplHelpers::BasicGeometryMethods
127
- include ::RGeo::Geography::SimpleSpherical::GeometryMethods
128
154
  include ::RGeo::ImplHelpers::BasicPolygonMethods
155
+ include ::RGeo::Geography::SimpleSpherical::GeometryMethods
129
156
 
130
157
 
131
158
  end
@@ -136,8 +163,8 @@ module RGeo
136
163
 
137
164
  include ::RGeo::Features::GeometryCollection
138
165
  include ::RGeo::ImplHelpers::BasicGeometryMethods
139
- include ::RGeo::Geography::SimpleSpherical::GeometryMethods
140
166
  include ::RGeo::ImplHelpers::BasicGeometryCollectionMethods
167
+ include ::RGeo::Geography::SimpleSpherical::GeometryMethods
141
168
 
142
169
 
143
170
  end
@@ -148,9 +175,9 @@ module RGeo
148
175
 
149
176
  include ::RGeo::Features::GeometryCollection
150
177
  include ::RGeo::ImplHelpers::BasicGeometryMethods
151
- include ::RGeo::Geography::SimpleSpherical::GeometryMethods
152
178
  include ::RGeo::ImplHelpers::BasicGeometryCollectionMethods
153
179
  include ::RGeo::ImplHelpers::BasicMultiPointMethods
180
+ include ::RGeo::Geography::SimpleSpherical::GeometryMethods
154
181
 
155
182
 
156
183
  end
@@ -161,9 +188,9 @@ module RGeo
161
188
 
162
189
  include ::RGeo::Features::GeometryCollection
163
190
  include ::RGeo::ImplHelpers::BasicGeometryMethods
164
- include ::RGeo::Geography::SimpleSpherical::GeometryMethods
165
191
  include ::RGeo::ImplHelpers::BasicGeometryCollectionMethods
166
192
  include ::RGeo::ImplHelpers::BasicMultiLineStringMethods
193
+ include ::RGeo::Geography::SimpleSpherical::GeometryMethods
167
194
 
168
195
 
169
196
  end
@@ -174,9 +201,9 @@ module RGeo
174
201
 
175
202
  include ::RGeo::Features::GeometryCollection
176
203
  include ::RGeo::ImplHelpers::BasicGeometryMethods
177
- include ::RGeo::Geography::SimpleSpherical::GeometryMethods
178
204
  include ::RGeo::ImplHelpers::BasicGeometryCollectionMethods
179
205
  include ::RGeo::ImplHelpers::BasicMultiPolygonMethods
206
+ include ::RGeo::Geography::SimpleSpherical::GeometryMethods
180
207
 
181
208
 
182
209
  end
data/lib/rgeo/geos.rb CHANGED
@@ -73,3 +73,5 @@ require 'rgeo/geos/factory'
73
73
  require 'rgeo/geos/interface'
74
74
  require 'rgeo/geos/geos_c_impl'
75
75
  require 'rgeo/geos/impl_additions'
76
+ require 'rgeo/geos/zm_factory'
77
+ require 'rgeo/geos/zm_impl'
@@ -43,6 +43,7 @@ module RGeo
43
43
 
44
44
  class Factory
45
45
 
46
+
46
47
  include Features::Factory::Instance
47
48
 
48
49
 
@@ -65,7 +66,8 @@ module RGeo
65
66
  end
66
67
  buffer_resolution_ = opts_[:buffer_resolution].to_i
67
68
  buffer_resolution_ = 1 if buffer_resolution_ < 1
68
- _create(flags_, opts_[:srid].to_i, buffer_resolution_)
69
+ result_ = _create(flags_, opts_[:srid].to_i, buffer_resolution_)
70
+ result_
69
71
  end
70
72
  alias_method :new, :create
71
73
 
@@ -73,6 +75,19 @@ module RGeo
73
75
  end
74
76
 
75
77
 
78
+ def inspect # :nodoc:
79
+ "#<#{self.class}:0x#{object_id.to_s(16)} srid=#{_srid} bufres=#{_buffer_resolution} flags=#{_flags}>"
80
+ end
81
+
82
+
83
+ # Factory equivalence test.
84
+
85
+ def eql?(rhs_)
86
+ rhs_.is_a?(Factory) && rhs_.srid == _srid && rhs_._buffer_resolution == _buffer_resolution && rhs_._flags == _flags
87
+ end
88
+ alias_method :==, :eql?
89
+
90
+
76
91
  # Returns the SRID of geometries created by this factory.
77
92
 
78
93
  def srid
@@ -95,14 +110,6 @@ module RGeo
95
110
  end
96
111
 
97
112
 
98
- # Factory equivalence test.
99
-
100
- def eql?(rhs_)
101
- rhs_.is_a?(Factory) && rhs_.srid == _srid && rhs_._buffer_resolution == _buffer_resolution && rhs_._flags == _flags
102
- end
103
- alias_method :==, :eql?
104
-
105
-
106
113
  # See ::RGeo::Features::Factory#has_capability?
107
114
 
108
115
  def has_capability?(name_)
@@ -211,24 +218,33 @@ module RGeo
211
218
  return nil unless Geos.supported?
212
219
  keep_subtype_ = flags_[:keep_subtype]
213
220
  force_new_ = flags_[:force_new]
214
- if GeometryImpl === original_
215
- type_ = original_.geometry_type
216
- ntype_ = type_ if keep_subtype_ && type_.include?(ntype_)
217
- if original_.factory != self && ntype_ == type_
221
+ type_ = original_.geometry_type
222
+ ntype_ = type_ if keep_subtype_ && type_.include?(ntype_)
223
+ case original_
224
+ when GeometryImpl
225
+ # Optimization if we're just changing factories, but the
226
+ # factories are zm-compatible.
227
+ if original_.factory != self && ntype_ == type_ &&
228
+ original_.factory._flags & 0x6 == _flags & 0x6
229
+ then
218
230
  result_ = original_.dup
219
231
  result_._set_factory(self)
220
232
  return result_
221
233
  end
234
+ # LineString conversion optimization.
222
235
  if (original_.factory != self || ntype_ != type_) &&
223
- (type_ == Features::LineString || type_.include?(Features::LineString))
236
+ original_.factory._flags & 0x6 == _flags & 0x6 &&
237
+ type_.subtype_of?(Features::LineString) && ntype_.subtype_of?(Features::LineString)
224
238
  then
225
- if ntype_ == Features::LineString
226
- return LineStringImpl._copy_from(self, original_)
227
- elsif ntype_ == Features::Line
228
- return LineImpl._copy_from(self, original_)
229
- elsif ntype_ == Features::LinearRing
230
- return LinearRingImpl._copy_from(self, original_)
231
- end
239
+ return IMPL_CLASSES[ntype_]._copy_from(self, original_)
240
+ end
241
+ when ZMGeometryImpl
242
+ # Optimization for just removing a coordinate from an otherwise
243
+ # compatible factory
244
+ if _flags & 0x6 == 0x2 && self == original_.factory.z_factory
245
+ return Features.cast(original_.z_geometry, ntype_, flags_)
246
+ elsif _flags & 0x6 == 0x4 && self == original_.factory.m_factory
247
+ return Features.cast(original_.m_geometry, ntype_, flags_)
232
248
  end
233
249
  end
234
250
  false