简单插件编写leaflet-pip-v2
github源码在此,记得点星:
https://github.com/brandonxiang/leaflet-pip-v2
在学习了leaflet之后,你可能会注意到它的插件,生态丰富,实用有效。当然,你也可以写一些满足自己需求的插件。相对而言,这有点难度。
而leaflet的插件而言,我将其分为两大类:
- 自成一类的数据处理型
- L.extend的继承扩展型 3进阶插件编写geojsonFilter
这篇笔记主要写的是前者。受leaflet-pip插件启发,点与线之间的数据选择进行扩展。你可以先参考mapbox/leaflet-pip,再看我的这段代码brandonxiang/leaflet-pip-v2,再做调整。如果还是很难理解,那就看demo。
Demo
不难看出,leaflet-pip的本意是通过点选择面,与点产生包含关系的多边形被选择,我将其设置为红色。
而leaflet-pip-v2的想法是通过面去选择点,与面积相交的点被选择,我将其设置成半透明。
原理
本插件的目标是去完成一个找出点与面包含关系的查询,即Point in Polygon(pip)。当然,方法很多,你可以使用空间查询,那可以是后端技术利用空间数据库。方法可以参考substack/point-in-polygon以及maxogden/geojson-js-utils,而mapbox/leaflet-pip则是利用过这两个库。
原理都是[PNPOLY](https://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html#The Method)。原理大概是将多边形分成多个三角形,判断点是否在三角形内。而凸三角形或凹三角形可能影响判断点是否在多边形。C语言代码如下,可以被改写为其它语言。
参数 | 意义 |
---|---|
nvert | 多边形顶点数 |
vertx,verty | 顶点的x和y数组 |
testx,testy | 测试点的x和y |
int pnpoly(int nvert, float *vertx, float *verty, float testx, float testy)
{
int i, j, c = 0;
for (i = 0, j = nvert-1; i < nvert; j = i++) {
if ( ((verty[i]>testy) != (verty[j]>testy)) &&
(testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
c = !c;
}
return c;
}
利用leaflet选点在某个多边形内
leaflet-pip是通过点要素的相交关系从多面状GeoJSON中选择一个面状,但是我的想法是通过面要素的相交关系从点的GeoJSON中选择多个点。这两个处理过程都基于同样的原理--空间查询。
使用方法
var selectedpoints = leafletPip.pointsInPolygon(
L.geoJson(point.geojson),L.geoJson(singlepolygon.geojson)
);
源码剖析
引用了geojson-utils内的其中一个方法,用于判断点是否在面之类,所以原理十分简单。即是将点图层循环,查找它是否在多边形内部。如果是,将其返回即可。在这里极度推荐各位GISER看看maxogden/geojson-js-utils的源码。
pointsInPolygon: function(points, layer) {
'use strict';
var results = [];
points.eachLayer(function(p) {
if (gju.pointInPolygon(p.toGeoJSON().geometry, layer.toGeoJSON().geometry)) {
results.push(p);
}
});
return results;
}
转载,请表明出处。总目录Awesome GIS