add vtk solids

This commit is contained in:
AndreaRigoni
2026-03-25 21:03:13 +00:00
parent e4a8499104
commit 422113a0e9
17 changed files with 353 additions and 16 deletions

View File

@@ -151,6 +151,7 @@ TessellatedSolid::TessellatedSolid(const char *name)
}
void TessellatedSolid::SetMesh(TriangleMesh &mesh) {
this->m_Mesh = mesh;
G4TessellatedSolid *ts = this->m_Solid;
for (int i = 0; i < mesh.Triangles().size(); ++i) {
const Vector3i &trg = mesh.Triangles().at(i);
@@ -165,6 +166,9 @@ void TessellatedSolid::SetMesh(TriangleMesh &mesh) {
}
}
void TessellatedSolid::Update() {
}

View File

@@ -93,11 +93,14 @@ public:
void SetMesh(TriangleMesh &mesh);
uLibGetMacro(Solid, G4TessellatedSolid *)
virtual G4VSolid* GetG4Solid() const override { return (G4VSolid*)m_Solid; }
const TriangleMesh& GetMesh() const { return m_Mesh; }
public slots:
void Update();
private :
TriangleMesh m_Mesh;
G4TessellatedSolid *m_Solid;
};

View File

@@ -52,7 +52,9 @@ public:
Vector3f GetPoint(const Id_t id) const;
inline std::vector<Vector3f> & Points() { return this->m_Points; }
inline const std::vector<Vector3f> & Points() const { return this->m_Points; }
inline std::vector<Vector4i> & Quads() { return this->m_Quads; }
inline const std::vector<Vector4i> & Quads() const { return this->m_Quads; }
const Vector4i & GetQuad(const Id_t id) const { return m_Quads.at(id); }
Vector3f GetNormal(const Id_t id) const;

View File

@@ -55,7 +55,9 @@ public:
Vector3f GetPoint(const Id_t id) const;
inline std::vector<Vector3f> & Points() { return this->m_Points; }
inline const std::vector<Vector3f> & Points() const { return this->m_Points; }
inline std::vector<Vector3i> & Triangles() { return this->m_Triangles; }
inline const std::vector<Vector3i> & Triangles() const { return this->m_Triangles; }
const Vector3i & GetTriangle(const Id_t id) const { return m_Triangles.at(id); }
Vector3f GetNormal(const Id_t id) const;

View File

@@ -432,9 +432,9 @@ void init_math(py::module_ &m) {
.def("AddPoint", &TriangleMesh::AddPoint)
.def("AddTriangle",
py::overload_cast<const Vector3i &>(&TriangleMesh::AddTriangle))
.def("Points", &TriangleMesh::Points,
.def("Points", py::overload_cast<>(&TriangleMesh::Points),
py::return_value_policy::reference_internal)
.def("Triangles", &TriangleMesh::Triangles,
.def("Triangles", py::overload_cast<>(&TriangleMesh::Triangles),
py::return_value_policy::reference_internal)
.def("GetTriangle", &TriangleMesh::GetTriangle)
.def("GetNormal", &TriangleMesh::GetNormal);
@@ -444,9 +444,9 @@ void init_math(py::module_ &m) {
.def("AddPoint", &QuadMesh::AddPoint)
.def("AddQuad",
py::overload_cast<const Vector4i &>(&QuadMesh::AddQuad))
.def("Points", &QuadMesh::Points,
.def("Points", py::overload_cast<>(&QuadMesh::Points),
py::return_value_policy::reference_internal)
.def("Quads", &QuadMesh::Quads,
.def("Quads", py::overload_cast<>(&QuadMesh::Quads),
py::return_value_policy::reference_internal)
.def("GetQuad", &QuadMesh::GetQuad)
.def("GetNormal", &QuadMesh::GetNormal);

View File

@@ -6,6 +6,8 @@
set(HEP_GEANT_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/vtkGeantEvent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/vtkGeantSolid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/vtkBoxSolid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/vtkTessellatedSolid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/vtkGeantScene.cpp
${CMAKE_CURRENT_SOURCE_DIR}/vtkEmitterPrimary.cpp
PARENT_SCOPE)
@@ -13,6 +15,8 @@ set(HEP_GEANT_SOURCES
set(HEP_GEANT_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/vtkGeantEvent.h
${CMAKE_CURRENT_SOURCE_DIR}/vtkGeantSolid.h
${CMAKE_CURRENT_SOURCE_DIR}/vtkBoxSolid.h
${CMAKE_CURRENT_SOURCE_DIR}/vtkTessellatedSolid.h
${CMAKE_CURRENT_SOURCE_DIR}/vtkGeantScene.h
${CMAKE_CURRENT_SOURCE_DIR}/vtkEmitterPrimary.h
PARENT_SCOPE)

View File

@@ -2,6 +2,7 @@
set(TESTS
vtkGeantEventTest
vtkGeantSceneTest
vtkSolidsTest
vtkEmitterPrimaryTest
vtkSkyPlaneEmitterPrimaryTest
vtkCylinderEmitterPrimaryTest

View File

@@ -0,0 +1,84 @@
/*//////////////////////////////////////////////////////////////////////////////
// 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 "Vtk/HEP/Geant/vtkBoxSolid.h"
#include "Vtk/HEP/Geant/vtkTessellatedSolid.h"
#include "Vtk/uLibVtkViewer.h"
#include "HEP/Geant/Solid.h"
#include "Math/ContainerBox.h"
#include "Math/TriangleMesh.h"
#include "Math/Units.h"
#include <vtkProperty.h>
#include <vtkActor.h>
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::vtkBoxSolid 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::vtkTessellatedSolid vtkTess(&gTess);
// 3. Visualization setup
Vtk::Viewer viewer;
vtkBox.AddToViewer(viewer);
vtkTess.AddToViewer(viewer);
// Color them differently
vtkActor::SafeDownCast(vtkBox.GetProp())->GetProperty()->SetColor(0.8, 0.2, 0.2); // Redish box
vtkActor::SafeDownCast(vtkTess.GetProp())->GetProperty()->SetColor(0.2, 0.8, 0.2); // Greenish tess
// Position tessellated solid away from box
Matrix4f trans = Matrix4f::Identity();
trans.block<3,1>(0,3) = Vector3f(5_m, 0, 0);
gTess.SetTransform(trans);
vtkTess.Update();
std::cout << "..:: Testing vtkSolidsTest ::.." << std::endl;
std::cout << "Box and Tessellated solids initialized." << std::endl;
if (interactive) {
viewer.ZoomAuto();
viewer.Start();
} else {
std::cout << "Non-interactive test passed." << std::endl;
}
return 0;
}

View File

@@ -0,0 +1,57 @@
/*//////////////////////////////////////////////////////////////////////////////
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Copyright (c) 2014, Universita' degli Studi Padova, INFN sez. di Padova
All rights reserved
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
//////////////////////////////////////////////////////////////////////////////*/
#include "vtkBoxSolid.h"
#include <vtkCubeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
namespace uLib {
namespace Vtk {
vtkBoxSolid::vtkBoxSolid(Geant::BoxSolid *content)
: vtkGeantSolid(content), m_BoxContent(content) {
// Re-run Update for box-specific pipe
this->Update();
}
vtkBoxSolid::~vtkBoxSolid() {}
void vtkBoxSolid::Update() {
this->UpdateGeometry();
this->UpdateTransform();
}
void vtkBoxSolid::UpdateGeometry() {
if (!m_BoxContent || !m_BoxContent->GetObject()) {
// Fallback to base tessellation if no model object
vtkGeantSolid::UpdateGeometry();
return;
}
// Use the underlying ContainerBox for precise geometry
Vector3f size = m_BoxContent->GetObject()->GetSize();
vtkNew<vtkCubeSource> cube;
cube->SetXLength(size(0));
cube->SetYLength(size(1));
cube->SetZLength(size(2));
cube->Update();
vtkPolyData *poly = GetPolyData();
if (poly) {
poly->ShallowCopy(cube->GetOutput());
poly->Modified();
}
}
} // namespace Vtk
} // namespace uLib

View File

@@ -0,0 +1,52 @@
/*//////////////////////////////////////////////////////////////////////////////
// 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_VTKBOXSOLID_H
#define U_VTKBOXSOLID_H
#include "vtkGeantSolid.h"
namespace uLib {
namespace Vtk {
/**
* @brief VTK Puppet for visualizing a Geant::BoxSolid.
*/
class vtkBoxSolid : public vtkGeantSolid {
public:
vtkBoxSolid(Geant::BoxSolid *content);
virtual ~vtkBoxSolid();
virtual void Update() override;
virtual void UpdateGeometry() override;
protected:
Geant::BoxSolid *m_BoxContent;
};
} // namespace Vtk
} // namespace uLib
#endif // U_VTKBOXSOLID_H

View File

@@ -25,6 +25,8 @@
#include "vtkGeantScene.h"
#include "vtkGeantSolid.h"
#include "vtkBoxSolid.h"
#include "vtkTessellatedSolid.h"
#include "Vtk/vtkViewport.h"
namespace uLib {
@@ -54,8 +56,19 @@ vtkGeantScene::vtkGeantScene(Geant::Scene *scene)
// Only create a puppet if the solid has a valid G4VSolid
if (solid->GetG4Solid()) {
vtkGeantSolid *vtkSolid = new vtkGeantSolid(solid);
m_SolidPuppets.push_back(vtkSolid);
vtkGeantSolid *vtkSolid = nullptr;
if (auto *box = dynamic_cast<Geant::BoxSolid *>(solid)) {
vtkSolid = new vtkBoxSolid(box);
} else if (auto *tess = dynamic_cast<Geant::TessellatedSolid *>(solid)) {
vtkSolid = new vtkTessellatedSolid(tess);
} else {
vtkSolid = new vtkGeantSolid(solid);
vtkSolid->Update();
}
if (vtkSolid) {
m_SolidPuppets.push_back(vtkSolid);
}
}
}
}

View File

@@ -45,7 +45,6 @@ namespace Vtk {
vtkGeantSolid::vtkGeantSolid(Content *content)
: m_SolidActor(vtkActor::New()), m_Content(content) {
this->InstallPipe();
this->Update();
}
vtkGeantSolid::~vtkGeantSolid() {
@@ -59,6 +58,11 @@ vtkPolyData *vtkGeantSolid::GetPolyData() const {
}
void vtkGeantSolid::Update() {
this->UpdateGeometry();
this->UpdateTransform();
}
void vtkGeantSolid::UpdateGeometry() {
if (!m_Content)
return;
@@ -103,6 +107,11 @@ void vtkGeantSolid::Update() {
polyData->SetPolys(polys);
polyData->Modified();
}
}
void vtkGeantSolid::UpdateTransform() {
if (!m_Content || !m_SolidActor)
return;
// Apply the Geant4 transform (position/rotation) if placed
if (m_Content->GetPhysical()) {

View File

@@ -51,7 +51,10 @@ public:
virtual class vtkPolyData *GetPolyData() const override;
virtual void Update();
virtual void Update() override;
virtual void UpdateGeometry();
virtual void UpdateTransform();
protected:
virtual void InstallPipe();

View File

@@ -0,0 +1,62 @@
/*//////////////////////////////////////////////////////////////////////////////
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Copyright (c) 2014, Universita' degli Studi Padova, INFN sez. di Padova
All rights reserved
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
//////////////////////////////////////////////////////////////////////////////*/
#include "vtkTessellatedSolid.h"
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkPolyData.h>
namespace uLib {
namespace Vtk {
vtkTessellatedSolid::vtkTessellatedSolid(Geant::TessellatedSolid *content)
: vtkGeantSolid(content), m_TessContent(content) {
this->Update();
}
vtkTessellatedSolid::~vtkTessellatedSolid() {}
void vtkTessellatedSolid::Update() {
this->UpdateGeometry();
this->UpdateTransform();
}
void vtkTessellatedSolid::UpdateGeometry() {
if (!m_TessContent || m_TessContent->GetMesh().Points().empty()) {
// Fallback to base tessellation if no model mesh
vtkGeantSolid::UpdateGeometry();
return;
}
const TriangleMesh &mesh = m_TessContent->GetMesh();
vtkNew<vtkPoints> points;
for (const auto& pt : mesh.Points()) {
points->InsertNextPoint(pt(0), pt(1), pt(2));
}
vtkNew<vtkCellArray> polys;
for (const auto& trg : mesh.Triangles()) {
vtkIdType ids[3] = { (vtkIdType)trg(0), (vtkIdType)trg(1), (vtkIdType)trg(2) };
polys->InsertNextCell(3, ids);
}
vtkPolyData *poly = GetPolyData();
if (poly) {
poly->SetPoints(points);
poly->SetPolys(polys);
poly->Modified();
}
}
} // namespace Vtk
} // namespace uLib

View File

@@ -0,0 +1,38 @@
/*//////////////////////////////////////////////////////////////////////////////
// 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 >
//////////////////////////////////////////////////////////////////////////////*/
#ifndef U_VTKTESSELLATEDSOLID_H
#define U_VTKTESSELLATEDSOLID_H
#include "vtkGeantSolid.h"
namespace uLib {
namespace Vtk {
/**
* @brief VTK Puppet for visualizing a Geant::TessellatedSolid.
*/
class vtkTessellatedSolid : public vtkGeantSolid {
public:
vtkTessellatedSolid(Geant::TessellatedSolid *content);
virtual ~vtkTessellatedSolid();
virtual void Update() override;
virtual void UpdateGeometry() override;
protected:
Geant::TessellatedSolid *m_TessContent;
};
} // namespace Vtk
} // namespace uLib
#endif // U_VTKTESSELLATEDSOLID_H

View File

@@ -39,11 +39,11 @@
#include <string>
#include <vtkVersion.h>
#include <vtkProp.h>
#include <vtkActor.h>
#include <vtkSmartPointer.h>
#include "vtkViewport.h"
#include "uLibVtkInterface.h"
#include <vtkActor.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkPropCollection.h>
#include <vtkProp3DCollection.h>
#include <vtkRendererCollection.h>
@@ -278,14 +278,14 @@ void Puppet::DisconnectRenderer(vtkRenderer *renderer)
}
}
void Puppet::ConnectViewer(Viewer *viewer)
void Puppet::AddToViewer(Viewport &viewer)
{
// TODO
viewer.AddPuppet(*this);
}
void Puppet::DisonnectViewer(Viewer *viewer)
void Puppet::RemoveFromViewer(Viewport &viewer)
{
// TODO
viewer.RemovePuppet(*this);
}
vtkRendererCollection *Puppet::GetRenderers() const

View File

@@ -107,6 +107,9 @@ public:
virtual void ConnectInteractor(class vtkRenderWindowInteractor *interactor);
void AddToViewer(class Viewport &viewer);
void RemoveFromViewer(class Viewport &viewer);
protected:
void SetProp(vtkProp *prop);