我正在解决一个
geospatial
问题,其中我有两个点由地图上的纬度和经度定义,我需要根据这些点计算第三个点的位置。这是场景:
给出 A 点和 B 点,每个点由纬度和经度定义。 我有一个距离(以米或公里为单位)和一个角度(以度为单位)。 我想要实现的是计算C点的位置。C点应该位于距B点给定的距离处,并且相对于从A点到B点的直线处于指定的角度。
我尝试使用这个:
但是当我将垂直线延伸 105 度时,我得到 75 度,90 度是 64 等..
from geopy import Point
from pyproj import Proj, transform
from geopy.distance import Geodesic, geodesic
import math
def extend_perpendicular_line(pointA, pointB, distance,direction = 1,angle=90):
# Calculate the bearing from pointA to pointB
bearing = calculate_bearing(pointA, pointB)
# Calculate the bearing that is perpendicular to the initial bearing
perp_bearing = (bearing + angle*direction) % 360
# Create a geodesic line from pointB and extend it by the given distance at the perpendicular bearing
extended_point = geodesic().destination(Point(pointB.latitude, pointB.longitude), perp_bearing, distance)
anga = calculate_angle(pointA,pointB,extended_point)
return extended_point
def calculate_bearing(pointA, pointB):
lat1, lon1 = pointA.latitude, pointA.longitude
lat2, lon2 = pointB.latitude, pointB.longitude
diff_lon = math.radians(lon2 - lon1)
lat1 = math.radians(lat1)
lat2 = math.radians(lat2)
x = math.sin(diff_lon) * math.cos(lat2)
y = math.cos(lat1) * math.sin(lat2) - (math.sin(lat1) * math.cos(lat2) * math.cos(diff_lon))
initial_bearing = math.atan2(x, y)
# Normalize the bearing
initial_bearing = math.degrees(initial_bearing)
bearing = (initial_bearing + 360) % 360
return bearing
def calculate_angle(pointA, pointB, pointC):
# Calculate the sides of the triangle
a = calculate_distance(pointB, pointC)
b = calculate_distance(pointA, pointC)
c = calculate_distance(pointA, pointB)
# Law of cosines: c^2 = a^2 + b^2 - 2ab * cos(C)
# Solve for cos(C)
cos_B = (a ** 2 + c ** 2 - b ** 2) / (2 * a * c)
angle = math.degrees(math.acos(cos_B))
return angle
def calculate_distance(pointA, pointB):
# Haversine formula to calculate distance between two lat/lon points
coords_1 = (pointA.latitude, pointA.longitude)
coords_2 = (pointB.latitude, pointB.longitude)
return geodesic(coords_1, coords_2).km
pointA = Point(46.9540700,7.4474400)
pointB = Point(46.9560700,7.4494400)
extend_perpendicular_line(pointA,pointB,0.25,1,105)
正如你所提出的问题,从什么点计算线AB和C之间的角度(AB到AC或AB到BC)有点含糊。这里有几个图表显示了这种歧义。
由于第一个示例很少有唯一的解决方案,因此我在这里提供了第二个示例的解决方案,主要使用 pyproj 中内置的函数。
import pyproj
def extend_angled_line(point_a, point_b, distance_from_b, angle, geo=None):
geo = geo or pyproj.Geod(ellps='WGS84')
bearing_a_to_b, _, d = geo.inv(point_a[1], point_a[0], point_b[1], point_b[0]) # deg, deg, m
new_bearing = bearing_a_to_b + angle
c_lon, c_lat, _ = geo.fwd(*point_b, new_bearing, distance_from_b)
return c_lat, c_lon
def _main():
a = (45, 45)
b = (45.1, 45.1)
c = extend_angled_line(a, b, 1000, 180)
print(c)
if __name__ == '__main__':
_main()