I'm trying to convert a lat/long point into a 2d point so that I can display it on an image of the world-which is a mercator projection.
I've seen various ways of doing this and a few questions on stack overflow-I've tried out the different code snippets and although I get the correct longitude to pixel, the latitude is always off-seems to be getting more reasonable though.
I need the formula to take into account the image size, width etc.
I've tried this piece of code:
double minLat = -85.05112878;
double minLong = -180;
double maxLat = 85.05112878;
double maxLong = 180;
// Map image size (in points)
double mapHeight = 768.0;
double mapWidth = 991.0;
// Determine the map scale (points per degree)
double xScale = mapWidth/ (maxLong - minLong);
double yScale = mapHeight / (maxLat - minLat);
// position of map image for point
double x = (lon - minLong) * xScale;
double y = - (lat + minLat) * yScale;
System.out.println("final coords: " + x + " " + y);
The latitude seems to be off by about 30px in the example I'm trying. Any help or advice?
Update
Based on this question:Lat/lon to xy
I've tried to use the code provided but I'm still having some problems with latitude conversion, longitude is fine.
int mapWidth = 991;
int mapHeight = 768;
double mapLonLeft = -180;
double mapLonRight = 180;
double mapLonDelta = mapLonRight - mapLonLeft;
double mapLatBottom = -85.05112878;
double mapLatBottomDegree = mapLatBottom * Math.PI / 180;
double worldMapWidth = ((mapWidth / mapLonDelta) * 360) / (2 * Math.PI);
double mapOffsetY = (worldMapWidth / 2 * Math.log((1 + Math.sin(mapLatBottomDegree)) / (1 - Math.sin(mapLatBottomDegree))));
double x = (lon - mapLonLeft) * (mapWidth / mapLonDelta);
double y = 0.1;
if (lat < 0) {
lat = lat * Math.PI / 180;
y = mapHeight - ((worldMapWidth / 2 * Math.log((1 + Math.sin(lat)) / (1 - Math.sin(lat)))) - mapOffsetY);
} else if (lat > 0) {
lat = lat * Math.PI / 180;
lat = lat * -1;
y = mapHeight - ((worldMapWidth / 2 * Math.log((1 + Math.sin(lat)) / (1 - Math.sin(lat)))) - mapOffsetY);
System.out.println("y before minus: " + y);
y = mapHeight - y;
} else {
y = mapHeight / 2;
}
System.out.println(x);
System.out.println(y);
When using the original code if the latitude value is positive it returned a negative point, so I modified it slightly and tested with the extreme latitudes-which should be point 0 and point 766, it works fine. However when I try a different latitude value ex: 58.07 (just north of the UK) it displays as north of Spain.
The Mercator map projection is a special limiting case of the Lambert Conic Conformal map projection with the equator as the single standard parallel. All other parallels of latitude are straight lines and the meridians are also straight lines at right angles to the equator, equally spaced. It is the basis for the transverse and oblique forms of the projection. It is little used for land mapping purposes but is in almost universal use for navigation charts. As well as being conformal, it has the particular property that straight lines drawn on it are lines of constant bearing. Thus navigators may derive their course from the angle the straight course line makes with the meridians. [1.]
The formulas to derive projected Easting and Northing coordinates from spherical latitude φ and longitude λ are:
E = FE + R (λ – λₒ)
N = FN + R ln[tan(π/4 + φ/2)]
where λO is the longitude of natural origin and FE and FN are false easting and false northing. In spherical Mercator those values are actually not used, so you can simplify the formula to
Pseudo code example, so this can be adapted to every programming language.
latitude = 41.145556; // (φ)
longitude = -73.995; // (λ)
mapWidth = 200;
mapHeight = 100;
// get x value
x = (longitude+180)*(mapWidth/360)
// convert from degrees to radians
latRad = latitude*PI/180;
// get y value
mercN = ln(tan((PI/4)+(latRad/2)));
y = (mapHeight/2)-(mapWidth*mercN/(2*PI));
Sources:
EDIT Created a working example in PHP (because I suck at Java)
https://github.com/mfeldheim/mapStuff.git
EDIT2
Nice animation of the Mercator projection https://amp-reddit-com.cdn.ampproject.org/v/s/amp.reddit.com/r/educationalgifs/comments/5lhk8y/how_the_mercator_projection_distorts_the_poles/?usqp=mq331AQJCAEoAVgBgAEB&_js_v=0.1