Rik*_*ter 10 .net api static bounds
我正在使用.NET使用静态地图从Google地图加载地图图块.
我遇到的问题是我不知道返回图像的SW和NE坐标是什么.
我发现了许多不同的代码示例,公式,但它们似乎都有缺陷.这是最接近正确答案的那个.当我在Google地图中输入坐标时,它显示它有点偏离.
var result = GoogleMapsAPI.GetBounds(new Coordinate(4.79635, 51.15479), 20, 512, 512);
public static class GoogleMapsAPI
{
public static MapCoordinates GetBounds(Coordinate center, int zoom, int mapWidth, int mapHeight)
{
var scale = Math.Pow(2, zoom);
var SWPoint = new Coordinate(center.X - (mapWidth / 2) / scale, center.Y - (mapHeight / 2) / scale);
var NEPoint = new Coordinate(center.X + (mapWidth / 2) / scale, center.Y + (mapHeight / 2) / scale);
return new MapCoordinates() { SouthWest = SWPoint, NorthEast = NEPoint };
}
}
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 X { get { return Latitude; } set { Latitude = value; } }
public double Y { get { return Longitude; } set { Longitude = value; } }
public Coordinate(double lat, double lng)
{
Latitude = lat;
Longitude = lng;
}
public override string ToString()
{
return X.ToString() + ", " + Y.ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
来源:
如何获得谷歌静态地图的界限?
http://www.easywms.com/easywms/?q=zh-hans/node/3612
按中心坐标加载的图像:http://maps.googleapis.com/maps/api/staticmap? centre = 51.15479,4.79635&zoom = 20&size = 512x512&senns =
false
错误的SW:https://maps.google.be/maps?q = 51.154545859375,+ 4.776105859375 &hl = en&l = 51.154763,4.796695&spn = 0.000568,0.001635&else = 51.154687,4.796838&sssn = 0.001136,0.00327&t = m&z
= 20
有缺陷的网元:https://maps.google.be/maps?q = + 51.155034140625,+ 4.796594140625 &hl = en&_ll = 51.154764,4.796684&spn = 0.000568,0.001635&_ll = 51.154599,4.796723&spn = 0.001136,0.00327&t = m&z
= 20
编辑:哇,我刚刚意识到这个问题已经快两年了。对于那个很抱歉。
好,所以我认为这里发生了一些事情。最重要的是,您没有进行提供的链接中提到的墨卡托投影。您可以在google maps API文档中的代码示例中看到运行中的代码。我认为您之所以有点接近是因为缩放级别20时比例因子太大,以至于淹没了问题的细节。
要获取边界,您需要获取中心纬度/经度,将其转换为像素坐标,加/减以获取所需拐角的像素坐标,然后转换回纬度/经度。第一个链接中的代码可以进行投影和反投影。下面,我将其翻译为c#。
在上述解决方案中,您将获取经/纬坐标,并添加/减去世界坐标(像素坐标/比例),因此您要组合两个不同的坐标系。
我试图弄清楚这一点时遇到的一个问题是您的Coordinate课堂有点混乱。希望我没有这个倒退,但是看起来您正在倒置纬度和经度。这很重要,因为除其他原因外,墨卡托投影在每个方向上都不同。您的X / Y映射也向后看,因为“纬度”是您的北/南位置,在投影时应为Y坐标,而经度是您的东/西位置,在投影时应为X坐标。
要找到边界,需要三个坐标系:经度/纬度,世界坐标和像素坐标。该过程是中心纬度/经度-(墨卡托投影)->中心世界坐标->中心像素坐标-> NE / SW像素坐标-> NE / SW世界坐标-(墨卡托逆投影)-> NE / SW纬度/经度。
您可以通过添加/减去图像的尺寸/ 2来找到像素坐标。像素坐标系从左上角开始,因此要获得NE角,您需要从x添加width / 2并从y减去height / 2。对于SW角,您需要从x减去width / 2并向y增加height / 2。
这是c#中的投影代码(作为GoogleMapsAPI类的一部分),是javascript上方第一个链接的翻译:
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;
}
Run Code Online (Sandbox Code Playgroud)
您可以检查原始javascript代码以获取更多详细注释。
我通过手动逼近边界并与代码给出的答案进行比较来对其进行测试。我对NE角的手动近似值是(51.15501,4.796695),代码吐出了(51.155005 ...,4.797038 ...),看起来很接近。SW角近似为(51.154572,4.796007),代码吐出(51.154574 ...,4.796006 ...)。
这是一个有趣的过程,希望对您有所帮助!
编辑:意识到我没有包括新GetBounds功能:
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 };
}
Run Code Online (Sandbox Code Playgroud)
只要记住确保您正确地找到了经纬度即可:
var result = GoogleMapsAPI.GetBounds(new Coordinate(51.15479, 4.79635), 20, 512, 512);
Run Code Online (Sandbox Code Playgroud)
我知道代码不是最大的代码,但我希望代码清楚。
| 归档时间: |
|
| 查看次数: |
2036 次 |
| 最近记录: |