Google Maps Static API - 通过中心坐标获取 SW 和 NE [英] Google Maps Static API - Get SW and NE by center coordinate

查看:37
本文介绍了Google Maps Static API - 通过中心坐标获取 SW 和 NE的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用静态地图和 .NET 从 Google 地图加载地图图块.

I'm loading map tiles from Google Maps using Static Maps, using .NET.

我遇到的问题是我不知道返回图像的 SW 和 NE 坐标是什么.

The problem I'm having is that I don't know what the SW and NE coordinates are of the returned image.

我发现了许多不同的代码示例、公式,但它们似乎都有缺陷.这是最接近正确答案的一个.当我在谷歌地图中输入坐标时,它显示它有点偏离.

I've found many different code samples, formulas, but they all seem to be flawed. This is the one that got closest to the correct answer. When I entered the coordinates in Google Maps it showed that it was a little bit off.

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

来源:
如何获取谷歌静态地图的边界?
http://www.easywms.com/easywms/?q=zh-hans/node/3612

按中心坐标加载图像:
http:///maps.googleapis.com/maps/api/staticmap?center=51.15479,4.79635&zoom=20&size=512x512&sensor=false

错误的软件:
https://maps.google.be/maps?q=51.154545859375,+4.796105859375&ll415&ll4164.796695&spn=0.000568,0.001635&sll=51.154687,4.796838&sspn=0.001136,0.00327&t=m&z=20

NE 故障:
https://maps.google.be/maps?q=+51.155034140625,+4.796594140625&hl=en51.154764,4.796684&spn=0.000568,0.001635&sll=51.154599,4.796723&sspn=0.001136,0.00327&z=2&t=m&a

推荐答案

哇,我刚刚意识到这个问题已经快两年了.很抱歉.

Wow, I just realized this question is almost two years old. Sorry about that.

好的,所以我认为这里发生了一些事情.最重要的是您没有进行您提供的链接中提到的墨卡托投影.您可以使用 Google 中的代码示例查看它的实际效果地图 API 文档.我认为您有点接近的原因是缩放级别 20 时的比例因子太大,以至于淹没了问题的细节.

OK so I think there are a few things going on here. The most important is that you aren't doing the Mercator projection mentioned in the links you provided. You can see it in action with a code sample in the google maps API docs. I think the reason you are getting somewhat close is that the scale factor is so large at zoom level 20 that it drowns out the details of the problem.

要获得边界,您需要取中心纬度/经度,将其转换为像素坐标,加/减以获得所需角点的像素坐标,然后再转换回纬度/经度.第一个链接中的代码可以做投影和反投影.下面我把它翻译成c#.

To get the bounds, you need to take the center lat/lon, convert it to pixel coordinates, add/subtract to get the pixel coordinates of the corners that you want, and then convert back to lat/lon. The code in the first link can do the projection and inverse projection. Below I've translated it into c#.

在上面的解决方案中,您使用的是纬度/经度坐标并添加/减去世界坐标(像素坐标/比例),因此您将组合两个不同的坐标系.

In your solution above, you are taking lat/lon coordinates and adding/subtracting world coordinates (pixel coords / scale), so you are combining two different coordinate systems.

我在尝试解决这个问题时遇到的一个问题是您的 Coordinate 类有点令人困惑.希望我没有倒退,但看起来您正在倒退纬度和经度.这很重要,因为墨卡托投影在每个方向上都不同,还有其他原因.您的 X/Y 映射似乎也向后,因为纬度是您的北/南位置,投影时应该是 Y 坐标,而经度是您的东/西位置,应该是投影时的 X 坐标.

An issue I ran into while trying to figure this out is that your Coordinate class is a little confusing. Hopefully I don't have this backwards, but it looks like you are putting in the latitude and longitude backwards. This is important because the Mercator projection is different in each direction, among other reasons. Your X/Y mapping seems backwards, too, because Latitude is your North/South position, which should be the Y coordinate when projected, and Longitude is you East/West position, which should be the X coordinate when projected.

要找到边界,需要三个坐标系:经度/纬度、世界坐标和像素坐标.过程是Center Lat/Lon -(Mercator Projection)-> Center World Coordinates -> Center Pixel Coordinates -> NE/SW Pixel Coordinates -> NE/SW World Coordinates -(Inverse Mercator Projection)-> NE/SW Lat/Lon.

To find the bounds, three coordinate systems are needed: Longitude/Latitude, World Coordinates and Pixel Coordinates. The process is Center Lat/Lon -(Mercator Projection)-> Center World Coordinates -> Center Pixel Coordinates -> NE/SW Pixel Coordinates -> NE/SW World Coordinates -(Inverse Mercator Projection)-> NE/SW Lat/Lon.

您可以通过添加/减去图像/2 的尺寸来找到像素坐标.像素坐标系从左上角开始,因此要获得 NE 角,您需要从 x 中添加 width/2 并从 y 中减去 height/2.对于 SW 角,您需要从 x 中减去 width/2 并将 height/2 添加到 y.

You find the pixel coordinates by adding/subtracting the dimensions of the image/2. The pixel coordinate system starts from the upper left corner though, so to get the NE corner you need to add width/2 from x and subtract height/2 from y. For the SW corner you need to subtract width/2 from x and add height/2 to y.

这是 C# 中的投影代码(作为 GoogleMapsAPI 类的一部分),翻译自 javascript 上面的第一个链接:

Here's the projection code (as part of your GoogleMapsAPI class) in c#, translation from the first link above 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;
}

您可以查看原始javascript代码以获取更详细的注释.

You can check the original javascript code for more detailed comments.

我通过手动近似边界然后与代码给出的答案进行比较来测试它.我对 NE 角的手动近似值是 (51.15501, 4.796695) 并且代码吐出 (51.155005..., 8...7970>3这似乎很接近.SW 角近似为 (51.154572, 4.796007),代码吐槽 (51.154574..., 4.796006...).

I tested it out by manually approximating the boundaries and then comparing to the answer the code gave. My manual approximations for the NE corner was (51.15501, 4.796695) and the code spit out (51.155005..., 4.797038...) which seems pretty close. SW corner approximate was (51.154572, 4.796007), code spit out (51.154574..., 4.796006...).

这很有趣,我希望这会有所帮助!

This was a fun one, I hope this helps!

意识到我没有包含新的 GetBounds 函数:

Realized I didn't include the new GetBounds function:

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

请记住确保您已正确输入纬度和经度:

Just remember to make sure you've got the Latitude and Longitude in there right:

var result = GoogleMapsAPI.GetBounds(new Coordinate(51.15479, 4.79635), 20, 512, 512);

我知道代码不是最好的,但我希望它很清楚.

I know the code is not the greatest, but I hope it is clear.

这篇关于Google Maps Static API - 通过中心坐标获取 SW 和 NE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆