diff --git a/src/Vtk/HEP/Detectors/testing/vtkDetectorChamberTest.cpp b/src/Vtk/HEP/Detectors/testing/vtkDetectorChamberTest.cpp index 6a8d0ee..2f126a7 100644 --- a/src/Vtk/HEP/Detectors/testing/vtkDetectorChamberTest.cpp +++ b/src/Vtk/HEP/Detectors/testing/vtkDetectorChamberTest.cpp @@ -32,11 +32,16 @@ #include BOOST_AUTO_TEST_CASE(vtkDetectorChamberTest) { - uLib::DetectorChamber content; - content.SetSize(uLib::Vector3f(10, 10, 10)); - content.SetPosition(uLib::Vector3f(0, 0, 0)); + uLib::DetectorChamber d1, d2; + d1.SetSize(uLib::Vector3f(10, 20, 2)); + d1.SetPosition(uLib::Vector3f(0, 0, 0)); - uLib::Vtk::vtkDetectorChamber vtkDetectorChamber(&content); + d2.SetSize(uLib::Vector3f(10, 20, 2)); + d2.SetPosition(uLib::Vector3f(0, 0, 20)); + + uLib::Vtk::vtkDetectorChamber vtkDetectorChamber(&d1); + + uLib::Vtk::vtkDetectorChamber vtkDetectorChamber2(&d2); if (!vtkDetectorChamber.GetProp()) { BOOST_FAIL("vtkDetectorChamber::GetProp() returned NULL"); @@ -45,6 +50,7 @@ BOOST_AUTO_TEST_CASE(vtkDetectorChamberTest) { if (std::getenv("CTEST_PROJECT_NAME") == nullptr) { uLib::Vtk::Viewer viewer; viewer.AddPuppet(vtkDetectorChamber); + viewer.AddPuppet(vtkDetectorChamber2); viewer.Start(); } diff --git a/src/Vtk/HEP/Detectors/vtkDetectorChamber.cxx b/src/Vtk/HEP/Detectors/vtkDetectorChamber.cxx index d3196df..7a4c700 100644 --- a/src/Vtk/HEP/Detectors/vtkDetectorChamber.cxx +++ b/src/Vtk/HEP/Detectors/vtkDetectorChamber.cxx @@ -23,18 +23,45 @@ //////////////////////////////////////////////////////////////////////////////*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "Vtk/HEP/Detectors/vtkDetectorChamber.h" -#include "Vtk/vtkContainerBox.h" namespace uLib { namespace Vtk { vtkDetectorChamber::vtkDetectorChamber(DetectorChamber *content) : vtkContainerBox(content) { - InstallPipe(); + m_Widget = vtkBoxWidget::New(); + m_Callback = vtkWidgetCallback::New(); + m_PickerCallback = vtkSelectionCallback::New(); + + m_Callback->SetChamber(this); + m_PickerCallback->SetChamber(this); + m_Widget->AddObserver(vtkCommand::InteractionEvent, m_Callback); + m_Widget->SetRotationEnabled(1); + m_Widget->SetTranslationEnabled(1); + m_Widget->SetScalingEnabled(0); } -vtkDetectorChamber::~vtkDetectorChamber() {} +vtkDetectorChamber::~vtkDetectorChamber() { + m_Widget->Delete(); + m_Callback->Delete(); + m_PickerCallback->Delete(); +} DetectorChamber *vtkDetectorChamber::GetContent() { return static_cast(m_Content); @@ -44,7 +71,130 @@ void vtkDetectorChamber::PrintSelf(std::ostream &o) const { vtkContainerBox::PrintSelf(o); } -void vtkDetectorChamber::InstallPipe() { vtkContainerBox::InstallPipe(); } +void vtkDetectorChamber::ConnectInteractor( + vtkRenderWindowInteractor *interactor) { + if (!interactor) + return; + m_Widget->SetInteractor(interactor); + m_Widget->SetProp3D(m_Cube); + m_Widget->PlaceWidget(); + interactor->AddObserver(vtkCommand::LeftButtonPressEvent, m_PickerCallback); +} + +void vtkDetectorChamber::Update() { + if (!m_Content) + return; + + Matrix4f mat = static_cast(m_Content)->GetWorldMatrix(); + vtkSmartPointer vmat = vtkSmartPointer::New(); + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 4; ++j) + vmat->SetElement(i, j, mat(i, j)); + + m_Cube->SetUserMatrix(vmat); + m_Axes->SetUserMatrix(vmat); + m_Pivot->SetUserMatrix(vmat); +} + +void vtkDetectorChamber::InstallPipe() { + if (!m_Content) + return; + + // Cube: unit box (0,0,0) -> (1,1,1) + vtkSmartPointer cube = vtkSmartPointer::New(); + cube->SetBounds(0, 1, 0, 1, 0, 1); + vtkSmartPointer mapper = + vtkSmartPointer::New(); + mapper->SetInputConnection(cube->GetOutputPort()); + m_Cube->SetMapper(mapper); + m_Cube->GetProperty()->SetRepresentationToWireframe(); + m_Cube->GetProperty()->SetAmbient(0.7); + + // Axes: corner origin + vtkSmartPointer axes = vtkSmartPointer::New(); + axes->SetOrigin(0, 0, 0); + axes->SetScaleFactor(0.2); + mapper = vtkSmartPointer::New(); + mapper->SetInputConnection(axes->GetOutputPort()); + m_Axes->SetMapper(mapper); + m_Axes->GetProperty()->SetLineWidth(3); + m_Axes->GetProperty()->SetAmbient(0.4); + + // Pivot: center of unit box + vtkSmartPointer pivot = vtkSmartPointer::New(); + pivot->SetOrigin(0.5, 0.5, 0.5); + pivot->SetScaleFactor(0.1); + mapper = vtkSmartPointer::New(); + mapper->SetInputConnection(pivot->GetOutputPort()); + m_Pivot->SetMapper(mapper); + m_Pivot->GetProperty()->SetLineWidth(3); + m_Pivot->GetProperty()->SetAmbient(0.4); + + this->SetProp(m_Cube); + this->SetProp(m_Axes); + this->SetProp(m_Pivot); + + this->Update(); +} + +void vtkDetectorChamber::vtkWidgetCallback::Execute(vtkObject *caller, + unsigned long, void *) { + vtkBoxWidget *widget = reinterpret_cast(caller); + vtkSmartPointer t = vtkSmartPointer::New(); + widget->GetTransform(t); + + vtkMatrix4x4 *vmat = t->GetMatrix(); + Matrix4f mat; + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 4; ++j) + mat(i, j) = vmat->GetElement(i, j); + + chamber->GetContent()->SetMatrix(mat); + + // Reset internal matrix to identity to avoid double-transformation + vtkProp3D *prop = widget->GetProp3D(); + if (prop) { + prop->SetPosition(0, 0, 0); + prop->SetOrientation(0, 0, 0); + prop->SetScale(1, 1, 1); + } + + chamber->Update(); +} + +void vtkDetectorChamber::vtkSelectionCallback::Execute(vtkObject *caller, + unsigned long, void *) { + vtkRenderWindowInteractor *interactor = + reinterpret_cast(caller); + vtkSmartPointer picker = vtkSmartPointer::New(); + int *pos = interactor->GetEventPosition(); + picker->Pick( + pos[0], pos[1], 0, + interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()); + + vtkProp *picked = picker->GetViewProp(); + if (picked == chamber->m_Cube || picked == chamber->m_Axes || + picked == chamber->m_Pivot) { + if (!chamber->m_Widget->GetEnabled()) { + // Register current position/rotation/scale from content // + Matrix4f mat = chamber->GetContent()->GetWorldMatrix(); + vtkSmartPointer vmat = vtkSmartPointer::New(); + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 4; ++j) + vmat->SetElement(i, j, mat(i, j)); + + vtkSmartPointer t = vtkSmartPointer::New(); + t->SetMatrix(vmat); + chamber->m_Widget->SetTransform(t); + chamber->m_Widget->PlaceWidget(); + chamber->m_Widget->On(); + } + } else { + if (chamber->m_Widget->GetEnabled()) { + chamber->m_Widget->Off(); + } + } +} } // namespace Vtk } // namespace uLib \ No newline at end of file diff --git a/src/Vtk/HEP/Detectors/vtkDetectorChamber.h b/src/Vtk/HEP/Detectors/vtkDetectorChamber.h index 3c7b3b9..157759a 100644 --- a/src/Vtk/HEP/Detectors/vtkDetectorChamber.h +++ b/src/Vtk/HEP/Detectors/vtkDetectorChamber.h @@ -27,26 +27,17 @@ #define VTK_DETECTOR_CHAMBER_H #include -#include -#include -#include -#include -#include - -#include -#include - -#include - #include +#include #include -#include "Math/Dense.h" - #include "HEP/Detectors/DetectorChamber.h" +#include "Math/Dense.h" #include "Vtk/uLibVtkInterface.h" #include "Vtk/vtkContainerBox.h" +class vtkBoxWidget; + namespace uLib { namespace Vtk { @@ -59,12 +50,39 @@ public: Content *GetContent(); + void Update(); + + void ConnectInteractor(vtkRenderWindowInteractor *interactor) override; + void PrintSelf(std::ostream &o) const; -private: - void InstallPipe(); +protected: + void InstallPipe() override; - vtkDetectorChamber::Content *content; +private: + class vtkWidgetCallback : public vtkCommand { + public: + static vtkWidgetCallback *New() { return new vtkWidgetCallback; } + void SetChamber(uLib::Vtk::vtkDetectorChamber *ch) { this->chamber = ch; } + virtual void Execute(vtkObject *caller, unsigned long, void *) override; + + private: + uLib::Vtk::vtkDetectorChamber *chamber; + }; + + class vtkSelectionCallback : public vtkCommand { + public: + static vtkSelectionCallback *New() { return new vtkSelectionCallback; } + void SetChamber(uLib::Vtk::vtkDetectorChamber *ch) { this->chamber = ch; } + virtual void Execute(vtkObject *caller, unsigned long, void *) override; + + private: + uLib::Vtk::vtkDetectorChamber *chamber; + }; + + vtkBoxWidget *m_Widget; + vtkWidgetCallback *m_Callback; + vtkSelectionCallback *m_PickerCallback; }; } // namespace Vtk diff --git a/src/Vtk/uLibVtkViewer.cpp b/src/Vtk/uLibVtkViewer.cpp index 668afc7..d089cd0 100644 --- a/src/Vtk/uLibVtkViewer.cpp +++ b/src/Vtk/uLibVtkViewer.cpp @@ -23,162 +23,137 @@ //////////////////////////////////////////////////////////////////////////////*/ - - - #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include -#include #include +#include +#include -#include #include #include #include #include +#include #include "uLibVtkViewer.h" // Custom interactor style: disables spin/inertia so the scene only // rotates while the mouse is actively being moved with the button held. -class vtkInteractorStyleNoSpin : public vtkInteractorStyleTrackballCamera -{ +class vtkInteractorStyleNoSpin : public vtkInteractorStyleTrackballCamera { public: - static vtkInteractorStyleNoSpin *New(); - vtkTypeMacro(vtkInteractorStyleNoSpin, vtkInteractorStyleTrackballCamera); + static vtkInteractorStyleNoSpin *New(); + vtkTypeMacro(vtkInteractorStyleNoSpin, vtkInteractorStyleTrackballCamera); - // Override: when the left button is released, immediately stop any - // ongoing motion (rotation/spin) so no momentum is carried over. - void OnLeftButtonUp() override - { - this->StopState(); - vtkInteractorStyleTrackballCamera::OnLeftButtonUp(); - } + // Override: when the left button is released, immediately stop any + // ongoing motion (rotation/spin) so no momentum is carried over. + void OnLeftButtonUp() override { + this->StopState(); + vtkInteractorStyleTrackballCamera::OnLeftButtonUp(); + } }; vtkStandardNewMacro(vtkInteractorStyleNoSpin); namespace uLib { namespace Vtk { - //////////////////////////////////////////////////////////////////////////////// ///// VTK VIEWER ////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// - -Viewer::Viewer() : - m_RenderWindow(vtkRenderWindow::New()), - m_Renderer(vtkRenderer::New()), - m_Annotation(vtkCornerAnnotation::New()), - m_Marker(vtkOrientationMarkerWidget::New()) -{ - InstallPipe(); +Viewer::Viewer() + : m_RenderWindow(vtkRenderWindow::New()), m_Renderer(vtkRenderer::New()), + m_Annotation(vtkCornerAnnotation::New()), + m_Marker(vtkOrientationMarkerWidget::New()) { + InstallPipe(); } -Viewer::~Viewer() -{ - UninstallPipe(); +Viewer::~Viewer() { + UninstallPipe(); - m_Annotation->Delete(); - m_Marker->Delete(); - m_Renderer->Delete(); - m_RenderWindow->Delete(); + m_Annotation->Delete(); + m_Marker->Delete(); + m_Renderer->Delete(); + m_RenderWindow->Delete(); } -void Viewer::InstallPipe() -{ - m_RenderWindow->AddRenderer(m_Renderer); - vtkSmartPointer renderWindowInteractor = - vtkSmartPointer::New(); - renderWindowInteractor->SetRenderWindow(m_RenderWindow); +void Viewer::InstallPipe() { + m_RenderWindow->AddRenderer(m_Renderer); + vtkSmartPointer renderWindowInteractor = + vtkSmartPointer::New(); + renderWindowInteractor->SetRenderWindow(m_RenderWindow); - // Use a custom style with no spin/inertia - vtkSmartPointer style = - vtkSmartPointer::New(); - renderWindowInteractor->SetInteractorStyle(style); + // Use a custom style with no spin/inertia + vtkSmartPointer style = + vtkSmartPointer::New(); + renderWindowInteractor->SetInteractorStyle(style); - // annotation // - m_Annotation->GetTextProperty()->SetColor(1,1,1); - m_Annotation->GetTextProperty()->SetFontFamilyToArial(); - m_Annotation->GetTextProperty()->SetOpacity(0.5); - m_Annotation->SetMaximumFontSize(10); - m_Annotation->SetText(0,"uLib VTK Viewer - OpenCMT all right reserved."); - m_Renderer->AddViewProp(m_Annotation); + // annotation // + m_Annotation->GetTextProperty()->SetColor(1, 1, 1); + m_Annotation->GetTextProperty()->SetFontFamilyToArial(); + m_Annotation->GetTextProperty()->SetOpacity(0.5); + m_Annotation->SetMaximumFontSize(10); + m_Annotation->SetText(0, "uLib VTK Viewer - OpenCMT all right reserved."); + m_Renderer->AddViewProp(m_Annotation); - // orientation marker // - vtkSmartPointer axes = - vtkSmartPointer::New(); - m_Marker->SetInteractor(renderWindowInteractor); - m_Marker->SetOrientationMarker(axes); - m_Marker->SetViewport(0.0,0.0,0.2,0.2); - m_Marker->SetEnabled(true); - m_Marker->InteractiveOff(); + // orientation marker // + vtkSmartPointer axes = vtkSmartPointer::New(); + m_Marker->SetInteractor(renderWindowInteractor); + m_Marker->SetOrientationMarker(axes); + m_Marker->SetViewport(0.0, 0.0, 0.2, 0.2); + m_Marker->SetEnabled(true); + m_Marker->InteractiveOff(); - // Must be rendered here in Vtk-6.0 or seg-fault // - m_RenderWindow->Render(); + // Must be rendered here in Vtk-6.0 or seg-fault // + m_RenderWindow->Render(); } -void Viewer::UninstallPipe() -{ - m_Renderer->RemoveAllViewProps(); - m_Renderer->Clear(); +void Viewer::UninstallPipe() { + m_Renderer->RemoveAllViewProps(); + m_Renderer->Clear(); } -void Viewer::addProp(vtkProp *prop) -{ - m_Renderer->AddActor(prop); - m_Renderer->Render(); +void Viewer::addProp(vtkProp *prop) { + m_Renderer->AddActor(prop); + m_Renderer->Render(); } -void Viewer::RemoveProp(vtkProp *prop) -{ - m_Renderer->RemoveViewProp(prop); - m_Renderer->Render(); +void Viewer::RemoveProp(vtkProp *prop) { + m_Renderer->RemoveViewProp(prop); + m_Renderer->Render(); } -void Viewer::AddPuppet(Puppet &prop) -{ - prop.ConnectRenderer(m_Renderer); - m_Renderer->Render(); +void Viewer::AddPuppet(Puppet &prop) { + prop.ConnectRenderer(m_Renderer); + prop.ConnectInteractor(this->GetInteractor()); + m_Renderer->Render(); } -void Viewer::RemovePuppet(Puppet &prop) -{ - prop.DisconnectRenderer(m_Renderer); - m_Renderer->Render(); +void Viewer::RemovePuppet(Puppet &prop) { + prop.DisconnectRenderer(m_Renderer); + m_Renderer->Render(); } -void Viewer::Start() -{ - m_RenderWindow->GetInteractor()->Start(); +void Viewer::Start() { m_RenderWindow->GetInteractor()->Start(); } + +vtkCornerAnnotation *Viewer::GetAnnotation() { return m_Annotation; } + +vtkRenderer *Viewer::GetRenderer() { return m_Renderer; } + +vtkRenderWindowInteractor *Viewer::GetInteractor() { + return m_RenderWindow->GetInteractor(); } -vtkCornerAnnotation *Viewer::GetAnnotation() -{ - return m_Annotation; +void Viewer::Reset() { + this->ZoomAuto(); + m_Renderer->Render(); } -vtkRenderer *Viewer::GetRenderer() -{ - return m_Renderer; +void Viewer::ZoomAuto() { + m_Renderer->ResetCameraClippingRange(); + m_Renderer->ResetCamera(); } -vtkRenderWindowInteractor *Viewer::GetInteractor() -{ - return m_RenderWindow->GetInteractor(); -} - -void Viewer::Reset() -{ - m_Renderer->ResetCameraClippingRange(); - m_Renderer->ResetCamera(); - m_Renderer->Render(); -} - - -} // vtk -} // uLib - +} // namespace Vtk +} // namespace uLib diff --git a/src/Vtk/uLibVtkViewer.h b/src/Vtk/uLibVtkViewer.h index ee1e0d8..b846540 100644 --- a/src/Vtk/uLibVtkViewer.h +++ b/src/Vtk/uLibVtkViewer.h @@ -23,18 +23,16 @@ //////////////////////////////////////////////////////////////////////////////*/ - - #ifndef ULIBVTKVIEWER_H #define ULIBVTKVIEWER_H -#include #include "uLibVtkInterface.h" +#include -#include -#include #include #include +#include +#include class vtkProp; class vtk3DWidget; @@ -45,63 +43,56 @@ class vtkRenderer; namespace uLib { namespace Vtk { - -template -class Tie { +template class Tie { public: - void DoAction() { - std::cout << "Tie::DoAction -> generic Tie does nothing\n"; - } + void DoAction() { + std::cout << "Tie::DoAction -> generic Tie does nothing\n"; + } }; - class Viewer { public: - Viewer(); - ~Viewer(); + Viewer(); + ~Viewer(); + void AddPuppet(Puppet &prop); - void AddPuppet(Puppet &prop); + void RemovePuppet(Puppet &prop); - void RemovePuppet(Puppet &prop); + void AddWidget(vtk3DWidget *widget); - void AddWidget(vtk3DWidget *widget); + void Reset(); + void ZoomAuto(); - void Reset(); + void Start(); - void Start(); + vtkCornerAnnotation *GetAnnotation(); - vtkCornerAnnotation *GetAnnotation(); + vtkRenderer *GetRenderer(); - vtkRenderer * GetRenderer(); + vtkRenderWindowInteractor *GetInteractor(); - vtkRenderWindowInteractor * GetInteractor(); + void addProp(vtkProp *prop); - void addProp(vtkProp *prop); - - void RemoveProp(vtkProp *prop); + void RemoveProp(vtkProp *prop); private: - void InstallPipe(); - void UninstallPipe(); + void InstallPipe(); + void UninstallPipe(); - vtkRenderer *m_Renderer; - vtkRenderWindow *m_RenderWindow; - vtkCornerAnnotation *m_Annotation; - vtkOrientationMarkerWidget *m_Marker; + vtkRenderer *m_Renderer; + vtkRenderWindow *m_RenderWindow; + vtkCornerAnnotation *m_Annotation; + vtkOrientationMarkerWidget *m_Marker; }; -template <> -class Tie { +template <> class Tie { public: - void DoAction() { - std::cout << " VIEWER TIE !!! \n"; - } + void DoAction() { std::cout << " VIEWER TIE !!! \n"; } }; - -} // vtk -} // uLib +} // namespace Vtk +} // namespace uLib #endif // ULIBVTKVIEWER_H diff --git a/src/Vtk/vtkContainerBox.h b/src/Vtk/vtkContainerBox.h index 92611bf..7d2d02e 100644 --- a/src/Vtk/vtkContainerBox.h +++ b/src/Vtk/vtkContainerBox.h @@ -42,7 +42,7 @@ public: virtual class vtkPolyData *GetPolyData() const; protected: - void InstallPipe(); + virtual void InstallPipe(); vtkActor *m_Cube; vtkActor *m_Axes;