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
@@ -19,9 +19,7 @@ module RGeo
19
19
  # LineStrings in general need to check that there's not one point
20
20
  # GEOS doesn't allow instantiation of single point LineStrings so
21
21
  # we should handle it.
22
- if @points.size == 1
23
- raise Error::InvalidGeometry, "LineString Cannot Have 1 Point"
24
- end
22
+ raise Error::InvalidGeometry, "LineString Cannot Have 1 Point" if @points.size == 1
25
23
  init_geometry
26
24
  end
27
25
 
@@ -29,8 +27,8 @@ module RGeo
29
27
  @points.size
30
28
  end
31
29
 
32
- def point_n(n)
33
- n < 0 ? nil : @points[n]
30
+ def point_n(idx)
31
+ idx < 0 ? nil : @points[idx]
34
32
  end
35
33
 
36
34
  def points
@@ -64,10 +62,9 @@ module RGeo
64
62
  end
65
63
 
66
64
  def closed?
67
- unless defined?(@closed)
68
- @closed = @points.size > 2 && @points.first == @points.last
69
- end
70
- @closed
65
+ return @closed if defined?(@closed)
66
+
67
+ @closed = @points.size > 2 && @points.first == @points.last
71
68
  end
72
69
 
73
70
  def ring?
@@ -111,15 +108,15 @@ module RGeo
111
108
  def point_intersect_segment?(point, start_point, end_point)
112
109
  return false unless point_collinear?(point, start_point, end_point)
113
110
 
114
- if start_point.x != end_point.x
115
- between_coordinate?(point.x, start_point.x, end_point.x)
116
- else
111
+ if start_point.x == end_point.x
117
112
  between_coordinate?(point.y, start_point.y, end_point.y)
113
+ else
114
+ between_coordinate?(point.x, start_point.x, end_point.x)
118
115
  end
119
116
  end
120
117
 
121
- def point_collinear?(a, b, c)
122
- (b.x - a.x) * (c.y - a.y) == (c.x - a.x) * (b.y - a.y)
118
+ def point_collinear?(pt1, pt2, pt3)
119
+ (pt2.x - pt1.x) * (pt3.y - pt1.y) == (pt3.x - pt1.x) * (pt2.y - pt1.y)
123
120
  end
124
121
 
125
122
  def between_coordinate?(coord, start_coord, end_coord)
@@ -137,9 +134,7 @@ module RGeo
137
134
  def initialize(factory, start, stop)
138
135
  self.factory = factory
139
136
  cstart = Feature.cast(start, factory, Feature::Point)
140
- unless cstart
141
- raise Error::InvalidGeometry, "Could not cast start: #{start}"
142
- end
137
+ raise Error::InvalidGeometry, "Could not cast start: #{start}" unless cstart
143
138
  cstop = Feature.cast(stop, factory, Feature::Point)
144
139
  raise Error::InvalidGeometry, "Could not cast end: #{stop}" unless cstop
145
140
  @points = [cstart, cstop]
@@ -158,9 +153,7 @@ module RGeo
158
153
  module BasicLinearRingMethods # :nodoc:
159
154
  def initialize(factory, points)
160
155
  super
161
- unless @points.size >= 4 || @points.size == 0
162
- raise Error::InvalidGeometry, "LinearRings must have 0 or >= 4 points"
163
- end
156
+ raise Error::InvalidGeometry, "LinearRings must have 0 or >= 4 points" if @points.size.between?(1, 3)
164
157
  end
165
158
 
166
159
  def geometry_type
@@ -176,10 +169,11 @@ module RGeo
176
169
  # Close ring if necessary.
177
170
  def init_geometry
178
171
  super
179
- if @points.size > 0
180
- @points << @points.first if @points.first != @points.last
181
- @points = @points.chunk { |x| x }.map(&:first)
182
- end
172
+
173
+ return if @points.empty?
174
+
175
+ @points << @points.first if @points.first != @points.last
176
+ @points = @points.chunk { |x| x }.map(&:first)
183
177
  end
184
178
  end
185
179
  end
@@ -15,9 +15,7 @@ module RGeo
15
15
  @y = y.to_f
16
16
  @z = factory.property(:has_z_coordinate) ? extra.shift.to_f : nil
17
17
  @m = factory.property(:has_m_coordinate) ? extra.shift.to_f : nil
18
- if extra.size > 0
19
- raise ArgumentError, "Too many arguments for point initializer"
20
- end
18
+ raise ArgumentError, "Too many arguments for point initializer" unless extra.empty?
21
19
  init_geometry
22
20
  end
23
21
 
@@ -12,14 +12,10 @@ module RGeo
12
12
  def initialize(factory, exterior_ring, interior_rings)
13
13
  self.factory = factory
14
14
  @exterior_ring = Feature.cast(exterior_ring, factory, Feature::LinearRing)
15
- unless @exterior_ring
16
- raise Error::InvalidGeometry, "Failed to cast exterior ring #{exterior_ring}"
17
- end
15
+ raise Error::InvalidGeometry, "Failed to cast exterior ring #{exterior_ring}" unless @exterior_ring
18
16
  @interior_rings = (interior_rings || []).map do |elem|
19
17
  elem = Feature.cast(elem, factory, Feature::LinearRing)
20
- unless elem
21
- raise Error::InvalidGeometry, "Could not cast interior ring #{elem}"
22
- end
18
+ raise Error::InvalidGeometry, "Could not cast interior ring #{elem}" unless elem
23
19
  elem
24
20
  end
25
21
  init_geometry
@@ -33,8 +29,8 @@ module RGeo
33
29
  @interior_rings.size
34
30
  end
35
31
 
36
- def interior_ring_n(n)
37
- n < 0 ? nil : @interior_rings[n]
32
+ def interior_ring_n(idx)
33
+ idx < 0 ? nil : @interior_rings[idx]
38
34
  end
39
35
 
40
36
  def interior_rings
@@ -61,11 +57,14 @@ module RGeo
61
57
  end
62
58
 
63
59
  def rep_equals?(rhs)
64
- if rhs.is_a?(self.class) && rhs.factory.eql?(@factory) && @exterior_ring.rep_equals?(rhs.exterior_ring) && @interior_rings.size == rhs.num_interior_rings
65
- rhs.interior_rings.each_with_index { |r, i| return false unless @interior_rings[i].rep_equals?(r) }
66
- else
67
- false
68
- end
60
+ proper_match = rhs.is_a?(self.class) &&
61
+ rhs.factory.eql?(@factory) &&
62
+ @exterior_ring.rep_equals?(rhs.exterior_ring) &&
63
+ @interior_rings.size == rhs.num_interior_rings
64
+
65
+ return false unless proper_match
66
+
67
+ rhs.interior_rings.each_with_index { |r, i| return false unless @interior_rings[i].rep_equals?(r) }
69
68
  end
70
69
 
71
70
  def hash
@@ -80,7 +79,8 @@ module RGeo
80
79
  if Feature::Point === rhs
81
80
  contains_point?(rhs)
82
81
  else
83
- raise(Error::UnsupportedOperation,
82
+ raise(
83
+ Error::UnsupportedOperation,
84
84
  "Method Polygon#contains? is only defined for Point"
85
85
  )
86
86
  end
@@ -90,7 +90,7 @@ module RGeo
90
90
 
91
91
  def contains_point?(point)
92
92
  ring_encloses_point?(@exterior_ring, point) &&
93
- !@interior_rings.any? do |exclusion|
93
+ @interior_rings.none? do |exclusion|
94
94
  ring_encloses_point?(exclusion, point, on_border_return: true)
95
95
  end
96
96
  end
@@ -114,7 +114,6 @@ module RGeo
114
114
  encloses_point
115
115
  end
116
116
 
117
-
118
117
  def copy_state_from(obj)
119
118
  super
120
119
  @exterior_ring = obj.exterior_ring
@@ -18,20 +18,14 @@ module RGeo
18
18
  # multiple times with different values and others pass the data
19
19
  # to a CAPI or FFI.
20
20
  def self.setup_coord_sys(srid, coord_sys, coord_sys_class)
21
- unless coord_sys_class.is_a?(Class)
22
- coord_sys_class = CoordSys::CONFIG.default_coord_sys_class
23
- end
21
+ coord_sys_class = CoordSys::CONFIG.default_coord_sys_class unless coord_sys_class.is_a?(Class)
24
22
 
25
- if coord_sys.is_a?(String)
26
- coord_sys = coord_sys_class.create_from_wkt(coord_sys)
27
- end
23
+ coord_sys = coord_sys_class.create_from_wkt(coord_sys) if coord_sys.is_a?(String)
28
24
 
29
25
  srid ||= coord_sys.authority_code if coord_sys
30
26
  srid = srid.to_i
31
27
  # Create a coord sys based on the SRID if one was not given
32
- if coord_sys.nil? && srid != 0
33
- coord_sys = coord_sys_class.create(srid)
34
- end
28
+ coord_sys = coord_sys_class.create(srid) if coord_sys.nil? && srid != 0
35
29
 
36
30
  { coord_sys: coord_sys, srid: srid }
37
31
  end
@@ -181,12 +181,12 @@ module RGeo
181
181
 
182
182
  # Checks that the given point has valid coordinates.
183
183
  #
184
- # @param pt [RGeo::Feature::Point]
184
+ # @param point [RGeo::Feature::Point]
185
185
  #
186
186
  # @return [String] invalid_reason
187
- def check_invalid_coordinate(pt)
188
- x = pt.x
189
- y = pt.y
187
+ def check_invalid_coordinate(point)
188
+ x = point.x
189
+ y = point.y
190
190
  return if x.finite? && y.finite? && x.real? && y.real?
191
191
 
192
192
  Error::INVALID_COORDINATE
@@ -265,9 +265,7 @@ module RGeo
265
265
 
266
266
  poly.interior_rings.each do |interior|
267
267
  test_pt = interior.start_point
268
- unless shell.contains?(test_pt) || poly.exterior_ring.contains?(test_pt)
269
- return Error::HOLE_OUTSIDE_SHELL
270
- end
268
+ return Error::HOLE_OUTSIDE_SHELL unless shell.contains?(test_pt) || poly.exterior_ring.contains?(test_pt)
271
269
  end
272
270
 
273
271
  nil
@@ -322,27 +320,25 @@ module RGeo
322
320
 
323
321
  # Checks that polygons do not intersect in a multipolygon.
324
322
  #
325
- # @param mp [RGeo::Feature::MultiPolygon]
323
+ # @param mpoly [RGeo::Feature::MultiPolygon]
326
324
  #
327
325
  # @return [String] invalid_reason
328
- def check_consistent_area_mp(mp)
329
- mp.geometries.combination(2) do |p1, p2|
330
- if p1.exterior_ring.crosses?(p2.exterior_ring)
331
- return Error::SELF_INTERSECTION
332
- end
326
+ def check_consistent_area_mp(mpoly)
327
+ mpoly.geometries.combination(2) do |p1, p2|
328
+ return Error::SELF_INTERSECTION if p1.exterior_ring.crosses?(p2.exterior_ring)
333
329
  end
334
330
  nil
335
331
  end
336
332
 
337
333
  # Checks that individual polygons within a multipolygon are not nested.
338
334
  #
339
- # @param mp [RGeo::Feature::MultiPolygon]
335
+ # @param mpoly [RGeo::Feature::MultiPolygon]
340
336
  #
341
337
  # @return [String] invalid_reason
342
- def check_shells_not_nested(mp)
338
+ def check_shells_not_nested(mpoly)
343
339
  # Since we've passed the consistent area test, we can just check
344
340
  # that one point lies in the other.
345
- mp.geometries.combination(2) do |p1, p2|
341
+ mpoly.geometries.combination(2) do |p1, p2|
346
342
  if p1.contains?(p2.exterior_ring.start_point) || p2.contains?(p1.exterior_ring.start_point)
347
343
  return Error::NESTED_SHELLS
348
344
  end
data/lib/rgeo/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RGeo
4
- VERSION = "3.0.0-rc.3"
4
+ VERSION = "3.0.0"
5
5
  end
@@ -39,7 +39,6 @@ module RGeo
39
39
  # [<tt>:little_endian</tt>]
40
40
  # If true, output little endian (NDR) byte order. If false, output
41
41
  # big endian (XDR), or network byte order. Default is false.
42
-
43
42
  class WKBGenerator
44
43
  # :stopdoc:
45
44
  TYPE_CODES = {
@@ -107,7 +106,7 @@ module RGeo
107
106
  has_m = false
108
107
  end
109
108
  result = Result.new(has_z, has_m)
110
- generate_feature(obj, result, true)
109
+ generate_feature(obj, result, toplevel: true)
111
110
  result.emit(@hex_format)
112
111
  end
113
112
 
@@ -126,7 +125,7 @@ module RGeo
126
125
 
127
126
  def emit(hex_format)
128
127
  str = @buffer.join
129
- hex_format ? str.unpack("H*")[0] : str
128
+ hex_format ? str.unpack1("H*") : str
130
129
  end
131
130
 
132
131
  def z?
@@ -139,79 +138,75 @@ module RGeo
139
138
  end
140
139
  private_constant :Result
141
140
 
142
- def emit_byte(value, rv)
143
- rv << [value].pack("C")
141
+ def emit_byte(value, rval)
142
+ rval << [value].pack("C")
144
143
  end
145
144
 
146
- def emit_integer(value, rv)
147
- rv << [value].pack(@little_endian ? "V" : "N")
145
+ def emit_integer(value, rval)
146
+ rval << [value].pack(@little_endian ? "V" : "N")
148
147
  end
149
148
 
150
- def emit_doubles(array, rv)
151
- rv << array.pack(@little_endian ? "E*" : "G*")
149
+ def emit_doubles(array, rval)
150
+ rval << array.pack(@little_endian ? "E*" : "G*")
152
151
  end
153
152
 
154
- def emit_line_string_coords(obj, rv)
153
+ def emit_line_string_coords(obj, rval)
155
154
  array = []
156
- obj.points.each { |pt| point_coords(pt, rv, array) }
157
- emit_integer(obj.num_points, rv)
158
- emit_doubles(array, rv)
155
+ obj.points.each { |pt| point_coords(pt, rval, array) }
156
+ emit_integer(obj.num_points, rval)
157
+ emit_doubles(array, rval)
159
158
  end
160
159
 
161
- def point_coords(obj, rv, array = [])
160
+ def point_coords(obj, rval, array = [])
162
161
  array << obj.x
163
162
  array << obj.y
164
- array << obj.z if rv.z?
165
- array << obj.m if rv.m?
163
+ array << obj.z if rval.z?
164
+ array << obj.m if rval.m?
166
165
  array
167
166
  end
168
167
 
169
- def generate_feature(obj, rv, toplevel = false)
170
- emit_byte(@little_endian ? 1 : 0, rv)
168
+ def generate_feature(obj, rval, toplevel: false)
169
+ emit_byte(@little_endian ? 1 : 0, rval)
171
170
  type = obj.geometry_type
172
171
  type_code = TYPE_CODES[type]
173
- unless type_code
174
- raise Error::ParseError, "Unrecognized Geometry Type: #{type}"
175
- end
172
+ raise Error::ParseError, "Unrecognized Geometry Type: #{type}" unless type_code
176
173
  emit_srid = false
177
- if @type_format == :ewkb
178
- type_code |= 0x80000000 if rv.z?
179
- type_code |= 0x40000000 if rv.m?
174
+ case @type_format
175
+ when :ewkb
176
+ type_code |= 0x80000000 if rval.z?
177
+ type_code |= 0x40000000 if rval.m?
180
178
  if @emit_ewkb_srid && toplevel
181
179
  type_code |= 0x20000000
182
180
  emit_srid = true
183
181
  end
184
- elsif @type_format == :wkb12
185
- type_code += 1000 if rv.z?
186
- type_code += 2000 if rv.m?
182
+ when :wkb12
183
+ type_code += 1000 if rval.z?
184
+ type_code += 2000 if rval.m?
187
185
  end
188
- emit_integer(type_code, rv)
189
- emit_integer(obj.srid, rv) if emit_srid
186
+ emit_integer(type_code, rval)
187
+ emit_integer(obj.srid, rval) if emit_srid
188
+ type_is_collection = [
189
+ Feature::GeometryCollection,
190
+ Feature::MultiPoint,
191
+ Feature::MultiLineString,
192
+ Feature::MultiPolygon
193
+ ].include?(type)
190
194
  if type == Feature::Point
191
- emit_doubles(point_coords(obj, rv), rv)
195
+ emit_doubles(point_coords(obj, rval), rval)
192
196
  elsif type.subtype_of?(Feature::LineString)
193
- emit_line_string_coords(obj, rv)
197
+ emit_line_string_coords(obj, rval)
194
198
  elsif type == Feature::Polygon
195
199
  exterior_ring = obj.exterior_ring
196
200
  if exterior_ring.empty?
197
- emit_integer(0, rv)
201
+ emit_integer(0, rval)
198
202
  else
199
- emit_integer(1 + obj.num_interior_rings, rv)
200
- emit_line_string_coords(exterior_ring, rv)
201
- obj.interior_rings.each { |r| emit_line_string_coords(r, rv) }
203
+ emit_integer(1 + obj.num_interior_rings, rval)
204
+ emit_line_string_coords(exterior_ring, rval)
205
+ obj.interior_rings.each { |r| emit_line_string_coords(r, rval) }
202
206
  end
203
- elsif type == Feature::GeometryCollection
204
- emit_integer(obj.num_geometries, rv)
205
- obj.each { |g| generate_feature(g, rv) }
206
- elsif type == Feature::MultiPoint
207
- emit_integer(obj.num_geometries, rv)
208
- obj.each { |g| generate_feature(g, rv) }
209
- elsif type == Feature::MultiLineString
210
- emit_integer(obj.num_geometries, rv)
211
- obj.each { |g| generate_feature(g, rv) }
212
- elsif type == Feature::MultiPolygon
213
- emit_integer(obj.num_geometries, rv)
214
- obj.each { |g| generate_feature(g, rv) }
207
+ elsif type_is_collection
208
+ emit_integer(obj.num_geometries, rval)
209
+ obj.each { |g| generate_feature(g, rval) }
215
210
  end
216
211
  end
217
212
  end
@@ -42,7 +42,6 @@ module RGeo
42
42
  # [<tt>:default_srid</tt>]
43
43
  # A SRID to pass to the factory generator if no SRID is present in
44
44
  # the input. Defaults to nil (i.e. don't specify a SRID).
45
-
46
45
  class WKBParser
47
46
  # Create and configure a WKB parser. See the WKBParser
48
47
  # documentation for the options that can be passed.
@@ -118,9 +117,7 @@ module RGeo
118
117
  obj = parse_object(false)
119
118
  unless @ignore_extra_bytes
120
119
  bytes = bytes_remaining
121
- if bytes > 0
122
- raise Error::ParseError, "Found #{bytes} extra bytes at the end of the stream."
123
- end
120
+ raise Error::ParseError, "Found #{bytes} extra bytes at the end of the stream." if bytes > 0
124
121
  end
125
122
  ensure
126
123
  @data = nil
@@ -133,7 +130,7 @@ module RGeo
133
130
  private
134
131
 
135
132
  def parse_object(contained)
136
- endian_value = get_byte
133
+ endian_value = byte
137
134
  case endian_value
138
135
  when 0
139
136
  little_endian = false
@@ -161,14 +158,20 @@ module RGeo
161
158
  if contained != true && contained != type_code
162
159
  raise Error::ParseError, "Enclosed type=#{type_code} is different from container constraint #{contained}"
163
160
  end
161
+
164
162
  if has_z != @cur_has_z
165
163
  raise Error::ParseError, "Enclosed hasZ=#{has_z} is different from toplevel hasZ=#{@cur_has_z}"
166
164
  end
165
+
167
166
  if has_m != @cur_has_m
168
167
  raise Error::ParseError, "Enclosed hasM=#{has_m} is different from toplevel hasM=#{@cur_has_m}"
169
168
  end
169
+
170
170
  if srid && srid != @cur_srid
171
- raise Error::ParseError, "Enclosed SRID #{srid} is different from toplevel srid #{@cur_srid || '(unspecified)'}"
171
+ raise(
172
+ Error::ParseError,
173
+ "Enclosed SRID #{srid} is different from toplevel srid #{@cur_srid || '(unspecified)'}"
174
+ )
172
175
  end
173
176
  else
174
177
  @cur_has_z = has_z
@@ -176,9 +179,11 @@ module RGeo
176
179
  @cur_dims = 2 + (@cur_has_z ? 1 : 0) + (@cur_has_m ? 1 : 0)
177
180
  @cur_srid = srid
178
181
  @cur_factory = @factory_generator.call(srid: @cur_srid, has_z_coordinate: has_z, has_m_coordinate: has_m)
182
+
179
183
  if @cur_has_z && !@cur_factory.property(:has_z_coordinate)
180
184
  raise Error::ParseError, "Data has Z coordinates but the factory doesn't have Z coordinates"
181
185
  end
186
+
182
187
  if @cur_has_m && !@cur_factory.property(:has_m_coordinate)
183
188
  raise Error::ParseError, "Data has M coordinates but the factory doesn't have M coordinates"
184
189
  end
@@ -222,29 +227,23 @@ module RGeo
222
227
  @len - @pos
223
228
  end
224
229
 
225
- def get_byte
226
- if @pos + 1 > @len
227
- raise Error::ParseError, "Not enough bytes left to fulfill 1 byte"
228
- end
230
+ def byte
231
+ raise Error::ParseError, "Not enough bytes left to fulfill 1 byte" if @pos + 1 > @len
229
232
  str = @data[@pos, 1]
230
233
  @pos += 1
231
- str.unpack("C").first
234
+ str.unpack1("C")
232
235
  end
233
236
 
234
237
  def get_integer(little_endian)
235
- if @pos + 4 > @len
236
- raise Error::ParseError, "Not enough bytes left to fulfill 1 integer"
237
- end
238
+ raise Error::ParseError, "Not enough bytes left to fulfill 1 integer" if @pos + 4 > @len
238
239
  str = @data[@pos, 4]
239
240
  @pos += 4
240
- str.unpack(little_endian ? "V" : "N").first
241
+ str.unpack1(little_endian ? "V" : "N")
241
242
  end
242
243
 
243
244
  def get_doubles(little_endian, count)
244
245
  len = 8 * count
245
- if @pos + len > @len
246
- raise Error::ParseError, "Not enough bytes left to fulfill #{count} doubles"
247
- end
246
+ raise Error::ParseError, "Not enough bytes left to fulfill #{count} doubles" if @pos + len > @len
248
247
  str = @data[@pos, len]
249
248
  @pos += len
250
249
  str.unpack("#{little_endian ? 'E' : 'G'}*")
@@ -45,15 +45,16 @@ module RGeo
45
45
  # letters to lower case; or nil, indicating no case changes from
46
46
  # the default (which is not specified exactly, but is chosen by the
47
47
  # generator to emphasize readability.) Default is nil.
48
-
49
48
  class WKTGenerator
50
49
  # Create and configure a WKT generator. See the WKTGenerator
51
50
  # documentation for the options that can be passed.
52
51
 
53
52
  def initialize(opts = {})
54
53
  @tag_format = opts[:tag_format] || opts[:type_format] || :wkt11
55
- @emit_ewkt_srid = @tag_format == :ewkt ?
56
- (opts[:emit_ewkt_srid] ? true : false) : nil
54
+ @emit_ewkt_srid =
55
+ if @tag_format == :ewkt
56
+ (opts[:emit_ewkt_srid] ? true : false)
57
+ end
57
58
  @square_brackets = opts[:square_brackets] ? true : false
58
59
  @convert_case = opts[:convert_case]
59
60
  end
@@ -99,10 +100,11 @@ module RGeo
99
100
  support_z = factory.property(:has_z_coordinate)
100
101
  support_m = factory.property(:has_m_coordinate)
101
102
  end
102
- str = generate_feature(obj, support_z, support_m, true)
103
- if @convert_case == :upper
103
+ str = generate_feature(obj, support_z, support_m, toplevel: true)
104
+ case @convert_case
105
+ when :upper
104
106
  str.upcase
105
- elsif @convert_case == :lower
107
+ when :lower
106
108
  str.downcase
107
109
  else
108
110
  str
@@ -111,20 +113,22 @@ module RGeo
111
113
 
112
114
  private
113
115
 
114
- def generate_feature(obj, support_z, support_m, toplevel = false)
116
+ def generate_feature(obj, support_z, support_m, toplevel: false)
115
117
  type = obj.geometry_type
116
118
  type = Feature::LineString if type.subtype_of?(Feature::LineString)
117
119
  tag = type.type_name.dup
118
- if @tag_format == :ewkt
120
+ case @tag_format
121
+ when :ewkt
119
122
  tag << "M" if support_m && !support_z
120
123
  tag = "SRID=#{obj.srid};#{tag}" if toplevel && @emit_ewkt_srid
121
- elsif @tag_format == :wkt12
124
+ when :wkt12
122
125
  if support_z
123
- if support_m
124
- tag << " ZM"
125
- else
126
- tag << " Z"
127
- end
126
+ tag <<
127
+ if support_m
128
+ " ZM"
129
+ else
130
+ " Z"
131
+ end
128
132
  elsif support_m
129
133
  tag << " M"
130
134
  end
@@ -163,7 +167,8 @@ module RGeo
163
167
  if obj.empty?
164
168
  "EMPTY"
165
169
  else
166
- "#{@begin_bracket}#{obj.points.map { |p| generate_coords(p, support_z, support_m) }.join(', ')}#{@end_bracket}"
170
+ points = obj.points.map { |p| generate_coords(p, support_z, support_m) }
171
+ "#{@begin_bracket}#{points.join(', ')}#{@end_bracket}"
167
172
  end
168
173
  end
169
174
 
@@ -171,7 +176,9 @@ module RGeo
171
176
  if obj.empty?
172
177
  "EMPTY"
173
178
  else
174
- "#{@begin_bracket}#{([generate_line_string(obj.exterior_ring, support_z, support_m)] + obj.interior_rings.map { |r| generate_line_string(r, support_z, support_m) }).join(', ')}#{@end_bracket}"
179
+ lines = [generate_line_string(obj.exterior_ring, support_z, support_m)]
180
+ lines += obj.interior_rings.map { |r| generate_line_string(r, support_z, support_m) }
181
+ "#{@begin_bracket}#{lines.join(', ')}#{@end_bracket}"
175
182
  end
176
183
  end
177
184