rgeo 3.0.0.pre.rc.3 → 3.0.0

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -0
  3. data/ext/geos_c_impl/factory.c +41 -5
  4. data/ext/geos_c_impl/factory.h +13 -2
  5. data/ext/geos_c_impl/geometry.c +151 -122
  6. data/ext/geos_c_impl/geometry_collection.c +17 -19
  7. data/ext/geos_c_impl/line_string.c +46 -36
  8. data/ext/geos_c_impl/point.c +0 -2
  9. data/ext/geos_c_impl/polygon.c +10 -11
  10. data/ext/geos_c_impl/polygon.h +1 -1
  11. data/ext/geos_c_impl/ruby_more.c +7 -0
  12. data/ext/geos_c_impl/ruby_more.h +8 -0
  13. data/lib/rgeo/cartesian/analysis.rb +5 -3
  14. data/lib/rgeo/cartesian/bounding_box.rb +74 -79
  15. data/lib/rgeo/cartesian/calculations.rb +20 -26
  16. data/lib/rgeo/cartesian/factory.rb +47 -49
  17. data/lib/rgeo/cartesian/planar_graph.rb +10 -16
  18. data/lib/rgeo/cartesian/sweepline_intersector.rb +1 -3
  19. data/lib/rgeo/cartesian/valid_op.rb +1 -3
  20. data/lib/rgeo/coord_sys/cs/entities.rb +87 -101
  21. data/lib/rgeo/coord_sys/cs/factories.rb +0 -2
  22. data/lib/rgeo/coord_sys/cs/wkt_parser.rb +70 -29
  23. data/lib/rgeo/feature/curve.rb +0 -1
  24. data/lib/rgeo/feature/factory.rb +25 -27
  25. data/lib/rgeo/feature/factory_generator.rb +3 -4
  26. data/lib/rgeo/feature/geometry.rb +41 -30
  27. data/lib/rgeo/feature/geometry_collection.rb +3 -4
  28. data/lib/rgeo/feature/line_string.rb +1 -2
  29. data/lib/rgeo/feature/linear_ring.rb +0 -1
  30. data/lib/rgeo/feature/multi_curve.rb +0 -1
  31. data/lib/rgeo/feature/multi_surface.rb +0 -1
  32. data/lib/rgeo/feature/point.rb +0 -1
  33. data/lib/rgeo/feature/polygon.rb +1 -2
  34. data/lib/rgeo/feature/surface.rb +0 -1
  35. data/lib/rgeo/feature/types.rb +73 -83
  36. data/lib/rgeo/geographic/factory.rb +87 -80
  37. data/lib/rgeo/geographic/interface.rb +40 -23
  38. data/lib/rgeo/geographic/projected_feature_methods.rb +2 -6
  39. data/lib/rgeo/geographic/projected_window.rb +35 -21
  40. data/lib/rgeo/geographic/simple_mercator_projector.rb +25 -13
  41. data/lib/rgeo/geographic/spherical_feature_methods.rb +8 -3
  42. data/lib/rgeo/geographic/spherical_math.rb +17 -20
  43. data/lib/rgeo/geos/capi_factory.rb +50 -50
  44. data/lib/rgeo/geos/ffi_factory.rb +41 -42
  45. data/lib/rgeo/geos/ffi_feature_methods.rb +72 -97
  46. data/lib/rgeo/geos/interface.rb +16 -16
  47. data/lib/rgeo/geos/utils.rb +3 -3
  48. data/lib/rgeo/geos/zm_factory.rb +50 -42
  49. data/lib/rgeo/geos/zm_feature_methods.rb +15 -8
  50. data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +4 -4
  51. data/lib/rgeo/impl_helper/basic_geometry_methods.rb +1 -2
  52. data/lib/rgeo/impl_helper/basic_line_string_methods.rb +18 -24
  53. data/lib/rgeo/impl_helper/basic_point_methods.rb +1 -3
  54. data/lib/rgeo/impl_helper/basic_polygon_methods.rb +15 -16
  55. data/lib/rgeo/impl_helper/utils.rb +3 -9
  56. data/lib/rgeo/impl_helper/valid_op.rb +12 -16
  57. data/lib/rgeo/version.rb +1 -1
  58. data/lib/rgeo/wkrep/wkb_generator.rb +42 -47
  59. data/lib/rgeo/wkrep/wkb_parser.rb +17 -18
  60. data/lib/rgeo/wkrep/wkt_generator.rb +23 -16
  61. data/lib/rgeo/wkrep/wkt_parser.rb +23 -13
  62. metadata +5 -5
@@ -13,7 +13,6 @@ module RGeo
13
13
  # map visualization, an envelope in a projected coordinate system, or
14
14
  # a spatial constraint. It must be attached to a Geographic::Factory
15
15
  # that has a projection.
16
-
17
16
  class ProjectedWindow
18
17
  # Create a new ProjectedWindow given the Geographic::Factory, and the
19
18
  # x and y extents of the rectangle.
@@ -64,10 +63,10 @@ module RGeo
64
63
  to_s
65
64
  end
66
65
 
67
- def eql?(obj_) # :nodoc:
68
- return false unless obj_.is_a?(ProjectedWindow)
69
- @factory == obj_.factory && @x_min == obj_.x_min && @x_max == obj_.x_max &&
70
- @y_min = obj_.y_min && @y_max = obj_.y_max
66
+ def eql?(other) # :nodoc:
67
+ return false unless other.is_a?(ProjectedWindow)
68
+ @factory == other.factory && @x_min == other.x_min && @x_max == other.x_max &&
69
+ @y_min = other.y_min && @y_max = other.y_max
71
70
  end
72
71
  alias == eql?
73
72
 
@@ -79,23 +78,18 @@ module RGeo
79
78
  # Note that this factory is the overall geography factory, not the
80
79
  # projected factory (which can be obtained by calling
81
80
  # Geographic::Factory#projection_factory on this factory).
82
-
83
81
  attr_reader :factory
84
82
 
85
83
  # Returns the lower limit in the x (easting) direction.
86
-
87
84
  attr_reader :x_min
88
85
 
89
86
  # Returns the upper limit in the x (easting) direction.
90
-
91
87
  attr_reader :x_max
92
88
 
93
89
  # Returns the lower limit in the y (northing) direction.
94
-
95
90
  attr_reader :y_min
96
91
 
97
92
  # Returns the upper limit in the y (northing) direction.
98
-
99
93
  attr_reader :y_max
100
94
 
101
95
  # Returns true if the projection wraps along the x axis, and this
@@ -146,35 +140,45 @@ module RGeo
146
140
  # (lat/lng) space, as a Feature::Point object.
147
141
 
148
142
  def sw_point
149
- @sw ||= @factory.unproject(@factory.projection_factory.point(@x_min, @y_min))
143
+ return @sw_point if defined?(@sw_point)
144
+
145
+ @sw_point = @factory.unproject(@factory.projection_factory.point(@x_min, @y_min))
150
146
  end
151
147
 
152
148
  # Returns the southeast corner of the rectangle in _unprojected_
153
149
  # (lat/lng) space, as a Feature::Point object.
154
150
 
155
151
  def se_point
156
- @se ||= @factory.unproject(@factory.projection_factory.point(@x_max, @y_min))
152
+ return @se_point if defined?(@se_point)
153
+
154
+ @se_point = @factory.unproject(@factory.projection_factory.point(@x_max, @y_min))
157
155
  end
158
156
 
159
157
  # Returns the northwest corner of the rectangle in _unprojected_
160
158
  # (lat/lng) space, as a Feature::Point object.
161
159
 
162
160
  def nw_point
163
- @nw ||= @factory.unproject(@factory.projection_factory.point(@x_min, @y_max))
161
+ return @nw_point if defined?(@nw_point)
162
+
163
+ @nw_point = @factory.unproject(@factory.projection_factory.point(@x_min, @y_max))
164
164
  end
165
165
 
166
166
  # Returns the northeast corner of the rectangle in _unprojected_
167
167
  # (lat/lng) space, as a Feature::Point object.
168
168
 
169
169
  def ne_point
170
- @ne ||= @factory.unproject(@factory.projection_factory.point(@x_max, @y_max))
170
+ return @ne_point if defined?(@ne_point)
171
+
172
+ @ne_point = @factory.unproject(@factory.projection_factory.point(@x_max, @y_max))
171
173
  end
172
174
 
173
175
  # Returns the center of the rectangle in _unprojected_
174
176
  # (lat/lng) space, as a Feature::Point object.
175
177
 
176
178
  def center_point
177
- @center ||= @factory.unproject(@factory.projection_factory.point(*center_xy))
179
+ return @center_point if defined?(@center_point)
180
+
181
+ @center_point = @factory.unproject(@factory.projection_factory.point(*center_xy))
178
182
  end
179
183
 
180
184
  # Returns a random point inside the rectangle in _unprojected_
@@ -233,7 +237,7 @@ module RGeo
233
237
 
234
238
  def scaled_by(x_factor_, y_factor_ = nil)
235
239
  y_factor_ ||= x_factor_
236
- if x_factor_ != 1.0 || y_factor_ != 1.0
240
+ if x_factor_ != 1 || y_factor_ != 1
237
241
  x_, y_ = *center_xy
238
242
  xr_ = x_span * 0.5 * x_factor_
239
243
  yr_ = y_span * 0.5 * y_factor_
@@ -287,9 +291,14 @@ module RGeo
287
291
 
288
292
  def with_margin(x_margin_, y_margin_ = nil)
289
293
  y_margin_ ||= x_margin_
290
- if x_margin_ != 0.0 || y_margin_ != 0.0
291
- ProjectedWindow.new(@factory, @x_min - x_margin_, @y_min - y_margin_,
292
- @x_max + x_margin_, @y_max + y_margin_)
294
+ if x_margin_ != 0 || y_margin_ != 0
295
+ ProjectedWindow.new(
296
+ @factory,
297
+ @x_min - x_margin_,
298
+ @y_min - y_margin_,
299
+ @x_max + x_margin_,
300
+ @y_max + y_margin_
301
+ )
293
302
  else
294
303
  self
295
304
  end
@@ -318,8 +327,13 @@ module RGeo
318
327
  y_margin_ ||= x_margin_
319
328
  factory_ = point_.factory
320
329
  projection_ = factory_.project(point_)
321
- ProjectedWindow.new(factory_, projection_.x - x_margin_, projection_.y - y_margin_,
322
- projection_.x + x_margin_, projection_.y + y_margin_)
330
+ ProjectedWindow.new(
331
+ factory_,
332
+ projection_.x - x_margin_,
333
+ projection_.y - y_margin_,
334
+ projection_.x + x_margin_,
335
+ projection_.y + y_margin_
336
+ )
323
337
  end
324
338
 
325
339
  # Creates a new window that contains all of the given points.
@@ -32,8 +32,10 @@ module RGeo
32
32
  when Feature::Point
33
33
  rpd_ = ImplHelper::Math::RADIANS_PER_DEGREE
34
34
  radius = EQUATORIAL_RADIUS
35
- @projection_factory.point(geometry.x * rpd_ * radius,
36
- Math.log(Math.tan(Math::PI / 4.0 + geometry.y * rpd_ / 2.0)) * radius)
35
+ @projection_factory.point(
36
+ geometry.x * rpd_ * radius,
37
+ Math.log(Math.tan(Math::PI / 4.0 + geometry.y * rpd_ / 2.0)) * radius
38
+ )
37
39
  when Feature::Line
38
40
  @projection_factory.line(project(geometry.start_point), project(geometry.end_point))
39
41
  when Feature::LinearRing
@@ -59,8 +61,10 @@ module RGeo
59
61
  when Feature::Point
60
62
  dpr = ImplHelper::Math::DEGREES_PER_RADIAN
61
63
  radius = EQUATORIAL_RADIUS
62
- @geography_factory.point(geometry.x / radius * dpr,
63
- (2.0 * Math.atan(Math.exp(geometry.y / radius)) - Math::PI / 2.0) * dpr)
64
+ @geography_factory.point(
65
+ geometry.x / radius * dpr,
66
+ (2.0 * Math.atan(Math.exp(geometry.y / radius)) - Math::PI / 2.0) * dpr
67
+ )
64
68
  when Feature::Line
65
69
  @geography_factory.line(unproject(geometry.start_point), unproject(geometry.end_point))
66
70
  when Feature::LinearRing
@@ -68,8 +72,10 @@ module RGeo
68
72
  when Feature::LineString
69
73
  @geography_factory.line_string(geometry.points.map { |p| unproject(p) })
70
74
  when Feature::Polygon
71
- @geography_factory.polygon(unproject(geometry.exterior_ring),
72
- geometry.interior_rings.map { |p| unproject(p) })
75
+ @geography_factory.polygon(
76
+ unproject(geometry.exterior_ring),
77
+ geometry.interior_rings.map { |p| unproject(p) }
78
+ )
73
79
  when Feature::MultiPoint
74
80
  @geography_factory.multi_point(geometry.map { |p| unproject(p) })
75
81
  when Feature::MultiLineString
@@ -86,16 +92,22 @@ module RGeo
86
92
  end
87
93
 
88
94
  def limits_window
89
- @limits_window ||= ProjectedWindow.new(@geography_factory,
90
- -20_037_508.342789, -20_037_508.342789, 20_037_508.342789, 20_037_508.342789,
91
- is_limits: true)
95
+ return @limits_window if defined?(@limits_window)
96
+
97
+ @limits_window = ProjectedWindow.new(
98
+ @geography_factory,
99
+ -20_037_508.342789,
100
+ -20_037_508.342789,
101
+ 20_037_508.342789,
102
+ 20_037_508.342789,
103
+ is_limits: true
104
+ )
92
105
  end
93
106
 
94
107
  def self._coordsys_3857 # :nodoc:
95
- unless defined?(@coordsys_3857)
96
- @coordsys_3857 = CoordSys::CONFIG.default_coord_sys_class.create(3857)
97
- end
98
- @coordsys_3857
108
+ return @coordsys_3857 if defined?(@coordsys_3857)
109
+
110
+ @coordsys_3857 = CoordSys::CONFIG.default_coord_sys_class.create(3857)
99
111
  end
100
112
  end
101
113
  end
@@ -49,9 +49,10 @@ module RGeo
49
49
  return false unless rhs.is_a?(self.class) && rhs.factory == factory
50
50
  case rhs
51
51
  when Feature::Point
52
- if @y == 90
52
+ case @y
53
+ when 90
53
54
  rhs.y == 90
54
- elsif @y == -90
55
+ when -90
55
56
  rhs.y == -90
56
57
  else
57
58
  rhs.x == @x && rhs.y == @y
@@ -193,7 +194,11 @@ module RGeo
193
194
  next unless arc.intersects_arc?(rhs_arc)
194
195
 
195
196
  # check that endpoints aren't the intersection point
196
- is_endpoint = arc.contains_point?(rhs_arc.s) || arc.contains_point?(rhs_arc.e) || rhs_arc.contains_point?(arc.s) || rhs_arc.contains_point?(arc.e)
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
+
197
202
  return true unless is_endpoint
198
203
  end
199
204
  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)
@@ -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
@@ -28,9 +27,11 @@ module RGeo
28
27
  flags = 0
29
28
  flags |= 2 if opts[:has_z_coordinate]
30
29
  flags |= 4 if opts[:has_m_coordinate]
30
+
31
31
  if flags & 6 == 6
32
32
  raise Error::UnsupportedOperation, "GEOS cannot support both Z and M coordinates at the same time."
33
33
  end
34
+
34
35
  flags |= 8 unless opts[:auto_prepare] == :disabled
35
36
 
36
37
  # Buffer resolution
@@ -39,19 +40,17 @@ module RGeo
39
40
 
40
41
  # Interpret the generator options
41
42
  wkt_generator = opts[:wkt_generator]
42
- case wkt_generator
43
- when Hash
44
- wkt_generator = WKRep::WKTGenerator.new(wkt_generator)
45
- else
46
- wkt_generator = nil
47
- end
43
+ wkt_generator =
44
+ case wkt_generator
45
+ when Hash
46
+ WKRep::WKTGenerator.new(wkt_generator)
47
+ end
48
48
  wkb_generator = opts[:wkb_generator]
49
- case wkb_generator
50
- when Hash
51
- wkb_generator = WKRep::WKBGenerator.new(wkb_generator)
52
- else
53
- wkb_generator = nil
54
- end
49
+ wkb_generator =
50
+ case wkb_generator
51
+ when Hash
52
+ WKRep::WKBGenerator.new(wkb_generator)
53
+ end
55
54
 
56
55
  # Coordinate system (srid and coord_sys)
57
56
  coord_sys_info = ImplHelper::Utils.setup_coord_sys(opts[:srid], opts[:coord_sys], opts[:coord_sys_class])
@@ -59,24 +58,28 @@ module RGeo
59
58
  coord_sys = coord_sys_info[:coord_sys]
60
59
 
61
60
  # Create the factory and set instance variables
62
- result = _create(flags, srid.to_i, buffer_resolution,
63
- wkt_generator, wkb_generator, coord_sys)
61
+ result = _create(
62
+ flags,
63
+ srid.to_i,
64
+ buffer_resolution,
65
+ wkt_generator,
66
+ wkb_generator,
67
+ coord_sys
68
+ )
64
69
 
65
70
  # Interpret parser options
66
71
  wkt_parser = opts[:wkt_parser]
67
- case wkt_parser
68
- when Hash
69
- wkt_parser = WKRep::WKTParser.new(result, wkt_parser)
70
- else
71
- wkt_parser = nil
72
- end
72
+ wkt_parser =
73
+ case wkt_parser
74
+ when Hash
75
+ WKRep::WKTParser.new(result, wkt_parser)
76
+ end
73
77
  wkb_parser = opts[:wkb_parser]
74
- case wkb_parser
75
- when Hash
76
- wkb_parser = WKRep::WKBParser.new(result, wkb_parser)
77
- else
78
- wkb_parser = nil
79
- end
78
+ wkb_parser =
79
+ case wkb_parser
80
+ when Hash
81
+ WKRep::WKBParser.new(result, wkb_parser)
82
+ end
80
83
  result._set_wkrep_parsers(wkt_parser, wkb_parser)
81
84
 
82
85
  # Return the result
@@ -93,10 +96,10 @@ module RGeo
93
96
 
94
97
  # Factory equivalence test.
95
98
 
96
- def eql?(rhs_)
97
- rhs_.is_a?(CAPIFactory) && rhs_.srid == _srid &&
98
- rhs_._buffer_resolution == _buffer_resolution && rhs_._flags == _flags &&
99
- rhs_.coord_sys == coord_sys
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
100
103
  end
101
104
  alias == eql?
102
105
 
@@ -127,11 +130,9 @@ module RGeo
127
130
  end
128
131
 
129
132
  def marshal_load(data_) # :nodoc:
130
- if (coord_sys_data_ = data_["cs"])
131
- coord_sys_ = CoordSys::CONFIG.default_coord_sys_class.create_from_wkt(coord_sys_data_)
132
- else
133
- coord_sys_ = nil
134
- end
133
+ cs_class = CoordSys::CONFIG.default_coord_sys_class
134
+ coord_sys_ = data_["cs"]&.then { |cs| cs_class.create_from_wkt(cs) }
135
+
135
136
  initialize_copy(
136
137
  CAPIFactory.create(
137
138
  has_z_coordinate: data_["hasz"],
@@ -160,17 +161,16 @@ module RGeo
160
161
  coder_["wkt_parser"] = _wkt_parser ? _wkt_parser.properties : {}
161
162
  coder_["wkb_parser"] = _wkb_parser ? _wkb_parser.properties : {}
162
163
  coder_["auto_prepare"] = auto_prepare
163
- if (coord_sys_ = _coord_sys)
164
- coder_["coord_sys"] = coord_sys_.to_wkt
165
- end
164
+
165
+ return unless (coord_sys_ = _coord_sys)
166
+
167
+ coder_["coord_sys"] = coord_sys_.to_wkt
166
168
  end
167
169
 
168
170
  def init_with(coder_) # :nodoc:
169
- if (coord_sys_data_ = coder_["cs"])
170
- coord_sys_ = CoordSys::CONFIG.default_coord_sys_class.create_from_wkt(coord_sys_data_.to_s)
171
- else
172
- coord_sys_ = nil
173
- end
171
+ cs_class = CoordSys::CONFIG.default_coord_sys_class
172
+ coord_sys_ = coder_["cs"]&.then { |cs| cs_class.create_from_wkt(cs) }
173
+
174
174
  initialize_copy(
175
175
  CAPIFactory.create(
176
176
  has_z_coordinate: coder_["has_z_coordinate"],
@@ -239,11 +239,9 @@ module RGeo
239
239
  # See RGeo::Feature::Factory#point
240
240
 
241
241
  def point(x, y, *extra)
242
- if extra.length > (supports_z_or_m? ? 1 : 0)
243
- raise(RGeo::Error::InvalidGeometry, "Parse error")
244
- else
245
- CAPIPointImpl.create(self, x, y, extra[0].to_f)
246
- end
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)
247
245
  end
248
246
 
249
247
  # See RGeo::Feature::Factory#line_string
@@ -341,7 +339,9 @@ module RGeo
341
339
  # compatible factory
342
340
  if supports_z? && !supports_m? && self == original.factory.z_factory
343
341
  return Feature.cast(original.z_geometry, ntype, flags)
344
- elsif supports_m? && !supports_z? && self == original.factory.m_factory
342
+ end
343
+
344
+ if supports_m? && !supports_z? && self == original.factory.m_factory
345
345
  return Feature.cast(original.m_geometry, ntype, flags)
346
346
  end
347
347
  end
@@ -9,11 +9,22 @@
9
9
  module RGeo
10
10
  module Geos
11
11
  # This the FFI-GEOS implementation of RGeo::Feature::Factory.
12
-
13
12
  class FFIFactory
14
13
  include Feature::Factory::Instance
15
14
  include ImplHelper::Utils
16
15
 
16
+ attr_reader :coordinate_dimension, :spatial_dimension, :_has_3d, :_auto_prepare
17
+
18
+ # Returns the SRID of geometries created by this factory.
19
+ attr_reader :srid
20
+
21
+ # Returns the resolution used by buffer calculations on geometries
22
+ # created by this factory
23
+ attr_reader :buffer_resolution
24
+
25
+ # See RGeo::Feature::Factory#coord_sys
26
+ attr_reader :coord_sys
27
+
17
28
  # Create a new factory. Returns nil if the FFI-GEOS implementation
18
29
  # is not supported.
19
30
  #
@@ -22,9 +33,11 @@ module RGeo
22
33
  def initialize(opts = {})
23
34
  @has_z = opts[:has_z_coordinate] ? true : false
24
35
  @has_m = opts[:has_m_coordinate] ? true : false
36
+
25
37
  if @has_z && @has_m
26
38
  raise Error::UnsupportedOperation, "GEOS cannot support both Z and M coordinates at the same time."
27
39
  end
40
+
28
41
  @coordinate_dimension = 2
29
42
  @coordinate_dimension += 1 if @has_z
30
43
  @coordinate_dimension += 1 if @has_m
@@ -81,7 +94,6 @@ module RGeo
81
94
  @wkb_parser = nil
82
95
  end
83
96
  end
84
- attr_reader :coordinate_dimension, :spatial_dimension
85
97
 
86
98
  # Standard object inspection output
87
99
 
@@ -91,12 +103,12 @@ module RGeo
91
103
 
92
104
  # Factory equivalence test.
93
105
 
94
- def eql?(rhs)
95
- rhs.is_a?(self.class) && @srid == rhs.srid &&
96
- @has_z == rhs.property(:has_z_coordinate) &&
97
- @has_m == rhs.property(:has_m_coordinate) &&
98
- @buffer_resolution == rhs.property(:buffer_resolution) &&
99
- @coord_sys.eql?(rhs.coord_sys)
106
+ def eql?(other)
107
+ other.is_a?(self.class) && @srid == other.srid &&
108
+ @has_z == other.property(:has_z_coordinate) &&
109
+ @has_m == other.property(:has_m_coordinate) &&
110
+ @buffer_resolution == other.property(:buffer_resolution) &&
111
+ @coord_sys.eql?(other.coord_sys)
100
112
  end
101
113
  alias == eql?
102
114
 
@@ -125,11 +137,9 @@ module RGeo
125
137
  end
126
138
 
127
139
  def marshal_load(data) # :nodoc:
128
- if (coord_sys_data = data["cs"])
129
- coord_sys = CoordSys::CONFIG.default_coord_sys_class.create_from_wkt(coord_sys_data)
130
- else
131
- coord_sys = nil
132
- end
140
+ cs_class = CoordSys::CONFIG.default_coord_sys_class
141
+ coord_sys = data["cs"]&.then { |cs| cs_class.create_from_wkt(cs) }
142
+
133
143
  initialize(
134
144
  has_z_coordinate: data["hasz"],
135
145
  has_m_coordinate: data["hasm"],
@@ -160,11 +170,9 @@ module RGeo
160
170
  end
161
171
 
162
172
  def init_with(coder) # :nodoc:
163
- if (coord_sys_data = coder["cs"])
164
- coord_sys = CoordSys::CONFIG.default_coord_sys_class.create_from_wkt(coord_sys_data.to_s)
165
- else
166
- coord_sys = nil
167
- end
173
+ cs_class = CoordSys::CONFIG.default_coord_sys_class
174
+ coord_sys = coder["cs"]&.then { |cs| cs_class.create_from_wkt(cs) }
175
+
168
176
  initialize(
169
177
  has_z_coordinate: coder["has_z_coordinate"],
170
178
  has_m_coordinate: coder["has_m_coordinate"],
@@ -179,15 +187,6 @@ module RGeo
179
187
  )
180
188
  end
181
189
 
182
- # Returns the SRID of geometries created by this factory.
183
-
184
- attr_reader :srid
185
-
186
- # Returns the resolution used by buffer calculations on geometries
187
- # created by this factory
188
-
189
- attr_reader :buffer_resolution
190
-
191
190
  # See RGeo::Feature::Factory#property
192
191
  def property(name_)
193
192
  case name_
@@ -328,8 +327,13 @@ module RGeo
328
327
  def multi_point(elems)
329
328
  elems = elems.to_a unless elems.is_a?(Array)
330
329
  elems = elems.map do |elem|
331
- elem = RGeo::Feature.cast(elem, self, RGeo::Feature::Point,
332
- :force_new, :keep_subtype)
330
+ elem = RGeo::Feature.cast(
331
+ elem,
332
+ self,
333
+ RGeo::Feature::Point,
334
+ :force_new,
335
+ :keep_subtype
336
+ )
333
337
  return unless elem
334
338
  elem.detach_fg_geom
335
339
  end
@@ -367,13 +371,9 @@ module RGeo
367
371
  FFIMultiPolygonImpl.new(self, fg_geom, klasses)
368
372
  end
369
373
 
370
- # See RGeo::Feature::Factory#coord_sys
371
-
372
- attr_reader :coord_sys
373
-
374
374
  # See RGeo::Feature::Factory#override_cast
375
375
 
376
- def override_cast(original, ntype, flags)
376
+ def override_cast(_original, _ntype, _flags)
377
377
  false
378
378
  # TODO
379
379
  end
@@ -421,14 +421,13 @@ module RGeo
421
421
  klass.new(self, fg_geom, klasses)
422
422
  end
423
423
 
424
- attr_reader :_has_3d # :nodoc:
425
- attr_reader :_auto_prepare # :nodoc:
426
-
427
424
  def convert_to_fg_geometry(obj, type = nil)
428
- if type && obj.factory != self
429
- obj = Feature.cast(obj, self, type)
430
- end
431
- obj&.fg_geom
425
+ obj = Feature.cast(obj, self, type) if type && obj.factory != self
426
+
427
+ geom = obj&.fg_geom
428
+ raise RGeo::Error::InvalidGeometry, "Unable to cast the geometry to the FFI Factory" if geom.nil?
429
+
430
+ geom
432
431
  end
433
432
 
434
433
  def generate_wkt(geom)
@@ -480,7 +479,7 @@ module RGeo
480
479
 
481
480
  def create_fg_linear_ring(points)
482
481
  size = points.size
483
- return if size == 1 || size == 2
482
+ return if size.between?(1, 2)
484
483
  if size > 0 && points.first != points.last
485
484
  points += [points.first]
486
485
  size += 1