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!