【问题标题】:Tile Projection Google Maps: Convert Distance to Screen Dimensions瓷砖投影谷歌地图:将距离转换为屏幕尺寸
【发布时间】:2016-06-04 04:42:24
【问题描述】:

我在 Google Maps Android v2 中使用 CanvasTileProvider。

我可以将经纬度点转换为屏幕像素。

但是,我想创建一种将距离转换为屏幕像素的方法。这将允许我绘制一个 x 半径的圆。有人可以帮忙吗?

下面的代码是我从其他地方截取和修改的,感谢原作者。

/**
 * Converts between LatLng coordinates and the pixels inside a tile.
 */
public class TileProjection {

    public int x;
    public int y;
    private int zoom;
    private int TILE_SIZE;

    private DoublePoint pixelOrigin_;
    private double pixelsPerLonDegree_;
    private double pixelsPerLonRadian_;

    TileProjection(int tileSize, int x, int y, int zoom) {
        this.TILE_SIZE = tileSize;
        this.x = x;
        this.y = y;
        this.zoom = zoom;
        pixelOrigin_ = new DoublePoint(TILE_SIZE / 2, TILE_SIZE / 2);
        pixelsPerLonDegree_ = TILE_SIZE / 360d;
        pixelsPerLonRadian_ = TILE_SIZE / (2 * Math.PI);
    }

    /**
     * Get the dimensions of the Tile in LatLng coordinates
     */
    public LatLngBounds getTileBounds() {
        DoublePoint tileSW = new DoublePoint(x * TILE_SIZE, (y + 1) * TILE_SIZE);
        DoublePoint worldSW = pixelToWorldCoordinates(tileSW);
        LatLng SW = worldCoordToLatLng(worldSW);
        DoublePoint tileNE = new DoublePoint((x + 1) * TILE_SIZE, y * TILE_SIZE);
        DoublePoint worldNE = pixelToWorldCoordinates(tileNE);
        LatLng NE = worldCoordToLatLng(worldNE);
        return new LatLngBounds(SW, NE);
    }

    /**
     * Calculate the pixel coordinates inside a tile, relative to the left upper
     * corner (origin) of the tile.
     */
    public PointF latLngToPoint(LatLng latLng) {
        DoublePoint result = new DoublePoint(1, 1);
        //  Log.d("Aero","x " + String.valueOf(x));
        // Log.d("Aero","y " + String.valueOf(y));

        latLngToWorldCoordinates(latLng, result);
        worldToPixelCoordinates(result, result);
        result.x -= x * TILE_SIZE;

        int numTiles = 1 << zoom;
        if (latLng.longitude < 0) {
            result.x = result.x + (numTiles * TILE_SIZE);
        }

        result.y -= y * TILE_SIZE;
        return new PointF((float) result.x, (float) result.y);
    }    

    private DoublePoint pixelToWorldCoordinates(DoublePoint pixelCoord) {
        int numTiles = 1 << zoom;
        DoublePoint worldCoordinate = new DoublePoint(pixelCoord.x / numTiles,
                pixelCoord.y / numTiles);
        return worldCoordinate;
    }

    /**
     * Transform the world coordinates into pixel-coordinates relative to the
     * whole tile-area. (i.e. the coordinate system that spans all tiles.)
     * <p/>
     * <p/>
     * Takes the resulting point as parameter, to avoid creation of new objects.
     */
    private void worldToPixelCoordinates(DoublePoint worldCoord, DoublePoint result) {
        int numTiles = 1 << zoom;
        result.x = worldCoord.x * numTiles;
        result.y = worldCoord.y * numTiles;
    }

    private LatLng worldCoordToLatLng(DoublePoint worldCoordinate) {
        DoublePoint origin = pixelOrigin_;
        double lng = (worldCoordinate.x - origin.x) / pixelsPerLonDegree_;
        double latRadians = (worldCoordinate.y - origin.y)
                / -pixelsPerLonRadian_;
        double lat = Math.toDegrees(2 * Math.atan(Math.exp(latRadians))
                - Math.PI / 2);
        return new LatLng(lat, lng);
    }

    /**
     * Get the coordinates in a system describing the whole globe in a
     * coordinate range from 0 to TILE_SIZE (type double).
     * <p/>
     * Takes the resulting point as parameter, to avoid creation of new objects.
     */
    private void latLngToWorldCoordinates(LatLng latLng, DoublePoint result) {
        DoublePoint origin = pixelOrigin_;

        result.x = origin.x + latLng.longitude * 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(Math.toRadians(latLng.latitude)), -0.9999,
                0.9999);
        result.y = origin.y + 0.5 * Math.log((1 + siny) / (1 - siny))
                * -pixelsPerLonRadian_;
    }

    ;

    /**
     * Return value reduced to min and max if outside one of these bounds.
     */
    private double bound(double value, double min, double max) {
        value = Math.max(value, min);
        value = Math.min(value, max);
        return value;
    }

    /**
     * A Point in an x/y coordinate system with coordinates of type double
     */
    public static class DoublePoint {
        double x;
        double y;

        public DoublePoint(double x, double y) {
            this.x = x;
            this.y = y;
        }
    }

}

这是我建议使用的:

public Double MetersToPixels(LatLng latLng, Double distance){
    double tileScale = TILE_SIZE / 256;
    double pixelsPerMeter =1 / (156543.03392 * Math.cos(latLng.latitude * Math.PI / 180) / Math.pow(2, zoom)) * tileScale;
    return  pixelsPerMeter * distance;
}

【问题讨论】:

    标签: java android graphics google-maps-android-api-2 map-projections


    【解决方案1】:

    首先,您应该意识到,地球表面的圆圈并不完全是地图上的圆圈。但是如果你忽略这个不准确,你只需要在 25nm 距离内创建一个 LatLng 点,然后使用 latLngToPoint 方法获取像素。将它们与中心的像素进行比较,即可得出半径。要在给定距离内创建 LatLng,请参阅SO question 的答案(方法移动)

    【讨论】:

    • 感谢您的帮助,我查看了您的答案/链接,这很有意义。但是,在您发布之前,我已经提出了一些代码,您介意查看我编辑的问题底部的代码并告诉我您认为它是否正确吗?它似乎对我有用。
    • 嗨 Reafidy,很久以前我就深入研究了。所以我不能开箱即用地判断你的公式是否可以。或不。但我认为,如果你计算 y 距离(南北),你应该独立于纬度本身,因为南北周长总是相同的长度,而东西周长取决于纬度。由于您的公式中有纬度,因此您似乎正在计算东西距离。 (正如可能回答的那样。地球上的精确圆不会是地图上的精确圆,反之亦然)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-09
    • 1970-01-01
    • 2013-05-27
    • 2012-04-10
    • 1970-01-01
    • 1970-01-01
    • 2012-06-30
    相关资源
    最近更新 更多