使用voronoi / delaunay图生成库in this program,它基于Fortune的his algorithm原始实现,随机点集作为输入数据,我能够获取以下输出数据:
以下是使用此库对我的程序进行测试运行的数据示例:
Input points:
0 (426.484, 175.16)
1 (282.004, 231.388)
2 (487.891, 353.996)
3 (50.8574, 5.02996)
4 (602.252, 288.418)
Vertex Pairs:
0 (387.425, 288.533) (277.142, 5.15565)
1 (387.425, 288.533) (503.484, 248.682)
2 (277.142, 5.15565) (0, 288.161)
3 (387.425, 288.533) (272.213, 482)
4 (503.484, 248.682) (637.275, 482)
5 (503.484, 248.682) (642, 33.7153)
6 (277.142, 5.15565) (279.477, 0)
Voronoi lines?:
0 (279.477, 0) (277.142, 5.15565)
1 (642, 33.7153) (503.484, 248.682)
2 (503.484, 248.682) (637.275, 482)
3 (387.425, 288.533) (272.213, 482)
4 (277.142, 5.15565) (0, 288.161)
5 (387.425, 288.533) (503.484, 248.682)
6 (277.142, 5.15565) (387.425, 288.533)
Delaunay Edges:
0 (282.004, 231.388) (487.891, 353.996)
1 (602.252, 288.418) (487.891, 353.996)
2 (426.484, 175.16) (487.891, 353.996)
3 (426.484, 175.16) (602.252, 288.418)
4 (50.8574, 5.02996) (282.004, 231.388)
5 (426.484, 175.16) (282.004, 231.388)
6 (50.8574, 5.02996) (426.484, 175.16)
Vertices:
0 (277.142, 5.15565)
1 (503.484, 248.682)
2 (387.425, 288.533)
3 (0, 288.161)
4 (272.213, 482)
5 (637.275, 482)
6 (642, 33.7153)
7 (279.477, 0)
虽然如果我只需要绘制Voronoi和Delaunay图表,上述数据就足够了,但对于我试图用这些图表进行的实际工作来说,这些信息还不够。 我需要的是由Voronoi顶点形成的多边形字典,由每个多边形形成的输入点索引。优选地,对于每个多边形,这些点将按顺时针顺序排序。
根据上述信息,我可以隐式地为每个区域分配数据,必要时将数据分配给角落,告诉哪些区域共享边缘(使用Delaunay边缘),并相应地进行分析。
简而言之,如何使用我可用的数据将一个字典放在一起,其中键是输入点之一,而该键索引的数据是Voronoi顶点的列表,形成周围的多边形?或者,我所提供的数据中隐含的信息是什么?
答案 0 :(得分:11)
Fortune的算法是O(n log n) - 但是如果你尝试重建Alink提出的细胞暴力方式,你的代码将是O(n ^ 2)。
我的答案的出发点是,您用于生成单元格的不是库,而是a class written to neatly wrap up the code originally presented by Fortune himself,而实际上并不是一个成熟的库。因此,作者实际上没有预料到您的需求,虽然您想要的信息已经计算出来,但却无法访问。
在内部,您的输入点存储为“Site”结构的实例,算法继续创建half-edges,每个都维护一个引用“vertex”,它是指向站点的指针它包含。沿着半边走,你自然环绕着封闭的网站 - 正是你需要的。
为了访问这些数据,我建议修改或扩展VoronoiDiagramGenerator类;我会通过创建一个散列表来实现它,其中Site指针作为键,单个HalfEdge指针作为值。然后,修改generateVoroni方法,在调用voronoi之后立即插入新代码:
For each HalfEdge in ELHash
Get table entry for current half edge's Site
If site in table has null HalfEdge reference
set current HalfEdge reference
End If
End For each
...还有你的字典。单个半边将允许您“走”围绕相关站点的多边形的周长,我认为这就是您所要求的。您的下一个问题是有效地发现哪个多边形包含一些新的数据点 - 但这是另一个问题:-)。我希望你能考虑分享你完成的课程 - 它应该比基础课程更有用。
编辑: 以下是图片中所有上述内容的精彩演示:http://ima.udg.es/~sellares/ComGeo/Vor2D_1.ppt:
这是一个C#实现,它可以帮助您检索字典,如上所述:http://www.codeproject.com/Articles/11275/Fortune-s-Voronoi-algorithm-implemented-in-C
答案 1 :(得分:3)
你的边缘列表在某种程度上是不完整的,你需要在提供给库调用的包含矩形的边界处添加那些边缘(这里似乎是642,482)。从技术上讲,Voronoi细分应该使用一些无限边,但那些都是有限的。我假设你也希望在这个边界附近有这些“开放”的多边形,因为它们就像你的例子中那样。
添加边框边缘似乎并不难,只是单调乏味。可能类似于,对于主矩形的每一侧,找到它上面的所有顶点(忽略角),对它们进行排序(对于水平对象,按x,对于垂直对象,按y),并使用这些值对该边进行分割。这会生成缺失的边缘,但不要将它们直接添加到主列表中,因为它们是特殊的,因为它们是唯一不分离两个单元格的边缘。
所以,对于问题本身,我会这样: 在你的主要边缘列表中(由库提供),每个边缘分隔两个单元格,如果我们找到哪些单元格,那么我们可以将该边缘分配给这些单元格中的每一个。由于单元格相当于一个输入点,我们将需要字典,除了边缘列表而不是顶点,但这很容易转换。
现在获取这两个单元格: 计算边缘的中间点,然后通过简单地遍历列表同时保持2个最小距离来找到两个最近的输入点。根据Voronoi结构的特性,这两个是形成两个单元的结构。请注意,这两个距离应该相等,但浮动不精确可能会引起一些细微差别。
要完成,请添加沿主矩形生成的边框边缘,但对于这些边缘,只需使用第一个最近的输入点,因为它们仅与一个单元格相邻。
最后,我们可以将每个边缘列表转换为顶点列表(将每个端点转储到一个集合中)。如果要按顺时针顺序对它们进行排序,请注意它是一个带有输入点的凸多边形。因此,您可以生成从输入点到每个顶点的向量,从一个轴计算其角度(使用std :: atan2(x,y))并使用此角度作为比较器值对它们进行排序(请参阅std ::排序)。
答案 2 :(得分:1)
我使用Triangle包生成Dalaunay三角测量:http://www.cs.cmu.edu/~quake/triangle.html
它以2种模式工作a)作为triangulate.exe实用程序,b)作为C库 要将其编译为实用程序,只需编译triangle.c并运行:
triangulate -vZ input.poly
#v -voronoy, Z - starting from 0 index
获取voronoi图(请参阅有关.poly format的手册) 我在这样的.poly文件中对您的输入数据进行了实验:
# <# of vertices> <dimension (must be 2)> <# of attributes> <# of boundary markers (0 or 1)>
5 2 0 0
# Following lines: <vertex #> <x> <y> [attributes] [boundary marker]
0 426.484 175.16
1 282.004 231.388
2 487.891 353.996
3 50.8574 5.02996
4 602.252 288.418
#One line: <# of segments> <# of boundary markers (0 or 1)>
5 0
#Following lines: <segment #> <endpoint> <endpoint> [boundary marker]
0 0 1
1 1 2
2 2 3
3 3 4
4 4 0
但它只是报告输入数据错误。
答案 3 :(得分:0)
你可以使用Triangle:http://www.cs.cmu.edu/~quake/triangle.html
答案 4 :(得分:0)
http://svn.osgeo.org/qgis/trunk/qgis/python/plugins/fTools/tools/voronoi.py
Carson Farmer的这个python实现为您提供拓扑信息