9

Djangoアプリに登録しているユーザーがいますが、郵便番号に基づいて2人のユーザー間の距離を地理的に把握し、それに基づいてリストを並べ替えることができます。この機能はDjangoに組み込まれていないと思います。私はいくつかのオプションを探していて、geodjangoに出くわしましたが、それは私のニーズが何であるかにはやり過ぎかもしれないようです。

4

4 に答える 4

18

これは、@ 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

于 2011-01-17T23:02:55.393 に答える
6

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

結果は法定マイルで示されることに注意してください。

編集:ジョン・マチンによる訂正。

于 2011-01-17T18:49:53.183 に答える
0

http://code.google.com/apis/maps/documentation/directions/

あなたはそれぞれの場所のための道順を行うことができます。合計距離が表示されます。APIはJSONを出力しているようです。サーバー側で回答を解析するか、JavaScriptで距離を計算することができます。

于 2011-01-17T17:48:58.303 に答える
0

別の簡単な方法:

以下の関数は、郵便番号から緯度と経度を計算した後、2つの場所の間の距離を返します。

lat1long1は最初の場所の緯度と経度です。

lat2long2は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
于 2016-04-06T13:56:21.807 に答える