VTK编程指南<十六>:VTK表面重建之Delaunay三角剖分

news2025/2/12 10:32:41

1、无边界限制

  三角剖分是一种应用非常广泛的重建技术。三角剖分将一些散乱的点云数据划分为一系列的三角形网格。最常用的三角剖分技术是Delaunay三角剖分。Delaunay三角剖分具有许多优良的性质,即最大化最小角特性,即所有可能的三角形剖分中,其生成的三角形最小角的角度最大。所以,Delaunay三角剖分无论在哪个区域开始构建,最终生成的三角网格是唯一的。

  VTK的vtkDelaunay2D类实现了二维三角剖分。该类的输入数据集为一个vtkPointSet或其它类表示的三维空间点集,其中输出为一个三角网格vtkPolyData数据。虽然输入的三维数据, 但是计算仅使用XY平面数据进行平面三角剖分,而忽略Z方向数据。 当然,也可以为vtkDelaunay2D设置一个投影转换从而在投影平面上进行三角剖分。需要注意的是,在不加任何限制的情况下,该类生成的平面网格为一个凸包。下面通过示例演示vtkDelaunay2D, 将其生成的数据信息用于模拟地形数据(程序执行结果如图所示):

在这里插入图片描述

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);// VTK was built with vtkRenderingOpenGL2
VTK_MODULE_INIT(vtkInteractionStyle);

#include <vtkSmartPointer.h>
#include <vtkProperty.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkDelaunay2D.h>
#include <vtkMath.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkVertexGlyphFilter.h>

int main(int, char *[])
{
	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(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(renderer);

	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renderWindowInteractor->SetRenderWindow(renderWindow);

	renderWindow->SetSize(640, 320);
	renderWindow->Render();
	renderWindow->SetWindowName("PolyDataDelaunay2D");
	renderWindow->Render();

	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}

2、边界限制

  vtkDelaunay2D 还支持加入边界限制。用户需要设置另外一个vtkPolyData数据,其中部分的线段、闭合或非闭合的线段集合作为边界条件控制三角剖分的过程。过程中组成这些边界的点的索引必须与原始点集数据一致。加入边界条件后,最后的剖分结果可能不再满足Delaunay准则。在上述例子的基础上,加入一个多边形边界来限制三角剖分,这里定义了一个vtkPolyData类型的数据boundary,其点数据与上例中的points一致,其单元数据为一个多边形。通过vtkDelaunay2D的SetSource()函数设置边界数据,运行结果如图6-22a所示,该边界多边形内部的数据并未进行三角剖分。对于边界多边形数据的内部或者外部,与多边形点的顺序有关。这里采用右手坐标系,从Z轴向下看去,如果多边形的点顺序为逆时针,则对多边形内部数据进行剖分;而如果顺时针方向,则对多边形外部数据进行剖分,此时该边界多边形可以看作一个孔洞。将上例中的点数据反向,则剖分结果如图所示。

在这里插入图片描述

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);// VTK was built with vtkRenderingOpenGL2
VTK_MODULE_INIT(vtkInteractionStyle);

#include <vtkSmartPointer.h>
#include <vtkProperty.h>
#include <vtkPolygon.h>
#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkDelaunay2D.h>
#include <vtkMath.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkVertexGlyphFilter.h>

int main(int, char *[])
{
	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(22);
	poly->GetPointIds()->InsertNextId(23);
	poly->GetPointIds()->InsertNextId(24);
	poly->GetPointIds()->InsertNextId(25);
	poly->GetPointIds()->InsertNextId(35);
	poly->GetPointIds()->InsertNextId(45);
	poly->GetPointIds()->InsertNextId(44);
	poly->GetPointIds()->InsertNextId(43);
	poly->GetPointIds()->InsertNextId(42);
	poly->GetPointIds()->InsertNextId(32);*/

	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(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(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(renderer);

	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renderWindowInteractor->SetRenderWindow(renderWindow);

	renderWindow->SetSize(640, 480);
	renderWindow->Render();
	renderWindow->SetWindowName("PolyDataConstrainedDelaunay2D");
	renderWindow->Render();
	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2296785.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2.Excel:滨海市重点中学的物理统考考试情况❗(15)

目录 NO12​ 1.数据透视表​ 2. 3.sum函数 4.sumifs客观/主观平均分​ 5.sumifs得分率​ 6.数字格式修改​ NO3/4/5​ sumifs某一组数据相加&#xff0c;某一范围&#xff0c;某一范围的具体点向下拖拉&#xff0c;锁定列&#xff1b;向左右&#xff0c;锁定行F4&#x…

Hdoop之MapReduce的原理

简单版本 AppMaster: 整个Job任务的核心协调工具 MapTask: 主要用于Map任务的执行 ReduceTask: 主要用于Reduce任务的执行 一个任务提交Job --> AppMaster(项目经理)--> 根据切片的数量统计出需要多少个MapTask任务 --> 向ResourceManager(Yarn平台的老大)索要资源 --…

JAVA并发编程3--多线程程序

​ 1.创建线程的方法&#xff1a; 案例&#xff1a;计算1-1000的整数和 实现Runnable接口 步骤&#xff1a; 1.创建一个实现了Runnable接口的类 2.实现类去实现Runnable中的抽象方法&#xff1a;run() 3.创建实现类的对象 4.将此对象作为参数传递到Thread类的构造器中&#…

自主项目面试点总结

1、许苑–OJ判题系统 技术栈&#xff1a;Spring BootSpring Cloud AlibabaRedisMybatisMQDocker 项目地址: https://github.com/xuyuan-upward/xyoj-backend-microservice 1.1、项目介绍: 一个基于微服务的OJ系统&#xff0c;具备能够根据管理员预设的题目用例对用户提交的代…

idea Ai工具通义灵码,Copilot我的使用方法以及比较

我用过多个idea Ai 编程工具&#xff0c;大约用了1年时间&#xff0c;来体会他们那个好用&#xff0c;以下只是针对我个人的一点分享&#xff0c;不一定对你适用 仅作参考。 介于篇幅原因我觉得能说上好用的 目前只有两个 一个是阿里的通义灵码和Copilot&#xff0c;我用它来干…

4.python基础语法-下

文章目录 1.顺序语句2.条件语句 - if2.1什么是条件语句2.2语法格式2.2.1if2.2.2if - else2.2.3if - elif - else 2.3缩进和代码块2.4练习2.5空语句 pass 3.循环语句3.1while循环3.2for循环3.3continue3.4break 4.综合案例4.1设置初始属性4.2设置性别4.3设置出生点4.4针对每一岁…

Java--集合(理论)

目录 一、collection collection常用方法 1.List&#xff08;可以存在重复元素&#xff09; 迭代器 迭代器的概念 注意事项 例子 1.ArrayList 特点 2.LinkedLIst 特点 3.Vector 特点 2.Set&#xff08;无重复元素&#xff09; 1.HashSet 特点 2.Linkedhashset&…

3D图形学与可视化大屏: 3D 图形学的定义、应用领域和发展历程

一、3D 图形学的定义 3D 图形学是计算机科学的一个分支&#xff0c;主要研究如何在计算机上生成、处理和显示三维图形。它涉及到数学、物理学、计算机科学等多个学科领域&#xff0c;旨在通过计算机技术模拟真实世界中的三维物体和场景&#xff0c;为用户提供逼真的视觉体验。…

Python 面向对象(类,对象,方法,属性,魔术方法)

前言&#xff1a;在讲面向对象之前&#xff0c;我们先将面向过程和面向对象进行一个简单的分析比较&#xff0c;这样我们可以更好的理解与区分&#xff0c;然后我们在详细的讲解面向对象的优势。 面向过程&#xff08;Procedure-Oriented Programming&#xff0c;POP&#xff0…

轮子项目--消息队列的实现(3)

上一篇文章中我把一些关键的类以及表示出来&#xff0c;如何对这些类对应的对象进行管理呢&#xff1f;管理分为硬盘和内存上&#xff0c;硬盘又分为数据库&#xff08;管理交换机&#xff0c;队列和绑定&#xff09;和文件&#xff08;管理消息&#xff09;&#xff0c;本文就…

5.7.1 软件项目管理范围、成本估算、风险分析

文章目录 管理范围成本估算风险分析 管理范围 软件项目管理范围包含4P&#xff0c;即人员、产品、过程、项目。人员管理通过人员能力成熟度模型PCMM进行管理。产品管理需要制定产品目标&#xff0c;识别产品的总体目标&#xff0c;而不涉及细枝末节。产品范围&#xff0c;识别产…

Android新版高斯模糊(毛玻璃)官方实现,Kotlin

Android新版高斯模糊(毛玻璃)官方实现&#xff0c;Kotlin 从Android 12开始&#xff0c;Android官方API支持高斯模糊(毛玻璃)效果。关键是通过RenderEffect实现。 https://developer.android.com/reference/android/graphics/RenderEffecthttps://developer.android.com/refer…

仿 RabbitMQ 实现的简易消息队列

文章目录 项目介绍开放环境第三⽅库介绍ProtobufMuduo库 需求分析核⼼概念实现内容 消息队列系统整体框架服务端模块数据管理模块虚拟机数据管理模块交换路由模块消费者管理模块信道&#xff08;通信通道&#xff09;管理模块连接管理模块 客户端模块 公共模块日志类其他工具类…

实验9 基于WebGoat平台的SQL注入攻击

实验9 基于WebGoat平台的SQL注入攻击 1.实验目的 熟悉WebGoat平台&#xff0c;在该平台上实现SQL注入攻击。 2.实验内容 &#xff08;1&#xff09;下载webgoat-server-8.2.2.jar。 &#xff08;2&#xff09;搭建java环境。 &#xff08;3&#xff09;运行webgoat。 &#xf…

多光谱技术在华为手机上的应用发展历史

2018 年&#xff0c;华为 P20 系列首次搭载 5 通道色温传感器&#xff0c;可帮助手机在不同光照条件下保持画面色彩一致性。 2020 年&#xff0c;华为 P40 系列搭载 8 通道多光谱色温传感器&#xff08;实际为 11 通道&#xff0c;当时只用 8 个通道检测可见光&#xff09;&am…

如何免费白嫖 Deepseek API 接口

今天我将教大家如何利用网络空间测绘搜索引擎「Fofa」来寻找已经部署并开放 Deepseek 接口的服务。以下是详细步骤&#xff1a; 1. 访问 Fofa 搜索引擎 首先&#xff0c;打开 Fofa 搜索引擎的网站&#xff1a;https://fofa.info 2. 搜索开放的 Deepseek 接口 在搜索框中输入…

SaaS+AI应用架构:业务场景、智能体、大模型、知识库、传统工具系统

SaaSAI应用架构&#xff1a;业务场景、智能体、大模型、知识库、传统工具系统 大家好&#xff0c;我是汤师爷~ 在SaaS与AI应用的演进过程中&#xff0c;合理的架构设计至关重要。本节将详细介绍其五个核心层次&#xff1a; 业务场景层&#xff1a;发现和确定业务场景智能体层…

ios通过xib创建控件

之前写过ios动态创建控件及添加事件&#xff0c;纯手工代码写控件&#xff0c;虽然比较灵活&#xff0c;但是就是代码量比较多。这次我们通过xib来创建app下载列表项 AppView.xib。一个imageview,一个label,一个button构成 1.创建AppView.xib 2.再创建xib对应的mode&#xff0…

【树莓派Pico设备驱动】-WS2812B全彩LED驱动(基于SPI)

WS2812B全彩LED驱动(基于SPI) 文章目录 WS2812B全彩LED驱动(基于SPI)1、WS2812介绍2、WS2812配置4、驱动实现1、WS2812介绍 WS2812/WS2812B LED 使用 24 位来表示绿色、红色和蓝色值。 WS2812采用单线通信的设计,通信协议为非归零编码,每个LED需要24个bit的数据,数据依…

AIGC-微头条爆款文案创作智能体完整指令(DeepSeek,豆包,千问,Kimi,GPT)

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列AIGC(GPT、DeepSeek、豆包、千问、Kimi)👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资…