以下内容引用自VTKUsersGuide.pdf

vtkPropPicker uses hardware picking to determine the instance of vtk- Prop that was picked, as well as the pick position (in global coordinates). vtkPropPicker is generally faster than all other decendents of vtkAbstractPropPicker but it cannot return information detailed information about what was picked.
The AreaPicker classes(vtkAreaPicker and vtkRenderedAreaPicker)differ from all other pickers in that they can determine what lies begin an entire rectangular region of pixels on the screen instead of only what lies behind a single pixel. These classes have an AreaPick(x_min, y_min, x_max, y_max, Renderer) method that can be called in addition to the standard Pick(x,y,z, Renderer) method. If you need detailed information, for example specific cells and points or information about what lies behind an area, review the following picker explanations below.
vtkPicker is a software-based picker that selects vtkProp’s based on their bounding box. Its pick method fires a ray from the camera position through the selection point and intersects the bounding box of each prop 3D; of course, more than one prop 3D may be picked. The “closest” prop 3D in terms of its bounding box intersection point along the ray is returned. (The GetProp3Ds() method can be used to get all prop 3D’s whose bounding box was intersected.)
vtkPointPicker selects a point and returns the point id and coordinates. It operates by firing a ray from the camera position through the selection point, and pro- jecting those points that lie within Tolerance onto the ray. The projected point closest to the camera position is selected, along with its associated actor. It cannot always return a unique pick because of the tolerances involved.
vtkCellPicker selects a cell and returns information about the intersection point (cell id, global coordinates, and parametric cell coordinates).The cell closest to the camera position along the specified ray is selected, along with its associated actor.It will generate a unique pick within the toler- ance specified.

vtkPropPicker基于硬件,返回结果非常迅速,但是不能得到picked item的细节信息。
AreaPicker classes也不能得到picked item的细节信息,但是它不仅有Pick方法,还提供了AreaPick(x_min, y_min, x_max, y_max, Renderer)
vtkPicker基于软件,从相机的位置发出穿透点击点的射线,哪些物体被该射线穿过,该物体就被picked。如此看,射线可能会穿过多个物体,但是功能类返回靠近Camera Position最近的actor信息。它能获取更多的信息,vtkPicker包括了两个子类。
1、vtkPointPicker并不保证唯一性,比vtkCellPicker更快反馈。
2、vtkCellPicker保证了唯一性。

vtkCellPicker

创建一个cone和一个sphere,然后形成叠加的视觉效果,如下图。




使用vtkCellPicker进行pick操作,可以保证获取的唯一性。
CMakeList.txt

cmake_minimum_required(VERSION 2.8)

project(cellPicker)

find_package( VTK REQUIRED )
include( ${VTK_USE_FILE} )

add_executable(${PROJECT_NAME} "main.cpp")

target_link_libraries( ${PROJECT_NAME} ${VTK_LIBRARIES} )

main.cpp

#include <iostream>
#include <stdio.h>
#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 <vtkCellPicker.h>

#include <vtkInteractorStyleTrackballCamera.h>

vtkSmartPointer<vtkCellPicker> picker =
  vtkSmartPointer<vtkCellPicker>::New();

vtkSmartPointer<vtkActor> coneActor =
        vtkSmartPointer<vtkActor>::New();

vtkSmartPointer<vtkActor> sphereActor =
        vtkSmartPointer<vtkActor>::New();

class PickInteractorStyle: public vtkInteractorStyleTrackballCamera
{
public:
    static PickInteractorStyle* New();
    void OnLeftButtonDown() override
    {
        // Get the location of the click (in window coordinates)
        int* pos = this->GetInteractor()->GetEventPosition();

        // Pick from this location.
        picker->Pick( pos[0], pos[1], 0, this->GetDefaultRenderer() );

        // If click position is not in default render's area, it return -1.
        std::cout << "Cell id is: " << picker->GetCellId() << std::endl;

        // If CellId = -1, nothing was picked.
        if(picker->GetCellId() > -1)
        {
            double* worldPosition = picker->GetPickPosition();
            std::cout << "Pick position is: " << worldPosition[0] << " "
                      << worldPosition[1] << " " << worldPosition[2] << endl;

            vtkProp3D * pickedActor = picker->GetProp3D();
            if( pickedActor == coneActor.Get() )
            {
                std::cout << "picked actor is coneActor\n";
            }
            else if( pickedActor == sphereActor.Get() )
            {
                std::cout << "picked actor is sphereActor\n";
            }
        }
        fflush( stdout );
        vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
    }
};

vtkStandardNewMacro( PickInteractorStyle )

int main()
{
    picker->SetTolerance(0.0005);
    picker->PickFromListOn();

    /* cone */
    vtkSmartPointer<vtkConeSource> cone =
            vtkSmartPointer<vtkConeSource>::New();

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

    coneActor->SetMapper( coneMapper );

    picker->AddPickList( coneActor );
    /* cone end */

    /* sphere */
    vtkSmartPointer<vtkSphereSource> sphere =
            vtkSmartPointer<vtkSphereSource>::New();

    vtkSmartPointer<vtkPolyDataMapper> sphereMapper =
            vtkSmartPointer<vtkPolyDataMapper>::New();
    sphereMapper->SetInputConnection( sphere->GetOutputPort() );

    sphereActor->SetMapper( sphereMapper );
    sphereActor->AddPosition( 0, 0, coneActor->GetBounds()[5] - coneActor->GetBounds()[4] );

    picker->AddPickList( sphereActor );
    /* cone end */


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

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

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

    vtkSmartPointer<PickInteractorStyle> pickStyle =
            vtkSmartPointer<PickInteractorStyle>::New();
    pickStyle->SetDefaultRenderer( renderer );

    renderWindow->Render();
    renderWindowInteractor->SetInteractorStyle( pickStyle );
    renderWindowInteractor->Start();

    return 0;
}

执行:

Cell id is: 2
Pick position is: -0.0202024 0.160918 1.32739
picked actor is sphereActor

vtk的tcl例子:VTK-8.1.1/Examples/Annotation/Tcl/annotatePick.tcl

# Create a cell picker.
vtkCellPicker picker
    picker AddObserver EndPickEvent annotatePick

vtkRenderWindowInteractor iren
    iren SetRenderWindow renWin
    iren SetPicker picker

#...

proc annotatePick {} {
    if { [picker GetCellId] < 0 } {
    textActor VisibilityOff

    } else {
    set selPt [picker GetSelectionPoint]
    set x [lindex $selPt 0]
    set y [lindex $selPt 1]
    set pickPos [picker GetPickPosition]
    set xp [lindex $pickPos 0]
    set yp [lindex $pickPos 1]
    set zp [lindex $pickPos 2]

    textMapper SetInput "($xp, $yp, $zp)"
    textActor SetPosition $x $y
    textActor VisibilityOn
    }

对于vtkPointPicker,我本想复现It cannot always return a unique pick because of the tolerances involved.的结论。但是,picker->GetProp3Ds得到的一直是空,奇怪。。。。

#include <iostream>
#include <stdio.h>
#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 <vtkCellPicker.h>
#include <vtkPointPicker.h>
#include <vtkProp3DCollection.h>

#include <vtkInteractorStyleTrackballCamera.h>

//vtkSmartPointer<vtkCellPicker> picker =
// vtkSmartPointer<vtkCellPicker>::New();

vtkSmartPointer<vtkPointPicker> picker =
vtkSmartPointer<vtkPointPicker>::New();

vtkSmartPointer<vtkActor> coneActor =
vtkSmartPointer<vtkActor>::New();

vtkSmartPointer<vtkActor> sphereActor =
vtkSmartPointer<vtkActor>::New();

class PickInteractorStyle: public vtkInteractorStyleTrackballCamera
{
public:
static PickInteractorStyle* New();
void OnLeftButtonDown() override
{
// Get the location of the click (in window coordinates)
int* pos = this->GetInteractor()->GetEventPosition();

// Pick from this location.
picker->Pick( pos[0], pos[1], 0, this->GetDefaultRenderer() );

// Get the id of the picked point. If PointId = -1, nothing was picked.
std::cout << "Point id is: " << picker->GetPointId() << std::endl;

vtkProp3DCollection *propCollect = picker->GetProp3Ds();
vtkProp3D *prop = nullptr;
prop = propCollect->GetNextProp3D();
printf( "prop is %p\n", prop );
while( prop != nullptr )
{
if( prop == coneActor.Get() )
{
std::cout << "From GetNextProp3D, picked actor is coneActor\n";
}
else if( prop == sphereActor.Get() )
{
std::cout << "From GetNextProp3D, picked actor is sphereActor\n";
}
prop = propCollect->GetNextProp3D();
}


// If PointId = -1, nothing was picked.
if(picker->GetPointId() > -1)
{
double* worldPosition = picker->GetPickPosition();
std::cout << "Pick position is: " << worldPosition[0] << " "
<< worldPosition[1] << " " << worldPosition[2] << endl;

vtkProp3D * pickedActor = picker->GetProp3D();
if( pickedActor == coneActor.Get() )
{
std::cout << "picked actor is coneActor\n";
}
else if( pickedActor == sphereActor.Get() )
{
std::cout << "picked actor is sphereActor\n";
}
}
fflush( stdout );
vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
}
};

vtkStandardNewMacro( PickInteractorStyle )

int main()
{
picker->SetTolerance(0.05);
picker->PickFromListOn();

/* cone */
vtkSmartPointer<vtkConeSource> cone =
vtkSmartPointer<vtkConeSource>::New();

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

coneActor->SetMapper( coneMapper );

picker->AddPickList( coneActor );
/* cone end */

/* sphere */
vtkSmartPointer<vtkSphereSource> sphere =
vtkSmartPointer<vtkSphereSource>::New();

vtkSmartPointer<vtkPolyDataMapper> sphereMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
sphereMapper->SetInputConnection( sphere->GetOutputPort() );

sphereActor->SetMapper( sphereMapper );
sphereActor->AddPosition( 0, 0, coneActor->GetBounds()[5] - coneActor->GetBounds()[4] );

picker->AddPickList( sphereActor );
/* cone end */


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

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

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

vtkSmartPointer<PickInteractorStyle> pickStyle =
vtkSmartPointer<PickInteractorStyle>::New();
pickStyle->SetDefaultRenderer( renderer );

renderWindow->Render();
renderWindowInteractor->SetInteractorStyle( pickStyle );
renderWindowInteractor->Start();

return 0;
}

分类: C plus plus

发表评论

电子邮件地址不会被公开。 必填项已用*标注