有时候我们想通过在样条曲线上得到更多的点,比如用这些点来与另一条曲线连通生成三角条,让曲线在可视化的时候分辨率更高,等等,就需要用到曲线插值采用。最常见的是样条曲线插值采样。
曲线已经有了情况下(关于如何生成样条曲线,可参照VTK笔记——插值样条曲线(Parametric Spline)),
接下来要在曲线上取更多的点。
曲线方程
直线,两点就可形成一条直线。通过数学表示的直线方程,可以求得直线上任意一点的坐标。同理,曲线也是如此。
vtk中,vtkParametricSpline包含有曲线方程,
vtkParametricSpline::Evaluate
通常,根据需求的不同,有两种方式
方式一
点的个数n固定,求步长step。
vtkSmartPointer<vtkPoints> outPoints =
vtkSmartPointer<vtkPoints>::New();
int pointsCnt = 11; // n = 11
double step = 1.0 / (pointsCnt - 1);
// Fix bug: the result points n probably not enough
//for (double i = 0; i <= 1; i += step)
//{
// double u[] = {i, 0, 0};
// double p[3];
// spline->Evaluate(u, p, NULL);
// outPoints->InsertNextPoint(p);
//}
for (int i = 0; i < n; i++)
{
double u[3] = { i * step, 0, 0 }, p[3];
spline->Evaluate(u, p, nullptr);
outPoints->InsertNextPoint(p);
}
}
方式二
步长step一定,求点n的个数
#define DIS(p1, p2) (sqrt((p1[0]-p2[0])*(p1[0]-p2[0]) + (p1[1]-p2[1])*(p1[1]-p2[1]) + (p1[2]-p2[2])*(p1[2]-p2[2])))
vtkSmartPointer<vtkPoints> outPoints =
vtkSmartPointer<vtkPoints>::New();
double totalLen = DIS(p0, p1) + DIS(p1, p2);
double start = 0;
double step = .5;
while (start <= totalLen)
{
double u[] = { start/totalLen, 0, 0 };
double p[3];
spline->Evaluate(u, p, NULL);
outPoints->InsertNextPoint(p);
start += step;
}
示例代码
#include <vtkPolyData.h>
#include <vtkSmartPointer.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkParametricSpline.h>
#include <vtkParametricFunctionSource.h>
#include <vtkSphereSource.h>
#include <vtkGlyph3DMapper.h>
int main(int, char *[])
{
double p0[3] = { 1.0, 0.0, 0.0 };
double p1[3] = { 3.0, 2.0, 0.0 };
double p2[3] = { 5.0, 0.0, 0.0 };
vtkSmartPointer<vtkPoints> points =
vtkSmartPointer<vtkPoints>::New();
points->InsertNextPoint(p0);
points->InsertNextPoint(p1);
points->InsertNextPoint(p2);
vtkSmartPointer<vtkParametricSpline> spline =
vtkSmartPointer<vtkParametricSpline>::New();
spline->SetPoints(points);
// Method1
#if (0)
vtkSmartPointer<vtkPoints> outPoints =
vtkSmartPointer<vtkPoints>::New();
int pointsCnt = 11;
double step = 1.0 / (pointsCnt-1);
for (double i = 0; i <= 1; i = i + step)
{
double u[] = {i, 0, 0};
double p[3];
spline->Evaluate(u, p, NULL);
outPoints->InsertNextPoint(p);
}
#else
// Method2
#define DIS(p1, p2) (sqrt((p1[0]-p2[0])*(p1[0]-p2[0]) + (p1[1]-p2[1])*(p1[1]-p2[1]) + (p1[2]-p2[2])*(p1[2]-p2[2])))
vtkSmartPointer<vtkPoints> outPoints =
vtkSmartPointer<vtkPoints>::New();
double totalLen = DIS(p0, p1) + DIS(p1, p2);
double start = 0;
double step = .3;
while (start <= totalLen)
{
double u[] = { start/totalLen, 0, 0 };
double p[3];
spline->Evaluate(u, p, NULL);
outPoints->InsertNextPoint(p);
start += step;
}
#endif
vtkSmartPointer<vtkParametricSpline> outSpline =
vtkSmartPointer<vtkParametricSpline>::New();
outSpline->SetPoints(outPoints);
vtkSmartPointer<vtkParametricFunctionSource> functionSource =
vtkSmartPointer<vtkParametricFunctionSource>::New();
functionSource->SetParametricFunction(outSpline);
functionSource->Update();
vtkSmartPointer<vtkPolyDataMapper> splineMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
splineMapper->SetInputConnection(functionSource->GetOutputPort());
vtkSmartPointer<vtkActor> splineActor =
vtkSmartPointer<vtkActor>::New();
splineActor->SetMapper(splineMapper);
vtkSmartPointer<vtkSphereSource> sphereSource =
vtkSmartPointer<vtkSphereSource>::New();
sphereSource->SetPhiResolution(21);
sphereSource->SetThetaResolution(21);
sphereSource->SetRadius(.05);
vtkSmartPointer<vtkPolyData> splinePointsData =
vtkSmartPointer<vtkPolyData>::New();
splinePointsData->SetPoints(outPoints);
vtkSmartPointer<vtkGlyph3DMapper> splinePointsMapper =
vtkSmartPointer<vtkGlyph3DMapper>::New();
splinePointsMapper->SetInputData(splinePointsData);
splinePointsMapper->SetSourceConnection(sphereSource->GetOutputPort());
vtkSmartPointer<vtkActor> pointsActor =
vtkSmartPointer<vtkActor>::New();
pointsActor->SetMapper(splinePointsMapper);
pointsActor->GetProperty()->SetColor(1, 0, 0);
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->SetSize(600, 600);
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->AddActor(splineActor);
renderer->AddActor(pointsActor);
renderWindow->Render();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
Reference
vtkParametricSpline Class Reference