Djangoアプリに登録しているユーザーがいますが、郵便番号に基づいて2人のユーザー間の距離を地理的に把握し、それに基づいてリストを並べ替えることができます。この機能はDjangoに組み込まれていないと思います。私はいくつかのオプションを探していて、geodjangoに出くわしましたが、それは私のニーズが何であるかにはやり過ぎかもしれないようです。
4 に答える
これは、@ Sven Marnachによる(現在受け入れられている)回答に投稿されたコードに対する大きなコメントです。
私が編集したインデント付きのzipプロジェクトWebサイトの元のコード:
from math import *
def calcDist(lat_A, long_A, lat_B, long_B):
distance = (sin(radians(lat_A)) *
sin(radians(lat_B)) +
cos(radians(lat_A)) *
cos(radians(lat_B)) *
cos(radians(long_A - long_B)))
distance = (degrees(acos(distance))) * 69.09
return distance
Svenによって投稿されたコード:
from math import sin, cos, radians, degrees
def calc_dist(lat_a, long_a, lat_b, long_b):
lat_a = radians(lat_a)
lat_b = radians(lat_b)
distance = (sin(lat_a) * sin(lat_b) +
cos(lat_a) * cos(lat_b) * cos(long_a - long_b))
return degrees(acos(distance)) * 69.09
問題1:実行されない:インポートする必要がありますacos
問題2:間違った答え:最後から2番目の行で経度の差をラジアンに変換する必要があります
問題3:変数名「distance」は極端な誤称です。その量は、実際には、地球の中心から入力ポイントまでの2本の線の間の角度のcosです。「cos_x」に変更します
問題4:角度xを度に変換する必要はありません。選択した単位(km、nm、または「法定マイル」)でxに地球半径を掛けるだけです。
それをすべて修正すると、次のようになります。
from math import sin, cos, radians, acos
# http://en.wikipedia.org/wiki/Earth_radius
# """For Earth, the mean radius is 6,371.009 km (˜3,958.761 mi; ˜3,440.069 nmi)"""
EARTH_RADIUS_IN_MILES = 3958.761
def calc_dist_fixed(lat_a, long_a, lat_b, long_b):
"""all angles in degrees, result in miles"""
lat_a = radians(lat_a)
lat_b = radians(lat_b)
delta_long = radians(long_a - long_b)
cos_x = (
sin(lat_a) * sin(lat_b) +
cos(lat_a) * cos(lat_b) * cos(delta_long)
)
return acos(cos_x) * EARTH_RADIUS_IN_MILES
注:問題1と2を修正した後、これは通常実装される「余弦定理」です。「2つの米国の郵便番号間の距離」などのアプリケーションでは問題ありません。
警告1:正面玄関から通りまでのような短い距離では正確ではないため、2つのポイントが同一である場合、ゼロ以外の距離を指定したり、例外(cos_x> 1.0)を発生させたりする可能性があります。この状況は特別な場合があります。
警告2:2つのポイントが対蹠である場合(直線パスが地球の中心を通過する場合)、例外が発生する可能性があります(cos_x <-1.0)。それを心配している人は、acos(cos_x)を実行する前にcos_xをチェックできます。
例:
SFO(37.676、-122.433)からNYC(40.733、-73.917)
calcDist-> 2570.7758043869976
calc_dist-> 5038.599866130089
calc_dist_fixed-> 2570.9028268899356
米国政府のウェブサイト(http://www.nhc.noaa.gov/gccalc.shtml)-> 2569
このウェブサイト(http://www.timeanddate.com/worldclock/distanceresult.html?p1=179&p2=224)から、SFOとNYCの座標を取得しました-> 2577
tcarobruceの提案に続いて、これが答えとしての私の上記のコメントです:
郵便番号データベースプロジェクトには、SQLまたはCSVとして、米国の郵便番号の緯度と経度のデータベースがあります。彼らはまた、距離計算のために次のコードを提供します(私が編集したslighlty):
from math import sin, cos, radians, degrees, acos
def calc_dist(lat_a, long_a, lat_b, long_b):
lat_a = radians(lat_a)
lat_b = radians(lat_b)
long_diff = radians(long_a - long_b)
distance = (sin(lat_a) * sin(lat_b) +
cos(lat_a) * cos(lat_b) * cos(long_diff))
return degrees(acos(distance)) * 69.09
結果は法定マイルで示されることに注意してください。
編集:ジョン・マチンによる訂正。
http://code.google.com/apis/maps/documentation/directions/
あなたはそれぞれの場所のための道順を行うことができます。合計距離が表示されます。APIはJSONを出力しているようです。サーバー側で回答を解析するか、JavaScriptで距離を計算することができます。
別の簡単な方法:
以下の関数は、郵便番号から緯度と経度を計算した後、2つの場所の間の距離を返します。
lat1
、long1
は最初の場所の緯度と経度です。
lat2
、long2
は2番目の場所の緯度と経度です。
from decimal import Decimal
from math import sin, cos, sqrt, atan2, radians
def distance(lat1, lat2, long1, long2):
r = 6373.0
lat1 = radians(lat1)
lat2 = radians(lat2)
long1 = radians(long1)
long2 = radians(long2)
d_lat = lat2 - lat1
d_long = long2 - long1
a = (sin(d_lat/2))**2 + cos(lat1) * cos(lat2) * (sin(d_long/2))**2
c = 2 * atan2(sqrt(a), sqrt(1-a))
# distance in miles
dis = r * c
# distance in KM
dis /= 1.609344
return dis