1.表面重建

通过三维扫描仪所获取的实际物体的空间点云数据仅仅表示物体的几何形状,而无法表达其内部的拓扑结构。拓扑结构对于实际图形处理以及可视化具有更重要的意义。因此,这就需要利用表面重建技术奖点云数据转换成面模型,通常为三角网格模型。除此之外,基于图像数据的面绘制技术也是一种应用非常广泛的表面重建技术。

2.VTK中实现三角剖分技术

三角剖分技术是一种应用非常广泛的面重建技术。三角剖分将一些散乱的点云数据剖分为一系列的三角形网格。最常用的三角剖分技术为Delaunay三角剖分。Delaunay三角剖分具有许多优良的性质,如最大化最小角特性,即在所有可能的三角剖分中,其所生成的的三角形的最小角的角度最大。所以,Delaunay三角剖分无论从哪个区域开始构建,最终生成的三角网格还是唯一的。
VTK的vtkDelaunay2D类实现了二维三角剖分。该类的输入数据为一个vtkPointSet或其子类表示的三维空间点集,其输出为一个三角网格vtkPolyData数据。虽然输入的是三维数据,但是算法仅适用XY平面数据进行平面三角剖分,而忽略Z方向数据。当然,也可以为vtkDelaunay2D设置一个投影变换从而在新的投影平面上进行三角剖分。需要注意的是,再不添加任何限制条件下,该类生成的平面三角网格为一个凸包。
下例演示如何使用vtkDelaunay2D,将其生成的数据用于模型地形数据:
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL);
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkInteractionStyle);#include <vtkSmartPointer.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkDelaunay2D.h>
#include <vtkMath.h>
#include <vtkVertexGlyphFilter.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>int main()
{unsigned int gridSize = 10;vtkSmartPointer<vtkPoints> points =vtkSmartPointer<vtkPoints>::New();for (unsigned int x = 0; x < gridSize; x++){for (unsigned int y = 0; y < gridSize; y++){points->InsertNextPoint(x, y, vtkMath::Random(0.0, 3.0));}}vtkSmartPointer<vtkPolyData> polydata =vtkSmartPointer<vtkPolyData>::New();polydata->SetPoints(points);vtkSmartPointer<vtkDelaunay2D> delaunay =vtkSmartPointer<vtkDelaunay2D>::New();delaunay->SetInputData(polydata);delaunay->Update();vtkSmartPointer<vtkVertexGlyphFilter> glyphFilter =vtkSmartPointer<vtkVertexGlyphFilter>::New();glyphFilter->SetInputData(polydata);glyphFilter->Update();vtkSmartPointer<vtkPolyDataMapper> pointsMapper =vtkSmartPointer<vtkPolyDataMapper>::New();pointsMapper->SetInputData(glyphFilter->GetOutput());vtkSmartPointer<vtkActor> pointsActor =vtkSmartPointer<vtkActor>::New();pointsActor->SetMapper(pointsMapper);pointsActor->GetProperty()->SetPointSize(3);pointsActor->GetProperty()->SetColor(1, 0, 0);vtkSmartPointer<vtkPolyDataMapper> triangulatedMapper =vtkSmartPointer<vtkPolyDataMapper>::New();triangulatedMapper->SetInputData(delaunay->GetOutput());vtkSmartPointer<vtkActor> triangulatedActor =vtkSmartPointer<vtkActor>::New();triangulatedActor->SetMapper(triangulatedMapper);vtkSmartPointer<vtkRenderer> renderer =vtkSmartPointer<vtkRenderer>::New();renderer->AddActor(pointsActor);renderer->AddActor(triangulatedActor);renderer->SetBackground(0, 0, 0);vtkSmartPointer<vtkRenderWindow> renderWindow =vtkSmartPointer<vtkRenderWindow>::New();renderWindow->AddRenderer(renderer);renderWindow->SetSize(640, 640);renderWindow->Render();renderWindow->SetWindowName("PolyData Delaunay2D");vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =vtkSmartPointer<vtkRenderWindowInteractor>::New();renderWindowInteractor->SetRenderWindow(renderWindow);renderWindowInteractor->Start();return 0;
}

该例先定义了一个vtkPolyData数据,并为其生成一个10*10的地面网格点集points以及每个点生成了一个随机数,表示每个点的海拔值;然后将该数据做为vtkDelaunay2D对象的输入实现三角剖分,即可得到一个地面的网格数据。

输出结果如下所示:

3.局部数据三角剖分(带约束的三角平分)

vtkDelaunay2D还支持加入边界限制。用户需要设置另外一个vtkPolyData数据,其内部的线段、闭合或者非闭合的线段集合将作为边界条件控制三角剖分的过程。其中,组成这些边界的点的索引必须与原始点集数据一致。加入边界条件后,最后的剖分结果可能不在满足Delaunay准则。
下面的例子,是在上例的基础上,加入一个多变形边界来限制三角剖分:
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL);
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkInteractionStyle);#include <vtkSmartPointer.h>
#include <vtkPoints.h>
#include <vtkMath.h>
#include <vtkPointData.h>
#include <vtkPolyData.h>
#include <vtkVertexGlyphFilter.h>
#include <vtkProperty.h>
#include <vtkPolygon.h>
#include <vtkCellArray.h>
#include <vtkDelaunay2D.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>int main()
{vtkSmartPointer<vtkPoints> points =vtkSmartPointer<vtkPoints>::New();unsigned int gridSize = 10;for (unsigned int x = 0; x < gridSize; x++){for (unsigned int y = 0; y < gridSize; y++){points->InsertNextPoint(x, y, vtkMath::Random(0.0, 3.0));}}vtkSmartPointer<vtkPolyData> polydata =vtkSmartPointer<vtkPolyData>::New();polydata->SetPoints(points);//多边形vtkSmartPointer<vtkPolygon> poly =vtkSmartPointer<vtkPolygon>::New();poly->GetPointIds()->InsertNextId(32);poly->GetPointIds()->InsertNextId(42);poly->GetPointIds()->InsertNextId(43);poly->GetPointIds()->InsertNextId(44);poly->GetPointIds()->InsertNextId(45);poly->GetPointIds()->InsertNextId(35);poly->GetPointIds()->InsertNextId(25);poly->GetPointIds()->InsertNextId(24);poly->GetPointIds()->InsertNextId(23);poly->GetPointIds()->InsertNextId(22);vtkSmartPointer<vtkCellArray> cell =vtkSmartPointer<vtkCellArray>::New();cell->InsertNextCell(poly); //设计拓扑结构//边界约束vtkSmartPointer<vtkPolyData> boundary =vtkSmartPointer<vtkPolyData>::New();boundary->SetPoints(points);boundary->SetPolys(cell); //只显示具有拓扑结构部分vtkSmartPointer<vtkDelaunay2D> delaunay =vtkSmartPointer<vtkDelaunay2D>::New();delaunay->SetInputData(polydata);delaunay->SetSourceData(boundary); //约束源delaunay->Update();
///vtkSmartPointer<vtkVertexGlyphFilter> glyphFilter =vtkSmartPointer<vtkVertexGlyphFilter>::New();glyphFilter->SetInputData(polydata);glyphFilter->Update();vtkSmartPointer<vtkPolyDataMapper> pointsMapper =vtkSmartPointer<vtkPolyDataMapper>::New();pointsMapper->SetInputData(glyphFilter->GetOutput());vtkSmartPointer<vtkActor> pointsActor =vtkSmartPointer<vtkActor>::New();pointsActor->SetMapper(pointsMapper);pointsActor->GetProperty()->SetPointSize(8);pointsActor->GetProperty()->SetColor(1, 0, 0);vtkSmartPointer<vtkPolyDataMapper> triangulatedMapper =vtkSmartPointer<vtkPolyDataMapper>::New();triangulatedMapper->SetInputData(delaunay->GetOutput());vtkSmartPointer<vtkActor> triangulatedActor =vtkSmartPointer<vtkActor>::New();triangulatedActor->SetMapper(triangulatedMapper);
//vtkSmartPointer<vtkRenderer> renderer =vtkSmartPointer<vtkRenderer>::New();renderer->AddActor(pointsActor);renderer->AddActor(triangulatedActor);renderer->SetBackground(0, 0, 0);vtkSmartPointer<vtkRenderWindow> rw =vtkSmartPointer<vtkRenderWindow>::New();rw->AddRenderer(renderer);rw->SetSize(640, 480);rw->SetWindowName("PolyData By ConstrainedDelaunay2D");vtkSmartPointer<vtkRenderWindowInteractor> rwi =vtkSmartPointer<vtkRenderWindowInteractor>::New();rwi->SetRenderWindow(rw);rwi->Start();return 0;
}

这里定义一个vtkPolyData类型的数据boundary,其点数据与上例中的points一致。其单元数据为一个多边形。通过vtkDelaunay2D的SetSourceData()函数设置边界数据,运行结果如下所示:

该边界多边形内部的数据并未进行三角剖分。对于边界多边形限制数据的内部或者外部,与多边形点的顺序有关。这里采用右手坐标系,从Z轴向下看去,如果多边形的点顺序为逆时针,则仅对多边形内部数据进行剖分;而如果为顺时针方向,则对多边形外部数据进行剖分,此时该边界多边形可以看成一个孔洞。

4.vtkelaunay3D实现三维三角剖分

VTK的vtkDelaunay3D类可实现三维三角剖分。该类的使用方法与vtkDelaunay2D基本一致,不同的是,三维三角剖分得到的结果并非三角网格,而是四面体网络。因此,其输出数据的类型为vtkUnstructuredGrid,在未加入边界条件下的三维三角剖分通常也为一个凸包。

5.简述类vtkVertexGlyphFilter

This filter throws away all of the cells in the input and replaces them with a vertex on each point.  The intended use of this filter is roughly equivalent to the vtkGlyph3D filter, except this filter is specifically for
data that has many vertices, making the rendered result faster and less cluttered than the glyph filter. This filter may take a graph or point set as input.

6.参看资料

1.《C++ primer》
2.《The VTK User’s Guide – 11thEdition》
3.  张晓东, 罗火灵. VTK图形图像开发进阶[M]. 机械工业出版社, 2015.

VTK修炼之道54:图形基本操作进阶_表面重建技术(三角剖分)相关推荐

  1. VTK_Learning_图形基本操作进阶_表面重建技术(三角剖分)

    1.表面重建 通过三维扫描仪所获取的实际物体的空间点云数据仅仅表示物体的几何形状,而无法表达其内部的拓扑结构.拓扑结构对于实际图形处理以及可视化具有更重要的意义.因此,这就需要利用表面重建技术奖点云数 ...

  2. VTK修炼之道56:图形基本操作进阶_表面重建技术(三维点云曲面重建)

    1.点云重建 虽然Delaunay三角剖分算法可以实现网格曲面重建,但是其应用主要在二维剖分,在三维空间网格生成中遇到了问题.因为在三维点云曲面重建中,Delaunay条件不在满足,不仅基于最大最小角 ...

  3. VTK修炼之道55:图形基本操作进阶_表面重建技术(等值面提取)

    1.等值面提取 等值面(线)提取是一种常用的可视化技术,常应用于医学.地质.气象等领域.例如,在医学图像处理中,由于CT.MRI等图像分辨率越来越高,虽然体绘制技术可以清晰地对数据内部结构进行可视化, ...

  4. VTK修炼之道46:图形基本操作进阶_三角网格体积、表面积、测地距离、包围盒

    1.基本图形操作意义 图形处理,比如图形平滑.多分辨率分析.特征提取等都离不开一些基本的图形操作.掌握这些基本的图形操作有助于理解和深入学习图形处理和分析方法. VTK中提供了多种图形的基本操作,其中 ...

  5. VTK修炼之道49:图形基本操作进阶_网格平滑(点云的曲面重建技术)

    1.网格平滑 现代扫描技术的发展使得获取点云数据不再困难,通过曲线重建技术可以获取表面网格来表示各种复杂的实体.但是点云数据中往往存在噪声,这样得到的重建网格通常都需要进行平滑处理. 拉普拉斯平滑是一 ...

  6. VTK修炼之道59:图形基本操作进阶_纹理映射

    1.纹理映射 纹理映射是将纹理空间中的纹理像素映射到屏幕空间中的像素的过程.纹理生成过程实质上是将所定义的纹理映射为某种三维物体表面的属性,并参与后续的光照计算.在三维图形中,纹理映射运用的十分广泛, ...

  7. VTK修炼之道58:图形基本操作进阶_点云配准技术(迭代最近点ICP算法)

    1.Iterative Closest Points算法 点云数据配准最经典的方法是迭代最近点算法(Iterative Closest Points,ICP).ICP算法是一个迭代的过程,每次迭代中对 ...

  8. VTK修炼之道57:图形基本操作进阶_点云配准技术(LandMark标记点算法和坐标系显示方法)

    1.点云配准 在计算机逆向工程中,通过三维扫描等实物数字化技术可以获取各种点云数据.但是受到测量环境和设备的影响,再一次测量的情况下,难以获取实物整体的点云数据,因此需要多次从不同角度进行测量.但不同 ...

  9. VTK修炼之道53:图形基本操作进阶_多分辨率策略(模型细化的三种方法)

    1.模型细化 vtk中实现网格细化的累有vtkLinearSubdivisionFilter.vtkLoopsubdivisionFilter.vtkButterflySubdivisionFilte ...

最新文章

  1. hdu3594 强连通 tarjan
  2. linux 上传带宽限速
  3. 80070583类不存在_结合JVM源码谈Java类加载器
  4. 前端学习(615):变量
  5. 《计算机应用基础》在线考试,2018年自学考试《计算机应用基础》考试题及答案...
  6. h5海报设计开源工具_5个用于教幼儿阅读的开源工具
  7. 【华为云实战开发】2.Docker镜像部署怎么玩才酷炫?
  8. android方向触摸事件,Android触摸事件传递机制,这一篇就够了
  9. Maven核心概念(转)
  10. 网络基础知识(黑马教程笔记)-2-http协议(请求报文)
  11. opencv立方体的画法_opencv几何图形画法
  12. SSM-Mybatis的Mapper.xml配置文件
  13. Android锁屏下弹窗的尝试,android开发实战我的云音乐
  14. 【CodeForces 332B --- Maximum Absurdity】递推
  15. 微信开发_Exception_02_errcode:40164,errmsg:invalid ip 61.172.68.219, not in whitelist hint
  16. golang中builtin包说明
  17. 云服务器和独享虚拟主机的区别,云服务器和独享虚拟主机的区别
  18. 谷歌云wordpress搭建博客网站
  19. 青蛙跳台阶python解法
  20. e-icon-picker

热门文章

  1. IntelliJ IDEA 15发布
  2. map area 鼠标跟随
  3. Oracle建立约束、删除约束
  4. mapReducer第一个例子WordCount
  5. Tomcat 9.0.6 HostManager页面 403 Access Denied 错误
  6. 使用Apache php 的一些基本操作(一)
  7. 巧用css text-indent减小中文标点符号的占位大小
  8. Codeforces 235B Let's Play Osu!
  9. 软件工程课堂作业(八)——结对开发(三)
  10. Android 自定义组件随着手指自动画圆