I want to show png picture by vtkActor2D rather than vtkImageActor or vtkImageViewer. There is not rotating and scaling for the picture when move mouse and click if the vtkActor2D object works. But how to do it?
The following project shows axes and a png picture in the window, the axes indicates there is interaction.
#define vtkSPtr vtkSmartPointer
#define vtkSPtrNew(Var, Type) vtkSPtr<Type> Var = vtkSPtr<Type>::New();
using namespace std;
int main()
{
vtkObject::GlobalWarningDisplayOn();
vtkSPtrNew( reader, vtkPNGReader );
reader->SetFileName( "/Users/weiyang/Desktop/person.png" );
reader->Update();
vtkSPtrNew( imageMapper, vtkImageMapper );
imageMapper->SetInputData( reader->GetOutput() );
imageMapper->Update();
imageMapper->SetDebug( true );
int *extend = reader->GetOutput()->GetExtent();
printf( "extend: (%d, %d, %d, %d , %d, %d)\n", extend[0], extend[1], extend[2], extend[3], extend[4], extend[5] );
imageMapper->GetInputAlgorithm()->UpdateInformation();
double *range = imageMapper->GetInput()->GetScalarRange();
//imageMapper->SetColorWindow( range[1] - range[0] );
//imageMapper->SetColorLevel(0.5 * (range[1] + range[0]));
imageMapper->SetColorWindow( 256 );
imageMapper->SetColorLevel( 128 );
int *ext = imageMapper->GetInputInformation()->Get( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT() );
// if it would be smaller than 150 by 100 then limit to 150 by 100
int xs = ext[1] - ext[0] + 1;
int ys = ext[3] - ext[2] + 1;
int size[2] = { max( xs, 150 ), max( ys, 150 ) };
vtkSPtrNew( actor2D, vtkActor2D );
actor2D->SetMapper( imageMapper );
vtkSPtrNew( renderer, vtkRenderer );
renderer->AddActor2D( actor2D );
renderer->SetBackground( 0, 0, 0 );
vtkSPtrNew( axes, vtkAxesActor );
axes->SetTotalLength( 1, 1, 1 ); // change length of three axis
renderer->AddActor( axes );
vtkSPtrNew( renderWindow, vtkRenderWindow );
renderWindow->AddRenderer( renderer );
vtkSPtrNew( renderWindowInteractor, vtkRenderWindowInteractor );
renderWindowInteractor->SetRenderWindow( renderWindow );
renderWindow->SetSize( size[0], size[1] );
renderer->ResetCamera();
renderWindow->Render();
renderWindowInteractor->Start();
return 0;
}
Header files we need:
#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkPNGReader.h>
#include <vtkImageActor.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkImageMapper3D.h>
#include <vtkAxesActor.h>
#include <vtkImageMapper.h>
#include <vtkImageData.h>
#include <vtkActor2D.h>
#include <vtkImageViewer2.h>
#include <vtkImageViewer.h>
#include <vtkInformation.h>
#include <vtkStreamingDemandDrivenPipeline.h>
CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project(vtkLearn2)
find_package( VTK REQUIRED )
include( ${VTK_USE_FILE} )
add_executable(${PROJECT_NAME} "main.cpp")
target_link_libraries( ${PROJECT_NAME} ${VTK_LIBRARIES} )
We can use vtkPropPicker to capture pick event for 2d actor, and the interface vtkActor2D::SetDisplayPosition
can help us to move the image dynamically.
vtkSPtr<vtkPropPicker> picker;
vtkSPtr<vtkActor2D> actor2D;
class CustomStyle : public vtkInteractorStyleTrackballCamera
{
public:
static CustomStyle *New(){ return new CustomStyle(); }
void OnLeftButtonDown() override
{
vtkRenderWindowInteractor *interactor = this->Interactor;
int *eventPos( interactor->GetEventPosition() );
picker->Pick( eventPos[0], eventPos[1], 0, m_Renderer );
vtkActor2D *__actor2D = picker->GetActor2D();
printf( "actor2D: %p\n", __actor2D );
if( __actor2D == actor2D )
{
printf( "Picked actor2D\n" );
}
vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
}
void setm_Renderer( vtkRenderer *renderer ){ m_Renderer = renderer; }
protected:
vtkRenderer *m_Renderer;
};
int main()
{
// ...
vtkSPtrNew( style, CustomStyle );
style->setm_Renderer( renderer );
renderWindowInteractor->SetInteractorStyle( style );
// ...
}