diff --git a/src/HEP/Geant/Scene.cpp b/src/HEP/Geant/Scene.cpp index 661e3f6..9466b31 100644 --- a/src/HEP/Geant/Scene.cpp +++ b/src/HEP/Geant/Scene.cpp @@ -102,6 +102,7 @@ void Scene::AddSolid(Solid *solid, Solid *parent) { const Solid* Scene::GetWorld() const { return d->m_World; } ContainerBox* Scene::GetWorldBox() const { return &d->m_WorldBox; } +const Vector& Scene::GetSolids() const { return d->m_Solids; } void Scene::ConstructWorldBox(const Vector3f &size, const char *material) { d->m_WorldBox.Scale(size); diff --git a/src/HEP/Geant/Scene.h b/src/HEP/Geant/Scene.h index d3c5f8c..504a56e 100644 --- a/src/HEP/Geant/Scene.h +++ b/src/HEP/Geant/Scene.h @@ -58,6 +58,9 @@ public: ContainerBox* GetWorldBox() const; + /// Get the list of solids in the scene + const Vector& GetSolids() const; + /// Set the primary generator (emitter) for the simulation. /// The Scene does NOT take ownership of the emitter. void SetEmitter(EmitterPrimary *emitter); diff --git a/src/Vtk/HEP/Geant/CMakeLists.txt b/src/Vtk/HEP/Geant/CMakeLists.txt index 3685437..bf03459 100644 --- a/src/Vtk/HEP/Geant/CMakeLists.txt +++ b/src/Vtk/HEP/Geant/CMakeLists.txt @@ -5,11 +5,15 @@ set(HEP_GEANT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/vtkGeantEvent.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/vtkGeantSolid.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/vtkGeantScene.cpp ${CMAKE_CURRENT_SOURCE_DIR}/vtkEmitterPrimary.cpp PARENT_SCOPE) set(HEP_GEANT_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/vtkGeantEvent.h + ${CMAKE_CURRENT_SOURCE_DIR}/vtkGeantSolid.h + ${CMAKE_CURRENT_SOURCE_DIR}/vtkGeantScene.h ${CMAKE_CURRENT_SOURCE_DIR}/vtkEmitterPrimary.h PARENT_SCOPE) diff --git a/src/Vtk/HEP/Geant/testing/CMakeLists.txt b/src/Vtk/HEP/Geant/testing/CMakeLists.txt index ee0fd69..4cc85be 100644 --- a/src/Vtk/HEP/Geant/testing/CMakeLists.txt +++ b/src/Vtk/HEP/Geant/testing/CMakeLists.txt @@ -1,6 +1,7 @@ # TESTS set(TESTS vtkGeantEventTest + vtkGeantSceneTest vtkEmitterPrimaryTest vtkSkyPlaneEmitterPrimaryTest vtkCylinderEmitterPrimaryTest diff --git a/src/Vtk/HEP/Geant/testing/vtkGeantSceneTest.cpp b/src/Vtk/HEP/Geant/testing/vtkGeantSceneTest.cpp new file mode 100644 index 0000000..c79d9b9 --- /dev/null +++ b/src/Vtk/HEP/Geant/testing/vtkGeantSceneTest.cpp @@ -0,0 +1,65 @@ +/*////////////////////////////////////////////////////////////////////////////// +// CMT Cosmic Muon Tomography project ////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + + Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova + All rights reserved + + Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it > + +//////////////////////////////////////////////////////////////////////////////*/ + +#include "Geant/Solid.h" +#include "HEP/Geant/Scene.h" +#include "Math/ContainerBox.h" +#include "Math/Dense.h" +#include "Math/Units.h" +#include "Vtk/uLibVtkViewer.h" +#include "Vtk/HEP/Geant/vtkGeantScene.h" + +#include +#include +#include + +#include + +using namespace uLib; + +int main(int argc, char** argv) { + bool interactive = (argc > 1 && std::string(argv[1]) == "-i"); + + // 1. Setup Geant4 Scene + Geant::Scene scene; + scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR"); + + // Add an iron cube inside the world + ContainerBox iron_box; + iron_box.Scale(Vector3f(10_m, 10_m, 10_m)); + iron_box.SetPosition(Vector3f(-5_m, -5_m, -5_m)); + Geant::BoxSolid* iron_cube = new Geant::BoxSolid("IronCube", &iron_box); + iron_cube->SetNistMaterial("G4_Fe"); + iron_cube->Update(); + scene.AddSolid(iron_cube); + scene.Initialize(); + + // 2. Build VTK scene representation + Vtk::Viewer viewer; + viewer.GetRenderer()->SetBackground(0.05, 0.05, 0.1); + + Vtk::vtkGeantScene vtkScene(&scene); + vtkScene.AddToViewer(viewer); + + std::cout << "==================================================" << std::endl; + std::cout << " vtkGeantScene Test" << std::endl; + std::cout << " World box + 1 iron cube displayed" << std::endl; + std::cout << "==================================================" << std::endl; + + if (interactive) { + viewer.ZoomAuto(); + viewer.Start(); + } else { + std::cout << "Non-interactive test: scene initialized successfully" << std::endl; + } + + return 0; +} diff --git a/src/Vtk/HEP/Geant/vtkGeantScene.cpp b/src/Vtk/HEP/Geant/vtkGeantScene.cpp new file mode 100644 index 0000000..75e3c94 --- /dev/null +++ b/src/Vtk/HEP/Geant/vtkGeantScene.cpp @@ -0,0 +1,89 @@ +/*////////////////////////////////////////////////////////////////////////////// +// CMT Cosmic Muon Tomography project ////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + + Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova + All rights reserved + + Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it > + + ------------------------------------------------------------------ + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. + +//////////////////////////////////////////////////////////////////////////////*/ + +#include "vtkGeantScene.h" +#include "vtkGeantSolid.h" +#include "Vtk/vtkViewport.h" + +namespace uLib { +namespace Vtk { + +vtkGeantScene::vtkGeantScene(Geant::Scene *scene) + : m_Scene(scene), m_WorldPuppet(nullptr) { + if (!m_Scene) + return; + + // 1. Create the world box wireframe puppet + ContainerBox *worldBox = m_Scene->GetWorldBox(); + if (worldBox) { + m_WorldPuppet = new vtkContainerBox(worldBox); + m_WorldPuppet->SetRepresentation(Puppet::Wireframe); + m_WorldPuppet->ShowScaleMeasures(true); + } + + // 2. Create puppets for each non-world solid + const Geant::Solid *world = m_Scene->GetWorld(); + const Vector &solids = m_Scene->GetSolids(); + + for (Geant::Solid *solid : solids) { + // Skip the world volume itself — it's already shown as the wireframe box + if (solid == world) + continue; + + // Only create a puppet if the solid has a valid G4VSolid + if (solid->GetG4Solid()) { + vtkGeantSolid *vtkSolid = new vtkGeantSolid(solid); + m_SolidPuppets.push_back(vtkSolid); + } + } +} + +vtkGeantScene::~vtkGeantScene() { + delete m_WorldPuppet; + for (auto *p : m_SolidPuppets) { + delete p; + } +} + +void vtkGeantScene::AddToViewer(Viewport &viewer) { + if (m_WorldPuppet) { + viewer.AddPuppet(*m_WorldPuppet); + } + for (auto *p : m_SolidPuppets) { + viewer.AddPuppet(*p); + } +} + +void vtkGeantScene::RemoveFromViewer(Viewport &viewer) { + if (m_WorldPuppet) { + viewer.RemovePuppet(*m_WorldPuppet); + } + for (auto *p : m_SolidPuppets) { + viewer.RemovePuppet(*p); + } +} + +} // namespace Vtk +} // namespace uLib diff --git a/src/Vtk/HEP/Geant/vtkGeantScene.h b/src/Vtk/HEP/Geant/vtkGeantScene.h new file mode 100644 index 0000000..0b50836 --- /dev/null +++ b/src/Vtk/HEP/Geant/vtkGeantScene.h @@ -0,0 +1,87 @@ +/*////////////////////////////////////////////////////////////////////////////// +// CMT Cosmic Muon Tomography project ////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + + Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova + All rights reserved + + Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it > + + ------------------------------------------------------------------ + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. + +//////////////////////////////////////////////////////////////////////////////*/ + +#ifndef U_VTKGEANTSCENE_H +#define U_VTKGEANTSCENE_H + +#include "HEP/Geant/Scene.h" +#include "uLibVtkInterface.h" +#include "Vtk/Math/vtkContainerBox.h" + +#include +#include + +namespace uLib { +namespace Vtk { + +class vtkGeantSolid; + +/** + * @brief VTK Puppet representing the entire Geant::Scene. + * + * When constructed, it creates child puppets for the world box (as a + * vtkContainerBox wireframe) and for each non-world Solid in the scene + * (as vtkGeantSolid surfaces). + * + * Usage: + * @code + * Geant::Scene scene; + * scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR"); + * // ... add solids ... + * scene.Initialize(); + * + * Vtk::Viewer viewer; + * Vtk::vtkGeantScene vtkScene(&scene); + * vtkScene.AddToViewer(viewer); + * viewer.Start(); + * @endcode + */ +class vtkGeantScene : public Object { +public: + vtkGeantScene(Geant::Scene *scene); + ~vtkGeantScene(); + + /// Add all puppets (world box + solids) to a viewer. + void AddToViewer(class Viewport &viewer); + + /// Remove all puppets from viewport. + void RemoveFromViewer(class Viewport &viewer); + + /// Get the world box puppet + vtkContainerBox* GetWorldPuppet() const { return m_WorldPuppet; } + + /// Get the solid puppets + const std::vector& GetSolidPuppets() const { return m_SolidPuppets; } + +private: + Geant::Scene *m_Scene; + vtkContainerBox *m_WorldPuppet; + std::vector m_SolidPuppets; +}; + +} // namespace Vtk +} // namespace uLib + +#endif // U_VTKGEANTSCENE_H diff --git a/src/Vtk/HEP/Geant/vtkGeantSolid.cpp b/src/Vtk/HEP/Geant/vtkGeantSolid.cpp new file mode 100644 index 0000000..df0b2d1 --- /dev/null +++ b/src/Vtk/HEP/Geant/vtkGeantSolid.cpp @@ -0,0 +1,156 @@ +/*////////////////////////////////////////////////////////////////////////////// +// CMT Cosmic Muon Tomography project ////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + + Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova + All rights reserved + + Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it > + + ------------------------------------------------------------------ + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. + +//////////////////////////////////////////////////////////////////////////////*/ + +#include "vtkGeantSolid.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace uLib { +namespace Vtk { + +vtkGeantSolid::vtkGeantSolid(Content *content) + : m_SolidActor(vtkActor::New()), m_Content(content) { + this->InstallPipe(); + this->Update(); +} + +vtkGeantSolid::~vtkGeantSolid() { + m_SolidActor->Delete(); +} + +vtkPolyData *vtkGeantSolid::GetPolyData() const { + if (!m_SolidActor || !m_SolidActor->GetMapper()) + return NULL; + return vtkPolyData::SafeDownCast(m_SolidActor->GetMapper()->GetInput()); +} + +void vtkGeantSolid::Update() { + if (!m_Content) + return; + + G4VSolid *g4solid = m_Content->GetG4Solid(); + if (!g4solid) + return; + + // Get the polyhedron tessellation from Geant4 + G4Polyhedron *polyhedron = g4solid->GetPolyhedron(); + if (!polyhedron) + return; + + vtkSmartPointer points = vtkSmartPointer::New(); + vtkSmartPointer polys = vtkSmartPointer::New(); + + // Extract vertices + int nVertices = polyhedron->GetNoVertices(); + for (int i = 1; i <= nVertices; ++i) { + G4Point3D vtx = polyhedron->GetVertex(i); + points->InsertNextPoint(vtx.x(), vtx.y(), vtx.z()); + } + + // Extract facets (polygons) + int nFacets = polyhedron->GetNoFacets(); + for (int f = 1; f <= nFacets; ++f) { + G4int nEdges; + G4int iVertex[4]; // G4Polyhedron facets have at most 4 vertices + // GetNextFacet returns edges; for quads nEdges=4, for triangles nEdges=3 + polyhedron->GetFacet(f, nEdges, iVertex); + + vtkIdType ids[4]; + for (int e = 0; e < nEdges; ++e) { + // G4Polyhedron vertices are 1-indexed; VTK expects 0-indexed + ids[e] = static_cast(std::abs(iVertex[e]) - 1); + } + polys->InsertNextCell(nEdges, ids); + } + + vtkPolyData *polyData = GetPolyData(); + if (polyData) { + polyData->SetPoints(points); + polyData->SetPolys(polys); + polyData->Modified(); + } + + // Apply the Geant4 transform (position/rotation) if placed + if (m_Content->GetPhysical()) { + auto *phys = m_Content->GetPhysical(); + G4ThreeVector pos = phys->GetTranslation(); + const G4RotationMatrix *rot = phys->GetRotation(); + + vtkSmartPointer transform = vtkSmartPointer::New(); + transform->Identity(); + transform->Translate(pos.x(), pos.y(), pos.z()); + + if (rot) { + // G4RotationMatrix stores the inverse of the rotation for placement + G4RotationMatrix invRot = rot->inverse(); + double elements[16] = { + invRot.xx(), invRot.xy(), invRot.xz(), 0, + invRot.yx(), invRot.yy(), invRot.yz(), 0, + invRot.zx(), invRot.zy(), invRot.zz(), 0, + 0, 0, 0, 1 + }; + vtkSmartPointer mat = vtkSmartPointer::New(); + mat->DeepCopy(elements); + transform->Concatenate(mat); + } + + m_SolidActor->SetUserTransform(transform); + } +} + +void vtkGeantSolid::InstallPipe() { + vtkSmartPointer polyData = vtkSmartPointer::New(); + vtkSmartPointer mapper = + vtkSmartPointer::New(); + mapper->SetInputData(polyData); + + m_SolidActor->SetMapper(mapper); + + // Default look: semi-transparent blue surface + m_SolidActor->GetProperty()->SetColor(0.4, 0.6, 0.9); + m_SolidActor->GetProperty()->SetOpacity(0.3); + m_SolidActor->GetProperty()->SetAmbient(0.5); + m_SolidActor->GetProperty()->SetDiffuse(0.6); + m_SolidActor->GetProperty()->SetSpecular(0.2); + m_SolidActor->GetProperty()->SetEdgeVisibility(1); + m_SolidActor->GetProperty()->SetEdgeColor(0.2, 0.3, 0.5); + + this->SetProp(m_SolidActor); +} + +} // namespace Vtk +} // namespace uLib diff --git a/src/Vtk/HEP/Geant/vtkGeantSolid.h b/src/Vtk/HEP/Geant/vtkGeantSolid.h new file mode 100644 index 0000000..8a947ca --- /dev/null +++ b/src/Vtk/HEP/Geant/vtkGeantSolid.h @@ -0,0 +1,66 @@ +/*////////////////////////////////////////////////////////////////////////////// +// CMT Cosmic Muon Tomography project ////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + + Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova + All rights reserved + + Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it > + + ------------------------------------------------------------------ + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3.0 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. + +//////////////////////////////////////////////////////////////////////////////*/ + +#ifndef U_VTKGEANTSOLID_H +#define U_VTKGEANTSOLID_H + +#include "HEP/Geant/Solid.h" +#include "uLibVtkInterface.h" +#include "vtkPolydata.h" + +class vtkActor; + +namespace uLib { +namespace Vtk { + +/** + * @brief VTK Puppet for visualizing a Geant::Solid. + * + * Renders the G4VSolid geometry as a tessellated polydata surface. + * Works with BoxSolid, TessellatedSolid, or any Solid that provides + * a valid G4VSolid via GetG4Solid(). + */ +class vtkGeantSolid : public Puppet, public Polydata { + typedef Geant::Solid Content; + +public: + vtkGeantSolid(Content *content); + ~vtkGeantSolid(); + + virtual class vtkPolyData *GetPolyData() const override; + + virtual void Update(); + +protected: + virtual void InstallPipe(); + + vtkActor *m_SolidActor; + Content *m_Content; +}; + +} // namespace Vtk +} // namespace uLib + +#endif // U_VTKGEANTSOLID_H diff --git a/src/Vtk/Math/vtkContainerBox.cpp b/src/Vtk/Math/vtkContainerBox.cpp index ee5bfeb..2b8a37f 100644 --- a/src/Vtk/Math/vtkContainerBox.cpp +++ b/src/Vtk/Math/vtkContainerBox.cpp @@ -48,13 +48,11 @@ namespace uLib { namespace Vtk { struct ContainerBoxData { - vtkActor *m_Cube; - vtkActor *m_Axes; + vtkSmartPointer m_Cube; + vtkSmartPointer m_Axes; - ContainerBoxData() : m_Cube(vtkActor::New()), m_Axes(vtkActor::New()) {} + ContainerBoxData() : m_Cube(vtkSmartPointer::New()), m_Axes(vtkSmartPointer::New()) {} ~ContainerBoxData() { - m_Cube->Delete(); - m_Axes->Delete(); } }; diff --git a/src/Vtk/testing/vtkHandlerWidget.cpp b/src/Vtk/testing/vtkHandlerWidget.cpp index 2c70d92..6ea20c7 100644 --- a/src/Vtk/testing/vtkHandlerWidget.cpp +++ b/src/Vtk/testing/vtkHandlerWidget.cpp @@ -46,13 +46,14 @@ int main() { box.Scale(Vector3f(2.0, 3.0, 4.0)); box.SetPosition(Vector3f(1.0, 1.0, 1.0)); + // 3. Setup the Viewer + Vtk::Viewer viewer; + // 2. Wrap it in a Vtk::vtkContainerBox (Vtk Puppet) Vtk::vtkContainerBox v_box(&box); v_box.SetRepresentation(Vtk::Puppet::Surface); v_box.SetOpacity(0.5); - // 3. Setup the Viewer - Vtk::Viewer viewer; viewer.AddPuppet(v_box); // 4. Create and setup the vtkHandlerWidget @@ -112,5 +113,6 @@ int main() { << std::endl; } + handler->EnabledOff(); END_TESTING; } diff --git a/src/Vtk/uLibVtkViewer.cpp b/src/Vtk/uLibVtkViewer.cpp index a1cdd43..726f075 100644 --- a/src/Vtk/uLibVtkViewer.cpp +++ b/src/Vtk/uLibVtkViewer.cpp @@ -84,6 +84,13 @@ Viewer::Viewer() } Viewer::~Viewer() { + this->DisableHandler(); + if (this->GetRenderWindow()) { + this->GetRenderWindow()->RemoveAllObservers(); + } + if (this->GetInteractor()) { + this->GetInteractor()->RemoveAllObservers(); + } UninstallPipe(); delete d; } @@ -111,9 +118,6 @@ void Viewer::InstallPipe() { } void Viewer::UninstallPipe() { - if (GetRenderer()) { - GetRenderer()->RemoveAllViewProps(); - } } void Viewer::Render() { diff --git a/src/Vtk/vtkHandlerWidget.cpp b/src/Vtk/vtkHandlerWidget.cpp index 6919ef2..4f460ac 100644 --- a/src/Vtk/vtkHandlerWidget.cpp +++ b/src/Vtk/vtkHandlerWidget.cpp @@ -100,6 +100,7 @@ vtkHandlerWidget::vtkHandlerWidget() : d(new HandlerWidgetData()) { } vtkHandlerWidget::~vtkHandlerWidget() { + this->SetEnabled(0); delete d; } @@ -194,9 +195,12 @@ void vtkHandlerWidget::SetEnabled(int enabling) { this->Enabled = 0; this->Highlight(nullptr); - this->Interactor->RemoveObserver(this->EventCallbackCommand); - if (this->Interactor->GetRenderWindow()) { - this->Interactor->GetRenderWindow()->RemoveRenderer(this->d->m_OverlayRenderer); + if (this->Interactor) { + this->Interactor->RemoveObserver(this->EventCallbackCommand); + if (this->Interactor->GetRenderWindow()) { + this->Interactor->GetRenderWindow()->MakeCurrent(); + this->Interactor->GetRenderWindow()->RemoveRenderer(this->d->m_OverlayRenderer); + } } this->d->m_OverlayRenderer->RemoveAllViewProps(); this->InvokeEvent(::vtkCommand::DisableEvent, nullptr); @@ -792,21 +796,23 @@ void vtkHandlerWidget::UpdateGizmoPosition() { if (bboxSize < 1e-6) bboxSize = 1.0; double screenLimit = bboxSize * 2.0; // Default if no renderer - if (this->CurrentRenderer) { - int *sz = this->CurrentRenderer->GetSize(); - if (sz[1] > 0) { - double pixelSize = std::min(sz[0], sz[1]) / 5.0; - vtkCamera *cam = this->CurrentRenderer->GetActiveCamera(); - if (cam->GetParallelProjection()) { - screenLimit = (pixelSize / (double)sz[1]) * 2.0 * cam->GetParallelScale(); - } else { - double dist = cam->GetDistance(); - double angleRad = vtkMath::Pi() * cam->GetViewAngle() / 180.0; - double viewHeightAtDist = 2.0 * dist * tan(angleRad / 2.0); - screenLimit = (pixelSize / (double)sz[1]) * viewHeightAtDist; + if (this->CurrentRenderer && this->CurrentRenderer->GetRenderWindow() && this->CurrentRenderer->GetRenderWindow()->GetInteractor()) { + int *sz = this->CurrentRenderer->GetSize(); + if (sz[1] > 0) { + double pixelSize = std::min(sz[0], sz[1]) / 5.0; + vtkCamera *cam = this->CurrentRenderer->GetActiveCamera(); + if (cam) { + if (cam->GetParallelProjection()) { + screenLimit = (pixelSize / (double)sz[1]) * 2.0 * cam->GetParallelScale(); + } else { + double dist = cam->GetDistance(); + double angleRad = vtkMath::Pi() * cam->GetViewAngle() / 180.0; + double viewHeightAtDist = 2.0 * dist * tan(angleRad / 2.0); + screenLimit = (pixelSize / (double)sz[1]) * viewHeightAtDist; + } + } } } - } double scaleFactor = std::min(bboxSize, screenLimit); vtkNew mat_gizmo; diff --git a/src/Vtk/vtkViewport.cpp b/src/Vtk/vtkViewport.cpp index 1eae672..6550921 100644 --- a/src/Vtk/vtkViewport.cpp +++ b/src/Vtk/vtkViewport.cpp @@ -64,9 +64,23 @@ Viewport::Viewport() { } +void Viewport::DisableHandler() { + if (d->m_HandlerWidget) { + d->m_HandlerWidget->SetEnabled(0); + } +} + Viewport::~Viewport() { + if (d->m_HandlerWidget) { + d->m_HandlerWidget->SetEnabled(0); + d->m_HandlerWidget = nullptr; + } if (d->m_Renderer) { + if (d->m_Renderer->GetActiveCamera()) { + d->m_Renderer->GetActiveCamera()->RemoveAllObservers(); + } + d->m_Renderer->RemoveAllObservers(); d->m_Renderer->RemoveAllViewProps(); } delete d; diff --git a/src/Vtk/vtkViewport.h b/src/Vtk/vtkViewport.h index 0715be5..1054909 100644 --- a/src/Vtk/vtkViewport.h +++ b/src/Vtk/vtkViewport.h @@ -58,6 +58,7 @@ public: virtual vtkRenderWindowInteractor* GetInteractor() = 0; vtkCornerAnnotation* GetAnnotation(); vtkCameraOrientationWidget* GetCameraWidget(); + void DisableHandler(); const std::vector& getPuppets() const { return m_Puppets; } // Grid control