1. 程式人生 > >【VTK】使用vtkActor2D新增polyline

【VTK】使用vtkActor2D新增polyline

具體實現如下:

#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkLight.h>
#include <vtkCamera.h>
#include <vtkPolyDataMapper2D.h>
#include <vtkActor2D.h>
#include <vtkProperty2D.h>

using namespace std;

int main()
{
    vtkSmartPointer<vtkConeSource> cone =
            vtkSmartPointer<vtkConeSource>::New();

    vtkSmartPointer<vtkPolyDataMapper> mapper =
            vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection( cone->GetOutputPort() );

    vtkSmartPointer<vtkActor> actor =
            vtkSmartPointer<vtkActor>::New();
    actor->SetMapper( mapper );

    vtkSmartPointer<vtkRenderer> renderer =
            vtkSmartPointer<vtkRenderer>::New();
    renderer->AddActor(actor);
    renderer->SetBackground( 0, 0, 0 );

    vtkSmartPointer<vtkRenderWindow> renderWindow =
            vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->AddRenderer( renderer );

    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
            vtkSmartPointer<vtkRenderWindowInteractor>::New();
    renderWindowInteractor->SetRenderWindow( renderWindow );

    // ------------- start to add red line ----------------
    vtkSmartPointer<vtkPolyDataMapper2D> v1mmMapper = vtkSmartPointer<vtkPolyDataMapper2D>::New();
    vtkSmartPointer<vtkPolyData> v1mmPolyData = vtkSmartPointer<vtkPolyData>::New();
    vtkSmartPointer<vtkCellArray> v1mmLines = vtkSmartPointer<vtkCellArray>::New();
    vtkSmartPointer<vtkPoints> v1mmPoints = vtkSmartPointer<vtkPoints>::New();

    v1mmPolyData->SetPoints( v1mmPoints );
    v1mmPolyData->SetLines( v1mmLines );
    v1mmMapper->SetInputData( v1mmPolyData );

    vtkSmartPointer<vtkActor2D> v1mmLinesActor = vtkSmartPointer<vtkActor2D>::New();
    v1mmLinesActor->SetMapper( v1mmMapper );
    v1mmLinesActor->GetProperty()->SetColor( 1, 0, 0 );
    v1mmLinesActor->GetProperty()->SetLineWidth( 1 );

    vtkSmartPointer<vtkCoordinate> normCoords = vtkSmartPointer<vtkCoordinate>::New();
    normCoords->SetCoordinateSystemToView();
    v1mmMapper->SetTransformCoordinate( normCoords );

    // just for test
    vtkCoordinate *cd = v1mmMapper->GetTransformCoordinate();
    assert( nullptr != cd );
    printf( "GetCoordinateSystemAsString: %s\n", cd->GetCoordinateSystemAsString() );

    double linePoint1[3] = { 0, -1, 0.0 };
    double linePoint2[3] = { 0, 1, 0.0 };
    vtkIdType pointId1 = v1mmPoints->InsertNextPoint(linePoint1);
    vtkIdType pointId2 = v1mmPoints->InsertNextPoint(linePoint2);
    vtkIdType lineIds[2] = { pointId1, pointId2 };
    v1mmLines->InsertNextCell(2, lineIds);

    linePoint1[0] = -1; linePoint1[1] = 0; linePoint1[2] = 0;
    linePoint2[0] = 1; linePoint2[1] = 0; linePoint2[2] = 0;
    lineIds[0] = v1mmPoints->InsertNextPoint(linePoint1);
    lineIds[1] = v1mmPoints->InsertNextPoint(linePoint2);
    v1mmLines->InsertNextCell(2, lineIds);
    v1mmPolyData->Modified();
    // ------------- adding red line finished----------------

    renderer->ResetCamera();

    renderer->AddActor2D( v1mmLinesActor );

    renderWindow->Render();
    renderWindowInteractor->Start();
    return 0;
}

我們也可以使用viewport座標系來繪圖。 改動的程式碼只有vtkCoordinate的座標系統設定以及線段兩端點的位置設定。 因為view的座標範圍是[0,1],而viewport的座標對應著畫素值,所以我們需要使用renderWindow->GetSize();獲取窗體的畫素尺寸。

    vtkSmartPointer<vtkCoordinate> normCoords = vtkSmartPointer<vtkCoordinate>::New();
    normCoords->SetCoordinateSystemToViewport();
    v1mmMapper->SetTransformCoordinate( normCoords );

    // just for test
    vtkCoordinate *cd = v1mmMapper->GetTransformCoordinate();
    assert( nullptr != cd );
    printf( "GetCoordinateSystemAsString: %s\n", cd->GetCoordinateSystemAsString() );

    renderWindow->Render(); //after render, window's size is not (0, 0) any more.

    int *size = renderWindow->GetSize();
    printf( "size: %d, %d\n", size[0], size[1] );

    // viewport origin point is at left-bottom corner.
    double linePoint1[3] = { size[0]/2.0, 0, 0.0 };
    double linePoint2[3] = { size[0]/2.0, size[1] * 1.0, 0.0 };

    vtkIdType pointId1 = v1mmPoints->InsertNextPoint(linePoint1);
    vtkIdType pointId2 = v1mmPoints->InsertNextPoint(linePoint2);
    vtkIdType lineIds[2] = { pointId1, pointId2 };
    v1mmLines->InsertNextCell(2, lineIds);

    linePoint1[0] = 0; linePoint1[1] = size[1] / 2; linePoint1[2] = 0;
    linePoint2[0] = size[0]; linePoint2[1] = size[1] / 2; linePoint2[2] = 0;
    lineIds[0] = v1mmPoints->InsertNextPoint(linePoint1);
    lineIds[1] = v1mmPoints->InsertNextPoint(linePoint2);
    v1mmLines->InsertNextCell(2, lineIds);
    v1mmPolyData->Modified();
    // ------------- adding red line finished----------------

顯示結果和view系統一樣。 圖略。 在放大窗體後,view座標裡面的紅線仍然佈滿整個窗體,但是viewport裡的紅線因為最初設定的寸尺比改變後的窗體寸尺小,所以就會有這樣的放大效果:

如果不為render設定viewport,viewport和display的效果是一樣的

    //normCoords->SetCoordinateSystemToViewport();
    normCoords->SetCoordinateSystemToDisplay();

但是,我們如果設定了viewport,那麼差異就出現了: 在新增red line的程式碼塊之前寫上如下程式碼

    renderer->SetViewport( 0.0, 0.0, 0.5, 1.0 );

效果: