我正在将 WMS 与 Telerik 地图集成。在 Telerik 论坛中,我发现一些示例代码可以正常工作,直到缩放效果很好并且执行计算不正确,因为 MaxX 和 MinX 返回相同的值,而 Miny 和 Maxy 返回相同的值。我不太了解 QuadKey、BBox、Tilex、Tiley ... 的功能,以免更正代码。在这里,我将您的论坛 Telerik 中提供的示例代码。看看是否有人看到这个错误在哪里。
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 的值也不同。
我不知道十进制和双精度是否有问题。
谢谢和对不起我的英语