Try cleaning up ugly API around position angles
This commit is contained in:
parent
3b366b32af
commit
a50b317194
|
@ -65,12 +65,11 @@ Try reversing the coordinates, like:
|
|||
|
||||
.. testcode::
|
||||
|
||||
def rev(tup): return tup[1], tup[0]
|
||||
print(position_angle_of(rev(m.radec()), rev(s.radec())))
|
||||
print(position_angle_of(m.radec(), s.radec()))
|
||||
|
||||
.. testoutput::
|
||||
|
||||
77deg 31' 44.3"
|
||||
282deg 28' 15.7"
|
||||
|
||||
Drat, but this angle is backwards, because right ascension increases
|
||||
toward the east whereas the other angles, like azimuth, increase the
|
||||
|
|
|
@ -20,8 +20,5 @@ def test_position_angle_against_nasa_horizons():
|
|||
|
||||
a = position_angle_of(j.radec(epoch='date')[1::-1],
|
||||
i.radec(epoch='date')[1::-1])
|
||||
# TODO: eliminate the need for this reversal step
|
||||
from skyfield.api import tau
|
||||
a2 = Angle(radians=(-a.radians) % tau)
|
||||
print(abs(a2.degrees - 293.671), 0.002)
|
||||
assert abs(a2.degrees - 293.671) < 0.002
|
||||
|
||||
assert abs(a.degrees - 293.671) < 0.002
|
||||
|
|
|
@ -4,14 +4,30 @@ from numpy import arctan2, sin, cos, tan
|
|||
from skyfield.constants import tau
|
||||
from skyfield.units import Angle
|
||||
|
||||
def position_angle_of(latlon1, latlon2):
|
||||
def position_angle_of(anglepair1, anglepair2):
|
||||
"""Return the position angle of one position with respect to another.
|
||||
|
||||
Both arguments should be a tuple of :class:`~skyfield.units.Angle`
|
||||
objects whose first item is latitude-like and whose second item is
|
||||
longitude-like. The position angle returned will be 0 degrees if
|
||||
position #2 is directly north of position #1 on the celestial
|
||||
sphere, 90 degrees if east, 180 if south, and 270 if west.
|
||||
Each argument should be a tuple whose first two items are
|
||||
:class:`~skyfield.units.Angle` objects, like the tuples returned by
|
||||
:meth:`~skyfield.positionlib.ICRF.radec()`,
|
||||
:meth:`~skyfield.positionlib.ICRF.ecliptic_latlon()`, and
|
||||
:meth:`~skyfield.positionlib.Apparent.altaz()`.
|
||||
|
||||
If one of the two angle items is signed (if its ``.signed``
|
||||
attribute is true), then that angle is used as the latitude and the
|
||||
other as the longitude; otherwise the first argument is assumed to
|
||||
be the latitude.
|
||||
|
||||
If the longitude has a ``.preference`` attribute of ``'hours'``, it
|
||||
is assumed to be a right ascension which is positive towards the
|
||||
east. The position angle returned will be 0 degrees if position #2
|
||||
is directly north of position #1 on the celestial sphere, 90 degrees
|
||||
if east, 180 if south, and 270 if west.
|
||||
|
||||
Otherwise, the longitude is assumed to be azimuth, which measures
|
||||
north to east around the horizon. The position angle returned will
|
||||
be 0 degrees if position #2 is directly above position #1 in the
|
||||
sky, 90 degrees to its left, 180 if below, and 270 if to the right.
|
||||
|
||||
>>> from skyfield.trigonometry import position_angle_of
|
||||
>>> from skyfield.units import Angle
|
||||
|
@ -20,19 +36,21 @@ def position_angle_of(latlon1, latlon2):
|
|||
>>> position_angle_of(a, b)
|
||||
<Angle 315deg 00' 15.7">
|
||||
|
||||
The tuples provided as arguments can have more than 2 items; any
|
||||
extra items are ignored. This means you can pass in the output of
|
||||
routines like :meth:`~skyfield.positionlib.ICRF.ecliptic_latlon()`
|
||||
and :meth:`~skyfield.positionlib.Apparent.altaz()` as arguments.
|
||||
Their angles will be used, but the third item of each tuple, the
|
||||
distance, will be cleanly ignored.
|
||||
|
||||
"""
|
||||
lat1 = latlon1[0].radians
|
||||
lon1 = latlon1[1].radians
|
||||
lat2 = latlon2[0].radians
|
||||
lon2 = latlon2[1].radians
|
||||
lat1, lon1 = anglepair1[0], anglepair1[1]
|
||||
if lon1.signed:
|
||||
lat1, lon1 = lon1, lat1
|
||||
|
||||
lat2, lon2 = anglepair2[0], anglepair2[1]
|
||||
if lon2.signed:
|
||||
lat2, lon2 = lon2, lat2
|
||||
|
||||
lat1 = lat1.radians
|
||||
lon1 = lon1.radians if lon1.preference == 'hours' else -lon1.radians
|
||||
lat2 = lat2.radians
|
||||
lon2 = lon2.radians if lon2.preference == 'hours' else -lon2.radians
|
||||
|
||||
return Angle(radians=arctan2(
|
||||
sin(lon1 - lon2),
|
||||
sin(lon2 - lon1),
|
||||
cos(lat1) * tan(lat2) - sin(lat1) * cos(lon2 - lon1),
|
||||
) % tau)
|
||||
|
|
Loading…
Reference in New Issue