rgeo 2.4.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +6 -0
  3. data/README.md +21 -11
  4. data/ext/geos_c_impl/analysis.c +29 -26
  5. data/ext/geos_c_impl/analysis.h +8 -5
  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 +41 -29
  11. data/ext/geos_c_impl/factory.c +441 -351
  12. data/ext/geos_c_impl/factory.h +98 -55
  13. data/ext/geos_c_impl/geometry.c +563 -384
  14. data/ext/geos_c_impl/geometry.h +10 -3
  15. data/ext/geos_c_impl/geometry_collection.c +288 -316
  16. data/ext/geos_c_impl/geometry_collection.h +6 -18
  17. data/ext/geos_c_impl/globals.c +99 -21
  18. data/ext/geos_c_impl/globals.h +3 -2
  19. data/ext/geos_c_impl/line_string.c +263 -222
  20. data/ext/geos_c_impl/line_string.h +5 -6
  21. data/ext/geos_c_impl/main.c +8 -9
  22. data/ext/geos_c_impl/point.c +62 -65
  23. data/ext/geos_c_impl/point.h +4 -5
  24. data/ext/geos_c_impl/polygon.c +134 -132
  25. data/ext/geos_c_impl/polygon.h +11 -9
  26. data/ext/geos_c_impl/preface.h +10 -12
  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 +299 -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 +73 -83
  58. data/lib/rgeo/geographic/factory.rb +98 -125
  59. data/lib/rgeo/geographic/interface.rb +66 -163
  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 +24 -23
  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 +95 -165
  72. data/lib/rgeo/geos/ffi_feature_classes.rb +34 -10
  73. data/lib/rgeo/geos/ffi_feature_methods.rb +105 -126
  74. data/lib/rgeo/geos/interface.rb +20 -59
  75. data/lib/rgeo/geos/utils.rb +3 -3
  76. data/lib/rgeo/geos/zm_factory.rb +53 -95
  77. data/lib/rgeo/geos/zm_feature_methods.rb +30 -32
  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 +51 -16
  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 = {