У меня возникла проблема с получением границ моей Статической карты Google в приложении Unity. Я попробовал несколько ответов, найденных здесь, в stackoverflow.Получить SW & NE углы API статических карт Google
Карта Я пытаюсь вычислить углы для this является один.
Сначала я пробовал переводить marcelo свой код с 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);
Принесли мне this результат.
Поскольку так много людей проголосовало. Сначала я пробовал перевести marcelo его ответ. Я решил, что я сделал что-то неправильно во время перевода кода на C#.
Чем я наткнулся на peterjb's answer, который уже сделал перевод ответа на 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
Координаты SouthWest - это то же самое, что и мой собственный перевод из javascript. Так как peterjb утверждал в своем ответе, что его решение работало в определенной области в Бельгии, я пробовал код в той же области. Однако результат снова был совсем немного.
Так что совершенно случайно я попытался использовать расчет для города в Нигерии по имени Kano/Static map, и, к моему удивлению, угол SouthWest был предельно точным!
Выход:
SouthWest: 12,015251, 8,527824 NorthEast: 12,028983, 8,541404
После этого я попробовал несколько других областей в мире, но часто это было далеко, а иногда и сотни миль. Так что, возможно, этот город в Нигерии был просто совпадением, но я надеюсь, что у кого-то есть объяснение и/или решение для меня.
Особая благодарность peterjb и marcelo
Дополнительная информация: https://alastaira.wordpress.com/2011/01/23/the-google-maps-bing-maps-spherical-mercator-projection/ –
Привет, Leniaal, я думаю, проблема в том, что ваша координата конструктор принимает параметры как lng, lat, но вы проходите в lat, lng. Пример Кано, вероятно, близок, потому что lat и lng почти одинаковы. Надеюсь, это поможет, дайте мне знать, если все еще не совсем. – peterjb
Привет, @peterjb Спасибо за ваше время и интерес. Вы правы, я не могу поверить, что я этого не замечал. Я очень рад, что вы это заметили, потому что я смотрел на эту проблему, спасибо тонну! Вы можете добавить его в качестве ответа, если хотите, чтобы я мог отметить этот вопрос. – Leniaal