谁能帮我在 SharpMap 中实施 WMTS / TMS 服务器?
我一直在尝试从差异来源进行很多尝试,但我似乎无法提出一个可行的解决方案。下面是我正在使用的处理程序,它只是绘制框而不是数据库中的数据。我正在使用与 WMS 服务器相同的方法:
DatabaseUtil.SqlServer(ConnectionString(), Layers(), new Size(1, 1), bbox, "id");
从 SQL Server 获取数据,它对 WMS 工作得很好。唯一的区别是下面的那个通过使用.FindAll(lyr => lyr.Table.Equals(layer))
查询返回一个特定的层而不是一个列表。
/// <summary>
/// Summary description for WMTS
/// </summary>
public class WMTS : IHttpHandler
{
/// <summary>
/// Defines the projection
/// </summary>
private readonly ICoordinateTransformation projection = ProjUtil.ToPseudoMercator();
/// <summary>
/// The ProcessRequest
/// wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=layer_id&STYLE=default&TILEMATRIXSET=matrix_id&TILEMATRIX=3&TILEROW=2&TILECOL=0&FORMAT=image%2Fjpeg
/// </summary>
/// <param name="context">The <see cref="HttpContext"/></param>
public void ProcessRequest(HttpContext context)
{
string layer = context.Request.Params["LAYER"];
int tilematrix = int.Parse(context.Request.Params["TILEMATRIX"]);
int tilerow = int.Parse(context.Request.Params["TILEROW"]);
int tilecol = int.Parse(context.Request.Params["TILECOL"]);
string service = context.Request.Params["SERVICE"];
string request = context.Request.Params["REQUEST"];
string version = context.Request.Params["VERSION"];
string style = context.Request.Params["STYLE"];
string tilematrixset = context.Request.Params["TILEMATRIXSET"];
string format = context.Request.Params["FORMAT"];
if (String.IsNullOrEmpty(layer))
throw new ArgumentNullException("layer");
Map map = Map(layer, tilecol, tilerow, tilematrix);
var map_image = map.GetMap();
//using (var memory_stream = new MemoryStream())
//{
// map_image.Save(memory_stream, ImageFormat.Png);
// var wms = memory_stream.ToArray();
// WriteResponseInChunks(wms, context);
//}
byte[] buffer;
using (var ms = new MemoryStream())
{
map_image.Save(ms, ImageFormat.Png);
map_image.Dispose();
buffer = ms.ToArray();
}
WriteResponseInChunks(buffer, context);
}
public static ImageCodecInfo GetEncoderInfo(String mimeType)
{
foreach (var encoder in ImageCodecInfo.GetImageEncoders())
if (encoder.MimeType == mimeType)
return encoder;
return null;
}
/// <summary>
/// The GetMap
/// </summary>
/// <returns>The <see cref="SharpMap.Map"/></returns>
protected Map Map(string layer, int x, int y, int z)
{
Envelope bbox = GetBoundingBoxInLatLngWithMargin(x, y, z);
return DatabaseUtil.SqlServer(ConnectionString(), Layers().FindAll(lyr => lyr.Table.Equals(layer)), new Size(1, 1), bbox, "id");
}
/// <summary>
/// The Layers
/// </summary>
/// <returns>The <see cref="List{VectorLayerModel}"/></returns>
private List<VectorLayerModel> Layers()
{
VectorLayerModel standsLayerModel = new VectorLayerModel()
{
Table = "cadastre",
Style = new VectorStyle { Line = new Pen(Color.DarkGray, 2) }
};
VectorLayerModel roadsLayerModel = new VectorLayerModel()
{
Table = "townships",
Style = new VectorStyle { Line = new Pen(Color.DarkRed, 2.5f) }
};
VectorLayerModel pipeLayerModel = new VectorLayerModel()
{
Table = "provinces",
Style = new VectorStyle { Line = new Pen(Color.DarkBlue, 1.5f) }
};
return new List<VectorLayerModel>() { standsLayerModel, roadsLayerModel, pipeLayerModel };
}
/// <summary>
/// The ConnectionString
/// </summary>
/// <returns>The <see cref="string"/></returns>
private string ConnectionString()
{
return "Data Source=******;Initial Catalog=GCCIGO_V2;Integrated Security=SSPI;";
}
/// <summary>
/// The GetBoundingBoxInLatLngWithMargin
/// </summary>
/// <param name="tileX">The <see cref="int"/></param>
/// <param name="tileY">The <see cref="int"/></param>
/// <param name="zoom">The <see cref="int"/></param>
/// <returns>The <see cref="Envelope"/></returns>
private Envelope GetBoundingBoxInLatLngWithMargin(int tileX, int tileY, int zoom)
{
Point px1 = new Point((tileX * 256), (tileY * 256));
Point px2 = new Point(((tileX + 1) * 256), ((tileY + 1) * 256));
PointF ll1 = TileSystemHelper.PixelXYToLatLong(px1, zoom);
PointF ll2 = TileSystemHelper.PixelXYToLatLong(px2, zoom);
double[] prj1 = projection.MathTransform.Transform(new double[] { ll1.X, ll1.Y });
double[] prj2 = projection.MathTransform.Transform(new double[] { ll2.X, ll2.Y });
Envelope bbox = new Envelope();
bbox.ExpandToInclude(prj1[0], prj1[1]);
bbox.ExpandToInclude(prj2[0], prj2[1]);
return bbox;
}
/// <summary>
/// The size of the chunks written to response.
/// </summary>
private const int ChunkSize = 2 * 8192;
/// <summary>
/// Method to write an array of bytes in chunks to a http response
/// </summary>
/// <remarks>
/// The code was adopted from http://support.microsoft.com/kb/812406/en-us
/// </remarks>
/// <param name="buffer">The array of bytes</param>
/// <param name="context">The response</param>
private static void WriteResponseInChunks(byte[] buffer, HttpContext context)
{
try
{
bool _continue;
context.Response.ClearContent();
context.Response.ContentType = "image/png";
using (var ms = new MemoryStream(buffer))
{
var dataToRead = buffer.Length;
while (dataToRead > 0)
{
if (context.Response.IsClientConnected)
{
{
var tmpBuffer = new byte[ChunkSize];
var length = ms.Read(tmpBuffer, 0, tmpBuffer.Length);
context.Response.OutputStream.Write(tmpBuffer, 0, length);
context.Response.Flush();
dataToRead -= length;
}
}
else
{
dataToRead = -1;
}
}
_continue = dataToRead > 0;
}
}
catch (Exception ex)
{
context.Response.ClearContent();
context.Response.ContentType = "text/plain";
context.Response.Write(string.Format("Error : {0}", ex.Message));
context.Response.Write(string.Format("Source : {0}", ex.Message));
context.Response.Write(string.Format("StackTrace: {0}", ex.StackTrace));
}
finally
{
context.Response.End();
}
}
/// <summary>
/// Gets a value indicating whether IsReusable
/// </summary>
public bool IsReusable
{
get
{
return true;
}
}
}
如果我只是提出创建代码可能会有所帮助SharpMap.Map
:
public static Map SqlServer(string conn, List<VectorLayerModel> layers, Size map_size, Envelope bbox, string id_column = "ID")
{
Map map = new Map(map_size);
foreach (var layer in layers)
{
VectorLayer lyr = CreateSqlServerLayer(conn, layer.Table, layer.Style, id_column);
lyr.IsQueryEnabled = true;
lyr.Enabled = true;
if (bbox != null)
{
var geometries = lyr.DataSource.GetGeometriesInView(bbox);
lyr.DataSource = new GeometryFeatureProvider(geometries);
}
map.Layers.Add(lyr);
}
return map;
}