我们创建三个点:

    double p[3][3] = { {0.0, 0.0, 0.0},
                       {2.0, 4.0, 0.0},
                       {20.0, 0.0, 0.0} };

在平面上,他们大致的分布是这样的:




很多情况下,我们希望利用spline得到picture2的插值结果。



但是,如果使用vtkParametricSpline搭配vtkParametricFunctionSource产生3个点,画出来的场景是这样的:



这对应着picture 1。
但,如果想要得到picture 2的插值呢?
vtkParametricFunctionSource是支持非均匀样条插值的,只要我们设置足够的点数即可。
比如设置10个点


#include <vtkSmartPointer.h>
#include <vtkParametricFunctionSource.h>
#include <vtkParametricSpline.h>

#include <vtkCellArray.h>
#include <vtkCellData.h>
#include <vtkDoubleArray.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkProperty.h>

#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkTransform.h>

#include <vtkSphereSource.h>
#include <vtkNamedColors.h>
#include <vtkTextSource.h>
#include <vtkCoordinate.h>
#include <vtkPolyDataMapper2D.h>
#include <vtkActor2D.h>

#include <QString>
#include <iostream>
using namespace std;

int main(int, char *[])
{
    vtkSmartPointer<vtkNamedColors> colors =
            vtkSmartPointer<vtkNamedColors>::New();

    double p[3][3] = { {0.0, 0.0, 0.0},
                       {2.0, 4.0, 0.0},
                       {20.0, 0.0, 0.0} };

    vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
    for( int i = 0; i < 3; ++i )
    {
        points->InsertNextPoint( p[i] );
    }

    vtkSmartPointer<vtkParametricSpline> spline =
        vtkSmartPointer<vtkParametricSpline>::New();
    spline->SetPoints(points);
    vtkSmartPointer<vtkParametricFunctionSource> functionSource =
        vtkSmartPointer<vtkParametricFunctionSource>::New();
    functionSource->SetParametricFunction(spline);
    functionSource->SetUResolution( 10 - 1 );
    functionSource->Update();

    vtkPolyData* polyData = functionSource->GetOutput();
    vtkPoints* splinePoints = polyData->GetPoints();

    // Setup actor and mapper
    vtkSmartPointer<vtkPolyDataMapper> mapper =
        vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection(functionSource->GetOutputPort());

    vtkSmartPointer<vtkActor> actor =
        vtkSmartPointer<vtkActor>::New();
    actor->SetMapper(mapper);
    actor->GetProperty()->SetColor( 1, 0, 0 );
    actor->GetProperty()->SetLineWidth(3.0);

    // Setup render window, renderer, and interactor
    vtkSmartPointer<vtkRenderer> renderer =
        vtkSmartPointer<vtkRenderer>::New();
    vtkSmartPointer<vtkRenderWindow> renderWindow =
        vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->AddRenderer(renderer);
    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
        vtkSmartPointer<vtkRenderWindowInteractor>::New();
    renderWindowInteractor->SetRenderWindow(renderWindow);
    renderer->AddActor(actor);

    printf( "the count of spline points is %d\n", splinePoints->GetNumberOfPoints() );
    for( int i = 0; i < splinePoints->GetNumberOfPoints(); ++i )
    {
        vtkSmartPointer<vtkSphereSource> sphere = vtkSmartPointer<vtkSphereSource>::New();
        sphere->SetRadius( 0.1 );

        vtkSmartPointer<vtkPolyDataMapper> sphereMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
        sphereMapper->SetInputConnection( sphere->GetOutputPort() );

        vtkSmartPointer<vtkActor> sphereActor = vtkSmartPointer<vtkActor>::New();
        sphereActor->SetMapper( sphereMapper );
        sphereActor->GetProperty()->SetColor( 0, 0, 1 );
        sphereActor->VisibilityOn();

        sphereActor->SetPosition( splinePoints->GetPoint(i) );
        renderer->AddActor( sphereActor );

        // text 2D
        vtkSmartPointer<vtkTextSource> text2D =
                vtkSmartPointer<vtkTextSource>::New();
        text2D->SetText( QString::number( i+1 ).toStdString().c_str() );

        vtkSmartPointer<vtkTransform> text2DTransform =
                vtkSmartPointer<vtkTransform>::New();
        double *center = sphereActor->GetCenter();
        text2DTransform->Translate( center[0], center[1] + 0.1, center[2] );
        text2DTransform->Scale( 0.1, 0.1, 0.1 );

        vtkSmartPointer<vtkTransformPolyDataFilter> text2DDataFilter =
                vtkSmartPointer<vtkTransformPolyDataFilter>::New();
        text2DDataFilter->SetTransform( text2DTransform );
        text2DDataFilter->SetInputConnection( text2D->GetOutputPort() );

        vtkSmartPointer<vtkCoordinate> coords =
                vtkSmartPointer<vtkCoordinate>::New();
        coords->SetCoordinateSystemToWorld();

        vtkSmartPointer<vtkPolyDataMapper2D> text2DMapper =
                vtkSmartPointer<vtkPolyDataMapper2D>::New();
        text2DMapper->SetInputConnection( text2DDataFilter->GetOutputPort() );
        text2DMapper->SetTransformCoordinate( coords );

        vtkSmartPointer<vtkActor2D> text2DActor =
                vtkSmartPointer<vtkActor2D>::New();
        text2DActor->SetMapper( text2DMapper );

        renderer->AddActor( text2DActor );
    }

    renderer->SetBackground(colors->GetColor3d("Silver").GetData());

    renderWindow->Render();
    renderWindowInteractor->Start();

    return EXIT_SUCCESS;
}

点设置的越多,插值效果越好




同样地,使用Evaluate分step计算,也能得到类似的插值效果。
如下:

    vtkSmartPointer<vtkPoints> betaPoints = vtkSmartPointer<vtkPoints>::New();
    int index = 0;
    int countOfDeltaPoints = 20;
    double step = 1.0 / ( countOfDeltaPoints - 1 );
    for( double i = 0; i <= 1; i = i + step )
    {
        double tmp[3] = { i, 0, 0 };
        spline->Evaluate( tmp, tmp, NULL );
        betaPoints->InsertPoint( index++, tmp );
    }

    vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New();
    for( int i = 0; i < index-1; ++i )
    {
        vtkIdType pts[2] = { i, i+1 };
        lines->InsertNextCell(2, pts );
    }

    vtkSmartPointer<vtkPolyData> pd = vtkSmartPointer<vtkPolyData>::New();
    pd->SetPoints( betaPoints );
    pd->SetLines( lines );

    vtkSmartPointer<vtkPolyDataMapper> mapper =
        vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputData( pd );

分类: C plus plus

发表评论

电子邮件地址不会被公开。 必填项已用*标注