在实际的开发中,提供有限的连续线段组成一条曲线,需要将该条曲线进行插值处理,生成更高采样率的曲线;这种情况下就需要进行插值;VTK中的线段插值是通过B样条插值实现,使用vtkSplineFilter完成这一功能;

vtkSplineFilter

  vtkSplineFilter是一个从多段线的输入集生成输出多段线的Filter。
  通过用户可以指定的vtkSpline类(默认情况下使用vtkCardinalSpline),可以对多段线进行统一细分和生成。可以通过多种方式控制线的细分数目。用户可以指定细分的数量,也可以提供每个细分的长度(vtkSplineFilter类将计算出整个多段线上需要计算出多少个细分段)。也可以设置最大细分数。
  此Filter的输出是每个输入多段线(或线)的多段线。将创建新的点和纹理坐标。对点数据进行插值,并传递单元数据。任何少于两点的多段线或具有重合点的多段线都将被忽略。

接口

细分段个数

vtkSetClampMacro(NumberOfSubdivisions, int, 1, VTK_INT_MAX);
vtkGetMacro(NumberOfSubdivisions, int);
vtkSetClampMacro(MaximumNumberOfSubdivisions, int, 1, VTK_INT_MAX);
vtkGetMacro(MaximumNumberOfSubdivisions, int);
void SetSubdivideToSpecified() { this->SetSubdivide(VTK_SUBDIVIDE_SPECIFIED); }
void SetSubdivideToLength() { this->SetSubdivide(VTK_SUBDIVIDE_LENGTH); }
vtkSetClampMacro(Subdivide, int, VTK_SUBDIVIDE_SPECIFIED, VTK_SUBDIVIDE_LENGTH);
vtkGetMacro(Subdivide, int);
vtkSetClampMacro(Length, double, 0.0000001, VTK_DOUBLE_MAX);
vtkGetMacro(Length, double);
const char* GetSubdivideAsString();

  SetNumberOfSubdivisions:设置为多段线创建的细分数目。只有将Subdivisions设置为SetSubdivisionsToSpecify()时,此方法才有效。
  SetSubdivideToSpecified:指定如何确定细分数目。
  SetLength基于绝对长度控制为多段线创建的细分数目。样条曲线的长度除以此长度以确定细分的数目。只有将Subdivisions设置为SetSubdivideToLength()时,此方法才有效。
  SetMaximumNumberOfSubdivisions:设置为每条多段线创建的最大细分数。

插值类型对象

vtkSpline是样条插值的样条抽象类,SetSpline设置了vtkSplineFilter使用的vtkSpline的派生类对象,可以使用vtkCardinalSpline/vtkKochanekSpline/vtkSCurveSpline;

virtual void SetSpline(vtkSpline*);
vtkGetObjectMacro(Spline, vtkSpline);

纹理坐标

  纹理坐标可以通过三种方式生成:归一化(0,1)生成;基于长度(除以纹理长度);通过使用输入的标量值。

意义
VTK_TCOORDS_FROM_NORMALIZED_LENGTH 归一化方式
VTK_TCOORDS_FROM_LENGTH 基于长度方式
VTK_TCOORDS_FROM_SCALARS 基于输入的标量值方式
vtkSetClampMacro(GenerateTCoords, int, VTK_TCOORDS_OFF, VTK_TCOORDS_FROM_SCALARS);
vtkGetMacro(GenerateTCoords, int);
void SetGenerateTCoordsToOff() { this->SetGenerateTCoords(VTK_TCOORDS_OFF); }
void SetGenerateTCoordsToNormalizedLength(){this->SetGenerateTCoords(VTK_TCOORDS_FROM_NORMALIZED_LENGTH);}
void SetGenerateTCoordsToUseLength() { this->SetGenerateTCoords(VTK_TCOORDS_FROM_LENGTH); }
void SetGenerateTCoordsToUseScalars() { this->SetGenerateTCoords(VTK_TCOORDS_FROM_SCALARS); }
const char* GetGenerateTCoordsAsString();
vtkSetClampMacro(TextureLength, double, 0.000001, VTK_INT_MAX);
vtkGetMacro(TextureLength, double);

vtkSpline


  vtkSpline插值一组数据点(插值意味着样条曲线通过这些点)。
  vtkSpline是一个抽象类:它的子类vtkCardinalSpline、vtkKochanekSpline和vtkSCurveSpline实现vtkSpline提供的接口功能。请注意,此样条曲线将1D参数化坐标t映射为单个值x。因此,如果要使用样条曲线插值点(即x[3]),则必须为每个x-y-z坐标创建三条样条曲线。vtkParametricSpline类可以将离散点拟合成一条样条曲线。通常,样条曲线是通过添加一系列参数坐标/数据(t,x)值,然后使用求值函数(例如,vtkCardinalSpline::Evaluate())来使用的。因为这些样条曲线是一维的,所以这里的一个点是独立/因变量对。样条曲线也可以设置为关闭或打开。闭合样条曲线以连续函数和导数值从最后一点延续到第一点(无需复制第一个点即可闭合样条曲线,只需设置ClosedOn即可)。
  样条曲线的这种实现不使用规范化的参数化坐标。如果样条曲线打开,则参数空间为(tMin<=t<=tMax),其中tMin和tMax是执行AddPoint()时看到的最小和最大参数值。如果样条曲线是闭合的,那么参数空间是(tMin<=t<=(tMax+1)),其中tMin和tMax是执行AddPoint()时看到的最小和最大参数值。但是,请注意,可以通过显式设置ParametricRange(tMin,tMax)来更改此行为。如果设置,则参数空间保持不变(tMin<=t<=tMax),除非参数值超出此范围的数据的添加被限制在此范围内。
样条:通过一组指定点集生成平滑曲线的柔型带;
样条曲线:计算机图形学中,样条曲线指多项式曲线段连接而成的曲线;

样条(Spline) 可以理解为 多段 Cubic Curve 的拼接,不过样条在 Cubic Curve 拼接的时候,提出了特殊要求:两段 Cubic Curve 在拼接的位置,需要能够“平滑衔接”,以保证整个样条的曲线平滑。这种“平滑衔接”,是通过导数和曲线的连续性来实现的。

需要实现的两个接口

virtual void Compute() = 0;
virtual double Evaluate(double t) = 0;

参数空间

void SetParametricRange(double tMin, double tMax);
void SetParametricRange(double tRange[2]) { this->SetParametricRange(tRange[0], tRange[1]); }
void GetParametricRange(double tRange[2]) const;

  SetParametricRange设置参数空间范围;如果未设置,则通过跟踪t的(min,max)参数值隐式确定范围。如果设置了,AddPoint()方法会将t值钳制在指定的范围内。

样条曲线拟合的点

void AddPoint(double t, double x);
void RemovePoint(double t);
void RemoveAllPoints();
int GetNumberOfPoints();

  AddPoint添加一对要与样条曲线拟合的点。
  RemovePoint移除一个坐标对应的点;
  RemoveAllPoints移除所有点;

夹逼模式

vtkSetMacro(ClampValue, vtkTypeBool);
vtkGetMacro(ClampValue, vtkTypeBool);
vtkBooleanMacro(ClampValue, vtkTypeBool);

  SetClampValue设置插值夹逼类型,如果启用,插值结果将被钳制为输入数据的最小值/最大值。

样条区间是否打开

vtkSetMacro(Closed, vtkTypeBool);
vtkGetMacro(Closed, vtkTypeBool);
vtkBooleanMacro(Closed, vtkTypeBool);

  SetClosed()设置是否开启闭合样条曲线,闭合样条曲线形成一个连续的循环:第一个点和最后一个点是相同的,导数是连续的。

   vtkSetClampMacro(LeftConstraint, int, 0, 3);vtkGetMacro(LeftConstraint, int);vtkSetClampMacro(RightConstraint, int, 0, 3);vtkGetMacro(RightConstraint, int);  vtkSetMacro(LeftValue, double);vtkGetMacro(LeftValue, double);vtkSetMacro(RightValue, double);vtkGetMacro(RightValue, double);

  SetLeftConstraint和SetRightConstraint设置左(右)端点的约束类型。
  有四个约束:

含义
0 最左(右)点的一阶导数由前(后)两点定义的直线确定
1 最左(右)点的一阶导数设为左(右)值
2 最左(右)点的二阶导数设为左(右)值
3 最左(右)点的二阶导数是左(右)值乘以第一个内点的二阶导数

  SetLeftValue和SetRightValue用来设置左右两边导数的值。

vtkCardinalSpline

  在Cardinal样条中,一个控制点的一阶导数值可以由两个相邻控制点的坐标进行计算。
  一个Cardinal样条完全由四个连续控制点给出,中间两个控制点是曲线端点,另外两个点用于计算端点斜率。
  如图14.12所示,设P(u)是两控制点Pk和Pk+1间的参数三次函数式,则从Pk-1到Pk+1间的四个控制点用于建立cardinal样条段的边界条件:
    P(0) = pk;
    P(1) = pk+1;
    P(0) =1/2*(1-t)(pk+1-pk-1);
    P(1) =1/2
(1-t)*(pk+2-pk);
  控制点Pk​和Pk+1处的一阶导数(斜率)分别和弦Pk-1Pk+1和PkPk+2​成正比。参数t称为张量(tension)参数,因为t控制cardinal样条与输入控制点之间的松紧程度。图14.14说明了张量t取很大和很小值时cardinal曲线的形状。当t=0时,这样的曲线称为Catmull-Rom样条或Overhauser样条。

接口

在这里插入代码片

vtkKochanekSpline

  vtkKochanekSpline提供三个参数来控制花键的形状:
    张力:更改切线向量的长度;
    偏差:主要改变切向量的方向;
    连续性:改变切线之间变化的清晰度;
  给出了四个连续控制点,记为Pk-1、Pk、Pk+1和Pk+2,在Pk和Pk+1间的Konchanek-Bartels曲线段中的边界条件定义为:
    P(0) = pk;
    P(1) = pk+1;
    P(0)in =1/2*(1-t*)[(1+b)(1-c)*(pk-pk-1)+(1-b)+(1-b)*(1+c)*(pk+1-pk)];
    P(1)out 1/2*(1-t*)[(1+b)(1+c)*(pk+1-pk)+(1-b)+(1-b)*(1-c)*(pk+2-pk+1)];
其中t是张量(tension)参数,b是偏离(bias)参数,c是连续性(continuity)参数。在Konchanek-Bartels公式中,导数在曲线段边界处不一定是连续。
张量参数t具有cardinal样条公式中同样的解释,即该参数控制曲线段的松紧程度。偏离参数b用来调整曲线段在端点处弯曲的数值,因此曲线段可以偏向一个端点或另一个端点(参见图14.19)。参数c控制切向量在曲线段边界处的连续性。若c取非零值,则曲线在曲线段边界处的斜率上具有不连续性。

#include <vtkActor.h>
#include <vtkGlyph3DMapper.h>
#include <vtkKochanekSpline.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkParametricFunctionSource.h>
#include <vtkParametricSpline.h>
#include <vtkPointSource.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
using namespace std;int main()
{vtkNew<vtkNamedColors> colors;int numberOfPoints = 10;vtkNew<vtkPointSource> pointSource;pointSource->SetNumberOfPoints(numberOfPoints);pointSource->Update();vtkPoints* points = pointSource->GetOutput()->GetPoints();vtkNew<vtkKochanekSpline> xSpline;vtkNew<vtkKochanekSpline> ySpline;vtkNew<vtkKochanekSpline> zSpline;vtkNew<vtkParametricSpline> spline;spline->SetXSpline(xSpline);spline->SetYSpline(ySpline);spline->SetZSpline(zSpline);spline->SetPoints(points);vtkNew<vtkParametricFunctionSource> functionSource;functionSource->SetParametricFunction(spline);functionSource->SetUResolution(50 * numberOfPoints);functionSource->SetVResolution(50 * numberOfPoints);functionSource->SetWResolution(50 * numberOfPoints);functionSource->Update();// Setup actor and mappervtkNew<vtkPolyDataMapper> mapper;mapper->SetInputConnection(functionSource->GetOutputPort());vtkNew<vtkActor> actor;actor->SetMapper(mapper);actor->GetProperty()->SetColor(colors->GetColor3d("DarkSlateGrey").GetData());actor->GetProperty()->SetLineWidth(3.0);// Glyph the pointsvtkNew<vtkSphereSource> sphere;sphere->SetPhiResolution(21);sphere->SetThetaResolution(21);sphere->SetRadius(.02);// Create a polydata to store everything invtkNew<vtkPolyData> polyData;polyData->SetPoints(points);vtkNew<vtkGlyph3DMapper> pointMapper;pointMapper->SetInputData(polyData);pointMapper->SetSourceConnection(sphere->GetOutputPort());vtkNew<vtkActor> pointActor;pointActor->SetMapper(pointMapper);pointActor->GetProperty()->SetColor(colors->GetColor3d("Peacock").GetData());// Setup render window, renderer, and interactorvtkNew<vtkRenderer> renderer;vtkNew<vtkRenderWindow> renderWindow;renderWindow->AddRenderer(renderer);renderWindow->SetWindowName("KochanekSpline");vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;renderWindowInteractor->SetRenderWindow(renderWindow);renderer->AddActor(actor);renderer->AddActor(pointActor);renderer->SetBackground(colors->GetColor3d("Silver").GetData());renderWindow->Render();renderWindowInteractor->Start();return 0;
}

vtkSCurveSpline

vtkSCurveSpline 使用曲线基计算插值样条曲线。使用方法同vtkKochanekSpline;

示例

1.生成8条线段;

 float x[8][3] = {{0,0,0},{1,0,0},{1,1,0},{0,1,0},{0,0,1},{1,0,1},{1,1,1},{0,1,1}};vtkNew<vtkPolyData> geometry;vtkNew<vtkPoints> points;for (size_t i = 0; i < 8; i++)   {points->InsertPoint(i, x[i]);}vtkNew<vtkCellArray> polys;polys->InsertNextCell(8);for (size_t i = 0; i < 8; i++) {       polys->InsertCellPoint(i);}geometry->SetPoints(points);geometry->SetLines(polys);vtkNew<vtkPolyDataMapper> geometryMapper;geometryMapper->SetInputData(geometry);vtkNew<vtkActor> geometryActor;geometryActor->SetMapper(geometryMapper);vtkNew<vtkRenderer> renderer;renderer->AddActor(geometryActor);renderer->ResetCamera();renderer->SetBackground(0, 0, 0);vtkNew<vtkRenderWindow> renWin;renWin->AddRenderer(renderer);renWin->SetSize(300, 300);vtkNew<vtkRenderWindowInteractor> iren;iren->SetRenderWindow(renWin);renWin->Render();iren->Start();


2.使用样条插值后

 float x[8][3] = {{0,0,0},{1,0,0},{1,1,0},{0,1,0},{0,0,1},{1,0,1},{1,1,1},{0,1,1}};vtkNew<vtkPolyData> geometry;vtkNew<vtkPoints> points;for (size_t i = 0; i < 8; i++)   {points->InsertPoint(i, x[i]);}vtkNew<vtkCellArray> polys;polys->InsertNextCell(8);for (size_t i = 0; i < 8; i++) {       polys->InsertCellPoint(i);}geometry->SetPoints(points);geometry->SetLines(polys);vtkNew<vtkCardinalSpline> spline;spline->SetLeftConstraint(2);spline->SetLeftValue(0.0);spline->SetRightConstraint(2);spline->SetRightValue(0.0);vtkNew<vtkSplineFilter> filter;filter->SetInputData(geometry);filter->SetNumberOfSubdivisions(100);filter->SetSpline(spline);filter->Update();vtkNew<vtkPolyDataMapper> geometryMapper;geometryMapper->SetInputData(filter->GetOutput());vtkNew<vtkActor> geometryActor;geometryActor->SetMapper(geometryMapper);vtkNew<vtkRenderer> renderer;renderer->AddActor(geometryActor);renderer->ResetCamera();renderer->SetBackground(0, 0, 0);vtkNew<vtkRenderWindow> renWin;renWin->AddRenderer(renderer);renWin->SetSize(300, 300);vtkNew<vtkRenderWindowInteractor> iren;iren->SetRenderWindow(renWin);renWin->Render();iren->Start();

参考文献

1.vtkSpline
2.vtkCardinalSpline
3.vtkKochanekSpline
4.vtkSCurveSpline

VTK笔记-图形相关-线段平滑-vtkSplineFilter类相关推荐

  1. VTK笔记-图形相关-圆锥体-vtkConeSoure类

    圆锥体 文章目录 圆锥体 前言 一.代码 1.1流程 二.遇到的问题 1.运行时异常 2.在ThinkPad E530C笔记本上出现的异常 3.运行结果 三.相机旋转 四.vtkConeSource ...

  2. VTK笔记-图形相关-多边形数据转换图像数据-vtkPolyData转换为vtkImageData

      VTK中vtkImageData类和vtkPolyData类使用频率极高,vtkImageData类和vtkPolyData类派生自vtkDataSet类,是数据集的一种.   vtkPolyDa ...

  3. VTK笔记-图像相关-vtkImageViewer2类

    vtkImageViewer2   vtkImageViewer2类用来显示二维图像:vtk的版本更新,使用vtkImageViewer2替代vtkImageViewer类:   vtkImageVi ...

  4. VTK笔记-CT图像获取皮肤等值面-vtkContourFilter类的使用

    文章目录 vtkContourFilter SetValue GenerateValues SetValue与GenerateValues的区别与联系 实例 代码 各个对象的关系图 运行效果 引用 本 ...

  5. qml学习笔记(二):可视化元素基类Item详解(上半场anchors等等)

    原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7851 ...

  6. Java快速入门学习笔记7 | Java语言中的类与对象

    有人相爱,有人夜里开车看海,有人却连LeetCode第一题都解不出来!虽然之前系统地学习过java课程,但是到现在一年多没有碰过Java的代码,遇到LeetCode不知是喜是悲,思来想去,然后清空自己 ...

  7. C++学习笔记-第4单元-对象和类(基础)

    C++学习笔记 文章目录 C++学习笔记 第4单元 对象和类(基础) 单元导读 4.1 用类创建对象 4.1.1 对象和类 4.1.2 创建对象并访问 4.2 对象拷贝.分离声明与实现 4.2.1 对 ...

  8. Dubins曲线学习笔记及相关思考

       本篇博客主要记录在学习Dubins曲线过程中的笔记及相关思考和概括总结 一.主要参考资料      1.Andy G's Blog:[点击此处跳转]      2.Andy G's Blog的P ...

  9. 数据结构专题-学习笔记:李超线段树

    数据结构专题 - 学习笔记:李超线段树 1. 前言 2. 详解 3. 应用 4. 总结 5. 参考资料 1. 前言 本篇博文是博主学习李超线段树的学习笔记. 2020/12/21 的时候我在 线段树算 ...

最新文章

  1. 计算机应用基础 pdf 陈建军教案,温州市第二职业中等专业学校(温五中) 教学资源 温州市《计算机应用基础》学业水平测试考纲(转发)...
  2. release8_如何在Windows 8 Release Preview中将Chrome用作Metro浏览器
  3. 认识JSON补丁:JSON-P 1.1概述系列
  4. python含多个附件的邮件_Python发送带有多个图像附件的电子邮件
  5. 修改oracle rac sid,修改Oracle RAC的_asm_hbeatiowait的方法
  6. 月薪10000在中国是什么水平?
  7. java 函数式编程 示例_Java套接字编程–套接字服务器,客户端示例
  8. 查看Linux是Redhat 还是centos 还是...
  9. python时间戳格式定义_关于Python时间戳是什么讲解
  10. 根据 ”艾宾浩斯遗忘曲线“复习时间点生成的复习计划模板
  11. 根据出库、入库表,实现对库存的信息查询
  12. uniapp获取本机ip地址
  13. HTML如何把输入框变成必填值,required输入框为必填项
  14. 【算法】生成n个互异随机数的初步算法
  15. Intel汇编指令在线手册
  16. 目标跟踪技术及其数据集
  17. 山石网科面经(附参考回答)
  18. 极简主义、人工智能与Readhub的产品哲学
  19. 【渝粤教育】21秋期末考试建筑工程计量与计价10517k1
  20. PS缩小图层兼如何使用蒙版

热门文章

  1. 公司企业邮箱怎么群发邮件?如何在工作中脱颖而出
  2. JQuery字符串文本替换并且加样式
  3. 结合锚点利用滚动条监听跳转
  4. IIS 配置问题解决
  5. python线程wait_Python线程指南
  6. html css 边框不显示,css怎么设置不显示下边框?
  7. 给编程一个你热爱它的机会
  8. python2.7常用的标准库
  9. 例7.6有5个学生坐在一起,问第5个学生多少岁,他说比第4个学生大2岁。
  10. 神经网络四:Softmax以及与Sigmoid的关系