Получите SW & NE углы API статических карт Google

У меня проблема с получением границ моей статической карты Google в приложении Unity. Я попробовал несколько ответов, найденных здесь на stackoverflow.

.NET связанный вопрос

Javascript-связанный вопрос

Карта, для которой я пытаюсь вычислить углыэтот один.

Сначала я попробовал перевестиМарсело его код из JavaScript в C #. Который переводится в следующий класс.

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);
    }
}

Итак, сначала я попытался получить только юго-западный угол карты, и он довольно близко, но это немного не так.

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

Привел меняэтот результат.

Так как очень много людей проголосовали. Сначала я попытался перевестиМарсело Я решил, что во время перевода кода на C # я сделал что-то не так.

Чем я наткнулсяответ петериба который уже сделал перевод ответа javascript на C # и даже привел примеры, когда его код получил правильные границы статической карты Google. Итак, после попытки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();
    }
}

Я попытался снова вычислить углы 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());

Выход:

Юго-запад: 51,438825, 5,453483 Северо-восток: 51,452557, 5,467153

Юго-западные координаты такие же, как и мой собственный перевод javascript. Так как в своем ответе peterjb заявил, что его решение работает для определенной области в Бельгии, я попробовал код в той же области. Тем не менее, результат снова был совсем немного.

Поэтому совершенно случайно я попытался использовать расчет для города в Нигерии с именемKano / Статическая карта и, к моему удивлению, юго-западный угол был чрезвычайно точным!

Выход:

Юго-запад: 12.015251, 8.527824 Северо-восток: 12.028983, 8.541404

Юго-западная позиция.

Впоследствии я пробовал несколько других мест в мире, но часто это было далеко, а иногда даже за сотни миль. Так что, возможно, этот город в Нигерии был просто совпадением, но я надеюсь, что у кого-то есть объяснение и / или решение для меня.

Особая благодарностьpeterjb а такжеМарсело

Ответы на вопрос(1)

Ваш ответ на вопрос