我有一个大的地理点数据集(大约22000点,但未来我可能会更多),我需要计算他们的Voronoï图。我首先将我的点从(lat,lng)
投射到(x,y)
(使用Leaflet中的latLngToLayerPoint()),然后根据Javascript implementation of Fortune's algorithm 计算图表。我恢复了图表的每个单元格,或更精确地va
和vb
,分别为:
“Voronoi.Vertex对象,其x和y属性定义了开始 这个Voronoi.Edge的点(相对于左边的Voronoi站点) 对象“。
和
“Voronoi.Vertex对象,其x和y属性定义结束 这个Voronoi.Edge的点(相对于左边的Voronoi站点) 对象“。
(参见文献资料)
最后,我投射这些点以使用传单显示图表。我知道,为了计算图表,每个点都需要是唯一的,所以我在计算图表之前就删除了重复项。但问题是,我的结果非常糟糕(非节点交叉点,复杂多边形):
特写
我在图中有洞,我不知道为什么。积分是房子地址所以其中一些,即使它们不相等,也真的(非常)接近。我想知道问题是否来自预测(如果(lat1,lng1)
和(lat2,lng2)
几乎相等,(x1,y1)
和(x2,y2)
是否等于?)。我强烈怀疑这是问题的来源,但我不知道如何解决(建立一个门槛?)
编辑:我确切地说我在投影后删除了重复项,所以它不是关于投影的精确度,而是关于如果两个点相距一个像素会发生什么?
答案 0 :(得分:1)
所以我找到了我的问题的解决方案,我发布它以防任何人需要使用Leaflet和Turf在地图上计算Voronoï图并且在实施Fortune算法时遇到麻烦(直到turf-voronoi工作)。 Other sources of how to compute a Voronoï diagram on map can be found (but using d3)(我认为d3也使用Fortune算法的这个Javascript实现)
问题不是由数据集的大小或点的接近度引起的,而是由我如何恢复单元格引起的。
首先,您需要将您的观点从(lat,lng)
投射到(x,y)
(使用latLngToLayerPoint()
),计算图表:voronoi.compute(sites,bbox)
,其中网站是您的点这个[ {x: 200, y: 200}, {x: 50, y: 250}, {x: 400, y: 100} /* , ... */ ]
(请注意,您的网站需要唯一),如果您希望当前缩放的屏幕边框成为您的bbox juste,请使用:
var xl = 0,
xr = $(document).width(),
yt = 0,
yb = $(document).height();
一旦你计算了图表,只需恢复单元格(carfull,如果你想要正确的多边形,你需要边缘是逆时针排序的(或顺时针排序,但你要对它们进行排序),幸好算法提供了一半逆时针顺序给定Voronoï.Vertex
的边缘)。要恢复每个单元格的顶点,您可以使用getStartpoint()
或getEndpoint()
,而不要忘记将它们从(x,y)
投射回(lat,lng)
(使用layerPointToLatLng()
)
diagram.cells.forEach(function (c) {
var edges=[];
var size = c.halfedges.length;
for (var i = 0; i < size; i++) {
var pt = c.halfedges[i].getEndpoint();
edges.push(map.layerPointToLatLng(L.point(pt.x,pt.y)));
};
voronoi_cells.push(L.polygon(edges));
});
最后,您必须使用FeatureCollection
来显示图表:
答案 1 :(得分:0)
我强烈建议您不要自己实施Voronoi tesselation算法,而是使用https://github.com/Turfjs/turf-voronoi代替。