rgeo 0.1.11 → 0.1.12

Sign up to get free protection for your applications and to get access to all the features.
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.11
1
+ 0.1.12
@@ -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("coerce"), 1, obj);
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("coerce"), 2, obj, Qtrue);
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
- # Coerce an existing feature to a feature of the type created by
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 coerce(original_, force_new_=false)
182
+ def cast(original_, force_new_=false)
182
183
  nil
183
184
  end
184
185
 
@@ -116,7 +116,7 @@ module RGeo
116
116
 
117
117
 
118
118
  def included(mod_) # :nodoc:
119
- mod_.extend(ClassMethods)
119
+ mod_.extend(ClassMethods) unless mod_.kind_of?(Class)
120
120
  end
121
121
 
122
122
  end
@@ -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 methods uses the eql? method to test geometry equality, which
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 methods uses the == operator to test geometry equality, which
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_)
@@ -56,7 +56,7 @@ module RGeo
56
56
 
57
57
 
58
58
  def _setup(elements_)
59
- @elements = elements_.map{ |elem_| factory.coerce(elem_) }
59
+ @elements = elements_.map{ |elem_| factory.cast(elem_) }
60
60
  _validate_geometry
61
61
  end
62
62
 
@@ -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_.coerce(obj_) : nil
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_.coerce(obj_) : nil
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_.coerce(obj_).as_text : nil
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_.coerce(obj_).as_binary : nil
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{ |elem_| factory.coerce(elem_) }
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.coerce(rhs_)
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.coerce(elem_) }
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. Default is false.
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 not specified.
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#coerce
216
+ # See ::RGeo::Features::Factory#cast
217
217
 
218
- def coerce(original_, force_new_=false)
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, coerce(original_.start_point), coerce(original_.end_point)) rescue nil
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_| coerce(g_) }) rescue nil
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_| coerce(g_) }) rescue nil
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, coerce(original_.exterior_ring), original_.interior_rings.map{ |g_| coerce(g_) }) rescue nil
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_| coerce(g_) }) rescue nil
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_| coerce(g_) }) rescue nil
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_| coerce(g_) }) rescue nil
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_| coerce(g_) }) rescue nil
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.coerce(rhs_).projection)
106
+ projection.equals?(factory.cast(rhs_).projection)
107
107
  end
108
108
 
109
109
 
110
110
  def disjoint?(rhs_)
111
- projection.disjoint?(factory.coerce(rhs_).projection)
111
+ projection.disjoint?(factory.cast(rhs_).projection)
112
112
  end
113
113
 
114
114
 
115
115
  def intersects?(rhs_)
116
- projection.intersects?(factory.coerce(rhs_).projection)
116
+ projection.intersects?(factory.cast(rhs_).projection)
117
117
  end
118
118
 
119
119
 
120
120
  def touches?(rhs_)
121
- projection.touches?(factory.coerce(rhs_).projection)
121
+ projection.touches?(factory.cast(rhs_).projection)
122
122
  end
123
123
 
124
124
 
125
125
  def crosses?(rhs_)
126
- projection.crosses?(factory.coerce(rhs_).projection)
126
+ projection.crosses?(factory.cast(rhs_).projection)
127
127
  end
128
128
 
129
129
 
130
130
  def within?(rhs_)
131
- projection.within?(factory.coerce(rhs_).projection)
131
+ projection.within?(factory.cast(rhs_).projection)
132
132
  end
133
133
 
134
134
 
135
135
  def contains?(rhs_)
136
- projection.contains?(factory.coerce(rhs_).projection)
136
+ projection.contains?(factory.cast(rhs_).projection)
137
137
  end
138
138
 
139
139
 
140
140
  def overlaps?(rhs_)
141
- projection.overlaps?(factory.coerce(rhs_).projection)
141
+ projection.overlaps?(factory.cast(rhs_).projection)
142
142
  end
143
143
 
144
144
 
145
145
  def relate(rhs_, pattern_)
146
- projection.relate(factory.coerce(rhs_).projection, pattern_)
146
+ projection.relate(factory.cast(rhs_).projection, pattern_)
147
147
  end
148
148
 
149
149
 
150
150
  def distance(rhs_)
151
- projection.distance(factory.coerce(rhs_).projection) / scaling_factor
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.coerce(rhs_).projection))
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.coerce(rhs_).projection))
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.coerce(rhs_).projection))
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.coerce(rhs_).projection))
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-rx_) rescue nil
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
- module Calculations
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
- def point_distance(p1_, p2_)
112
- rpd_ = Common::Helper::RADIANS_PER_DEGREE
113
- from_lat_rad_ = rpd_ * from_.lat
114
- to_lat_rad_ = rpd_ * to_.lat
115
- delta_lon_rad_ = rpd_ * (to_.lon - from_.lon)
116
- val_ = ::Math.sin(from_lat_rad_) * ::Math.sin(to_lat_rad_) +
117
- ::Math.cos(from_lat_rad_) * ::Math.cos(to_lat_rad_) * ::Math.cos(delta_lon_rad_)
118
- val_ = 1.0 if val_ > 1.0
119
- val_ = -1.0 if val_ < -1.0
120
- ::Math.acos(val_) * RADIUS
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 xyz
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 Features::Point
76
- Calculator.point_distance(self, rhs_)
76
+ when PointImpl
77
+ _xyz.dist_to_point(rhs_._xyz) * SimpleSpherical::RADIUS
77
78
  else
78
79
  super
79
80
  end
@@ -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. Default is false.
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 internal to GEOS, and is not
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#coerce
206
+ # See ::RGeo::Features::Factory#cast
207
207
 
208
- def coerce(original_, force_new_=false)
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, coerce(original_.start_point), coerce(original_.end_point))
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_| coerce(g_) })
230
+ LinearRingImpl.create(self, original_.points.map{ |g_| cast(g_) })
231
231
  when Features::LineString
232
- LineStringImpl.create(self, original_.points.map{ |g_| coerce(g_) })
232
+ LineStringImpl.create(self, original_.points.map{ |g_| cast(g_) })
233
233
  when Features::Polygon
234
- PolygonImpl.create(self, coerce(original_.exterior_ring), original_.interior_rings.map{ |g_| coerce(g_) })
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_| coerce(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_| coerce(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_| coerce(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_| coerce(g_) })
242
+ GeometryCollectionImpl.create(self, original_.to_a.map{ |g_| cast(g_) })
243
243
  else
244
244
  nil
245
245
  end
@@ -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
- assert_equal(line1_, line2_)
222
+ assert(line1_.eql?(line2_))
223
223
  assert_equal(2, line2_.num_points)
224
- assert_equal(point1_, line2_.point_n(0))
225
- assert_equal(point2_, line2_.point_n(1))
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
- assert_equal(line2_, line1_)
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
- assert_equal(line2_, line1_)
258
+ assert(line2_.eql?(line1_))
259
259
  end
260
260
 
261
261
 
@@ -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
- assert_equal(point1_, point2_)
157
- assert_not_equal(point1_, point3_)
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
- - 11
9
- version: 0.1.11
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-21 00:00:00 -07:00
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