From 64bfd92e344f987fefac1b5df93203dd5d4988f1 Mon Sep 17 00:00:00 2001 From: AndreaRigoni Date: Thu, 16 Apr 2026 15:09:42 +0000 Subject: [PATCH] refactor: update Geant scene visualization to use PhysicalVolumes instead of raw Solids for improved placement and context handling. --- .gitignore | 3 + src/HEP/Geant/Scene.cpp | 4 + src/HEP/Geant/Scene.h | 3 + .../testing/vtkCylinderEmitterPrimaryTest.cpp | 26 +++++-- .../Geant/testing/vtkEmitterPrimaryTest.cpp | 65 +++++++++++----- .../HEP/Geant/testing/vtkGeantEventTest.cpp | 25 ++++-- .../HEP/Geant/testing/vtkGeantSceneTest.cpp | 23 ++++-- .../testing/vtkSkyPlaneEmitterPrimaryTest.cpp | 65 +++++++++++----- src/Vtk/HEP/Geant/testing/vtkSolidsTest.cpp | 72 +++++++++-------- src/Vtk/HEP/Geant/vtkBoxSolid.cpp | 19 +++-- src/Vtk/HEP/Geant/vtkBoxSolid.h | 7 +- src/Vtk/HEP/Geant/vtkGeantScene.cpp | 22 +++--- src/Vtk/HEP/Geant/vtkGeantSolid.cpp | 78 +++++++++---------- src/Vtk/HEP/Geant/vtkGeantSolid.h | 16 ++-- src/Vtk/HEP/Geant/vtkTessellatedSolid.cpp | 12 +-- src/Vtk/HEP/Geant/vtkTessellatedSolid.h | 4 +- src/Vtk/vtkObjectsContext.cpp | 13 ++++ 17 files changed, 288 insertions(+), 169 deletions(-) diff --git a/.gitignore b/.gitignore index 228451b..1bdfd06 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,6 @@ test_boost.cpp .claude/settings.json build_output.log configure_output.log +test.xml +test_ref_smartpointer.xml +test_ref.xml diff --git a/src/HEP/Geant/Scene.cpp b/src/HEP/Geant/Scene.cpp index a195267..eaa3b75 100644 --- a/src/HEP/Geant/Scene.cpp +++ b/src/HEP/Geant/Scene.cpp @@ -127,6 +127,10 @@ const Vector& Scene::GetSolids() const { return d->m_Solids; } +const Vector>& Scene::GetVolumes() const { + return d->m_Volumes; +} + void Scene::ConstructWorldBox(const Vector3f &size, const char *materialName) { d->m_WorldBox->SetSize(size); diff --git a/src/HEP/Geant/Scene.h b/src/HEP/Geant/Scene.h index 0bed2d6..127d9da 100644 --- a/src/HEP/Geant/Scene.h +++ b/src/HEP/Geant/Scene.h @@ -60,6 +60,9 @@ public: /// Get the list of solids in the scene const Vector& GetSolids() const; + /// Get the list of physical volumes in the scene + const Vector>& GetVolumes() 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/testing/vtkCylinderEmitterPrimaryTest.cpp b/src/Vtk/HEP/Geant/testing/vtkCylinderEmitterPrimaryTest.cpp index a12a7e8..4f6b9db 100644 --- a/src/Vtk/HEP/Geant/testing/vtkCylinderEmitterPrimaryTest.cpp +++ b/src/Vtk/HEP/Geant/testing/vtkCylinderEmitterPrimaryTest.cpp @@ -75,13 +75,23 @@ int main(int argc, char** argv) { Geant::Scene scene; scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR"); - ContainerBox iron_box; - iron_box.Scale(Vector3f(10_m, 10_m, 10_m)); - iron_box.SetPosition(Vector3f(0, 0, 0)); - Geant::BoxSolid* iron_cube = new Geant::BoxSolid("IronCube", &iron_box); - iron_cube->SetNistMaterial("G4_Fe"); - iron_cube->Update(); - scene.AddSolid(iron_cube); + // Iron Cube + SmartPointer iron_box(new ContainerBox()); + iron_box->Scale(Vector3f(10_m, 10_m, 10_m)); + iron_box->SetPosition(Vector3f(0, 0, 0)); + + SmartPointer iron_solid(new Geant::BoxSolid("IronSolid", iron_box)); + iron_solid->Update(); + + SmartPointer iron_mat(new Geant::Material("IronMat")); + iron_mat->SetFromNist("G4_Fe"); + + SmartPointer iron_lv(new Geant::LogicalVolume("IronLV")); + iron_lv->SetSolid(iron_solid); + iron_lv->SetMaterial(iron_mat); + + SmartPointer iron_pv(new Geant::PhysicalVolume("IronPV", iron_lv)); + scene.AddVolume(iron_pv); // Use CylinderEmitterPrimary Geant::CylinderEmitterPrimary* emitter = new Geant::CylinderEmitterPrimary(); @@ -103,7 +113,7 @@ int main(int argc, char** argv) { vtkWorld->SetSelectable(false); viewer.AddProp3D(*vtkWorld); - Vtk::ContainerBox* vtkIron = new Vtk::ContainerBox(&iron_box); + Vtk::ContainerBox* vtkIron = new Vtk::ContainerBox(iron_box.Get()); vtkIron->SetOpacity(0.2); vtkIron->SetRepresentation(Vtk::Prop3D::Surface); viewer.AddProp3D(*vtkIron); diff --git a/src/Vtk/HEP/Geant/testing/vtkEmitterPrimaryTest.cpp b/src/Vtk/HEP/Geant/testing/vtkEmitterPrimaryTest.cpp index ec8f118..51446e1 100644 --- a/src/Vtk/HEP/Geant/testing/vtkEmitterPrimaryTest.cpp +++ b/src/Vtk/HEP/Geant/testing/vtkEmitterPrimaryTest.cpp @@ -69,31 +69,56 @@ int main(int argc, char** argv) { Geant::Scene scene; scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR"); - 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); + // Iron Cube + SmartPointer iron_box(new ContainerBox()); + iron_box->Scale(Vector3f(10_m, 10_m, 10_m)); + iron_box->SetPosition(Vector3f(-5_m, -5_m, -5_m)); + + SmartPointer iron_solid(new Geant::BoxSolid("IronSolid", iron_box)); + iron_solid->Update(); + + SmartPointer iron_mat(new Geant::Material("IronMat")); + iron_mat->SetFromNist("G4_Fe"); + + SmartPointer iron_lv(new Geant::LogicalVolume("IronLV")); + iron_lv->SetSolid(iron_solid); + iron_lv->SetMaterial(iron_mat); + + SmartPointer iron_pv(new Geant::PhysicalVolume("IronPV", iron_lv)); + scene.AddVolume(iron_pv); // Top Detector Chamber - DetectorChamber* top_chamber_box = new DetectorChamber(); + SmartPointer top_chamber_box(new DetectorChamber()); top_chamber_box->Scale(Vector3f(10_m, 10_m, 40_cm)); top_chamber_box->SetPosition(Vector3f(-5_m, -5_m, 7_m)); - Geant::BoxSolid* top_chamber = new Geant::BoxSolid("TopChamber", top_chamber_box); - top_chamber->SetNistMaterial("G4_AIR"); - top_chamber->Update(); - scene.AddSolid(top_chamber); + + SmartPointer top_solid(new Geant::BoxSolid("TopSolid", top_chamber_box)); + top_solid->Update(); + + SmartPointer air_mat(new Geant::Material("AirMat")); + air_mat->SetFromNist("G4_AIR"); + + SmartPointer top_lv(new Geant::LogicalVolume("TopLV")); + top_lv->SetSolid(top_solid); + top_lv->SetMaterial(air_mat); + + SmartPointer top_pv(new Geant::PhysicalVolume("TopPV", top_lv)); + scene.AddVolume(top_pv); // Bottom Detector Chamber - DetectorChamber* bottom_chamber_box = new DetectorChamber(); + SmartPointer bottom_chamber_box(new DetectorChamber()); bottom_chamber_box->Scale(Vector3f(10_m, 10_m, 40_cm)); bottom_chamber_box->SetPosition(Vector3f(-5_m, -5_m, -7.1_m)); - Geant::BoxSolid* bottom_chamber = new Geant::BoxSolid("BottomChamber", bottom_chamber_box); - bottom_chamber->SetNistMaterial("G4_AIR"); - bottom_chamber->Update(); - scene.AddSolid(bottom_chamber); + + SmartPointer bottom_solid(new Geant::BoxSolid("BottomSolid", bottom_chamber_box)); + bottom_solid->Update(); + + SmartPointer bottom_lv(new Geant::LogicalVolume("BottomLV")); + bottom_lv->SetSolid(bottom_solid); + bottom_lv->SetMaterial(air_mat); + + SmartPointer bottom_pv(new Geant::PhysicalVolume("BottomPV", bottom_lv)); + scene.AddVolume(bottom_pv); Geant::EmitterPrimary* emitter = new Geant::EmitterPrimary(); emitter->SetPosition(Vector3f(0, 0, 14_m)); @@ -112,20 +137,20 @@ int main(int argc, char** argv) { viewer.AddProp3D(*vtkWorld); // Visualize iron cube - Vtk::ContainerBox* vtkIron = new Vtk::ContainerBox(&iron_box); + Vtk::ContainerBox* vtkIron = new Vtk::ContainerBox(iron_box.Get()); vtkIron->SetOpacity(0.2); vtkIron->SetRepresentation(Vtk::Prop3D::Surface); viewer.AddProp3D(*vtkIron); // Visualize Top Chamber - Vtk::DetectorChamber* vtkTop = new Vtk::DetectorChamber(top_chamber_box); + Vtk::DetectorChamber* vtkTop = new Vtk::DetectorChamber(top_chamber_box.Get()); vtkTop->SetOpacity(0.5); vtkTop->SetColor(0.2, 0.8, 0.2); vtkTop->SetRepresentation(Vtk::Prop3D::Surface); viewer.AddProp3D(*vtkTop); // Visualize Bottom Chamber - Vtk::DetectorChamber* vtkBottom = new Vtk::DetectorChamber(bottom_chamber_box); + Vtk::DetectorChamber* vtkBottom = new Vtk::DetectorChamber(bottom_chamber_box.Get()); vtkBottom->SetOpacity(0.5); vtkBottom->SetColor(0.2, 0.8, 0.2); vtkBottom->SetRepresentation(Vtk::Prop3D::Surface); diff --git a/src/Vtk/HEP/Geant/testing/vtkGeantEventTest.cpp b/src/Vtk/HEP/Geant/testing/vtkGeantEventTest.cpp index 93030b3..fcc4260 100644 --- a/src/Vtk/HEP/Geant/testing/vtkGeantEventTest.cpp +++ b/src/Vtk/HEP/Geant/testing/vtkGeantEventTest.cpp @@ -100,13 +100,22 @@ int main(int argc, char** argv) { Geant::Scene scene; scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR"); - 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); + SmartPointer iron_box(new ContainerBox()); + iron_box->Scale(Vector3f(10_m, 10_m, 10_m)); + iron_box->SetPosition(Vector3f(-5_m, -5_m, -5_m)); + + SmartPointer iron_solid(new Geant::BoxSolid("IronSolid", iron_box)); + iron_solid->Update(); + + SmartPointer iron_mat(new Geant::Material("IronMat")); + iron_mat->SetFromNist("G4_Fe"); + + SmartPointer iron_lv(new Geant::LogicalVolume("IronLV")); + iron_lv->SetSolid(iron_solid); + iron_lv->SetMaterial(iron_mat); + + SmartPointer iron_pv(new Geant::PhysicalVolume("IronPV", iron_lv)); + scene.AddVolume(iron_pv); RandomEmitter* emitter = new RandomEmitter(); scene.SetEmitter(emitter); @@ -123,7 +132,7 @@ int main(int argc, char** argv) { viewer.AddProp3D(*vtkWorld); // Visualize iron cube - Vtk::ContainerBox* vtkIron = new Vtk::ContainerBox(&iron_box); + Vtk::ContainerBox* vtkIron = new Vtk::ContainerBox(iron_box.Get()); vtkIron->SetOpacity(0.2); vtkIron->SetRepresentation(Vtk::Prop3D::Surface); viewer.AddProp3D(*vtkIron); diff --git a/src/Vtk/HEP/Geant/testing/vtkGeantSceneTest.cpp b/src/Vtk/HEP/Geant/testing/vtkGeantSceneTest.cpp index bbb8326..d59f0db 100644 --- a/src/Vtk/HEP/Geant/testing/vtkGeantSceneTest.cpp +++ b/src/Vtk/HEP/Geant/testing/vtkGeantSceneTest.cpp @@ -33,13 +33,22 @@ int main(int argc, char** argv) { 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); + SmartPointer iron_box(new ContainerBox()); + iron_box->Scale(Vector3f(10_m, 10_m, 10_m)); + iron_box->SetPosition(Vector3f(-5_m, -5_m, -5_m)); + + SmartPointer iron_solid(new Geant::BoxSolid("IronSolid", iron_box)); + iron_solid->Update(); + + SmartPointer iron_mat(new Geant::Material("IronMat")); + iron_mat->SetFromNist("G4_Fe"); + + SmartPointer iron_lv(new Geant::LogicalVolume("IronLV")); + iron_lv->SetSolid(iron_solid); + iron_lv->SetMaterial(iron_mat); + + SmartPointer iron_pv(new Geant::PhysicalVolume("IronPV", iron_lv)); + scene.AddVolume(iron_pv); scene.Initialize(); // 2. Build VTK scene representation diff --git a/src/Vtk/HEP/Geant/testing/vtkSkyPlaneEmitterPrimaryTest.cpp b/src/Vtk/HEP/Geant/testing/vtkSkyPlaneEmitterPrimaryTest.cpp index 195e2a3..5eeea50 100644 --- a/src/Vtk/HEP/Geant/testing/vtkSkyPlaneEmitterPrimaryTest.cpp +++ b/src/Vtk/HEP/Geant/testing/vtkSkyPlaneEmitterPrimaryTest.cpp @@ -66,33 +66,58 @@ int main(int argc, char** argv) { Geant::Scene scene; scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR"); - ContainerBox iron_box; - iron_box.Scale(Vector3f(18_m, 18_m, 18_m)); - iron_box.SetPosition(Vector3f(-9_m, -9_m, -9_m)); - Geant::BoxSolid* iron_cube = new Geant::BoxSolid("IronCube", &iron_box); - iron_cube->SetNistMaterial("G4_Fe"); - iron_cube->Update(); - scene.AddSolid(iron_cube); + // Iron Cube + SmartPointer iron_box(new ContainerBox()); + iron_box->Scale(Vector3f(18_m, 18_m, 18_m)); + iron_box->SetPosition(Vector3f(-9_m, -9_m, -9_m)); + + SmartPointer iron_solid(new Geant::BoxSolid("IronSolid", iron_box)); + iron_solid->Update(); + + SmartPointer iron_mat(new Geant::Material("IronMat")); + iron_mat->SetFromNist("G4_Fe"); + + SmartPointer iron_lv(new Geant::LogicalVolume("IronLV")); + iron_lv->SetSolid(iron_solid); + iron_lv->SetMaterial(iron_mat); + + SmartPointer iron_pv(new Geant::PhysicalVolume("IronPV", iron_lv)); + scene.AddVolume(iron_pv); // Top Detector Chamber (along Y axis) - DetectorChamber* top_chamber_box = new DetectorChamber(); + SmartPointer top_chamber_box(new DetectorChamber()); top_chamber_box->Scale(Vector3f(20_m, 40_cm, 20_m)); top_chamber_box->Rotate(90_deg, Vector3f(1, 0, 0)); top_chamber_box->SetPosition(Vector3f(-10_m, 12_m, -10_m)); - Geant::BoxSolid* top_chamber = new Geant::BoxSolid("TopChamber", top_chamber_box); - top_chamber->SetNistMaterial("G4_AIR"); - top_chamber->Update(); - scene.AddSolid(top_chamber); + + SmartPointer top_solid(new Geant::BoxSolid("TopSolid", top_chamber_box)); + top_solid->Update(); + + SmartPointer air_mat(new Geant::Material("AirMat")); + air_mat->SetFromNist("G4_AIR"); + + SmartPointer top_lv(new Geant::LogicalVolume("TopLV")); + top_lv->SetSolid(top_solid); + top_lv->SetMaterial(air_mat); + + SmartPointer top_pv(new Geant::PhysicalVolume("TopPV", top_lv)); + scene.AddVolume(top_pv); // Bottom Detector Chamber (along Y axis) - DetectorChamber* bottom_chamber_box = new DetectorChamber(); + SmartPointer bottom_chamber_box(new DetectorChamber()); bottom_chamber_box->Scale(Vector3f(20_m, 40_cm, 20_m)); bottom_chamber_box->Rotate(90_deg, Vector3f(1, 0, 0)); bottom_chamber_box->SetPosition(Vector3f(-10_m, -12_m, -10_m)); - Geant::BoxSolid* bottom_chamber = new Geant::BoxSolid("BottomChamber", bottom_chamber_box); - bottom_chamber->SetNistMaterial("G4_AIR"); - bottom_chamber->Update(); - scene.AddSolid(bottom_chamber); + + SmartPointer bottom_solid(new Geant::BoxSolid("BottomSolid", bottom_chamber_box)); + bottom_solid->Update(); + + SmartPointer bottom_lv(new Geant::LogicalVolume("BottomLV")); + bottom_lv->SetSolid(bottom_solid); + bottom_lv->SetMaterial(air_mat); + + SmartPointer bottom_pv(new Geant::PhysicalVolume("BottomPV", bottom_lv)); + scene.AddVolume(bottom_pv); // Use SkyPlaneEmitterPrimary instead of EmitterPrimary Geant::SkyPlaneEmitterPrimary* emitter = new Geant::SkyPlaneEmitterPrimary(); @@ -113,20 +138,20 @@ int main(int argc, char** argv) { vtkWorld->SetSelectable(false); viewer.AddProp3D(*vtkWorld); - Vtk::ContainerBox* vtkIron = new Vtk::ContainerBox(&iron_box); + Vtk::ContainerBox* vtkIron = new Vtk::ContainerBox(iron_box.Get()); vtkIron->SetOpacity(0.2); vtkIron->SetRepresentation(Vtk::Prop3D::Surface); viewer.AddProp3D(*vtkIron); // Visualize Top Chamber - Vtk::DetectorChamber* vtkTop = new Vtk::DetectorChamber(top_chamber_box); + Vtk::DetectorChamber* vtkTop = new Vtk::DetectorChamber(top_chamber_box.Get()); vtkTop->SetOpacity(0.5); vtkTop->SetColor(0.2, 0.8, 0.2); vtkTop->SetRepresentation(Vtk::Prop3D::Surface); viewer.AddProp3D(*vtkTop); // Visualize Bottom Chamber - Vtk::DetectorChamber* vtkBottom = new Vtk::DetectorChamber(bottom_chamber_box); + Vtk::DetectorChamber* vtkBottom = new Vtk::DetectorChamber(bottom_chamber_box.Get()); vtkBottom->SetOpacity(0.5); vtkBottom->SetColor(0.2, 0.8, 0.2); vtkBottom->SetRepresentation(Vtk::Prop3D::Surface); diff --git a/src/Vtk/HEP/Geant/testing/vtkSolidsTest.cpp b/src/Vtk/HEP/Geant/testing/vtkSolidsTest.cpp index 294c4a4..665b42d 100644 --- a/src/Vtk/HEP/Geant/testing/vtkSolidsTest.cpp +++ b/src/Vtk/HEP/Geant/testing/vtkSolidsTest.cpp @@ -25,53 +25,59 @@ using namespace uLib; int main(int argc, char** argv) { bool interactive = (argc > 1 && std::string(argv[1]) == "-i"); - // 1. Create a BoxSolid - ContainerBox box; - box.Scale(Vector3f(1_m, 2_m, 3_m)); - Geant::BoxSolid gBox("MyBox", &box); - gBox.Update(); - - Vtk::BoxSolid vtkBox(&gBox); - - // 2. Create a TessellatedSolid - Geant::TessellatedSolid gTess("MyTess"); - TriangleMesh mesh; - // Create a simple pyramid - mesh.Points().push_back(Vector3f(0, 0, 1_m)); // apex - mesh.Points().push_back(Vector3f(-1_m, -1_m, 0)); - mesh.Points().push_back(Vector3f( 1_m, -1_m, 0)); - mesh.Points().push_back(Vector3f( 1_m, 1_m, 0)); - mesh.Points().push_back(Vector3f(-1_m, 1_m, 0)); - - mesh.Triangles().push_back(Vector3i(1, 2, 0)); - mesh.Triangles().push_back(Vector3i(2, 3, 0)); - mesh.Triangles().push_back(Vector3i(3, 4, 0)); - mesh.Triangles().push_back(Vector3i(4, 1, 0)); - mesh.Triangles().push_back(Vector3i(1, 3, 2)); // base - mesh.Triangles().push_back(Vector3i(1, 4, 3)); // base - - gTess.SetMesh(mesh); - gTess.Update(); - - Vtk::TessellatedSolid vtkTess(&gTess); - // 3. Visualization setup Vtk::Viewer viewer; + + // 1. Create a BoxSolid + SmartPointer box(new ContainerBox()); + box->Scale(Vector3f(1_m, 2_m, 3_m)); + SmartPointer gBox(new Geant::BoxSolid("MyBox", box)); + gBox->Update(); + + SmartPointer lvBox(new Geant::LogicalVolume("BoxLV")); + lvBox->SetSolid(gBox); + SmartPointer pvBox(new Geant::PhysicalVolume("BoxPV", lvBox)); + Vtk::BoxSolid vtkBox(pvBox); vtkBox.AddToViewer(viewer); + + // 2. Create a TessellatedSolid + SmartPointer gTess(new Geant::TessellatedSolid("MyTess")); + SmartPointer mesh(new TriangleMesh()); + // ... same points ... + mesh->Points().push_back(Vector3f(0, 0, 1_m)); // apex + mesh->Points().push_back(Vector3f(-1_m, -1_m, 0)); + mesh->Points().push_back(Vector3f( 1_m, -1_m, 0)); + mesh->Points().push_back(Vector3f( 1_m, 1_m, 0)); + mesh->Points().push_back(Vector3f(-1_m, 1_m, 0)); + + mesh->Triangles().push_back(Vector3i(1, 2, 0)); + mesh->Triangles().push_back(Vector3i(2, 3, 0)); + mesh->Triangles().push_back(Vector3i(3, 4, 0)); + mesh->Triangles().push_back(Vector3i(4, 1, 0)); + mesh->Triangles().push_back(Vector3i(1, 3, 2)); // base + mesh->Triangles().push_back(Vector3i(1, 4, 3)); // base + + gTess->SetMesh(mesh.Get()); + gTess->Update(); + + SmartPointer lvTess(new Geant::LogicalVolume("TessLV")); + lvTess->SetSolid(gTess); + SmartPointer pvTess(new Geant::PhysicalVolume("TessPV", lvTess)); + Vtk::TessellatedSolid vtkTess(pvTess); vtkTess.AddToViewer(viewer); // Color them differently vtkBox.SetColor(0.8, 0.2, 0.2); // Redish box vtkTess.SetColor(0.2, 0.8, 0.2); // Greenish tess - // Position tessellated solid away from box + // Position tessellated solid away from box using the PhysicalVolume Matrix4f trans = Matrix4f::Identity(); trans.block<3,1>(0,3) = Vector3f(5_m, 0, 0); - gTess.SetTransform(trans); + pvTess->SetMatrix(trans); vtkTess.Update(); std::cout << "..:: Testing vtkSolidsTest ::.." << std::endl; - std::cout << "Box and Tessellated solids initialized." << std::endl; + std::cout << "Box and Tessellated solids (placed via PhysicalVolumes) initialized." << std::endl; if (interactive) { viewer.ZoomAuto(); diff --git a/src/Vtk/HEP/Geant/vtkBoxSolid.cpp b/src/Vtk/HEP/Geant/vtkBoxSolid.cpp index 5a0e871..3bc125b 100644 --- a/src/Vtk/HEP/Geant/vtkBoxSolid.cpp +++ b/src/Vtk/HEP/Geant/vtkBoxSolid.cpp @@ -24,8 +24,15 @@ namespace uLib { namespace Vtk { -BoxSolid::BoxSolid(Geant::BoxSolid *content) - : GeantSolid(content), m_BoxContent(content) { +BoxSolid::BoxSolid(Geant::PhysicalVolume *content) + : GeantSolid(content), m_BoxSolid(nullptr) { + if (content && content->GetLogical()) { + m_BoxSolid = dynamic_cast(content->GetLogical()->GetSolid()); + } +} + +BoxSolid::BoxSolid(Geant::BoxSolid *solid) + : GeantSolid(solid), m_BoxSolid(solid) { } BoxSolid::~BoxSolid() { @@ -35,10 +42,10 @@ void BoxSolid::serialize_display(uLib::Archive::display_properties_archive &ar, const unsigned int version) { // Expose Geant solid properties and underlying Box/TRS properties this->Prop3D::serialize_display(ar, version); - if (m_BoxContent) { - ar & NVP("Box", *m_BoxContent); - if (m_BoxContent->GetObject()) { - ar & NVP("Container", *m_BoxContent->GetObject()); + if (m_BoxSolid) { + ar & NVP("Box", *m_BoxSolid); + if (m_BoxSolid->GetObject()) { + ar & NVP("Container", *m_BoxSolid->GetObject()); } } } diff --git a/src/Vtk/HEP/Geant/vtkBoxSolid.h b/src/Vtk/HEP/Geant/vtkBoxSolid.h index 7a00df4..2c49d6e 100644 --- a/src/Vtk/HEP/Geant/vtkBoxSolid.h +++ b/src/Vtk/HEP/Geant/vtkBoxSolid.h @@ -45,7 +45,8 @@ class BoxSolid : public GeantSolid { uLibTypeMacro(BoxSolid, uLib::Vtk::GeantSolid) public: - BoxSolid(Geant::BoxSolid *content); + BoxSolid(Geant::PhysicalVolume *content); + BoxSolid(Geant::BoxSolid *solid); virtual ~BoxSolid(); virtual void serialize_display(uLib::Archive::display_properties_archive &ar, @@ -53,13 +54,13 @@ public: template void serialize(Ar &ar, const unsigned int version) { - ar & NVP("BoxSolid", *m_BoxContent); + ar & NVP("BoxSolid", *m_BoxSolid); } protected: virtual void InstallPipe() override; - Geant::BoxSolid *m_BoxContent; + Geant::BoxSolid *m_BoxSolid; ULIB_DECLARE_PROPERTIES(BoxSolid) }; diff --git a/src/Vtk/HEP/Geant/vtkGeantScene.cpp b/src/Vtk/HEP/Geant/vtkGeantScene.cpp index cf61301..49534d8 100644 --- a/src/Vtk/HEP/Geant/vtkGeantScene.cpp +++ b/src/Vtk/HEP/Geant/vtkGeantScene.cpp @@ -45,25 +45,29 @@ GeantScene::GeantScene(Geant::Scene *scene) m_WorldProp3D->ShowScaleMeasures(true); } - // 2. Create prop3ds for each non-world solid - const Geant::Solid *world = m_Scene->GetWorld(); - const Vector &solids = m_Scene->GetSolids(); + // 2. Create prop3ds for each physical volume in the scene + const Vector> &volumes = m_Scene->GetVolumes(); + + for (auto &volume : volumes) { + if (!volume || !volume->GetLogical() || !volume->GetLogical()->GetSolid()) + continue; + + Geant::PhysicalVolume *pv = volume.Get(); + Geant::Solid *solid = pv->GetLogical()->GetSolid(); - for (Geant::Solid *solid : solids) { // Skip the world volume itself — it's already shown as the wireframe box - if (solid == world) + if (solid == m_Scene->GetWorld()) continue; // Only create a prop3d if the solid has a valid G4VSolid if (solid->GetG4Solid()) { GeantSolid *vtkSolid = nullptr; if (auto *box = dynamic_cast(solid)) { - vtkSolid = new BoxSolid(box); + vtkSolid = new BoxSolid(pv); } else if (auto *tess = dynamic_cast(solid)) { - vtkSolid = new TessellatedSolid(tess); + vtkSolid = new TessellatedSolid(pv); } else { - vtkSolid = new GeantSolid(solid); - vtkSolid->Update(); + vtkSolid = new GeantSolid(pv); } if (vtkSolid) { diff --git a/src/Vtk/HEP/Geant/vtkGeantSolid.cpp b/src/Vtk/HEP/Geant/vtkGeantSolid.cpp index b5a0439..5fa29ce 100644 --- a/src/Vtk/HEP/Geant/vtkGeantSolid.cpp +++ b/src/Vtk/HEP/Geant/vtkGeantSolid.cpp @@ -44,15 +44,26 @@ namespace uLib { namespace Vtk { -GeantSolid::GeantSolid(Content *content) - : m_SolidActor(vtkActor::New()), m_Content(content) { +GeantSolid::GeantSolid(Geant::PhysicalVolume *content) + : m_SolidActor(vtkActor::New()), m_Volume(content), m_Solid(nullptr) { this->InstallPipe(); - if (m_Content) { - m_UpdateConnection = Object::connect(m_Content, &uLib::Object::Updated, [this]() { - std::cout << "GeantSolid: Signal Updated received." << std::endl; + if (m_Volume) { + m_UpdateConnection = Object::connect(m_Volume, &uLib::Object::Updated, [this]() { this->Update(); }); - // Mandatory initial update to generate geometry and apply initial transform + // Mandatory initial update + this->Update(); + } +} + +GeantSolid::GeantSolid(Geant::Solid *solid) + : m_SolidActor(vtkActor::New()), m_Volume(nullptr), m_Solid(solid) { + this->InstallPipe(); + if (m_Solid) { + m_UpdateConnection = Object::connect(m_Solid, &uLib::Object::Updated, [this]() { + this->Update(); + }); + // Mandatory initial update this->Update(); } } @@ -75,21 +86,25 @@ void GeantSolid::Update() { } void GeantSolid::SyncFromVtk() { - if (!m_Content) return; + if (!m_Volume) return; this->Prop3D::SyncFromVtk(); if (auto* proxy = vtkProp3D::SafeDownCast(this->GetProxyProp())) { if (vtkMatrix4x4* mat = proxy->GetUserMatrix()) { - m_Content->SetTransform(VtkToMatrix4f(mat)); + m_Volume->SetMatrix(VtkToMatrix4f(mat)); } } } void GeantSolid::UpdateGeometry() { - if (!m_Content) - return; + Geant::Solid *solid = m_Solid; + if (m_Volume && m_Volume->GetLogical()) { + solid = m_Volume->GetLogical()->GetSolid(); + } - G4VSolid *g4solid = m_Content->GetG4Solid(); + if (!solid) return; + + G4VSolid *g4solid = solid->GetG4Solid(); if (!g4solid) return; @@ -134,39 +149,20 @@ void GeantSolid::UpdateGeometry() { } void GeantSolid::UpdateTransform() { - if (!m_Content || !m_SolidActor) + if (!m_SolidActor) return; - // Apply the Geant4 transform (position/rotation/scaling) - G4ThreeVector pos = m_Content->GetPosition(); - const G4RotationMatrix *rot = m_Content->GetRotation(); - G4ThreeVector scale = m_Content->GetScaling(); - - std::cout << "GeantSolid: Updating transform. Pos: " << pos.x() << " " << pos.y() << " " << pos.z() - << " Scale: " << scale.x() << " " << scale.y() << " " << scale.z() << std::endl; - - vtkNew transform; - transform->Identity(); - transform->Translate(pos.x(), pos.y(), pos.z()); - - if (rot) { - G4RotationMatrix invRot = *rot; - 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 - }; - vtkNew mat; - mat->DeepCopy(elements); - transform->Concatenate(mat); - } - - transform->Scale(scale.x(), scale.y(), scale.z()); - - m_SolidActor->SetUserTransform(transform); - m_SolidActor->Modified(); + if (m_Volume) { + // Apply the TRS transform directly from the PhysicalVolume + vtkNew vtkMat; + Matrix4fToVtk(m_Volume->GetMatrix(), vtkMat); + m_SolidActor->SetUserMatrix(vtkMat); + } else { + // Identity for unplaced solids + m_SolidActor->SetUserMatrix(nullptr); } + m_SolidActor->Modified(); +} void GeantSolid::InstallPipe() { vtkSmartPointer polyData = vtkSmartPointer::New(); diff --git a/src/Vtk/HEP/Geant/vtkGeantSolid.h b/src/Vtk/HEP/Geant/vtkGeantSolid.h index 626c820..f4cd136 100644 --- a/src/Vtk/HEP/Geant/vtkGeantSolid.h +++ b/src/Vtk/HEP/Geant/vtkGeantSolid.h @@ -43,10 +43,9 @@ namespace Vtk { * a valid G4VSolid via GetG4Solid(). */ class GeantSolid : public Prop3D, public Polydata { - typedef Geant::Solid Content; - public: - GeantSolid(Content *content); + GeantSolid(Geant::PhysicalVolume *content); + GeantSolid(Geant::Solid *solid); ~GeantSolid(); virtual class vtkPolyData *GetPolyData() const override; @@ -57,14 +56,17 @@ public: virtual void UpdateGeometry(); virtual void UpdateTransform(); - virtual uLib::Object *GetContent() const override { return (uLib::Object*)m_Content; } + virtual uLib::Object *GetContent() const override { + return m_Volume ? (uLib::Object*)m_Volume : (uLib::Object*)m_Solid; + } protected: virtual void InstallPipe(); - Content *m_Content; - vtkActor *m_SolidActor; - uLib::Connection m_UpdateConnection; + Geant::PhysicalVolume *m_Volume; + Geant::Solid *m_Solid; + vtkActor *m_SolidActor; + uLib::Connection m_UpdateConnection; }; } // namespace Vtk diff --git a/src/Vtk/HEP/Geant/vtkTessellatedSolid.cpp b/src/Vtk/HEP/Geant/vtkTessellatedSolid.cpp index 1ec807c..a0cd730 100644 --- a/src/Vtk/HEP/Geant/vtkTessellatedSolid.cpp +++ b/src/Vtk/HEP/Geant/vtkTessellatedSolid.cpp @@ -18,9 +18,11 @@ namespace uLib { namespace Vtk { -TessellatedSolid::TessellatedSolid(Geant::TessellatedSolid *content) - : GeantSolid(content), m_TessContent(content) { - this->Update(); +TessellatedSolid::TessellatedSolid(Geant::PhysicalVolume *content) + : GeantSolid(content), m_TessSolid(nullptr) { + if (content && content->GetLogical()) { + m_TessSolid = dynamic_cast(content->GetLogical()->GetSolid()); + } } TessellatedSolid::~TessellatedSolid() {} @@ -31,13 +33,13 @@ void TessellatedSolid::Update() { } void TessellatedSolid::UpdateGeometry() { - if (!m_TessContent || m_TessContent->GetMesh().Points().empty()) { + if (!m_TessSolid || !m_TessSolid->GetMesh() || m_TessSolid->GetMesh()->Points().empty()) { // Fallback to base tessellation if no model mesh GeantSolid::UpdateGeometry(); return; } - const TriangleMesh &mesh = m_TessContent->GetMesh(); + const TriangleMesh &mesh = *m_TessSolid->GetMesh(); vtkNew points; for (const auto& pt : mesh.Points()) { diff --git a/src/Vtk/HEP/Geant/vtkTessellatedSolid.h b/src/Vtk/HEP/Geant/vtkTessellatedSolid.h index 9a93989..eed0339 100644 --- a/src/Vtk/HEP/Geant/vtkTessellatedSolid.h +++ b/src/Vtk/HEP/Geant/vtkTessellatedSolid.h @@ -22,14 +22,14 @@ namespace Vtk { */ class TessellatedSolid : public GeantSolid { public: - TessellatedSolid(Geant::TessellatedSolid *content); + TessellatedSolid(Geant::PhysicalVolume *content); virtual ~TessellatedSolid(); virtual void Update() override; virtual void UpdateGeometry() override; protected: - Geant::TessellatedSolid *m_TessContent; + Geant::TessellatedSolid *m_TessSolid; }; } // namespace Vtk diff --git a/src/Vtk/vtkObjectsContext.cpp b/src/Vtk/vtkObjectsContext.cpp index 1931f77..cbda114 100644 --- a/src/Vtk/vtkObjectsContext.cpp +++ b/src/Vtk/vtkObjectsContext.cpp @@ -6,6 +6,7 @@ #include "Vtk/HEP/Detectors/vtkDetectorChamber.h" #include "Vtk/HEP/Geant/vtkBoxSolid.h" +#include "Vtk/HEP/Geant/vtkTessellatedSolid.h" #include #include @@ -150,8 +151,20 @@ Prop3D *ObjectsContext::CreateProp3D(uLib::Object *obj) { return new Cylinder(cylinder); } else if (auto *assembly = dynamic_cast(obj)) { return new Assembly(assembly); + } else if (auto *pv = dynamic_cast(obj)) { + uLib::Geant::Solid *solid = pv->GetLogical()->GetSolid(); + if (auto *box = dynamic_cast(solid)) { + return new BoxSolid(pv); + } else if (auto *tess = dynamic_cast(solid)) { + return new TessellatedSolid(pv); + } else { + return new GeantSolid(pv); + } } else if (auto *box = dynamic_cast(obj)) { return new BoxSolid(box); + } else if (auto *solid = dynamic_cast(obj)) { + // Unplaced solid visualization + return new GeantSolid(solid); } // Fallback if we don't know the exact class but it might be a context itself