/// <summary>
/// Calculate the three dimensional geodetic measurement between two positions
/// measured in reference to a specified ellipsoid.
///
/// This calculation is performed by first computing a new ellipsoid by expanding or contracting
/// the reference ellipsoid such that the new ellipsoid passes through the average elevation
/// of the two positions. A geodetic curve across the new ellisoid is calculated. The
/// point-to-point distance is calculated as the hypotenuse of a right triangle where the length
/// of one side is the ellipsoidal distance and the other is the difference in elevation.
/// </summary>
/// <param name="refEllipsoid">reference ellipsoid to use</param>
/// <param name="start">starting position</param>
/// <param name="end">ending position</param>
/// <returns></returns>
public GeodeticMeasurement CalculateGeodeticMeasurement(Ellipsoid refEllipsoid, GlobalPosition start, GlobalPosition end)
{
// get the coordinates
GlobalCoordinates startCoords = start.Coordinates;
GlobalCoordinates endCoords = end.Coordinates;
// calculate elevation differences
double elev1 = start.Elevation;
double elev2 = end.Elevation;
double elev12 = (elev1 + elev2) / 2.0;
// calculate latitude differences
double phi1 = startCoords.Latitude.Radians;
double phi2 = endCoords.Latitude.Radians;
double phi12 = (phi1 + phi2) / 2.0;
// calculate a new ellipsoid to accommodate average elevation
double refA = refEllipsoid.SemiMajorAxis;
double f = refEllipsoid.Flattening;
double a = refA + elev12 * (1.0 + f * Math.Sin(phi12));
Ellipsoid ellipsoid = Ellipsoid.FromAAndF(a, f);
// calculate the curve at the average elevation
GeodeticCurve averageCurve = CalculateGeodeticCurve(ellipsoid, startCoords, endCoords);
// return the measurement
return(new GeodeticMeasurement(averageCurve, elev2 - elev1));
}