rgeo 3.0.0.pre.rc.2 → 3.0.0.pre.rc.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/ext/geos_c_impl/analysis.c +26 -23
  4. data/ext/geos_c_impl/analysis.h +8 -5
  5. data/ext/geos_c_impl/coordinates.c +27 -21
  6. data/ext/geos_c_impl/coordinates.h +5 -2
  7. data/ext/geos_c_impl/errors.c +15 -8
  8. data/ext/geos_c_impl/errors.h +4 -1
  9. data/ext/geos_c_impl/extconf.rb +40 -30
  10. data/ext/geos_c_impl/factory.c +367 -387
  11. data/ext/geos_c_impl/factory.h +59 -48
  12. data/ext/geos_c_impl/geometry.c +368 -320
  13. data/ext/geos_c_impl/geometry.h +5 -5
  14. data/ext/geos_c_impl/geometry_collection.c +256 -183
  15. data/ext/geos_c_impl/geometry_collection.h +6 -7
  16. data/ext/geos_c_impl/globals.c +99 -21
  17. data/ext/geos_c_impl/globals.h +3 -2
  18. data/ext/geos_c_impl/line_string.c +229 -198
  19. data/ext/geos_c_impl/line_string.h +5 -6
  20. data/ext/geos_c_impl/main.c +8 -9
  21. data/ext/geos_c_impl/point.c +62 -63
  22. data/ext/geos_c_impl/point.h +4 -5
  23. data/ext/geos_c_impl/polygon.c +116 -84
  24. data/ext/geos_c_impl/polygon.h +10 -8
  25. data/ext/geos_c_impl/preface.h +4 -13
  26. data/ext/geos_c_impl/ruby_more.c +35 -40
  27. data/ext/geos_c_impl/ruby_more.h +3 -2
  28. data/lib/rgeo/cartesian/bounding_box.rb +1 -1
  29. data/lib/rgeo/cartesian/factory.rb +8 -43
  30. data/lib/rgeo/cartesian/feature_methods.rb +0 -5
  31. data/lib/rgeo/cartesian/interface.rb +6 -5
  32. data/lib/rgeo/coord_sys/cs/entities.rb +214 -0
  33. data/lib/rgeo/coord_sys/cs/wkt_parser.rb +15 -8
  34. data/lib/rgeo/coord_sys.rb +1 -9
  35. data/lib/rgeo/feature/curve.rb +0 -10
  36. data/lib/rgeo/feature/factory.rb +1 -9
  37. data/lib/rgeo/feature/factory_generator.rb +3 -7
  38. data/lib/rgeo/feature/geometry.rb +0 -10
  39. data/lib/rgeo/feature/multi_curve.rb +0 -5
  40. data/lib/rgeo/feature/types.rb +5 -5
  41. data/lib/rgeo/geographic/factory.rb +9 -42
  42. data/lib/rgeo/geographic/interface.rb +28 -99
  43. data/lib/rgeo/geographic/projected_feature_methods.rb +0 -10
  44. data/lib/rgeo/geographic/projected_window.rb +1 -1
  45. data/lib/rgeo/geographic/{proj4_projector.rb → projector.rb} +3 -3
  46. data/lib/rgeo/geographic/simple_mercator_projector.rb +1 -10
  47. data/lib/rgeo/geographic/spherical_feature_methods.rb +0 -5
  48. data/lib/rgeo/geographic.rb +1 -1
  49. data/lib/rgeo/geos/capi_factory.rb +37 -91
  50. data/lib/rgeo/geos/capi_feature_classes.rb +0 -29
  51. data/lib/rgeo/geos/ffi_factory.rb +52 -92
  52. data/lib/rgeo/geos/ffi_feature_methods.rb +1 -31
  53. data/lib/rgeo/geos/interface.rb +5 -20
  54. data/lib/rgeo/geos/zm_factory.rb +5 -36
  55. data/lib/rgeo/geos/zm_feature_methods.rb +1 -26
  56. data/lib/rgeo/geos.rb +2 -5
  57. data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +1 -14
  58. data/lib/rgeo/impl_helper/basic_line_string_methods.rb +1 -19
  59. data/lib/rgeo/impl_helper/basic_point_methods.rb +0 -10
  60. data/lib/rgeo/impl_helper/basic_polygon_methods.rb +1 -9
  61. data/lib/rgeo/impl_helper/utils.rb +27 -0
  62. data/lib/rgeo/impl_helper/validity_check.rb +3 -3
  63. data/lib/rgeo/version.rb +1 -1
  64. data/lib/rgeo/wkrep/wkb_generator.rb +68 -53
  65. data/lib/rgeo/wkrep/wkb_parser.rb +19 -16
  66. data/lib/rgeo/wkrep/wkt_generator.rb +34 -34
  67. data/lib/rgeo/wkrep/wkt_parser.rb +26 -23
  68. data/lib/rgeo.rb +1 -3
  69. metadata +7 -6
@@ -41,7 +41,6 @@ module RGeo
41
41
  end
42
42
 
43
43
  def initialize(opts = {}) # :nodoc:
44
- proj4 = opts[:proj4]
45
44
  coord_sys = opts[:coord_sys]
46
45
  srid = opts[:srid]
47
46
  srid ||= coord_sys.authority_code if coord_sys
@@ -49,7 +48,7 @@ module RGeo
49
48
  buffer_resolution: opts[:buffer_resolution], auto_prepare: opts[:auto_prepare],
50
49
  wkt_generator: opts[:wkt_generator], wkt_parser: opts[:wkt_parser],
51
50
  wkb_generator: opts[:wkb_generator], wkb_parser: opts[:wkb_parser],
52
- srid: srid.to_i, proj4: proj4, coord_sys: coord_sys
51
+ srid: srid.to_i, coord_sys: coord_sys
53
52
  }
54
53
  native_interface = opts[:native_interface] || Geos.preferred_native_interface
55
54
  if native_interface == :ffi
@@ -103,22 +102,14 @@ module RGeo
103
102
  "apre" => @zfactory.property(:auto_prepare) == :simple,
104
103
  "nffi" => @zfactory.is_a?(FFIFactory)
105
104
  }
106
- proj4 = @zfactory.proj4
107
105
  coord_sys = @zfactory.coord_sys
108
- hash["proj4"] = proj4.marshal_dump if proj4
109
106
  hash["cs"] = coord_sys.to_wkt if coord_sys
110
107
  hash
111
108
  end
112
109
 
113
110
  def marshal_load(data) # :nodoc:
114
- if (proj4_data = data["proj4"]) && CoordSys.check!(:proj4)
115
- proj4 = CoordSys::Proj4.allocate
116
- proj4.marshal_load(proj4_data)
117
- else
118
- proj4 = nil
119
- end
120
111
  if (coord_sys_data = data["cs"])
121
- coord_sys = CoordSys::CS.create_from_wkt(coord_sys_data)
112
+ coord_sys = CoordSys::CONFIG.default_coord_sys_class.create_from_wkt(coord_sys_data)
122
113
  else
123
114
  coord_sys = nil
124
115
  end
@@ -133,7 +124,6 @@ module RGeo
133
124
  wkt_parser: symbolize_hash(data["wktp"]),
134
125
  wkb_parser: symbolize_hash(data["wkbp"]),
135
126
  auto_prepare: (data["apre"] ? :simple : :disabled),
136
- proj4: proj4,
137
127
  coord_sys: coord_sys
138
128
  )
139
129
  end
@@ -149,28 +139,14 @@ module RGeo
149
139
  coder["wkb_parser"] = @wkb_parser.properties
150
140
  coder["auto_prepare"] = @zfactory.property(:auto_prepare).to_s
151
141
  coder["native_interface"] = @zfactory.is_a?(FFIFactory) ? "ffi" : "capi"
152
- if (proj4 = @zfactory.proj4)
153
- str = proj4.original_str || proj4.canonical_str
154
- coder["proj4"] = proj4.radians? ? { "proj4" => str, "radians" => true } : str
155
- end
156
142
  if (coord_sys = @zfactory.coord_sys)
157
143
  coder["coord_sys"] = coord_sys.to_wkt
158
144
  end
159
145
  end
160
146
 
161
147
  def init_with(coder) # :nodoc:
162
- if (proj4_data = coder["proj4"])
163
- CoordSys.check!(:proj4)
164
- if proj4_data.is_a?(Hash)
165
- proj4 = CoordSys::Proj4.create(proj4_data["proj4"], radians: proj4_data["radians"])
166
- else
167
- proj4 = CoordSys::Proj4.create(proj4_data.to_s)
168
- end
169
- else
170
- proj4 = nil
171
- end
172
148
  if (coord_sys_data = coder["cs"])
173
- coord_sys = CoordSys::CS.create_from_wkt(coord_sys_data.to_s)
149
+ coord_sys = CoordSys::CONFIG.default_coord_sys_class.create_from_wkt(coord_sys_data.to_s)
174
150
  else
175
151
  coord_sys = nil
176
152
  end
@@ -185,7 +161,6 @@ module RGeo
185
161
  wkt_parser: symbolize_hash(coder["wkt_parser"]),
186
162
  wkb_parser: symbolize_hash(coder["wkb_parser"]),
187
163
  auto_prepare: coder["auto_prepare"] == "disabled" ? :disabled : :simple,
188
- proj4: proj4,
189
164
  coord_sys: coord_sys
190
165
  )
191
166
  end
@@ -303,12 +278,6 @@ module RGeo
303
278
  create_feature(ZMMultiPolygonImpl, @zfactory.multi_polygon(elems), @mfactory.multi_polygon(elems))
304
279
  end
305
280
 
306
- # See RGeo::Feature::Factory#proj4
307
-
308
- def proj4
309
- @zfactory.proj4
310
- end
311
-
312
281
  # See RGeo::Feature::Factory#coord_sys
313
282
 
314
283
  def coord_sys
@@ -328,7 +297,7 @@ module RGeo
328
297
  # Optimization if we're just changing factories, but to
329
298
  # another ZM factory.
330
299
  if original.factory != self && ntype == type &&
331
- (!project || original.factory.proj4 == @proj4)
300
+ (!project || original.factory.coord_sys == @coord_sys)
332
301
  zresult = original.z_geometry.dup
333
302
  zresult.factory = @zfactory
334
303
  mresult = original.m_geometry.dup
@@ -337,7 +306,7 @@ module RGeo
337
306
  end
338
307
  # LineString conversion optimization.
339
308
  if (original.factory != self || ntype != type) &&
340
- (!project || original.factory.proj4 == @proj4) &&
309
+ (!project || original.factory.coord_sys == @coord_sys) &&
341
310
  type.subtypeof?(Feature::LineString) && ntype.subtypeof?(Feature::LineString)
342
311
  klass = Factory::IMPL_CLASSES[ntype]
343
312
  zresult = klass._copy_from(@zfactory, original.z_geometry)
@@ -26,7 +26,7 @@ module RGeo
26
26
  end
27
27
 
28
28
  def hash
29
- @factory.hash ^ @zgeometry.hash ^ @mgeometry.hash
29
+ [@factory, @zgeometry, @mgeometry].hash
30
30
  end
31
31
 
32
32
  def factory
@@ -77,20 +77,10 @@ module RGeo
77
77
  @zgeometry.empty?
78
78
  end
79
79
 
80
- def is_empty?
81
- warn "The is_empty? method is deprecated, please use the empty? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
82
- empty?
83
- end
84
-
85
80
  def simple?
86
81
  @zgeometry.simple?
87
82
  end
88
83
 
89
- def is_simple?
90
- warn "The is_simple? method is deprecated, please use the simple? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
91
- simple?
92
- end
93
-
94
84
  def is_3d?
95
85
  true
96
86
  end
@@ -252,20 +242,10 @@ module RGeo
252
242
  @zgeometry.closed?
253
243
  end
254
244
 
255
- def is_closed?
256
- warn "The is_closed? method is deprecated, please use the closed? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
257
- closed?
258
- end
259
-
260
245
  def ring?
261
246
  @zgeometry.ring?
262
247
  end
263
248
 
264
- def is_ring?
265
- warn "The is_ring? method is deprecated, please use the ring? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
266
- ring?
267
- end
268
-
269
249
  def num_points
270
250
  @zgeometry.num_points
271
251
  end
@@ -363,11 +343,6 @@ module RGeo
363
343
  @zgeometry.closed?
364
344
  end
365
345
 
366
- def is_closed?
367
- warn "The is_closed? method is deprecated, please use the closed? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
368
- closed?
369
- end
370
-
371
346
  def coordinates
372
347
  each.map(&:coordinates)
373
348
  end
data/lib/rgeo/geos.rb CHANGED
@@ -45,12 +45,9 @@ module RGeo
45
45
  raise "Problem loading FFI" unless ::FFI::AutoPointer
46
46
  FFI_SUPPORTED = true
47
47
  FFI_SUPPORT_EXCEPTION = nil
48
- rescue LoadError => ex
48
+ rescue LoadError, StandardError => e
49
49
  FFI_SUPPORTED = false
50
- FFI_SUPPORT_EXCEPTION = ex
51
- rescue StandardError => ex
52
- FFI_SUPPORTED = false
53
- FFI_SUPPORT_EXCEPTION = ex
50
+ FFI_SUPPORT_EXCEPTION = e
54
51
  end
55
52
 
56
53
  if FFI_SUPPORTED
@@ -55,11 +55,6 @@ module RGeo
55
55
  @elements.size == 0
56
56
  end
57
57
 
58
- def is_empty?
59
- warn "The is_empty? method is deprecated, please use the empty? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
60
- empty?
61
- end
62
-
63
58
  def rep_equals?(rhs)
64
59
  if rhs.is_a?(self.class) && rhs.factory.eql?(@factory) && @elements.size == rhs.num_geometries
65
60
  rhs.each_with_index { |p, i| return false unless @elements[i].rep_equals?(p) }
@@ -69,10 +64,7 @@ module RGeo
69
64
  end
70
65
 
71
66
  def hash
72
- @hash ||= begin
73
- hash = [factory, geometry_type].hash
74
- @elements.inject(hash) { |h, g| (1_664_525 * h + g.hash).hash }
75
- end
67
+ @hash ||= [factory, geometry_type, *@elements].hash
76
68
  end
77
69
 
78
70
  private
@@ -102,11 +94,6 @@ module RGeo
102
94
  all?(&:closed?)
103
95
  end
104
96
 
105
- def is_closed?
106
- warn "The is_closed? method is deprecated, please use the closed? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
107
- closed?
108
- end
109
-
110
97
  def length
111
98
  @elements.inject(0.0) { |sum, obj| sum + obj.length }
112
99
  end
@@ -49,11 +49,6 @@ module RGeo
49
49
  @points.size == 0
50
50
  end
51
51
 
52
- def is_empty?
53
- warn "The is_empty? method is deprecated, please use the empty? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
54
- empty?
55
- end
56
-
57
52
  def boundary
58
53
  array = []
59
54
  array << @points.first << @points.last if !empty? && !closed?
@@ -75,20 +70,10 @@ module RGeo
75
70
  @closed
76
71
  end
77
72
 
78
- def is_closed?
79
- warn "The is_closed? method is deprecated, please use the closed? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
80
- closed?
81
- end
82
-
83
73
  def ring?
84
74
  closed? && simple?
85
75
  end
86
76
 
87
- def is_ring?
88
- warn "The is_ring? method is deprecated, please use the ring? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
89
- ring?
90
- end
91
-
92
77
  def rep_equals?(rhs)
93
78
  if rhs.is_a?(self.class) && rhs.factory.eql?(@factory) && @points.size == rhs.num_points
94
79
  rhs.points.each_with_index { |p, i| return false unless @points[i].rep_equals?(p) }
@@ -98,10 +83,7 @@ module RGeo
98
83
  end
99
84
 
100
85
  def hash
101
- @hash ||= begin
102
- hash = [factory, geometry_type].hash
103
- @points.inject(hash) { |h, p| (1_664_525 * h + p.hash).hash }
104
- end
86
+ @hash ||= [factory, geometry_type, *@points].hash
105
87
  end
106
88
 
107
89
  def coordinates
@@ -49,20 +49,10 @@ module RGeo
49
49
  false
50
50
  end
51
51
 
52
- def is_empty?
53
- warn "The is_empty? method is deprecated, please use the empty? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
54
- empty?
55
- end
56
-
57
52
  def simple?
58
53
  true
59
54
  end
60
55
 
61
- def is_simple?
62
- warn "The is_simple? method is deprecated, please use the simple? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
63
- simple?
64
- end
65
-
66
56
  def envelope
67
57
  self
68
58
  end
@@ -53,11 +53,6 @@ module RGeo
53
53
  @exterior_ring.empty?
54
54
  end
55
55
 
56
- def is_empty?
57
- warn "The is_empty? method is deprecated, please use the empty? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
58
- empty?
59
- end
60
-
61
56
  def boundary
62
57
  array = []
63
58
  array << @exterior_ring unless @exterior_ring.empty?
@@ -74,10 +69,7 @@ module RGeo
74
69
  end
75
70
 
76
71
  def hash
77
- @hash ||= begin
78
- hash = [geometry_type, @exterior_ring].hash
79
- @interior_rings.inject(hash) { |h, r| (1_664_525 * h + r.hash).hash }
80
- end
72
+ @hash ||= [geometry_type, @exterior_ring, *@interior_rings].hash
81
73
  end
82
74
 
83
75
  def coordinates
@@ -9,6 +9,33 @@
9
9
  module RGeo
10
10
  module ImplHelper # :nodoc:
11
11
  module Utils # :nodoc:
12
+ # Helper function to create coord_sys from
13
+ # common options in most factories. Returns
14
+ # a hash with finalized coord sys info after processing.
15
+ #
16
+ # The reason we return the data as a hash instead of assigning
17
+ # instance variables is because some classes need to do this
18
+ # multiple times with different values and others pass the data
19
+ # to a CAPI or FFI.
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
24
+
25
+ if coord_sys.is_a?(String)
26
+ coord_sys = coord_sys_class.create_from_wkt(coord_sys)
27
+ end
28
+
29
+ srid ||= coord_sys.authority_code if coord_sys
30
+ srid = srid.to_i
31
+ # 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
35
+
36
+ { coord_sys: coord_sys, srid: srid }
37
+ end
38
+
12
39
  private
13
40
 
14
41
  def symbolize_hash(hash)
@@ -31,7 +31,7 @@ module RGeo
31
31
  # Trivial methods
32
32
  :num_points, :locate_along, :locate_between,
33
33
  # Comparison
34
- :equals?, :rep_equals?, :eql?, :==, :'!='
34
+ :equals?, :rep_equals?, :eql?, :==, :"!="
35
35
  ].freeze
36
36
  private_constant :UNCHECKED_METHODS
37
37
 
@@ -109,7 +109,7 @@ module RGeo
109
109
  def invalid_reason
110
110
  if defined?(super) == "super"
111
111
  raise Error::RGeoError, "ValidityCheck MUST be loaded before " \
112
- "definition of #{self.class}##{__method__}."
112
+ "definition of #{self.class}##{__method__}."
113
113
  end
114
114
 
115
115
  raise Error::UnsupportedOperation, "Method #{self.class}##{__method__} not defined."
@@ -120,7 +120,7 @@ module RGeo
120
120
  def make_valid
121
121
  if defined?(super) == "super"
122
122
  raise Error::RGeoError, "ValidityCheck MUST be loaded before " \
123
- "definition of #{self.class}##{__method__}."
123
+ "definition of #{self.class}##{__method__}."
124
124
  end
125
125
 
126
126
  raise Error::UnsupportedOperation, "Method #{self.class}##{__method__} not defined."
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.2"
4
+ VERSION = "3.0.0-rc.3"
5
5
  end
@@ -100,59 +100,74 @@ module RGeo
100
100
  def generate(obj)
101
101
  factory = obj.factory
102
102
  if @type_format == :ewkb || @type_format == :wkb12
103
- @cur_has_z = factory.property(:has_z_coordinate)
104
- @cur_has_m = factory.property(:has_m_coordinate)
103
+ has_z = factory.property(:has_z_coordinate)
104
+ has_m = factory.property(:has_m_coordinate)
105
105
  else
106
- @cur_has_z = nil
107
- @cur_has_m = nil
106
+ has_z = false
107
+ has_m = false
108
108
  end
109
- @cur_dims = 2 + (@cur_has_z ? 1 : 0) + (@cur_has_m ? 1 : 0)
110
- start_emitter
111
- generate_feature(obj, true)
112
- finish_emitter
109
+ result = Result.new(has_z, has_m)
110
+ generate_feature(obj, result, true)
111
+ result.emit(@hex_format)
113
112
  end
114
113
 
115
114
  private
116
115
 
117
- def emit_byte(value)
118
- @cur_array << [value].pack("C")
116
+ class Result
117
+ def initialize(has_z, has_m)
118
+ @buffer = []
119
+ @has_z = has_z
120
+ @has_m = has_m
121
+ end
122
+
123
+ def <<(data)
124
+ @buffer << data
125
+ end
126
+
127
+ def emit(hex_format)
128
+ str = @buffer.join
129
+ hex_format ? str.unpack("H*")[0] : str
130
+ end
131
+
132
+ def z?
133
+ @has_z
134
+ end
135
+
136
+ def m?
137
+ @has_m
138
+ end
139
+ end
140
+ private_constant :Result
141
+
142
+ def emit_byte(value, rv)
143
+ rv << [value].pack("C")
119
144
  end
120
145
 
121
- def emit_integer(value)
122
- @cur_array << [value].pack(@little_endian ? "V" : "N")
146
+ def emit_integer(value, rv)
147
+ rv << [value].pack(@little_endian ? "V" : "N")
123
148
  end
124
149
 
125
- def emit_doubles(array)
126
- @cur_array << array.pack(@little_endian ? "E*" : "G*")
150
+ def emit_doubles(array, rv)
151
+ rv << array.pack(@little_endian ? "E*" : "G*")
127
152
  end
128
153
 
129
- def emit_line_string_coords(obj)
154
+ def emit_line_string_coords(obj, rv)
130
155
  array = []
131
- obj.points.each { |p| point_coords(p, array) }
132
- emit_integer(obj.num_points)
133
- emit_doubles(array)
156
+ obj.points.each { |pt| point_coords(pt, rv, array) }
157
+ emit_integer(obj.num_points, rv)
158
+ emit_doubles(array, rv)
134
159
  end
135
160
 
136
- def point_coords(obj, array = [])
161
+ def point_coords(obj, rv, array = [])
137
162
  array << obj.x
138
163
  array << obj.y
139
- array << obj.z if @cur_has_z
140
- array << obj.m if @cur_has_m
164
+ array << obj.z if rv.z?
165
+ array << obj.m if rv.m?
141
166
  array
142
167
  end
143
168
 
144
- def start_emitter
145
- @cur_array = []
146
- end
147
-
148
- def finish_emitter
149
- str = @cur_array.join
150
- @cur_array = nil
151
- @hex_format ? str.unpack("H*")[0] : str
152
- end
153
-
154
- def generate_feature(obj, toplevel = false)
155
- emit_byte(@little_endian ? 1 : 0)
169
+ def generate_feature(obj, rv, toplevel = false)
170
+ emit_byte(@little_endian ? 1 : 0, rv)
156
171
  type = obj.geometry_type
157
172
  type_code = TYPE_CODES[type]
158
173
  unless type_code
@@ -160,43 +175,43 @@ module RGeo
160
175
  end
161
176
  emit_srid = false
162
177
  if @type_format == :ewkb
163
- type_code |= 0x80000000 if @cur_has_z
164
- type_code |= 0x40000000 if @cur_has_m
178
+ type_code |= 0x80000000 if rv.z?
179
+ type_code |= 0x40000000 if rv.m?
165
180
  if @emit_ewkb_srid && toplevel
166
181
  type_code |= 0x20000000
167
182
  emit_srid = true
168
183
  end
169
184
  elsif @type_format == :wkb12
170
- type_code += 1000 if @cur_has_z
171
- type_code += 2000 if @cur_has_m
185
+ type_code += 1000 if rv.z?
186
+ type_code += 2000 if rv.m?
172
187
  end
173
- emit_integer(type_code)
174
- emit_integer(obj.srid) if emit_srid
188
+ emit_integer(type_code, rv)
189
+ emit_integer(obj.srid, rv) if emit_srid
175
190
  if type == Feature::Point
176
- emit_doubles(point_coords(obj))
191
+ emit_doubles(point_coords(obj, rv), rv)
177
192
  elsif type.subtype_of?(Feature::LineString)
178
- emit_line_string_coords(obj)
193
+ emit_line_string_coords(obj, rv)
179
194
  elsif type == Feature::Polygon
180
195
  exterior_ring = obj.exterior_ring
181
196
  if exterior_ring.empty?
182
- emit_integer(0)
197
+ emit_integer(0, rv)
183
198
  else
184
- emit_integer(1 + obj.num_interior_rings)
185
- emit_line_string_coords(exterior_ring)
186
- obj.interior_rings.each { |r| emit_line_string_coords(r) }
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) }
187
202
  end
188
203
  elsif type == Feature::GeometryCollection
189
- emit_integer(obj.num_geometries)
190
- obj.each { |g| generate_feature(g) }
204
+ emit_integer(obj.num_geometries, rv)
205
+ obj.each { |g| generate_feature(g, rv) }
191
206
  elsif type == Feature::MultiPoint
192
- emit_integer(obj.num_geometries)
193
- obj.each { |g| generate_feature(g) }
207
+ emit_integer(obj.num_geometries, rv)
208
+ obj.each { |g| generate_feature(g, rv) }
194
209
  elsif type == Feature::MultiLineString
195
- emit_integer(obj.num_geometries)
196
- obj.each { |g| generate_feature(g) }
210
+ emit_integer(obj.num_geometries, rv)
211
+ obj.each { |g| generate_feature(g, rv) }
197
212
  elsif type == Feature::MultiPolygon
198
- emit_integer(obj.num_geometries)
199
- obj.each { |g| generate_feature(g) }
213
+ emit_integer(obj.num_geometries, rv)
214
+ obj.each { |g| generate_feature(g, rv) }
200
215
  end
201
216
  end
202
217
  end
@@ -62,6 +62,7 @@ module RGeo
62
62
  @support_wkb12 = opts[:support_wkb12] ? true : false
63
63
  @ignore_extra_bytes = opts[:ignore_extra_bytes] ? true : false
64
64
  @default_srid = opts[:default_srid]
65
+ @mutex = Mutex.new
65
66
  end
66
67
 
67
68
  # Returns the factory generator. See WKBParser for details.
@@ -105,25 +106,27 @@ module RGeo
105
106
  # reasons but deprecated. Use #parse instead.
106
107
 
107
108
  def parse(data)
108
- data = [data].pack("H*") if data[0, 1] =~ /[0-9a-fA-F]/
109
- @cur_has_z = nil
110
- @cur_has_m = nil
111
- @cur_srid = nil
112
- @cur_dims = 2
113
- @cur_factory = nil
114
- begin
115
- start_scanner(data)
116
- obj = parse_object(false)
117
- unless @ignore_extra_bytes
118
- bytes = bytes_remaining
119
- if bytes > 0
120
- raise Error::ParseError, "Found #{bytes} extra bytes at the end of the stream."
109
+ @mutex.synchronize do
110
+ data = [data].pack("H*") if data[0, 1] =~ /[0-9a-fA-F]/
111
+ @cur_has_z = nil
112
+ @cur_has_m = nil
113
+ @cur_srid = nil
114
+ @cur_dims = 2
115
+ @cur_factory = nil
116
+ begin
117
+ start_scanner(data)
118
+ obj = parse_object(false)
119
+ unless @ignore_extra_bytes
120
+ bytes = bytes_remaining
121
+ if bytes > 0
122
+ raise Error::ParseError, "Found #{bytes} extra bytes at the end of the stream."
123
+ end
121
124
  end
125
+ ensure
126
+ @data = nil
122
127
  end
123
- ensure
124
- @data = nil
128
+ obj
125
129
  end
126
- obj
127
130
  end
128
131
  alias parse_hex parse
129
132