ffi-geos 1.2.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +4851 -0
  3. data/.travis.yml +24 -9
  4. data/FUNDING.yml +2 -0
  5. data/Gemfile +12 -16
  6. data/Guardfile +6 -8
  7. data/MIT-LICENSE +1 -1
  8. data/README.rdoc +2 -20
  9. data/Rakefile +4 -2
  10. data/ffi-geos.gemspec +13 -14
  11. data/lib/ffi-geos.rb +342 -244
  12. data/lib/ffi-geos/buffer_params.rb +9 -20
  13. data/lib/ffi-geos/coordinate_sequence.rb +351 -65
  14. data/lib/ffi-geos/geometry.rb +267 -191
  15. data/lib/ffi-geos/geometry_collection.rb +74 -12
  16. data/lib/ffi-geos/interrupt.rb +11 -16
  17. data/lib/ffi-geos/line_string.rb +157 -33
  18. data/lib/ffi-geos/linear_ring.rb +2 -3
  19. data/lib/ffi-geos/multi_line_string.rb +1 -2
  20. data/lib/ffi-geos/multi_point.rb +0 -1
  21. data/lib/ffi-geos/multi_polygon.rb +0 -1
  22. data/lib/ffi-geos/point.rb +70 -15
  23. data/lib/ffi-geos/polygon.rb +124 -21
  24. data/lib/ffi-geos/prepared_geometry.rb +11 -12
  25. data/lib/ffi-geos/strtree.rb +64 -77
  26. data/lib/ffi-geos/tools.rb +16 -19
  27. data/lib/ffi-geos/utils.rb +36 -60
  28. data/lib/ffi-geos/version.rb +1 -3
  29. data/lib/ffi-geos/wkb_reader.rb +4 -9
  30. data/lib/ffi-geos/wkb_writer.rb +15 -20
  31. data/lib/ffi-geos/wkt_reader.rb +2 -5
  32. data/lib/ffi-geos/wkt_writer.rb +20 -31
  33. data/sonar-project.properties +16 -0
  34. data/test/.rubocop.yml +36 -0
  35. data/test/coordinate_sequence_tests.rb +322 -52
  36. data/test/geometry_collection_tests.rb +388 -4
  37. data/test/geometry_tests.rb +466 -121
  38. data/test/interrupt_tests.rb +9 -12
  39. data/test/line_string_tests.rb +213 -25
  40. data/test/linear_ring_tests.rb +1 -3
  41. data/test/misc_tests.rb +28 -30
  42. data/test/multi_line_string_tests.rb +0 -2
  43. data/test/point_tests.rb +158 -2
  44. data/test/polygon_tests.rb +283 -2
  45. data/test/prepared_geometry_tests.rb +8 -11
  46. data/test/strtree_tests.rb +14 -15
  47. data/test/test_helper.rb +75 -51
  48. data/test/tools_tests.rb +1 -4
  49. data/test/utils_tests.rb +85 -76
  50. data/test/wkb_reader_tests.rb +18 -18
  51. data/test/wkb_writer_tests.rb +15 -22
  52. data/test/wkt_reader_tests.rb +1 -4
  53. data/test/wkt_writer_tests.rb +8 -17
  54. metadata +11 -7
@@ -1,4 +1,3 @@
1
- # encoding: UTF-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module Geos
@@ -17,7 +16,7 @@ module Geos
17
16
  # WktReader and the various Geos.create_* methods.
18
17
  def initialize(ptr, options = {})
19
18
  options = {
20
- :auto_free => true
19
+ auto_free: true
21
20
  }.merge(options)
22
21
 
23
22
  @ptr = FFI::AutoPointer.new(
@@ -45,52 +44,53 @@ module Geos
45
44
 
46
45
  # Returns the name of the Geometry type, i.e. "Point", "Polygon", etc.
47
46
  def geom_type
48
- FFIGeos.GEOSGeomType_r(Geos.current_handle_pointer, self.ptr)
47
+ FFIGeos.GEOSGeomType_r(Geos.current_handle_pointer, ptr)
49
48
  end
50
49
 
51
50
  # Returns one of the values from Geos::GeomTypes.
52
51
  def type_id
53
- FFIGeos.GEOSGeomTypeId_r(Geos.current_handle_pointer, self.ptr)
52
+ FFIGeos.GEOSGeomTypeId_r(Geos.current_handle_pointer, ptr)
54
53
  end
55
54
 
56
55
  def normalize!
57
- if FFIGeos.GEOSNormalize_r(Geos.current_handle_pointer, self.ptr) == -1
58
- raise Geos::Geometry::CouldntNormalizeError.new(self.class)
59
- end
56
+ raise Geos::Geometry::CouldntNormalizeError, self.class if FFIGeos.GEOSNormalize_r(Geos.current_handle_pointer, ptr) == -1
60
57
 
61
58
  self
62
59
  end
63
- alias_method :normalize, :normalize!
60
+ alias normalize normalize!
64
61
 
65
62
  def srid
66
- FFIGeos.GEOSGetSRID_r(Geos.current_handle_pointer, self.ptr)
63
+ FFIGeos.GEOSGetSRID_r(Geos.current_handle_pointer, ptr)
67
64
  end
68
65
 
69
66
  def srid=(s)
70
- FFIGeos.GEOSSetSRID_r(Geos.current_handle_pointer, self.ptr, s)
67
+ FFIGeos.GEOSSetSRID_r(Geos.current_handle_pointer, ptr, s)
71
68
  end
72
69
 
73
70
  def dimensions
74
- FFIGeos.GEOSGeom_getDimensions_r(Geos.current_handle_pointer, self.ptr)
71
+ FFIGeos.GEOSGeom_getDimensions_r(Geos.current_handle_pointer, ptr)
75
72
  end
76
73
 
77
74
  def num_geometries
78
- FFIGeos.GEOSGetNumGeometries_r(Geos.current_handle_pointer, self.ptr)
75
+ FFIGeos.GEOSGetNumGeometries_r(Geos.current_handle_pointer, ptr)
79
76
  end
80
77
 
81
78
  def num_coordinates
82
- FFIGeos.GEOSGetNumCoordinates_r(Geos.current_handle_pointer, self.ptr)
79
+ FFIGeos.GEOSGetNumCoordinates_r(Geos.current_handle_pointer, ptr)
83
80
  end
84
81
 
85
82
  def coord_seq
86
- CoordinateSequence.new(FFIGeos.GEOSGeom_getCoordSeq_r(Geos.current_handle_pointer, self.ptr), false, self)
83
+ CoordinateSequence.new(FFIGeos.GEOSGeom_getCoordSeq_r(Geos.current_handle_pointer, ptr), false, self)
87
84
  end
88
85
 
89
- def intersection(geom)
86
+ def intersection(geom, precision: nil)
90
87
  check_geometry(geom)
91
- cast_geometry_ptr(FFIGeos.GEOSIntersection_r(Geos.current_handle_pointer, self.ptr, geom.ptr), {
92
- :srid_copy => pick_srid_from_geoms(self.srid, geom.srid)
93
- })
88
+
89
+ if precision
90
+ cast_geometry_ptr(FFIGeos.GEOSIntersectionPrec_r(Geos.current_handle_pointer, ptr, geom.ptr, precision), srid_copy: pick_srid_from_geoms(srid, geom.srid))
91
+ else
92
+ cast_geometry_ptr(FFIGeos.GEOSIntersection_r(Geos.current_handle_pointer, ptr, geom.ptr), srid_copy: pick_srid_from_geoms(srid, geom.srid))
93
+ end
94
94
  end
95
95
 
96
96
  if FFIGeos.respond_to?(:GEOSBufferWithParams_r)
@@ -115,12 +115,12 @@ module Geos
115
115
  when Geos::BufferParams
116
116
  options
117
117
  when Numeric
118
- Geos::BufferParams.new(:quad_segs => options)
118
+ Geos::BufferParams.new(quad_segs: options)
119
119
  else
120
- raise ArgumentError.new("Expected Geos::BufferParams, a Hash or a Numeric")
120
+ raise ArgumentError, 'Expected Geos::BufferParams, a Hash or a Numeric'
121
121
  end
122
122
 
123
- cast_geometry_ptr(FFIGeos.GEOSBufferWithParams_r(Geos.current_handle_pointer, self.ptr, params.ptr, width), :srid_copy => self.srid)
123
+ cast_geometry_ptr(FFIGeos.GEOSBufferWithParams_r(Geos.current_handle_pointer, ptr, params.ptr, width), srid_copy: srid)
124
124
  end
125
125
  else
126
126
  def buffer(width, options = nil)
@@ -133,109 +133,131 @@ module Geos
133
133
  when Numeric
134
134
  options
135
135
  else
136
- raise ArgumentError.new("Expected Geos::BufferParams, a Hash or a Numeric")
136
+ raise ArgumentError, 'Expected Geos::BufferParams, a Hash or a Numeric'
137
137
  end
138
138
 
139
- cast_geometry_ptr(FFIGeos.GEOSBuffer_r(Geos.current_handle_pointer, self.ptr, width, quad_segs), :srid_copy => self.srid)
139
+ cast_geometry_ptr(FFIGeos.GEOSBuffer_r(Geos.current_handle_pointer, ptr, width, quad_segs), srid_copy: srid)
140
140
  end
141
141
  end
142
142
 
143
143
  def convex_hull
144
- cast_geometry_ptr(FFIGeos.GEOSConvexHull_r(Geos.current_handle_pointer, self.ptr), :srid_copy => self.srid)
144
+ cast_geometry_ptr(FFIGeos.GEOSConvexHull_r(Geos.current_handle_pointer, ptr), srid_copy: srid)
145
145
  end
146
146
 
147
- def difference(geom)
147
+ def difference(geom, precision: nil)
148
148
  check_geometry(geom)
149
- cast_geometry_ptr(FFIGeos.GEOSDifference_r(Geos.current_handle_pointer, self.ptr, geom.ptr), {
150
- :srid_copy => pick_srid_from_geoms(self.srid, geom.srid)
151
- })
149
+
150
+ if precision
151
+ cast_geometry_ptr(FFIGeos.GEOSDifferencePrec_r(Geos.current_handle_pointer, ptr, geom.ptr, precision), srid_copy: pick_srid_from_geoms(srid, geom.srid))
152
+ else
153
+ cast_geometry_ptr(FFIGeos.GEOSDifference_r(Geos.current_handle_pointer, ptr, geom.ptr), srid_copy: pick_srid_from_geoms(srid, geom.srid))
154
+ end
152
155
  end
153
156
 
154
- def sym_difference(geom)
157
+ def sym_difference(geom, precision: nil)
155
158
  check_geometry(geom)
156
- cast_geometry_ptr(FFIGeos.GEOSSymDifference_r(Geos.current_handle_pointer, self.ptr, geom.ptr), {
157
- :srid_copy => pick_srid_from_geoms(self.srid, geom.srid)
158
- })
159
+
160
+ if precision
161
+ cast_geometry_ptr(FFIGeos.GEOSSymDifferencePrec_r(Geos.current_handle_pointer, ptr, geom.ptr, precision), srid_copy: pick_srid_from_geoms(srid, geom.srid))
162
+ else
163
+ cast_geometry_ptr(FFIGeos.GEOSSymDifference_r(Geos.current_handle_pointer, ptr, geom.ptr), srid_copy: pick_srid_from_geoms(srid, geom.srid))
164
+ end
159
165
  end
160
- alias_method :symmetric_difference, :sym_difference
166
+ alias symmetric_difference sym_difference
161
167
 
162
168
  def boundary
163
- cast_geometry_ptr(FFIGeos.GEOSBoundary_r(Geos.current_handle_pointer, self.ptr), :srid_copy => self.srid)
169
+ cast_geometry_ptr(FFIGeos.GEOSBoundary_r(Geos.current_handle_pointer, ptr), srid_copy: srid)
164
170
  end
165
171
 
166
172
  # Calling without a geom argument is equivalent to calling unary_union when
167
173
  # using GEOS 3.3+ and is equivalent to calling union_cascaded in older
168
174
  # versions.
169
- def union(geom = nil)
175
+ def union(geom = nil, precision: nil)
170
176
  if geom
171
177
  check_geometry(geom)
172
- cast_geometry_ptr(FFIGeos.GEOSUnion_r(Geos.current_handle_pointer, self.ptr, geom.ptr), {
173
- :srid_copy => pick_srid_from_geoms(self.srid, geom.srid)
174
- })
175
- else
176
- if self.respond_to?(:unary_union)
177
- self.unary_union
178
+
179
+ if precision
180
+ cast_geometry_ptr(FFIGeos.GEOSUnionPrec_r(Geos.current_handle_pointer, ptr, geom.ptr, precision), srid_copy: pick_srid_from_geoms(srid, geom.srid))
178
181
  else
179
- self.union_cascaded
182
+ cast_geometry_ptr(FFIGeos.GEOSUnion_r(Geos.current_handle_pointer, ptr, geom.ptr), srid_copy: pick_srid_from_geoms(srid, geom.srid))
180
183
  end
184
+ elsif respond_to?(:unary_union)
185
+ unary_union
186
+ else
187
+ union_cascaded
181
188
  end
182
189
  end
183
190
 
184
191
  def union_cascaded
185
- cast_geometry_ptr(FFIGeos.GEOSUnionCascaded_r(Geos.current_handle_pointer, self.ptr), {
186
- :srid_copy => self.srid
187
- })
192
+ cast_geometry_ptr(FFIGeos.GEOSUnionCascaded_r(Geos.current_handle_pointer, ptr), srid_copy: srid)
193
+ end
194
+
195
+ if FFIGeos.respond_to?(:GEOSCoverageUnion_r)
196
+ # Added in GEOS 3.8+
197
+ def coverage_union
198
+ cast_geometry_ptr(FFIGeos.GEOSCoverageUnion_r(Geos.current_handle_pointer, ptr), srid_copy: srid)
199
+ end
188
200
  end
189
201
 
190
202
  if FFIGeos.respond_to?(:GEOSUnaryUnion_r)
191
203
  # Available in GEOS 3.3+
192
- def unary_union
193
- cast_geometry_ptr(FFIGeos.GEOSUnaryUnion_r(Geos.current_handle_pointer, self.ptr), {
194
- :srid_copy => self.srid
195
- })
204
+ def unary_union(precision = nil)
205
+ if precision
206
+ cast_geometry_ptr(FFIGeos.GEOSUnaryUnionPrec_r(Geos.current_handle_pointer, ptr, precision), srid_copy: srid)
207
+ else
208
+ cast_geometry_ptr(FFIGeos.GEOSUnaryUnion_r(Geos.current_handle_pointer, ptr), srid_copy: srid)
209
+ end
196
210
  end
197
211
  end
198
212
 
199
213
  if FFIGeos.respond_to?(:GEOSNode_r)
200
214
  # Available in GEOS 3.3.4+
201
215
  def node
202
- cast_geometry_ptr(FFIGeos.GEOSNode_r(Geos.current_handle_pointer, self.ptr))
216
+ cast_geometry_ptr(FFIGeos.GEOSNode_r(Geos.current_handle_pointer, ptr))
203
217
  end
204
218
  end
205
219
 
206
220
  def point_on_surface
207
- cast_geometry_ptr(FFIGeos.GEOSPointOnSurface_r(Geos.current_handle_pointer, self.ptr), :srid_copy => self.srid)
221
+ cast_geometry_ptr(FFIGeos.GEOSPointOnSurface_r(Geos.current_handle_pointer, ptr), srid_copy: srid)
208
222
  end
209
- alias_method :representative_point, :point_on_surface
223
+ alias representative_point point_on_surface
210
224
 
211
225
  if FFIGeos.respond_to?(:GEOSClipByRect_r)
212
226
  # Available in GEOS 3.5.0+.
213
227
  def clip_by_rect(xmin, ymin, xmax, ymax)
214
- cast_geometry_ptr(FFIGeos.GEOSClipByRect_r(Geos.current_handle_pointer, self.ptr, xmin, ymin, xmax, ymax))
228
+ cast_geometry_ptr(FFIGeos.GEOSClipByRect_r(Geos.current_handle_pointer, ptr, xmin, ymin, xmax, ymax))
215
229
  end
216
- alias_method :clip_by_rectangle, :clip_by_rect
230
+ alias clip_by_rectangle clip_by_rect
217
231
  end
218
232
 
219
233
  def centroid
220
- cast_geometry_ptr(FFIGeos.GEOSGetCentroid_r(Geos.current_handle_pointer, self.ptr), :srid_copy => self.srid)
234
+ cast_geometry_ptr(FFIGeos.GEOSGetCentroid_r(Geos.current_handle_pointer, ptr), srid_copy: srid)
235
+ end
236
+ alias center centroid
237
+
238
+ if FFIGeos.respond_to?(:GEOSMinimumBoundingCircle_r)
239
+ # Added in GEOS 3.8+. Does not yet support the radius or center
240
+ # arguments.
241
+ def minimum_bounding_circle
242
+ cast_geometry_ptr(FFIGeos.GEOSMinimumBoundingCircle_r(Geos.current_handle_pointer, ptr, nil, nil), srid_copy: srid)
243
+ end
221
244
  end
222
- alias_method :center, :centroid
223
245
 
224
246
  def envelope
225
- cast_geometry_ptr(FFIGeos.GEOSEnvelope_r(Geos.current_handle_pointer, self.ptr), :srid_copy => self.srid)
247
+ cast_geometry_ptr(FFIGeos.GEOSEnvelope_r(Geos.current_handle_pointer, ptr), srid_copy: srid)
226
248
  end
227
249
 
228
250
  # Returns the Dimensionally Extended Nine-Intersection Model (DE-9IM)
229
251
  # matrix of the geometries as a String.
230
252
  def relate(geom)
231
253
  check_geometry(geom)
232
- FFIGeos.GEOSRelate_r(Geos.current_handle_pointer, self.ptr, geom.ptr)
254
+ FFIGeos.GEOSRelate_r(Geos.current_handle_pointer, ptr, geom.ptr)
233
255
  end
234
256
 
235
257
  # Checks the DE-9IM pattern against the geoms.
236
258
  def relate_pattern(geom, pattern)
237
259
  check_geometry(geom)
238
- bool_result(FFIGeos.GEOSRelatePattern_r(Geos.current_handle_pointer, self.ptr, geom.ptr, pattern))
260
+ bool_result(FFIGeos.GEOSRelatePattern_r(Geos.current_handle_pointer, ptr, geom.ptr, pattern))
239
261
  end
240
262
 
241
263
  if FFIGeos.respond_to?(:GEOSRelateBoundaryNodeRule_r)
@@ -243,60 +265,60 @@ module Geos
243
265
  def relate_boundary_node_rule(geom, bnr = :mod2)
244
266
  check_geometry(geom)
245
267
  check_enum_value(Geos::RelateBoundaryNodeRules, bnr)
246
- FFIGeos.GEOSRelateBoundaryNodeRule_r(Geos.current_handle_pointer, self.ptr, geom.ptr, bnr)
268
+ FFIGeos.GEOSRelateBoundaryNodeRule_r(Geos.current_handle_pointer, ptr, geom.ptr, bnr)
247
269
  end
248
270
  end
249
271
 
250
272
  def line_merge
251
- cast_geometry_ptr(FFIGeos.GEOSLineMerge_r(Geos.current_handle_pointer, self.ptr), :srid_copy => self.srid)
273
+ cast_geometry_ptr(FFIGeos.GEOSLineMerge_r(Geos.current_handle_pointer, ptr), srid_copy: srid)
252
274
  end
253
275
 
254
276
  def simplify(tolerance)
255
- cast_geometry_ptr(FFIGeos.GEOSSimplify_r(Geos.current_handle_pointer, self.ptr, tolerance), :srid_copy => self.srid)
277
+ cast_geometry_ptr(FFIGeos.GEOSSimplify_r(Geos.current_handle_pointer, ptr, tolerance), srid_copy: srid)
256
278
  end
257
279
 
258
280
  def topology_preserve_simplify(tolerance)
259
- cast_geometry_ptr(FFIGeos.GEOSTopologyPreserveSimplify_r(Geos.current_handle_pointer, self.ptr, tolerance), :srid_copy => self.srid)
281
+ cast_geometry_ptr(FFIGeos.GEOSTopologyPreserveSimplify_r(Geos.current_handle_pointer, ptr, tolerance), srid_copy: srid)
260
282
  end
261
283
 
262
284
  def extract_unique_points
263
- cast_geometry_ptr(FFIGeos.GEOSGeom_extractUniquePoints_r(Geos.current_handle_pointer, self.ptr), :srid_copy => self.srid)
285
+ cast_geometry_ptr(FFIGeos.GEOSGeom_extractUniquePoints_r(Geos.current_handle_pointer, ptr), srid_copy: srid)
264
286
  end
265
- alias_method :unique_points, :extract_unique_points
287
+ alias unique_points extract_unique_points
266
288
 
267
289
  def disjoint?(geom)
268
290
  check_geometry(geom)
269
- bool_result(FFIGeos.GEOSDisjoint_r(Geos.current_handle_pointer, self.ptr, geom.ptr))
291
+ bool_result(FFIGeos.GEOSDisjoint_r(Geos.current_handle_pointer, ptr, geom.ptr))
270
292
  end
271
293
 
272
294
  def touches?(geom)
273
295
  check_geometry(geom)
274
- bool_result(FFIGeos.GEOSTouches_r(Geos.current_handle_pointer, self.ptr, geom.ptr))
296
+ bool_result(FFIGeos.GEOSTouches_r(Geos.current_handle_pointer, ptr, geom.ptr))
275
297
  end
276
298
 
277
299
  def intersects?(geom)
278
300
  check_geometry(geom)
279
- bool_result(FFIGeos.GEOSIntersects_r(Geos.current_handle_pointer, self.ptr, geom.ptr))
301
+ bool_result(FFIGeos.GEOSIntersects_r(Geos.current_handle_pointer, ptr, geom.ptr))
280
302
  end
281
303
 
282
304
  def crosses?(geom)
283
305
  check_geometry(geom)
284
- bool_result(FFIGeos.GEOSCrosses_r(Geos.current_handle_pointer, self.ptr, geom.ptr))
306
+ bool_result(FFIGeos.GEOSCrosses_r(Geos.current_handle_pointer, ptr, geom.ptr))
285
307
  end
286
308
 
287
309
  def within?(geom)
288
310
  check_geometry(geom)
289
- bool_result(FFIGeos.GEOSWithin_r(Geos.current_handle_pointer, self.ptr, geom.ptr))
311
+ bool_result(FFIGeos.GEOSWithin_r(Geos.current_handle_pointer, ptr, geom.ptr))
290
312
  end
291
313
 
292
314
  def contains?(geom)
293
315
  check_geometry(geom)
294
- bool_result(FFIGeos.GEOSContains_r(Geos.current_handle_pointer, self.ptr, geom.ptr))
316
+ bool_result(FFIGeos.GEOSContains_r(Geos.current_handle_pointer, ptr, geom.ptr))
295
317
  end
296
318
 
297
319
  def overlaps?(geom)
298
320
  check_geometry(geom)
299
- bool_result(FFIGeos.GEOSOverlaps_r(Geos.current_handle_pointer, self.ptr, geom.ptr))
321
+ bool_result(FFIGeos.GEOSOverlaps_r(Geos.current_handle_pointer, ptr, geom.ptr))
300
322
  end
301
323
 
302
324
  if FFIGeos.respond_to?(:GEOSCovers_r)
@@ -305,7 +327,7 @@ module Geos
305
327
  # implementation.
306
328
  def covers?(geom)
307
329
  check_geometry(geom)
308
- bool_result(FFIGeos.GEOSCovers_r(Geos.current_handle_pointer, self.ptr, geom.ptr))
330
+ bool_result(FFIGeos.GEOSCovers_r(Geos.current_handle_pointer, ptr, geom.ptr))
309
331
  end
310
332
  else
311
333
  def covers?(geom) #:nodoc:
@@ -315,9 +337,9 @@ module Geos
315
337
  *T****FF*
316
338
  ***T**FF*
317
339
  ****T*FF*
318
- }.detect do |pattern|
319
- self.relate_pattern(geom, pattern)
320
- end
340
+ }.detect { |pattern|
341
+ relate_pattern(geom, pattern)
342
+ }
321
343
  end
322
344
  end
323
345
 
@@ -327,7 +349,7 @@ module Geos
327
349
  # implementation.
328
350
  def covered_by?(geom)
329
351
  check_geometry(geom)
330
- bool_result(FFIGeos.GEOSCoveredBy_r(Geos.current_handle_pointer, self.ptr, geom.ptr))
352
+ bool_result(FFIGeos.GEOSCoveredBy_r(Geos.current_handle_pointer, ptr, geom.ptr))
331
353
  end
332
354
  else
333
355
  def covered_by?(geom) #:nodoc:
@@ -337,58 +359,56 @@ module Geos
337
359
  *TF**F***
338
360
  **FT*F***
339
361
  **F*TF***
340
- }.detect do |pattern|
341
- self.relate_pattern(geom, pattern)
342
- end
362
+ }.detect { |pattern|
363
+ relate_pattern(geom, pattern)
364
+ }
343
365
  end
344
366
  end
345
367
 
346
- def eql?(geom)
347
- check_geometry(geom)
348
- bool_result(FFIGeos.GEOSEquals_r(Geos.current_handle_pointer, self.ptr, geom.ptr))
368
+ def eql?(other)
369
+ check_geometry(other)
370
+ bool_result(FFIGeos.GEOSEquals_r(Geos.current_handle_pointer, ptr, other.ptr))
349
371
  end
350
- alias_method :equals?, :eql?
372
+ alias equals? eql?
351
373
 
352
- def ==(geom)
353
- if geom.is_a?(Geos::Geometry)
354
- self.eql?(geom)
355
- else
356
- false
357
- end
374
+ def ==(other)
375
+ return eql?(other) if other.is_a?(Geos::Geometry)
376
+
377
+ false
358
378
  end
359
379
 
360
- def eql_exact?(geom, tolerance)
361
- check_geometry(geom)
362
- bool_result(FFIGeos.GEOSEqualsExact_r(Geos.current_handle_pointer, self.ptr, geom.ptr, tolerance))
380
+ def eql_exact?(other, tolerance)
381
+ check_geometry(other)
382
+ bool_result(FFIGeos.GEOSEqualsExact_r(Geos.current_handle_pointer, ptr, other.ptr, tolerance))
363
383
  end
364
- alias_method :equals_exact?, :eql_exact?
365
- alias_method :exactly_equals?, :eql_exact?
384
+ alias equals_exact? eql_exact?
385
+ alias exactly_equals? eql_exact?
366
386
 
367
- def eql_almost?(geom, decimal = 6)
368
- check_geometry(geom)
369
- bool_result(FFIGeos.GEOSEqualsExact_r(Geos.current_handle_pointer, self.ptr, geom.ptr, 0.5 * 10 ** (-decimal)))
387
+ def eql_almost?(other, decimal = 6)
388
+ check_geometry(other)
389
+ bool_result(FFIGeos.GEOSEqualsExact_r(Geos.current_handle_pointer, ptr, other.ptr, 0.5 * 10 ** -decimal))
370
390
  end
371
- alias_method :equals_almost?, :eql_almost?
372
- alias_method :almost_equals?, :eql_almost?
391
+ alias equals_almost? eql_almost?
392
+ alias almost_equals? eql_almost?
373
393
 
374
394
  def empty?
375
- bool_result(FFIGeos.GEOSisEmpty_r(Geos.current_handle_pointer, self.ptr))
395
+ bool_result(FFIGeos.GEOSisEmpty_r(Geos.current_handle_pointer, ptr))
376
396
  end
377
397
 
378
398
  def valid?
379
- bool_result(FFIGeos.GEOSisValid_r(Geos.current_handle_pointer, self.ptr))
399
+ bool_result(FFIGeos.GEOSisValid_r(Geos.current_handle_pointer, ptr))
380
400
  end
381
401
 
382
402
  # Returns a String describing whether or not the Geometry is valid.
383
403
  def valid_reason
384
- FFIGeos.GEOSisValidReason_r(Geos.current_handle_pointer, self.ptr)
404
+ FFIGeos.GEOSisValidReason_r(Geos.current_handle_pointer, ptr)
385
405
  end
386
406
 
387
407
  # Returns a Hash containing the following structure on invalid geometries:
388
408
  #
389
409
  # {
390
- # :detail => "String explaining the problem",
391
- # :location => Geos::Point # centered on the problem
410
+ # detail: "String explaining the problem",
411
+ # location: Geos::Point # centered on the problem
392
412
  # }
393
413
  #
394
414
  # If the Geometry is valid, returns nil.
@@ -396,107 +416,112 @@ module Geos
396
416
  detail = FFI::MemoryPointer.new(:pointer)
397
417
  location = FFI::MemoryPointer.new(:pointer)
398
418
  valid = bool_result(
399
- FFIGeos.GEOSisValidDetail_r(Geos.current_handle_pointer, self.ptr, flags, detail, location)
419
+ FFIGeos.GEOSisValidDetail_r(Geos.current_handle_pointer, ptr, flags, detail, location)
400
420
  )
401
421
 
402
- if !valid
403
- {
404
- :detail => detail.read_pointer.read_string,
405
- :location => cast_geometry_ptr(location.read_pointer, {
406
- :srid_copy => self.srid
407
- })
408
- }
409
- end
422
+ return if valid
423
+
424
+ {
425
+ detail: detail.read_pointer.read_string,
426
+ location: cast_geometry_ptr(location.read_pointer, srid_copy: srid)
427
+ }
410
428
  end
411
429
 
412
430
  def simple?
413
- bool_result(FFIGeos.GEOSisSimple_r(Geos.current_handle_pointer, self.ptr))
431
+ bool_result(FFIGeos.GEOSisSimple_r(Geos.current_handle_pointer, ptr))
414
432
  end
415
433
 
416
434
  def ring?
417
- bool_result(FFIGeos.GEOSisRing_r(Geos.current_handle_pointer, self.ptr))
435
+ bool_result(FFIGeos.GEOSisRing_r(Geos.current_handle_pointer, ptr))
418
436
  end
419
437
 
420
438
  def has_z?
421
- bool_result(FFIGeos.GEOSHasZ_r(Geos.current_handle_pointer, self.ptr))
439
+ bool_result(FFIGeos.GEOSHasZ_r(Geos.current_handle_pointer, ptr))
422
440
  end
423
441
 
424
442
  # GEOS versions prior to 3.3.0 didn't handle exceptions and can crash on
425
443
  # bad input.
426
444
  if FFIGeos.respond_to?(:GEOSProject_r) && Geos::GEOS_VERSION >= '3.3.0'
427
445
  def project(geom, normalized = false)
428
- raise TypeError.new("Expected Geos::Point type") if !geom.is_a?(Geos::Point)
446
+ raise TypeError, 'Expected Geos::Point type' unless geom.is_a?(Geos::Point)
429
447
 
430
448
  if normalized
431
- FFIGeos.GEOSProjectNormalized_r(Geos.current_handle_pointer, self.ptr, geom.ptr)
449
+ FFIGeos.GEOSProjectNormalized_r(Geos.current_handle_pointer, ptr, geom.ptr)
432
450
  else
433
- FFIGeos.GEOSProject_r(Geos.current_handle_pointer, self.ptr, geom.ptr)
451
+ FFIGeos.GEOSProject_r(Geos.current_handle_pointer, ptr, geom.ptr)
434
452
  end
435
453
  end
436
454
 
437
455
  def project_normalized(geom)
438
- self.project(geom, true)
456
+ project(geom, true)
439
457
  end
440
458
  end
441
459
 
442
460
  def interpolate(d, normalized = false)
443
461
  ret = if normalized
444
- FFIGeos.GEOSInterpolateNormalized_r(Geos.current_handle_pointer, self.ptr, d)
462
+ FFIGeos.GEOSInterpolateNormalized_r(Geos.current_handle_pointer, ptr, d)
445
463
  else
446
- FFIGeos.GEOSInterpolate_r(Geos.current_handle_pointer, self.ptr, d)
464
+ FFIGeos.GEOSInterpolate_r(Geos.current_handle_pointer, ptr, d)
447
465
  end
448
466
 
449
- cast_geometry_ptr(ret, :srid_copy => self.srid)
467
+ cast_geometry_ptr(ret, srid_copy: srid)
450
468
  end
451
469
 
452
470
  def interpolate_normalized(d)
453
- self.interpolate(d, true)
471
+ interpolate(d, true)
454
472
  end
455
473
 
456
474
  def start_point
457
- cast_geometry_ptr(FFIGeos.GEOSGeomGetStartPoint_r(Geos.current_handle_pointer, self.ptr), :srid_copy => self.srid)
475
+ cast_geometry_ptr(FFIGeos.GEOSGeomGetStartPoint_r(Geos.current_handle_pointer, ptr), srid_copy: srid)
458
476
  end
459
477
 
460
478
  def end_point
461
- cast_geometry_ptr(FFIGeos.GEOSGeomGetEndPoint_r(Geos.current_handle_pointer, self.ptr), :srid_copy => self.srid)
479
+ cast_geometry_ptr(FFIGeos.GEOSGeomGetEndPoint_r(Geos.current_handle_pointer, ptr), srid_copy: srid)
462
480
  end
463
481
 
464
482
  def area
465
- if self.empty?
466
- 0
467
- else
468
- double_ptr = FFI::MemoryPointer.new(:double)
469
- FFIGeos.GEOSArea_r(Geos.current_handle_pointer, self.ptr, double_ptr)
470
- double_ptr.read_double
471
- end
483
+ return 0 if empty?
484
+
485
+ double_ptr = FFI::MemoryPointer.new(:double)
486
+ FFIGeos.GEOSArea_r(Geos.current_handle_pointer, ptr, double_ptr)
487
+ double_ptr.read_double
472
488
  end
473
489
 
474
490
  def length
475
- if self.empty?
476
- 0
477
- else
478
- double_ptr = FFI::MemoryPointer.new(:double)
479
- FFIGeos.GEOSLength_r(Geos.current_handle_pointer, self.ptr, double_ptr)
480
- double_ptr.read_double
481
- end
491
+ return 0 if empty?
492
+
493
+ double_ptr = FFI::MemoryPointer.new(:double)
494
+ FFIGeos.GEOSLength_r(Geos.current_handle_pointer, ptr, double_ptr)
495
+ double_ptr.read_double
482
496
  end
483
497
 
484
498
  def distance(geom)
485
499
  check_geometry(geom)
486
500
  double_ptr = FFI::MemoryPointer.new(:double)
487
- FFIGeos.GEOSDistance_r(Geos.current_handle_pointer, self.ptr, geom.ptr, double_ptr)
501
+ FFIGeos.GEOSDistance_r(Geos.current_handle_pointer, ptr, geom.ptr, double_ptr)
488
502
  double_ptr.read_double
489
503
  end
490
504
 
505
+ if FFIGeos.respond_to?(:GEOSDistanceIndexed_r)
506
+ # Available in GEOS 3.7+.
507
+ def distance_indexed(geom)
508
+ check_geometry(geom)
509
+ double_ptr = FFI::MemoryPointer.new(:double)
510
+ FFIGeos.GEOSDistanceIndexed_r(Geos.current_handle_pointer, ptr, geom.ptr, double_ptr)
511
+ double_ptr.read_double
512
+ end
513
+ alias indexed_distance distance_indexed
514
+ end
515
+
491
516
  def hausdorff_distance(geom, densify_frac = nil)
492
517
  check_geometry(geom)
493
518
 
494
519
  double_ptr = FFI::MemoryPointer.new(:double)
495
520
 
496
521
  if densify_frac
497
- FFIGeos.GEOSHausdorffDistanceDensify_r(Geos.current_handle_pointer, self.ptr, geom.ptr, densify_frac, double_ptr)
522
+ FFIGeos.GEOSHausdorffDistanceDensify_r(Geos.current_handle_pointer, ptr, geom.ptr, densify_frac, double_ptr)
498
523
  else
499
- FFIGeos.GEOSHausdorffDistance_r(Geos.current_handle_pointer, self.ptr, geom.ptr, double_ptr)
524
+ FFIGeos.GEOSHausdorffDistance_r(Geos.current_handle_pointer, ptr, geom.ptr, double_ptr)
500
525
  end
501
526
 
502
527
  double_ptr.read_double
@@ -506,72 +531,91 @@ module Geos
506
531
  # Available in GEOS 3.4+.
507
532
  def nearest_points(geom)
508
533
  check_geometry(geom)
509
- ptr = FFIGeos.GEOSNearestPoints_r(Geos.current_handle_pointer, self.ptr, geom.ptr)
534
+ nearest_points_ptr = FFIGeos.GEOSNearestPoints_r(Geos.current_handle_pointer, ptr, geom.ptr)
510
535
 
511
- if !ptr.null?
512
- CoordinateSequence.new(ptr)
513
- end
536
+ return CoordinateSequence.new(nearest_points_ptr) unless nearest_points_ptr.null?
514
537
  end
515
538
  end
516
539
 
517
540
  def snap(geom, tolerance)
518
541
  check_geometry(geom)
519
- cast_geometry_ptr(FFIGeos.GEOSSnap_r(Geos.current_handle_pointer, self.ptr, geom.ptr, tolerance), {
520
- :srid_copy => pick_srid_from_geoms(self.srid, geom.srid)
521
- })
542
+ cast_geometry_ptr(FFIGeos.GEOSSnap_r(Geos.current_handle_pointer, ptr, geom.ptr, tolerance), srid_copy: pick_srid_from_geoms(srid, geom.srid))
522
543
  end
523
- alias_method :snap_to, :snap
544
+ alias snap_to snap
524
545
 
525
546
  def shared_paths(geom)
526
547
  check_geometry(geom)
527
- cast_geometry_ptr(FFIGeos.GEOSSharedPaths_r(Geos.current_handle_pointer, self.ptr, geom.ptr), {
528
- :srid_copy => pick_srid_from_geoms(self.srid, geom.srid)
529
- }).to_a
548
+ cast_geometry_ptr(FFIGeos.GEOSSharedPaths_r(Geos.current_handle_pointer, ptr, geom.ptr), srid_copy: pick_srid_from_geoms(srid, geom.srid)).to_a
530
549
  end
531
550
 
532
551
  # Returns a Hash with the following structure:
533
552
  #
534
553
  # {
535
- # :rings => [ ... ],
536
- # :cuts => [ ... ],
537
- # :dangles => [ ... ],
538
- # :invalid_rings => [ ... ]
554
+ # rings: [ ... ],
555
+ # cuts: [ ... ],
556
+ # dangles: [ ... ],
557
+ # invalid_rings: [ ... ]
539
558
  # }
540
559
  def polygonize_full
541
560
  cuts = FFI::MemoryPointer.new(:pointer)
542
561
  dangles = FFI::MemoryPointer.new(:pointer)
543
562
  invalid_rings = FFI::MemoryPointer.new(:pointer)
544
563
 
545
- rings = cast_geometry_ptr(
546
- FFIGeos.GEOSPolygonize_full_r(Geos.current_handle_pointer, self.ptr, cuts, dangles, invalid_rings), {
547
- :srid_copy => self.srid
548
- }
549
- )
564
+ rings = cast_geometry_ptr(FFIGeos.GEOSPolygonize_full_r(Geos.current_handle_pointer, ptr, cuts, dangles, invalid_rings), srid_copy: srid)
550
565
 
551
- cuts = cast_geometry_ptr(cuts.read_pointer, :srid_copy => self.srid)
552
- dangles = cast_geometry_ptr(dangles.read_pointer, :srid_copy => self.srid)
553
- invalid_rings = cast_geometry_ptr(invalid_rings.read_pointer, :srid_copy => self.srid)
566
+ cuts = cast_geometry_ptr(cuts.read_pointer, srid_copy: srid)
567
+ dangles = cast_geometry_ptr(dangles.read_pointer, srid_copy: srid)
568
+ invalid_rings = cast_geometry_ptr(invalid_rings.read_pointer, srid_copy: srid)
554
569
 
555
570
  {
556
- :rings => rings.to_a,
557
- :cuts => cuts.to_a,
558
- :dangles => dangles.to_a,
559
- :invalid_rings => invalid_rings.to_a
571
+ rings: rings.to_a,
572
+ cuts: cuts.to_a,
573
+ dangles: dangles.to_a,
574
+ invalid_rings: invalid_rings.to_a
560
575
  }
561
576
  end
562
577
 
563
- def polygonize
564
- ary = FFI::MemoryPointer.new(:pointer)
565
- ary.write_array_of_pointer([ self.ptr ])
578
+ def polygonize(*geoms)
579
+ geoms.each do |geom|
580
+ raise ArgumentError unless geom.is_a?(Geos::Geometry)
581
+ end
582
+
583
+ ary = [ptr].concat(geoms.collect(&:ptr))
584
+ ary_ptr = FFI::MemoryPointer.new(:pointer, ary.length)
585
+ ary_ptr.write_array_of_pointer(ary)
566
586
 
567
- cast_geometry_ptr(FFIGeos.GEOSPolygonize_r(Geos.current_handle_pointer, ary, 1), :srid_copy => self.srid).to_a
587
+ cast_geometry_ptr(FFIGeos.GEOSPolygonize_r(Geos.current_handle_pointer, ary_ptr, ary.length), srid_copy: srid).to_a
588
+ end
589
+
590
+ if FFIGeos.respond_to?(:GEOSPolygonize_valid_r)
591
+ # Added in GEOS 3.8+
592
+ def polygonize_valid
593
+ ary = FFI::MemoryPointer.new(:pointer)
594
+ ary.write_array_of_pointer([ptr])
595
+
596
+ cast_geometry_ptr(FFIGeos.GEOSPolygonize_valid_r(Geos.current_handle_pointer, ary, 1), srid_copy: srid)
597
+ end
568
598
  end
569
599
 
570
600
  def polygonize_cut_edges
571
601
  ary = FFI::MemoryPointer.new(:pointer)
572
- ary.write_array_of_pointer([ self.ptr ])
602
+ ary.write_array_of_pointer([ptr])
603
+
604
+ cast_geometry_ptr(FFIGeos.GEOSPolygonizer_getCutEdges_r(Geos.current_handle_pointer, ary, 1), srid_copy: srid).to_a
605
+ end
606
+
607
+ if FFIGeos.respond_to?(:GEOSBuildArea_r)
608
+ # Added in GEOS 3.8+
609
+ def build_area
610
+ cast_geometry_ptr(FFIGeos.GEOSBuildArea_r(Geos.current_handle_pointer, ptr))
611
+ end
612
+ end
573
613
 
574
- cast_geometry_ptr(FFIGeos.GEOSPolygonizer_getCutEdges_r(Geos.current_handle_pointer, ary, 1), :srid_copy => self.srid).to_a
614
+ if FFIGeos.respond_to?(:GEOSMakeValid_r)
615
+ # Added in GEOS 3.8+
616
+ def make_valid
617
+ cast_geometry_ptr(FFIGeos.GEOSMakeValid_r(Geos.current_handle_pointer, ptr))
618
+ end
575
619
  end
576
620
 
577
621
  if FFIGeos.respond_to?(:GEOSDelaunayTriangulation_r)
@@ -589,7 +633,7 @@ module Geos
589
633
  tolerance = args.first || options[:tolerance] || 0.0
590
634
  only_edges = bool_to_int(options[:only_edges])
591
635
 
592
- cast_geometry_ptr(FFIGeos.GEOSDelaunayTriangulation_r(Geos.current_handle_pointer, self.ptr, tolerance, only_edges))
636
+ cast_geometry_ptr(FFIGeos.GEOSDelaunayTriangulation_r(Geos.current_handle_pointer, ptr, tolerance, only_edges))
593
637
  end
594
638
  end
595
639
 
@@ -617,7 +661,7 @@ module Geos
617
661
 
618
662
  only_edges = bool_to_int(options[:only_edges])
619
663
 
620
- cast_geometry_ptr(FFIGeos.GEOSVoronoiDiagram_r(Geos.current_handle_pointer, self.ptr, envelope_ptr, tolerance, only_edges))
664
+ cast_geometry_ptr(FFIGeos.GEOSVoronoiDiagram_r(Geos.current_handle_pointer, ptr, envelope_ptr, tolerance, only_edges))
621
665
  end
622
666
  end
623
667
 
@@ -628,24 +672,22 @@ module Geos
628
672
  def to_s
629
673
  writer = WktWriter.new
630
674
  wkt = writer.write(self)
631
- if wkt.length > 120
632
- wkt = "#{wkt[0...120]} ... "
633
- end
675
+ wkt = "#{wkt[0...120]} ... " if wkt.length > 120
634
676
 
635
- "#<Geos::#{self.geom_type}: #{wkt}>"
677
+ "#<Geos::#{geom_type}: #{wkt}>"
636
678
  end
637
679
 
638
680
  if FFIGeos.respond_to?(:GEOSGeom_getPrecision_r)
639
681
  def precision
640
- FFIGeos.GEOSGeom_getPrecision_r(Geos.current_handle_pointer, self.ptr)
682
+ FFIGeos.GEOSGeom_getPrecision_r(Geos.current_handle_pointer, ptr)
641
683
  end
642
684
  end
643
685
 
644
686
  if FFIGeos.respond_to?(:GEOSGeom_setPrecision_r)
645
687
  def with_precision(grid_size, options = {})
646
688
  options = {
647
- :no_topology => false,
648
- :keep_collapsed => false
689
+ no_topology: false,
690
+ keep_collapsed: false
649
691
  }.merge(options)
650
692
 
651
693
  flags = options.reduce(0) do |memo, (key, value)|
@@ -653,33 +695,67 @@ module Geos
653
695
  memo
654
696
  end
655
697
 
656
- cast_geometry_ptr(FFIGeos.GEOSGeom_setPrecision_r(Geos.current_handle_pointer, self.ptr, grid_size, flags))
698
+ cast_geometry_ptr(FFIGeos.GEOSGeom_setPrecision_r(Geos.current_handle_pointer, ptr, grid_size, flags))
657
699
  end
658
700
  end
659
701
 
660
702
  if FFIGeos.respond_to?(:GEOSMinimumRotatedRectangle_r)
661
703
  def minimum_rotated_rectangle
662
- cast_geometry_ptr(FFIGeos.GEOSMinimumRotatedRectangle_r(Geos.current_handle_pointer, self.ptr))
704
+ cast_geometry_ptr(FFIGeos.GEOSMinimumRotatedRectangle_r(Geos.current_handle_pointer, ptr))
663
705
  end
664
706
  end
665
707
 
666
708
  if FFIGeos.respond_to?(:GEOSMinimumClearance_r)
667
709
  def minimum_clearance
668
710
  double_ptr = FFI::MemoryPointer.new(:double)
669
- ret = FFIGeos.GEOSMinimumClearance_r(Geos.current_handle_pointer, self.ptr, double_ptr)
711
+ FFIGeos.GEOSMinimumClearance_r(Geos.current_handle_pointer, ptr, double_ptr)
670
712
  double_ptr.read_double
671
713
  end
672
714
  end
673
715
 
674
716
  if FFIGeos.respond_to?(:GEOSMinimumClearanceLine_r)
675
717
  def minimum_clearance_line
676
- cast_geometry_ptr(FFIGeos.GEOSMinimumClearanceLine_r(Geos.current_handle_pointer, self.ptr))
718
+ cast_geometry_ptr(FFIGeos.GEOSMinimumClearanceLine_r(Geos.current_handle_pointer, ptr))
719
+ end
720
+ end
721
+
722
+ if FFIGeos.respond_to?(:GEOSMaximumInscribedCircle_r)
723
+ def maximum_inscribed_circle(precision)
724
+ cast_geometry_ptr(FFIGeos.GEOSMaximumInscribedCircle_r(Geos.current_handle_pointer, ptr, precision))
725
+ end
726
+ end
727
+
728
+ if FFIGeos.respond_to?(:GEOSLargestEmptyCircle_r)
729
+ def largest_empty_circle(precision, boundary: nil)
730
+ cast_geometry_ptr(FFIGeos.GEOSLargestEmptyCircle_r(Geos.current_handle_pointer, ptr, boundary ? boundary.ptr : nil, precision))
677
731
  end
678
732
  end
679
733
 
680
734
  if FFIGeos.respond_to?(:GEOSMinimumWidth_r)
681
735
  def minimum_width
682
- cast_geometry_ptr(FFIGeos.GEOSMinimumWidth_r(Geos.current_handle_pointer, self.ptr))
736
+ cast_geometry_ptr(FFIGeos.GEOSMinimumWidth_r(Geos.current_handle_pointer, ptr))
737
+ end
738
+ end
739
+
740
+ if FFIGeos.respond_to?(:GEOSReverse_r)
741
+ def reverse
742
+ cast_geometry_ptr(FFIGeos.GEOSReverse_r(Geos.current_handle_pointer, ptr))
743
+ end
744
+ end
745
+
746
+ if FFIGeos.respond_to?(:GEOSFrechetDistance_r)
747
+ def frechet_distance(geom, densify_frac = nil)
748
+ check_geometry(geom)
749
+
750
+ double_ptr = FFI::MemoryPointer.new(:double)
751
+
752
+ if densify_frac
753
+ FFIGeos.GEOSFrechetDistanceDensify_r(Geos.current_handle_pointer, ptr, geom.ptr, densify_frac, double_ptr)
754
+ else
755
+ FFIGeos.GEOSFrechetDistance_r(Geos.current_handle_pointer, ptr, geom.ptr, double_ptr)
756
+ end
757
+
758
+ double_ptr.read_double
683
759
  end
684
760
  end
685
761
  end