public static GeoPoint3 EcefToGeodetic(Vector3 ecef, GeoDatum datum)
        {
            const double precision2    = 1e-6;
            const int    maxIterations = 16;

            var norm = ecef.Norm;

            var phi    = Math.Atan2(ecef.Y, ecef.X);
            var theta0 = BasicMath.Asin(ecef.Z / ecef.Norm); // first approximation
            var h0     = norm - datum.Semiminor;             // first approximation

            var theta = theta0;
            var h     = h0;

            var error2 = double.PositiveInfinity;

            for (var i = 0; i < maxIterations && error2 > precision2; i++)
            {
                var ecefPrime = new GeoPoint3(theta, phi, h).ToEcef(datum);

                var normPrime   = ecefPrime.Norm;
                var thetaSphere = BasicMath.Asin(ecefPrime.Z / normPrime);
                var hSphere     = normPrime - datum.Semiminor;

                theta += theta0 - thetaSphere;
                h     += h0 - hSphere;

                error2 = Vector3.Distance2(ecef, ecefPrime);
            }

            return(new GeoPoint3(theta, phi, h));
        }