• 使用Leaflet对WMS做空间几何范围查询


    一、需求

           使用GeoServer发布的WMS服务对WMS做空间范围查询,默认情况下WMS支持点击查询,网上有很多的资料不在赘述。那么WMS做几何查询该怎么实现呢?

    二、实现路径

            查询WMS查询的服务参数,WMS支持三种请求方式:GetCapabilities、GetMap、GetFeatureInfo。其中GetCapabilities获取WMS服务的元数据信息,GetMap用于出图;GetFeatureInfo获取属性信息,我们查询需要的是GetFeatureInfo请求方式,参数结果如下:

    GetFeatureInfo操作请求地图上给定位置处要素的空间和属性数据它类似于WFS GetFeature操作,但在输入和输出方面不太灵活。由于 GeoServer 提供了 WFS 服务,我们建议尽可能使用它GetFeatureInfo

    其优点之一GetFeatureInfo是请求使用返回的WMS图像中的 (x,y) 像素值。对于无法执行真实地理参考的天真的客户端来说,这更容易使用。

    这里面大部分的都是跟出图参数相关的参数,重点关注x和y这两个参数,使用的像素坐标值,需要用leaflet进行转化。

    空间查询的参数主要是以下几个:

         通过buffer可以做缓冲半径查询,通过cql_filter可以对返回的结果进行过滤,它支持ECQL格式,可以使用wkt语言文本格式传入空间条件,如下所示:

    所以空间几何查询思路如下:

    1. 获取当前地图绘制的几何范围
    2. 获取几何范围的最大外接矩形
    3. 计算缓冲半径,进行空间查询
    4. 通过cql_filter过滤空间范围的结果
    5. 结果渲染、实现路径

    三、代码实现

    1、获取地图视窗的范围和宽高

    1. // 获取地图视窗bounds
    2. const mapBounds = map.getBounds();
    3. const bbox = `${mapBounds._southWest.lng},${mapBounds._southWest.lat},${mapBounds._northEast.lng},${mapBounds._northEast.lat}`;
    4. // 获取地图视窗的宽高
    5. const mapClientHeight = map._container.clientHeight;
    6. const mapClientWidth = map._container.clientWidth;
    7. const size = map.getSize();

    2、获取当前地图绘制的几何范围和外接矩形

    1. // 获取geometry的最小外包矩形
    2. const geoBounds = geo.getBounds();
    3. params.BBOX = geoBounds.toBBoxString();
    4. // 计算四个点的像素位置
    5. // 右上角
    6. const _northEast = geoBounds._northEast;
    7. // 左下角
    8. const _southWest = geoBounds._southWest;
    9. // 转为屏幕坐标
    10. let northEastPoint = map.latLngToContainerPoint(_northEast, map.getZoom());
    11. let southWestPoint = map.latLngToContainerPoint(_southWest, map.getZoom());

    3、根据外接矩形的宽高计算缓冲半径

    1. // x,y坐标差
    2. const xf = Math.abs(northEastPoint.x - southWestPoint.x);
    3. const yf = Math.abs(southWestPoint.y - northEastPoint.y);
    4. // 设置图片的宽高,为x,y坐标差
    5. params.width = Math.floor(xf);
    6. params.height = Math.floor(yf);
    7. // 以图片宽高的一半为中心点
    8. params.X = Math.round(xf / 2);
    9. params.Y = Math.round(yf / 2);
    10. // 设置以中心点为圆心的缓冲半径(像素)
    11. // 以x,y屏幕坐标差大的设置buffer参数
    12. const buffer = xf > yf ? xf : yf;
    13. params.buffer = Math.round(buffer / 2);

    3、拼接cql_filter过滤空间范围

    1. // geojson 跟 wkt 相互转换
    2. const wktReader = new Wkt.Wkt();
    3. const wkt = wktReader.read(JSON.stringify(geometry));
    4. // 二次过滤,设置过滤的空间范围
    5. params.CQL_FILTER = `INTERSECTS(the_geom,${wkt.write()})`;
    6. }

    4、查询返回结果

    1. $.ajax({
    2. url: url + L.Util.getParamString(params),
    3. success: (response) => {
    4. console.log(response);
    5. queryResultLayers.addLayer(L.geoJSON(response))
    6. }
    7. })

    参考资料:

    ECQL Reference — GeoServer 2.23-SNAPSHOT User Manual

  • 相关阅读:
    [附源码]计算机毕业设计JAVA学生实习管理系统
    0基础学习Elasticsearch-使用Java操作ES
    多级式多传感器信息融合中的状态估计(Matlab代码实现)
    40-Jenkins-环境变量的使用
    ChainForge:衡量Prompt性能和模型稳健性的GUI工具包
    vue3学习-1配置以及启动
    [汇编语言]寄存器(内部访问)
    Linux 操作系统启动流程1
    1.2.OpenCV技能树--第一单元--OpenCV安装
    Java源码分析(一)Integer
  • 原文地址:https://blog.csdn.net/u010499087/article/details/133078595