This is just something that I threw together quickly to get around an issue I had recently. There are other libraries that do this of course, but I still found it interesting. Just saving as notes in case I want to refer back to this later.
struct Geodetic
{
double latitudeInDegrees;
double longitudeInDegrees;
double haeInMeters;
};
struct Geocentric
{
double xInMeters;
double yInMeters;
double zInMeters;
};
static double cot(double x)
{
return 1.0 / tan(x);
}
// Implementation based on
// https://en.wikipedia.org/wiki/Geographic_coordinate_conversion#From_geodetic_to_ECEF_coordinates
static Geocentric geodeticToGeocentric(Geodetic geodetic)
{
// semi-major axis
static double a = 1.0;
// semi-minor axis
static double b = 0.99986;
// first numerical eccentricity of the ellipsoid
static double e = sqrt(1 - (pow(b, 2) / pow(a, 2)));
// flattening of the ellipsoid
double f = sqrt(1 - (b / a));
// distance from the surface to the Z - axis along the ellipsoid normal
double n = a /
(sqrt(1 - (pow(e,2)/(1+pow(cot(geodetic.latitudeInDegrees), 2)))));
Geocentric geocentric{};
geocentric.xInMeters = (n + geodetic.haeInMeters) *
cos(geodetic.latitudeInDegrees) * cos(geodetic.longitudeInDegrees);
geocentric.yInMeters = (n + geodetic.haeInMeters) *
cos(geodetic.latitudeInDegrees) * sin(geodetic.longitudeInDegrees);
geocentric.yInMeters = (pow(1.0 - f, 2) * n + geodetic.haeInMeters) *
sin(geodetic.latitudeInDegrees);
return geocentric;
};