2012-10-02 69 views
9

Tôi đang tải các lát bản đồ từ Google Maps bằng Bản đồ tĩnh, sử dụng .NET.API tĩnh của Google Maps - Nhận SW và NE theo tọa độ trung tâm

Sự cố tôi gặp phải là tôi không biết tọa độ SW và NE là của hình ảnh được trả về.

Tôi đã tìm thấy nhiều mẫu mã, công thức khác nhau, nhưng tất cả đều có vẻ thiếu sót. Đây là câu trả lời đúng nhất. Khi tôi nhập tọa độ trong Google Maps, nó cho thấy rằng nó đã được một chút tắt.

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

Nguồn:
How to get bounds of a google static map?
http://www.easywms.com/easywms/?q=zh-hans/node/3612

ảnh Loaded bởi trung tâm phối hợp:
http://maps.googleapis.com/maps/api/staticmap?center=51.15479,4.79635&zoom=20&size=512x512&sensor=false

Lỗi 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

Lỗi 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

Trả lời

4

EDIT: Wow, tôi vừa nhận ra câu hỏi này đã gần hai tuổi. Xin lỗi vì điều đó.

OK vì vậy tôi nghĩ có một vài điều đang diễn ra tại đây. Điều quan trọng nhất là bạn không thực hiện phép chiếu Mercator được đề cập trong các liên kết bạn đã cung cấp. Bạn có thể thấy nó hoạt động với code sample trong tài liệu API bản đồ google. Tôi nghĩ rằng lý do bạn đang nhận được phần nào là gần gũi là yếu tố quy mô là quá lớn ở mức độ zoom 20 rằng nó bị chết đuối ra các chi tiết của vấn đề.

Để có giới hạn, bạn cần lấy vĩ độ/vĩ độ trung tâm, chuyển nó thành tọa độ điểm ảnh, cộng/trừ để lấy tọa độ điểm ảnh của các góc bạn muốn và sau đó chuyển đổi lại thành vĩ độ/lon. Mã trong liên kết đầu tiên có thể thực hiện phép chiếu và phép chiếu nghịch đảo. Dưới đây tôi đã dịch nó thành C#.

Trong giải pháp trên, bạn đang dùng tọa độ vĩ độ/vĩ độ và cộng/trừ các tọa độ thế giới (coords pixel/tỷ lệ), vì vậy bạn đang kết hợp hai hệ tọa độ khác nhau.

Một vấn đề mà tôi gặp phải trong khi cố gắng tìm ra điều này là lớp học Coordinate của bạn hơi khó hiểu. Hy vọng rằng tôi không có điều này ngược, nhưng có vẻ như bạn đang đặt trong vĩ độ và kinh độ về phía sau. Điều này rất quan trọng vì phép chiếu Mercator khác nhau theo từng hướng, trong số các lý do khác. Ánh xạ X/Y của bạn cũng có vẻ ngược, vì Latitude là vị trí Bắc/Nam của bạn, nên là toạ độ Y khi được chiếu và Kinh độ là vị trí Đông/Tây của bạn, nên là tọa độ X khi được chiếu.

Để tìm các giới hạn, cần three coordinate systems: Kinh độ/vĩ độ, tọa độ thế giới và tọa độ pixel. Quá trình này là Trung tâm Latinh - (Mercator Projection) -> Center World Coordinates -> Center Pixel Coordinates -> NE/SW Pixel Coordinates -> NE/SW World Coordinates - (Nghịch đảo Mercator Projection) -> NE/SW Lat/Lon .

Bạn tìm tọa độ pixel bằng cách cộng/trừ kích thước của hình ảnh/2. Hệ tọa độ pixel bắt đầu từ góc trên bên trái, do đó, để có góc NE bạn cần thêm chiều rộng/2 từ x và trừ chiều cao/2 từ y. Đối với góc SW bạn cần phải trừ chiều rộng/2 từ x và thêm chiều cao/2 đến y.

Dưới đây là mã chiếu (như là một phần của lớp GoogleMapsAPI của bạn) trong C#, dịch từ liên kết đầu tiên ở trên 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; 
} 

Bạn có thể kiểm tra mã javascript gốc để lấy ý kiến ​​chi tiết hơn.

Tôi đã thử nghiệm nó bằng cách xấp xỉ các ranh giới theo cách thủ công và sau đó so sánh với câu trả lời mà mã đã đưa ra. Khoảng cách thủ công của tôi cho góc NE là (51.15501, 4.796695) và mã nhổ ra (51.155005..., 4.797038...) có vẻ khá gần. Góc gần đúng của SW là (51.154572, 4.796007), mã nhổ ra (51.154574..., 4.796006...).

Đây là một điều thú vị, tôi hy vọng điều này sẽ hữu ích!

EDIT: Nhận ra tôi đã không bao gồm các chức năng mới 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 }; 
} 

Chỉ cần nhớ để chắc chắn rằng bạn đã có Latitude và Longitude trong đó phải:

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

tôi biết mã không phải là lớn nhất, nhưng tôi hy vọng nó là rõ ràng.

+0

Cảm ơn bạn rất nhiều vì câu trả lời bằng văn bản, thật đáng buồn là 2 năm quá muộn :) – FrieK

+0

Cảm ơn bạn đã bỏ phiếu :) – peterjb

+0

Tôi rất nhiều trừ khi tôi nhân 'Math.Pow (2, zoom)' với 2. Tôi cũng so sánh với các nguồn khác và thử tất cả các biến thể nhỏ. Bất kỳ ý tưởng tại sao đó là? – clankill3r

Các vấn đề liên quan