当前位置: 首页 > news >正文

VTK平面切割

文章目录

    • 一、vtkClipPolyData
    • 二、CapClip
    • 三、SolidClip
    • 四、vtkClipClosedSurface

本文的主要内容:简单介绍VTK中通过平面切割模型的相关功能。
哪些人适合阅读本文:有一定VTK基础的人。

一、vtkClipPolyData

VTK官网描述:
vtkClipPolyData使用用户指定的隐函数剪切多边形数据,如果使用vtkPlane作为隐函数就是平面切割。
vtkClipPolyData是一个过滤器,它使用vtkImplicitFunction的任何子类或输入标量数据来剪辑多边形数据。剪切意味着它实际上“剪切”了数据集的单元格,返回指定隐式函数(或大于标量值)内的所有内容,包括单元格的“片段”。(将其与vtkExtractGeometry进行比较,后者提取整个未切割的单元格。)此过滤器的输出是多边形数据。
要使用此过滤器,必须决定是使用隐式函数进行剪裁,还是使用输入标量数据。如果你想使用隐式函数进行剪裁,你必须:1)定义一个隐式函数2)用SetClipFunction方法设置它3)应用GenerateClipScalarsOn方法如果未指定ClipFunction,或者GenerateClipScalar处于关闭状态(默认设置),则输入的标量数据将用于剪裁polydata。
还可以指定一个标量值,用于决定隐式函数内部和外部的内容。还可以通过设置InsideOut实例变量来颠倒内部/外部的含义。(切割算法通过计算隐式函数值或使用数据集中每个点的输入标量数据来进行。将其与标量值进行比较以确定内部/外部。)
该滤波器可以被配置为计算第二输出。第二个输出是剪切掉的多边形数据。如果要访问此输出数据,请启用GenerateClippedData布尔值。

vtkClipPolyData的使用很简单:

vtkNew<vtkSphereSource> source;
source->SetThetaResolution(20);
source->SetPhiResolution(20);
source->Update();vtkNew<vtkPlane> plane;
plane->SetOrigin(polyData->GetCenter());
plane->SetNormal(1.0, -1.0, -1.0);vtkNew<vtkClipPolyData> clipper;
clipper->SetInputData(source->GetOutput());
clipper->SetClipFunction(plane);
clipper->Update();

在这里插入图片描述
这种方法切完之后是个空壳子,切口不封闭。要想让切割之后的切口封闭,继续往下看。

二、CapClip

此示例显示了如何在剪切的vtkPolyData上生成“上限”。在使用vtkClipPolyData进行裁剪后,它使用了一种巧妙的“技巧”将折线转换为多边形。
就是通过vtkFeatureEdges和vtkStripper将切割之后的边缘进行封闭。

// Extract feature edges
vtkNew<vtkFeatureEdges> boundaryEdges;
boundaryEdges->SetInputData(clipper->GetOutput());
boundaryEdges->BoundaryEdgesOn();
boundaryEdges->FeatureEdgesOff();
boundaryEdges->NonManifoldEdgesOff();
boundaryEdges->ManifoldEdgesOff();vtkNew<vtkStripper> boundaryStrips;
boundaryStrips->SetInputConnection(boundaryEdges->GetOutputPort());
boundaryStrips->Update();// Change the polylines into polygons
vtkNew<vtkPolyData> boundaryPoly;
boundaryPoly->SetPoints(boundaryStrips->GetOutput()->GetPoints());
boundaryPoly->SetPolys(boundaryStrips->GetOutput()->GetLines());vtkNew<vtkPolyDataMapper> boundaryMapper;
boundaryMapper->SetInputData(boundaryPoly);vtkNew<vtkActor> boundaryActor;
boundaryActor->SetMapper(boundaryMapper);
boundaryActor->GetProperty()->SetDiffuseColor(boundaryColor.GetData());

在这里插入图片描述

三、SolidClip

此示例剪裁网格并将背面特性应用于该网格,使其看起来具有实心内部。
还显示了被剪掉的部分的“幽灵”。

其实还是用vtkClipPolyData来切割,然后通过将模型内表面的漫反射和镜面反射光关闭,只保留环境光,造成一种视觉上模型是实心的效果。

// Create a mapper and actor
vtkNew<vtkPolyDataMapper> superquadricMapper;
superquadricMapper->SetInputConnection(clipper->GetOutputPort());vtkNew<vtkActor> superquadricActor;
superquadricActor->SetMapper(superquadricMapper);// Create a property to be used for the back faces. Turn off all
// shading by specifying 0 weights for specular and diffuse. Max the
// ambient.
vtkNew<vtkProperty> backFaces;
backFaces->SetSpecular(0.0);
backFaces->SetDiffuse(0.0);
backFaces->SetAmbient(1.0);
backFaces->SetAmbientColor(colors->GetColor3d("Tomato").GetData());superquadricActor->SetBackfaceProperty(backFaces);

在这里插入图片描述

四、vtkClipClosedSurface

VTK官网描述:
使用平面集合剪裁闭合曲面。
vtkClipClosedSurface将使用一组剪裁平面剪裁一个闭合的polydata曲面。它将通过创建剪切输入数据的新多边形面来生成新的闭合曲面。
形成曲面的多边形的方向很重要。多边形有一个正面和一个背面,背面定义了闭合曲面的内部或“实体”区域。当剪切平面剪切穿过“实体”区域时,会生成一个新的剪切面,但当剪切平面切割穿过孔或“空”区域时则不会。在处理复杂曲面时,这种区别至关重要。请注意,如果一个简单曲面的背面朝外,则该曲面在潜在的无限实体中定义了一个孔。
非歧管表面不应用作此过滤器的输入。输入曲面不应有开放边,并且不得有任何由两个以上面共享的边。vtkFeatureEdges过滤器可用于验证数据集是否满足这些条件。此外,输入曲面不应自相交,这意味着曲面的面只应接触其边缘。
如果启用了GenerateOutline,则此过滤器将在剪裁平面与数据相交的任何位置生成轮廓。ScalarMode选项将向输出中添加单元格标量,以便生成的面可以以与原始曲面不同的颜色显示。
InsideOut标志可用于反转剪辑区域内外的含义。这将更改剪裁平面的哪一侧被剪裁掉。
该滤波器可以被配置为计算第二输出。第二个输出是具有新三角面的多边形数据。如果要访问此输出数据,请启用GenerateClipFaceOutput布尔值。

vtkClipClosedSurface需要输入一个polyData和一组vtkPlaneCollection面集合,有两种输出一种是剪切之后的模型,一种是剪切的面的模型。

vtkNew<vtkNamedColors> colors;// PolyData to process
vtkSmartPointer<vtkPolyData> polyData;// Create a sphere
vtkNew<vtkSphereSource> sphereSource;
sphereSource->SetThetaResolution(20);
sphereSource->SetPhiResolution(11);
sphereSource->Update();polyData = sphereSource->GetOutput();auto center = polyData->GetCenter();
vtkNew<vtkPlane> plane1;
plane1->SetOrigin(center[0], center[1], center[2]);
plane1->SetNormal(0.0, -1.0, 0.0);
vtkNew<vtkPlane> plane2;
plane2->SetOrigin(center[0], center[1], center[2]);
plane2->SetNormal(0.0, 0.0, 1.0);
vtkNew<vtkPlane> plane3;
plane3->SetOrigin(center[0], center[1], center[2]);
plane3->SetNormal(-1.0, 0.0, 0.0);vtkNew<vtkPlaneCollection> planes;
planes->AddItem(plane1);
planes->AddItem(plane2);
planes->AddItem(plane3);vtkNew<vtkClipClosedSurface> clipper;
clipper->SetInputData(polyData);
clipper->SetClippingPlanes(planes);
clipper->SetActivePlaneId(2);
clipper->SetScalarModeToColors();
clipper->SetClipColor(colors->GetColor3d("Banana").GetData());
clipper->SetBaseColor(colors->GetColor3d("Tomato").GetData());
clipper->SetActivePlaneColor(colors->GetColor3d("Green").GetData());
clipper->GenerateClipFaceOutputOn();
clipper->Update();vtkNew<vtkDataSetMapper> clipMapper;
clipMapper->SetInputConnection(clipper->GetOutputPort());
//clipMapper->SetInputData(clipper->GetClipFaceOutput());vtkNew<vtkActor> clipActor;
clipActor->SetMapper(clipMapper);
clipActor->GetProperty()->SetColor(colors->GetColor3d("tomato").GetData());
clipActor->GetProperty()->SetInterpolationToFlat();

在这里插入图片描述
在这里插入图片描述
vtkClipClosedSurface和SolidClip这两种方法都有一个小问题,就是模型被一刀切完。如果只想切一半的话就没办法实现。

如果只想切一部分的话,在vtkClipClosedSurface里面SetClippingPlanes设置一个面的集合就可以,但是这个面集必须是闭合的,得到的效果如下图所示。
在这里插入图片描述
可以看出这种方法切出来的必然是一个凸集,要想切一个凹面如下图所示的效果,这种方法就做不了。
为什么会这样?是因为vtkClipClosedSurface的原理是把每个切割面法相对应的模型全部切掉,如下图所示。最后只剩下闭合平面包络中心的模型被保留。
在这里插入图片描述
可以想想看,无论怎么设计闭合平面以及平面法线如何指向,都无法得到下图所示的切割模型。
那么要如何实现切割凹面模型?可以尝试vtk的纹理切割,主要用到的是vtkImplicitTextureCoords,具体可以看官方例子,切出的效果是这样的。
在这里插入图片描述
可以看出也没有封口,要封口也不难,改变一下纹理就可以。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Spring 框架下 Redis 数据结构的全面解析
  • 【Unity小工具】Image组件宽度、高度自适应
  • 【Google Play】X浏览器4.8.1国际版(如何鉴别是否官方?)
  • 掌握 SQL 数据操纵的基础技巧
  • 点亮ESP 32 板载LED 灯
  • Java 入门指南:Java 并发编程 —— 并发容器 PriorityBlockingQueue
  • Spark2.x 入门:逻辑回归分类器
  • 简单的Linux Ftp服务搭建
  • 通过redis-operator 来部署 Redis Cluster 集群
  • 【大数据】Canal实现MySQL数据增量同步至Kafka:原理与配置解析
  • MSSQL数据库安全配置
  • 北京君正低功耗MCU芯片应用在柯氏音法电子血压计
  • 使用 ELK Stack 进行云原生日志记录和监控:AWS 中的开发运营方法
  • Python【1】
  • JS设计模式之“神奇的魔术师” - 简单工厂模式
  • iBatis和MyBatis在使用ResultMap对应关系时的区别
  • JavaScript 奇技淫巧
  • javascript 总结(常用工具类的封装)
  • leetcode46 Permutation 排列组合
  • php的插入排序,通过双层for循环
  • Promise面试题2实现异步串行执行
  • Protobuf3语言指南
  • ReactNative开发常用的三方模块
  • vagrant 添加本地 box 安装 laravel homestead
  • 编写高质量JavaScript代码之并发
  • 前端之Sass/Scss实战笔记
  • 原生Ajax
  • 阿里云服务器如何修改远程端口?
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • # 利刃出鞘_Tomcat 核心原理解析(八)-- Tomcat 集群
  • (2022版)一套教程搞定k8s安装到实战 | RBAC
  • (4)事件处理——(7)简单事件(Simple events)
  • (C#)一个最简单的链表类
  • (JS基础)String 类型
  • (k8s)Kubernetes 从0到1容器编排之旅
  • (八)Spring源码解析:Spring MVC
  • (二)原生js案例之数码时钟计时
  • (机器学习的矩阵)(向量、矩阵与多元线性回归)
  • (剑指Offer)面试题34:丑数
  • (强烈推荐)移动端音视频从零到上手(下)
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • (转)树状数组
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .libPaths()设置包加载目录
  • .NET 发展历程
  • .NET 中小心嵌套等待的 Task,它可能会耗尽你线程池的现有资源,出现类似死锁的情况
  • .NET轻量级ORM组件Dapper葵花宝典
  • .NET使用HttpClient以multipart/form-data形式post上传文件及其相关参数
  • .NET中GET与SET的用法
  • @JsonFormat 和 @DateTimeFormat 的区别
  • @四年级家长,这条香港优才计划+华侨生联考捷径,一定要看!
  • [ Linux 长征路第五篇 ] make/Makefile Linux项目自动化创建工具
  • [ 代码审计篇 ] 代码审计案例详解(一) SQL注入代码审计案例
  • [ 云计算 | AWS 实践 ] Java 如何重命名 Amazon S3 中的文件和文件夹
  • [2]十道算法题【Java实现】