We don’t allow questions seeking recommendations for software libraries, tutorials, tools, books, or other off-site resources. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
The community reviewed whether to reopen this question 2 years ago and left it closed:
Original close reason(s) were not resolved
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(14)
计算点集 Delaunay 三角剖分的一种简单算法是翻转边< /a>. 由于 Delaunay 三角剖分是 Voronoi 图的对偶图,因此您可以在线性时间内根据三角剖分构造该图。
不幸的是,翻转方法的最坏情况运行时间是 O(n^2)。 存在更好的算法,例如 Fortune 的线扫描,它需要 O(n log n) 时间。 但这实施起来有些棘手。 如果您很懒(像我一样),我建议您寻找 Delaunay 三角剖分的现有实现,使用它,然后计算对偶图。
一般来说,关于该主题的一本好书是 de Berg 等人的计算几何 。
An easy algorithm to compute the Delaunay triangulation of a point set is flipping edges. Since a Delaunay triangulation is the dual graph of a Voronoi diagram, you can construct the diagram from the triangulation in linear time.
Unfortunately, the worst case running time of the flipping approach is O(n^2). Better algorithms such as Fortune's line sweep exist, which take O(n log n) time. This is somewhat tricky to implement though. If you're lazy (as I am), I would suggest looking for an existing implementation of a Delaunay triangulation, use it, and then compute the dual graph.
In general, a good book on the topic is Computational Geometry by de Berg et al.
最简单? 这是蛮力方法:对于输出中的每个像素,迭代所有点,计算距离,使用最近的点。 尽可能慢,但非常简单。 如果性能不重要,它就可以完成工作。 我自己一直在进行一项有趣的改进,但仍在寻找其他人是否有相同(相当明显)的想法。
Easiest? That's the brute-force approach: For each pixel in your output, iterate through all points, compute distance, use the closest. Slow as can be, but very simple. If performance isn't important, it does the job. I've been working on an interesting refinement myself, but still searching to see if anyone else has had the same (rather obvious) idea.
Bowyer-Watson 算法非常容易理解。 这是一个实现:http://paulbourke.net/papers/triangulate/。 这是一组点的德劳内三角剖分,但您可以使用它来获得德劳内的对偶,即沃罗诺图。 顺便提一句。 最小生成树是 delaunay 三角剖分的子集。
The Bowyer-Watson algorithm is quite easy to understand. Here is an implementation: http://paulbourke.net/papers/triangulate/. It's a delaunay triangulation for a set of points but you can use it to get the dual of the delaunay,i.e. a voronoi-diagram. BTW. the minimum spanning tree is a subset of delaunay triangulation.
构建 voronoi 图最有效的算法是 Fortune 算法。 它的运行时间为 O(n log n)。
以下是他的C 参考实现的链接。
就我个人而言,我真的很喜欢 python 实现由 Bill Simons 和 Carson Farmer 撰写,因为我发现它更容易扩展。
The most effecient algorithm to construct a voronoi diagram is Fortune's algorithm. It runs in O(n log n).
Here is a link to his reference implementation in C.
Personally I really like the python implementation by Bill Simons and Carson Farmer, since I found it easier to extend.
维基百科页面 (http://en.wikipedia.org/wiki/Voronoi_diagram) 有一个算法部分包含用于实现 Voronoi 图的算法的链接。
The Wikipedia page (http://en.wikipedia.org/wiki/Voronoi_diagram) has an Algorithms section with links to algorithms for implementing Voronoi diagrams.
Stephan Fortune / Shane O'Sullivan 提供了一个用 C 和 C++ 语言免费提供的用于二维图的 voronoi 实现:
您可以在很多地方找到它。 即位于 http://www.skynet.ie/~sos/masters/
There is a freely availble voronoi implementation for 2-d graphs in C and in C++ from Stephan Fortune / Shane O'Sullivan:
You'll find it at many places. I.e. at http://www.skynet.ie/~sos/masters/
这是一个使用 quat-tree 并允许增量构造的 JavaScript 实现。
http://code.google.com/p/javascript-voronoi/
Here is a javascript implementation that uses quat-tree and allows incremental construction.
http://code.google.com/p/javascript-voronoi/
虽然最初的问题询问如何实现 Voronoi,但如果我在搜索有关此主题的信息时发现一篇文章说以下内容,它会节省我很多时间:
有很多“几乎正确”的 C++ 代码用于实现 Voronoi 图的互联网。 当种子点变得非常密集时,大多数都很少触发失败。
我建议您在浪费太多时间之前,先对您在网上找到的任何代码进行广泛测试,并根据您希望在已完成的项目中使用的点数进行测试。
我在网上找到的最好的实现是从这里链接的 MapManager 程序的一部分:
http://www.skynet.ie/~sos/mapviewer/voronoi.php
它大部分工作正常,但在处理 10^6 点的订单时,我遇到间歇性图表损坏。
我一直无法弄清楚腐败是如何蔓延的。
昨晚我发现了这一点:
http://www.boost.org/doc/libs /1_53_0_beta1/libs/polygon/doc/voronoi_main.htm
“Boost.Polygon Voronoi 库”。
看起来很有前途。 它带有基准测试来证明其准确性并具有出色的性能。
该库有适当的界面和文档。
我很惊讶我之前没有找到这个库,因此我在这里写了关于它的文章。 (我在研究初期读过这篇文章。)
While the original question asks about how to implement Voronoi, had I found a post that said the following when I was searching for info on this subject it would have saved me a lot of time:
There's a lot of "nearly correct" C++ code on the internet for implementing Voronoi diagrams. Most have rarely triggered failures when the seed points get very dense.
I would recommend to test any code you find online extensively with the number of points you expect to use in your finished project before you waste too much time on it.
The best of the implementations I found online was part of the MapManager program linked from here:
http://www.skynet.ie/~sos/mapviewer/voronoi.php
It mostly works but i'm getting intermittent diagram corruption when dealing with order 10^6 points.
I have not been able to work out exactly how the corruption is creeping in.
Last night I found this:
http://www.boost.org/doc/libs/1_53_0_beta1/libs/polygon/doc/voronoi_main.htm
"The Boost.Polygon Voronoi library".
It looks very promising. This comes with benchmark tests to prove it's accuracy and has great performance.
The library has a proper interface and documentation.
I'm surprised I didn't find this library before now, hence my writing about it here. (I read this post early in my research.)
这是最快的 - 这是一个简单的 voronoi,但看起来很棒。 它将空间划分为网格,在随机放置的每个网格单元中放置一个点,并沿着网格移动检查 3x3 单元以找出它与相邻单元的关系。
没有渐变的话速度会更快。
您可能会问最简单的 3d voronoi 是什么。 如果知道的话会很有趣。 可能是 3x3x3 单元格并检查梯度。
http://www.iquilezles.org/www/articles/smoothvoronoi/smoothvoronoi。 htm
这里与切比雪夫距离相同。 您可以从这里使用 random2f 2d 浮动噪声:
https://www.shadertoy.com/view/Msl3DM
编辑:我已将其转换为类似 C 的代码
这是不久前的事了,为了那些这样做的人的利益,我相信这很酷:
This is the fastest possible - it's a simple voronoi but it looks great. It divides spaces into a grid, places a dot in each grid cell randomly placed and moves along the grid checking 3x3 cells to find how it relates to adjacent cells.
It's faster without the gradient.
You may ask what the easiest 3d voronoi would be. It would be fascinating to know. Probably 3x3x3 cells and checking gradient.
http://www.iquilezles.org/www/articles/smoothvoronoi/smoothvoronoi.htm
and here is the same with chebychev distance. you can use a random2f 2d float noise from here:
https://www.shadertoy.com/view/Msl3DM
edit: I have converted this to C like code
This was a while ago, for the benefit of those who what it, i believe this is cool:
实际上,https://rosettacode.org/wiki/Voronoi_diagram 上提供了 25 种不同语言的实现,
例如爪哇:
Actually there are implementations for 25 different languages available on https://rosettacode.org/wiki/Voronoi_diagram
E.g for Java:
最简单的算法来自 voronoi 图的定义:
“将具有 n 个点的平面划分为凸多边形,使得每个多边形恰好包含一个生成点,并且给定多边形中的每个点比任何其他点都更接近其生成点。”来自 Wolfram 的定义。
这里重要的部分是每个点都比其他点更接近生成点,从这里开始算法非常简单:
如果您想要一个用边框分隔的图表,请检查第二个最接近的点,然后检查它们与边框颜色的差异和颜色(如果它小于某个值)。
如果您想要一个颜色图,那么有一个与每个生成点关联的颜色,并使用与它最接近的生成点关联的颜色为每个像素着色。
就是这样,它效率不高,但很容易实现。
The simplest algorithm comes from the definition of a voronoi diagram:
"The partitioning of a plane with n points into convex polygons such that each polygon contains exactly one generating point and every point in a given polygon is closer to its generating point than to any other." definition from wolfram.
The important part here is about every point being closer to the generating point than any other, from here the algorithm is very simple:
If you want a diagram separated with a border, check for the second to closest point, then check their difference and color with the border color if it's smaller than some value.
If you want a color diagram then have a color associated with every generating point and color every pixel with it's closest generating point associated color.
And that's about it, it's not efficient but very easy to implement.
检查 Richard Franks 在他对问题 我该怎么办给定点集和 Delaunay 三角剖分,导出 Voronoi 图?
Check brute-force solution presented with pseudo-code by Richard Franks in his answer on the question How do I derive a Voronoi diagram given its point set and its Delaunay triangulation?
在 google code 上找到了这个基于 Fortune 算法/扫线算法的优秀 C# 库
https://code。 google.com/p/fortune-voronoi/
您只需创建一个列表。 可以通过传入两个数字(坐标)作为浮点数来创建向量。 然后将列表传递到 Fortune.ComputeVoronoiGraph()
您可以从这些维基百科页面进一步了解算法的概念:
http://en.wikipedia.org/wiki/Fortune%27s_algorithm
http:/ /en.wikipedia.org/wiki/Sweep_line_algorithm
虽然我无法理解的一件事是如何为部分无限边缘创建一条线(对坐标几何不太了解:-))。 如果有人知道,也请告诉我。
Found this excellent C# library on google code based on Fortune's algorithm/Sweep line algorithm
https://code.google.com/p/fortune-voronoi/
You just need to create a List. A Vector can be created by passing in two numbers (coordinates) as float. Then pass the list into Fortune.ComputeVoronoiGraph()
You can understand the concept of the algorithm a bit more from these wikipedia pages:
http://en.wikipedia.org/wiki/Fortune%27s_algorithm
http://en.wikipedia.org/wiki/Sweep_line_algorithm
Though one thing I was not able to understand is how to create a line for Partially Infinite edges (don't know much about coordinate geometry :-)). If someone does know, please let me know that as well.
如果您尝试将其绘制到图像中,可以使用基于队列的洪水填充算法。
使用队列将确保区域并行传播,从而最大限度地减少像素访问总数。 如果使用堆栈,第一个点将填充整个图像,然后第二个点将填充比第一个点更靠近它的任何像素。 这种情况将继续下去,从而大大增加访问次数。 使用 FIFO 队列按照像素被推送的顺序处理像素。 无论使用堆栈还是队列,生成的图像都大致相同,但队列的 big-O 比堆栈算法的 big-O 更接近线性(与图像像素数相关)。 一般的想法是,区域将以相同的速率扩散,并且碰撞通常恰好发生在与区域边界相对应的点处。
If you are trying to draw it to an image, you can use a queue-based flood-filling algorithm.
Using a queue will ensure that regions spread in parallel, minimizing total number of pixel visits. If you use a stack the first point will fill the whole image, then the second will fill any pixels closer to it than the first point. This will continue, greatly increasing visit counts. Using a FIFO queue processes pixels in the order that they are pushed. The resulting images will be roughly the same whether you use stack or queue, but the big-O for queue is far closer to linear (in relation to number of image pixels) than the stack algoritm's big-O. The general idea is that the regions will spread at the same rate and collisions will generally happen exactly at points that correspond to region boundaries.