C# SharpMap WMTS/TMS服务器实现

C# SharpMap WMTS/TMS服务器实现,c#,gis,sharpmap,ogc,geoapi,C#,Gis,Sharpmap,Ogc,Geoapi,有人能帮我在SharpMap中实现WMTS/TMS服务器吗 我从不同的渠道尝试了很多,但我似乎没有找到一个有效的解决方案。下面是我正在使用的一个处理程序,它只是绘制框,而不是数据库中的数据。我使用与WMS服务器相同的方法: DatabaseUtil.SqlServer(ConnectionString(), Layers(), new Size(1, 1), bbox, "id"); 从SQL Server中获取数据,并且它对WMS工作正常。唯一的区别是,下面的方法通过使用.FindAll(l

有人能帮我在SharpMap中实现WMTS/TMS服务器吗

我从不同的渠道尝试了很多,但我似乎没有找到一个有效的解决方案。下面是我正在使用的一个处理程序,它只是绘制框,而不是数据库中的数据。我使用与WMS服务器相同的方法:

DatabaseUtil.SqlServer(ConnectionString(), Layers(), new Size(1, 1), bbox, "id");
从SQL Server中获取数据,并且它对WMS工作正常。唯一的区别是,下面的方法通过使用
.FindAll(lyr=>lyr.Table.Equals(layer))
query返回一个特定的层而不是列表

/// <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;
        }
    }
}

经过一些调试,我发现我的
GetBoundingBoxInLatLngWithMargin(int-tileX、int-tileY、int-zoom)
返回的边界超出了我的数据边界。我意识到我正在对我的bbox应用坐标变换,给我一个伪墨卡托的bbox,而我的图层是wgs84。我将
GetBoundingBoxInLatLngWithMargin
更改为:

//code omited
Envelope bbox = new Envelope();
bbox.ExpandToInclude(ll1.X, ll1.Y );
bbox.ExpandToInclude(ll2.X, ll2.Y);
return bbox;

请查看

I上的完整对话,是否支持此功能?SharpMap可以用作WMTS/TMS客户端,但我不认为它可以用作服务器。从示例来看,这是有可能的。我使用SQLServer作为数据源,自己设置了一个WMS服务器。我还看到了一个UTFGrid示例,它让我相信它可以被使用。你能指出github上的示例吗?@pauldendulk,在你找到的示例文件夹中。
//code omited
Envelope bbox = new Envelope();
bbox.ExpandToInclude(ll1.X, ll1.Y );
bbox.ExpandToInclude(ll2.X, ll2.Y);
return bbox;