rgeo 2.3.0 → 3.0.0.pre.rc.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +6 -0
- data/README.md +1 -0
- data/ext/geos_c_impl/analysis.c +8 -6
- data/ext/geos_c_impl/analysis.h +1 -3
- data/ext/geos_c_impl/errors.c +10 -8
- data/ext/geos_c_impl/errors.h +7 -3
- data/ext/geos_c_impl/extconf.rb +3 -0
- data/ext/geos_c_impl/factory.c +251 -182
- data/ext/geos_c_impl/factory.h +43 -62
- data/ext/geos_c_impl/geometry.c +56 -24
- data/ext/geos_c_impl/geometry.h +8 -3
- data/ext/geos_c_impl/geometry_collection.c +41 -148
- data/ext/geos_c_impl/geometry_collection.h +1 -14
- data/ext/geos_c_impl/globals.c +91 -0
- data/ext/geos_c_impl/globals.h +45 -0
- data/ext/geos_c_impl/line_string.c +28 -29
- data/ext/geos_c_impl/line_string.h +1 -3
- data/ext/geos_c_impl/main.c +10 -9
- data/ext/geos_c_impl/point.c +9 -8
- data/ext/geos_c_impl/point.h +1 -3
- data/ext/geos_c_impl/polygon.c +15 -51
- data/ext/geos_c_impl/polygon.h +1 -3
- data/ext/geos_c_impl/preface.h +8 -0
- data/lib/rgeo/cartesian/analysis.rb +2 -2
- 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 +56 -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/curve.rb +12 -2
- data/lib/rgeo/feature/geometry.rb +38 -28
- data/lib/rgeo/feature/geometry_collection.rb +13 -5
- data/lib/rgeo/feature/line_string.rb +3 -3
- data/lib/rgeo/feature/multi_curve.rb +6 -1
- 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 +4 -18
- 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 +63 -30
- 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 +68 -2
- data/lib/rgeo/geos/capi_factory.rb +21 -31
- data/lib/rgeo/geos/capi_feature_classes.rb +64 -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 +53 -10
- data/lib/rgeo/geos/interface.rb +18 -10
- data/lib/rgeo/geos/zm_factory.rb +0 -12
- data/lib/rgeo/geos/zm_feature_methods.rb +30 -5
- data/lib/rgeo/impl_helper/basic_geometry_collection_methods.rb +18 -8
- data/lib/rgeo/impl_helper/basic_geometry_methods.rb +1 -1
- data/lib/rgeo/impl_helper/basic_line_string_methods.rb +37 -26
- data/lib/rgeo/impl_helper/basic_point_methods.rb +13 -3
- data/lib/rgeo/impl_helper/basic_polygon_methods.rb +8 -3
- 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
- data/lib/rgeo/wkrep/wkb_generator.rb +1 -1
- data/lib/rgeo/wkrep/wkt_generator.rb +6 -6
- metadata +30 -7
@@ -0,0 +1,149 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# -----------------------------------------------------------------------------
|
4
|
+
#
|
5
|
+
# Simple Sweepline Intersector Class
|
6
|
+
#
|
7
|
+
# -----------------------------------------------------------------------------
|
8
|
+
|
9
|
+
module RGeo
|
10
|
+
module Cartesian
|
11
|
+
# Implements a Sweepline intersector to find all intersections
|
12
|
+
# in a group of segments. The idea is to use a horizontal line starting
|
13
|
+
# at y = +Infinity that sweeps down to y = -Infinity and every time it hits
|
14
|
+
# a new line, it will check if it intersects with any of the segments
|
15
|
+
# the line currently intersects at that y value.
|
16
|
+
# This is a more simplistic implementation that uses an array to hold
|
17
|
+
# observed segments instead of a sorted BST, so performance may be significantly
|
18
|
+
# worse in the case of lots of segments overlapping in y-ranges.
|
19
|
+
class SweeplineIntersector
|
20
|
+
Event = Struct.new(:point, :segment, :is_start)
|
21
|
+
Intersection = Struct.new(:point, :s1, :s2)
|
22
|
+
|
23
|
+
def initialize(segments)
|
24
|
+
@segments = segments
|
25
|
+
end
|
26
|
+
attr_reader :segments
|
27
|
+
|
28
|
+
# Returns the "proper" intersections from the list of segments.
|
29
|
+
#
|
30
|
+
# This will only return intersections that are not the start/end or
|
31
|
+
# end/start of the 2 segments. This could be useful for finding intersections
|
32
|
+
# in a ring for example, because knowing that segments are connected in a linestring
|
33
|
+
# is not always helpful, but those are reported by default.
|
34
|
+
#
|
35
|
+
# Note: This is not the true definition of a proper intersection. A
|
36
|
+
# truly proper intersection does not include colinear intersections and
|
37
|
+
# the intersection must lie in the interior of both segments.
|
38
|
+
#
|
39
|
+
# @return [Array<RGeo::Cartesian::SweeplineIntersector::Intersection>]
|
40
|
+
def proper_intersections
|
41
|
+
return @proper_intersections if defined?(@proper_intersections)
|
42
|
+
|
43
|
+
@proper_intersections = []
|
44
|
+
intersections.each do |intersection|
|
45
|
+
s1 = intersection.s1
|
46
|
+
s2 = intersection.s2
|
47
|
+
pt = intersection.point
|
48
|
+
|
49
|
+
unless (pt == s1.s && pt == s2.e) || (pt == s1.e && pt == s2.s)
|
50
|
+
@proper_intersections << intersection
|
51
|
+
end
|
52
|
+
end
|
53
|
+
@proper_intersections
|
54
|
+
end
|
55
|
+
|
56
|
+
# Computes the intersections of the input segments.
|
57
|
+
#
|
58
|
+
# Creates an event queue from the +events+ and adds segments to the
|
59
|
+
# +observed_segments+ array while their ending event has not been popped
|
60
|
+
# from the queue.
|
61
|
+
#
|
62
|
+
# Compares the new segment from the +is_start+ event to each observed segment
|
63
|
+
# then adds it to +observed_segments+. Records any intersections in to the
|
64
|
+
# returned array.
|
65
|
+
#
|
66
|
+
# @return [Array<RGeo::Cartesian::SweeplineIntersector::Intersection>]
|
67
|
+
def intersections
|
68
|
+
return @intersections if defined?(@intersections)
|
69
|
+
|
70
|
+
@intersections = []
|
71
|
+
observed_segments = Set.new
|
72
|
+
events.each do |e|
|
73
|
+
seg = e.segment
|
74
|
+
|
75
|
+
if e.is_start
|
76
|
+
observed_segments.each do |oseg|
|
77
|
+
int_pt = seg.segment_intersection(oseg)
|
78
|
+
if int_pt
|
79
|
+
intersect = Intersection.new(int_pt, seg, oseg)
|
80
|
+
@intersections << intersect
|
81
|
+
end
|
82
|
+
end
|
83
|
+
observed_segments << seg
|
84
|
+
else
|
85
|
+
observed_segments.delete(seg)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
@intersections
|
89
|
+
end
|
90
|
+
|
91
|
+
# Returns an ordered array of events from the input segments. Events
|
92
|
+
# are the start and endpoints of each segment with an is_start tag to
|
93
|
+
# indicate if this is the starting or ending event for that segment.
|
94
|
+
#
|
95
|
+
# Ordering is done by greatest-y -> smallest-x -> is_start = true.
|
96
|
+
#
|
97
|
+
# @return [Array]
|
98
|
+
def events
|
99
|
+
return @events if defined?(@events)
|
100
|
+
|
101
|
+
@events = []
|
102
|
+
segments.each do |segment|
|
103
|
+
event_pair = create_event_pair(segment)
|
104
|
+
@events.concat(event_pair)
|
105
|
+
end
|
106
|
+
|
107
|
+
@events.sort! do |a, b|
|
108
|
+
if a.point == b.point
|
109
|
+
if a.is_start
|
110
|
+
-1
|
111
|
+
else
|
112
|
+
1
|
113
|
+
end
|
114
|
+
elsif a.point.y == b.point.y
|
115
|
+
a.point.x <=> b.point.x
|
116
|
+
else
|
117
|
+
b.point.y <=> a.point.y
|
118
|
+
end
|
119
|
+
end
|
120
|
+
@events
|
121
|
+
end
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
# Creates a pair of events from a segment
|
126
|
+
#
|
127
|
+
# @param segment [Segment]
|
128
|
+
#
|
129
|
+
# @return [Array]
|
130
|
+
def create_event_pair(segment)
|
131
|
+
s = segment.s
|
132
|
+
e = segment.e
|
133
|
+
|
134
|
+
s_event = Event.new(s, segment)
|
135
|
+
e_event = Event.new(e, segment)
|
136
|
+
|
137
|
+
if s.y > e.y || (s.y == e.y && s.x < e.x)
|
138
|
+
s_event.is_start = true
|
139
|
+
e_event.is_start = false
|
140
|
+
else
|
141
|
+
s_event.is_start = false
|
142
|
+
e_event.is_start = true
|
143
|
+
end
|
144
|
+
|
145
|
+
[s_event, e_event]
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RGeo
|
4
|
+
module Cartesian
|
5
|
+
module ValidOp
|
6
|
+
include ImplHelper::ValidOp
|
7
|
+
|
8
|
+
def validity_helper
|
9
|
+
ValidOpHelpers
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module ValidOpHelpers
|
14
|
+
include ImplHelper::ValidOpHelpers
|
15
|
+
|
16
|
+
module_function(*ImplHelper::ValidOpHelpers.singleton_methods) # rubocop:disable Style/AccessModifierDeclarations
|
17
|
+
|
18
|
+
module_function
|
19
|
+
|
20
|
+
# Checks that there are no invalid intersections between the components
|
21
|
+
# of a polygon.
|
22
|
+
#
|
23
|
+
# @param [RGeo::Feature::Polygon] poly
|
24
|
+
#
|
25
|
+
# @return [String] invalid_reason
|
26
|
+
def check_consistent_area(poly)
|
27
|
+
# Get set of unique coords
|
28
|
+
pts = poly.exterior_ring.coordinates.to_set
|
29
|
+
poly.interior_rings.each do |ring|
|
30
|
+
pts += ring.coordinates
|
31
|
+
end
|
32
|
+
num_points = pts.size
|
33
|
+
|
34
|
+
# if additional nodes were added, there must be an intersection
|
35
|
+
# through a boundary.
|
36
|
+
if poly.send(:graph).incident_edges.size > num_points
|
37
|
+
return Error::SELF_INTERSECTION
|
38
|
+
end
|
39
|
+
|
40
|
+
rings = [poly.exterior_ring] + poly.interior_rings
|
41
|
+
return Error::SELF_INTERSECTION if rings.uniq.size != rings.size
|
42
|
+
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
|
46
|
+
# Checks that the interior of a polygon is connected.
|
47
|
+
#
|
48
|
+
# Process to do this is to walk around an interior cycle of the
|
49
|
+
# exterior shell in the polygon's geometry graph. It will keep track
|
50
|
+
# of all the nodes it visited and if that set is a superset of the
|
51
|
+
# coordinates in the exterior_ring, the interior is connected, otherwise
|
52
|
+
# it is split somewhere.
|
53
|
+
#
|
54
|
+
# @param [RGeo::Feature::Polygon] poly
|
55
|
+
#
|
56
|
+
# @return [String] invalid_reason
|
57
|
+
def check_connected_interiors(poly)
|
58
|
+
exterior_coords = poly.exterior_ring.coordinates.to_set
|
59
|
+
|
60
|
+
visited = Set.new
|
61
|
+
poly.send(:graph).geom_edges.first.exterior_edge.and_connected do |hedge|
|
62
|
+
visited << hedge.origin.coordinates
|
63
|
+
end
|
64
|
+
|
65
|
+
return Error::DISCONNECTED_INTERIOR unless exterior_coords.subset?(visited)
|
66
|
+
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/rgeo/cartesian.rb
CHANGED
@@ -8,8 +8,11 @@
|
|
8
8
|
|
9
9
|
require_relative "cartesian/calculations"
|
10
10
|
require_relative "cartesian/feature_methods"
|
11
|
+
require_relative "cartesian/valid_op"
|
11
12
|
require_relative "cartesian/feature_classes"
|
12
13
|
require_relative "cartesian/factory"
|
13
14
|
require_relative "cartesian/interface"
|
14
15
|
require_relative "cartesian/bounding_box"
|
15
16
|
require_relative "cartesian/analysis"
|
17
|
+
require_relative "cartesian/sweepline_intersector"
|
18
|
+
require_relative "cartesian/planar_graph"
|
@@ -24,7 +24,7 @@ module RGeo
|
|
24
24
|
return value
|
25
25
|
end
|
26
26
|
unless @cur_token.is_a?(TypeString)
|
27
|
-
raise Error::ParseError
|
27
|
+
raise Error::ParseError, "Found token #{@cur_token} when we expected a value"
|
28
28
|
end
|
29
29
|
type = @cur_token
|
30
30
|
next_token
|
@@ -48,7 +48,7 @@ module RGeo
|
|
48
48
|
when "TOWGS84"
|
49
49
|
bursa_wolf_params = args.find_all(Numeric)
|
50
50
|
unless bursa_wolf_params.size == 7
|
51
|
-
raise Error::ParseError
|
51
|
+
raise Error::ParseError, "Expected 7 Bursa Wolf parameters but found #{bursa_wolf_params.size}"
|
52
52
|
end
|
53
53
|
obj = WGS84ConversionInfo.create(*bursa_wolf_params)
|
54
54
|
when "UNIT"
|
@@ -87,7 +87,7 @@ module RGeo
|
|
87
87
|
unit = args.find_first(Unit)
|
88
88
|
axes = args.find_all(AxisInfo)
|
89
89
|
unless axes.size > 0
|
90
|
-
raise Error::ParseError
|
90
|
+
raise Error::ParseError, "Expected at least one AXIS in a LOCAL_CS"
|
91
91
|
end
|
92
92
|
obj = LocalCoordinateSystem.create(name, local_datum, unit, axes, *args.create_optionals)
|
93
93
|
when "GEOCCS"
|
@@ -97,7 +97,7 @@ module RGeo
|
|
97
97
|
linear_unit = args.find_first(LinearUnit)
|
98
98
|
axes = args.find_all(AxisInfo)
|
99
99
|
unless axes.size == 0 || axes.size == 3
|
100
|
-
raise Error::ParseError
|
100
|
+
raise Error::ParseError, "GEOCCS must contain either 0 or 3 AXIS parameters"
|
101
101
|
end
|
102
102
|
obj = GeocentricCoordinateSystem.create(name, horizontal_datum, prime_meridian, linear_unit, axes[0], axes[1], axes[2], *args.create_optionals)
|
103
103
|
when "VERT_CS"
|
@@ -113,7 +113,7 @@ module RGeo
|
|
113
113
|
angular_unit = args.find_first(AngularUnit)
|
114
114
|
axes = args.find_all(AxisInfo)
|
115
115
|
unless axes.size == 0 || axes.size == 2
|
116
|
-
raise Error::ParseError
|
116
|
+
raise Error::ParseError, "GEOGCS must contain either 0 or 2 AXIS parameters"
|
117
117
|
end
|
118
118
|
obj = GeographicCoordinateSystem.create(name, angular_unit, horizontal_datum, prime_meridian, axes[0], axes[1], *args.create_optionals)
|
119
119
|
when "PROJCS"
|
@@ -125,7 +125,7 @@ module RGeo
|
|
125
125
|
linear_unit = args.find_first(LinearUnit)
|
126
126
|
axes = args.find_all(AxisInfo)
|
127
127
|
unless axes.size == 0 || axes.size == 2
|
128
|
-
raise Error::ParseError
|
128
|
+
raise Error::ParseError, "PROJCS must contain either 0 or 2 AXIS parameters"
|
129
129
|
end
|
130
130
|
obj = ProjectedCoordinateSystem.create(name, geographic_coordinate_system, projection, linear_unit, axes[0], axes[1], *args.create_optionals)
|
131
131
|
else
|
data/lib/rgeo/error.rb
CHANGED
@@ -29,5 +29,20 @@ module RGeo
|
|
29
29
|
# Parsing failed
|
30
30
|
class ParseError < RGeoError
|
31
31
|
end
|
32
|
+
|
33
|
+
# Standard error messages from
|
34
|
+
# https://github.com/locationtech/jts/blob/0afbfb1956ec24912a8b4dc4edff0f1200442857/modules/core/src/main/java/org/locationtech/jts/operation/valid/TopologyValidationError.java#L98-L110
|
35
|
+
TOPOLOGY_VALIDATION_ERR = "Topology Validation Error"
|
36
|
+
REPEATED_POINT = "Repeated Point"
|
37
|
+
HOLE_OUTSIDE_SHELL = "Hole lies outside shell"
|
38
|
+
NESTED_HOLES = "Holes are nested"
|
39
|
+
DISCONNECTED_INTERIOR = "Interior is disconnected"
|
40
|
+
SELF_INTERSECTION = "Self-intersection"
|
41
|
+
RING_SELF_INTERSECTION = "Ring Self-intersection"
|
42
|
+
NESTED_SHELLS = "Nested shells"
|
43
|
+
DUPLICATE_RINGS = "Duplicate Rings"
|
44
|
+
TOO_FEW_POINTS = "Too few distinct points in geometry component"
|
45
|
+
INVALID_COORDINATE = "Invalid Coordinate"
|
46
|
+
UNCLOSED_RING = "Ring is not closed"
|
32
47
|
end
|
33
48
|
end
|
data/lib/rgeo/feature/curve.rb
CHANGED
@@ -90,8 +90,13 @@ module RGeo
|
|
90
90
|
# Returns a boolean value. Note that this is different from the SFS
|
91
91
|
# specification, which stipulates an integer return value.
|
92
92
|
|
93
|
+
def closed?
|
94
|
+
raise Error::UnsupportedOperation, "Method Curve#closed? not defined."
|
95
|
+
end
|
96
|
+
|
93
97
|
def is_closed?
|
94
|
-
|
98
|
+
warn "The is_closed? method is deprecated, please use the closed? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
|
99
|
+
closed?
|
95
100
|
end
|
96
101
|
|
97
102
|
# === SFS 1.1 Description
|
@@ -105,8 +110,13 @@ module RGeo
|
|
105
110
|
# Returns a boolean value. Note that this is different from the SFS
|
106
111
|
# specification, which stipulates an integer return value.
|
107
112
|
|
113
|
+
def ring?
|
114
|
+
raise Error::UnsupportedOperation, "Method Curve#ring? not defined."
|
115
|
+
end
|
116
|
+
|
108
117
|
def is_ring?
|
109
|
-
|
118
|
+
warn "The is_ring? method is deprecated, please use the ring? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
|
119
|
+
ring?
|
110
120
|
end
|
111
121
|
end
|
112
122
|
end
|
@@ -90,7 +90,7 @@ module RGeo
|
|
90
90
|
# operations on them.)
|
91
91
|
|
92
92
|
def factory
|
93
|
-
raise Error::UnsupportedOperation, "Method
|
93
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#factory not defined."
|
94
94
|
end
|
95
95
|
|
96
96
|
# === SFS 1.1 Description
|
@@ -105,7 +105,7 @@ module RGeo
|
|
105
105
|
# point geometries, 1 for curves, and 2 for surfaces.
|
106
106
|
|
107
107
|
def dimension
|
108
|
-
raise Error::UnsupportedOperation, "Method
|
108
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#dimension not defined."
|
109
109
|
end
|
110
110
|
|
111
111
|
# === SFS 1.1 Description
|
@@ -122,7 +122,7 @@ module RGeo
|
|
122
122
|
# call the +type_name+ method of the returned module.
|
123
123
|
|
124
124
|
def geometry_type
|
125
|
-
raise Error::UnsupportedOperation, "Method
|
125
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#geometry_type not defined."
|
126
126
|
end
|
127
127
|
|
128
128
|
# === SFS 1.1 Description
|
@@ -137,7 +137,7 @@ module RGeo
|
|
137
137
|
# stored in either the same or some other datastore.
|
138
138
|
|
139
139
|
def srid
|
140
|
-
raise Error::UnsupportedOperation, "Method
|
140
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#srid not defined."
|
141
141
|
end
|
142
142
|
|
143
143
|
# === SFS 1.1 Description
|
@@ -151,7 +151,7 @@ module RGeo
|
|
151
151
|
# Returns an object that supports the Geometry interface.
|
152
152
|
|
153
153
|
def envelope
|
154
|
-
raise Error::UnsupportedOperation, "Method
|
154
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#envelope not defined."
|
155
155
|
end
|
156
156
|
|
157
157
|
# === SFS 1.1 Description
|
@@ -164,7 +164,7 @@ module RGeo
|
|
164
164
|
# Returns an ASCII string.
|
165
165
|
|
166
166
|
def as_text
|
167
|
-
raise Error::UnsupportedOperation, "Method
|
167
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#as_text not defined."
|
168
168
|
end
|
169
169
|
|
170
170
|
# === SFS 1.1 Description
|
@@ -177,7 +177,7 @@ module RGeo
|
|
177
177
|
# Returns a binary string.
|
178
178
|
|
179
179
|
def as_binary
|
180
|
-
raise Error::UnsupportedOperation, "Method
|
180
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#as_binary not defined."
|
181
181
|
end
|
182
182
|
|
183
183
|
# === SFS 1.1 Description
|
@@ -191,8 +191,13 @@ module RGeo
|
|
191
191
|
# Returns a boolean value. Note that this is different from the SFS
|
192
192
|
# specification, which stipulates an integer return value.
|
193
193
|
|
194
|
+
def empty?
|
195
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#empty? not defined."
|
196
|
+
end
|
197
|
+
|
194
198
|
def is_empty?
|
195
|
-
|
199
|
+
warn "The is_empty? method is deprecated, please use the empty? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
|
200
|
+
empty?
|
196
201
|
end
|
197
202
|
|
198
203
|
# === SFS 1.1 Description
|
@@ -208,8 +213,13 @@ module RGeo
|
|
208
213
|
# Returns a boolean value. Note that this is different from the SFS
|
209
214
|
# specification, which stipulates an integer return value.
|
210
215
|
|
216
|
+
def simple?
|
217
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#simple? not defined."
|
218
|
+
end
|
219
|
+
|
211
220
|
def is_simple?
|
212
|
-
|
221
|
+
warn "The is_simple? method is deprecated, please use the simple? counterpart, will be removed in v3" unless ENV["RGEO_SILENCE_DEPRECATION"]
|
222
|
+
simple?
|
213
223
|
end
|
214
224
|
|
215
225
|
# === SFS 1.1 Description
|
@@ -224,7 +234,7 @@ module RGeo
|
|
224
234
|
# Returns an object that supports the Geometry interface.
|
225
235
|
|
226
236
|
def boundary
|
227
|
-
raise Error::UnsupportedOperation, "Method
|
237
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#boundary not defined."
|
228
238
|
end
|
229
239
|
|
230
240
|
# === SFS 1.1 Description
|
@@ -243,7 +253,7 @@ module RGeo
|
|
243
253
|
# from different factories is undefined.
|
244
254
|
|
245
255
|
def equals?(another_geometry)
|
246
|
-
raise Error::UnsupportedOperation, "Method
|
256
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#equals? not defined."
|
247
257
|
end
|
248
258
|
|
249
259
|
# === SFS 1.1 Description
|
@@ -262,7 +272,7 @@ module RGeo
|
|
262
272
|
# from different factories is undefined.
|
263
273
|
|
264
274
|
def disjoint?(another_geometry)
|
265
|
-
raise Error::UnsupportedOperation, "Method
|
275
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#disjoint? not defined."
|
266
276
|
end
|
267
277
|
|
268
278
|
# === SFS 1.1 Description
|
@@ -281,7 +291,7 @@ module RGeo
|
|
281
291
|
# from different factories is undefined.
|
282
292
|
|
283
293
|
def intersects?(another_geometry)
|
284
|
-
raise Error::UnsupportedOperation, "Method
|
294
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#intersects? not defined."
|
285
295
|
end
|
286
296
|
|
287
297
|
# === SFS 1.1 Description
|
@@ -300,7 +310,7 @@ module RGeo
|
|
300
310
|
# from different factories is undefined.
|
301
311
|
|
302
312
|
def touches?(another_geometry)
|
303
|
-
raise Error::UnsupportedOperation, "Method
|
313
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#touches? not defined."
|
304
314
|
end
|
305
315
|
|
306
316
|
# === SFS 1.1 Description
|
@@ -319,7 +329,7 @@ module RGeo
|
|
319
329
|
# from different factories is undefined.
|
320
330
|
|
321
331
|
def crosses?(another_geometry)
|
322
|
-
raise Error::UnsupportedOperation, "Method
|
332
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#crosses? not defined."
|
323
333
|
end
|
324
334
|
|
325
335
|
# === SFS 1.1 Description
|
@@ -338,7 +348,7 @@ module RGeo
|
|
338
348
|
# from different factories is undefined.
|
339
349
|
|
340
350
|
def within?(another_geometry)
|
341
|
-
raise Error::UnsupportedOperation, "Method
|
351
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#within? not defined."
|
342
352
|
end
|
343
353
|
|
344
354
|
# === SFS 1.1 Description
|
@@ -357,7 +367,7 @@ module RGeo
|
|
357
367
|
# from different factories is undefined.
|
358
368
|
|
359
369
|
def contains?(another_geometry)
|
360
|
-
raise Error::UnsupportedOperation, "Method
|
370
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#contains? not defined."
|
361
371
|
end
|
362
372
|
|
363
373
|
# === SFS 1.1 Description
|
@@ -376,7 +386,7 @@ module RGeo
|
|
376
386
|
# from different factories is undefined.
|
377
387
|
|
378
388
|
def overlaps?(another_geometry)
|
379
|
-
raise Error::UnsupportedOperation, "Method
|
389
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#overlaps? not defined."
|
380
390
|
end
|
381
391
|
|
382
392
|
# === SFS 1.1 Description
|
@@ -402,7 +412,7 @@ module RGeo
|
|
402
412
|
# from different factories is undefined.
|
403
413
|
|
404
414
|
def relate?(another_geometry, _intersection_pattern_matrix_)
|
405
|
-
raise Error::UnsupportedOperation, "Method
|
415
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#relate not defined."
|
406
416
|
end
|
407
417
|
|
408
418
|
# === SFS 1.1 Description
|
@@ -421,7 +431,7 @@ module RGeo
|
|
421
431
|
# distance between objects from different factories is undefined.
|
422
432
|
|
423
433
|
def distance(another_geometry)
|
424
|
-
raise Error::UnsupportedOperation, "Method
|
434
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#distance not defined."
|
425
435
|
end
|
426
436
|
|
427
437
|
# === SFS 1.1 Description
|
@@ -436,7 +446,7 @@ module RGeo
|
|
436
446
|
# Returns an object that supports the Geometry interface.
|
437
447
|
|
438
448
|
def buffer(_distance_)
|
439
|
-
raise Error::UnsupportedOperation, "Method
|
449
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#buffer not defined."
|
440
450
|
end
|
441
451
|
|
442
452
|
# === SFS 1.1 Description
|
@@ -449,7 +459,7 @@ module RGeo
|
|
449
459
|
# Returns an object that supports the Geometry interface.
|
450
460
|
|
451
461
|
def convex_hull
|
452
|
-
raise Error::UnsupportedOperation, "Method
|
462
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#convex_hull not defined."
|
453
463
|
end
|
454
464
|
|
455
465
|
# === SFS 1.1 Description
|
@@ -467,7 +477,7 @@ module RGeo
|
|
467
477
|
# operations on objects from different factories is undefined.
|
468
478
|
|
469
479
|
def intersection(another_geometry)
|
470
|
-
raise Error::UnsupportedOperation, "Method
|
480
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#intersection not defined."
|
471
481
|
end
|
472
482
|
|
473
483
|
# === SFS 1.1 Description
|
@@ -485,7 +495,7 @@ module RGeo
|
|
485
495
|
# operations on objects from different factories is undefined.
|
486
496
|
|
487
497
|
def union(another_geometry)
|
488
|
-
raise Error::UnsupportedOperation, "Method
|
498
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#union not defined."
|
489
499
|
end
|
490
500
|
|
491
501
|
# === SFS 1.1 Description
|
@@ -503,7 +513,7 @@ module RGeo
|
|
503
513
|
# operations on objects from different factories is undefined.
|
504
514
|
|
505
515
|
def difference(another_geometry)
|
506
|
-
raise Error::UnsupportedOperation, "Method
|
516
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#difference not defined."
|
507
517
|
end
|
508
518
|
|
509
519
|
# === SFS 1.1 Description
|
@@ -521,7 +531,7 @@ module RGeo
|
|
521
531
|
# operations on objects from different factories is undefined.
|
522
532
|
|
523
533
|
def sym_difference(another_geometry)
|
524
|
-
raise Error::UnsupportedOperation, "Method
|
534
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#sym_difference not defined."
|
525
535
|
end
|
526
536
|
|
527
537
|
# Returns true if this geometric object is representationally
|
@@ -533,7 +543,7 @@ module RGeo
|
|
533
543
|
# from different factories is undefined.
|
534
544
|
|
535
545
|
def rep_equals?(another_geometry)
|
536
|
-
raise Error::UnsupportedOperation, "Method
|
546
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#rep_equals? not defined."
|
537
547
|
end
|
538
548
|
|
539
549
|
# Unions a collection of Geometry or a single Geometry
|
@@ -550,7 +560,7 @@ module RGeo
|
|
550
560
|
# returns nil.
|
551
561
|
#
|
552
562
|
def unary_union
|
553
|
-
raise Error::UnsupportedOperation, "Method
|
563
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#unary_union not defined."
|
554
564
|
end
|
555
565
|
|
556
566
|
# This method should behave almost the same as the rep_equals?
|
@@ -44,7 +44,7 @@ module RGeo
|
|
44
44
|
# Returns an integer.
|
45
45
|
|
46
46
|
def num_geometries
|
47
|
-
raise Error::UnsupportedOperation, "Method
|
47
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#num_geometries not defined."
|
48
48
|
end
|
49
49
|
|
50
50
|
# === SFS 1.1 Description
|
@@ -59,7 +59,7 @@ module RGeo
|
|
59
59
|
# in that it does not support negative indexes.
|
60
60
|
|
61
61
|
def geometry_n(n)
|
62
|
-
raise Error::UnsupportedOperation, "Method
|
62
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#geometry_n not defined."
|
63
63
|
end
|
64
64
|
|
65
65
|
# Alias of the num_geometries method.
|
@@ -79,13 +79,13 @@ module RGeo
|
|
79
79
|
# returns nil, where [-1] returns the last element of the collection.
|
80
80
|
|
81
81
|
def [](n)
|
82
|
-
raise Error::UnsupportedOperation, "Method
|
82
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#[] not defined."
|
83
83
|
end
|
84
84
|
|
85
85
|
# Nodes the linework in a list of Geometries
|
86
86
|
#
|
87
87
|
def node
|
88
|
-
raise Error::UnsupportedOperation, "Method
|
88
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#node not defined."
|
89
89
|
end
|
90
90
|
|
91
91
|
# Iterates over the geometries of this GeometryCollection.
|
@@ -96,7 +96,15 @@ module RGeo
|
|
96
96
|
# include the Enumerable mixin.
|
97
97
|
|
98
98
|
def each(&block)
|
99
|
-
raise Error::UnsupportedOperation, "Method
|
99
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#each not defined."
|
100
|
+
end
|
101
|
+
|
102
|
+
# Gives a point that is guaranteed to be within the geometry.
|
103
|
+
#
|
104
|
+
# Extends OGC SFS 1.1 and follows PostGIS standards.
|
105
|
+
# @see https://postgis.net/docs/ST_PointOnSurface.html
|
106
|
+
def point_on_surface
|
107
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#each not defined."
|
100
108
|
end
|
101
109
|
end
|
102
110
|
end
|
@@ -34,7 +34,7 @@ module RGeo
|
|
34
34
|
# Returns an integer.
|
35
35
|
|
36
36
|
def num_points
|
37
|
-
raise Error::UnsupportedOperation, "Method
|
37
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#num_points not defined."
|
38
38
|
end
|
39
39
|
|
40
40
|
# === SFS 1.1 Description
|
@@ -48,14 +48,14 @@ module RGeo
|
|
48
48
|
# Does not support negative indexes.
|
49
49
|
|
50
50
|
def point_n(n)
|
51
|
-
raise Error::UnsupportedOperation, "Method
|
51
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#point_n not defined."
|
52
52
|
end
|
53
53
|
|
54
54
|
# Returns the constituent points as an array of objects that
|
55
55
|
# support the Point interface.
|
56
56
|
|
57
57
|
def points
|
58
|
-
raise Error::UnsupportedOperation, "Method
|
58
|
+
raise Error::UnsupportedOperation, "Method #{self.class}#points not defined."
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|