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

对比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);

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

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

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

在这里插入图片描述
在这里插入图片描述
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();

在这里插入图片描述

在这里插入图片描述
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();

在这里插入图片描述

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


注意点

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


vtkFrenetSerretFrame 弗莱纳框架

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

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

主要作用:能够输入一组线段(例如上文代码段中的数据输出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());

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

  • 0
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值