【问题标题】:Conversion of lat/lng coordinates to pixels on a given map (with JavaScript)将 lat/lng 坐标转换为给定地图上的像素(使用 JavaScript)
【发布时间】:2012-02-12 11:07:00
【问题描述】:

我从 MaxMind 整理了一个城市数据库,其中包含数据库中每个城市的纬度/经度值。我还整理了一张北美/美国地图,我希望在地图的 x/y 坐标上显示一个图标,该图标源自城市数据库记录的 lat/lng 坐标。

据我了解,我需要先找到地图的左/上边界(lat/lng -> x/y),然后将其用作北美城市 x/y 之间线性关系的差异坐标。最后,根据地图的大小,只需进行几个简单的除法和减法运算就可以确定该点的放置位置。

但是我似乎无法弄清楚如何执行以下操作:

  1. 我不确定 lat/lng 映射系统是什么。我怎样才能知道这一点?
  2. 使用 JavaScript 库,如何将 lat/lng 转换为 0,0 坐标和每个城市坐标的像素。我尝试过 Proj4js,但它们要求您指定坐标图类型等。这是另一个提出类似问题的问题。 Convert long/lat to pixel x/y on a given picture

有什么想法吗?

-- 编辑--

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

【问题讨论】:

标签: javascript maps latitude-longitude


【解决方案1】:

纬度和经度是在地球上绘制的假想线,因此您可以准确地确定世界上的任何位置。简单地说,它们是飞机的 X 和 Y 坐标。 纬度是一条从北到南的垂直线,北极90度,南极-90度。

另一方面,经度是一条从东到南的水平线,西为-180度,东为180度。

您可以将 latLng 转换为像素坐标,假设 html 容器的宽度是世界的宽度,高度也是如此。

公式 - 经度 - 像素

(givenLng*widthOfContainerElement)/360

其中 360 度是总经度

公式 - 纬度 - 像素化

(givenLat*heightOfContainerElement)/180

其中 360 度是总经度

//Height is calculated from the bottom

如果您还需要任何说明,请告诉我。

【讨论】:

  • 经度是垂直线,而纬度是水平线。请更正你的答案
  • ... Longitude on the other hand is a horizontal line running east to ---> 西
【解决方案2】:

这是 Mercator projection 的 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));

【讨论】:

    【解决方案3】:

    这是一个非常古老的问题,但公认的答案有一些......细微差别......

    通常,这是为卫星/航空图像完成的,通常伴随着“缩放级别”。

    这个缩放级别大致(我的意思是大致)转换为“地面样本距离”或 GSD,如果提供它,它表示图像中每像素的厘米数。

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

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

    Google provides a method 使用墨卡托投影提供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)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-06
      • 2023-04-07
      • 2010-11-12
      • 1970-01-01
      • 2018-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多