rails-geocoder 0.8.6 → 0.8.7

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/CHANGELOG.rdoc CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  Per-release changes to Geocoder.
4
4
 
5
+ == 0.8.7 (2009 Nov 4)
6
+
7
+ * Added Geocoder.geographic_center method.
8
+ * Replaced _get_coordinates class method with read_coordinates instance method.
9
+
5
10
  == 0.8.6 (2009 Oct 27)
6
11
 
7
12
  * The fetch_coordinates method now assigns coordinates to attributes (behaves like fetch_coordinates! used to) and fetch_coordinates! both assigns and saves the attributes.
data/README.rdoc CHANGED
@@ -73,6 +73,9 @@ Some utility methods are also available:
73
73
 
74
74
  # look up coordinates of some location (like searching Google Maps)
75
75
  Geocoder.fetch_coordinates("25 Main St, Cooperstown, NY")
76
+
77
+ # find the geographic center (aka center of gravity) of objects or points
78
+ Geocoder.geographic_center([ city1, city2, city3, [40.22,-73.99], city4 ])
76
79
 
77
80
 
78
81
  == More On Configuration
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.8.6
1
+ 0.8.7
data/lib/geocoder.rb CHANGED
@@ -102,22 +102,21 @@ module Geocoder
102
102
  :limit => limit
103
103
  }
104
104
  end
105
+ end
105
106
 
106
- ##
107
- # Get the coordinates [lat,lon] of an object. This is not great but it
108
- # seems cleaner than polluting the object method namespace.
109
- #
110
- def _get_coordinates(object)
111
- [object.send(geocoder_options[:latitude]),
112
- object.send(geocoder_options[:longitude])]
113
- end
107
+ ##
108
+ # Read the coordinates [lat,lon] of an object. This is not great but it
109
+ # seems cleaner than polluting the instance method namespace.
110
+ #
111
+ def read_coordinates
112
+ [:latitude, :longitude].map{ |i| send self.class.geocoder_options[i] }
114
113
  end
115
-
114
+
116
115
  ##
117
116
  # Is this object geocoded? (Does it have latitude and longitude?)
118
117
  #
119
118
  def geocoded?
120
- self.class._get_coordinates(self).compact.size > 0
119
+ read_coordinates.compact.size > 0
121
120
  end
122
121
 
123
122
  ##
@@ -126,7 +125,7 @@ module Geocoder
126
125
  #
127
126
  def distance_to(lat, lon, units = :mi)
128
127
  return nil unless geocoded?
129
- mylat,mylon = self.class._get_coordinates(self)
128
+ mylat,mylon = read_coordinates
130
129
  Geocoder.distance_between(mylat, mylon, lat, lon, :units => units)
131
130
  end
132
131
 
@@ -137,9 +136,8 @@ module Geocoder
137
136
  #
138
137
  def nearbys(radius = 20, options = {})
139
138
  return [] unless geocoded?
140
- coords = self.class._get_coordinates(self)
141
139
  options = {:conditions => ["id != ?", id]}.merge(options)
142
- self.class.near(coords, radius, options) - [self]
140
+ self.class.near(read_coordinates, radius, options) - [self]
143
141
  end
144
142
 
145
143
  ##
@@ -213,6 +211,44 @@ module Geocoder
213
211
  c * units[options[:units]]
214
212
  end
215
213
 
214
+ ##
215
+ # Compute the geographic center (aka geographic midpoint, center of
216
+ # gravity) for an array of geocoded objects and/or [lat,lon] arrays
217
+ # (can be mixed). Any objects missing coordinates are ignored. Follows
218
+ # the procedure documented at http://www.geomidpoint.com/calculation.html.
219
+ #
220
+ def self.geographic_center(points)
221
+
222
+ # convert objects to [lat,lon] arrays and remove nils
223
+ points = points.map{ |p|
224
+ p.is_a?(Array) ? p : (p.geocoded?? p.read_coordinates : nil)
225
+ }.compact
226
+
227
+ # convert degrees to radians
228
+ points.map!{ |p| [to_radians(p[0]), to_radians(p[1])] }
229
+
230
+ # convert to Cartesian coordinates
231
+ x = []; y = []; z = []
232
+ points.each do |p|
233
+ x << Math.cos(p[0]) * Math.cos(p[1])
234
+ y << Math.cos(p[0]) * Math.sin(p[1])
235
+ z << Math.sin(p[0])
236
+ end
237
+
238
+ # compute average coordinate values
239
+ xa, ya, za = [x,y,z].map do |c|
240
+ c.inject(0){ |tot,i| tot += i } / c.size.to_f
241
+ end
242
+
243
+ # convert back to latitude/longitude
244
+ lon = Math.atan2(ya, xa)
245
+ hyp = Math.sqrt(xa**2 + ya**2)
246
+ lat = Math.atan2(za, hyp)
247
+
248
+ # return answer in degrees
249
+ [to_degrees(lat), to_degrees(lon)]
250
+ end
251
+
216
252
  ##
217
253
  # Convert degrees to radians.
218
254
  #
@@ -220,6 +256,13 @@ module Geocoder
220
256
  degrees * (Math::PI / 180)
221
257
  end
222
258
 
259
+ ##
260
+ # Convert radians to degrees.
261
+ #
262
+ def self.to_degrees(radians)
263
+ (radians * 180.0) / Math::PI
264
+ end
265
+
223
266
  ##
224
267
  # Query Google for geographic information about the given phrase.
225
268
  #
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rails-geocoder}
8
- s.version = "0.8.6"
8
+ s.version = "0.8.7"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Alex Reisner"]
12
- s.date = %q{2009-10-27}
12
+ s.date = %q{2009-11-04}
13
13
  s.description = %q{Geocoder adds object geocoding and database-agnostic distance calculations to Ruby on Rails. It does not rely on proprietary database functions so finding geocoded objects in a given area is easily done using out-of-the-box MySQL or even SQLite.}
14
14
  s.email = %q{alex@alexreisner.com}
15
15
  s.extra_rdoc_files = [
@@ -7,4 +7,17 @@ class GeocoderTest < Test::Unit::TestCase
7
7
  assert_equal [40.7495760, -73.9916733], v.fetch_coordinates
8
8
  assert_equal [40.7495760, -73.9916733], [v.latitude, v.longitude]
9
9
  end
10
+
11
+ # sanity check
12
+ def test_distance_between
13
+ assert_equal 69, Geocoder.distance_between(0,0, 0,1).round
14
+ end
15
+
16
+ # sanity check
17
+ def test_geographic_center
18
+ assert_equal [0.0, 0.5],
19
+ Geocoder.geographic_center([[0,0], [0,1]])
20
+ assert_equal [0.0, 1.0],
21
+ Geocoder.geographic_center([[0,0], [0,1], [0,2]])
22
+ end
10
23
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-geocoder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.6
4
+ version: 0.8.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Reisner
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-27 00:00:00 -04:00
12
+ date: 2009-11-04 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies: []
15
15