在给定的地图上将经纬度坐标转换为像素(使用JavaScript)

9
我从MaxMind整理了一个城市数据库,其中包含数据库中每个城市的经纬度值。我还制作了一张北美地图,希望在地图上基于城市数据库记录的经纬度坐标,在相应的x/y坐标上显示一个图标。
据我所知,首先需要找到地图的左侧/顶部边界(经纬度-> x / y),然后将其作为任何北美城市x / y坐标之间线性关系的差异。最后,根据地图的大小,只需进行几个简单的除法和减法运算即可确定放置点的位置。
然而,我似乎无法弄清楚如何执行以下操作:
  1. 我不确定什么是纬度/经度映射系统。我该如何找到这个信息?
  2. 使用JavaScript库,如何将纬度/经度转换为0,0坐标和每个城市坐标的像素。我已经尝试了Proj4js,但他们要求您指定您的坐标映射类型等。这里有一个类似的问题。 在给定图片上将经纬度转换为像素x / y

有任何想法吗?

--编辑--

输出地图(北美)是一个连续的圆柱体:“米勒圆柱投影”。 http://en.wikipedia.org/wiki/Miller_cylindrical_projection


1
数学可以非常简单,但这取决于地图的类型,也就是说,地图使用哪种投影呈现?http://en.wikipedia.org/wiki/Map_projection - Umbrella
输出地图是一个连续的圆柱体:"米勒圆柱投影"。http://en.wikipedia.org/wiki/Miller_cylindrical_projection - matsko
你提供的维基百科文章中给出了公式……为什么不使用它们呢? - derobert
检查这个工具:http://trimaps.com - Gilbou
3个回答

11

纬度和经度是在地球上虚构的线条,可以准确地定位世界上的任何位置。简单来说,它们是平面坐标系中的X和Y坐标。

纬度是一条垂直线,从北极到南极延伸,其90度处为北极,-90度处为南极。

另一方面,经度是一条水平线,从东到西延伸,在西经180度和东经180度分别为-180度。

您可以将纬度和经度转换为像素坐标,方法是假设HTML容器的宽度是世界的宽度,高度同理。

公式 - 经度 - 像素

(givenLng*widthOfContainerElement)/360

360是总经度,以度为单位。

公式 - 纬度 - 像素

(givenLat*heightOfContainerElement)/180

其中360是经度的总数,以度为单位。

//Height is calculated from the bottom

如果您仍需要任何澄清,请告诉我。


5
经度是垂直线,而纬度是水平线。请更正您的答案。 - Deepak kaku
...而经度则是一条水平线,从东到西延伸。 - tonix

5
这是一个Javascript实现的墨卡托投影,它仅返回正值(屏幕的笛卡尔坐标系),并考虑了球体与平面的转换:
// get x   
var x = (lng + 180) * (mapWidth / 360);
// convert from degrees to radians
var latRad = lat * Math.PI / 180;
// get y value
var mercN = Math.log(Math.tan((Math.PI / 4) + (latRad / 2)));
var y = (mapHeight / 2) - (mapWidth * mercN / (2 * Math.PI));

4

这是一个很古老的问题,但是已经接受的答案有一些...细微差别...

通常,这是针对卫星 / 航空摄影图像进行的操作,它通常伴随着“缩放级别”。

这个缩放级别大致上意味着“地面采样距离”或 GSD,当提供时,代表着图像中每个像素的厘米数。

你经常会看到18、19、20或21的缩放级别。

需要注意的其中一个问题是地球不是平的也不是完美的球形,因此有许多不同的“投影”方法可用于从地球表面的三维坐标转换为屏幕上的二维图像。其中最流行和广泛使用的投影方法是墨卡托投影。

谷歌提供了一种方法,使用墨卡托投影提供 xy 的像素坐标。

我们可以使用“缩放级别”来缩放坐标以适应我们的图像。

interface LatLngLiteral {
    lat: number;
    lng: number;
}

interface Coordinate {
    x: number;
    y: number;
}

const project = (latLng: LatLngLiteral): Coordinate => {
    const TILE_SIZE: number = 256;
    let siny: number = Math.sin((latLng.lat * Math.PI) / 180);

    // Truncating to 0.9999 effectively limits latitude to 89.189. This is
    // about a third of a tile past the edge of the world tile.
    siny = Math.min(Math.max(siny, -0.9999), 0.9999);

    return {
        x: TILE_SIZE * (0.5 + latLng.lng / 360),
        y: TILE_SIZE * (0.5 - Math.log((1 + siny) / (1 - siny)) / (4 * Math.PI))
    };
};
export function formatToPoint(latLng: LatLngLiteral, zoom: number): Coordinate {
    // Get the world coordinates in pixels
    const worldCoordinate: Coordinate = project(latLng);
    // Scale to fit our image
    const scale: number = Math.pow(2, zoom);

    // Apply scale to world coordinates to get image coordinates
    return {
        x: Math.floor(worldCoordinate.x * scale),
        y: Math.floor(worldCoordinate.y * scale)
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接