如何在Leaflet地图中添加经多边形裁剪的Voronoi图?
实现多边形裁剪的Voronoi图方案
方案一:d3-delaunay + Turf.js 二次裁剪
d3-delaunay仅支持矩形裁剪,但可结合现代GIS处理库Turf.js完成多边形裁剪,步骤如下:
- 先通过d3-delaunay生成基于边界外接矩形的Voronoi图,过滤掉明显在边界外的Voronoi多边形
- 遍历每个Voronoi多边形,将其与你的边界多边形做交集运算,保留落在边界内的部分
- 将裁剪后的多边形转换为GeoJSON格式,添加到Leaflet地图
核心代码示例
// 假设points是区域内点的经纬度数组,boundary是边界多边形的GeoJSON const [xmin, ymin, xmax, ymax] = d3.extent(points, d => d[0]).concat(d3.extent(points, d => d[1])); const delaunay = d3.Delaunay.from(points.map(p => [p[0], p[1]])); const voronoi = delaunay.voronoi([xmin, ymin, xmax, ymax]); // 遍历每个Voronoi多边形 const clippedVoronoi = []; for (let i = 0; i < points.length; i++) { const cell = voronoi.cellPolygon(i); if (!cell) continue; // 转换为Turf支持的Polygon格式 const voronoiPoly = turf.polygon([cell]); // 计算与边界的交集 const clipped = turf.intersect(voronoiPoly, boundary); if (clipped) { clippedVoronoi.push(clipped); } } // 添加到Leaflet地图 L.geoJSON(clippedVoronoi, { style: { fillColor: '#ccc', weight: 1 } }).addTo(map);
方案二:使用支持多边形裁剪的Voronoi库
直接使用原生支持任意多边形裁剪的现代Voronoi库,避免二次裁剪的性能损耗,推荐**@thi.ng/voronoi**(活跃维护的功能库):
- 支持将自定义多边形作为裁剪区域,直接生成符合边界的Voronoi图
- 需注意坐标转换:Leaflet的经纬度是球面坐标,需先转换为平面坐标(如EPSG3857)再计算,完成后转回经纬度
核心代码示例
import { voronoi } from "@thi.ng/voronoi"; // 将经纬度转换为平面坐标(EPSG3857) const project = (latlng) => { const point = L.CRS.EPSG3857.project(L.latLng(latlng)); return [point.x, point.y]; }; // 将平面坐标转回经纬度 const unproject = (point) => { const latlng = L.CRS.EPSG3857.unproject(L.point(point[0], point[1])); return [latlng.lng, latlng.lat]; }; // 准备平面坐标的点和边界 const planarPoints = points.map(project); const planarBoundary = boundary.geometry.coordinates[0].map(project); // 生成带多边形裁剪的Voronoi图 const result = voronoi({ points: planarPoints, clipPolygon: planarBoundary }); // 转换为GeoJSON并添加到地图 const geojson = { type: "FeatureCollection", features: result.cells.map(cell => ({ type: "Feature", geometry: { type: "Polygon", coordinates: [cell.map(unproject)] } })) }; L.geoJSON(geojson, { style: { fillColor: '#ccc', weight: 1 } }).addTo(map);
关键注意事项
- 坐标转换:所有多边形计算需在平面坐标系下进行,避免球面坐标带来的误差
- 性能优化:提前过滤掉边界外的点,减少无效计算;点数量极大时可考虑分块处理
- 边界兼容性:确保边界多边形是闭合的、无自相交的单连通多边形,否则裁剪库可能出错
内容的提问来源于stack exchange,提问作者Alasdair
相关产品推荐
相关产品推荐

