rgeo 2.3.1 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +6 -0
  3. data/README.md +23 -14
  4. data/ext/geos_c_impl/analysis.c +30 -25
  5. data/ext/geos_c_impl/analysis.h +8 -7
  6. data/ext/geos_c_impl/coordinates.c +27 -21
  7. data/ext/geos_c_impl/coordinates.h +5 -2
  8. data/ext/geos_c_impl/errors.c +19 -10
  9. data/ext/geos_c_impl/errors.h +11 -4
  10. data/ext/geos_c_impl/extconf.rb +42 -28
  11. data/ext/geos_c_impl/factory.c +540 -451
  12. data/ext/geos_c_impl/factory.h +105 -95
  13. data/ext/geos_c_impl/geometry.c +593 -387
  14. data/ext/geos_c_impl/geometry.h +10 -5
  15. data/ext/geos_c_impl/geometry_collection.c +306 -339
  16. data/ext/geos_c_impl/geometry_collection.h +6 -20
  17. data/ext/geos_c_impl/globals.c +169 -0
  18. data/ext/geos_c_impl/globals.h +46 -0
  19. data/ext/geos_c_impl/line_string.c +271 -231
  20. data/ext/geos_c_impl/line_string.h +5 -8
  21. data/ext/geos_c_impl/main.c +16 -16
  22. data/ext/geos_c_impl/point.c +65 -67
  23. data/ext/geos_c_impl/point.h +4 -7
  24. data/ext/geos_c_impl/polygon.c +137 -135
  25. data/ext/geos_c_impl/polygon.h +11 -11
  26. data/ext/geos_c_impl/preface.h +16 -10
  27. data/ext/geos_c_impl/ruby_more.c +67 -0
  28. data/ext/geos_c_impl/ruby_more.h +25 -0
  29. data/lib/rgeo/cartesian/analysis.rb +5 -3
  30. data/lib/rgeo/cartesian/bounding_box.rb +74 -79
  31. data/lib/rgeo/cartesian/calculations.rb +64 -33
  32. data/lib/rgeo/cartesian/factory.rb +57 -102
  33. data/lib/rgeo/cartesian/feature_classes.rb +68 -46
  34. data/lib/rgeo/cartesian/feature_methods.rb +67 -25
  35. data/lib/rgeo/cartesian/interface.rb +6 -41
  36. data/lib/rgeo/cartesian/planar_graph.rb +373 -0
  37. data/lib/rgeo/cartesian/sweepline_intersector.rb +147 -0
  38. data/lib/rgeo/cartesian/valid_op.rb +69 -0
  39. data/lib/rgeo/cartesian.rb +3 -0
  40. data/lib/rgeo/coord_sys/cs/entities.rb +303 -99
  41. data/lib/rgeo/coord_sys/cs/factories.rb +0 -2
  42. data/lib/rgeo/coord_sys/cs/wkt_parser.rb +90 -42
  43. data/lib/rgeo/coord_sys.rb +1 -20
  44. data/lib/rgeo/error.rb +15 -0
  45. data/lib/rgeo/feature/curve.rb +0 -11
  46. data/lib/rgeo/feature/factory.rb +26 -36
  47. data/lib/rgeo/feature/factory_generator.rb +6 -14
  48. data/lib/rgeo/feature/geometry.rb +146 -66
  49. data/lib/rgeo/feature/geometry_collection.rb +16 -9
  50. data/lib/rgeo/feature/line_string.rb +4 -5
  51. data/lib/rgeo/feature/linear_ring.rb +0 -1
  52. data/lib/rgeo/feature/multi_curve.rb +0 -6
  53. data/lib/rgeo/feature/multi_surface.rb +3 -4
  54. data/lib/rgeo/feature/point.rb +4 -5
  55. data/lib/rgeo/feature/polygon.rb +1 -2
  56. data/lib/rgeo/feature/surface.rb +3 -4
  57. data/lib/rgeo/feature/types.rb +69 -85
  58. data/lib/rgeo/geographic/factory.rb +98 -125
  59. data/lib/rgeo/geographic/interface.rb +69 -166
  60. data/lib/rgeo/geographic/projected_feature_classes.rb +21 -9
  61. data/lib/rgeo/geographic/projected_feature_methods.rb +67 -42
  62. data/lib/rgeo/geographic/projected_window.rb +36 -22
  63. data/lib/rgeo/geographic/{proj4_projector.rb → projector.rb} +3 -5
  64. data/lib/rgeo/geographic/simple_mercator_projector.rb +26 -25
  65. data/lib/rgeo/geographic/spherical_feature_classes.rb +29 -9
  66. data/lib/rgeo/geographic/spherical_feature_methods.rb +86 -9
  67. data/lib/rgeo/geographic/spherical_math.rb +17 -20
  68. data/lib/rgeo/geographic.rb +1 -1
  69. data/lib/rgeo/geos/capi_factory.rb +87 -158
  70. data/lib/rgeo/geos/capi_feature_classes.rb +50 -36
  71. data/lib/rgeo/geos/ffi_factory.rb +105 -173
  72. data/lib/rgeo/geos/ffi_feature_classes.rb +34 -10
  73. data/lib/rgeo/geos/ffi_feature_methods.rb +105 -127
  74. data/lib/rgeo/geos/interface.rb +20 -59
  75. data/lib/rgeo/geos/utils.rb +5 -5
  76. data/lib/rgeo/geos/zm_factory.rb +53 -95
  77. data/lib/rgeo/geos/zm_feature_methods.rb +30 -33
  78. data/lib/rgeo/geos.rb +8 -8
  79. data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +9 -22
  80. data/lib/rgeo/impl_helper/basic_geometry_methods.rb +1 -2
  81. data/lib/rgeo/impl_helper/basic_line_string_methods.rb +28 -56
  82. data/lib/rgeo/impl_helper/basic_point_methods.rb +2 -14
  83. data/lib/rgeo/impl_helper/basic_polygon_methods.rb +17 -26
  84. data/lib/rgeo/impl_helper/utils.rb +21 -0
  85. data/lib/rgeo/impl_helper/valid_op.rb +350 -0
  86. data/lib/rgeo/impl_helper/validity_check.rb +139 -0
  87. data/lib/rgeo/impl_helper.rb +1 -0
  88. data/lib/rgeo/version.rb +1 -1
  89. data/lib/rgeo/wkrep/wkb_generator.rb +73 -63
  90. data/lib/rgeo/wkrep/wkb_parser.rb +33 -31
  91. data/lib/rgeo/wkrep/wkt_generator.rb +52 -45
  92. data/lib/rgeo/wkrep/wkt_parser.rb +48 -35
  93. data/lib/rgeo.rb +1 -3
  94. metadata +50 -13
  95. data/lib/rgeo/coord_sys/srs_database/entry.rb +0 -107
  96. data/lib/rgeo/coord_sys/srs_database/sr_org.rb +0 -64
  97. data/lib/rgeo/coord_sys/srs_database/url_reader.rb +0 -65
@@ -12,6 +12,22 @@ module RGeo
12
12
  def srid
13
13
  factory.srid
14
14
  end
15
+
16
+ def coordinate_dimension
17
+ factory.coordinate_dimension
18
+ end
19
+
20
+ def spatial_dimension
21
+ factory.spatial_dimension
22
+ end
23
+
24
+ def is_3d?
25
+ factory.property(:has_z_coordinate)
26
+ end
27
+
28
+ def measured?
29
+ factory.property(:has_m_coordinate)
30
+ end
15
31
  end
16
32
 
17
33
  module SphericalPointMethods # :nodoc:
@@ -33,9 +49,10 @@ module RGeo
33
49
  return false unless rhs.is_a?(self.class) && rhs.factory == factory
34
50
  case rhs
35
51
  when Feature::Point
36
- if @y == 90
52
+ case @y
53
+ when 90
37
54
  rhs.y == 90
38
- elsif @y == -90
55
+ when -90
39
56
  rhs.y == -90
40
57
  else
41
58
  rhs.x == @x && rhs.y == @y
@@ -79,7 +96,8 @@ module RGeo
79
96
 
80
97
  private
81
98
 
82
- def validate_geometry
99
+ # Ensure coordinates fall within a valid range.
100
+ def init_geometry
83
101
  if @x < -180.0 || @x > 180.0
84
102
  @x = @x % 360.0
85
103
  @x -= 360.0 if @x > 180.0
@@ -120,14 +138,73 @@ module RGeo
120
138
  true
121
139
  end
122
140
 
123
- def is_simple?
124
- warn "The is_simple? method is deprecated, please use the simple? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
125
- simple?
126
- end
127
-
128
141
  def length
129
142
  arcs.inject(0.0) { |sum, arc| sum + arc.length } * SphericalMath::RADIUS
130
143
  end
144
+
145
+ def intersects?(rhs)
146
+ case rhs
147
+ when Feature::LineString
148
+ intersects_line_string?(rhs)
149
+ else
150
+ super
151
+ end
152
+ end
153
+
154
+ def crosses?(rhs)
155
+ case rhs
156
+ when Feature::LineString
157
+ crosses_line_string?(rhs)
158
+ else
159
+ super
160
+ end
161
+ end
162
+
163
+ private
164
+
165
+ # TODO: replace with better algorithm (https://github.com/rgeo/rgeo/issues/274)
166
+ # Very simple algorithm to determine if 2 LineStrings intersect.
167
+ # Uses a nested for loop to look at each arc in the LineStrings and
168
+ # check if each arc intersects.
169
+ #
170
+ # @param [RGeo::Geographic::SphericalLineStringImpl] rhs
171
+ #
172
+ # @return [Boolean]
173
+ def intersects_line_string?(rhs)
174
+ arcs.each do |arc|
175
+ rhs.arcs.each do |rhs_arc|
176
+ return true if arc.intersects_arc?(rhs_arc)
177
+ end
178
+ end
179
+
180
+ false
181
+ end
182
+
183
+ # TODO: replace with better algorithm (https://github.com/rgeo/rgeo/issues/274)
184
+ # Very simple algorithm to determine if 2 LineStrings cross.
185
+ # Uses a nested for loop to look at each arc in the LineStrings and
186
+ # check if each arc crosses.
187
+ #
188
+ # @param [RGeo::Geographic::SphericalLineStringImpl] rhs
189
+ #
190
+ # @return [Boolean]
191
+ def crosses_line_string?(rhs)
192
+ arcs.each do |arc|
193
+ rhs.arcs.each do |rhs_arc|
194
+ next unless arc.intersects_arc?(rhs_arc)
195
+
196
+ # check that endpoints aren't the intersection point
197
+ is_endpoint = arc.contains_point?(rhs_arc.s) ||
198
+ arc.contains_point?(rhs_arc.e) ||
199
+ rhs_arc.contains_point?(arc.s) ||
200
+ rhs_arc.contains_point?(arc.e)
201
+
202
+ return true unless is_endpoint
203
+ end
204
+ end
205
+
206
+ false
207
+ end
131
208
  end
132
209
 
133
210
  module SphericalMultiLineStringMethods # :nodoc:
@@ -155,7 +232,7 @@ module RGeo
155
232
  centroid_lat /= (6.0 * signed_area)
156
233
  centroid_lng /= (6.0 * signed_area)
157
234
 
158
- RGeo::Geographic.spherical_factory.point(centroid_lat, centroid_lng)
235
+ factory.point(centroid_lat, centroid_lng)
159
236
  end
160
237
  end
161
238
  end
@@ -23,6 +23,8 @@ module RGeo
23
23
  # of rotation.
24
24
 
25
25
  class PointXYZ # :nodoc:
26
+ attr_reader :x, :y, :z
27
+
26
28
  def initialize(x, y, z)
27
29
  r = Math.sqrt(x * x + y * y + z * z)
28
30
  @x = (x / r).to_f
@@ -35,12 +37,8 @@ module RGeo
35
37
  "(#{@x}, #{@y}, #{@z})"
36
38
  end
37
39
 
38
- attr_reader :x
39
- attr_reader :y
40
- attr_reader :z
41
-
42
- def eql?(rhs)
43
- rhs.is_a?(PointXYZ) && @x == rhs.x && @y == rhs.y && @z == rhs.z
40
+ def eql?(other)
41
+ other.is_a?(PointXYZ) && @x == other.x && @y == other.y && @z == other.z
44
42
  end
45
43
  alias == eql?
46
44
 
@@ -58,17 +56,17 @@ module RGeo
58
56
  [lon_rad / rpd, lat_rad / rpd]
59
57
  end
60
58
 
61
- def *(rhs)
62
- val = @x * rhs.x + @y * rhs.y + @z * rhs.z
59
+ def *(other)
60
+ val = @x * other.x + @y * other.y + @z * other.z
63
61
  val = 1.0 if val > 1.0
64
62
  val = -1.0 if val < -1.0
65
63
  val
66
64
  end
67
65
 
68
- def %(rhs)
69
- rx = rhs.x
70
- ry = rhs.y
71
- rz = rhs.z
66
+ def %(other)
67
+ rx = other.x
68
+ ry = other.y
69
+ rz = other.z
72
70
  begin
73
71
  PointXYZ.new(@y * rz - @z * ry, @z * rx - @x * rz, @x * ry - @y * rx)
74
72
  rescue StandardError
@@ -113,8 +111,8 @@ module RGeo
113
111
  new(x, y, z)
114
112
  end
115
113
 
116
- def self.weighted_combination(p1, w1, p2, w2)
117
- new(p1.x * w1 + p2.x * w2, p1.y * w1 + p2.y * w2, p1.z * w1 + p2.z * w2)
114
+ def self.weighted_combination(pt1, wt1, pt2, wt2)
115
+ new(pt1.x * wt1 + pt2.x * wt2, pt1.y * wt1 + pt2.y * wt2, pt1.z * wt1 + pt2.z * wt2)
118
116
  end
119
117
 
120
118
  P1 = new(1, 0, 0)
@@ -124,21 +122,20 @@ module RGeo
124
122
  # Represents a finite arc on the sphere.
125
123
 
126
124
  class ArcXYZ # :nodoc:
125
+ attr_reader :s, :e
126
+
127
127
  def initialize(start, stop)
128
128
  @s = start
129
129
  @e = stop
130
130
  @axis = false
131
131
  end
132
132
 
133
- attr_reader :s
134
- attr_reader :e
135
-
136
133
  def to_s
137
134
  "#{@s} - #{@e}"
138
135
  end
139
136
 
140
- def eql?(rhs)
141
- rhs.is_a?(ArcXYZ) && @s == rhs.s && @e == rhs.e
137
+ def eql?(other)
138
+ other.is_a?(ArcXYZ) && @s == other.s && @e == other.e
142
139
  end
143
140
  alias == eql?
144
141
 
@@ -156,7 +153,7 @@ module RGeo
156
153
  my_axis = axis
157
154
  s_axis = ArcXYZ.new(@s, obj).axis
158
155
  e_axis = ArcXYZ.new(obj, @e).axis
159
- !s_axis || !e_axis || obj * my_axis == 0.0 && s_axis * my_axis > 0 && e_axis * my_axis > 0
156
+ !s_axis || !e_axis || obj * my_axis == 0 && s_axis * my_axis > 0 && e_axis * my_axis > 0
160
157
  end
161
158
 
162
159
  def intersects_arc?(obj)
@@ -24,7 +24,7 @@ require_relative "geographic/interface"
24
24
  require_relative "geographic/spherical_math"
25
25
  require_relative "geographic/spherical_feature_methods"
26
26
  require_relative "geographic/spherical_feature_classes"
27
- require_relative "geographic/proj4_projector"
27
+ require_relative "geographic/projector"
28
28
  require_relative "geographic/simple_mercator_projector"
29
29
  require_relative "geographic/projected_feature_methods"
30
30
  require_relative "geographic/projected_feature_classes"
@@ -9,7 +9,6 @@
9
9
  module RGeo
10
10
  module Geos
11
11
  # This the GEOS CAPI implementation of RGeo::Feature::Factory.
12
-
13
12
  class CAPIFactory
14
13
  include Feature::Factory::Instance
15
14
  include ImplHelper::Utils
@@ -20,91 +19,68 @@ module RGeo
20
19
  #
21
20
  # See RGeo::Geos.factory for a list of supported options.
22
21
 
23
- def create(opts_ = {})
22
+ def create(opts = {})
24
23
  # Make sure GEOS is available
25
24
  return unless respond_to?(:_create)
26
25
 
27
26
  # Get flags to pass to the C extension
28
27
  flags = 0
29
- flags |= 1 if opts_[:uses_lenient_assertions] || opts_[:lenient_multi_polygon_assertions] || opts_[:uses_lenient_multi_polygon_assertions]
30
- flags |= 2 if opts_[:has_z_coordinate]
31
- flags |= 4 if opts_[:has_m_coordinate]
28
+ flags |= 2 if opts[:has_z_coordinate]
29
+ flags |= 4 if opts[:has_m_coordinate]
30
+
32
31
  if flags & 6 == 6
33
32
  raise Error::UnsupportedOperation, "GEOS cannot support both Z and M coordinates at the same time."
34
33
  end
35
- flags |= 8 unless opts_[:auto_prepare] == :disabled
34
+
35
+ flags |= 8 unless opts[:auto_prepare] == :disabled
36
36
 
37
37
  # Buffer resolution
38
- buffer_resolution_ = opts_[:buffer_resolution].to_i
39
- buffer_resolution_ = 1 if buffer_resolution_ < 1
38
+ buffer_resolution = opts[:buffer_resolution].to_i
39
+ buffer_resolution = 1 if buffer_resolution < 1
40
40
 
41
41
  # Interpret the generator options
42
- wkt_generator_ = opts_[:wkt_generator]
43
- case wkt_generator_
44
- when :geos
45
- wkt_generator_ = nil
46
- when Hash
47
- wkt_generator_ = WKRep::WKTGenerator.new(wkt_generator_)
48
- else
49
- wkt_generator_ = WKRep::WKTGenerator.new(convert_case: :upper)
50
- end
51
- wkb_generator_ = opts_[:wkb_generator]
52
- case wkb_generator_
53
- when :geos
54
- wkb_generator_ = nil
55
- when Hash
56
- wkb_generator_ = WKRep::WKBGenerator.new(wkb_generator_)
57
- else
58
- wkb_generator_ = WKRep::WKBGenerator.new
59
- end
60
-
61
- # Coordinate system (srid, proj4, and coord_sys)
62
- srid_ = opts_[:srid]
63
- proj4_ = opts_[:proj4]
64
- if proj4_ && CoordSys.check!(:proj4)
65
- if proj4_.is_a?(String) || proj4_.is_a?(Hash)
66
- proj4_ = CoordSys::Proj4.create(proj4_)
42
+ wkt_generator = opts[:wkt_generator]
43
+ wkt_generator =
44
+ case wkt_generator
45
+ when Hash
46
+ WKRep::WKTGenerator.new(wkt_generator)
67
47
  end
68
- else
69
- proj4_ = nil
70
- end
71
- coord_sys_ = opts_[:coord_sys]
72
- if coord_sys_.is_a?(String)
73
- coord_sys_ = CoordSys::CS.create_from_wkt(coord_sys_)
74
- end
75
- if (!proj4_ || !coord_sys_) && srid_ && (db_ = opts_[:srs_database])
76
- entry_ = db_.get(srid_.to_i)
77
- if entry_
78
- proj4_ ||= entry_.proj4
79
- coord_sys_ ||= entry_.coord_sys
48
+ wkb_generator = opts[:wkb_generator]
49
+ wkb_generator =
50
+ case wkb_generator
51
+ when Hash
52
+ WKRep::WKBGenerator.new(wkb_generator)
80
53
  end
81
- end
82
- srid_ ||= coord_sys_.authority_code if coord_sys_
54
+
55
+ # Coordinate system (srid and coord_sys)
56
+ coord_sys_info = ImplHelper::Utils.setup_coord_sys(opts[:srid], opts[:coord_sys], opts[:coord_sys_class])
57
+ srid = coord_sys_info[:srid]
58
+ coord_sys = coord_sys_info[:coord_sys]
83
59
 
84
60
  # Create the factory and set instance variables
85
- result = _create(flags, srid_.to_i, buffer_resolution_,
86
- wkt_generator_, wkb_generator_, proj4_, coord_sys_)
61
+ result = _create(
62
+ flags,
63
+ srid.to_i,
64
+ buffer_resolution,
65
+ wkt_generator,
66
+ wkb_generator,
67
+ coord_sys
68
+ )
87
69
 
88
70
  # Interpret parser options
89
- wkt_parser_ = opts_[:wkt_parser]
90
- case wkt_parser_
91
- when :geos
92
- wkt_parser_ = nil
93
- when Hash
94
- wkt_parser_ = WKRep::WKTParser.new(result, wkt_parser_)
95
- else
96
- wkt_parser_ = WKRep::WKTParser.new(result)
97
- end
98
- wkb_parser_ = opts_[:wkb_parser]
99
- case wkb_parser_
100
- when :geos
101
- wkb_parser_ = nil
102
- when Hash
103
- wkb_parser_ = WKRep::WKBParser.new(result, wkb_parser_)
104
- else
105
- wkb_parser_ = WKRep::WKBParser.new(result)
106
- end
107
- result._set_wkrep_parsers(wkt_parser_, wkb_parser_)
71
+ wkt_parser = opts[:wkt_parser]
72
+ wkt_parser =
73
+ case wkt_parser
74
+ when Hash
75
+ WKRep::WKTParser.new(result, wkt_parser)
76
+ end
77
+ wkb_parser = opts[:wkb_parser]
78
+ wkb_parser =
79
+ case wkb_parser
80
+ when Hash
81
+ WKRep::WKBParser.new(result, wkb_parser)
82
+ end
83
+ result._set_wkrep_parsers(wkt_parser, wkb_parser)
108
84
 
109
85
  # Return the result
110
86
  result
@@ -120,37 +96,33 @@ module RGeo
120
96
 
121
97
  # Factory equivalence test.
122
98
 
123
- def eql?(rhs_)
124
- rhs_.is_a?(CAPIFactory) && rhs_.srid == _srid &&
125
- rhs_._buffer_resolution == _buffer_resolution && rhs_._flags == _flags &&
126
- rhs_.proj4 == _proj4
99
+ def eql?(other)
100
+ other.is_a?(CAPIFactory) && other.srid == _srid &&
101
+ other._buffer_resolution == _buffer_resolution && other._flags == _flags &&
102
+ other.coord_sys == coord_sys
127
103
  end
128
104
  alias == eql?
129
105
 
130
106
  # Standard hash code
131
107
 
132
108
  def hash
133
- @hash ||= [_srid, _buffer_resolution, _flags, _proj4].hash
109
+ @hash ||= [_srid, _buffer_resolution, _flags].hash
134
110
  end
135
111
 
136
112
  # Marshal support
137
113
 
138
114
  def marshal_dump # :nodoc:
139
115
  hash_ = {
140
- "hasz" => (_flags & 0x2 != 0),
141
- "hasm" => (_flags & 0x4 != 0),
116
+ "hasz" => supports_z?,
117
+ "hasm" => supports_m?,
142
118
  "srid" => _srid,
143
119
  "bufr" => _buffer_resolution,
144
120
  "wktg" => _wkt_generator ? _wkt_generator.properties : {},
145
121
  "wkbg" => _wkb_generator ? _wkb_generator.properties : {},
146
122
  "wktp" => _wkt_parser ? _wkt_parser.properties : {},
147
123
  "wkbp" => _wkb_parser ? _wkb_parser.properties : {},
148
- "lmpa" => (_flags & 0x1 != 0),
149
- "apre" => ((_flags & 0x8) >> 3)
124
+ "apre" => auto_prepare
150
125
  }
151
- if (proj4_ = _proj4)
152
- hash_["proj4"] = proj4_.marshal_dump
153
- end
154
126
  if (coord_sys_ = _coord_sys)
155
127
  hash_["cs"] = coord_sys_.to_wkt
156
128
  end
@@ -158,17 +130,9 @@ module RGeo
158
130
  end
159
131
 
160
132
  def marshal_load(data_) # :nodoc:
161
- if (proj4_data_ = data_["proj4"]) && CoordSys.check!(:proj4)
162
- proj4_ = CoordSys::Proj4.allocate
163
- proj4_.marshal_load(proj4_data_)
164
- else
165
- proj4_ = nil
166
- end
167
- if (coord_sys_data_ = data_["cs"])
168
- coord_sys_ = CoordSys::CS.create_from_wkt(coord_sys_data_)
169
- else
170
- coord_sys_ = nil
171
- end
133
+ cs_class = CoordSys::CONFIG.default_coord_sys_class
134
+ coord_sys_ = data_["cs"]&.then { |cs| cs_class.create_from_wkt(cs) }
135
+
172
136
  initialize_copy(
173
137
  CAPIFactory.create(
174
138
  has_z_coordinate: data_["hasz"],
@@ -179,9 +143,7 @@ module RGeo
179
143
  wkb_generator: symbolize_hash(data_["wkbg"]),
180
144
  wkt_parser: symbolize_hash(data_["wktp"]),
181
145
  wkb_parser: symbolize_hash(data_["wkbp"]),
182
- uses_lenient_multi_polygon_assertions: data_["lmpa"],
183
- auto_prepare: (data_["apre"] == 0 ? :disabled : :simple),
184
- proj4: proj4_,
146
+ auto_prepare: data_["apre"],
185
147
  coord_sys: coord_sys_
186
148
  )
187
149
  )
@@ -190,41 +152,25 @@ module RGeo
190
152
  # Psych support
191
153
 
192
154
  def encode_with(coder_) # :nodoc:
193
- coder_["has_z_coordinate"] = (_flags & 0x2 != 0)
194
- coder_["has_m_coordinate"] = (_flags & 0x4 != 0)
155
+ coder_["has_z_coordinate"] = supports_z?
156
+ coder_["has_m_coordinate"] = supports_m?
195
157
  coder_["srid"] = _srid
196
158
  coder_["buffer_resolution"] = _buffer_resolution
197
- coder_["lenient_multi_polygon_assertions"] = (_flags & 0x1 != 0)
198
159
  coder_["wkt_generator"] = _wkt_generator ? _wkt_generator.properties : {}
199
160
  coder_["wkb_generator"] = _wkb_generator ? _wkb_generator.properties : {}
200
161
  coder_["wkt_parser"] = _wkt_parser ? _wkt_parser.properties : {}
201
162
  coder_["wkb_parser"] = _wkb_parser ? _wkb_parser.properties : {}
202
- coder_["auto_prepare"] = ((_flags & 0x8) == 0 ? "disabled" : "simple")
203
- if (proj4_ = _proj4)
204
- str_ = proj4_.original_str || proj4_.canonical_str
205
- coder_["proj4"] = proj4_.radians? ? { "proj4" => str_, "radians" => true } : str_
206
- end
207
- if (coord_sys_ = _coord_sys)
208
- coder_["coord_sys"] = coord_sys_.to_wkt
209
- end
163
+ coder_["auto_prepare"] = auto_prepare
164
+
165
+ return unless (coord_sys_ = _coord_sys)
166
+
167
+ coder_["coord_sys"] = coord_sys_.to_wkt
210
168
  end
211
169
 
212
170
  def init_with(coder_) # :nodoc:
213
- if (proj4_data_ = coder_["proj4"])
214
- CoordSys.check!(:proj4)
215
- if proj4_data_.is_a?(Hash)
216
- proj4_ = CoordSys::Proj4.create(proj4_data_["proj4"], radians: proj4_data_["radians"])
217
- else
218
- proj4_ = CoordSys::Proj4.create(proj4_data_.to_s)
219
- end
220
- else
221
- proj4_ = nil
222
- end
223
- if (coord_sys_data_ = coder_["cs"])
224
- coord_sys_ = CoordSys::CS.create_from_wkt(coord_sys_data_.to_s)
225
- else
226
- coord_sys_ = nil
227
- end
171
+ cs_class = CoordSys::CONFIG.default_coord_sys_class
172
+ coord_sys_ = coder_["cs"]&.then { |cs| cs_class.create_from_wkt(cs) }
173
+
228
174
  initialize_copy(
229
175
  CAPIFactory.create(
230
176
  has_z_coordinate: coder_["has_z_coordinate"],
@@ -236,8 +182,6 @@ module RGeo
236
182
  wkt_parser: symbolize_hash(coder_["wkt_parser"]),
237
183
  wkb_parser: symbolize_hash(coder_["wkb_parser"]),
238
184
  auto_prepare: coder_["auto_prepare"] == "disabled" ? :disabled : :simple,
239
- uses_lenient_multi_polygon_assertions: coder_["lenient_multi_polygon_assertions"],
240
- proj4: proj4_,
241
185
  coord_sys: coord_sys_
242
186
  )
243
187
  )
@@ -256,28 +200,19 @@ module RGeo
256
200
  _buffer_resolution
257
201
  end
258
202
 
259
- # Returns true if this factory is lenient with MultiPolygon assertions
260
-
261
- def lenient_multi_polygon_assertions?
262
- _flags & 0x1 != 0
263
- end
264
-
265
203
  # See RGeo::Feature::Factory#property
266
-
267
204
  def property(name_)
268
205
  case name_
269
206
  when :has_z_coordinate
270
- _flags & 0x2 != 0
207
+ supports_z?
271
208
  when :has_m_coordinate
272
- _flags & 0x4 != 0
209
+ supports_m?
273
210
  when :is_cartesian
274
211
  true
275
- when :uses_lenient_multi_polygon_assertions
276
- _flags & 0x1 != 0
277
212
  when :buffer_resolution
278
213
  _buffer_resolution
279
214
  when :auto_prepare
280
- _flags & 0x8 != 0 ? :simple : :disabled
215
+ prepare_heuristic? ? :simple : :disabled
281
216
  end
282
217
  end
283
218
 
@@ -297,22 +232,16 @@ module RGeo
297
232
  if (wkb_parser_ = _wkb_parser)
298
233
  wkb_parser_.parse(str_)
299
234
  else
300
- if str_[0] == "\x00" || str_[0] == "\x01"
301
- _parse_wkb_impl(str_)
302
- else
303
- _parse_wkb_impl([str_].pack('H*'))
304
- end
235
+ _parse_wkb_impl(str_)
305
236
  end
306
237
  end
307
238
 
308
239
  # See RGeo::Feature::Factory#point
309
240
 
310
- def point(x_, y_, *extra_)
311
- if extra_.length > (_flags & 6 == 0 ? 0 : 1)
312
- raise(RGeo::Error::InvalidGeometry, "Parse error")
313
- else
314
- CAPIPointImpl.create(self, x_, y_, extra_[0].to_f)
315
- end
241
+ def point(x, y, *extra)
242
+ raise(RGeo::Error::InvalidGeometry, "Parse error") if extra.length > (supports_z_or_m? ? 1 : 0)
243
+
244
+ CAPIPointImpl.create(self, x, y, extra[0].to_f)
316
245
  end
317
246
 
318
247
  # See RGeo::Feature::Factory#line_string
@@ -372,12 +301,6 @@ module RGeo
372
301
  raise(RGeo::Error::InvalidGeometry, "Parse error")
373
302
  end
374
303
 
375
- # See RGeo::Feature::Factory#proj4
376
-
377
- def proj4
378
- _proj4
379
- end
380
-
381
304
  # See RGeo::Feature::Factory#coord_sys
382
305
 
383
306
  def coord_sys
@@ -396,33 +319,39 @@ module RGeo
396
319
  case original
397
320
  when CAPIGeometryMethods
398
321
  # Optimization if we're just changing factories, but the
399
- # factories are zm-compatible and proj4-compatible.
322
+ # factories are zm-compatible and coord_sys-compatible.
400
323
  if original.factory != self && ntype == type &&
401
- original.factory._flags & 0x6 == _flags & 0x6 &&
402
- (!project || original.factory.proj4 == _proj4)
324
+ original.factory._flags & FLAG_SUPPORTS_Z_OR_M == _flags & FLAG_SUPPORTS_Z_OR_M &&
325
+ (!project || original.factory.coord_sys == coord_sys)
403
326
  result = original.dup
404
327
  result.factory = self
405
328
  return result
406
329
  end
407
330
  # LineString conversion optimization.
408
331
  if (original.factory != self || ntype != type) &&
409
- original.factory._flags & 0x6 == _flags & 0x6 &&
410
- (!project || original.factory.proj4 == _proj4) &&
332
+ original.factory._flags & FLAG_SUPPORTS_Z_OR_M == _flags & FLAG_SUPPORTS_Z_OR_M &&
333
+ (!project || original.factory.coord_sys == coord_sys) &&
411
334
  type.subtype_of?(Feature::LineString) && ntype.subtype_of?(Feature::LineString)
412
335
  return IMPL_CLASSES[ntype]._copy_from(self, original)
413
336
  end
414
337
  when ZMGeometryMethods
415
338
  # Optimization for just removing a coordinate from an otherwise
416
339
  # compatible factory
417
- if _flags & 0x6 == 0x2 && self == original.factory.z_factory
340
+ if supports_z? && !supports_m? && self == original.factory.z_factory
418
341
  return Feature.cast(original.z_geometry, ntype, flags)
419
- elsif _flags & 0x6 == 0x4 && self == original.factory.m_factory
342
+ end
343
+
344
+ if supports_m? && !supports_z? && self == original.factory.m_factory
420
345
  return Feature.cast(original.m_geometry, ntype, flags)
421
346
  end
422
347
  end
423
348
  false
424
349
  end
425
350
 
351
+ def auto_prepare # :nodoc:
352
+ prepare_heuristic? ? :simple : :disabled
353
+ end
354
+
426
355
  # :stopdoc:
427
356
 
428
357
  IMPL_CLASSES = {