使用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、获取地图视窗的范围和宽高

复制代码
// 获取地图视窗bounds
            const mapBounds = map.getBounds();
            const bbox = `${mapBounds._southWest.lng},${mapBounds._southWest.lat},${mapBounds._northEast.lng},${mapBounds._northEast.lat}`;
            // 获取地图视窗的宽高
            const mapClientHeight = map._container.clientHeight;
            const mapClientWidth = map._container.clientWidth;

            const size = map.getSize();

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

复制代码
// 获取geometry的最小外包矩形
                const geoBounds = geo.getBounds();
                params.BBOX = geoBounds.toBBoxString();
                // 计算四个点的像素位置
                // 右上角
                const _northEast = geoBounds._northEast;
                // 左下角
                const _southWest = geoBounds._southWest;
                // 转为屏幕坐标
                let northEastPoint = map.latLngToContainerPoint(_northEast, map.getZoom());
                let southWestPoint = map.latLngToContainerPoint(_southWest, map.getZoom());

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

复制代码
// x,y坐标差
                const xf = Math.abs(northEastPoint.x - southWestPoint.x);
                const yf = Math.abs(southWestPoint.y - northEastPoint.y);
                // 设置图片的宽高,为x,y坐标差
                params.width = Math.floor(xf);
                params.height = Math.floor(yf);
                // 以图片宽高的一半为中心点
                params.X = Math.round(xf / 2);
                params.Y = Math.round(yf / 2);
                // 设置以中心点为圆心的缓冲半径(像素)
                // 以x,y屏幕坐标差大的设置buffer参数

                const buffer = xf > yf ? xf : yf;
                params.buffer = Math.round(buffer / 2);

3、拼接cql_filter过滤空间范围

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

4、查询返回结果

复制代码
$.ajax({
                url: url + L.Util.getParamString(params),
                success: (response) => {
                    console.log(response);
                    queryResultLayers.addLayer(L.geoJSON(response))
                }
            })

参考资料:

ECQL Reference --- GeoServer 2.23-SNAPSHOT User Manual

相关推荐
淡海水7 分钟前
02-07-原理篇-GC暂停时间的本质
开发语言·unity·c#·gc·暂停时间
骑着蜗牛撵大象32730 分钟前
豆包 Seed 驱动的记账智能体:从拍票抽取到月报生成的全链路落地记录
java·前端·javascript·结构化输出·豆包seed·多模态识别·记账系统
溪语流沙31 分钟前
【Web全栈进阶】前端世界观:现代工具链与框架为什么存在
前端·javascript·vue.js
kyriewen1 小时前
我逐个测了 JSON.stringify 的 7 个坑:第 1 个就在丢数据
前端·javascript·程序员
北i1 小时前
Dubbo 默认超时重试:把下游打雪崩的隐形放大器
开发语言·qt·dubbo
10mAh1 小时前
【Java】ArrayList 遍历删除为什么报错?三种写法与漏删复现
java·开发语言·windows
积流成海1 小时前
用代码实现哈希计算器:Web Crypto API 实战
前端·算法·哈希算法·哈希函数·盘子工具站
data analyse 4561 小时前
服务端访问日志聚合 PV 与 UV 怎么实现?日志采集与口径设计
大数据·前端·数据分析
song5011 小时前
React Native for OpenHarmony 实战:三方库 react-native-ratings 的鸿蒙化适配指南
javascript·react native·react.js·分类·harmonyos
JavaGuide2 小时前
DeepSeek Harness 重磅更新,Codex、Claude Code 子智能体进官方插件列表了,还有 Git 工作树和思考翻译!
前端·后端