ProjectionWgs84 implements GeographicProjection { @Override public Matrix4 geographicToCartesianTransform(Globe globe, double latitude, double longitude, double altitude, Matrix4 result) { if (globe == null) { throw new IllegalArgumentException( Logger.logMessage(Logger.ERROR, "ProjectionWgs84", "geographicToCartesianTransform", "missingGlobe")); } if (result == null) { throw new IllegalArgumentException( Logger.logMessage(Logger.ERROR, "ProjectionWgs84", "geographicToCartesianTransform", "missingResult")); } double radLat = Math.toRadians(latitude); double radLon = Math.toRadians(longitude); double cosLat = Math.cos(radLat); double sinLat = Math.sin(radLat); double cosLon = Math.cos(radLon); double sinLon = Math.sin(radLon); double ec2 = globe.getEccentricitySquared(); double rpm = globe.getEquatorialRadius() / Math.sqrt(1.0 - ec2 * sinLat * sinLat); double eqr2 = globe.getEquatorialRadius() * globe.getEquatorialRadius(); double pol2 = globe.getPolarRadius() * globe.getPolarRadius(); double px = (rpm + altitude) * cosLat * sinLon; double py = (rpm * (1.0 - ec2) + altitude) * sinLat; double pz = (rpm + altitude) * cosLat * cosLon; double ux = cosLat * sinLon / eqr2; double uy = (1 - globe.getEccentricitySquared()) * sinLat / pol2; double uz = cosLat * cosLon / eqr2; double len = Math.sqrt(ux * ux + uy * uy + uz * uz); ux /= len; uy /= len; uz /= len; double nx = -sinLat * sinLon; double ny = cosLat; double nz = -sinLat * cosLon; len = Math.sqrt(nx * nx + ny * ny + nz * nz); nx /= len; ny /= len; nz /= len; double ex = ny * uz - nz * uy; double ey = nz * ux - nx * uz; double ez = nx * uy - ny * ux; nx = uy * ez - uz * ey; ny = uz * ex - ux * ez; nz = ux * ey - uy * ex; result.set( ex, nx, ux, px, ey, ny, uy, py, ez, nz, uz, pz, 0, 0, 0, 1); 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 testGeographicToCartesianTransform() throws Exception { ProjectionWgs84 wgs84 = new ProjectionWgs84(); double lat = 34.2; double lon = -119.2; double alt = 0; double a = globe.getEquatorialRadius(); double e2 = globe.getEccentricitySquared(); double sinLat = Math.sin(Math.toRadians(lat)); double Rn = a / Math.sqrt(1 - e2 * sinLat * sinLat); double delta = e2 * Rn * sinLat; Matrix4 expected = new Matrix4(); expected.multiplyByRotation(0, 1, 0, lon); expected.multiplyByTranslation(0, -delta, 0); expected.multiplyByRotation(1, 0, 0, -lat); expected.multiplyByTranslation(0, 0, Rn); Matrix4 result = wgs84.geographicToCartesianTransform(globe, lat, lon, alt, new Matrix4()); assertArrayEquals(expected.m, result.m, 1e-6); }