Skip to content

Instantly share code, notes, and snippets.

@parrot-studio
Created September 13, 2013 00:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save parrot-studio/6545702 to your computer and use it in GitHub Desktop.
Save parrot-studio/6545702 to your computer and use it in GitHub Desktop.
座標系の計算モジュール 2点間の距離算出と、ある地点からNメートルの範囲にある緯度/経度範囲の算出 (ほとんど他の方のBlogのパクリであまりよろしくない) 実際は方形で大雑把に絞り込んだ後、具体的な各地点間の距離を算出し、 「半径Nメートル以内にあるポイント」を絞り込んでいる
# coding: utf-8
module Geolocation
def distance_to(lat, lon, mode = nil)
return unless (lat && lon)
return unless (self.respond_to?(:latitude) && self.respond_to?(:longitude))
earth_distance(self.latitude, self.longitude, lat, lon, mode)
end
def distance_between(point, mode = nil)
return unless point
return unless (self.respond_to?(:latitude) && self.respond_to?(:longitude))
return unless (point.respond_to?(:latitude) && point.respond_to?(:longitude))
earth_distance(self.latitude, self.longitude, point.latitude, point.longitude, mode)
end
module_function
def deg2rad(r)
r.to_f * (Math::PI / 180.0)
end
# 二点間座標距離
# ヒュベニの公式 see : yamadarake.jp/trdi/report000001.html
def earth_distance(lat1, lon1, lat2, lon2, mode = nil)
return unless (lat1 && lon1 && lat2 && lon2)
mode ||= :gps
case mode.to_sym
when :world
a = 6378137.0
e2 = 0.00669438002301188
mnum = 6335439.32708317
when :japan
a = 6377397.155
e2 = 0.00667436061028297
mnum = 6334832.10663254
else # => :gps
a = 6378137.0
e2 = 0.00669437999019758
mnum = 6335439.32729246
end
my = deg2rad((lat1 + lat2) / 2.0)
dy = deg2rad(lat1 - lat2)
dx = deg2rad(lon1 - lon2)
sin = Math.sin(my)
w = Math.sqrt(1.0 - e2 * sin * sin)
m = mnum / (w * w * w)
n = a / w
dym = dy * m
dxncos = dx * n * Math.cos(my)
Math.sqrt(dym * dym + dxncos * dxncos)
end
# ある地点からnメートルの大雑把な緯度範囲
# 緯度差は経度と関係ないので一定とみなして良い
# 地球の長さ(er):6378137.0m
# rad_dis = deg2rad(er)
# see : mononofu.hatenablog.com/entry/20090324/1237894846
def latitude_range(lat, range)
return unless (lat && range)
rad_dis = 111319.49079327357 # 1度あたりの長さ(メートル)
diff = range.to_f / rad_dis # 長さを度に変換
((lat - diff)..(lat + diff))
end
# ある地点からnメートルの大雑把な経度範囲
# 緯度によって円周が異なるため単純ではない
# 地球の長さ(er):6378137.0m
# 円周 = deg2rad(er * cos(deg2rad(lat)))
# see : mononofu.hatenablog.com/entry/20090324/1237894846
def longitude_range(lat, lon, range)
return unless (lat && lon && range)
rad_dis = deg2rad(6378137.0 * Math.cos(deg2rad(lat))) # 1度あたりの長さ(メートル)
diff = range.to_f / rad_dis # 長さを度に変換
((lon - diff)..(lon + diff))
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment