これを行うサンプルコードを次に示します。このアルゴリズムはすべてのケースで機能し、常に 2 つの場所の間の最短の大圏経路に従います。数学は基本的に Drew Hall の回答と同じですが、percent_traveled を使用し、地球の半径を無視しています。
簡単にするために、このコードでは緯度と経度がラジアンで格納されていることを前提としています。
def get_new_location(current_location, target_location, percent_traveled):
# convert locations into cartiesian co-ordinates
current_vector = location_to_vector(current_location)
target_vector = location_to_vector(target_location)
# compute the angle between current_vector and target_vector
complete_angle = acos(vector_dot_product(current_vector, target_vector))
# determine the current partial angle, based on percent_traveled
partial_angle = percent_traveled*complete_angle
# compute a temporary vector to simplify calculation
temporary_vector = vector_cross_product(current_vector, target_vector)
temporary_vector = vector_cross_product(current_vector, temporary_vector)
# calculate new_vector
scalar_one = cos(partial_angle)
scalar_two = -sin(partial_angle)/sin(complete_angle)
vector_one = vector_multiply_by_scalar(scalar_one, current_vector)
vector_two = vector_multiply_by_scalar(scalar_two, temporary_vector)
new_vector = vector_sum(vector_one, vector_two)
# convert new_vector back into latitude & longitude and return
new_location = vector_to_location(new_vector)
return new_location
緯度と経度からデカルト座標に変換する関数:
def location_to_vector(location)
vector.x = cos(location.lat)*sin(location.lon)
vector.y = sin(location.lat)
vector.z = cos(location.lat)*cos(location.lon)
return vector
デカルト座標から緯度と経度に変換する関数:
def vector_to_location(vector)
location.lat = asin(vector.y)
if (vector.z == 0):
if (vector.x < 0):
location.lon = -pi/2
else:
location.lon = pi/2
else:
if (vector.z < 0):
if (vector.x < 0):
location.lon = atan(vector.x/vector.z) - pi
else:
location.lon = pi - atan(-vector.x/vector.z)
else:
if (vector.x < 0):
location.lon = -atan(-vector.x/vector.z)
else:
location.lon = atan(vector.x/vector.z)
return location
2 つのベクトルの内積を計算する関数:
def vector_dot_product(A, B):
dot_product = A.x*B.x + A.y*B.y + A.z*B.z
return dot_product
2 つのベクトルの外積を計算する関数:
def vector_cross_product(A, B):
cross_product.x = A.y*B.z - A.z*B.y
cross_product.y = A.z*B.x - A.x*B.z
cross_product.z = A.x*B.y - A.y*B.x
return cross_product
ベクトルをスカラーで乗算する関数:
def vector_multiply_by_scalar(scalar, vector)
scaled_vector.x = scalar*vector.x
scaled_vector.y = scalar*vector.y
scaled_vector.z = scalar*vector.z
return scaled_vector
2 つのベクトルの和を計算する関数:
def vector_sum(A, B)
sum.x = A.x + B.x
sum.y = A.y + B.y
sum.z = A.z + B.z
return sum