【问题标题】:Convert pixel position from Google static map to LatLng将像素位置从谷歌静态地图转换为 LatLng
【发布时间】:2015-07-12 15:16:24
【问题描述】:

我有一个存储在二维数组中的谷歌静态地图。当用户点击一个像素时,我知道行/列 [0 - 1024]。

我需要将该行 col 转换回 lat lng。我一直在尝试使用下面的代码来进行从像素到纬度 lng 的转换。

我所做的是取中心 lat lng 和缩放级别。

  1. 使用 fromLatLngToPoint 将中心 lat lng 转换为像素。
  2. 使用图片中的row/col和图片的宽高得到
private static PointF getPointFromRowCol(int row, int col, int width, int  height, PointF center) {

    double adjustedStartCol = center.x - ((double)width / 2);
    double adjustedStartRow = center.y - ((double)height / 2);

    double adjustedCol = adjustedStartCol + col;
    double adjustedRow = adjustedStartRow + row;

    PointF adjustedWorldPoint = new PointF(adjustedCol, adjustedRow);

    return GoogleMapsProjection2.fromPointToLatLng(adjustedWorldPoint, 17);
}

问题是当我将生成的 lat lng 放回谷歌地图时,它偏离了 100 米。

有什么想法吗?

public final class GoogleMapsProjection2 {
    private final int TILE_SIZE = 256;
    private PointF _pixelOrigin;
    public double _pixelsPerLonDegree;
    public double _pixelsPerLonRadian;

    public GoogleMapsProjection2() {
        this._pixelOrigin = new PointF(TILE_SIZE / 2.0, TILE_SIZE / 2.0);
        this._pixelsPerLonDegree = TILE_SIZE / 360.0;
        this._pixelsPerLonRadian = TILE_SIZE / (2 * Math.PI);
    }

    double bound(double val, double valMin, double valMax) {
        double res;
        res = Math.max(val, valMin);
        res = Math.min(val, valMax);
        return res;
    }

    double degreesToRadians(double deg) {
        return deg * (Math.PI / 180);
    }

    double radiansToDegrees(double rad) {
        return rad / (Math.PI / 180);
    }

    public PointF fromLatLngToPoint(double lat, double lng, int zoom) {
        PointF point = new PointF(0, 0);

        point.x = _pixelOrigin.x + lng * _pixelsPerLonDegree;

        // 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.
        double siny = bound(Math.sin(degreesToRadians(lat)), -0.9999, 0.9999);
        point.y = _pixelOrigin.y + 0.5 * Math.log((1 + siny) / (1 - siny)) * -_pixelsPerLonRadian;

        int numTiles = 1 << zoom;
        point.x = point.x * numTiles;
        point.y = point.y * numTiles;
        return point;
    }

    public PointF fromPointToLatLng(PointF point, int zoom) {
        int numTiles = 1 << zoom;
        point.x = point.x / numTiles;
        point.y = point.y / numTiles;

        double lng = (point.x - _pixelOrigin.x) / _pixelsPerLonDegree;
        double latRadians = (point.y - _pixelOrigin.y) / -_pixelsPerLonRadian;
        double lat = radiansToDegrees(2 * Math.atan(Math.exp(latRadians)) - Math.PI / 2);
        return new PointF(lat, lng);
    }

    public static PointF fromWorldToPixel(PointF world){
        PointF pixelPoint = new PointF(world.x * (1 << 17), world.y * (1 << 17));
        return pixelPoint;
    }

    public static PointF pixelToWorld(PointF world){
        PointF pixelPoint = new PointF(world.x / (1 << 17), world.y / (1 << 17));
        return pixelPoint;
    }

}

【问题讨论】:

    标签: java google-maps google-static-maps mercator


    【解决方案1】:

    This page 似乎建议您可以将其他 API 与静态地图一起使用。

    似乎值得一提的是,您实际上可以让Google Maps Javascript API 为您提供像素坐标的纬度和经度坐标。

    虽然在 V3 中有点令人费解,但这里有一个如何做到这一点的示例。
    (注意:这是假设您已经有一张地图和要转换为 lat&lng 坐标的像素顶点):

    let overlay  = new google.maps.OverlayView();
    overlay.draw = function() {};
    overlay.onAdd = function() {};
    overlay.onRemove = function() {};
    overlay.setMap(map);
    
    let latlngObj = overlay.fromContainerPixelToLatLng(new google.maps.Point(pixelVertex.x, pixelVertex.y);
    
    overlay.setMap(null); //removes the overlay
    

    希望对某人有所帮助。

    【讨论】:

      【解决方案2】:

      你可以试试这个Java函数:

       function convertPixelToGeo(tx:Number, ty)
      {
        $LatBottomSin=min(max(sin($this->mapLatBottom*(M_PI/180)),-0.9999),0.9999);
        $worldMapWidth=(($this->mapWidth/$mapLonDelta)*360)/(2*M_PI);
      
        $worldMapRadius = $mapWidth / $mapLonDelta * 360/(2*M_PI);     
        $mapOffsetY = ($worldMapRadius/2 *log((1+sin($LatBottomSin))/(1-sin($LatBottomSin))));
        $equatorY = $this->mapHeight + mapOffsetY;   
        $a = ($equatorY-$ty)/$worldMapRadius;
      
        $lat = 180/Math.PI * (2 * Math.atan(Math.exp($a)) - Math.PI/2);
        $long = $this->mapLonLeft+$tx/$mapWidth*$mapLonDelta;
        return new Point($lat,$long);
       }
      

      如果它不起作用,试试这个:

          int numTiles = 1 << zoom;
          tx = tx / numTiles;
          ty = ty / numTiles;
      

      【讨论】:

      • 这看起来不像java,这也考虑到缩放级别?
      • 很抱歉我没有尝试过,但我修正了我的答案。如果它有帮助,请考虑接受和/或支持它。谢谢!
      猜你喜欢
      • 2018-04-16
      • 1970-01-01
      • 1970-01-01
      • 2017-01-12
      • 2014-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多