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 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