2016-09-28 454 views
2

我想用Delaunay算法对三维点云进行三角剖分。为了测试我的代码,我从STL文件中提取点云,然后尝试重新网格化它。这是我的代码:点云Delaunay三角剖分

import numpy as np 
import matplotlib.pyplot as plt 
from scipy.spatial import Delaunay 

#--------------def funtion extract point cloud------------------- 
def point_cloud(inp): 
    node = [] 
    for line in inp: 
     temp1 = line.strip() 
     x = temp1.split() 
     if x[0] == "vertex": 
      del x[0] 
      node.append(x) 
    node = set(map(tuple,node)) 
    return node 
#--------------------end function--------------------------------- 

with open("D:\\cilinder.stl","r") as fo: 
    pc = point_cloud(fo) 

u = [] 
v = [] 
w = [] 

for l in pc: 
    u.append(float(l[0])) 
    v.append(float(l[1])) 
    w.append(float(l[2])) 

ua = np.array(u) 
va = np.array(v) 

#tri = mtri.Triangulation(u, v) 
tri = Delaunay(np.array([u,v]).T) 

points = [] 
vertex = [] 

for i in range(ua.shape[0]): 
    points.append([ua[i],va[i],w[i]]) 

for vert in tri.simplices: 
#for vert in tri.triangles: 
    vertex.append(vert)  

fig = plt.figure() 
ax = fig.add_subplot(1, 1, 1, projection='3d') 
ax.plot_trisurf(ua, va, w, triangles=tri.simplices, cmap=plt.cm.Spectral) 
#ax.plot_trisurf(ua, va, w, triangles=tri.triangles, cmap=plt.cm.Spectral) 
plt.show() 

后,我运行此代码,我得到了以下结果:

结果:

enter image description here enter image description here

该算法不三角的外表面点云。我无法弄清楚为什么我得到了这个结果。任何建议?

编辑:我刚刚发现,函数point_cloud提供了重复点,因为它们直接从STL文件中提取。

+0

您是否想要生成三角形表面网格或四面体网格? –

+0

三角形表面网格 – drSlump

+0

好吧,问题很明显:那么只有给定一个点云,'Delaunay'无法知道哪个连接应该是所得形状的“外部”。它只是连接一些,导致你看起来有趣的东西。 –

回答

1

当你显示它们时,你得到网格的原因是你没有(也不能)向scipy的Delaunay网格提供拓扑信息。你给它一个点云,它连接所有的点,就是这样。

网格生成是一个复杂的话题,不幸的是我不知道任何软件,给定一个点云和拓扑信息,给你一个网格。

但是,如果从头开始生成网格,只要给出对象的几何形状,就有多种方法。对于你想要的圆筒,一种方法是自己做;退房meshzoo

#! /usr/bin/env python 
# -*- coding: utf-8 -*- 
import numpy as np 


def create_mesh(width=5.0, n=30, radius=1.0): 
    # Number of nodes along the width of the strip (>= 2) 
    # Choose it such that we have approximately square boxes. 
    nw = int(round(width * n/(2*np.pi*radius))) 

    # Generate suitable ranges for parametrization 
    u_range = np.linspace(0.0, 2*np.pi, num=n, endpoint=False) 
    v_range = np.linspace(-0.5*width, 0.5*width, num=nw) 

    # Create the vertices. 
    nodes = [] 
    for u in u_range: 
    x = radius * np.cos(u) 
    y = radius * np.sin(u) 
    for v in v_range: 
     nodes.append(np.array([x, y, v])) 

    # create the elements (cells) 
    elems = [] 
    for i in range(n - 1): 
    for j in range(nw - 1): 
     elems.append([i*nw + j, (i + 1)*nw + j + 1, i * nw + j + 1]) 
     elems.append([i*nw + j, (i + 1)*nw + j,  (i + 1)*nw + j + 1]) 
    # close the geometry 
    for j in range(nw - 1): 
    elems.append([(n - 1)*nw + j, j + 1, (n - 1)*nw + j + 1]) 
    elems.append([(n - 1)*nw + j, j, j + 1]) 

    return np.array(nodes), np.array(elems) 


if __name__ == '__main__': 
    import meshio 
    points, cells = create_mesh() 
    meshio.write('tube.vtu', points, {'triangle': cells}) 

enter image description here

制作一个锯齿形出这应该是很容易。

其他网格生成:

+0

问题是我必须从点云开始。 – drSlump

+0

随着点云,您还需要几何信息;否则你会得到你所得到的。如果你有几何体,你不需要点。这就是为什么没有你想要的那种网格生成器。对于拓扑等价于平坦表面的域,可以将点重新映射到表面,在那里做Delaunay,然后映射回去。 –

+0

感谢您的回答,我明白了您的观点。但是如果你有一个来自扫描几何的点云呢?您将不会获得有关几何图形的任何信息。我的目标是处理来自扫描复杂几何图形的点云。 – drSlump

1

你可以尝试一个德劳内三角但tetrahedons。然后手动删除孔。 IMO是一个四面体网格。尤其是Bowyer-Watson算法很简单。

+0

感谢您的建议。不幸的是,我想要一种自动化过程的方法,因为点云来自已知的扫描几何特征(例如凹面),并具有相当规则的表面。我会继续寻找一个解决方案,并且如果我会找到它,我会更新讨论内容。 – drSlump

相关问题