我有一个位置模型,其中每个位置都有一个以度为单位的纬度和经度坐标,我试图让一个位置实例返回基于http://www.mullie.eu/geographic-searches/的指定距离范围内的所有位置:
def in_range(distance)
earth_radius = 3958.75587
maxlat = self.lat + to_deg(distance / earth_radius)
minlat = self.lat - to_deg(distance / earth_radius)
maxlon = self.lon + to_deg(distance / earth_radius / Math::cos(to_rad(self.lat)))
minlon = self.lon - to_deg(distance / earth_radius / Math::cos(to_rad(self.lat)))
Location.where("lat > ? AND lat < ? AND lon > ? AND lon < ?",minlat,maxlat,minlon,maxlon)
end
当我创建位置并请求范围时:
l1 = Location.find_by_post_code("SW11")
这会返回一个51.4663的纬度和一个-0.165543的lon,当我要求时,我的maxlat,minlat,maxlon,minlon值太小了:
l1.in_range(10)
maxlat = 51.466344087822264
minlat = 51.46625591217773
maxlon = -0.1654722301720378
minlon = -0.1656137698279622
所以我认为这些值的计算是错误的,但是在找到这方面的资源时遇到了麻烦,有没有人知道获取最大和最小坐标值的正确方法?
编辑 - 随后回答,完整的工作代码如下:
class Location < ActiveRecord::Base
EARTH_RADIUS = 3958.75587
def in_range(distance)
maxlat = self.lat + rad2deg(distance / EARTH_RADIUS)
minlat = self.lat - rad2deg(distance / EARTH_RADIUS)
maxlon = self.lon + rad2deg(distance / EARTH_RADIUS / Math.cos(deg2rad(self.lat)))
minlon = self.lon - rad2deg(distance / EARTH_RADIUS / Math.cos(deg2rad(self.lat)))
locations = Location.where("lat > ? AND lat < ? AND lon > ? AND lon < ?",minlat,maxlat,minlon,maxlon).to_a
locations.each do |location|
if self.distance_to(location) > distance
locations.delete(location)
end
end
locations
end
def distance_to(location)
lat_source_rad = deg2rad(self.lat)
lat_destination_rad = deg2rad(location.lat)
lat_delta = deg2rad(location.lat - self.lat)
lon_delta = deg2rad(location.lon - self.lon)
a = Math::sin(lat_delta/2.0) * Math::sin(lat_delta/2.0) +
Math::cos(lat_source_rad) * Math::cos(lat_destination_rad) *
Math::sin(lon_delta/2.0) * Math::sin(lon_delta/2.0)
b = 2 * Math::atan2(Math::sqrt(a), Math::sqrt(1.0-a))
c = EARTH_RADIUS * b
end
private
def rad2deg(rad)
rad / Math::PI * 180.0
end
def deg2rad(deg)
deg / 180.0 * Math::PI
end
end
答案 0 :(得分:0)
我认为问题在于您没有发布的代码,特别是to_deg
和to_rad
方法。也许你在两种方法中的某处写过整数除法而不是浮点除法?请注意Ruby中的3/2==1
但3/2.0==1.5
。
class Location
RADIUS = 3958.75587
attr_accessor :lat, :lng
def initialize(lat, lng)
@lat = lat
@lng = lng
end
def ranges(distance)
maxlat = @lat + rad2deg(distance / RADIUS)
minlat = @lat - rad2deg(distance / RADIUS)
maxlng = @lng + rad2deg(distance / RADIUS / Math.cos(deg2rad(@lat)))
minlng = @lng - rad2deg(distance / RADIUS / Math.cos(deg2rad(@lat)))
[[minlat, maxlat], [minlng, maxlng]]
end
private
def rad2deg(rad)
rad / Math::PI * 180.0
end
def deg2rad(deg)
deg / 180.0 * Math::PI
end
end
l = Location.new(51.4663, -0.165543)
p l.ranges(10)
#=> [
# [51.32156821710003, 51.611031782899964],
# [-0.39786664062357346, 0.06678064062357347]
# ]