Draw The Plane Manually

We can create a big plane if we know its origin and normal. The algorithm class vtkPlaneSource is a solution for it, but the generated plane is too small, it’s hard to create a big plane based on vtkPlaneSource, so I wrote a function for the question.
The project is uploaded to GitHub: bigPlane

#include <vtkImageData.h>
#include <vtkImageCast.h>
#include <vtkSmartPointer.h>
#include <vtkImageMapper3D.h>
#include <vtkImageFlip.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkRenderer.h>
#include <vtkImageMandelbrotSource.h>
#include <vtkImageActor.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkPNGReader.h>
#include <vtkPNGWriter.h>
#include <vtkPlaneSource.h>
#include <vtkAxesActor.h>
#include <vtkAppendPolyData.h>

#include "tool.h"

/*
*   We can guess a point by plane equation, then use it and center, normal to 
*   calculate another two points on plane.
*   The interface is used to calculate four small squares to form a big plane
*   which center and normal are same as parameters.
*/
vtkSmartPointer<vtkPolyData> GetBigPlane(const PointStruct _center,
                                         const PointStruct _normal,
                                         const double lengthOfHalfDiagonal,
                                         const PointStruct guessPoint)
{
    vtkSmartPointer<vtkAppendPolyData> appendFilter =
            vtkSmartPointer<vtkAppendPolyData>::New();

    // a(x - x0) + b(y - y0) + c(z - z0) = 0
    vtkSmartPointer<vtkPlaneSource> planeSource0 =
            vtkSmartPointer<vtkPlaneSource>::New();
    //planeSource->SetCenter( center.point );
    //planeSource->SetNormal( normal.point );

    PointStruct center = _center;
    PointStruct normal = _normal;
    // there is at least one point on axes and on plane at the same time
    planeSource0->SetOrigin( center.point );

    // upper square
    PointStruct p1 = guessPoint;
    p1 = (p1 - center).Unit() * lengthOfHalfDiagonal + center;

    PointStruct p2 = ((p1 - center)^normal).Unit() * lengthOfHalfDiagonal + center;
    planeSource0->SetPoint1( p1.point );
    planeSource0->SetPoint2( p2.point );
    planeSource0->Update();

    appendFilter->AddInputData( planeSource0->GetOutput() );

    // left square
    p1 = guessPoint;
    p1 = (p1 - center).Unit() * lengthOfHalfDiagonal + center;
    p2 = ((p1 - center)^normal).Unit() * (-lengthOfHalfDiagonal) + center;
    vtkSmartPointer<vtkPlaneSource> planeSource1 =
            vtkSmartPointer<vtkPlaneSource>::New();
    planeSource1->SetOrigin( center.point );
    planeSource1->SetPoint1( p1.point );
    planeSource1->SetPoint2( p2.point );
    planeSource1->Update();

    appendFilter->AddInputData( planeSource1->GetOutput() );

    // lower square
    p1 = guessPoint;
    p1 = (p1 - center).Unit() * (-lengthOfHalfDiagonal) + center;
    p2 = ((p1 - center)^normal).Unit() * (lengthOfHalfDiagonal) + center;
    vtkSmartPointer<vtkPlaneSource> planeSource2 =
            vtkSmartPointer<vtkPlaneSource>::New();
    planeSource2->SetOrigin( center.point );
    planeSource2->SetPoint1( p1.point );
    planeSource2->SetPoint2( p2.point );
    planeSource2->Update();

    appendFilter->AddInputData( planeSource2->GetOutput() );

    // right square
    p1 = guessPoint;
    p1 = (p1 - center).Unit() * (-lengthOfHalfDiagonal) + center;
    p2 = ((p1 - center)^normal).Unit() * (-lengthOfHalfDiagonal) + center;
    vtkSmartPointer<vtkPlaneSource> planeSource3 =
            vtkSmartPointer<vtkPlaneSource>::New();
    planeSource3->SetOrigin( center.point );
    planeSource3->SetPoint1( p1.point );
    planeSource3->SetPoint2( p2.point );
    planeSource3->Update();

    appendFilter->AddInputData( planeSource3->GetOutput() );

    appendFilter->Update();
    return appendFilter->GetOutput();
}

int main()
{
    PointStruct center( 0, 1, 0 );
    PointStruct normal( 1, 0, 0 );
    PointStruct guessPoint( 0, 2, 1 );

    vtkSmartPointer<vtkPolyDataMapper> planeMapper =
            vtkSmartPointer<vtkPolyDataMapper>::New();

    planeMapper->SetInputData( GetBigPlane( center, normal, 2, guessPoint ) );

    vtkSmartPointer<vtkActor> planeActor =
            vtkSmartPointer<vtkActor>::New();
    planeActor->SetMapper( planeMapper );
    planeActor->GetProperty()->SetColor( 1, 1, 0 );

    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->SetBackground(.1, .2, .3);

    renderer->AddActor(planeActor);

    vtkSmartPointer<vtkAxesActor> axesActor = vtkSmartPointer<vtkAxesActor>::New();
    renderer->AddActor( axesActor );

    renderer->ResetCamera();
    renderWindow->Render();

    renderWindowInteractor->Start();
    return 0;
}

Use vtkPlaneSource

Another way is to use vtkPlaneSource create a plane polydata, make actor scale to form a big plane.
Notice: after scaling, we need to move the actor in the opposite direction.

vtkSmartPointer<vtkPlaneSource> planeSource =
        vtkSmartPointer<vtkPlaneSource>::New();
    planeSource->SetCenter( m_LevelPlane->GetOrigin() );
    planeSource->SetNormal( m_LevelPlane->GetNormal() );
    planeSource->Update();

    vtkSmartPointer<vtkPolyDataMapper> planeMapper =
        vtkSmartPointer<vtkPolyDataMapper>::New();    
    planeMapper->SetInputData( planeSource->GetOutput() );
    planeMapper->Update();

    int scaleAccount = 40;
    vtkSmartPointer<vtkActor> planeActor =
        vtkSmartPointer<vtkActor>::New();    
    planeActor->SetMapper( planeMapper );
    planeActor->SetScale( scaleAccount );
    planeActor->GetProperty()->SetColor( 0, 1, 1 );

    PointStruct originPt( m_LevelPlane->GetOrigin() );
    // move in the opposite direction to keep the same center.
    planeActor->AddPosition( ((-scaleAccount+1) * originPt).point );

    renderer->AddActor( planeActor );

Or use vtkTransform to scale the plane.

    vtkSmartPointer<vtkPlaneSource> planeSource =
        vtkSmartPointer<vtkPlaneSource>::New();
    planeSource->SetCenter( plane->GetOrigin() );
    planeSource->SetNormal( plane->GetNormal() );
    planeSource->Update();

    vtkSmartPointer<vtkPolyDataMapper> planeMapper =
        vtkSmartPointer<vtkPolyDataMapper>::New();    
    planeMapper->SetInputData( planeSource->GetOutput() );
    planeMapper->Update();

    int scaleValue = 40;
    vtkSmartPointer<vtkActor> planeActor =
        vtkSmartPointer<vtkActor>::New();    
    planeActor->SetMapper( planeMapper );
    planeActor->GetProperty()->SetColor( 0, 1, 1 );


    PointStruct originPt( plane->GetOrigin() );
    vSPNew( trans, vtkTransform );
    trans->Translate( originPt.point );
    trans->Scale( scaleValue, scaleValue, scaleValue );
    trans->Translate( (-originPt).point );
    planeActor->SetUserTransform( trans );

    renderer->AddActor( planeActor );
Categories: VTK

0 0 vote
Article Rating
Subscribe
Notify of
guest
1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
trackback

[…] to scale and move position. The details can be found in my previous article’s second part Create A Big Plane By Center And Normal: Use vtkPlaneSource. The other way is to define three important points, the origin, point1, and point2 for the […]

A prohibited operation
1
0
Would love your thoughts, please comment.x
()
x