Source code for rubin_scheduler.utils.bearing
__all__ = ("bearing", "dest_latlon", "point_to_line_distance")
import numpy as np
from .coordinate_transformations import _angular_separation
[docs]
def bearing(lon1, lat1, lon2, lat2):
"""Bearing between two points
all radians
"""
delta_l = lon2 - lon1
X = np.cos(lat2) * np.sin(delta_l)
Y = np.cos(lat1) * np.sin(lat2) - np.sin(lat1) * np.cos(lat2) * np.cos(delta_l)
theta = np.arctan2(X, Y)
return theta
[docs]
def dest_latlon(dist, bearing, lat1, lon1):
"""Destination lat and lon given a distance, bearing and starting position
all radians
"""
lat2 = np.arcsin(np.sin(lat1) * np.cos(dist) + np.cos(lat1) * np.sin(dist) * np.cos(bearing))
lon2 = lon1 + np.arctan2(
np.sin(bearing) * np.sin(dist) * np.cos(lat1),
np.cos(dist) - np.sin(lat1) * np.sin(lat2),
)
return lat2, lon2
[docs]
def point_to_line_distance(lon1, lat1, lon2, lat2, lon3, lat3):
"""All radians
points 1 and 2 define an arc segment,
this finds the distance of point 3 to the arc segment.
"""
result = lon1 * 0
needed = np.ones(result.size, dtype=bool)
bear12 = bearing(lon1, lat1, lon2, lat2)
bear13 = bearing(lon1, lat1, lon3, lat3)
dis13 = _angular_separation(lon1, lat1, lon3, lat3)
# Is relative bearing obtuse?
diff = np.abs(bear13 - bear12)
if np.size(diff) == 1:
if diff > np.pi:
diff = 2 * np.pi - diff
if diff > (np.pi / 2):
return dis13
else:
over = np.where(diff > np.pi)
diff[over] = 2 * np.pi - diff[over]
solved = np.where(diff > (np.pi / 2))[0]
result[solved] = dis13[solved]
needed[solved] = False
# Find the cross-track distance.
dxt = np.arcsin(np.sin(dis13) * np.sin(bear13 - bear12))
# Is p4 beyond the arc?
dis12 = _angular_separation(lon1, lat1, lon2, lat2)
dis14 = np.arccos(np.cos(dis13) / np.cos(dxt))
if np.size(dis14) == 1:
if dis14 > dis12:
return _angular_separation(lon2, lat2, lon3, lat3)
else:
solved = np.where((dis14 > dis12) & needed)[0]
result[solved] = _angular_separation(lon2[solved], lat2[solved], lon3[solved], lat3[solved])
needed[solved] = False
if np.size(lon1) == 1:
return np.abs(dxt)
else:
result[needed] = np.abs(dxt[needed])
return result