PYQT Delaunay triangulation 互动编程

Delaunay Triangulation 能干什么?
有限元计算 架空地图设计(procedural map) 几何图像生成 实在是算法学中重量级的算法

在2D平面上均匀散布点
用numpy形成均匀网格

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=n1i=1nxiyc=n1i=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算法,经过两次迭代后,可以看到原先尖锐的多边形明显圆滑起来,尖角现象消除,随机性还是有的,这是我们需要的
松弛网格

边界
缩小后,边界拉伸的问题比较严重,因为边界没有支撑点,被松弛后,边界无法保持,这里有两方法可以

  1. 刻意去除扭曲比较大的多边形
  2. 在多边形加入固定点,防止拉伸后变形

如何使用本案例

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) 

二分法形成不规则边界
在这里插入图片描述
结合在一起可以形成不规则的边界,如下图
map

说明

  • 为了能运行本案例,请自行安装python环境 和相关包,具体配置和安装在本文中不涉及也无需涉及,本案例不支大部分智能设备
  • 算法未经严格优化,只为了说明算法的使用方法
  • 本案例应用于非严肃领域,数值结果和算法探讨请@我,如需转载请注明
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值