brew install inetutils
月度归档: 2022 年 1 月
老家一隅
计算两点间的距离
from great_circle_calculator.__conversion import _point_to_radians, _point_to_degrees, _radians_to_degrees, \
_degrees_to_radians
from great_circle_calculator.__error_checking import _error_check_point
from great_circle_calculator._constants import *
def distance_between_points(p1, p2, unit='meters', haversine=True):
""" This function computes the distance between two points in the unit given in the unit parameter. It will
calculate the distance using the haversine unless the user specifies haversine to be False. Then law of cosines
will be used
:param p1: tuple point of (lon, lat)
:param p2: tuple point of (lon, lat)
:param unit: unit of measurement. List can be found in constants.eligible_units
:param haversine: True (default) uses haversine distance, False uses law of cosines
:return: Distance between p1 and p2 in the units specified.
"""
lon1, lat1 = _point_to_radians(_error_check_point(p1))
lon2, lat2 = _point_to_radians(_error_check_point(p2))
r_earth = getattr(radius_earth, unit, 'meters')
if haversine:
# Haversine
d_lat, d_lon = lat2 - lat1, lon2 - lon1
a = sin(d_lat / 2) * sin(d_lat / 2) + cos(lat1) * cos(lat2) * sin(d_lon / 2) * sin(d_lon / 2)
c = 2 * atan2(sqrt(a), sqrt((1 - a)))
dist = r_earth * c
return dist
# Spherical Law Of Cosines
dist = acos(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(lon2 - lon1)) * r_earth
return dist
def bearing_at_p1(p1, p2):
""" This function computes the bearing (i.e. course) at p1 given a destination of p2. Use in conjunction with
midpoint(*) and intermediate_point(*) to find the course along the route. Use bearing_at_p2(*) to find the bearing
at the endpoint
:param p1: tuple point of (lon, lat)
:param p2: tuple point of (lon, lat)
:return: Course, in degrees
"""
lon1, lat1 = _point_to_radians(_error_check_point(p1))
lon2, lat2 = _point_to_radians(_error_check_point(p2))
x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lon2 - lon1)
y = sin(lon2 - lon1) * cos(lat2)
course = atan2(y, x)
return _radians_to_degrees(course)
def bearing_at_p2(p1, p2):
""" This function computes the bearing (i.e. course) at p2 given a starting point of p1. Use in conjunction with
midpoint(*) and intermediate_point(*) to find the course along the route. Use bearing_at_p1(*) to find the bearing
at the endpoint
:param p1: tuple point of (lon, lat)
:param p2: tuple point of (lon, lat)
:return: Course, in degrees
"""
return (bearing_at_p1(p2, p1) + 180) % 360
def midpoint(p1, p2):
""" This is the half-way point along a great circle path between the two points.
:param p1: tuple point of (lon, lat)
:param p2: tuple point of (lon, lat)
:return: point (lon, lat)
"""
lon1, lat1 = _point_to_radians(_error_check_point(p1))
lon2, lat2 = _point_to_radians(_error_check_point(p2))
b_x = cos(lat2) * cos(lon2 - lon1)
b_y = cos(lat2) * sin(lon2 - lon1)
lat3 = atan2(sin(lat1) + sin(lat2), sqrt((cos(lat1) + b_x) * (cos(lat1) + b_x) + b_y * b_y))
lon3 = lon1 + atan2(b_y, cos(lat1) + b_x)
lat3 = _radians_to_degrees(lat3)
lon3 = (_radians_to_degrees(lon3) + 540) % 360 - 180
p3 = (lon3, lat3)
return p3
def intermediate_point(p1, p2, fraction=0.5):
""" This function calculates the intermediate point along the course laid out by p1 to p2. fraction is the fraction
of the distance between p1 and p2, where 0 is p1, 0.5 is equivalent to midpoint(*), and 1 is p2.
:param p1: tuple point of (lon, lat)
:param p2: tuple point of (lon, lat)
:param fraction: the fraction of the distance along the path.
:return: point (lon, lat)
"""
lon1, lat1 = _point_to_radians(_error_check_point(p1))
lon2, lat2 = _point_to_radians(_error_check_point(p2))
delta = distance_between_points(p1, p2) / radius_earth.meters
a = sin((1 - fraction) * delta) / sin(delta)
b = sin(fraction * delta) / sin(delta)
x = a * cos(lat1) * cos(lon1) + b * cos(lat2) * cos(lon2)
y = a * cos(lat1) * sin(lon1) + b * cos(lat2) * sin(lon2)
z = a * sin(lat1) + b * sin(lat2)
lat3 = atan2(z, sqrt(x * x + y * y))
lon3 = atan2(y, x)
return _point_to_degrees((lon3, lat3))
def point_given_start_and_bearing(p1, course, distance, unit='meters'):
""" Given a start point, initial bearing, and distance, this will calculate the destination point and final
bearing travelling along a (shortest distance) great circle arc.
:param p1: tuple point of (lon, lat)
:param course: Course, in degrees
:param distance: a length in unit
:param unit: unit of measurement. List can be found in constants.eligible_units
:return: point (lon, lat)
"""
lon1, lat1 = _point_to_radians(_error_check_point(p1))
brng = _degrees_to_radians(course)
r_earth = getattr(radius_earth, unit, 'meters')
delta = distance / r_earth
lat2 = asin(sin(lat1) * cos(delta) + cos(lat1) * sin(delta) * cos(brng))
lon2 = lon1 + atan2(sin(brng) * sin(delta) * cos(lat1), cos(delta) - sin(lat1) * sin(lat2))
lon2 = (_radians_to_degrees(lon2) + 540) % 360 - 180
p2 = (lon2, _radians_to_degrees(lat2))
return p2