ProjectionWgs84 implements GeographicProjection { @SuppressWarnings({"UnnecessaryLocalVariable", "SuspiciousNameCombination"}) @Override public Position cartesianToGeographic(Globe globe, double x, double y, double z, Position result) { if (globe == null) { throw new IllegalArgumentException( Logger.logMessage(Logger.ERROR, "ProjectionWgs84", "cartesianToGeographic", "missingGlobe")); } if (result == null) { throw new IllegalArgumentException( Logger.logMessage(Logger.ERROR, "ProjectionWgs84", "cartesianToGeographic", "missingResult")); } double X = z; double Y = x; double Z = y; double XXpYY = X * X + Y * Y; double sqrtXXpYY = Math.sqrt(XXpYY); double a = globe.getEquatorialRadius(); double ra2 = 1 / (a * a); double e2 = globe.getEccentricitySquared(); double e4 = e2 * e2; double p = XXpYY * ra2; double q = Z * Z * (1 - e2) * ra2; double r = (p + q - e4) / 6; double h; double phi; double evoluteBorderTest = 8 * r * r * r + e4 * p * q; if (evoluteBorderTest > 0 || q != 0) { double u; if (evoluteBorderTest > 0) { double rad1 = Math.sqrt(evoluteBorderTest); double rad2 = Math.sqrt(e4 * p * q); if (evoluteBorderTest > 10 * e2) { double rad3 = Math.cbrt((rad1 + rad2) * (rad1 + rad2)); u = r + 0.5 * rad3 + 2 * r * r / rad3; } else { u = r + 0.5 * Math.cbrt((rad1 + rad2) * (rad1 + rad2)) + 0.5 * Math.cbrt( (rad1 - rad2) * (rad1 - rad2)); } } else { double rad1 = Math.sqrt(-evoluteBorderTest); double rad2 = Math.sqrt(-8 * r * r * r); double rad3 = Math.sqrt(e4 * p * q); double atan = 2 * Math.atan2(rad3, rad1 + rad2) / 3; u = -4 * r * Math.sin(atan) * Math.cos(Math.PI / 6 + atan); } double v = Math.sqrt(u * u + e4 * q); double w = e2 * (u + v - q) / (2 * v); double k = (u + v) / (Math.sqrt(w * w + u + v) + w); double D = k * sqrtXXpYY / (k + e2); double sqrtDDpZZ = Math.sqrt(D * D + Z * Z); h = (k + e2 - 1) * sqrtDDpZZ / k; phi = 2 * Math.atan2(Z, sqrtDDpZZ + D); } else { double rad1 = Math.sqrt(1 - e2); double rad2 = Math.sqrt(e2 - p); double e = Math.sqrt(e2); h = -a * rad1 * rad2 / e; phi = rad2 / (e * rad2 + rad1 * Math.sqrt(p)); } double lambda; double s2 = Math.sqrt(2); if ((s2 - 1) * Y < sqrtXXpYY + X) { lambda = 2 * Math.atan2(Y, sqrtXXpYY + X); } else if (sqrtXXpYY + Y < (s2 + 1) * X) { lambda = -Math.PI * 0.5 + 2 * Math.atan2(X, sqrtXXpYY - Y); } else { lambda = Math.PI * 0.5 - 2 * Math.atan2(X, sqrtXXpYY + Y); } result.latitude = Math.toDegrees(phi); result.longitude = Math.toDegrees(lambda); result.altitude = h; return result; } ProjectionWgs84(); @Override String getDisplayName(); @Override Vec3 geographicToCartesian(Globe globe, double latitude, double longitude, double altitude, Vec3 result); @Override Vec3 geographicToCartesianNormal(Globe globe, double latitude, double longitude, Vec3 result); @Override Matrix4 geographicToCartesianTransform(Globe globe, double latitude, double longitude, double altitude, Matrix4 result); @Override float[] geographicToCartesianGrid(Globe globe, Sector sector, int numLat, int numLon, float[] height, float verticalExaggeration,
                                             Vec3 origin, float[] result, int offset, int rowStride); float[] geographicToCartesianBorder(Globe globe, Sector sector, int numLat, int numLon, float height,
                                               Vec3 origin, float[] result); @SuppressWarnings({"UnnecessaryLocalVariable", "SuspiciousNameCombination"}) @Override Position cartesianToGeographic(Globe globe, double x, double y, double z, Position result); @Override Matrix4 cartesianToLocalTransform(Globe globe, double x, double y, double z, Matrix4 result); @Override boolean intersect(Globe globe, Line line, Vec3 result);  }
@Test public void testCartesianToGeographic() throws Exception { ProjectionWgs84 wgs84 = new ProjectionWgs84(); Map<String, Object[]> stations = getStations(); for (Map.Entry<String, Object[]> station : stations.entrySet()) { Position p = (Position) station.getValue()[0]; Vec3 v = (Vec3) station.getValue()[1]; Position result = new Position(); wgs84.cartesianToGeographic(globe, v.x, v.y, v.z, result); assertEquals(station.getKey(), Location.normalizeLatitude(p.latitude), result.latitude, 1e-6); assertEquals(station.getKey(), Location.normalizeLongitude(p.longitude), result.longitude, 1e-6); assertEquals(station.getKey(), p.altitude, result.altitude, 1e-3); } }