谷歌地图API静态 - 获取SW和NE的中心坐标(Google Maps Static API -

2019-08-01 02:38发布

我是从谷歌地图使用静态地图加载地图图块,使用.NET。

我遇到的问题是,我不知道是什么SW和NE坐标返回的形象。

我发现很多不同的代码示例,公式,但他们似乎都存在缺陷。 这是得到最接近正确答案的人。 当我进入了谷歌地图的坐标就表明它是一点点了。

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

故障SW:
https://maps.google.be/maps?q=51.154545859375,+4.796105859375&hl=en&ll=51.154763,4.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=en&ll=51.154764,4.796684&spn=0.000568,0.001635&sll=51.154599,4.796723&sspn=0.001136,0.00327&t=m&z=20

Answer 1:

编辑:哇,我才意识到这个问题几乎是两岁。 对于那个很抱歉。

行,所以我觉得有几件事情怎么回事。 最重要的是你是不是在做你所提供的链接中提到的墨卡托投影。 你可以用一个看到它的行动代码示例在谷歌地图API文档。 我觉得你越来越有点接近的原因是,比例因子是缩放级别为20,它淹没了这个问题的细节如此之大。

为了得到边界,你需要采取中心经/纬度,将其转换为像素坐标,加/减,以获得您想要的角落的像素坐标,再转换回经/纬度。 在第一个链接的代码可以做投影和逆向投影。 下面,我把它翻译成C#。

在上面的解决方案,你正在服用经/纬度坐标和加法/减法世界坐标(像素COORDS /缩放),所以你将两个不同的坐标系。

我跑进试图想出解决办法的一个问题是,你的Coordinate类是有点混乱。 但愿我没有这个倒退,但它看起来像你的经度和纬度将倒退。 这是重要的,因为墨卡托投影是在每个方向上,除其他原因不同。 你的X / Y映射似乎倒退,也因为纬度是您的南/北的位置,这应该是投影时,Y坐标,以及经度是你东/西的位置,这应该是投影时,X坐标。

为了找到界限, 三个坐标系需要:经度/纬度,世界坐标和像素坐标。 这个过程是中心纬度/经度 - (墨卡托投影) - >中心世界坐标 - >中心像素坐标 - > NE / SW像素坐标 - > NE / SW世界坐标 - (逆墨卡托投影) - > NE / SW纬度/经度。

你会发现像素的加法/减法图像/ 2的尺寸协调。 像素坐标系统从左上角开始,虽然,所以要得到你需要添加宽度/ 2 x和从y中减去高度/ 2东北角。 对于SW角落,你需要减去宽/ 2 x和增加高度/ 2为y。

下面是在C#中,从上面的javascript第一链接转换的投影代码(如您的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;
}

您可以检查原始的JavaScript代码进行更详细的评论。

我测试了它通过手动逼近边界,然后比较的代码给出了答案。 我的东北角手动近似为(51.15501,4.796695)和代码吐出(51.155005 ...,4.797038 ......),这似乎相当接近。 西南角近似是(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 };
}

只要记住,以确保你有经度和纬度有权利:

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

我知道代码是不是最大的,但我希望它是明确的。



文章来源: Google Maps Static API - Get SW and NE by center coordinate