We often use vtkPropPicker to judge which 2D actor had been picked, but the solution doesn’t work in the Mac software Parallels. So we have to create a new method to found the 2D actor which had been picked.
There are two situations in my problem. The actor2D takes vtkImageMapper object or vtkPolyDataMapper2D object as its mapper. Both situations have different pipelines and different judging ways.
The vtkImageMapper is also a vtkMapper2D class, the size information can be found by WHOLE_EXTENT. Similarly, vtkPolyDataMapper2D had converted the 3D polydata to a 2D pixel image, we have to found the left-bottom point’s display coordinate value and its size. Finally, check whether the event position is in the 2D rectangle.

2D Actor Showing PolyData

#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkTextActor.h>
#include <vtkTextProperty.h>
#include <vtkRenderWindowInteractor.h>
#include <QString>
#include <vtkImageMapper.h>
#include <vtkImageData.h>
#include <vtkPNGReader.h>
#include <vtkInformation.h>
#include <vtkStreamingDemandDrivenPipeline.h>
#include <vtkCubeSource.h>
#include <vtkPolyDataMapper2D.h>
#include <vtkProperty2D.h>

#define vtkSPtr vtkSmartPointer
#define vtkSPtrNew(Var, Type) vtkSPtr<Type> Var = vtkSPtr<Type>::New();

using namespace std;

bool Is2DActorClicked(vtkActor2D *actor, int x, int y)
{
    double bounds[6];
    vtkPolyDataMapper2D *mapper = (vtkPolyDataMapper2D*)(actor->GetMapper());
    vtkPolyData *data = mapper->GetInput();
    data->ComputeBounds();
    data->GetBounds(bounds); // vtkPolyDataMapper2D had convert the 3D polydata to 2D pixel image
    double width = bounds[1] - bounds[0];
    double height = bounds[3] - bounds[2];
    double *pos = actor->GetPosition();
    double displayBounds[4] = { pos[0] - width/2, pos[0] + width/2, pos[1] - height/2, pos[1] + height/2 };

    if (x > displayBounds[0] && x < displayBounds[1] &&
        y > displayBounds[2] && y < displayBounds[3] )
    {
        return true;
    }
    return false;
}

int main()
{
    vtkSPtr<vtkActor2D> actor2D = vtkSPtr<vtkActor2D>::New();

    vtkSPtrNew( upCubeSource, vtkCubeSource );
    upCubeSource->SetBounds( -50, 50, -50, 50, -50, 50 );
    upCubeSource->Update();

    vtkSPtrNew( upCubeMapper, vtkPolyDataMapper2D );
    upCubeMapper->SetInputData( upCubeSource->GetOutput() );
    actor2D->SetMapper( upCubeMapper );
    actor2D->GetProperty()->SetColor( 0, 1, 1);

    vtkSPtrNew( renderer, vtkRenderer );
    renderer->AddActor2D( actor2D );
    renderer->SetBackground( 0, 0, 0 );

    vtkSPtrNew( renderWindow, vtkRenderWindow );
    renderWindow->AddRenderer( renderer );
    renderWindow->SetSize( 800, 400 );

    int *winSize = renderWindow->GetSize();
    int verticalSpace =  20;

    actor2D->SetDisplayPosition( winSize[0] / 2, verticalSpace*3 );

    vtkSPtrNew( renderWindowInteractor, vtkRenderWindowInteractor );
    renderWindowInteractor->SetRenderWindow( renderWindow );

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


2D Actor Showing Image

#define vtkSPtr vtkSmartPointer
#define vtkSPtrNew(Var, Type) vtkSPtr<Type> Var = vtkSPtr<Type>::New();

void Init2DActor()
{
    QString filePath = "test.png";

    vtkSPtrNew( reader, vtkPNGReader );
    reader->SetFileName( filePath.toStdString().c_str() );
    reader->Update();
    vtkSPtrNew( mapper, vtkImageMapper );
    mapper->SetInputData( reader->GetOutput() );
    mapper->Update();
    mapper->GetInputAlgorithm()->UpdateInformation();
    double *range = reader->GetOutput()->GetScalarRange();
    mapper->SetColorWindow( range[1] - range[0] );
    mapper->SetColorLevel(0.5 * (range[1] + range[0]));
    vtkSPtr<vtkActor2D> buttonActor0 = vtkSPtr<vtkActor2D>::New();
    buttonActor0->SetMapper( mapper );

    buttonActor0->SetDisplayPosition( OriginDisplayPt[0], OriginDisplayPt[1] );
    vtkMapper2D *mapper = buttonActor0->GetMapper();
    int *ext = mapper->GetInputInformation()->Get( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT() );
    PointStruct size = PointStruct( ext[1] - ext[0] + 1, ext[3] - ext[2] + 1, 0 );

    // ... create buttonActor1
    PointStruct lastPos( buttonActor0->GetPosition() );
    buttonActor1->SetDisplayPosition( lastPos[0] + size[0], lastPos[1] );
    mapper = buttonActor1->GetMapper();
    ext = mapper->GetInputInformation()->Get( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT() );
    size = PointStruct( ext[1] - ext[0] + 1, ext[3] - ext[2] + 1, 0 );
}

bool IsClicked2DButton(vtkActor2D *actor, int x, int y)
{
    vtkCoordinate *coordinate = actor->GetPositionCoordinate();
    PointStruct leftBottomPos( coordinate->GetValue() );
    PointStruct rightTopPos;
    vtkMapper2D *mapper = actor->GetMapper();
    int *ext = mapper->GetInputInformation()->Get( vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT() );
    PointStruct size = PointStruct( ext[1] - ext[0], ext[3] - ext[2], 0 );
    rightTopPos[0] = leftBottomPos[0] + size[0];
    rightTopPos[1] = leftBottomPos[1] + size[1];
    if ( x > leftBottomPos[0] && x < rightTopPos[0] &&
         y > leftBottomPos[1] && y < rightTopPos[1] )
    {
        return true;
    }
    return false;
}
Categories: VTK

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments

XML To JSON
: Input your strings, the tool can convert XML to JSON for you.

X
0
Would love your thoughts, please comment.x
()
x