ffi-geos 1.2.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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