package org.osm2world.core.map_data.creation; import static java.lang.Math.PI; import static java.lang.Math.atan; import static java.lang.Math.exp; import static java.lang.Math.log; import static java.lang.Math.pow; import static java.lang.Math.sin; import static java.lang.Math.sqrt; import static java.lang.Math.tan; import static java.lang.Math.toDegrees; import static java.lang.Math.toRadians; final class MercatorProjection { private MercatorProjection() { } private static final double R_MAJOR = 6378137.0; private static final double R_MINOR = 6356752.3142; private static final double RATIO = R_MINOR / R_MAJOR; private static final double ECCENT = sqrt(1.0 - (RATIO * RATIO)); private static final double COM = 0.5 * ECCENT; public static final double EARTH_CIRCUMFERENCE = 40075016.686; /** * Calculate earth circumference at given latitude. */ public static double earthCircumference(double latitude) { return EARTH_CIRCUMFERENCE * Math.cos(toRadians(latitude)); } /** * Convert longitude to Mercator projection (range [0..1]). */ public static double lonToX(double longitude) { return (longitude + 180.0) / 360.0; } /** * Convert from Mercator projection (range [0..1]) to longitude. */ public static double xToLon(double x) { return 360.0 * (x - 0.5); } /** * Convert latitude to Mercator projection (range [0..1]). */ public static double latToY(double latitude) { double sinLat = Math.sin(toRadians(latitude)); return Math.log((1.0 + sinLat) / (1.0 - sinLat)) / (4.0 * Math.PI) + 0.5; } /** * Convert from Mercator projection (range [0..1]) to latitude. */ public static double yToLat(double y) { return 360.0 * Math.atan(Math.exp((y - 0.5) * (2.0 * Math.PI))) / Math.PI - 90.0; } // This is for the Elliptical Mercator version public static double latToYElliptical(double lat) { lat = Math.min(89.5, Math.max(lat, -89.5)); double phi = toRadians(lat); double sinphi = sin(phi); double con = ECCENT * sinphi; con = pow(((1.0 - con) / (1.0 + con)), COM); double ts = tan(0.5 * ((PI * 0.5) - phi)) / con; return 0 - R_MAJOR * log(ts); } // This is for the Elliptical Mercator version public static double yToLatElliptical(double y) { double ts = exp(-y / R_MAJOR); double phi = PI / 2 - 2 * atan(ts); double dphi = 1.0; int i = 0; while ((Math.abs(dphi) > 0.000000001) && (i < 15)) { double con = ECCENT * sin(phi); dphi = PI / 2 - 2 * atan(ts * Math.pow((1.0 - con) / (1.0 + con), COM)) - phi; phi += dphi; i++; } return toDegrees(phi); } }