rgeo 0.1.11 → 0.1.12
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.
- data/History.rdoc +12 -0
- data/Version +1 -1
- data/ext/geos_c_impl/factory.c +2 -2
- data/lib/rgeo/features/factory.rb +3 -2
- data/lib/rgeo/features/geometry.rb +1 -1
- data/lib/rgeo/geo_json/entities.rb +2 -2
- data/lib/rgeo/geography/common/geometry_collection_methods.rb +1 -1
- data/lib/rgeo/geography/common/helper.rb +4 -4
- data/lib/rgeo/geography/common/line_string_methods.rb +15 -1
- data/lib/rgeo/geography/common/point_methods.rb +7 -3
- data/lib/rgeo/geography/common/polygon_methods.rb +2 -2
- data/lib/rgeo/geography/factories.rb +3 -2
- data/lib/rgeo/geography/factory.rb +10 -10
- data/lib/rgeo/geography/simple_mercator/feature_methods.rb +14 -14
- data/lib/rgeo/geography/simple_spherical/calculations.rb +86 -13
- data/lib/rgeo/geography/simple_spherical/line_string_impl.rb +48 -3
- data/lib/rgeo/geography/simple_spherical/point_impl.rb +5 -4
- data/lib/rgeo/geos/factory.rb +13 -13
- data/lib/rgeo/geos/interface.rb +20 -0
- data/tests/common/line_string_tests.rb +5 -5
- data/tests/common/point_tests.rb +0 -1
- data/tests/simple_spherical/tc_calculations.rb +203 -0
- data/tests/simple_spherical/tc_line_string.rb +231 -0
- data/tests/simple_spherical/tc_point.rb +34 -3
- data/tests/tc_oneoff.rb +1 -0
- metadata +7 -3
data/History.rdoc
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
=== 0.1.12 / 2010-10-23
|
2
|
+
|
3
|
+
Further development and fixes in the geographic coordinate systems.
|
4
|
+
|
5
|
+
Changes since 0.1.11:
|
6
|
+
|
7
|
+
* API CHANGE: Factory#coerce renamed to Factory#cast. I think this should be the final name for this function.
|
8
|
+
* Some new tests and a lot of fixes in SimpleMercator and SimpleSpherical.
|
9
|
+
* Implemented a few more pieces of SimpleSpherical. Notably, LineString#is_simple? (which should now allow LinearRing to work).
|
10
|
+
* Classes that included Features::Geometry had their === operator erroneously overridden. Fixed.
|
11
|
+
* A few more documentation updates.
|
12
|
+
|
1
13
|
=== 0.1.11 / 2010-10-21
|
2
14
|
|
3
15
|
Further development and fixing in the geographic coordinate systems.
|
data/Version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.12
|
data/ext/geos_c_impl/factory.c
CHANGED
@@ -332,7 +332,7 @@ VALUE rgeo_wrap_geos_geometry_clone(VALUE factory, const GEOSGeometry* geom, VAL
|
|
332
332
|
|
333
333
|
const GEOSGeometry* rgeo_convert_to_geos_geometry(VALUE factory, VALUE obj)
|
334
334
|
{
|
335
|
-
VALUE object = rb_funcall(factory, rb_intern("
|
335
|
+
VALUE object = rb_funcall(factory, rb_intern("cast"), 1, obj);
|
336
336
|
const GEOSGeometry* geom = NULL;
|
337
337
|
if (!NIL_P(object)) {
|
338
338
|
geom = RGEO_GET_GEOS_GEOMETRY(object);
|
@@ -346,7 +346,7 @@ GEOSGeometry* rgeo_convert_to_detached_geos_geometry(RGeo_Globals* globals, VALU
|
|
346
346
|
if (klasses) {
|
347
347
|
*klasses = Qnil;
|
348
348
|
}
|
349
|
-
VALUE object = rb_funcall(globals->default_factory, rb_intern("
|
349
|
+
VALUE object = rb_funcall(globals->default_factory, rb_intern("cast"), 2, obj, Qtrue);
|
350
350
|
GEOSGeometry* geom = NULL;
|
351
351
|
if (!NIL_P(object)) {
|
352
352
|
geom = RGEO_GEOMETRY_DATA_PTR(object)->geom;
|
@@ -144,6 +144,7 @@ module RGeo
|
|
144
144
|
|
145
145
|
|
146
146
|
# Create a feature of type MultiLineString.
|
147
|
+
#
|
147
148
|
# The elems should be an Enumerable of LineString objects, or
|
148
149
|
# collections whose contents, recursively expanded, eventually
|
149
150
|
# include only LineString objects (or subclasses thereof).
|
@@ -173,12 +174,12 @@ module RGeo
|
|
173
174
|
end
|
174
175
|
|
175
176
|
|
176
|
-
#
|
177
|
+
# Cast an existing feature to a feature of the type created by
|
177
178
|
# this implementation.
|
178
179
|
# If force_new is true, a new object is returned even if the original
|
179
180
|
# is already of this implementation.
|
180
181
|
|
181
|
-
def
|
182
|
+
def cast(original_, force_new_=false)
|
182
183
|
nil
|
183
184
|
end
|
184
185
|
|
@@ -77,7 +77,7 @@ module RGeo
|
|
77
77
|
|
78
78
|
# Two features are equal if their geometries, IDs, and properties
|
79
79
|
# are all equal.
|
80
|
-
# This
|
80
|
+
# This method uses the eql? method to test geometry equality, which
|
81
81
|
# may behave differently than the == operator.
|
82
82
|
|
83
83
|
def eql?(rhs_)
|
@@ -87,7 +87,7 @@ module RGeo
|
|
87
87
|
|
88
88
|
# Two features are equal if their geometries, IDs, and properties
|
89
89
|
# are all equal.
|
90
|
-
# This
|
90
|
+
# This method uses the == operator to test geometry equality, which
|
91
91
|
# may behave differently than the eql? method.
|
92
92
|
|
93
93
|
def ==(rhs_)
|
@@ -69,26 +69,26 @@ module RGeo
|
|
69
69
|
def self.parse_wkt(str_, factory_)
|
70
70
|
helper_factory_ = self.factory
|
71
71
|
obj_ = helper_factory_ ? helper_factory_.parse_wkt(str_) : nil
|
72
|
-
obj_ ? factory_.
|
72
|
+
obj_ ? factory_.cast(obj_) : nil
|
73
73
|
end
|
74
74
|
|
75
75
|
|
76
76
|
def self.parse_wkb(str_, factory_)
|
77
77
|
helper_factory_ = self.factory
|
78
78
|
obj_ = helper_factory_ ? helper_factory_.parse_wkb(str_) : nil
|
79
|
-
obj_ ? factory_.
|
79
|
+
obj_ ? factory_.cast(obj_) : nil
|
80
80
|
end
|
81
81
|
|
82
82
|
|
83
83
|
def self.unparse_wkt(obj_)
|
84
84
|
helper_factory_ = self.factory
|
85
|
-
helper_factory_ ? helper_factory_.
|
85
|
+
helper_factory_ ? helper_factory_.cast(obj_).as_text : nil
|
86
86
|
end
|
87
87
|
|
88
88
|
|
89
89
|
def self.unparse_wkb(obj_)
|
90
90
|
helper_factory_ = self.factory
|
91
|
-
helper_factory_ ? helper_factory_.
|
91
|
+
helper_factory_ ? helper_factory_.cast(obj_).as_binary : nil
|
92
92
|
end
|
93
93
|
|
94
94
|
|
@@ -45,7 +45,12 @@ module RGeo
|
|
45
45
|
|
46
46
|
|
47
47
|
def _setup(points_)
|
48
|
-
@points = points_.map
|
48
|
+
@points = points_.map do |elem_|
|
49
|
+
unless Features::Point.check_type(elem_)
|
50
|
+
raise Errors::InvalidGeometry, 'Element #{elem_} is not a point'
|
51
|
+
end
|
52
|
+
factory.cast(elem_)
|
53
|
+
end
|
49
54
|
_validate_geometry
|
50
55
|
end
|
51
56
|
|
@@ -57,6 +62,15 @@ module RGeo
|
|
57
62
|
end
|
58
63
|
|
59
64
|
|
65
|
+
def eql?(rhs_)
|
66
|
+
if rhs_.is_a?(self.class) && rhs_.factory.eql?(@factory) && @points.size == rhs_.num_points
|
67
|
+
rhs_.points.each_with_index{ |p_, i_| return false unless @points[i_].eql?(p_) }
|
68
|
+
else
|
69
|
+
false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
60
74
|
def cast(type_)
|
61
75
|
if type_ == self.geometry_type
|
62
76
|
self
|
@@ -62,9 +62,8 @@ module RGeo
|
|
62
62
|
|
63
63
|
|
64
64
|
def eql?(rhs_)
|
65
|
-
rhs_.is_a?(self.class) && @x == rhs_.x && @y == rhs_.y
|
65
|
+
rhs_.is_a?(self.class) && rhs_.factory.eql?(@factory) && @x == rhs_.x && @y == rhs_.y
|
66
66
|
end
|
67
|
-
alias_method :==, :eql?
|
68
67
|
|
69
68
|
|
70
69
|
def cast(type_)
|
@@ -111,9 +110,14 @@ module RGeo
|
|
111
110
|
end
|
112
111
|
|
113
112
|
|
113
|
+
def convex_hull
|
114
|
+
self
|
115
|
+
end
|
116
|
+
|
117
|
+
|
114
118
|
def equals?(rhs_)
|
115
119
|
return false unless rhs_.factory.is_a?(Factory)
|
116
|
-
rhs_ = factory.
|
120
|
+
rhs_ = factory.cast(rhs_)
|
117
121
|
case rhs_
|
118
122
|
when Features::Point
|
119
123
|
if @y == 90
|
@@ -45,8 +45,8 @@ module RGeo
|
|
45
45
|
|
46
46
|
|
47
47
|
def _setup(exterior_ring_, interior_rings_)
|
48
|
-
@exterior_ring = exterior_ring_
|
49
|
-
@interior_rings = (interior_rings_ || []).map{ |elem_| factory.
|
48
|
+
@exterior_ring = factory.cast(exterior_ring_)
|
49
|
+
@interior_rings = (interior_rings_ || []).map{ |elem_| factory.cast(elem_) }
|
50
50
|
unless Features::LinearRing.check_type(@exterior_ring)
|
51
51
|
raise Errors::InvalidGeometry, 'Exterior ring must be a LinearRing'
|
52
52
|
end
|
@@ -127,7 +127,8 @@ module RGeo
|
|
127
127
|
# If set to true, assertion checking on MultiPolygon is disabled.
|
128
128
|
# This may speed up creation of MultiPolygon objects, at the
|
129
129
|
# expense of not doing the proper checking for OGC MultiPolygon
|
130
|
-
# compliance.
|
130
|
+
# compliance. See RGeo::Features::MultiPolygon for details on
|
131
|
+
# the MultiPolygon assertions. Default is false.
|
131
132
|
# <tt>:buffer_resolution</tt>::
|
132
133
|
# The resolution of buffers around geometries created by this
|
133
134
|
# factory. This controls the number of line segments used to
|
@@ -135,7 +136,7 @@ module RGeo
|
|
135
136
|
# example, the buffer around a point to be approximated by a
|
136
137
|
# 4-sided polygon. A resolution of 2 would cause that buffer
|
137
138
|
# to be approximated by an 8-sided polygon. The exact behavior
|
138
|
-
# for different kinds of buffers is
|
139
|
+
# for different kinds of buffers is defined by GEOS.
|
139
140
|
|
140
141
|
def simple_mercator(opts_={})
|
141
142
|
Geography::Factory.new(Geography::SimpleMercator, :buffer_resolution => opts_[:buffer_resolution], :lenient_multi_polygon_assertions => opts_[:lenient_multi_polygon_assertions])
|
@@ -213,9 +213,9 @@ module RGeo
|
|
213
213
|
end
|
214
214
|
|
215
215
|
|
216
|
-
# See ::RGeo::Features::Factory#
|
216
|
+
# See ::RGeo::Features::Factory#cast
|
217
217
|
|
218
|
-
def
|
218
|
+
def cast(original_, force_new_=false)
|
219
219
|
if self == original_.factory
|
220
220
|
force_new_ ? original_.dup : original_
|
221
221
|
else
|
@@ -223,21 +223,21 @@ module RGeo
|
|
223
223
|
when Features::Point
|
224
224
|
@namespace.const_get(:PointImpl).new(self, original_.x, original_.y) rescue nil
|
225
225
|
when Features::Line
|
226
|
-
@namespace.const_get(:LineImpl).new(self,
|
226
|
+
@namespace.const_get(:LineImpl).new(self, cast(original_.start_point), cast(original_.end_point)) rescue nil
|
227
227
|
when Features::LinearRing
|
228
|
-
@namespace.const_get(:LinearRingImpl).new(self, original_.points.map{ |g_|
|
228
|
+
@namespace.const_get(:LinearRingImpl).new(self, original_.points.map{ |g_| cast(g_) }) rescue nil
|
229
229
|
when Features::LineString
|
230
|
-
@namespace.const_get(:LineStringImpl).new(self, original_.points.map{ |g_|
|
230
|
+
@namespace.const_get(:LineStringImpl).new(self, original_.points.map{ |g_| cast(g_) }) rescue nil
|
231
231
|
when Features::Polygon
|
232
|
-
@namespace.const_get(:PolygonImpl).new(self,
|
232
|
+
@namespace.const_get(:PolygonImpl).new(self, cast(original_.exterior_ring), original_.interior_rings.map{ |g_| cast(g_) }) rescue nil
|
233
233
|
when Features::MultiPoint
|
234
|
-
@namespace.const_get(:MultiPointImpl).new(self, original_.to_a.map{ |g_|
|
234
|
+
@namespace.const_get(:MultiPointImpl).new(self, original_.to_a.map{ |g_| cast(g_) }) rescue nil
|
235
235
|
when Features::MultiLineString
|
236
|
-
@namespace.const_get(:MultiLineStringImpl).new(self, original_.to_a.map{ |g_|
|
236
|
+
@namespace.const_get(:MultiLineStringImpl).new(self, original_.to_a.map{ |g_| cast(g_) }) rescue nil
|
237
237
|
when Features::MultiPolygon
|
238
|
-
@namespace.const_get(:MultiPolygonImpl).new(self, original_.to_a.map{ |g_|
|
238
|
+
@namespace.const_get(:MultiPolygonImpl).new(self, original_.to_a.map{ |g_| cast(g_) }) rescue nil
|
239
239
|
when Features::GeometryCollection
|
240
|
-
@namespace.const_get(:GeometryCollectionImpl).new(self, original_.to_a.map{ |g_|
|
240
|
+
@namespace.const_get(:GeometryCollectionImpl).new(self, original_.to_a.map{ |g_| cast(g_) }) rescue nil
|
241
241
|
else
|
242
242
|
nil
|
243
243
|
end
|
@@ -103,52 +103,52 @@ module RGeo
|
|
103
103
|
|
104
104
|
|
105
105
|
def equals?(rhs_)
|
106
|
-
projection.equals?(factory.
|
106
|
+
projection.equals?(factory.cast(rhs_).projection)
|
107
107
|
end
|
108
108
|
|
109
109
|
|
110
110
|
def disjoint?(rhs_)
|
111
|
-
projection.disjoint?(factory.
|
111
|
+
projection.disjoint?(factory.cast(rhs_).projection)
|
112
112
|
end
|
113
113
|
|
114
114
|
|
115
115
|
def intersects?(rhs_)
|
116
|
-
projection.intersects?(factory.
|
116
|
+
projection.intersects?(factory.cast(rhs_).projection)
|
117
117
|
end
|
118
118
|
|
119
119
|
|
120
120
|
def touches?(rhs_)
|
121
|
-
projection.touches?(factory.
|
121
|
+
projection.touches?(factory.cast(rhs_).projection)
|
122
122
|
end
|
123
123
|
|
124
124
|
|
125
125
|
def crosses?(rhs_)
|
126
|
-
projection.crosses?(factory.
|
126
|
+
projection.crosses?(factory.cast(rhs_).projection)
|
127
127
|
end
|
128
128
|
|
129
129
|
|
130
130
|
def within?(rhs_)
|
131
|
-
projection.within?(factory.
|
131
|
+
projection.within?(factory.cast(rhs_).projection)
|
132
132
|
end
|
133
133
|
|
134
134
|
|
135
135
|
def contains?(rhs_)
|
136
|
-
projection.contains?(factory.
|
136
|
+
projection.contains?(factory.cast(rhs_).projection)
|
137
137
|
end
|
138
138
|
|
139
139
|
|
140
140
|
def overlaps?(rhs_)
|
141
|
-
projection.overlaps?(factory.
|
141
|
+
projection.overlaps?(factory.cast(rhs_).projection)
|
142
142
|
end
|
143
143
|
|
144
144
|
|
145
145
|
def relate(rhs_, pattern_)
|
146
|
-
projection.relate(factory.
|
146
|
+
projection.relate(factory.cast(rhs_).projection, pattern_)
|
147
147
|
end
|
148
148
|
|
149
149
|
|
150
150
|
def distance(rhs_)
|
151
|
-
projection.distance(factory.
|
151
|
+
projection.distance(factory.cast(rhs_).projection) / scaling_factor
|
152
152
|
end
|
153
153
|
|
154
154
|
|
@@ -163,22 +163,22 @@ module RGeo
|
|
163
163
|
|
164
164
|
|
165
165
|
def intersection(rhs_)
|
166
|
-
factory.unproject(projection.intersection(factory.
|
166
|
+
factory.unproject(projection.intersection(factory.cast(rhs_).projection))
|
167
167
|
end
|
168
168
|
|
169
169
|
|
170
170
|
def union(rhs_)
|
171
|
-
factory.unproject(projection.union(factory.
|
171
|
+
factory.unproject(projection.union(factory.cast(rhs_).projection))
|
172
172
|
end
|
173
173
|
|
174
174
|
|
175
175
|
def difference(rhs_)
|
176
|
-
factory.unproject(projection.difference(factory.
|
176
|
+
factory.unproject(projection.difference(factory.cast(rhs_).projection))
|
177
177
|
end
|
178
178
|
|
179
179
|
|
180
180
|
def sym_difference(rhs_)
|
181
|
-
factory.unproject(projection.sym_difference(factory.
|
181
|
+
factory.unproject(projection.sym_difference(factory.cast(rhs_).projection))
|
182
182
|
end
|
183
183
|
|
184
184
|
|
@@ -62,6 +62,12 @@ module RGeo
|
|
62
62
|
@x = x_ / r_
|
63
63
|
@y = y_ / r_
|
64
64
|
@z = z_ / r_
|
65
|
+
raise "Not a number" if @x.nan? || @y.nan? || @z.nan?
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
def to_s
|
70
|
+
"(#{@x}, #{@y}, #{@z})"
|
65
71
|
end
|
66
72
|
|
67
73
|
|
@@ -70,6 +76,12 @@ module RGeo
|
|
70
76
|
attr_reader :z
|
71
77
|
|
72
78
|
|
79
|
+
def eql?(rhs_)
|
80
|
+
rhs_.kind_of?(PointXYZ) && @x == rhs_.x && @y == rhs_.y && @z == rhs_.z
|
81
|
+
end
|
82
|
+
alias_method :==, :eql?
|
83
|
+
|
84
|
+
|
73
85
|
def latlon
|
74
86
|
lat_rad_ = ::Math.asin(@z)
|
75
87
|
lon_rad_ = ::Math.atan2(@y, @x) rescue 0.0
|
@@ -79,7 +91,10 @@ module RGeo
|
|
79
91
|
|
80
92
|
|
81
93
|
def *(rhs_)
|
82
|
-
@x * rhs_.x + @y * rhs_.y + @z * rhs_.z
|
94
|
+
val_ = @x * rhs_.x + @y * rhs_.y + @z * rhs_.z
|
95
|
+
val_ = 1.0 if val_ > 1.0
|
96
|
+
val_ = -1.0 if val_ < -1.0
|
97
|
+
val_
|
83
98
|
end
|
84
99
|
|
85
100
|
|
@@ -87,7 +102,20 @@ module RGeo
|
|
87
102
|
rx_ = rhs_.x
|
88
103
|
ry_ = rhs_.y
|
89
104
|
rz_ = rhs_.z
|
90
|
-
PointXYZ.new(@y*rz_-@z*ry_, @z*rx_-@x*rz_, @x*ry_-@y
|
105
|
+
PointXYZ.new(@y*rz_-@z*ry_, @z*rx_-@x*rz_, @x*ry_-@y*rx_) rescue nil
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
def dist_to_point(rhs_)
|
110
|
+
rx_ = rhs_.x
|
111
|
+
ry_ = rhs_.y
|
112
|
+
rz_ = rhs_.z
|
113
|
+
x_ = @y*rz_-@z*ry_
|
114
|
+
y_ = @z*rx_-@x*rz_
|
115
|
+
z_ = @x*ry_-@y*rx_
|
116
|
+
r_ = ::Math.sqrt(x_*x_ + y_*y_ + z_*z_)
|
117
|
+
r_ = 1.0 if r_ > 1.0
|
118
|
+
::Math.asin(r_)
|
91
119
|
end
|
92
120
|
|
93
121
|
|
@@ -105,22 +133,67 @@ module RGeo
|
|
105
133
|
end
|
106
134
|
|
107
135
|
|
108
|
-
|
136
|
+
# Represents a finite arc on the sphere.
|
137
|
+
|
138
|
+
class ArcXYZ
|
109
139
|
|
140
|
+
def initialize(start_, end_)
|
141
|
+
@s = start_
|
142
|
+
@e = end_
|
143
|
+
@axis = false
|
144
|
+
end
|
110
145
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
146
|
+
|
147
|
+
attr_reader :s
|
148
|
+
attr_reader :e
|
149
|
+
|
150
|
+
|
151
|
+
def to_s
|
152
|
+
"#{@s} - #{@e}"
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
def eql?(rhs_)
|
157
|
+
rhs_.kind_of?(ArcXYZ) && @s == rhs_.s && @e == rhs_.e
|
121
158
|
end
|
159
|
+
alias_method :==, :eql?
|
160
|
+
|
122
161
|
|
162
|
+
def axis
|
163
|
+
if @axis == false
|
164
|
+
@axis = @s % @e
|
165
|
+
end
|
166
|
+
@axis
|
167
|
+
end
|
123
168
|
|
169
|
+
|
170
|
+
def contains_point?(obj_)
|
171
|
+
axis_ = axis
|
172
|
+
saxis_ = ArcXYZ.new(@s, obj_).axis
|
173
|
+
eaxis_ = ArcXYZ.new(obj_, @e).axis
|
174
|
+
!saxis_ || !eaxis_ || obj_ * axis_ == 0.0 && saxis_ * axis_ > 0 && eaxis_ * axis_ > 0
|
175
|
+
end
|
176
|
+
|
177
|
+
|
178
|
+
def intersects_arc?(obj_)
|
179
|
+
my_axis_ = axis
|
180
|
+
dot1_ = my_axis_ * obj_.s
|
181
|
+
dot2_ = my_axis_ * obj_.e
|
182
|
+
if dot1_ >= 0.0 && dot2_ <= 0.0 || dot1_ <= 0.0 && dot2_ >= 0.0
|
183
|
+
ob_axis_ = obj_.axis
|
184
|
+
dot1_ = ob_axis_ * @s
|
185
|
+
dot2_ = ob_axis_ * @e
|
186
|
+
dot1_ >= 0.0 && dot2_ <= 0.0 || dot1_ <= 0.0 && dot2_ >= 0.0
|
187
|
+
else
|
188
|
+
false
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
module Calculations
|
124
197
|
end
|
125
198
|
|
126
199
|
|
@@ -41,13 +41,56 @@ module RGeo
|
|
41
41
|
module SimpleSpherical
|
42
42
|
|
43
43
|
|
44
|
+
module LineStringMethods
|
45
|
+
|
46
|
+
|
47
|
+
def _arcs
|
48
|
+
unless @arcs
|
49
|
+
@arcs = (0..num_points-2).map do |i_|
|
50
|
+
ArcXYZ.new(point_n(i_)._xyz, point_n(i_+1)._xyz)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
@arcs
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def is_simple?
|
58
|
+
arcs_ = _arcs
|
59
|
+
len_ = arcs_.length
|
60
|
+
return false if arcs_.any?{ |a_| a_.nil? }
|
61
|
+
return true if len_ == 1
|
62
|
+
return arcs_[0].start != arcs_[1].end if len_ == 2
|
63
|
+
arcs_.each_with_index do |arc_, index_|
|
64
|
+
nindex_ = index_ + 1
|
65
|
+
nindex_ = nil if nindex_ == len_
|
66
|
+
return false if nindex_ && arc_.contains_point?(arcs_[nindex_].e)
|
67
|
+
pindex_ = index_ - 1
|
68
|
+
pindex_ = nil if pindex_ < 0
|
69
|
+
return false if pindex_ && arc_.contains_point?(arcs_[pindex_].s)
|
70
|
+
if nindex_
|
71
|
+
oindex_ = nindex_ + 1
|
72
|
+
while oindex_ < len_
|
73
|
+
oarc_ = arcs_[oindex_]
|
74
|
+
return false if !(index_ == 0 && oindex_ == len_-1 && arc_.s == oarc_.e) && arc_.intersects_arc?(oarc_)
|
75
|
+
oindex_ += 1
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
true
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
|
44
86
|
class LineStringImpl
|
45
87
|
|
46
88
|
|
47
89
|
include Features::LineString
|
48
90
|
include Common::GeometryMethods
|
49
|
-
include GeometryMethods
|
91
|
+
include SimpleSpherical::GeometryMethods
|
50
92
|
include Common::LineStringMethods
|
93
|
+
include SimpleSpherical::LineStringMethods
|
51
94
|
|
52
95
|
|
53
96
|
def initialize(factory_, points_)
|
@@ -64,8 +107,9 @@ module RGeo
|
|
64
107
|
|
65
108
|
include Features::Line
|
66
109
|
include Common::GeometryMethods
|
67
|
-
include GeometryMethods
|
110
|
+
include SimpleSpherical::GeometryMethods
|
68
111
|
include Common::LineStringMethods
|
112
|
+
include SimpleSpherical::LineStringMethods
|
69
113
|
include Common::LineMethods
|
70
114
|
|
71
115
|
|
@@ -83,8 +127,9 @@ module RGeo
|
|
83
127
|
|
84
128
|
include Features::Line
|
85
129
|
include Common::GeometryMethods
|
86
|
-
include GeometryMethods
|
130
|
+
include SimpleSpherical::GeometryMethods
|
87
131
|
include Common::LineStringMethods
|
132
|
+
include SimpleSpherical::LineStringMethods
|
88
133
|
include Common::LinearRingMethods
|
89
134
|
|
90
135
|
|
@@ -46,7 +46,7 @@ module RGeo
|
|
46
46
|
|
47
47
|
include Features::Point
|
48
48
|
include Common::GeometryMethods
|
49
|
-
include GeometryMethods
|
49
|
+
include SimpleSpherical::GeometryMethods
|
50
50
|
include Common::PointMethods
|
51
51
|
|
52
52
|
|
@@ -65,15 +65,16 @@ module RGeo
|
|
65
65
|
end
|
66
66
|
|
67
67
|
|
68
|
-
def
|
68
|
+
def _xyz
|
69
69
|
@xyz ||= PointXYZ.from_latlon(@y, @x)
|
70
70
|
end
|
71
71
|
|
72
72
|
|
73
73
|
def distance(rhs_)
|
74
|
+
rhs_ = @factory.cast(rhs_)
|
74
75
|
case rhs_
|
75
|
-
when
|
76
|
-
|
76
|
+
when PointImpl
|
77
|
+
_xyz.dist_to_point(rhs_._xyz) * SimpleSpherical::RADIUS
|
77
78
|
else
|
78
79
|
super
|
79
80
|
end
|
data/lib/rgeo/geos/factory.rb
CHANGED
@@ -58,7 +58,8 @@ module RGeo
|
|
58
58
|
# If set to true, assertion checking on MultiPolygon is disabled.
|
59
59
|
# This may speed up creation of MultiPolygon objects, at the
|
60
60
|
# expense of not doing the proper checking for OGC MultiPolygon
|
61
|
-
# compliance.
|
61
|
+
# compliance. See RGeo::Features::MultiPolygon for details on
|
62
|
+
# the MultiPolygon assertions. Default is false.
|
62
63
|
# <tt>:buffer_resolution</tt>::
|
63
64
|
# The resolution of buffers around geometries created by this
|
64
65
|
# factory. This controls the number of line segments used to
|
@@ -66,8 +67,7 @@ module RGeo
|
|
66
67
|
# example, the buffer around a point to be approximated by a
|
67
68
|
# 4-sided polygon. A resolution of 2 would cause that buffer
|
68
69
|
# to be approximated by an 8-sided polygon. The exact behavior
|
69
|
-
# for different kinds of buffers is
|
70
|
-
# well-specified as far as I can tell.
|
70
|
+
# for different kinds of buffers is defined by GEOS.
|
71
71
|
# <tt>:srid</tt>::
|
72
72
|
# Set the SRID returned by geometries created by this factory.
|
73
73
|
# Default is 0.
|
@@ -203,9 +203,9 @@ module RGeo
|
|
203
203
|
end
|
204
204
|
|
205
205
|
|
206
|
-
# See ::RGeo::Features::Factory#
|
206
|
+
# See ::RGeo::Features::Factory#cast
|
207
207
|
|
208
|
-
def
|
208
|
+
def cast(original_, force_new_=false)
|
209
209
|
return nil unless Geos.supported?
|
210
210
|
case original_
|
211
211
|
when GeometryImpl
|
@@ -225,21 +225,21 @@ module RGeo
|
|
225
225
|
PointImpl.create(self, original_.x, original_.y)
|
226
226
|
end
|
227
227
|
when Features::Line
|
228
|
-
LineImpl.create(self,
|
228
|
+
LineImpl.create(self, cast(original_.start_point), cast(original_.end_point))
|
229
229
|
when Features::LinearRing
|
230
|
-
LinearRingImpl.create(self, original_.points.map{ |g_|
|
230
|
+
LinearRingImpl.create(self, original_.points.map{ |g_| cast(g_) })
|
231
231
|
when Features::LineString
|
232
|
-
LineStringImpl.create(self, original_.points.map{ |g_|
|
232
|
+
LineStringImpl.create(self, original_.points.map{ |g_| cast(g_) })
|
233
233
|
when Features::Polygon
|
234
|
-
PolygonImpl.create(self,
|
234
|
+
PolygonImpl.create(self, cast(original_.exterior_ring), original_.interior_rings.map{ |g_| cast(g_) })
|
235
235
|
when Features::MultiPoint
|
236
|
-
MultiPointImpl.create(self, original_.to_a.map{ |g_|
|
236
|
+
MultiPointImpl.create(self, original_.to_a.map{ |g_| cast(g_) })
|
237
237
|
when Features::MultiLineString
|
238
|
-
MultiLineStringImpl.create(self, original_.to_a.map{ |g_|
|
238
|
+
MultiLineStringImpl.create(self, original_.to_a.map{ |g_| cast(g_) })
|
239
239
|
when Features::MultiPolygon
|
240
|
-
MultiPolygonImpl.create(self, original_.to_a.map{ |g_|
|
240
|
+
MultiPolygonImpl.create(self, original_.to_a.map{ |g_| cast(g_) })
|
241
241
|
when Features::GeometryCollection
|
242
|
-
GeometryCollectionImpl.create(self, original_.to_a.map{ |g_|
|
242
|
+
GeometryCollectionImpl.create(self, original_.to_a.map{ |g_| cast(g_) })
|
243
243
|
else
|
244
244
|
nil
|
245
245
|
end
|
data/lib/rgeo/geos/interface.rb
CHANGED
@@ -61,6 +61,26 @@ module RGeo
|
|
61
61
|
|
62
62
|
# Returns a factory for the GEOS implementation.
|
63
63
|
# Returns nil if the GEOS implementation is not supported.
|
64
|
+
#
|
65
|
+
# Options include:
|
66
|
+
#
|
67
|
+
# <tt>:lenient_multi_polygon_assertions</tt>::
|
68
|
+
# If set to true, assertion checking on MultiPolygon is disabled.
|
69
|
+
# This may speed up creation of MultiPolygon objects, at the
|
70
|
+
# expense of not doing the proper checking for OGC MultiPolygon
|
71
|
+
# compliance. See RGeo::Features::MultiPolygon for details on
|
72
|
+
# the MultiPolygon assertions. Default is false.
|
73
|
+
# <tt>:buffer_resolution</tt>::
|
74
|
+
# The resolution of buffers around geometries created by this
|
75
|
+
# factory. This controls the number of line segments used to
|
76
|
+
# approximate curves. The default is 1, which causes, for
|
77
|
+
# example, the buffer around a point to be approximated by a
|
78
|
+
# 4-sided polygon. A resolution of 2 would cause that buffer
|
79
|
+
# to be approximated by an 8-sided polygon. The exact behavior
|
80
|
+
# for different kinds of buffers is defined by GEOS.
|
81
|
+
# <tt>:srid</tt>::
|
82
|
+
# Set the SRID returned by geometries created by this factory.
|
83
|
+
# Default is 0.
|
64
84
|
|
65
85
|
def factory(opts_={})
|
66
86
|
supported? ? Factory.create(opts_) : nil
|
@@ -219,10 +219,10 @@ module RGeo
|
|
219
219
|
point2_ = @factory.point(0, 1)
|
220
220
|
line1_ = @factory.line_string([point1_, point2_])
|
221
221
|
line2_ = line1_.clone
|
222
|
-
|
222
|
+
assert(line1_.eql?(line2_))
|
223
223
|
assert_equal(2, line2_.num_points)
|
224
|
-
|
225
|
-
|
224
|
+
assert(point1_.eql?(line2_.point_n(0)))
|
225
|
+
assert(point2_.eql?(line2_.point_n(1)))
|
226
226
|
end
|
227
227
|
|
228
228
|
|
@@ -245,7 +245,7 @@ module RGeo
|
|
245
245
|
line1_ = @factory.line_string([point1_, point2_])
|
246
246
|
text_ = line1_.as_text
|
247
247
|
line2_ = @factory.parse_wkt(text_)
|
248
|
-
|
248
|
+
assert(line2_.eql?(line1_))
|
249
249
|
end
|
250
250
|
|
251
251
|
|
@@ -255,7 +255,7 @@ module RGeo
|
|
255
255
|
line1_ = @factory.line_string([point1_, point2_])
|
256
256
|
binary_ = line1_.as_binary
|
257
257
|
line2_ = @factory.parse_wkb(binary_)
|
258
|
-
|
258
|
+
assert(line2_.eql?(line1_))
|
259
259
|
end
|
260
260
|
|
261
261
|
|
data/tests/common/point_tests.rb
CHANGED
@@ -230,7 +230,6 @@ module RGeo
|
|
230
230
|
point3_ = @factory.point(12, 12)
|
231
231
|
assert_close_enough(point1_, point1_.intersection(point2_))
|
232
232
|
int13_ = point1_.intersection(point3_)
|
233
|
-
assert_equal(::RGeo::Features::GeometryCollection, int13_.geometry_type)
|
234
233
|
assert(int13_.is_empty?)
|
235
234
|
end
|
236
235
|
|
@@ -0,0 +1,203 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# Tests for the internal calculations for simple spherical
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# Copyright 2010 Daniel Azuma
|
7
|
+
#
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
12
|
+
#
|
13
|
+
# * Redistributions of source code must retain the above copyright notice,
|
14
|
+
# this list of conditions and the following disclaimer.
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
+
# this list of conditions and the following disclaimer in the documentation
|
17
|
+
# and/or other materials provided with the distribution.
|
18
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
+
# contributors to this software, may be used to endorse or promote products
|
20
|
+
# derived from this software without specific prior written permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
# -----------------------------------------------------------------------------
|
34
|
+
;
|
35
|
+
|
36
|
+
|
37
|
+
require 'test/unit'
|
38
|
+
require 'rgeo'
|
39
|
+
|
40
|
+
|
41
|
+
module RGeo
|
42
|
+
module Tests # :nodoc:
|
43
|
+
module SimpleSpherical # :nodoc:
|
44
|
+
|
45
|
+
class TestCalculations < ::Test::Unit::TestCase # :nodoc:
|
46
|
+
|
47
|
+
|
48
|
+
def assert_close_enough(v1_, v2_)
|
49
|
+
diff_ = (v1_ - v2_).abs
|
50
|
+
# denom_ = (v1_ + v2_).abs
|
51
|
+
# diff_ /= denom_ if denom_ > 0.01
|
52
|
+
assert(diff_ < 0.00000001, "#{v1_} is not close to #{v2_}")
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
def test_point_eql
|
57
|
+
point1_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 0, 0)
|
58
|
+
point2_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 0, 0)
|
59
|
+
assert_equal(point1_, point2_)
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
def test_point_from_latlng
|
64
|
+
point1_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.from_latlon(45, -45)
|
65
|
+
assert_close_enough(0.5, point1_.x)
|
66
|
+
assert_close_enough(-0.5, point1_.y)
|
67
|
+
assert_close_enough(::Math.sqrt(2) * 0.5, point1_.z)
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
def test_point_dot_one
|
72
|
+
point1_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 1, 1)
|
73
|
+
point2_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 1, 1)
|
74
|
+
assert_close_enough(1.0, point1_ * point2_)
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
def test_point_dot_minusone
|
79
|
+
point1_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 1, 1)
|
80
|
+
point2_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(-1, -1, -1)
|
81
|
+
assert_close_enough(-1.0, point1_ * point2_)
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
def test_point_dot_zero
|
86
|
+
point1_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 1, 0)
|
87
|
+
point2_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, -1, 0)
|
88
|
+
assert_close_enough(0.0, point1_ * point2_)
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
def test_point_cross
|
93
|
+
point1_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 1, 0)
|
94
|
+
point2_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, -1, 0)
|
95
|
+
assert_close_enough(-1.0, (point1_ % point2_).z)
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
def test_point_cross_coincident
|
100
|
+
point1_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 0, 0)
|
101
|
+
point2_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 0, 0)
|
102
|
+
assert_nil(point1_ % point2_)
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
def test_point_cross_opposite
|
107
|
+
point1_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 0, 0)
|
108
|
+
point2_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(-1, 0, 0)
|
109
|
+
assert_nil(point1_ % point2_)
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
def test_arc_axis
|
114
|
+
point1_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 1, 0)
|
115
|
+
point2_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, -1, 0)
|
116
|
+
arc1_ = ::RGeo::Geography::SimpleSpherical::ArcXYZ.new(point1_, point2_)
|
117
|
+
assert_close_enough(-1.0, arc1_.axis.z)
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
def test_arc_axis2
|
122
|
+
point1_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 0, 0)
|
123
|
+
point2_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 0.000001, 0)
|
124
|
+
arc1_ = ::RGeo::Geography::SimpleSpherical::ArcXYZ.new(point1_, point2_)
|
125
|
+
assert_close_enough(1.0, arc1_.axis.z)
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
def test_arc_intersects_point_off
|
130
|
+
point1_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 0, 0)
|
131
|
+
point2_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 0.000002, 0)
|
132
|
+
point3_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 0.000001, 0.1)
|
133
|
+
arc1_ = ::RGeo::Geography::SimpleSpherical::ArcXYZ.new(point1_, point2_)
|
134
|
+
assert_equal(false, arc1_.contains_point?(point3_))
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
def test_arc_intersects_point_between
|
139
|
+
point1_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 0, 0)
|
140
|
+
point2_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 0.000002, 0)
|
141
|
+
point3_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 0.000001, 0)
|
142
|
+
arc1_ = ::RGeo::Geography::SimpleSpherical::ArcXYZ.new(point1_, point2_)
|
143
|
+
assert_equal(true, arc1_.contains_point?(point3_))
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
def test_arc_intersects_point_endpoint
|
148
|
+
point1_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 0, 0)
|
149
|
+
point2_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(1, 0.000002, 0)
|
150
|
+
arc1_ = ::RGeo::Geography::SimpleSpherical::ArcXYZ.new(point1_, point2_)
|
151
|
+
assert_equal(true, arc1_.contains_point?(point1_))
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
def test_arc_intersects_arc_true
|
156
|
+
point1_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(0, 0.1, 1)
|
157
|
+
point2_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(0, -0.1, 1)
|
158
|
+
point3_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(-0.1, 0, 1)
|
159
|
+
point4_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(0.1, 0, 1)
|
160
|
+
arc1_ = ::RGeo::Geography::SimpleSpherical::ArcXYZ.new(point1_, point2_)
|
161
|
+
arc2_ = ::RGeo::Geography::SimpleSpherical::ArcXYZ.new(point3_, point4_)
|
162
|
+
assert_equal(true, arc1_.intersects_arc?(arc2_))
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
def test_arc_intersects_arc_parallel
|
167
|
+
point1_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(0, 0.1, 1)
|
168
|
+
point2_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(0, -0.1, 1)
|
169
|
+
point3_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(0.1, 0.1, 1)
|
170
|
+
point4_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(0.1, -0.1, 1)
|
171
|
+
arc1_ = ::RGeo::Geography::SimpleSpherical::ArcXYZ.new(point1_, point2_)
|
172
|
+
arc2_ = ::RGeo::Geography::SimpleSpherical::ArcXYZ.new(point3_, point4_)
|
173
|
+
assert_equal(false, arc1_.intersects_arc?(arc2_))
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
def test_arc_intersects_arc_separated_tee
|
178
|
+
point1_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(0, 0.1, 1)
|
179
|
+
point2_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(0, -0.1, 1)
|
180
|
+
point3_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(0.1, 0, 1)
|
181
|
+
point4_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(0.2, 0, 1)
|
182
|
+
arc1_ = ::RGeo::Geography::SimpleSpherical::ArcXYZ.new(point1_, point2_)
|
183
|
+
arc2_ = ::RGeo::Geography::SimpleSpherical::ArcXYZ.new(point3_, point4_)
|
184
|
+
assert_equal(false, arc1_.intersects_arc?(arc2_))
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
def test_arc_intersects_arc_connected_tee
|
189
|
+
point1_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(0, 0.1, 1)
|
190
|
+
point2_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(0, -0.1, 1)
|
191
|
+
point3_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(0, 0, 1)
|
192
|
+
point4_ = ::RGeo::Geography::SimpleSpherical::PointXYZ.new(0.1, 0, 1)
|
193
|
+
arc1_ = ::RGeo::Geography::SimpleSpherical::ArcXYZ.new(point1_, point2_)
|
194
|
+
arc2_ = ::RGeo::Geography::SimpleSpherical::ArcXYZ.new(point3_, point4_)
|
195
|
+
assert_equal(true, arc1_.intersects_arc?(arc2_))
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
@@ -0,0 +1,231 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# Tests for the simple spherical point implementation
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# Copyright 2010 Daniel Azuma
|
7
|
+
#
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
12
|
+
#
|
13
|
+
# * Redistributions of source code must retain the above copyright notice,
|
14
|
+
# this list of conditions and the following disclaimer.
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
+
# this list of conditions and the following disclaimer in the documentation
|
17
|
+
# and/or other materials provided with the distribution.
|
18
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
+
# contributors to this software, may be used to endorse or promote products
|
20
|
+
# derived from this software without specific prior written permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
# -----------------------------------------------------------------------------
|
34
|
+
;
|
35
|
+
|
36
|
+
|
37
|
+
require 'test/unit'
|
38
|
+
require 'rgeo'
|
39
|
+
|
40
|
+
|
41
|
+
module RGeo
|
42
|
+
module Tests # :nodoc:
|
43
|
+
module SimpleSpherical # :nodoc:
|
44
|
+
|
45
|
+
class TestLineString < ::Test::Unit::TestCase # :nodoc:
|
46
|
+
|
47
|
+
|
48
|
+
def setup
|
49
|
+
@factory = ::RGeo::Geography.simple_spherical
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def _test_creation_success
|
54
|
+
point1_ = @factory.point(0, 0)
|
55
|
+
point2_ = @factory.point(0, 1)
|
56
|
+
point3_ = @factory.point(1, 0)
|
57
|
+
line1_ = @factory.line_string([point1_, point2_])
|
58
|
+
assert_not_nil(line1_)
|
59
|
+
assert_equal(::RGeo::Features::LineString, line1_.geometry_type)
|
60
|
+
assert_equal(2, line1_.num_points)
|
61
|
+
assert_equal(point1_, line1_.point_n(0))
|
62
|
+
assert_equal(point2_, line1_.point_n(1))
|
63
|
+
line2_ = @factory.line_string([point1_, point2_, point3_])
|
64
|
+
assert_not_nil(line2_)
|
65
|
+
assert_equal(::RGeo::Features::LineString, line2_.geometry_type)
|
66
|
+
assert_equal(3, line2_.num_points)
|
67
|
+
assert_equal(point1_, line2_.point_n(0))
|
68
|
+
assert_equal(point2_, line2_.point_n(1))
|
69
|
+
assert_equal(point3_, line2_.point_n(2))
|
70
|
+
line3_ = @factory.line_string([point1_, point1_])
|
71
|
+
assert_not_nil(line3_)
|
72
|
+
assert_equal(::RGeo::Features::LineString, line3_.geometry_type)
|
73
|
+
assert_equal(2, line3_.num_points)
|
74
|
+
assert_equal(point1_, line3_.point_n(0))
|
75
|
+
assert_equal(point1_, line3_.point_n(1))
|
76
|
+
line4_ = @factory.line_string([])
|
77
|
+
assert_not_nil(line4_)
|
78
|
+
assert_equal(::RGeo::Features::LineString, line4_.geometry_type)
|
79
|
+
assert_equal(0, line4_.num_points)
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
def _test_creation_line_string
|
84
|
+
point1_ = @factory.point(0, 0)
|
85
|
+
point2_ = @factory.point(0, 1)
|
86
|
+
point3_ = @factory.point(1, 1)
|
87
|
+
line1_ = @factory.line_string([point1_, point2_, point3_])
|
88
|
+
assert_not_nil(line1_)
|
89
|
+
assert(::RGeo::Features::LineString === line1_)
|
90
|
+
assert(!(::RGeo::Features::LinearRing === line1_))
|
91
|
+
assert(!(::RGeo::Features::Line === line1_))
|
92
|
+
assert_equal(::RGeo::Features::LineString, line1_.geometry_type)
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
def test_creation_linear_ring
|
97
|
+
point1_ = @factory.point(0, 0)
|
98
|
+
point2_ = @factory.point(0, 1)
|
99
|
+
point3_ = @factory.point(1, 0)
|
100
|
+
line1_ = @factory.linear_ring([point1_, point2_, point3_, point1_])
|
101
|
+
assert_not_nil(line1_)
|
102
|
+
assert(line1_.is_ring?)
|
103
|
+
assert(::RGeo::Features::LinearRing === line1_)
|
104
|
+
assert_equal(::RGeo::Features::LinearRing, line1_.geometry_type)
|
105
|
+
line2_ = @factory.linear_ring([point1_, point2_, point3_])
|
106
|
+
assert_not_nil(line2_)
|
107
|
+
assert(line2_.is_ring?)
|
108
|
+
assert(::RGeo::Features::LinearRing === line2_)
|
109
|
+
assert_equal(4, line2_.num_points)
|
110
|
+
assert_equal(::RGeo::Features::LinearRing, line2_.geometry_type)
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
def _test_creation_line
|
115
|
+
point1_ = @factory.point(0, 0)
|
116
|
+
point2_ = @factory.point(0, 1)
|
117
|
+
line1_ = @factory.line(point1_, point2_)
|
118
|
+
assert_not_nil(line1_)
|
119
|
+
assert(::RGeo::Features::Line === line1_)
|
120
|
+
assert_equal(::RGeo::Features::Line, line1_.geometry_type)
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
def test_creation_errors
|
125
|
+
point1_ = @factory.point(0, 0)
|
126
|
+
collection_ = point1_.boundary
|
127
|
+
line1_ = @factory.line_string([point1_])
|
128
|
+
assert_nil(line1_)
|
129
|
+
line2_ = @factory.line_string([point1_, collection_])
|
130
|
+
assert_nil(line2_)
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
def test_wkt_creation
|
135
|
+
line1_ = @factory.parse_wkt('LINESTRING(21 22, 11 12)')
|
136
|
+
assert_equal(@factory.point(21, 22), line1_.point_n(0))
|
137
|
+
assert_equal(@factory.point(11, 12), line1_.point_n(1))
|
138
|
+
assert_equal(2, line1_.num_points)
|
139
|
+
line2_ = @factory.parse_wkt('LINESTRING(-1 -1, 21 22, 11 12, -1 -1)')
|
140
|
+
assert_equal(@factory.point(-1, -1), line2_.point_n(0))
|
141
|
+
assert_equal(@factory.point(21, 22), line2_.point_n(1))
|
142
|
+
assert_equal(@factory.point(11, 12), line2_.point_n(2))
|
143
|
+
assert_equal(@factory.point(-1, -1), line2_.point_n(3))
|
144
|
+
assert_equal(4, line2_.num_points)
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
def test_clone
|
149
|
+
point1_ = @factory.point(0, 0)
|
150
|
+
point2_ = @factory.point(0, 1)
|
151
|
+
line1_ = @factory.line_string([point1_, point2_])
|
152
|
+
line2_ = line1_.clone
|
153
|
+
assert(line1_.eql?(line2_))
|
154
|
+
assert_equal(2, line2_.num_points)
|
155
|
+
assert(point1_.eql?(line2_.point_n(0)))
|
156
|
+
assert(point2_.eql?(line2_.point_n(1)))
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
def test_type_check
|
161
|
+
point1_ = @factory.point(0, 0)
|
162
|
+
point2_ = @factory.point(0, 1)
|
163
|
+
line_ = @factory.line_string([point1_, point2_])
|
164
|
+
assert(::RGeo::Features::Geometry.check_type(line_))
|
165
|
+
assert(!::RGeo::Features::Point.check_type(line_))
|
166
|
+
assert(!::RGeo::Features::GeometryCollection.check_type(line_))
|
167
|
+
assert(::RGeo::Features::Curve.check_type(line_))
|
168
|
+
assert(::RGeo::Features::LineString.check_type(line_))
|
169
|
+
assert(!::RGeo::Features::LinearRing.check_type(line_))
|
170
|
+
end
|
171
|
+
|
172
|
+
|
173
|
+
def test_as_text_wkt_round_trip
|
174
|
+
point1_ = @factory.point(0, 0)
|
175
|
+
point2_ = @factory.point(0, 1)
|
176
|
+
line1_ = @factory.line_string([point1_, point2_])
|
177
|
+
text_ = line1_.as_text
|
178
|
+
line2_ = @factory.parse_wkt(text_)
|
179
|
+
assert(line2_.eql?(line1_))
|
180
|
+
end
|
181
|
+
|
182
|
+
|
183
|
+
def test_as_binary_wkb_round_trip
|
184
|
+
point1_ = @factory.point(-42, 0)
|
185
|
+
point2_ = @factory.point(0, 193)
|
186
|
+
line1_ = @factory.line_string([point1_, point2_])
|
187
|
+
binary_ = line1_.as_binary
|
188
|
+
line2_ = @factory.parse_wkb(binary_)
|
189
|
+
assert(line2_.eql?(line1_))
|
190
|
+
end
|
191
|
+
|
192
|
+
|
193
|
+
def test_empty_as_text_wkt_round_trip
|
194
|
+
line1_ = @factory.line_string([])
|
195
|
+
text_ = line1_.as_text
|
196
|
+
line2_ = @factory.parse_wkt(text_)
|
197
|
+
assert(line2_.is_empty?)
|
198
|
+
end
|
199
|
+
|
200
|
+
|
201
|
+
def test_empty_as_binary_wkb_round_trip
|
202
|
+
line1_ = @factory.line_string([])
|
203
|
+
binary_ = line1_.as_binary
|
204
|
+
line2_ = @factory.parse_wkb(binary_)
|
205
|
+
assert(line2_.is_empty?)
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
def test_dimension
|
210
|
+
point1_ = @factory.point(-42, 0)
|
211
|
+
point2_ = @factory.point(0, 193)
|
212
|
+
line1_ = @factory.line_string([point1_, point2_])
|
213
|
+
assert_equal(1, line1_.dimension)
|
214
|
+
end
|
215
|
+
|
216
|
+
|
217
|
+
def test_is_empty
|
218
|
+
point1_ = @factory.point(-42, 0)
|
219
|
+
point2_ = @factory.point(0, 193)
|
220
|
+
line1_ = @factory.line_string([point1_, point2_])
|
221
|
+
assert(!line1_.is_empty?)
|
222
|
+
line2_ = @factory.line_string([])
|
223
|
+
assert(line2_.is_empty?)
|
224
|
+
end
|
225
|
+
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
@@ -144,7 +144,6 @@ module RGeo
|
|
144
144
|
def test_boundary
|
145
145
|
point_ = @factory.point(11, 12)
|
146
146
|
boundary_ = point_.boundary
|
147
|
-
assert_equal(::RGeo::Features::GeometryCollection, boundary_.geometry_type)
|
148
147
|
assert(boundary_.is_empty?)
|
149
148
|
end
|
150
149
|
|
@@ -153,8 +152,40 @@ module RGeo
|
|
153
152
|
point1_ = @factory.point(11, 12)
|
154
153
|
point2_ = @factory.point(11, 12)
|
155
154
|
point3_ = @factory.point(13, 12)
|
156
|
-
|
157
|
-
|
155
|
+
assert(point1_.equals?(point2_))
|
156
|
+
assert(point1_ == point2_)
|
157
|
+
assert(point1_.eql?(point2_))
|
158
|
+
assert(!point1_.equals?(point3_))
|
159
|
+
assert(point1_ != point3_)
|
160
|
+
assert(!point1_.eql?(point3_))
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
def test_convex_hull
|
165
|
+
point_ = @factory.point(11, 12)
|
166
|
+
assert_equal(point_, point_.convex_hull)
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
def test_latlon
|
171
|
+
point_ = @factory.point(21, -22)
|
172
|
+
assert_equal(21, point_.longitude)
|
173
|
+
assert_equal(-22, point_.latitude)
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
def test_srid
|
178
|
+
point_ = @factory.point(11, 12)
|
179
|
+
assert_equal(4326, point_.srid)
|
180
|
+
end
|
181
|
+
|
182
|
+
|
183
|
+
def test_distance
|
184
|
+
point1_ = @factory.point(0, 10)
|
185
|
+
point2_ = @factory.point(0, 10)
|
186
|
+
point3_ = @factory.point(0, 40)
|
187
|
+
assert_in_delta(0, point1_.distance(point2_), 0.0001)
|
188
|
+
assert_in_delta(::Math::PI / 6.0 * ::RGeo::Geography::SimpleSpherical::RADIUS, point1_.distance(point3_), 0.0001)
|
158
189
|
end
|
159
190
|
|
160
191
|
|
data/tests/tc_oneoff.rb
CHANGED
@@ -46,6 +46,7 @@ module RGeo
|
|
46
46
|
|
47
47
|
def setup
|
48
48
|
@mercator_factory = ::RGeo::Geography.simple_mercator
|
49
|
+
@spherical_factory = ::RGeo::Geography.simple_spherical
|
49
50
|
@geos_factory = ::RGeo::Geos.factory(:srid => 4326)
|
50
51
|
@entity_factory = ::RGeo::GeoJSON::EntityFactory.instance
|
51
52
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 12
|
9
|
+
version: 0.1.12
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Daniel Azuma
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-10-
|
17
|
+
date: 2010-10-23 00:00:00 -07:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -117,6 +117,8 @@ files:
|
|
117
117
|
- tests/simple_mercator/tc_point.rb
|
118
118
|
- tests/simple_mercator/tc_polygon.rb
|
119
119
|
- tests/simple_mercator/tc_window.rb
|
120
|
+
- tests/simple_spherical/tc_calculations.rb
|
121
|
+
- tests/simple_spherical/tc_line_string.rb
|
120
122
|
- tests/simple_spherical/tc_point.rb
|
121
123
|
- tests/tc_geojson.rb
|
122
124
|
- tests/tc_oneoff.rb
|
@@ -196,6 +198,8 @@ test_files:
|
|
196
198
|
- tests/simple_mercator/tc_point.rb
|
197
199
|
- tests/simple_mercator/tc_polygon.rb
|
198
200
|
- tests/simple_mercator/tc_window.rb
|
201
|
+
- tests/simple_spherical/tc_calculations.rb
|
202
|
+
- tests/simple_spherical/tc_line_string.rb
|
199
203
|
- tests/simple_spherical/tc_point.rb
|
200
204
|
- tests/tc_geojson.rb
|
201
205
|
- tests/tc_oneoff.rb
|