实现VTK vtkAssembly单个部件的鼠标操作

一,需求

当把多个 actor拼装成vtkAssembly后,默认的操作是针对 vtkAssembly,无法对单个actor进行平移或者旋转。

二,实现

利用vtkBoxWidget2 实现actor的控制,并自定义 vtkInteractorStyleTrackballCamera,通过vtkAssemblyPath GetPath实现。

实现VTK vtkAssembly单个部件的鼠标操作_第1张图片

三,代码

#include "mainwindow.h"
#include 

#include 
#include 
#include "vtkRenderer.h"
#include 
#include "vtkRenderWindowInteractor.h"
#include "vtkInteractorStyleTrackballCamera.h"
#include "vtkCylinderSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkPolyDataMapper.h"
#include "vtkCubeAxesActor.h"
#include "vtkOrientationMarkerWidget.h"
#include "vtkBoxRepresentation.h"
#include "vtkBoxWidget2.h"
#include "vtkCellPicker.h"
#include "vtkAssemblyPath.h"

// Define interaction style
#include 
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType)

namespace {

// Handle mouse events
class MouseInteractorStyle : public vtkInteractorStyleTrackballCamera
{
public:
    static MouseInteractorStyle* New();
    vtkTypeMacro(MouseInteractorStyle, vtkInteractorStyleTrackballCamera);

    std::map,vtkSmartPointer> actorBoxWidgetMap;

    virtual void OnLeftButtonDown() override
    {
        int* clickPos = this->GetInteractor()->GetEventPosition();

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

        vtkAssemblyPath *path;
        path = picker->GetPath();
        if(path!=nullptr){
            vtkActor *pickedActor =  static_cast(path->GetLastNode()->GetViewProp());

            if (pickedActor == nullptr)
            {
                std::cout << "No actor picked." << std::endl;
                selectedActor(nullptr);
            } else {
                std::cout << "Picked actor: " << pickedActor << std::endl;
                selectedActor(pickedActor);
            }
        }else{
            selectedActor(nullptr);
        }
        vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
    }
private:
    void selectedActor(vtkActor *actor){
        for(auto it = actorBoxWidgetMap.begin();it!=actorBoxWidgetMap.end();++it){
            if(actor){
                if(it->first==actor){
                    it->first->GetProperty()->SetOpacity(0.5);
                    it->second->On();
                }else{
                    it->first->GetProperty()->SetOpacity(1);
                    it->second->Off();
                }
            }else{
                it->first->GetProperty()->SetOpacity(1);
                it->second->Off();
            }

        }
    }
};

vtkStandardNewMacro(MouseInteractorStyle);

} // namespace

namespace {
class vtkBoxCallback : public vtkCommand{
public:
    static vtkBoxCallback* New(){
        return new vtkBoxCallback;
    }


    void SetActor(vtkSmartPointer actor){
        m_actor = actor;
    }

    vtkSmartPointer GetActor() const{
        return m_actor;
    }

    virtual void Execute(vtkObject* caller, unsigned long, void*){
        vtkSmartPointer boxWidget = dynamic_cast(caller);
        vtkNew t;
        dynamic_cast(boxWidget->GetRepresentation())->GetTransform(t);
        this->m_actor->SetUserTransform(t);

        double pos[3];
        t->GetPosition(pos);
        cout<<"boxCallback pos value "<GetOrientationWXYZ(orient);
        cout<<"boxCallback orient value "< m_actor;
};
} // namespace


int main(int argc, char *argv[])
{

    // QApplication a(argc, argv);

    //MainWindow w;
    // w.show();
    //return a.exec();

    vtkNew namedColors;

    // Create a sphere
    vtkNew coneSource;
    coneSource->SetCenter(7,0,0);


    vtkNew coneMapper;
    coneMapper->SetInputConnection(coneSource->GetOutputPort());
    vtkNew coneActor;
    coneActor->SetMapper(coneMapper);
    coneActor->GetProperty()->SetColor(namedColors->GetColor3d("Banana").GetData());

    // Create a cube
    vtkNew cubeSource;
    cubeSource->SetCenter(5.0, 0.0, 0.0);


    vtkNew cubeMapper;
    cubeMapper->SetInputConnection(cubeSource->GetOutputPort());
    vtkNew cubeActor;
    cubeActor->SetMapper(cubeMapper);
    cubeActor->GetProperty()->SetColor(namedColors->GetColor3d("Tomato").GetData());

    //
    // Create a cube
    vtkNew cubeSource2;
    cubeSource2->SetCenter(3.0, 0, 0.0);

    vtkNew cubeMapper2;
    cubeMapper2->SetInputConnection(cubeSource2->GetOutputPort());
    vtkNew cubeActor2;
    cubeActor2->SetMapper(cubeMapper2);
    cubeActor2->GetProperty()->SetColor(namedColors->GetColor3d("Melon").GetData());

    vtkNew assembly;
    assembly->AddPart(coneActor);
    assembly->AddPart(cubeActor);
    assembly->AddPart(cubeActor2);

    // Visualization
    vtkNew renderer;
    vtkNew renderWindow;
    renderWindow->SetSize(1024,768);
    renderWindow->AddRenderer(renderer);

    vtkNew renderWindowInteractor;
    renderWindowInteractor->SetRenderWindow(renderWindow);

    vtkNew axesActor;
    axesActor->SetVisibility(false);
    vtkSmartPointer widget =
        vtkSmartPointer::New();
    widget->SetOutlineColor( 0.9300, 0.5700, 0.1300 );
    widget->SetOrientationMarker( axesActor );
    widget->SetInteractor( renderWindowInteractor );
    widget->SetViewport( 0.0, 0.0, 0.2, 0.2 );
    widget->SetEnabled( 1 );
    widget->InteractiveOff();


    renderer->AddActor(assembly);
    renderer->SetBackground(namedColors->GetColor3d("SlateGray").GetData());


    vtkNew style;
    style->SetDefaultRenderer(renderer);
    renderWindowInteractor->SetInteractorStyle(style);

    // Extract each actor from the assembly and change its opacity
    vtkNew collection;

    assembly->GetActors(collection);
    collection->InitTraversal();
    for (vtkIdType i = 0; i < collection->GetNumberOfItems(); i++)
    {
        vtkActor *actor =  dynamic_cast(collection->GetNextProp());

        vtkSmartPointer boxWidget = vtkSmartPointer::New();
        boxWidget->SetInteractor(renderWindowInteractor);
        boxWidget->GetRepresentation()->SetPlaceFactor(1.2);
        boxWidget->GetRepresentation()->PlaceWidget(actor->GetBounds());
        std::cout<<"actor boxwidget "< boxCallback;
        boxCallback->SetActor(actor);
        boxWidget->AddObserver(vtkCommand::InteractionEvent, boxCallback);
        style->actorBoxWidgetMap[actor]=boxWidget;
    }

    renderer->ResetCamera();
    renderWindow->SetWindowName("Assembly");
    renderWindow->Render();


    renderWindowInteractor->Start();
    return 0;
}

你可能感兴趣的:(其它,VTK,assembly)