VTK笔记-使用vtkSplineFilter类处理3D空间曲线-程序员宅基地

技术标签: VTK笔记-图形相关  VTK  

在之前笔记VTK笔记-图形相关-线段平滑-vtkSplineFilter类中,得知
vtkSplineFilter类用于对多线段的输入数据进行细化输出具有更多线段的点集合;
vtkSplineFilter类不仅可以用于插值,也可以进行抽样;
通过vtkSplineFilter类的SetSubdivideToSpecified()接口和SetSubdivideToLength()接口可以设置插值或抽样的方法;
SetSubdivideToSpecified()接口设置细化的个数,SetNumberOfSubdivisions用于设定输出线段的个数;

spline->SetSubdivideToSpecified();
spline->SetNumberOfSubdivisions(3);	

SetSubdivideToLength()接口设置每个线片段的长度;将曲线的长度总和除以每个线段的长度,就可以得到最终线段个数;

vtkNew<vtkSplineFilter> spline;
spline->SetInputDataObject(polyData);
spline->SetSpline(cardinal_spine);
spline->SetSubdivideToLength();
spline->SetLength(1);

示例代码

使用vtkParametricSpline类将四个点插值出一条曲线;

double p0[3] = {
     1.0, 0.0, 0.0 };
double p1[3] = {
     0.0, 1.0, 0.0 };
double p2[3] = {
     0.0, 0.0, 1.0 };
double p3[3] = {
     1.0, 2.0, 3.0 };

vtkNew<vtkPoints> points;
points->InsertNextPoint(p0);
points->InsertNextPoint(p1);
points->InsertNextPoint(p2);
points->InsertNextPoint(p3);

vtkNew<vtkParametricSpline> spline;
spline->SetPoints(points);
	
vtkNew<vtkParametricFunctionSource> functionSource;
functionSource->SetParametricFunction(spline);
functionSource->Update();

vtkNew<vtkPolyDataMapper> splineMapper;
splineMapper->SetInputConnection(functionSource->GetOutputPort());

vtkNew<vtkActor> splineActor;
splineActor->SetMapper(splineMapper);

vtkNew<vtkPolyData> resultPolydata;
resultPolydata->SetPoints(points);

vtkNew<vtkVertexGlyphFilter> resultGlyphFilter;
resultGlyphFilter->AddInputData(resultPolydata);
resultGlyphFilter->Update();

vtkNew<vtkPolyDataMapper> resultMapper;
resultMapper->SetInputConnection(resultGlyphFilter->GetOutputPort());
vtkNew<vtkActor> resultActor;
resultActor->SetMapper(resultMapper);
resultActor->GetProperty()->SetPointSize(5);//定义点的尺寸大小,这样点才能在画布上显示出来
resultActor->GetProperty()->SetColor(1, 0.0, 0.0);
	
vtkNew<vtkRenderer> ren1;
ren1->AddActor(splineActor);
ren1->AddActor(resultActor);
ren1->SetBackground(0.1, 0.2, 0.4);

vtkNew<vtkRenderWindow> renWin;
renWin->AddRenderer(ren1);
renWin->SetSize(300, 300);

vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin);
iren->Initialize();
iren->Start();

在这里插入图片描述
或者使用vtkSplineFilter类将四个点插值出一条曲线;

double p0[3] = {
     1.0, 0.0, 0.0 };
double p1[3] = {
     0.0, 1.0, 0.0 };
double p2[3] = {
     0.0, 0.0, 1.0 };
double p3[3] = {
     1.0, 2.0, 3.0 };

vtkNew<vtkPoints> points;
points->InsertNextPoint(p0);
points->InsertNextPoint(p1);
points->InsertNextPoint(p2);
points->InsertNextPoint(p3);

vtkNew<vtkCellArray> lines;
lines->InsertNextCell(4);
for (unsigned long i = 0; i < 4; ++i) {
    
	lines->InsertCellPoint(i);
}
vtkNew<vtkPolyData> polyData;
polyData->SetPoints(points);
polyData->SetLines(lines);

vtkNew<vtkSplineFilter> spline;
vtkNew<vtkCardinalSpline> cardinal_spine;

spline->SetInputDataObject(polyData);
spline->SetSpline(cardinal_spine);
spline->SetSubdivideToLength();
spline->SetLength(0.1);
spline->Update();

vtkNew<vtkPolyDataMapper> splineMapper;
splineMapper->SetInputConnection(spline->GetOutputPort());

vtkNew<vtkActor> splineActor;
splineActor->SetMapper(splineMapper);

vtkNew<vtkPolyData> resultPolydata;
resultPolydata->SetPoints(points);

vtkNew<vtkVertexGlyphFilter> resultGlyphFilter;
resultGlyphFilter->AddInputData(resultPolydata);
resultGlyphFilter->Update();

vtkNew<vtkPolyDataMapper> resultMapper;
resultMapper->SetInputConnection(resultGlyphFilter->GetOutputPort());
vtkNew<vtkActor> resultActor;
resultActor->SetMapper(resultMapper);
resultActor->GetProperty()->SetPointSize(5);//定义点的尺寸大小,这样点才能在画布上显示出来
resultActor->GetProperty()->SetColor(1, 0.0, 0.0);
	
vtkNew<vtkRenderer> ren1;
ren1->AddActor(splineActor);
ren1->AddActor(resultActor);
ren1->SetBackground(0.1, 0.2, 0.4);

vtkNew<vtkRenderWindow> renWin;
renWin->AddRenderer(ren1);
renWin->SetSize(300, 300);

vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin);
iren->Initialize();
iren->Start();
return 0;

在这里插入图片描述
使用SetLength(1)的结果:
在这里插入图片描述
注意:从上图可以看出vtkSplineFilter类抽点和插值后的线段不一定通过输入点的位置;
设置SetNumberOfSubdivisions的个数为3时;

double p0[3] = {
     1.0, 0.0, 0.0 };
double p1[3] = {
     0.0, 1.0, 0.0 };
double p2[3] = {
     0.0, 0.0, 1.0 };
double p3[3] = {
     1.0, 2.0, 3.0 };

vtkNew<vtkPoints> points;
points->InsertNextPoint(p0);
points->InsertNextPoint(p1);
points->InsertNextPoint(p2);
points->InsertNextPoint(p3);
vtkNew<vtkCellArray> lines;
lines->InsertNextCell(4);
for (unsigned long i = 0; i < 4; ++i) {
    
	lines->InsertCellPoint(i);
}
vtkNew<vtkPolyData> polyData;
polyData->SetPoints(points);
polyData->SetLines(lines);

vtkNew<vtkSplineFilter> spline;
vtkNew<vtkCardinalSpline> cardinal_spine;

spline->SetInputDataObject(polyData);
spline->SetSpline(cardinal_spine);
spline->SetSubdivideToSpecified();
spline->SetNumberOfSubdivisions(3);	
spline->Update();

vtkNew<vtkPolyDataMapper> splineMapper;
splineMapper->SetInputConnection(spline->GetOutputPort());

vtkNew<vtkActor> splineActor;
splineActor->SetMapper(splineMapper);

vtkNew<vtkPolyData> resultPolydata;
resultPolydata->SetPoints(points);

vtkNew<vtkVertexGlyphFilter> resultGlyphFilter;
resultGlyphFilter->AddInputData(resultPolydata);
resultGlyphFilter->Update();

vtkNew<vtkPolyDataMapper> resultMapper;
resultMapper->SetInputConnection(resultGlyphFilter->GetOutputPort());
vtkNew<vtkActor> resultActor;
resultActor->SetMapper(resultMapper);
resultActor->GetProperty()->SetPointSize(5);//定义点的尺寸大小,这样点才能在画布上显示出来
resultActor->GetProperty()->SetColor(1, 0.0, 0.0);

vtkNew<vtkRenderer> ren1;
ren1->AddActor(splineActor);
ren1->AddActor(resultActor);
ren1->SetBackground(0.1, 0.2, 0.4);

vtkNew<vtkRenderWindow> renWin;
renWin->AddRenderer(ren1);
renWin->SetSize(300, 300);

vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin);
iren->Initialize();
iren->Start();
return 0;

在这里插入图片描述
设置SetNumberOfSubdivisions的个数为30时;
在这里插入图片描述

对曲线数据的进一步处理

如果我们的输入数据是一条携带很多干扰的曲线,曲线上有较多的高频信号;例如下图,
在这里插入图片描述
我们就可以先对该数据进行一个抽点操作(其实这里应该操作的是低通滤波),然后再插值操作,就会得到稍微平滑的曲线;
vtkSplineFilter类就可以实现这么一个简单的操作;
当我们对一条平滑曲线移动或者修改某一个点的位置时,就可能会破坏曲线的平滑度。可以使用vtkSplineFilter类修复平滑,不过使用vtkSplineFilter类并不是上上之策,三维曲线的滤波应该是一个比较好的选择。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/liushao1031177/article/details/120966778

智能推荐

ASR6501模组Cortex-M0+ SX1262 PSoC+LoRaWAN节点模块 CubeCell系列AT指令中文手册_sx1262中文手册-程序员宅基地

文章浏览阅读2.2k次。CubeCell系列AT指令中文手册0.版权声明1.摘要2.串口设置3. AT指令语法3.1语法概述3.2 AT指令集基础控制指令(括号中为译者注释,并不会显示)用户AT指令用户AT指令执行逻辑“ 普通LoRa模式”专有指令设置LoRa监听/发送参数接收模式接收数据输出模式选择LoRaWAN模式专有指令设置 DevEui设置 AppEui设置AppKey设置NwkSKey设置 AppSKey设置 DevAddr设置 OTAA / ABP mode配置ADR配置LoRaWAN通道掩码触发OTAA访问设置通讯周_sx1262中文手册

C++语法基础-程序员宅基地

文章浏览阅读122次。两种方法 一种是宏定义 一种是const修饰c++风格字符串跟定义变量是一样的 前提是要加上一个头文件#include。

基于springboot2.1.7的springcloud(简单应用)eureka+Feign远程调用服务_org.springframework.boot2.7.17该使用那个版本的feign-程序员宅基地

文章浏览阅读1.3k次,点赞2次,收藏3次。基于springboot2.1.7的springcloud前言搭建一个父maven项目搭建Eureka注册中心搭建提供者搭建消费者前言不同的springboot对应的springcloud版本可能不一样,就拿springboot2.1.7或者2.1.8来说,它对应的springcloud版本是Greenwich.SR3。这些对应的版本信息都是从官方文档中所得知,所以要养成翻阅官方文档的好习惯。..._org.springframework.boot2.7.17该使用那个版本的feign

【转】加权最小二乘法_带权函数的最小二乘法-程序员宅基地

文章浏览阅读4.9k次,点赞4次,收藏44次。加权最小二乘、迭代最小二乘、抗差最小二乘、稳健最小二乘他们细节的区别我就不过分研究了,不过这些最小二乘似乎表达的是一个意思:构造权重函数,给不同测量值不同的权重,偏差大的值权重小,偏差小的权重大,采用迭代最小二乘的方式最优化目标函数。下面是matlab中robustfit函数权重函数,可以参考一下:..._带权函数的最小二乘法

openstack keystone 添加工程以及用户_openstack将用户加入到用户组-程序员宅基地

文章浏览阅读2.3k次。keystone用户管理可以通过rest api进行,也可以通过相关的命令行进行。python-keystone是keystone认证组件的一个客户端,提供了两种使用方式,(1)python编程接口 (2)命令行接口# Using token auth env variablesexport SERVICE_ENDPOINT=http://127.0.0.1:3535_openstack将用户加入到用户组

基于Python爬虫江苏南京餐厅餐馆数据可视化系统设计与实现(Django框架) 研究背景与意义、国内外研究现状-程序员宅基地

文章浏览阅读2.2k次,点赞21次,收藏19次。基于Python爬虫江苏南京餐厅餐馆数据可视化系统设计与实现(Django框架) 研究背景与意义、国内外研究现状毕设毕业设计源代码,经营者可以了解顾客的消费习惯、评价意见等信息,从而调整经营策略,提供更好的服务,增加顾客的满意度和忠诚度。消费者可以通过系统获得餐厅餐馆的基本信息、价格、评价等数据,从而能够更好地了解餐厅餐馆的情况,减少了选择就餐场所时的盲目性,提高了消费者的就餐体验。通过数据可视化的方式,餐厅餐馆可以直观地展示自己的特色、菜品、评价等信息,提高了餐厅餐馆的知名度和曝光率,吸引更多的潜在顾客。

随便推点

c++编写暴力破解密码_怎么用c++破译administrator密码-程序员宅基地

文章浏览阅读760次。打开控制台:windows+R,进入目录路径。三、将两个程序复制到一个文件夹中。_怎么用c++破译administrator密码

社会网络分析能干什么?_社会网络分析用来做什么-程序员宅基地

文章浏览阅读8.5k次,点赞3次,收藏11次。现在来看,社会网络分析可以解决或可以尝试解决下列问题:1-人际传播问题,发现舆论领袖,创新扩散过程;2-小世界理论,六度空间分割理论;3-Web分析,数据挖掘中的关联分析,形成交叉销售,增量销售,也就是啤酒和尿布的故事;4-社会资本,产业链与价值链;5-文本的意义输出,通过追问调查研究文本的关联和意义;6-竞争情报分析;7-语言的关联,符号意_社会网络分析用来做什么

开源软件的总拥有成本指南_使用开源软件需要履行哪些义务-程序员宅基地

文章浏览阅读2.2k次,点赞3次,收藏5次。使用现成的软件能加速开发进程。然而开源软件(OSS)并不是免费使用的。使用开源软件往往伴随着承担义务和风险,这些都是成本。本指南根据公开信息和我15年的经验总结了使用开源软件进行专业软件开发的成本。_使用开源软件需要履行哪些义务

ROS2 Warning: RosPluginProvider._parse_plugin_xml() plugin file rqt_gui_cpp/plugin.xml not found-程序员宅基地

文章浏览阅读1k次。ROS2运行rqt指令,出现一个警告,RosPluginProvider._parse_plugin_xml() plugin file "C:\dev\ros2_galactic\share\rqt_gui_cpp/plugin.xml" in package "rqt_gui_cpp" not found原因,RosPluginProvider._parse_plugin_xml() plugin 在windows系统上不受支持。参考,https://github.com/ros-v_rospluginprovider._parse_plugin_xml() plugin file "/opt/ros/kinetic/share/rq

精品单页个人导航HTML源码_单页导航源码-程序员宅基地

文章浏览阅读1k次。简约大气精品单页导航-可自行修改其他页面,源码由HTML+CSS+JS组成,记事本打开源码文件可以进行内容文字之类的修改,双击html文件可以本地运行效果,也可以上传到服务器里面。_单页导航源码

Axure RP医疗在线挂号问诊原型图医院APP原形模板_医疗app原型-程序员宅基地

文章浏览阅读1.1k次。本套原型图主要功能有医疗常识科普、医院挂号、排队预约、在线问诊、医院查找等,基本所有模块都是原创设计。同时页面中使用了大量的动态面板效果,制作了仿真的预约弹窗、医院详情介绍等。你可以将页面直接套用在类似项目上,或直接在模板上拓展页面,快速搭建出高质量的医疗类APP。医疗在线挂号问诊Axure RP原型图医院APP原形模板,是一款原创的医疗类APP,设计尺寸采用iPhone13(375*812px),原型图上加入了仿真手机壳,使得预览效果更加逼真。_医疗app原型

推荐文章

热门文章

相关标签