当前位置:   article > 正文

VTK的Spline样条对比——vtkSCurveSpline、vtkKochanekSpline、vtkCardinalSpline和vtkParametricSpline

vtkcardinalspline

对比VTK中的不同Spline样条


Spline样条作用:

VTK中的Spline样条可以将顶点连接成平滑的线段,并且对线段重新采样。目前主要有vtkSCurveSpline、vtkKochanekSpline、vtkCardinalSpline和vtkParametricSpline四种Spline可以用,后文将对比这四种Spline的效果。


输入的点集

后文的示例都是用同样的四个单独顶点来完成,顶点的顺序可以更改,而Spline是严格根据点集中顶点的顺序来完成连接的,所以调换顶点顺序可以更改Spline的模样。

//定义点集
vtkPoints* ps = vtkPoints::New();
double a[3] = { 0,0,0 };    //插入顶点a
ps->InsertNextPoint(a);
double b[3] = { 1,0,0 };    //插入顶点b
ps->InsertNextPoint(b);
double c[3] = { 1,1,0 };    //插入顶点c
ps->InsertNextPoint(c);
double d[3] = { 0,1,0 };    //插入顶点d
ps->InsertNextPoint(d);
//将顶点插入到vtkPolyData中,没有定义拓扑
vtkNew<vtkPolyData> pointData;
pointData->SetPoints(ps);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

vtkKochanekSpline:根据点集的顺序就能连接得到平滑曲线

//代码参考官方示例
vtkNew<vtkKochanekSpline> xSpline;
vtkNew<vtkKochanekSpline> ySpline;
vtkNew<vtkKochanekSpline> zSpline;

vtkNew<vtkParametricSpline> spline;
spline->SetXSpline(xSpline);
spline->SetYSpline(ySpline);
spline->SetZSpline(zSpline);
spline->SetPoints(ps);

vtkParametricFunctionSource* functionSource = vtkParametricFunctionSource::New();
functionSource->SetParametricFunction(spline);
functionSource->SetUResolution(50 * ps->GetNumberOfPoints());
functionSource->SetVResolution(50 * ps->GetNumberOfPoints());
functionSource->SetWResolution(50 * ps->GetNumberOfPoints());
functionSource->Update();
vtkPolyData* out = functionSource->GetOutput();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

在这里插入图片描述
在这里插入图片描述

vtkKochanekSpline生成的曲线弯曲幅度会相对小一点。


vtkCardinalSpline

vtkSmartPointer<vtkCardinalSpline> xSpline = 
		 vtkSmartPointer<vtkCardinalSpline>::New();
vtkSmartPointer<vtkCardinalSpline> ySpline =
		 vtkSmartPointer<vtkCardinalSpline>::New();
vtkSmartPointer<vtkCardinalSpline> zSpline = 
		 vtkSmartPointer<vtkCardinalSpline>::New();

vtkSmartPointer<vtkParametricSpline> spline =
    vtkSmartPointer<vtkParametricSpline>::New();
spline->SetXSpline(xSpline);
spline->SetYSpline(ySpline);
spline->SetZSpline(zSpline);
spline->SetPoints(ps);

vtkParametricFunctionSource* functionSource =
    	 vtkParametricFunctionSource::New();
functionSource->SetParametricFunction(spline);
functionSource->SetUResolution(50 * ps->GetNumberOfPoints());
functionSource->SetVResolution(50 * ps->GetNumberOfPoints());
functionSource->SetWResolution(50 * ps->GetNumberOfPoints());
functionSource->Update();
vtkPolyData* out = functionSource->GetOutput();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

在这里插入图片描述
在这里插入图片描述
vtkCardinalSpline生成曲线的弯曲幅度会相对更大一点。


vtkParametricSpline:更简单的构建曲线

vtkNew<vtkParametricSpline> spline;
spline->SetPoints(ps);

vtkParametricFunctionSource* functionSource = 
			vtkParametricFunctionSource::New();
functionSource->SetParametricFunction(spline);
functionSource->SetUResolution(50 * ps->GetNumberOfPoints());
functionSource->SetVResolution(50 * ps->GetNumberOfPoints());
functionSource->SetWResolution(50 * ps->GetNumberOfPoints());
functionSource->Update();
vtkPolyData* out = functionSource->GetOutput();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在这里插入图片描述

在这里插入图片描述
vtkParametricSpline生成曲线的效果目前看来和vtkCardinalSpline类似,实际上vtkParametricSpline默认使用的就是vtkCardinalSpline方法


vtkSCurveSpline:直接就是用直线相连

  vtkNew<vtkSCurveSpline> xSpline;
  vtkNew<vtkSCurveSpline> ySpline;
  vtkNew<vtkSCurveSpline> zSpline;

  vtkNew<vtkParametricSpline> spline;
  spline->SetXSpline(xSpline);
  spline->SetYSpline(ySpline);
  spline->SetZSpline(zSpline);
  spline->SetPoints(ps);

  vtkParametricFunctionSource* functionSource = 
  			vtkParametricFunctionSource::New();
  functionSource->SetParametricFunction(spline);
  functionSource->Update();
  vtkPolyData* out = functionSource->GetOutput();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在这里插入图片描述

在这里插入图片描述
如果需要用直线连接点集合的话,vtkSCurveSpline很合适。


注意点

如果你的顶点数量很大的话,要用以上Filter连接顶点前,注意要先对顶点排序,目前VTK还没有能直接用来对顶点集合排序的函数,因此基本需要自行实现。


vtkFrenetSerretFrame 弗莱纳框架

这个函数要使用的话需要额外的第三方依赖:

//在编译VTK时的CMakeList文件中或者CMAKE界面中设置
 ''Module_SplineDrivenImageSlicer:BOOL=ON'' or 
 ''VTK_MODULE_ENABLE_VTK_SplineDrivenImageSlicer:STRING=WANT''
  • 1
  • 2
  • 3

主要作用:能够输入一组线段(例如上文代码段中的数据输出out),然后经过该Filter的处理,能够得到该线段在各顶点处的法向量和切向量属性数据。

 // Create the frame
 vtkNew<vtkFrenetSerretFrame> frame;
 //functionSource为上文代码段中的生成曲线的结果
 frame->SetInputConnection(functionSource->GetOutputPort()); 
 frame->ConsistentNormalsOn();
 frame->Update();

 vtkNew<vtkGlyph3D> glyph3DNormals;
 vtkNew<vtkGlyph3D> glyph3DTangents;
 vtkNew<vtkGlyph3D> glyph3DBinormals;

 // for each vector, create a Glyph3D and DeepCopy the output
 double radius = 0.05;
 frame->GetOutput()->GetPointData()->SetActiveVectors("FSNormals");
 MakeGlyphs(frame->GetOutput(), radius, glyph3DNormals.GetPointer());
 vtkNew<vtkPolyData> normalsPolyData;
 normalsPolyData->DeepCopy(glyph3DNormals->GetOutput());

 frame->GetOutput()->GetPointData()->SetActiveVectors("FSTangents");
 MakeGlyphs(frame->GetOutput(), radius, glyph3DTangents.GetPointer());
 vtkNew<vtkPolyData> tangentsPolyData;
 tangentsPolyData->DeepCopy(glyph3DTangents->GetOutput());

 frame->GetOutput()->GetPointData()->SetActiveVectors("FSBinormals");
 MakeGlyphs(frame->GetOutput(), radius, glyph3DBinormals.GetPointer());
 vtkNew<vtkPolyData> binormalsPolyData;
 binormalsPolyData->DeepCopy(glyph3DBinormals->GetOutput());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

将各属性渲染出来如下图所示:
在这里插入图片描述
示例链接

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/128791
推荐阅读
相关标签
  

闽ICP备14008679号