简体   繁体   English

获取Google Static Maps API的西南和东北角

[英]Get SW & NE corners of Google Static Maps API

I'm having a problem with getting the bounds of my Google Static Map in my Unity application. 我在Unity应用程序中获取Google静态地图的范围时遇到问题。 I've tried multiple answers found here on stackoverflow. 我已经尝试过在stackoverflow上找到多个答案。

.NET related question .NET相关问题

Javascript related question JavaScript相关问题

The map I'm trying to calculate the corners for is this one. 我试图计算角落的地图是一个。

First I tried translating marcelo his code from javascript to C#. 首先,我尝试将marcelo的代码从javascript转换为C#。 Which is translated into the following class. 将其翻译为以下类。

using System;
using UnityEngine;
public class MercatorProjection
{
    static double MERCATOR_RANGE = 256;
    Point pixelsOrigin;
    double pixelsPerLonDegree;
    double pixelsPerLonRadian;

    public MercatorProjection()
    {
        pixelsOrigin = new Point(MERCATOR_RANGE / 2, MERCATOR_RANGE / 2);
        pixelsPerLonDegree = MERCATOR_RANGE / 360;
        pixelsPerLonRadian = MERCATOR_RANGE / (2 * Math.PI);
    }

    double bound(double value, double opt_min, double opt_max)
    {
        if (opt_min != 0)
            value = Math.Max(value, opt_min);
        if (opt_max != 0)
            value = Math.Min(value, opt_max);
        return value;
    }

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

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

    Point fromLatLonToPoint(Coordinates latLon)
    {
        Point point = new Point();
        Point origin = pixelsOrigin;

        point.X = origin.X + latLon.Longitude * pixelsPerLonDegree;

        double sinY = bound(Math.Sin(degreesToRadians(latLon.Latitude)), -0.9999, 0.9999);

        point.Y = origin.Y + 0.5 * Math.Log((1 + sinY) / (1 - sinY)) * -pixelsPerLonRadian;

        return point;
    }

    Coordinates fromPointToLatlon(Point point)
    {
        Point origin = pixelsOrigin;
        Coordinates latLon = new Coordinates();

        latLon.Latitude = (point.X - origin.X) / pixelsPerLonDegree;
        double latRadians = (point.Y - origin.Y) / -pixelsPerLonRadian;
        latLon.Longitude = radiansToDegrees(2 * Math.Atan(Math.Exp(latRadians)) - Math.PI / 2);

        return latLon;
    }

    public void GetCorners(Coordinates center, float zoom, float mapWidth, float mapHeight)
    {
        double scale = Math.Pow(2, zoom);
        Point centerPx = fromLatLonToPoint(center);
        Point SWPoint = new Point(centerPx.X - (mapWidth / 2) / scale, centerPx.Y + (mapHeight / 2) / scale);
        Coordinates SWLatLon = fromPointToLatlon(SWPoint);
        Debug.Log(SWLatLon.Latitude + " " + SWLatLon.Longitude + " " + SWPoint.X + " " + SWPoint.Y);
    }
}

So at first I tried only getting the South West corner of the map and it's pretty close, but it's a bit off. 因此,起初我仅尝试获取地图的西南角,它非常接近,但是有点偏离。

MercatorProjection.GetCorners(new Coordinates(Coordinates.Longitude, Coordinates.Latitude), 16, 640, 640);

Brought me this result. 带给我这个结果。

Since so many people voted First I tried translating marcelo his answer up I figured I did something wrong during the translation of the code to C#. 因为有很多人投票,所以我首先尝试翻译marcelo的答案,然后发现在将代码转换为C#的过程中做错了什么。

Than I stumbled across peterjb's answer who already did the translation of the javascript answer to C# and even gave examples where his code got the right bounds of a Google static map. 而不是我偶然发现了peterjb的答案 ,他已经将javascript答案翻译成C#,甚至给出了示例,说明他的代码正确地构成了Google静态地图。 So after trying peterjb 's code in the following class; 因此,在下面的类中尝试了peterjb的代码之后;

using System;

public static class GoogleMapsAPI{

    static GoogleMapsAPI()
    {
        OriginX = TileSize / 2;
        OriginY = TileSize / 2;
        PixelsPerLonDegree = TileSize / 360.0;
        PixelsPerLonRadian = TileSize / (2 * Math.PI);
    }

    public static int TileSize = 256;
    public static double OriginX, OriginY;
    public static double PixelsPerLonDegree;
    public static double PixelsPerLonRadian;

    public static double DegreesToRadians(double deg)
    {
        return deg * Math.PI / 180.0;
    }

    public static double RadiansToDegrees(double rads)
    {
        return rads * 180.0 / Math.PI;
    }

    public static double Bound(double value, double min, double max)
    {
        value = Math.Min(value, max);
        return Math.Max(value, min);
    }

    //From Lat, Lon to World Coordinate X, Y. I'm being explicit in assigning to
    //X and Y properties.
    public static Coordinate Mercator(double latitude, double longitude)
    {
        double siny = Bound(Math.Sin(DegreesToRadians(latitude)), -.9999, .9999);

        Coordinate c = new Coordinate(0, 0);
        c.X = OriginX + longitude * PixelsPerLonDegree;
        c.Y = OriginY + .5 * Math.Log((1 + siny) / (1 - siny)) * -PixelsPerLonRadian;

        return c;
    }

    //From World Coordinate X, Y to Lat, Lon. I'm being explicit in assigning to
    //Latitude and Longitude properties.
    public static Coordinate InverseMercator(double x, double y)
    {
        Coordinate c = new Coordinate(0, 0);

        c.Longitude = (x - OriginX) / PixelsPerLonDegree;
        double latRadians = (y - OriginY) / -PixelsPerLonRadian;
        c.Latitude = RadiansToDegrees(Math.Atan(Math.Sinh(latRadians)));

        return c;
    }

    public static MapCoordinates GetBounds(Coordinate center, int zoom, int mapWidth, int mapHeight)
    {
        var scale = Math.Pow(2, zoom);

        var centerWorld = Mercator(center.Latitude, center.Longitude);
        var centerPixel = new Coordinate(0, 0);
        centerPixel.X = centerWorld.X * scale;
        centerPixel.Y = centerWorld.Y * scale;

        var NEPixel = new Coordinate(0, 0);
        NEPixel.X = centerPixel.X + mapWidth / 2.0;
        NEPixel.Y = centerPixel.Y - mapHeight / 2.0;

        var SWPixel = new Coordinate(0, 0);
        SWPixel.X = centerPixel.X - mapWidth / 2.0;
        SWPixel.Y = centerPixel.Y + mapHeight / 2.0;

        var NEWorld = new Coordinate(0, 0);
        NEWorld.X = NEPixel.X / scale;
        NEWorld.Y = NEPixel.Y / scale;

        var SWWorld = new Coordinate(0, 0);
        SWWorld.X = SWPixel.X / scale;
        SWWorld.Y = SWPixel.Y / scale;

        var NELatLon = InverseMercator(NEWorld.X, NEWorld.Y);
        var SWLatLon = InverseMercator(SWWorld.X, SWWorld.Y);

        return new MapCoordinates() { NorthEast = NELatLon, SouthWest = SWLatLon };
    }
}
public class MapCoordinates
{
    public Coordinate SouthWest { get; set; }
    public Coordinate NorthEast { get; set; }
}

public class Coordinate
{
    public double Latitude { get; set; }
    public double Longitude { get; set; }

    public double Y { get { return Latitude; } set { Latitude = value; } }
    public double X { get { return Longitude; } set { Longitude = value; } }

    public Coordinate(double lng, double lat)
    {
        Latitude = lat;
        Longitude = lng;
    }

    public override string ToString()
    {
        return Math.Round(X, 6).ToString() + ", " + Math.Round(Y, 6).ToString();
    }
}

I tried calculating the SW and NE corners again by calling the following 我尝试通过调用以下命令再次计算SW和NE角

Coordinates = new Coordinate(51.445691, 5.460318);
var result = GoogleMapsAPI.GetBounds(Coordinates, 16, 640, 640);
Debug.Log("SouthWest: "+result.SouthWest.ToString() + " NorthEast: "+result.NorthEast.ToString());

Output: 输出:

SouthWest: 51.438825, 5.453483 NorthEast: 51.452557, 5.467153 西南:51.438825,5.453483东北:51.452557,5.467153

The SouthWest coordinates are the exact same as my own translation of the javascript. 西南坐标与我自己的javascript翻译完全相同。 So since peterjb claimed in his answer that his solution worked for a certain area in Belgium, I tried the code on the same area. 因此,由于peterjb在回答中声称他的解决方案适用于比利时的某个地区,因此我在同一地区尝试了该代码。 However, the result again was quite a bit off. 但是,结果还是有点差。

So quite randomly I tried using the calculation for a town in Nigeria named Kano / Static map and to my surprise, the SouthWest corner was extremely accurate! 因此,我非常随机地尝试使用尼日利亚的一个名为Kano / Static map的城镇的计算方法,令我惊讶的是,西南角非常准确!

Output: 输出:

SouthWest: 12.015251, 8.527824 NorthEast: 12.028983, 8.541404 西南:12.015251,8.527824东北:12.028983,8.541404

SouthWest position . 西南的位置

I've tried multiple other area's in the world afterwards, but it often was way off and sometimes even hundreds of miles. 此后,我在世界上其他多个地区进行了尝试,但它往往相距甚远,有时甚至达数百英里。 So maybe this town in Nigeria was just an coincidence, but I'm hoping someone has an explanation and/or solution for me. 因此,也许尼日利亚的这个小镇只是一个巧合,但我希望有人对我有一个解释和/或解决方案。

Special thanks to peterjb and marcelo 特别感谢peterjbmarcelo

The constructor for Coordinate class accepts (lng, lat) instead of (lat, lng) as you might expect, so the parameters are in a different order than you are passing in. 正如您所期望的,Coordinate类的构造函数接受(lng,lat)而不是(lat,lng),因此参数的顺序与传递的顺序不同。

I also noticed that Coordinate's ToString override prints as (lng, lat) as well, so it could be confusing if you expect to see (lat, lng). 我还注意到,Coordinate的ToString覆盖也将打印为(lng,lat),因此如果您希望看到(lat,lng),可能会造成混淆。

Simply swap both of these in the static API. 只需在静态API中交换这两者即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM