rgeo 2.4.0 → 3.0.0.pre.rc.1
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 +4 -4
- data/.yardopts +6 -0
- data/README.md +1 -0
- data/ext/geos_c_impl/analysis.c +4 -4
- data/ext/geos_c_impl/errors.c +8 -6
- data/ext/geos_c_impl/errors.h +7 -3
- data/ext/geos_c_impl/extconf.rb +2 -0
- data/ext/geos_c_impl/factory.c +80 -7
- data/ext/geos_c_impl/factory.h +28 -14
- data/ext/geos_c_impl/geometry.c +46 -14
- data/ext/geos_c_impl/geometry.h +7 -0
- data/ext/geos_c_impl/geometry_collection.c +2 -104
- data/ext/geos_c_impl/geometry_collection.h +0 -11
- data/ext/geos_c_impl/line_string.c +1 -1
- data/ext/geos_c_impl/point.c +1 -1
- data/ext/geos_c_impl/polygon.c +1 -37
- data/ext/geos_c_impl/preface.h +3 -0
- data/lib/rgeo/cartesian/calculations.rb +54 -17
- data/lib/rgeo/cartesian/factory.rb +0 -7
- data/lib/rgeo/cartesian/feature_classes.rb +66 -46
- data/lib/rgeo/cartesian/feature_methods.rb +51 -20
- data/lib/rgeo/cartesian/interface.rb +0 -6
- data/lib/rgeo/cartesian/planar_graph.rb +379 -0
- data/lib/rgeo/cartesian/sweepline_intersector.rb +149 -0
- data/lib/rgeo/cartesian/valid_op.rb +71 -0
- data/lib/rgeo/cartesian.rb +3 -0
- data/lib/rgeo/coord_sys/cs/wkt_parser.rb +6 -6
- data/lib/rgeo/error.rb +15 -0
- data/lib/rgeo/feature/geometry.rb +28 -28
- data/lib/rgeo/feature/geometry_collection.rb +13 -5
- data/lib/rgeo/feature/line_string.rb +3 -3
- data/lib/rgeo/feature/multi_surface.rb +3 -3
- data/lib/rgeo/feature/point.rb +4 -4
- data/lib/rgeo/feature/surface.rb +3 -3
- data/lib/rgeo/geographic/factory.rb +0 -7
- data/lib/rgeo/geographic/interface.rb +5 -20
- data/lib/rgeo/geographic/proj4_projector.rb +0 -2
- data/lib/rgeo/geographic/projected_feature_classes.rb +21 -9
- data/lib/rgeo/geographic/projected_feature_methods.rb +51 -28
- data/lib/rgeo/geographic/simple_mercator_projector.rb +0 -2
- data/lib/rgeo/geographic/spherical_feature_classes.rb +29 -9
- data/lib/rgeo/geographic/spherical_feature_methods.rb +62 -1
- data/lib/rgeo/geos/capi_factory.rb +21 -31
- data/lib/rgeo/geos/capi_feature_classes.rb +35 -11
- data/lib/rgeo/geos/ffi_factory.rb +0 -28
- data/lib/rgeo/geos/ffi_feature_classes.rb +34 -10
- data/lib/rgeo/geos/ffi_feature_methods.rb +23 -5
- data/lib/rgeo/geos/interface.rb +0 -7
- data/lib/rgeo/geos/zm_factory.rb +0 -12
- data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +4 -4
- data/lib/rgeo/impl_helper/basic_geometry_methods.rb +1 -1
- data/lib/rgeo/impl_helper/basic_line_string_methods.rb +15 -19
- data/lib/rgeo/impl_helper/basic_point_methods.rb +1 -1
- data/lib/rgeo/impl_helper/basic_polygon_methods.rb +1 -1
- data/lib/rgeo/impl_helper/valid_op.rb +354 -0
- data/lib/rgeo/impl_helper/validity_check.rb +138 -0
- data/lib/rgeo/impl_helper.rb +1 -0
- data/lib/rgeo/version.rb +1 -1
- metadata +31 -10
@@ -0,0 +1,354 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "set"
|
4
|
+
|
5
|
+
module RGeo
|
6
|
+
module ImplHelper
|
7
|
+
# Mixin based off of the JTS/GEOS IsValidOp class.
|
8
|
+
# Implements #valid? and #invalid_reason on Features that include this.
|
9
|
+
#
|
10
|
+
# @see https://github.com/locationtech/jts/blob/master/modules/core/src/main/java/org/locationtech/jts/operation/valid/IsValidOp.java
|
11
|
+
module ValidOp
|
12
|
+
# Validity of geometry
|
13
|
+
#
|
14
|
+
# @return Boolean
|
15
|
+
def valid?
|
16
|
+
invalid_reason.nil?
|
17
|
+
end
|
18
|
+
|
19
|
+
# Reason for invalidity or nil if valid
|
20
|
+
#
|
21
|
+
# @return String
|
22
|
+
def invalid_reason
|
23
|
+
return @invalid_reason if defined?(@invalid_reason)
|
24
|
+
@invalid_reason = check_valid
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def validity_helper
|
30
|
+
ValidOpHelpers
|
31
|
+
end
|
32
|
+
|
33
|
+
# Method that performs validity checking. Just checks the type of geometry
|
34
|
+
# and delegates to the proper validity checker.
|
35
|
+
#
|
36
|
+
# Returns a string describing the error or nil if it's a valid geometry.
|
37
|
+
# In some cases, "Unkown Validity" is returned if a dependent method has
|
38
|
+
# not been implemented.
|
39
|
+
#
|
40
|
+
# @return String
|
41
|
+
def check_valid
|
42
|
+
case self
|
43
|
+
when Feature::Point
|
44
|
+
check_valid_point
|
45
|
+
when Feature::LinearRing
|
46
|
+
check_valid_linear_ring
|
47
|
+
when Feature::LineString
|
48
|
+
check_valid_line_string
|
49
|
+
when Feature::Polygon
|
50
|
+
check_valid_polygon
|
51
|
+
when Feature::MultiPoint
|
52
|
+
check_valid_multi_point
|
53
|
+
when Feature::MultiPolygon
|
54
|
+
check_valid_multi_polygon
|
55
|
+
when Feature::GeometryCollection
|
56
|
+
check_valid_geometry_collection
|
57
|
+
else
|
58
|
+
raise NotImplementedError, "check_valid is not implemented for #{self}"
|
59
|
+
end
|
60
|
+
rescue RGeo::Error::UnsupportedOperation, NoMethodError
|
61
|
+
"Unkown Validity"
|
62
|
+
end
|
63
|
+
|
64
|
+
def check_valid_point
|
65
|
+
validity_helper.check_invalid_coordinate(self)
|
66
|
+
end
|
67
|
+
|
68
|
+
def check_valid_line_string
|
69
|
+
# check coordinates are all valid
|
70
|
+
points.each do |pt|
|
71
|
+
check = validity_helper.check_invalid_coordinate(pt)
|
72
|
+
return check unless check.nil?
|
73
|
+
end
|
74
|
+
|
75
|
+
# check more than 1 point
|
76
|
+
return Error::TOO_FEW_POINTS unless num_points > 1
|
77
|
+
|
78
|
+
nil
|
79
|
+
end
|
80
|
+
|
81
|
+
def check_valid_linear_ring
|
82
|
+
# check coordinates are all valid
|
83
|
+
points.each do |pt|
|
84
|
+
check = validity_helper.check_invalid_coordinate(pt)
|
85
|
+
return check unless check.nil?
|
86
|
+
end
|
87
|
+
|
88
|
+
# check closed
|
89
|
+
return Error::UNCLOSED_RING unless closed?
|
90
|
+
|
91
|
+
# check more than 3 points
|
92
|
+
return Error::TOO_FEW_POINTS unless num_points > 3
|
93
|
+
|
94
|
+
# check no self-intersections
|
95
|
+
validity_helper.check_no_self_intersections(self)
|
96
|
+
end
|
97
|
+
|
98
|
+
def check_valid_polygon
|
99
|
+
# check coordinates are all valid
|
100
|
+
exterior_ring.points.each do |pt|
|
101
|
+
check = validity_helper.check_invalid_coordinate(pt)
|
102
|
+
return check unless check.nil?
|
103
|
+
end
|
104
|
+
interior_rings.each do |ring|
|
105
|
+
ring.points.each do |pt|
|
106
|
+
check = validity_helper.check_invalid_coordinate(pt)
|
107
|
+
return check unless check.nil?
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# check closed
|
112
|
+
return Error::UNCLOSED_RING unless exterior_ring.closed?
|
113
|
+
return Error::UNCLOSED_RING unless interior_rings.all?(&:closed?)
|
114
|
+
|
115
|
+
# check more than 3 points in each ring
|
116
|
+
return Error::TOO_FEW_POINTS unless exterior_ring.num_points > 3
|
117
|
+
return Error::TOO_FEW_POINTS unless interior_rings.all? { |r| r.num_points > 3 }
|
118
|
+
|
119
|
+
# can skip this check if there's no holes
|
120
|
+
unless interior_rings.empty?
|
121
|
+
check = validity_helper.check_consistent_area(self)
|
122
|
+
return check unless check.nil?
|
123
|
+
end
|
124
|
+
|
125
|
+
# check that there are no self-intersections
|
126
|
+
check = validity_helper.check_no_self_intersecting_rings(self)
|
127
|
+
return check unless check.nil?
|
128
|
+
|
129
|
+
# can skip these checks if there's no holes
|
130
|
+
unless interior_rings.empty?
|
131
|
+
check = validity_helper.check_holes_in_shell(self)
|
132
|
+
return check unless check.nil?
|
133
|
+
|
134
|
+
check = validity_helper.check_holes_not_nested(self)
|
135
|
+
return check unless check.nil?
|
136
|
+
|
137
|
+
check = validity_helper.check_connected_interiors(self)
|
138
|
+
return check unless check.nil?
|
139
|
+
end
|
140
|
+
|
141
|
+
nil
|
142
|
+
end
|
143
|
+
|
144
|
+
def check_valid_multi_point
|
145
|
+
geometries.each do |pt|
|
146
|
+
check = validity_helper.check_invalid_coordinate(pt)
|
147
|
+
return check unless check.nil?
|
148
|
+
end
|
149
|
+
nil
|
150
|
+
end
|
151
|
+
|
152
|
+
def check_valid_multi_polygon
|
153
|
+
geometries.each do |poly|
|
154
|
+
return poly.invalid_reason unless poly.invalid_reason.nil?
|
155
|
+
end
|
156
|
+
|
157
|
+
check = validity_helper.check_consistent_area_mp(self)
|
158
|
+
return check unless check.nil?
|
159
|
+
|
160
|
+
# check no shells are nested
|
161
|
+
check = validity_helper.check_shells_not_nested(self)
|
162
|
+
return check unless check.nil?
|
163
|
+
|
164
|
+
nil
|
165
|
+
end
|
166
|
+
|
167
|
+
def check_valid_geometry_collection
|
168
|
+
geometries.each do |geom|
|
169
|
+
return geom.invalid_reason unless geom.invalid_reason.nil?
|
170
|
+
end
|
171
|
+
|
172
|
+
nil
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
##
|
177
|
+
# Helper functions for specific validity checks
|
178
|
+
##
|
179
|
+
module ValidOpHelpers
|
180
|
+
module_function
|
181
|
+
|
182
|
+
# Checks that the given point has valid coordinates.
|
183
|
+
#
|
184
|
+
# @param pt [RGeo::Feature::Point]
|
185
|
+
#
|
186
|
+
# @return [String] invalid_reason
|
187
|
+
def check_invalid_coordinate(pt)
|
188
|
+
x = pt.x
|
189
|
+
y = pt.y
|
190
|
+
return if x.finite? && y.finite? && x.real? && y.real?
|
191
|
+
|
192
|
+
Error::INVALID_COORDINATE
|
193
|
+
end
|
194
|
+
|
195
|
+
# Checks that the edges in the polygon form a consistent area.
|
196
|
+
#
|
197
|
+
# Specifically, checks that there are intersections no between the
|
198
|
+
# holes and the shell.
|
199
|
+
#
|
200
|
+
# Also checks that there are no duplicate rings.
|
201
|
+
#
|
202
|
+
# @param poly [RGeo::Feature::Polygon]
|
203
|
+
#
|
204
|
+
# @return [String] invalid_reason
|
205
|
+
def check_consistent_area(poly)
|
206
|
+
# Holes don't cross exterior check.
|
207
|
+
exterior = poly.exterior_ring
|
208
|
+
poly.interior_rings.each do |ring|
|
209
|
+
return Error::SELF_INTERSECTION if ring.crosses?(exterior)
|
210
|
+
end
|
211
|
+
|
212
|
+
# check interiors do not cross
|
213
|
+
poly.interior_rings.combination(2).each do |ring1, ring2|
|
214
|
+
return Error::SELF_INTERSECTION if ring1.crosses?(ring2)
|
215
|
+
end
|
216
|
+
|
217
|
+
# Duplicate rings check
|
218
|
+
rings = [exterior] + poly.interior_rings
|
219
|
+
return Error::SELF_INTERSECTION if rings.uniq.size != rings.size
|
220
|
+
|
221
|
+
nil
|
222
|
+
end
|
223
|
+
|
224
|
+
# Checks that the ring does not self-intersect. This is just a simplicity
|
225
|
+
# check on the ring.
|
226
|
+
#
|
227
|
+
# @param ring [RGeo::Feature::LinearRing]
|
228
|
+
#
|
229
|
+
# @return [String] invalid_reason
|
230
|
+
def check_no_self_intersections(ring)
|
231
|
+
return Error::SELF_INTERSECTION unless ring.simple?
|
232
|
+
end
|
233
|
+
|
234
|
+
# Check that rings do not self intersect in a polygon
|
235
|
+
#
|
236
|
+
# @param poly [RGeo::Feature::Polygon]
|
237
|
+
#
|
238
|
+
# @return [String] invalid_reason
|
239
|
+
def check_no_self_intersecting_rings(poly)
|
240
|
+
exterior = poly.exterior_ring
|
241
|
+
|
242
|
+
check = check_no_self_intersections(exterior)
|
243
|
+
return check unless check.nil?
|
244
|
+
|
245
|
+
poly.interior_rings.each do |ring|
|
246
|
+
check = check_no_self_intersections(ring)
|
247
|
+
return check unless check.nil?
|
248
|
+
end
|
249
|
+
|
250
|
+
nil
|
251
|
+
end
|
252
|
+
|
253
|
+
# Checks holes are contained inside the exterior of a polygon.
|
254
|
+
# Assuming check_consistent_area has already passed on the polygon,
|
255
|
+
# a simple point in polygon check can be done on one of the points
|
256
|
+
# in each hole to verify (since we know none of them intersect).
|
257
|
+
#
|
258
|
+
# @param poly [RGeo::Feature::Polygon]
|
259
|
+
#
|
260
|
+
# @return [String] invalid_reason
|
261
|
+
def check_holes_in_shell(poly)
|
262
|
+
# get hole-less shell as test polygon
|
263
|
+
shell = poly.exterior_ring
|
264
|
+
shell = shell.factory.polygon(shell)
|
265
|
+
|
266
|
+
poly.interior_rings.each do |interior|
|
267
|
+
test_pt = interior.start_point
|
268
|
+
unless shell.contains?(test_pt) || poly.exterior_ring.contains?(test_pt)
|
269
|
+
return Error::HOLE_OUTSIDE_SHELL
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
nil
|
274
|
+
end
|
275
|
+
|
276
|
+
# Checks that holes are not nested within each other.
|
277
|
+
#
|
278
|
+
# @param poly [RGeo::Feature::Polygon]
|
279
|
+
#
|
280
|
+
# @return [String] invalid_reason
|
281
|
+
def check_holes_not_nested(poly)
|
282
|
+
# convert holes from linear_rings to polygons
|
283
|
+
# Same logic that applies to check_holes_in_shell applies here
|
284
|
+
# since we've already passed the consistent area test, we just
|
285
|
+
# have to check if one point from each hole is contained in the other.
|
286
|
+
holes = poly.interior_rings
|
287
|
+
holes = holes.map { |v| v.factory.polygon(v) }
|
288
|
+
holes.combination(2).each do |p1, p2|
|
289
|
+
if p1.contains?(p2.exterior_ring.start_point) || p2.contains?(p1.exterior_ring.start_point)
|
290
|
+
return Error::NESTED_HOLES
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
nil
|
295
|
+
end
|
296
|
+
|
297
|
+
# Checks that the interior of the polygon is connected.
|
298
|
+
# A disconnected interior can be described by this polygon for example
|
299
|
+
# POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (5 0, 10 5, 5 10, 0 5, 5 0))
|
300
|
+
#
|
301
|
+
# Which is a square with a diamond inside of it.
|
302
|
+
#
|
303
|
+
# @param poly [RGeo::Feature::Polygon]
|
304
|
+
#
|
305
|
+
# @return [String] invalid_reason
|
306
|
+
def check_connected_interiors(poly)
|
307
|
+
# This is not proper and will flag valid geometries as invalid, but
|
308
|
+
# is an ok approximation.
|
309
|
+
# Idea is to check if a single hole has multiple points on the
|
310
|
+
# exterior ring.
|
311
|
+
poly.interior_rings.each do |ring|
|
312
|
+
touches = Set.new
|
313
|
+
ring.points.each do |pt|
|
314
|
+
touches.add(pt) if poly.exterior_ring.contains?(pt)
|
315
|
+
end
|
316
|
+
|
317
|
+
return Error::DISCONNECTED_INTERIOR if touches.size > 1
|
318
|
+
end
|
319
|
+
|
320
|
+
nil
|
321
|
+
end
|
322
|
+
|
323
|
+
# Checks that polygons do not intersect in a multipolygon.
|
324
|
+
#
|
325
|
+
# @param mp [RGeo::Feature::MultiPolygon]
|
326
|
+
#
|
327
|
+
# @return [String] invalid_reason
|
328
|
+
def check_consistent_area_mp(mp)
|
329
|
+
mp.geometries.combination(2) do |p1, p2|
|
330
|
+
if p1.exterior_ring.crosses?(p2.exterior_ring)
|
331
|
+
return Error::SELF_INTERSECTION
|
332
|
+
end
|
333
|
+
end
|
334
|
+
nil
|
335
|
+
end
|
336
|
+
|
337
|
+
# Checks that individual polygons within a multipolygon are not nested.
|
338
|
+
#
|
339
|
+
# @param mp [RGeo::Feature::MultiPolygon]
|
340
|
+
#
|
341
|
+
# @return [String] invalid_reason
|
342
|
+
def check_shells_not_nested(mp)
|
343
|
+
# Since we've passed the consistent area test, we can just check
|
344
|
+
# that one point lies in the other.
|
345
|
+
mp.geometries.combination(2) do |p1, p2|
|
346
|
+
if p1.contains?(p2.exterior_ring.start_point) || p2.contains?(p1.exterior_ring.start_point)
|
347
|
+
return Error::NESTED_SHELLS
|
348
|
+
end
|
349
|
+
end
|
350
|
+
nil
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RGeo
|
4
|
+
module ImplHelper
|
5
|
+
# This helper enforces valid geometry computation, avoiding results such
|
6
|
+
# as a 0 area for a bowtie shaped polygon. Implementations that are part
|
7
|
+
# of RGeo core should all include this.
|
8
|
+
#
|
9
|
+
# You can play around validity checks if needed:
|
10
|
+
#
|
11
|
+
# - {check_validity!} is the method that will raise if your geometry is
|
12
|
+
# not valid. Its message will be the same as {invalid_reason}.
|
13
|
+
# - {make_valid} is the method you can call to get a valid copy of the
|
14
|
+
# current geometry.
|
15
|
+
# - finally, you can bypass any checked method by prepending `unsafe_` to
|
16
|
+
# it. At your own risk.
|
17
|
+
module ValidityCheck
|
18
|
+
# Every method that should not be overriden by the validity check.
|
19
|
+
# Those methods are either accessors or very basic methods not related
|
20
|
+
# to validity checks, or are used to check validity, in which case the
|
21
|
+
# `true/false` gives a correct information, no need to raise).
|
22
|
+
UNCHECKED_METHODS = [
|
23
|
+
# Basic methods
|
24
|
+
:factory, :geometry_type, :as_text, :as_binary, :srid,
|
25
|
+
# Tests
|
26
|
+
:simple?, :closed?, :empty?,
|
27
|
+
# Accessors
|
28
|
+
:exterior_ring, :interior_rings, :[], :num_geometries, :num_interior_rings,
|
29
|
+
:geometry_n, :each, :points, :point_n, :start_point, :end_point, :x, :y, :z, :m,
|
30
|
+
# Trivial methods
|
31
|
+
:num_points,
|
32
|
+
# Comparison
|
33
|
+
:equals?, :rep_equals?, :eql?, :==, :'!='
|
34
|
+
].freeze
|
35
|
+
private_constant :UNCHECKED_METHODS
|
36
|
+
|
37
|
+
# Since methods have their unsafe_ counter part, it means that the `+`
|
38
|
+
# method would lead to having an `unsafe_+` method that is not simply
|
39
|
+
# callable. Here's a simple fallback:
|
40
|
+
SYMBOL2NAME = {
|
41
|
+
:+ => "add",
|
42
|
+
:- => "remove",
|
43
|
+
:* => "multiply"
|
44
|
+
}.tap { |h| h.default_proc = ->(_, key) { key.to_s } }.freeze
|
45
|
+
private_constant :SYMBOL2NAME
|
46
|
+
|
47
|
+
class << self
|
48
|
+
# Note for contributors: this should be called after all methods
|
49
|
+
# are loaded for a given feature classe. No worries though, this
|
50
|
+
# is tested.
|
51
|
+
def override_classes # :nodoc:
|
52
|
+
# Using pop here to be thread safe.
|
53
|
+
while (klass = classes.pop)
|
54
|
+
override(klass)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def included(klass) # :nodoc:
|
59
|
+
classes << klass
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def classes
|
65
|
+
@classes ||= []
|
66
|
+
end
|
67
|
+
|
68
|
+
def override(klass)
|
69
|
+
methods_to_check = feature_methods(klass)
|
70
|
+
|
71
|
+
klass.class_eval do
|
72
|
+
methods_to_check.each do |method_sym|
|
73
|
+
copy = "unsafe_#{SYMBOL2NAME[method_sym]}".to_sym
|
74
|
+
alias_method copy, method_sym
|
75
|
+
undef_method method_sym
|
76
|
+
define_method(method_sym) do |*args|
|
77
|
+
check_validity!
|
78
|
+
args.each do |arg|
|
79
|
+
arg.check_validity! if RGeo::Feature::Geometry.check_type(arg)
|
80
|
+
end
|
81
|
+
method(copy).call(*args)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def feature_methods(klass)
|
88
|
+
feature_defs = Set.new
|
89
|
+
klass
|
90
|
+
.ancestors
|
91
|
+
.select { |ancestor| ancestor <= RGeo::Feature::Geometry }
|
92
|
+
.each { |ancestor| feature_defs.merge(ancestor.instance_methods(false)) }
|
93
|
+
feature_defs & klass.instance_methods - UNCHECKED_METHODS
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Raises {invalid_reason} if the polygon is not valid, does nothing
|
98
|
+
# otherwise.
|
99
|
+
def check_validity!
|
100
|
+
# This method will use a cached invalid_reason for performance purposes.
|
101
|
+
# DO NOT MUTATE GEOMETRIES.
|
102
|
+
return unless invalid_reason_memo
|
103
|
+
|
104
|
+
raise Error::InvalidGeometry, invalid_reason_memo
|
105
|
+
end
|
106
|
+
|
107
|
+
# Tell why the geometry is not valid, `nil` means it is valid.
|
108
|
+
def invalid_reason
|
109
|
+
if defined?(super) == "super"
|
110
|
+
raise Error::RGeoError, "ValidityCheck MUST be loaded before " \
|
111
|
+
"definition of #{self.class}##{__method__}."
|
112
|
+
end
|
113
|
+
|
114
|
+
raise Error::UnsupportedOperation, "Method #{self.class}##{__method__} not defined."
|
115
|
+
end
|
116
|
+
|
117
|
+
# Try and make the geometry valid, this may change its shape.
|
118
|
+
# Returns a valid copy of the geometry.
|
119
|
+
def make_valid
|
120
|
+
if defined?(super) == "super"
|
121
|
+
raise Error::RGeoError, "ValidityCheck MUST be loaded before " \
|
122
|
+
"definition of #{self.class}##{__method__}."
|
123
|
+
end
|
124
|
+
|
125
|
+
raise Error::UnsupportedOperation, "Method #{self.class}##{__method__} not defined."
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
def invalid_reason_memo
|
131
|
+
# `defined?` is a bit faster than `instance_variable_defined?`.
|
132
|
+
return @invalid_reason_memo if defined?(@invalid_reason_memo)
|
133
|
+
|
134
|
+
@invalid_reason_memo = invalid_reason
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
data/lib/rgeo/impl_helper.rb
CHANGED
data/lib/rgeo/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rgeo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0.pre.rc.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Azuma
|
8
8
|
- Tee Parham
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2022-
|
12
|
+
date: 2022-03-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi-geos
|
@@ -17,14 +17,14 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
20
|
+
version: '2.2'
|
21
21
|
type: :development
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: '
|
27
|
+
version: '2.2'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: minitest
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -81,6 +81,20 @@ dependencies:
|
|
81
81
|
- - "~>"
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: 1.8.1
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: yard
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0.9'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0.9'
|
84
98
|
description: RGeo is a geospatial data library for Ruby. It provides an implementation
|
85
99
|
of the Open Geospatial Consortium's Simple Features Specification, used by most
|
86
100
|
standard spatial/geographic data storage systems such as PostGIS. A number of add-on
|
@@ -90,11 +104,13 @@ email:
|
|
90
104
|
- dazuma@gmail.com
|
91
105
|
- parhameter@gmail.com
|
92
106
|
- kfdoggett@gmail.com
|
107
|
+
- buonomo.ulysse@gmail.com
|
93
108
|
executables: []
|
94
109
|
extensions:
|
95
110
|
- ext/geos_c_impl/extconf.rb
|
96
111
|
extra_rdoc_files: []
|
97
112
|
files:
|
113
|
+
- ".yardopts"
|
98
114
|
- LICENSE.txt
|
99
115
|
- README.md
|
100
116
|
- ext/geos_c_impl/analysis.c
|
@@ -129,6 +145,9 @@ files:
|
|
129
145
|
- lib/rgeo/cartesian/feature_classes.rb
|
130
146
|
- lib/rgeo/cartesian/feature_methods.rb
|
131
147
|
- lib/rgeo/cartesian/interface.rb
|
148
|
+
- lib/rgeo/cartesian/planar_graph.rb
|
149
|
+
- lib/rgeo/cartesian/sweepline_intersector.rb
|
150
|
+
- lib/rgeo/cartesian/valid_op.rb
|
132
151
|
- lib/rgeo/coord_sys.rb
|
133
152
|
- lib/rgeo/coord_sys/cs/entities.rb
|
134
153
|
- lib/rgeo/coord_sys/cs/factories.rb
|
@@ -185,6 +204,8 @@ files:
|
|
185
204
|
- lib/rgeo/impl_helper/basic_polygon_methods.rb
|
186
205
|
- lib/rgeo/impl_helper/math.rb
|
187
206
|
- lib/rgeo/impl_helper/utils.rb
|
207
|
+
- lib/rgeo/impl_helper/valid_op.rb
|
208
|
+
- lib/rgeo/impl_helper/validity_check.rb
|
188
209
|
- lib/rgeo/version.rb
|
189
210
|
- lib/rgeo/wkrep.rb
|
190
211
|
- lib/rgeo/wkrep/wkb_generator.rb
|
@@ -195,7 +216,7 @@ homepage: https://github.com/rgeo/rgeo
|
|
195
216
|
licenses:
|
196
217
|
- BSD-3-Clause
|
197
218
|
metadata: {}
|
198
|
-
post_install_message:
|
219
|
+
post_install_message:
|
199
220
|
rdoc_options: []
|
200
221
|
require_paths:
|
201
222
|
- lib
|
@@ -206,12 +227,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
206
227
|
version: 2.5.0
|
207
228
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
208
229
|
requirements:
|
209
|
-
- - "
|
230
|
+
- - ">"
|
210
231
|
- !ruby/object:Gem::Version
|
211
|
-
version:
|
232
|
+
version: 1.3.1
|
212
233
|
requirements: []
|
213
|
-
rubygems_version: 3.1.
|
214
|
-
signing_key:
|
234
|
+
rubygems_version: 3.1.4
|
235
|
+
signing_key:
|
215
236
|
specification_version: 4
|
216
237
|
summary: RGeo is a geospatial data library for Ruby.
|
217
238
|
test_files: []
|