Delaunay Triangulation 能干什么?
有限元计算 架空地图设计(procedural map) 几何图像生成 实在是算法学中重量级的算法
在2D平面上均匀散布点
self.point_count = 100
self.points = np.random.uniform(-400,400,(self.point_count,2))
使用reb blob games中提供的算法,获得的多边形比较尖锐,
The polygon shapes and sizes are a bit irregular. Random numbers are more “clumpy” than what people expect. I want something closer to semi-random “blue noise”, or quasirandomness, not random points. I approximate that by using a variant of Lloyd relaxation, which is a fairly simple tweak to the random point locations to make them more evenly distributed. Lloyd relaxation replaces each point by the centroid of the polygon. In my code I merely average the corners (see improveRandomPoints). Here’s the result after running approximate Lloyd relaxation twice:
意思大概是:产生的多边形形状和大小比我们的预期有些不规则,使用一种 Lloyd relaxation 方法进行网格松弛。在 Lloyd relaxation 方法中,会把新多边形的几何中心替换原来的随机点,作者这里使用了一种近似与Lloyd relaxation 的方法,经过两次迭代达到类似于 Lloyd relaxation效果。
到底如何才能,作者没具体写,至于作者提到的centroid ,到底是几何中心还是质心,也不清楚,真是欲言又止啊。
c e n t r o i d = { x c = 1 n ∑ i = 1 n x i y c = 1 n ∑ i = 1 n y i centroid = \begin{cases} x_c =\frac{1}{n}\sum_{i=1}^{n} x_i \\ y_c =\frac{1}{n}\sum_{i=1}^{n} y_i \end{cases} centroid={xc=n1∑i=1nxiyc=n1∑i=1nyi
计算多边形中心,非常粗糙的几何中心,可以认为用几何中心作为多边形的centroid,当然是有误差的
cx,cy = 0,0
for ie in range(0, len(vertices)):
cx = cx + vertices[ie][0]
cy = cy + vertices[ie][1]
cx = cx/len(vertices)
cy = cy/len(vertices)
将新的点集合,重新使用Delaunay算法,经过两次迭代后,可以看到原先尖锐的多边形明显圆滑起来,尖角现象消除,随机性还是有的,这是我们需要的
缩小后,边界拉伸的问题比较严重,因为边界没有支撑点,被松弛后,边界无法保持,这里有两方法可以
- 刻意去除扭曲比较大的多边形
- 在多边形加入固定点,防止拉伸后变形
如何使用本案例
Delaunay Triangulation 算法基于pyqt5 gui 互动编程
涉及到的算法如下
- 均匀分布 基于numpy
- Delaunay Triangulation 使用和结构渲染
- Lloyd relaxation 松弛网格
默认100个点,需要修改请 point_count = <数值>
操作说明:
空格 :形成Delaunay Triangulation网格并Lloyd relaxation 松弛网格
V:形成Delaunay Triangulation网格
左键:移动点并自动Delaunay化
右键:移动画布
鼠标滚轮:缩放画布
边界noise二分化处理
def div_quad(self,quad):
if dist(quad[0], quad[3])<10:
return [quad]
k = .4+random.random()*.3
cut = self.interp(quad[1], quad[3], k)
v1 = self.interp(quad[0], quad[1], 0.5)
v2 = self.interp(quad[0], quad[3], 0.5)
quad1 = [quad[0],v1,cut,v2]
v3 = self.interp(quad[1], quad[2], 0.5)
v4 = self.interp(quad[3], quad[2], 0.5)
quad2 = [cut,v3,quad[2],v4]
return [quad1,quad2]
def interp(self,a,b,k):
x = k*a[0]+(1-k)*b[0]
y = k*a[1]+(1-k)*b[1]
return [x,y]
def draw_costa(self,quad,painter):
painter.drawLine(quad[0][0],quad[0][1],quad[2][0],quad[2][1])
def paintEvent(self,event):
quad = [self.quad]
# divide
for j in range(8):
qr = []
for qq in quad:
qarr = self.div_quad(qq)
qr = qr + qarr
quad = qr
for qj in quad:
self.draw_costa(qj,painter)
二分法形成不规则边界
结合在一起可以形成不规则的边界,如下图
说明
- 为了能运行本案例,请自行安装python环境 和相关包,具体配置和安装在本文中不涉及也无需涉及,本案例不支大部分智能设备
- 算法未经严格优化,只为了说明算法的使用方法
- 本案例应用于非严肃领域,数值结果和算法探讨请@我,如需转载请注明