Anyone tried geolocation?

10 views
Skip to first unread message

Roy Wright

unread,
Oct 8, 2009, 1:20:35 PM10/8/09
to mongo...@googlegroups.com
Howdy,

I'm looking at a project for using MongoMapper, but it really needs a
geolocation search (find address within so many miles). Any pointers
or ideas?

TIA,
Roy

Robert Malko

unread,
Oct 8, 2009, 4:53:25 PM10/8/09
to MongoMapper
Roy,

Take a look at: http://github.com/andre/geokit-rails/tree/master/lib/geokit-rails/

There is an adapters folder with some sql. I'd suggest writing some
math for the haversine formula that takes in the same options. All
those finders are doing is some math. Let me know if that helps or if
you'd want some help as I'd probably be looking in to this in the near
future as well.

Best

Chris McGrath

unread,
Oct 8, 2009, 6:22:24 PM10/8/09
to MongoMapper
Roy,

Ran into this about a week back.
If you want to just geocode Roberts advice is good. You can still use
geokit to get lat/lng.

http://github.com/andre/geokit-gem

>> require 'geokit'

>> a = Geokit::Geocoders::MultiGeocoder.geocode("seattle wa")
>> a.ll
=> "47.6062095,-122.3320708"

>> b = Geokit::Geocoders::MultiGeocoder.geocode("austin tx")
>> b.ll
=> "30.267153,-97.7430608"

>> lat_m = 69.172 #latitude miles
>> lng_m = (lat_m * Math.cos(b.lat * (Math::PI/180))).abs #longitude miles

>> distance = Math.sqrt((lat_m * (a.lat - (b.lat)) ** 2) + (lng_m * (a.lng - (b.lng)) ** 2)) * 10
=> 2385.74354549272

im assuming multigeocoder takes googles first since the milage form
these are exactly the same. below is the gmpa link.

http://maps.google.com/maps?f=d&source=s_d&saddr=47.6062095,-122.3320708&daddr=30.267153,-97.7430608&hl=en&geocode=&mra=ls&sll=38.93448,-109.70755&sspn=18.637252,39.506836&ie=UTF8&t=h&z=5

snag your addresses, geocode and get the lat/lng, plug them into that
formula and you should have your distance
where a = first address and b = second address

hope this helps or at least gets you started in the right direction.

/cheers

Roy Wright

unread,
Oct 8, 2009, 6:37:10 PM10/8/09
to mongo...@googlegroups.com
Getting there.

What I'd really like is to do the selection on the db side, something
like:

distance = 25 * 5280 # in feet
lng,lat = current_location
nearby_stors = Store.all(:conditions => {'$where' => "within(this,
#{distance}, #{lng}, #{lat}"})

I'm currently trying to figure out how to do server-side functions.
Here's my in-progress gist:

http://gist.github.com/205303

Not quite there yet...

Thank you!

Chris McGrath

unread,
Oct 8, 2009, 6:42:07 PM10/8/09
to MongoMapper
Roy,

maybe this would help
(again assuming you have a db with zips and lat/lng on each)

r = radius
zip = zip your searching with

r = r.to_f
lat_m = 69.172
lng_m = (lat_m * Math.cos(zip.lat * (Math::PI/180))).abs
lat_d = r/lat_m
lng_d = r/lng_m

min_lat = zip.lat - lat_d
max_lat = zip.lat + lat_d
min_lng = zip.lng - lng_d
max_lng = zip.lng + lng_d

zips = ZipCode.all(:select => [:zip_code, :lng, :lat], :conditions =>
{:lat => {"$gt" => min_lat, "$lt" => max_lat}, :lng => {"$gt" =>
min_lng, "$lt" => max_lng}}).each do |z|
z[:distance] = Math.sqrt((lat_m * (z.lat - (zip.lat)) ** 2) +
(lng_m * (z.lng - (zip.lng)) ** 2))
end
zips.sort{|a,b| a.distance <=> b.distance} # if you want the closest
first

/cheers
Reply all
Reply to author
Forward
0 new messages