DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Location Queries For A Model

04.12.2006
| 8484 views |
  • submit to reddit
        // These are class functions which are useful for finding locations in a database 
// when PostGIS is not available (when using MySQL for example)

def self.deg2rad(deg)
	(deg * Math::PI / 180)
end

def self.rad2deg(rad)
	(rad * 180 / Math::PI)
end

def self.acos(rad)
	Math.atan2(Math.sqrt(1 - rad**2), rad)
end

def self.distance_in_miles(loc1, loc2)
	lat1 = loc1.latitude
	lon1 = loc1.longitude
	lat2 = loc2.latitude
	lon2 = loc2.longitude
	theta = lon1 - lon2
	
	dist = Math.sin(self.deg2rad(lat1)) * Math.sin(deg2rad(lat2)) 
		+ Math.cos(self.deg2rad(lat1)) * Math.cos(self.deg2rad(lat2)) * Math.cos(deg2rad(theta))
	
	dist = self.rad2deg(self.acos(dist))
	
	(dist * 60 * 1.1515).round #distance in miles
end

def miles_to(location)
	Location.distance_in_miles(self, location)
end

def self.locationArea(location, miles)
	radius = miles.to_f
	latR = radius / ((6076 / 5280) * 60)
	lonR = radius / (((Math.cos(location.latitude * Math::PI / 180) * 6076) / 5280) * 60)
	
	{
		:min_latitude => location.latitude - latR,
		:min_longitude => location.longitude - lonR,
		:max_latitude => location.latitude + latR,
		:max_longitude => location.longitude + lonR
	}
end

def self.location_ids_in_range(location, miles)
	la = Location.locationArea(location, miles)
	Location.find(:all,
		:select => "locations.id",
		:conditions => ["locations.latitude <= ? and locations.latitude >= ? " + \
			" AND locations.longitude >= ? and locations.longitude <= ?",
			la[:max_latitude], la[:min_latitude], la[:min_longitude], la[:max_longitude]
		]
	).collect { |l| l.id }
end

def self.locations_in_range(location, miles)
	la = Location.locationArea(location, miles)
	Location.find(:all,
		:conditions => ["locations.latitude <= ? and locations.latitude >= ? " + \
			" AND locations.longitude >= ? and locations.longitude <= ?",
			la[:max_latitude], la[:min_latitude], la[:min_longitude], la[:max_longitude]
		]
	)
end
    

Comments

John Griffiths replied on Mon, 2007/07/23 - 7:25am

awesome work ajturner, especially => self.locationArea great stuff, John.