Created
September 13, 2013 00:49
-
-
Save parrot-studio/6545702 to your computer and use it in GitHub Desktop.
座標系の計算モジュール
2点間の距離算出と、ある地点からNメートルの範囲にある緯度/経度範囲の算出
(ほとんど他の方のBlogのパクリであまりよろしくない) 実際は方形で大雑把に絞り込んだ後、具体的な各地点間の距離を算出し、
「半径Nメートル以内にあるポイント」を絞り込んでいる
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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