将纬度/经度点转换为墨卡托投影上的像素 (x,y) [英] Convert latitude/longitude point to a pixels (x,y) on mercator projection
问题描述
我正在尝试将纬度/经度点转换为二维点,以便我可以将其显示在世界图像上 - 这是墨卡托投影.
我已经看到了执行此操作的各种方法以及有关堆栈溢出的一些问题 - 我已经尝试了不同的代码片段,虽然我得到了正确的像素经度,但纬度似乎总是越来越多虽然合理.
我需要公式来考虑图像大小、宽度等.
我试过这段代码:
double minLat = -85.05112878;双 minLong = -180;双最大纬度 = 85.05112878;双 maxLong = 180;//地图图像大小(以点为单位)双地图高度 = 768.0;双地图宽度 = 991.0;//确定地图比例尺(每度点数)double xScale = mapWidth/(maxLong - minLong);double yScale = mapHeight/(maxLat - minLat);//点的地图图像位置双 x = (lon - minLong) * xScale;双 y = - (lat + minLat) * yScale;System.out.println("最终坐标:" + x + " " + y);
在我尝试的示例中,纬度似乎偏离了大约 30 像素.有什么帮助或建议吗?
更新
基于这个问题:
编辑在 PHP 中创建了一个工作示例(因为我很擅长 Java)
https://github.com/mfeldheim/mapStuff.git
EDIT2
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:
- OGP Geomatics Committee, Guidance Note Number 7, part 2: Coordinate Conversions and Transformation
- Derivation of the Mercator projection
- National Atlas: Map Projections
- Mercator Map projection
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
这篇关于将纬度/经度点转换为墨卡托投影上的像素 (x,y)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!