NavList:
A Community Devoted to the Preservation and Practice of Celestial Navigation and Other Methods of Traditional Wayfinding
Re: Unexpected USNO height correction precepts
From: Paul Hirose
Date: 2018 Dec 21, 12:51 -0800
From: Paul Hirose
Date: 2018 Dec 21, 12:51 -0800
On 2018-12-21 10:15, Mehmet Guzey wrote:
> By the way, how does your "SofaJpl.Vector" function works? does it just
scale a vector in a specified angle and range?
There are several constructors for the SofaJpl Vector class. The
constructor in the center of light computation has three parameters: a
Vector object and two double precision values. It creates a new Vector
object at the given position angle and separation angle from the old
Vector. The algorithm is very accurate, whether the separation angle is
many degrees or a microsecond of arc.
The first thing you need is the phase angle: the angle between a vector
from Venus (for example) to the Sun, and from Venus to the observer. (If
phase angle = 0, Venus is fully illuminated.) It's actually easier to
compute the inverse vectors: a heliocentric vector to Venus ("helioVec"
in my code) and a topocentric vector to Venus ("bodyVec").
SofaJpl has a SeparationAngle() function which returns the angle
(radians) between two vectors:
double phaseAngle = bodyVec.SeparationAngle(helioVec);
The other illumination variable is position angle: the "azimuth" on the
celestial sphere from Venus to the Sun. The Vector class has a function
for that too:
double positionAngle = bodyVec.PositionAngle(sunVec);
Semidiameter of a body is computed with a function in the SofaJpl Angle
class. Parameters are distance to the body and its radius, in the same
unit of measure. To obtain distance, apply the Modulus() function to the
Venus vector. For radius, use the "Radius" property of the body. (For
the nine planets, Moon, and Sun, this is set automatically to the
adopted IAU radius. The radius for a star defaults to zero.)
double sd = SofaJpl.Angle.Semidiameter(bodyVec.Modulus(), body.Radius);
Now apply George Huxtable's formula for the offset between the center of
a body and the center of light:
double sinHalfPhi = Math.Sin(phaseAngle / 2.0);
double offset = 8.0 / (3.0 * Math.PI) * sinHalfPhi * sinHalfPhi * sd;
Finally, return a Vector to the center of light:
return new SofaJpl.Vector(bodyVec, positionAngle, offset);
Note: the new vector has modulus = 1. However, the SofaJpl Vector class
defines multiplication by a scalar with the * operator (which is
commutative), so the original modulus can be restored like this:
return new SofaJpl.Vector(bodyVec, positionAngle, offset) *
bodyVec.Modulus();
Of course this isn't necessary if only the direction to the center of
light is important. But my program also displays the distance to the
body, so I have to make the change. Lucky someone asked the question!






