2012-03-19 3 views
1

Telerik지도와 WMS를 통합합니다. Telerik 포럼에서 줌이 훌륭하게 작동 할 때까지 올바르게 작동하는 몇 가지 샘플 코드를 발견했으며 MaxX와 MinX가 동일한 값을 반환하고 Miny와 Maxy가 동일한 값을 반환하기 때문에 계산을 수행하는 것은 올바르지 않습니다. QuadKey, BBox, Tilex, Tiley ...의 기능을 이해하지 못하고 코드를 수정하지 않았습니다. 여기 포럼에 제공된 샘플 코드를 telerik에 넣습니다. 누군가이 오류의 위치를 ​​확인하십시오. 줌이 높을 때 나도 같은 값을 반환Telerik지도 + WMS

public class WMSCustomSource : TiledMapSource 
{ 
    private const string TileUrlFormat = @"http://www1.sedecatastro.gob.es/Cartografia/WMS/ServidorWMS.aspx?SERVICE=WMS&REQUEST=GetMap&SRS=EPSG:4326&BBOX={0},{1},{2},{3}&WIDTH={4}&HEIGHT={4}&Layers=Catastro&TRANSPARENT=TRUE&STYLES=PositionStyle&FORMAT=image/png"; 
    private const int TileSize = 256; 

    /// <summary> 
    /// Earth Circumference. 
    /// </summary> 
    private double earthCircumference; 
    private double halfEarthCircumference; 
    private double earthRadius; 

    /// <summary> 
    /// Initializes a new instance of the OSMCustomSource class. 
    /// </summary> 
    public WMSCustomSource(ISpatialReference spatialReference) 
     : base(1, 20, TileSize, TileSize) 
    { 
     this.earthRadius = spatialReference.SpheroidRadius; 
     this.earthCircumference = this.earthRadius * 2 * Math.PI; 
     this.halfEarthCircumference = this.earthCircumference/2d; 
    } 

    /// <summary> 
    /// Initialize provider. 
    /// </summary> 
    public override void Initialize() 
    { 
     // Raise provider intialized event. 
     this.RaiseIntializeCompleted(); 
    } 

    /// <summary> 
    /// Returns the bounding BBox for a grid square represented by the given quad key 
    /// </summary> 
    /// <param name="quadKey"></param> 
    /// <param name="x"></param> 
    /// <param name="y"></param> 
    /// <param name="zoomLevel"></param> 
    /// <returns></returns> 
    private BBOX ConvertQuadKeyToBBox(string quadKey, int x, int y, int zoomLevel) 
    { 
     char c = quadKey[0]; 

     int tileSize = 2 << (18 - zoomLevel - 1); 

     if (c == '0') 
     { 
      y = y - tileSize; 
     } 

     else if (c == '1') 
     { 
      y = y - tileSize; 
      x = x + tileSize; 
     } 

     else if (c == '3') 
     { 
      x = x + tileSize; 
     } 

     if (quadKey.Length > 1) 
     { 
      return ConvertQuadKeyToBBox(quadKey.Substring(1), x, y, zoomLevel + 1); 
     } 

     return new BBOX(x, y, tileSize, tileSize); 
    } 

    private BBOX ConvertQuadKeyToBBox(string quadKey) 
    { 
     const int x = 0; 
     const int y = 262144; 
     return ConvertQuadKeyToBBox(quadKey, x, y, 1); 
    } 

    /// <summary> 
    /// Converts radians to degrees 
    /// </summary> 
    /// <param name="d"></param> 
    /// <returns></returns> 
    private double RadiansToDegrees(double radians) 
    { 
     return radians/Math.PI * 180d; 
    } 

    /// <summary> 
    /// Converts a grid row to Latitude 
    /// </summary> 
    /// <param name="y"></param> 
    /// <param name="zoom"></param> 
    /// <returns></returns> 
    private double ConvertYToLatitude(int y, int zoom) 
    { 
     double arc = this.earthCircumference/((double)(1 << zoom) * (double)TileSize); 
     double metersY = this.halfEarthCircumference - ((double)y * (double)TileSize * arc); 
     double a = Math.Exp(metersY * 2d/this.earthRadius); 
     double result = RadiansToDegrees(Math.Asin((a - 1d)/(a + 1d))); 
     return result; 
    } 

    /// <summary> 
    /// Converts a grid column to Longitude 
    /// </summary> 
    /// <param name="x"></param> 
    /// <param name="zoom"></param> 
    /// <returns></returns> 
    private double ConvertXToLongitude(int x, int zoom) 
    { 
     double arc = this.earthCircumference/((double)(1 << zoom) * (double)TileSize); 
     double metersX = ((double)x * (double)TileSize * arc) - this.halfEarthCircumference; 
     double result = RadiansToDegrees(metersX/this.earthRadius); 
     return result; 
    } 

    private static string GetQuadKey(int tileX, int tileY, int levelOfDetail) 
    { 
     var quadKey = new StringBuilder(); 
     for (int i = levelOfDetail; i > 0; i--) 
     { 
      char digit = '0'; 
      int mask = 1 << (i - 1); 
      if ((tileX & mask) != 0) 
      { 
       digit++; 
      } 

      if ((tileY & mask) != 0) 
      { 
       digit++; 
       digit++; 
      } 

      quadKey.Append(digit); 
     } 

     return quadKey.ToString(); 
    } 

    /// <summary> 
    /// Gets the image URI. 
    /// </summary> 
    /// <param name="tileLevel">Tile level.</param> 
    /// <param name="tilePositionX">Tile X.</param> 
    /// <param name="tilePositionY">Tile Y.</param> 
    /// <returns>URI of image.</returns> 
    protected override Uri GetTile(int tileLevel, int tilePositionX, int tilePositionY) 
    { 
     int zoomLevel = ConvertTileToZoomLevel(tileLevel); 

     string quadKey = GetQuadKey(tilePositionX, tilePositionY, zoomLevel); 
     BBOX boundingBox = ConvertQuadKeyToBBox(quadKey); 

     **double longitude = ConvertXToLongitude(boundingBox.x, 18); 
     double latitude = ConvertYToLatitude(boundingBox.y, 18); 
     double longitude2 = ConvertXToLongitude(boundingBox.x + boundingBox.width, 18); 
     double latitude2 = ConvertYToLatitude(boundingBox.y - boundingBox.height, 18);** 

     string url = string.Format(CultureInfo.InvariantCulture, TileUrlFormat, 
      longitude, latitude, longitude2, latitude2, TileSize); 

     return new Uri(url); 


    } 

    /// <summary> 
    /// The box of the bounds of a tile 
    /// </summary> 
    private class BBOX 
    { 
     public int x; 
     public int y; 
     public int width; 
     public int height; 

     public BBOX(int x, int y, int width, int height) 
     { 
      this.x = x; 
      this.y = y; 
      this.width = width; 
      this.height = height; 
     } 
    } 
} 

기능은 다음과 같습니다 ConvertYToLatitude 및 ConvertXToLongitude. 비록 제가 X1과 X2에 제공하는 값이 다릅니다. 그리고 Y1과 Y2의 값도 다릅니다.

10 진수 및 2 진수로 문제가 될 수 있는지 알 수 없습니다.

내 영어를 사용해 주셔서 감사합니다.

+0

호세는 답변으로 솔루션을 게시 ..... – Simon

+0

OK 죄송합니다! 솔루션이 게시됩니다! – JoseMancebo

답변

2

해결책을 찾았습니다. 나는 마지막 클래스는 읽을 BBOX 에 쿼드 키를 변환 http://alastaira.wordpress.com/2011/01/07/accessing-a-wms-tile-server-from-bing-maps-v7/에서 발견 된 또 다른 함수를 사용

public class WMSCustomSource : TiledMapSource 
{ 

    private const string TileUrlFormat = @"http://www1.sedecatastro.gob.es/Cartografia/WMS/ServidorWMS.aspx?SERVICE=WMS&REQUEST=GetMap&SRS=EPSG:4326&BBOX={0}&WIDTH={1}&HEIGHT={1}&Layers=Catastro&TRANSPARENT=TRUE&STYLES=PositionStyle&FORMAT=image/png"; 
    private const int TileSize = 256; 

    /// <summary> 
    /// Earth Circumference. 
    /// </summary> 
    private double earthCircumference; 
    private double halfEarthCircumference; 
    private double earthRadius; 

    /// <summary> 
    /// Initializes a new instance of the OSMCustomSource class. 
    /// </summary> 
    public WMSCustomSource(ISpatialReference spatialReference) 
     : base(1, 20, TileSize, TileSize) 
    { 
     this.earthRadius = spatialReference.SpheroidRadius; 
     this.earthCircumference = this.earthRadius * 2 * Math.PI; 
     this.halfEarthCircumference = this.earthCircumference/2d; 
    } 

    /// <summary> 
    /// Initialize provider. 
    /// </summary> 
    public override void Initialize() 
    { 
     // Raise provider intialized event. 
     this.RaiseIntializeCompleted(); 
    } 



    public string QuadKeyToBBox(string quadKey) 
    { 

     int zoom = quadKey.Length; 
     int x = 0, y = 0; 
     // Work out the x and y position of this tile 

     for (int i = zoom; i > 0; i--) 
     { 
      int mask = 1 << (i - 1); 
      switch (quadKey[zoom - i]) 
      { 
       case '0': 
        break; 
       case '1': 
        x |= mask; 
        break; 
       case '2': 
        y |= mask; 
        break; 
       case '3': 
        x |= mask; 
        y |= mask; 
        break; 
       default: 
        throw new ArgumentException("Invalid QuadKey digit sequence."); 
      } 
     } 
     // From the grid position and zoom, work out the min and max Latitude/Longitude values of this tile 
     double W = (float)(x * TileSize) * 360/(float)(TileSize * Math.Pow(2, zoom)) - 180; 

     double N = (float)Math.Asin((Math.Exp((0.5 - (y * TileSize)/(TileSize)/Math.Pow(2, zoom)) * 4 * Math.PI) - 1)/(Math.Exp((0.5 - (y * TileSize)/256/Math.Pow(2, zoom)) * 4 * Math.PI) + 1)) * 180/(float)Math.PI; 

     double E = (float)((x + 1) * TileSize) * 360/(float)(TileSize * Math.Pow(2, zoom)) - 180; 
     double S = (float)Math.Asin((Math.Exp((0.5 - ((y + 1) * TileSize)/(TileSize)/Math.Pow(2, zoom)) * 4 * Math.PI) - 1)/(Math.Exp((0.5 - ((y + 1) * TileSize)/256/Math.Pow(2, zoom)) * 4 * Math.PI) + 1)) * 180/(float)Math.PI; 

     double[] bounds = new double[] { W, S, E, N }; 

     // Return a comma-separated string of the bounding coordinates 
     return string.Join(",", Array.ConvertAll(bounds, s => s.ToString().Replace(',','.'))); 
    } 


    /// <summary> 
    /// Converts radians to degrees 
    /// </summary> 
    /// <param name="d"></param> 
    /// <returns></returns> 
    private double RadiansToDegrees(double radians) 
    { 
     return radians/Math.PI * 180d; 
    } 

    /// <summary> 
    /// Converts a grid row to Latitude 
    /// </summary> 
    /// <param name="y"></param> 
    /// <param name="zoom"></param> 
    /// <returns></returns> 
    private double ConvertYToLatitude(int y, int zoom) 
    { 
     double arc = this.earthCircumference/((double)(1 << zoom) * (double)TileSize); 
     double metersY = this.halfEarthCircumference - ((double)y * (double)TileSize * arc); 
     double a = Math.Exp(metersY * 2d/this.earthRadius); 
     double result = RadiansToDegrees(Math.Asin((a - 1d)/(a + 1d))); 
     return result; 
    } 

    /// <summary> 
    /// Converts a grid column to Longitude 
    /// </summary> 
    /// <param name="x"></param> 
    /// <param name="zoom"></param> 
    /// <returns></returns> 
    private double ConvertXToLongitude(int x, int zoom) 
    { 
     double arc = this.earthCircumference/((double)(1 << zoom) * (double)TileSize); 
     double metersX = ((double)x * (double)TileSize * arc) - this.halfEarthCircumference; 
     double result = RadiansToDegrees(metersX/this.earthRadius); 
     return result; 
    } 

    private static string GetQuadKey(int tileX, int tileY, int levelOfDetail) 
    { 
     var quadKey = new StringBuilder(); 
     for (int i = levelOfDetail; i > 0; i--) 
     { 
      char digit = '0'; 
      int mask = 1 << (i - 1); 
      if ((tileX & mask) != 0) 
      { 
       digit++; 
      } 

      if ((tileY & mask) != 0) 
      { 
       digit++; 
       digit++; 
      } 

      quadKey.Append(digit); 
     } 

     return quadKey.ToString(); 
    } 

    /// <summary> 
    /// Gets the image URI. 
    /// </summary> 
    /// <param name="tileLevel">Tile level.</param> 
    /// <param name="tilePositionX">Tile X.</param> 
    /// <param name="tilePositionY">Tile Y.</param> 
    /// <returns>URI of image.</returns> 
    protected override Uri GetTile(int tileLevel, int tilePositionX, int tilePositionY) 
    { 
     int zoomLevel = ConvertTileToZoomLevel(tileLevel); 

     string quadKey = GetQuadKey(tilePositionX, tilePositionY, zoomLevel); 

     **string bbox = QuadKeyToBBox(quadKey);** 

     string url = string.Format(CultureInfo.InvariantCulture, TileUrlFormat, bbox, TileSize); 

     return new Uri(url); 
    } 


} 
관련 문제