rgeo 3.0.0.pre.rc.3 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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