module SdbDal module Geo class Location attr_accessor :latitude attr_accessor :longitude def initialize(lat,lon) self.latitude=lat self.longitude=lon end def to_address if latitude==nil || longitude==nil return nil end address='t' right=0 top=0 width=180.0 height=90.0 16.times do if latitude>top top=top+height/2.0 if longitude(zoom_level+1) address=address.slice(0,zoom_level+1) end result=[address] tileWidth=360.0/(2**zoom_level) tileHeight=180.0/(2**zoom_level) other=Geo::Location.new(self.latitude+tileHeight,self.longitude+tileWidth) result << other.to_address.slice(0,zoom_level+1) other=Geo::Location.new(self.latitude+tileHeight,self.longitude) result << other.to_address.slice(0,zoom_level+1) other=Geo::Location.new(self.latitude+tileHeight,self.longitude-tileWidth) result << other.to_address.slice(0,zoom_level+1) other=Geo::Location.new(self.latitude-tileHeight,self.longitude+tileWidth) result << other.to_address.slice(0,zoom_level+1) other=Geo::Location.new(self.latitude-tileHeight,self.longitude) result << other.to_address.slice(0,zoom_level+1) other=Geo::Location.new(self.latitude-tileHeight,self.longitude-tileWidth) result << other.to_address.slice(0,zoom_level+1) other=Geo::Location.new(self.latitude,self.longitude+tileWidth) result << other.to_address.slice(0,zoom_level+1) other=Geo::Location.new(self.latitude,self.longitude-tileWidth) result << other.to_address.slice(0,zoom_level+1) end def Location.to_location(address) width=90.0 height=45.0 index=0 x=0 y=0 length=address.length-1 length.times do index+=1 puts address[index].chr case address[index].chr when 'r' x+=width y+=height when 'q' x-=width y+=height when 't' x-=width y-=height when 's' x+=width y-=height end width/=2 height/=2 end loc=Location.new loc.latitude=y loc.longitude=x return loc end 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 distance_in_miles( loc2) lat2 = loc2.latitude lon2 = loc2.longitude theta = self.longitude - lon2 dist = Math.sin(self.deg2rad(self.latitude)) * Math.sin(deg2rad(lat2)) + Math.cos(self.deg2rad(self.latitude)) * Math.cos(self.deg2rad(lat2)) * Math.cos(deg2rad(theta)) dist = self.rad2deg(self.acos(dist)) (dist * 60 * 1.1515).round #distance in miles end end #mixin #locatable object must have latitude, longitude and address attributes module Locatable def location return Geo::Location.new(latitude,longitude) end def get_nearby(zoom_level=7,order=nil) if latitude==nil or longitude==nil return [] end result= self.class.find_near(self.location,zoom_level,order) result.delete_if{|item|item.id==id} return result end def find_near(loc,zoom_level=7,order_by=nil,order=:ascending) nearby= loc.get_nearby_addresses(zoom_level) address_params=[] for address in nearby address_params< 24,:order_by => order_by,:order => order,:conditions=>[orCondition]) end end module Xxx end end end