【VTK】create spline points

定義5個點

在這裏插入圖片描述

    double p[5][3] = { {0.0, 4.0, 0.0},
                       {2.0, 0.0, 0.0},
                       {4.0, 2.0, 0.0},
                       {6.0, 0.0, 0.0},
                       {8.0, 4.0, 0.0} };

定義500個插值點

在這裏插入圖片描述

示例代碼:

    double p[5][3] = { {0.0, 4.0, 0.0},
                       {2.0, 0.0, 0.0},
                       {4.0, 2.0, 0.0},
                       {6.0, 0.0, 0.0},
                       {8.0, 4.0, 0.0} };

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

    vtkSmartPointer<vtkParametricSpline> spline =
        vtkSmartPointer<vtkParametricSpline>::New();
    spline->SetPoints(points);

    vtkSmartPointer<vtkPoints> betaPoints = vtkSmartPointer<vtkPoints>::New();
    int index = 0;
    int countOfDeltaPoints = 500;
    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 );
    }

使用vtkParametricFunctionSource的polyData,不用開發者自己來create points:

在這裏插入圖片描述

示例代碼:

#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[5][3] = { {0.0, 4.0, 0.0},
                       {2.0, 0.0, 0.0},
                       {4.0, 2.0, 0.0},
                       {6.0, 0.0, 0.0},
                       {8.0, 4.0, 0.0} };

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

    vtkSmartPointer<vtkParametricSpline> spline =
        vtkSmartPointer<vtkParametricSpline>::New();
    spline->SetPoints(points);

/*
 * we can use this way to create some delta points on line.
 *
    vtkSmartPointer<vtkPoints> betaPoints = vtkSmartPointer<vtkPoints>::New();
    int index = 0;
    int countOfDeltaPoints = 500;
    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 );
    }

    spline->SetPoints( betaPoints );

*/
    vtkSmartPointer<vtkParametricFunctionSource> functionSource =
        vtkSmartPointer<vtkParametricFunctionSource>::New();
    functionSource->SetParametricFunction(spline);
    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.01, 0.01, 0.01 );

        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;
}

現在,再創建一條線,使得兩條線封閉。
接着,嘗試將這些points作爲平面的邊線點,創造一個cell將points串起來,畫出一個面。
這樣沿着曲線畫平面有一個問題:
曲面並不會100%的沿着邊界點生成。
如下圖:

在這裏插入圖片描述

在這裏插入圖片描述

實現代碼:
#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 <vtkPolyDataNormals.h>
#include <vtkPointData.h>
#include <vtkFloatArray.h>

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

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

    double p[5][3] = { {0.0, 4.0, 0.0},
                       {2.0, 0.0, 0.0},
                       {4.0, 2.0, 0.0},
                       {6.0, 0.0, 0.0},
                       {8.0, 4.0, 0.0} };

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

    double p2[5][3] = { {0.0, 4.0, 0.0},
                       {2.0, 4.0, 0.0},
                       {4.0, 4.0, 0.0},
                       {6.0, 4.0, 0.0},
                       {8.0, 4.0, 0.0} };
    for( int i = 0; i < 5; ++i )
    {
        points->InsertNextPoint( p2[4 - i] );
    }

/*
 * we can use this way to create some delta points on line.
 *
    vtkSmartPointer<vtkPoints> betaPoints = vtkSmartPointer<vtkPoints>::New();
    int index = 0;
    int countOfDeltaPoints = 500;
    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 );
    }

    spline->SetPoints( betaPoints );

*/
    vtkSmartPointer<vtkParametricFunctionSource> functionSource =
        vtkSmartPointer<vtkParametricFunctionSource>::New();
    functionSource->SetParametricFunction(spline);
    functionSource->SetUResolution( 60 );   // generate 61 points.
    functionSource->GenerateNormalsOn();
    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.01, 0.01, 0.01 );

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

    // create cell to form plane
    vtkSmartPointer<vtkCellArray> poly = vtkSmartPointer<vtkCellArray>::New();
    const int length = splinePoints->GetNumberOfPoints();
    vtkIdType pts[ length ];
    for( int i = 0; i < length; ++i )
    {
        pts[i] = i;
    }
    poly->InsertNextCell( length, pts );

    vtkSmartPointer<vtkPolyData> planePd = vtkSmartPointer<vtkPolyData>::New();
    planePd->SetPoints( splinePoints );
    planePd->SetPolys( poly );
    vtkSmartPointer<vtkPolyDataMapper> planeMapper =
            vtkSmartPointer<vtkPolyDataMapper>::New();
    planeMapper->SetInputData( planePd );

    vtkSmartPointer<vtkActor> planeActor =
            vtkSmartPointer<vtkActor>::New();
    planeActor->SetMapper( planeMapper );

    renderer->AddActor( planeActor );

    renderer->SetBackground(colors->GetColor3d("Silver").GetData());
    renderWindow->Render();
    renderWindowInteractor->Start();

    return EXIT_SUCCESS;
}

想要精確地畫出曲面,可以使用微積分模型,利用這些邊界點畫出一個個小的四邊形作爲不同的cell,然後將這些不同的cell插入到vtkCellArray中。最後再構造vtkPolyData,mapper,actor等。

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章