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