2016-05-03 14 views
2

UnityアプリケーションでGoogle Static Mapの境界を取得する際に問題があります。私はここで複数の答えをstackoverflowで見つけてみました。Google Static Maps APIのSW&NEコーナーを取得

.NET related question

Javascript related question

私はコーナーを計算しようとしているマップは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に直面していましたが、すでにC#のjavascriptの回答を翻訳していて、彼のコードがGoogleの静的マップの正しい範囲を取得している例もありました。だから、peterjbのコードを次のクラスに入れてみてください。

このSouthWest:51.438825、5.453483ノースイースト:51.452557、5.467153

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

は、私は次の

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

出力を呼び出すことによって、再びSWと北東の角を計算してみました

SouthWestの座標は自分の翻訳と全く同じですJavaScriptの。ベルギーのある地域で彼の解決策が働いたという彼の答えでpeterjbが主張して以来、私は同じ地域でコードを試してみました。しかし、結果はもう少しだった。

ナイジェリアの町の計算を使ってみましたが、Kano/Static mapという名前で、南西部のコーナーは非常に正確でした。

出力:

このSouthWest:12.015251、8.527824ノースイースト:12.028983、8.541404

SouthWest position

私はその後、世界中で複数のエリアを試しましたが、しばしば途方もなく、時には数百マイルにも及んでいました。ナイジェリアのこの町はちょうど偶然だったかもしれませんが、私は誰かが私のために説明や解決策を持っていることを願っています。ご想像のとおり

座標クラスのpeterjbmarcelo

+0

関連情報:https://alastaira.wordpress.com/2011/01/23/the-google-maps-bing-maps-spherical-mercator-projection/ –

+0

こんにちはLeniaal、私はあなたの座標コンストラクタはlng、latとしてパラメータをとりますが、lat、lngで渡しています。 latとlngがほぼ同じなので、Kanoの例はおそらく近くにあります。私はこれが助けてくれることを願っています。 – peterjb

+0

あなたの時間と興味に感謝します。あなたは正しい、私はこれを見落としたとは思えない。私は問題を盲目的に見つめていたので、気づいたことにとてもうれしく思います。あなたが好きなら、あなたはそれを答えとして加えることができるので、この質問に答えることができます。 – Leniaal

答えて

0

コンストラクタに感謝ではなく、(緯度、LNG)の(LNG、緯度)を受け入れ、あなたが渡しているよりも、パラメータが異なる順序であるので、

CoordinateのToStringオーバーライドも(lng、lat)として印刷されていることに気づいたので、(lat、lng)を見たい場合は混乱する可能性があります。

これらの両方を静的APIで交換するだけです。

関連する問題