3 Commits

20 changed files with 341 additions and 171 deletions

3
.gitignore vendored
View File

@@ -20,3 +20,6 @@ test_boost.cpp
.claude/settings.json .claude/settings.json
build_output.log build_output.log
configure_output.log configure_output.log
test.xml
test_ref_smartpointer.xml
test_ref.xml

View File

@@ -42,6 +42,8 @@ TODO:
#include <boost/mpl/for_each.hpp> #include <boost/mpl/for_each.hpp>
#include <boost/mpl/remove_if.hpp> #include <boost/mpl/remove_if.hpp>
#include <boost/serialization/nvp.hpp> #include <boost/serialization/nvp.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/unique_ptr.hpp>
// #include <boost/archive/xml_iarchive.hpp> // #include <boost/archive/xml_iarchive.hpp>
// #include <boost/archive/xml_oarchive.hpp> // #include <boost/archive/xml_oarchive.hpp>

View File

@@ -36,6 +36,9 @@
#include <boost/serialization/vector.hpp> #include <boost/serialization/vector.hpp>
#include <boost/serialization/string.hpp> #include <boost/serialization/string.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/nvp.hpp>
namespace uLib { namespace uLib {
/** /**
@@ -53,8 +56,13 @@ public:
/** /**
* @brief Default constructor. * @brief Default constructor.
* Allocates a new T following legacy behavior.
*/ */
SmartPointer() noexcept : m_counter(nullptr) {} SmartPointer() : m_counter(nullptr) {
if constexpr (std::is_default_constructible_v<T>) {
m_counter = new ReferenceCounter(new T());
}
}
/** /**
* @brief Constructor from nullptr. * @brief Constructor from nullptr.
@@ -216,6 +224,7 @@ public:
private: private:
friend class boost::serialization::access; friend class boost::serialization::access;
struct ReferenceCounter { struct ReferenceCounter {
T* ptr; T* ptr;
std::atomic<uint32_t> count; std::atomic<uint32_t> count;
@@ -228,7 +237,8 @@ private:
ReferenceCounter(T* p, D d, uint32_t initial_count = 1) ReferenceCounter(T* p, D d, uint32_t initial_count = 1)
: ptr(p), count(initial_count), deleter(d) {} : ptr(p), count(initial_count), deleter(d) {}
ReferenceCounter() : ptr(nullptr), count(0) {} ReferenceCounter()
: ptr(nullptr), count(0), deleter([](T* p) { delete p; }) {}
private: private:
friend class boost::serialization::access; friend class boost::serialization::access;

View File

@@ -172,6 +172,26 @@ ULIB_SERIALIZE_OBJECT(B, Object) {
class C : public virtual Object {
uLibTypeMacro(C, Object)
ULIB_SERIALIZE_ACCESS
public:
C() : m_c(1234566) {}
int m_c;
// reference to A (serializes through ID)
SmartPointer<A> m_a;
};
ULIB_SERIALIZABLE_OBJECT(C)
ULIB_SERIALIZE_OBJECT(C, Object) {
ar & "Object C : " & "--> m_c = " & AR(m_c) & "--> m_a = " & AR(m_a);
}
int test_referece_serialization() { int test_referece_serialization() {
A a; A a;
{ {
@@ -193,7 +213,25 @@ int test_referece_serialization() {
return (b.m_a->a() == a.a() && b2.m_a->a() == a.a()); return (b.m_a->a() == a.a() && b2.m_a->a() == a.a());
} }
int test_referece_smartpointer_serialization() {
SmartPointer<A> a;
a->init_properties();
{
C c, c2; c.m_a = a; c2.m_a = a;
std::ofstream file("test_ref_smartpointer.xml");
Archive::xml_oarchive(file) << NVP(c) << NVP(c2);
}
C c, c2;
{
std::ifstream file("test_ref_smartpointer.xml");
Archive::xml_iarchive(file) >> NVP(c) >> NVP(c2);
}
return (c.m_a->a() == a->a() && c2.m_a->a() == a->a());
}
int main() { int main() {
@@ -202,6 +240,7 @@ int main() {
TEST1(test_V3f()); TEST1(test_V3f());
TEST1(testing_xml_class()); TEST1(testing_xml_class());
TEST1(test_referece_serialization()); TEST1(test_referece_serialization());
TEST1(test_referece_smartpointer_serialization());
// TEST1(testing_hrt_class()); // TEST1(testing_hrt_class());
END_TESTING; END_TESTING;

View File

@@ -127,6 +127,10 @@ const Vector<Solid*>& Scene::GetSolids() const {
return d->m_Solids; return d->m_Solids;
} }
const Vector<SmartPointer<PhysicalVolume>>& Scene::GetVolumes() const {
return d->m_Volumes;
}
void Scene::ConstructWorldBox(const Vector3f &size, const char *materialName) { void Scene::ConstructWorldBox(const Vector3f &size, const char *materialName) {
d->m_WorldBox->SetSize(size); d->m_WorldBox->SetSize(size);

View File

@@ -60,6 +60,9 @@ public:
/// Get the list of solids in the scene /// Get the list of solids in the scene
const Vector<Solid*>& GetSolids() const; const Vector<Solid*>& GetSolids() const;
/// Get the list of physical volumes in the scene
const Vector<SmartPointer<PhysicalVolume>>& GetVolumes() const;
/// Set the primary generator (emitter) for the simulation. /// Set the primary generator (emitter) for the simulation.
/// The Scene does NOT take ownership of the emitter. /// The Scene does NOT take ownership of the emitter.
void SetEmitter(EmitterPrimary *emitter); void SetEmitter(EmitterPrimary *emitter);

View File

@@ -75,13 +75,23 @@ int main(int argc, char** argv) {
Geant::Scene scene; Geant::Scene scene;
scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR"); scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR");
ContainerBox iron_box; // Iron Cube
iron_box.Scale(Vector3f(10_m, 10_m, 10_m)); SmartPointer<ContainerBox> iron_box(new ContainerBox());
iron_box.SetPosition(Vector3f(0, 0, 0)); iron_box->Scale(Vector3f(10_m, 10_m, 10_m));
Geant::BoxSolid* iron_cube = new Geant::BoxSolid("IronCube", &iron_box); iron_box->SetPosition(Vector3f(0, 0, 0));
iron_cube->SetNistMaterial("G4_Fe");
iron_cube->Update(); SmartPointer<Geant::BoxSolid> iron_solid(new Geant::BoxSolid("IronSolid", iron_box));
scene.AddSolid(iron_cube); iron_solid->Update();
SmartPointer<Geant::Material> iron_mat(new Geant::Material("IronMat"));
iron_mat->SetFromNist("G4_Fe");
SmartPointer<Geant::LogicalVolume> iron_lv(new Geant::LogicalVolume("IronLV"));
iron_lv->SetSolid(iron_solid);
iron_lv->SetMaterial(iron_mat);
SmartPointer<Geant::PhysicalVolume> iron_pv(new Geant::PhysicalVolume("IronPV", iron_lv));
scene.AddVolume(iron_pv);
// Use CylinderEmitterPrimary // Use CylinderEmitterPrimary
Geant::CylinderEmitterPrimary* emitter = new Geant::CylinderEmitterPrimary(); Geant::CylinderEmitterPrimary* emitter = new Geant::CylinderEmitterPrimary();
@@ -103,7 +113,7 @@ int main(int argc, char** argv) {
vtkWorld->SetSelectable(false); vtkWorld->SetSelectable(false);
viewer.AddProp3D(*vtkWorld); 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->SetOpacity(0.2);
vtkIron->SetRepresentation(Vtk::Prop3D::Surface); vtkIron->SetRepresentation(Vtk::Prop3D::Surface);
viewer.AddProp3D(*vtkIron); viewer.AddProp3D(*vtkIron);

View File

@@ -69,31 +69,56 @@ int main(int argc, char** argv) {
Geant::Scene scene; Geant::Scene scene;
scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR"); scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR");
ContainerBox iron_box; // Iron Cube
iron_box.Scale(Vector3f(10_m, 10_m, 10_m)); SmartPointer<ContainerBox> iron_box(new ContainerBox());
iron_box.SetPosition(Vector3f(-5_m, -5_m, -5_m)); iron_box->Scale(Vector3f(10_m, 10_m, 10_m));
Geant::BoxSolid* iron_cube = new Geant::BoxSolid("IronCube", &iron_box); iron_box->SetPosition(Vector3f(-5_m, -5_m, -5_m));
iron_cube->SetNistMaterial("G4_Fe");
iron_cube->Update(); SmartPointer<Geant::BoxSolid> iron_solid(new Geant::BoxSolid("IronSolid", iron_box));
scene.AddSolid(iron_cube); iron_solid->Update();
SmartPointer<Geant::Material> iron_mat(new Geant::Material("IronMat"));
iron_mat->SetFromNist("G4_Fe");
SmartPointer<Geant::LogicalVolume> iron_lv(new Geant::LogicalVolume("IronLV"));
iron_lv->SetSolid(iron_solid);
iron_lv->SetMaterial(iron_mat);
SmartPointer<Geant::PhysicalVolume> iron_pv(new Geant::PhysicalVolume("IronPV", iron_lv));
scene.AddVolume(iron_pv);
// Top Detector Chamber // Top Detector Chamber
DetectorChamber* top_chamber_box = new DetectorChamber(); SmartPointer<DetectorChamber> top_chamber_box(new DetectorChamber());
top_chamber_box->Scale(Vector3f(10_m, 10_m, 40_cm)); top_chamber_box->Scale(Vector3f(10_m, 10_m, 40_cm));
top_chamber_box->SetPosition(Vector3f(-5_m, -5_m, 7_m)); 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"); SmartPointer<Geant::BoxSolid> top_solid(new Geant::BoxSolid("TopSolid", top_chamber_box));
top_chamber->Update(); top_solid->Update();
scene.AddSolid(top_chamber);
SmartPointer<Geant::Material> air_mat(new Geant::Material("AirMat"));
air_mat->SetFromNist("G4_AIR");
SmartPointer<Geant::LogicalVolume> top_lv(new Geant::LogicalVolume("TopLV"));
top_lv->SetSolid(top_solid);
top_lv->SetMaterial(air_mat);
SmartPointer<Geant::PhysicalVolume> top_pv(new Geant::PhysicalVolume("TopPV", top_lv));
scene.AddVolume(top_pv);
// Bottom Detector Chamber // Bottom Detector Chamber
DetectorChamber* bottom_chamber_box = new DetectorChamber(); SmartPointer<DetectorChamber> bottom_chamber_box(new DetectorChamber());
bottom_chamber_box->Scale(Vector3f(10_m, 10_m, 40_cm)); bottom_chamber_box->Scale(Vector3f(10_m, 10_m, 40_cm));
bottom_chamber_box->SetPosition(Vector3f(-5_m, -5_m, -7.1_m)); 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"); SmartPointer<Geant::BoxSolid> bottom_solid(new Geant::BoxSolid("BottomSolid", bottom_chamber_box));
bottom_chamber->Update(); bottom_solid->Update();
scene.AddSolid(bottom_chamber);
SmartPointer<Geant::LogicalVolume> bottom_lv(new Geant::LogicalVolume("BottomLV"));
bottom_lv->SetSolid(bottom_solid);
bottom_lv->SetMaterial(air_mat);
SmartPointer<Geant::PhysicalVolume> bottom_pv(new Geant::PhysicalVolume("BottomPV", bottom_lv));
scene.AddVolume(bottom_pv);
Geant::EmitterPrimary* emitter = new Geant::EmitterPrimary(); Geant::EmitterPrimary* emitter = new Geant::EmitterPrimary();
emitter->SetPosition(Vector3f(0, 0, 14_m)); emitter->SetPosition(Vector3f(0, 0, 14_m));
@@ -112,20 +137,20 @@ int main(int argc, char** argv) {
viewer.AddProp3D(*vtkWorld); viewer.AddProp3D(*vtkWorld);
// Visualize iron cube // 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->SetOpacity(0.2);
vtkIron->SetRepresentation(Vtk::Prop3D::Surface); vtkIron->SetRepresentation(Vtk::Prop3D::Surface);
viewer.AddProp3D(*vtkIron); viewer.AddProp3D(*vtkIron);
// Visualize Top Chamber // 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->SetOpacity(0.5);
vtkTop->SetColor(0.2, 0.8, 0.2); vtkTop->SetColor(0.2, 0.8, 0.2);
vtkTop->SetRepresentation(Vtk::Prop3D::Surface); vtkTop->SetRepresentation(Vtk::Prop3D::Surface);
viewer.AddProp3D(*vtkTop); viewer.AddProp3D(*vtkTop);
// Visualize Bottom Chamber // 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->SetOpacity(0.5);
vtkBottom->SetColor(0.2, 0.8, 0.2); vtkBottom->SetColor(0.2, 0.8, 0.2);
vtkBottom->SetRepresentation(Vtk::Prop3D::Surface); vtkBottom->SetRepresentation(Vtk::Prop3D::Surface);

View File

@@ -100,13 +100,22 @@ int main(int argc, char** argv) {
Geant::Scene scene; Geant::Scene scene;
scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR"); scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR");
ContainerBox iron_box; SmartPointer<ContainerBox> iron_box(new ContainerBox());
iron_box.Scale(Vector3f(10_m, 10_m, 10_m)); iron_box->Scale(Vector3f(10_m, 10_m, 10_m));
iron_box.SetPosition(Vector3f(-5_m, -5_m, -5_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"); SmartPointer<Geant::BoxSolid> iron_solid(new Geant::BoxSolid("IronSolid", iron_box));
iron_cube->Update(); iron_solid->Update();
scene.AddSolid(iron_cube);
SmartPointer<Geant::Material> iron_mat(new Geant::Material("IronMat"));
iron_mat->SetFromNist("G4_Fe");
SmartPointer<Geant::LogicalVolume> iron_lv(new Geant::LogicalVolume("IronLV"));
iron_lv->SetSolid(iron_solid);
iron_lv->SetMaterial(iron_mat);
SmartPointer<Geant::PhysicalVolume> iron_pv(new Geant::PhysicalVolume("IronPV", iron_lv));
scene.AddVolume(iron_pv);
RandomEmitter* emitter = new RandomEmitter(); RandomEmitter* emitter = new RandomEmitter();
scene.SetEmitter(emitter); scene.SetEmitter(emitter);
@@ -123,7 +132,7 @@ int main(int argc, char** argv) {
viewer.AddProp3D(*vtkWorld); viewer.AddProp3D(*vtkWorld);
// Visualize iron cube // 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->SetOpacity(0.2);
vtkIron->SetRepresentation(Vtk::Prop3D::Surface); vtkIron->SetRepresentation(Vtk::Prop3D::Surface);
viewer.AddProp3D(*vtkIron); viewer.AddProp3D(*vtkIron);

View File

@@ -33,13 +33,22 @@ int main(int argc, char** argv) {
scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR"); scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR");
// Add an iron cube inside the world // Add an iron cube inside the world
ContainerBox iron_box; SmartPointer<ContainerBox> iron_box(new ContainerBox());
iron_box.Scale(Vector3f(10_m, 10_m, 10_m)); iron_box->Scale(Vector3f(10_m, 10_m, 10_m));
iron_box.SetPosition(Vector3f(-5_m, -5_m, -5_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"); SmartPointer<Geant::BoxSolid> iron_solid(new Geant::BoxSolid("IronSolid", iron_box));
iron_cube->Update(); iron_solid->Update();
scene.AddSolid(iron_cube);
SmartPointer<Geant::Material> iron_mat(new Geant::Material("IronMat"));
iron_mat->SetFromNist("G4_Fe");
SmartPointer<Geant::LogicalVolume> iron_lv(new Geant::LogicalVolume("IronLV"));
iron_lv->SetSolid(iron_solid);
iron_lv->SetMaterial(iron_mat);
SmartPointer<Geant::PhysicalVolume> iron_pv(new Geant::PhysicalVolume("IronPV", iron_lv));
scene.AddVolume(iron_pv);
scene.Initialize(); scene.Initialize();
// 2. Build VTK scene representation // 2. Build VTK scene representation

View File

@@ -66,33 +66,58 @@ int main(int argc, char** argv) {
Geant::Scene scene; Geant::Scene scene;
scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR"); scene.ConstructWorldBox(Vector3f(30_m, 30_m, 30_m), "G4_AIR");
ContainerBox iron_box; // Iron Cube
iron_box.Scale(Vector3f(18_m, 18_m, 18_m)); SmartPointer<ContainerBox> iron_box(new ContainerBox());
iron_box.SetPosition(Vector3f(-9_m, -9_m, -9_m)); iron_box->Scale(Vector3f(18_m, 18_m, 18_m));
Geant::BoxSolid* iron_cube = new Geant::BoxSolid("IronCube", &iron_box); iron_box->SetPosition(Vector3f(-9_m, -9_m, -9_m));
iron_cube->SetNistMaterial("G4_Fe");
iron_cube->Update(); SmartPointer<Geant::BoxSolid> iron_solid(new Geant::BoxSolid("IronSolid", iron_box));
scene.AddSolid(iron_cube); iron_solid->Update();
SmartPointer<Geant::Material> iron_mat(new Geant::Material("IronMat"));
iron_mat->SetFromNist("G4_Fe");
SmartPointer<Geant::LogicalVolume> iron_lv(new Geant::LogicalVolume("IronLV"));
iron_lv->SetSolid(iron_solid);
iron_lv->SetMaterial(iron_mat);
SmartPointer<Geant::PhysicalVolume> iron_pv(new Geant::PhysicalVolume("IronPV", iron_lv));
scene.AddVolume(iron_pv);
// Top Detector Chamber (along Y axis) // Top Detector Chamber (along Y axis)
DetectorChamber* top_chamber_box = new DetectorChamber(); SmartPointer<DetectorChamber> top_chamber_box(new DetectorChamber());
top_chamber_box->Scale(Vector3f(20_m, 40_cm, 20_m)); top_chamber_box->Scale(Vector3f(20_m, 40_cm, 20_m));
top_chamber_box->Rotate(90_deg, Vector3f(1, 0, 0)); top_chamber_box->Rotate(90_deg, Vector3f(1, 0, 0));
top_chamber_box->SetPosition(Vector3f(-10_m, 12_m, -10_m)); 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"); SmartPointer<Geant::BoxSolid> top_solid(new Geant::BoxSolid("TopSolid", top_chamber_box));
top_chamber->Update(); top_solid->Update();
scene.AddSolid(top_chamber);
SmartPointer<Geant::Material> air_mat(new Geant::Material("AirMat"));
air_mat->SetFromNist("G4_AIR");
SmartPointer<Geant::LogicalVolume> top_lv(new Geant::LogicalVolume("TopLV"));
top_lv->SetSolid(top_solid);
top_lv->SetMaterial(air_mat);
SmartPointer<Geant::PhysicalVolume> top_pv(new Geant::PhysicalVolume("TopPV", top_lv));
scene.AddVolume(top_pv);
// Bottom Detector Chamber (along Y axis) // Bottom Detector Chamber (along Y axis)
DetectorChamber* bottom_chamber_box = new DetectorChamber(); SmartPointer<DetectorChamber> bottom_chamber_box(new DetectorChamber());
bottom_chamber_box->Scale(Vector3f(20_m, 40_cm, 20_m)); bottom_chamber_box->Scale(Vector3f(20_m, 40_cm, 20_m));
bottom_chamber_box->Rotate(90_deg, Vector3f(1, 0, 0)); bottom_chamber_box->Rotate(90_deg, Vector3f(1, 0, 0));
bottom_chamber_box->SetPosition(Vector3f(-10_m, -12_m, -10_m)); 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"); SmartPointer<Geant::BoxSolid> bottom_solid(new Geant::BoxSolid("BottomSolid", bottom_chamber_box));
bottom_chamber->Update(); bottom_solid->Update();
scene.AddSolid(bottom_chamber);
SmartPointer<Geant::LogicalVolume> bottom_lv(new Geant::LogicalVolume("BottomLV"));
bottom_lv->SetSolid(bottom_solid);
bottom_lv->SetMaterial(air_mat);
SmartPointer<Geant::PhysicalVolume> bottom_pv(new Geant::PhysicalVolume("BottomPV", bottom_lv));
scene.AddVolume(bottom_pv);
// Use SkyPlaneEmitterPrimary instead of EmitterPrimary // Use SkyPlaneEmitterPrimary instead of EmitterPrimary
Geant::SkyPlaneEmitterPrimary* emitter = new Geant::SkyPlaneEmitterPrimary(); Geant::SkyPlaneEmitterPrimary* emitter = new Geant::SkyPlaneEmitterPrimary();
@@ -113,20 +138,20 @@ int main(int argc, char** argv) {
vtkWorld->SetSelectable(false); vtkWorld->SetSelectable(false);
viewer.AddProp3D(*vtkWorld); 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->SetOpacity(0.2);
vtkIron->SetRepresentation(Vtk::Prop3D::Surface); vtkIron->SetRepresentation(Vtk::Prop3D::Surface);
viewer.AddProp3D(*vtkIron); viewer.AddProp3D(*vtkIron);
// Visualize Top Chamber // 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->SetOpacity(0.5);
vtkTop->SetColor(0.2, 0.8, 0.2); vtkTop->SetColor(0.2, 0.8, 0.2);
vtkTop->SetRepresentation(Vtk::Prop3D::Surface); vtkTop->SetRepresentation(Vtk::Prop3D::Surface);
viewer.AddProp3D(*vtkTop); viewer.AddProp3D(*vtkTop);
// Visualize Bottom Chamber // 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->SetOpacity(0.5);
vtkBottom->SetColor(0.2, 0.8, 0.2); vtkBottom->SetColor(0.2, 0.8, 0.2);
vtkBottom->SetRepresentation(Vtk::Prop3D::Surface); vtkBottom->SetRepresentation(Vtk::Prop3D::Surface);

View File

@@ -25,53 +25,59 @@ using namespace uLib;
int main(int argc, char** argv) { int main(int argc, char** argv) {
bool interactive = (argc > 1 && std::string(argv[1]) == "-i"); 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 // 3. Visualization setup
Vtk::Viewer viewer; Vtk::Viewer viewer;
// 1. Create a BoxSolid
SmartPointer<ContainerBox> box(new ContainerBox());
box->Scale(Vector3f(1_m, 2_m, 3_m));
SmartPointer<Geant::BoxSolid> gBox(new Geant::BoxSolid("MyBox", box));
gBox->Update();
SmartPointer<Geant::LogicalVolume> lvBox(new Geant::LogicalVolume("BoxLV"));
lvBox->SetSolid(gBox);
SmartPointer<Geant::PhysicalVolume> pvBox(new Geant::PhysicalVolume("BoxPV", lvBox));
Vtk::BoxSolid vtkBox(pvBox);
vtkBox.AddToViewer(viewer); vtkBox.AddToViewer(viewer);
// 2. Create a TessellatedSolid
SmartPointer<Geant::TessellatedSolid> gTess(new Geant::TessellatedSolid("MyTess"));
SmartPointer<TriangleMesh> 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<Geant::LogicalVolume> lvTess(new Geant::LogicalVolume("TessLV"));
lvTess->SetSolid(gTess);
SmartPointer<Geant::PhysicalVolume> pvTess(new Geant::PhysicalVolume("TessPV", lvTess));
Vtk::TessellatedSolid vtkTess(pvTess);
vtkTess.AddToViewer(viewer); vtkTess.AddToViewer(viewer);
// Color them differently // Color them differently
vtkBox.SetColor(0.8, 0.2, 0.2); // Redish box vtkBox.SetColor(0.8, 0.2, 0.2); // Redish box
vtkTess.SetColor(0.2, 0.8, 0.2); // Greenish tess 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(); Matrix4f trans = Matrix4f::Identity();
trans.block<3,1>(0,3) = Vector3f(5_m, 0, 0); trans.block<3,1>(0,3) = Vector3f(5_m, 0, 0);
gTess.SetTransform(trans); pvTess->SetMatrix(trans);
vtkTess.Update(); vtkTess.Update();
std::cout << "..:: Testing vtkSolidsTest ::.." << std::endl; 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) { if (interactive) {
viewer.ZoomAuto(); viewer.ZoomAuto();

View File

@@ -24,8 +24,15 @@
namespace uLib { namespace uLib {
namespace Vtk { namespace Vtk {
BoxSolid::BoxSolid(Geant::BoxSolid *content) BoxSolid::BoxSolid(Geant::PhysicalVolume *content)
: GeantSolid(content), m_BoxContent(content) { : GeantSolid(content), m_BoxSolid(nullptr) {
if (content && content->GetLogical()) {
m_BoxSolid = dynamic_cast<Geant::BoxSolid *>(content->GetLogical()->GetSolid());
}
}
BoxSolid::BoxSolid(Geant::BoxSolid *solid)
: GeantSolid(solid), m_BoxSolid(solid) {
} }
BoxSolid::~BoxSolid() { BoxSolid::~BoxSolid() {
@@ -35,10 +42,10 @@ void BoxSolid::serialize_display(uLib::Archive::display_properties_archive &ar,
const unsigned int version) { const unsigned int version) {
// Expose Geant solid properties and underlying Box/TRS properties // Expose Geant solid properties and underlying Box/TRS properties
this->Prop3D::serialize_display(ar, version); this->Prop3D::serialize_display(ar, version);
if (m_BoxContent) { if (m_BoxSolid) {
ar & NVP("Box", *m_BoxContent); ar & NVP("Box", *m_BoxSolid);
if (m_BoxContent->GetObject()) { if (m_BoxSolid->GetObject()) {
ar & NVP("Container", *m_BoxContent->GetObject()); ar & NVP("Container", *m_BoxSolid->GetObject());
} }
} }
} }

View File

@@ -45,7 +45,8 @@ class BoxSolid : public GeantSolid {
uLibTypeMacro(BoxSolid, uLib::Vtk::GeantSolid) uLibTypeMacro(BoxSolid, uLib::Vtk::GeantSolid)
public: public:
BoxSolid(Geant::BoxSolid *content); BoxSolid(Geant::PhysicalVolume *content);
BoxSolid(Geant::BoxSolid *solid);
virtual ~BoxSolid(); virtual ~BoxSolid();
virtual void serialize_display(uLib::Archive::display_properties_archive &ar, virtual void serialize_display(uLib::Archive::display_properties_archive &ar,
@@ -53,13 +54,13 @@ public:
template <typename Ar> template <typename Ar>
void serialize(Ar &ar, const unsigned int version) { void serialize(Ar &ar, const unsigned int version) {
ar & NVP("BoxSolid", *m_BoxContent); ar & NVP("BoxSolid", *m_BoxSolid);
} }
protected: protected:
virtual void InstallPipe() override; virtual void InstallPipe() override;
Geant::BoxSolid *m_BoxContent; Geant::BoxSolid *m_BoxSolid;
ULIB_DECLARE_PROPERTIES(BoxSolid) ULIB_DECLARE_PROPERTIES(BoxSolid)
}; };

View File

@@ -45,25 +45,29 @@ GeantScene::GeantScene(Geant::Scene *scene)
m_WorldProp3D->ShowScaleMeasures(true); m_WorldProp3D->ShowScaleMeasures(true);
} }
// 2. Create prop3ds for each non-world solid // 2. Create prop3ds for each physical volume in the scene
const Geant::Solid *world = m_Scene->GetWorld(); const Vector<SmartPointer<Geant::PhysicalVolume>> &volumes = m_Scene->GetVolumes();
const Vector<Geant::Solid *> &solids = m_Scene->GetSolids();
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 // Skip the world volume itself — it's already shown as the wireframe box
if (solid == world) if (solid == m_Scene->GetWorld())
continue; continue;
// Only create a prop3d if the solid has a valid G4VSolid // Only create a prop3d if the solid has a valid G4VSolid
if (solid->GetG4Solid()) { if (solid->GetG4Solid()) {
GeantSolid *vtkSolid = nullptr; GeantSolid *vtkSolid = nullptr;
if (auto *box = dynamic_cast<Geant::BoxSolid *>(solid)) { if (auto *box = dynamic_cast<Geant::BoxSolid *>(solid)) {
vtkSolid = new BoxSolid(box); vtkSolid = new BoxSolid(pv);
} else if (auto *tess = dynamic_cast<Geant::TessellatedSolid *>(solid)) { } else if (auto *tess = dynamic_cast<Geant::TessellatedSolid *>(solid)) {
vtkSolid = new TessellatedSolid(tess); vtkSolid = new TessellatedSolid(pv);
} else { } else {
vtkSolid = new GeantSolid(solid); vtkSolid = new GeantSolid(pv);
vtkSolid->Update();
} }
if (vtkSolid) { if (vtkSolid) {

View File

@@ -44,15 +44,26 @@
namespace uLib { namespace uLib {
namespace Vtk { namespace Vtk {
GeantSolid::GeantSolid(Content *content) GeantSolid::GeantSolid(Geant::PhysicalVolume *content)
: m_SolidActor(vtkActor::New()), m_Content(content) { : m_SolidActor(vtkActor::New()), m_Volume(content), m_Solid(nullptr) {
this->InstallPipe(); this->InstallPipe();
if (m_Content) { if (m_Volume) {
m_UpdateConnection = Object::connect(m_Content, &uLib::Object::Updated, [this]() { m_UpdateConnection = Object::connect(m_Volume, &uLib::Object::Updated, [this]() {
std::cout << "GeantSolid: Signal Updated received." << std::endl;
this->Update(); 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(); this->Update();
} }
} }
@@ -75,21 +86,25 @@ void GeantSolid::Update() {
} }
void GeantSolid::SyncFromVtk() { void GeantSolid::SyncFromVtk() {
if (!m_Content) return; if (!m_Volume) return;
this->Prop3D::SyncFromVtk(); this->Prop3D::SyncFromVtk();
if (auto* proxy = vtkProp3D::SafeDownCast(this->GetProxyProp())) { if (auto* proxy = vtkProp3D::SafeDownCast(this->GetProxyProp())) {
if (vtkMatrix4x4* mat = proxy->GetUserMatrix()) { if (vtkMatrix4x4* mat = proxy->GetUserMatrix()) {
m_Content->SetTransform(VtkToMatrix4f(mat)); m_Volume->SetMatrix(VtkToMatrix4f(mat));
} }
} }
} }
void GeantSolid::UpdateGeometry() { void GeantSolid::UpdateGeometry() {
if (!m_Content) Geant::Solid *solid = m_Solid;
return; 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) if (!g4solid)
return; return;
@@ -134,39 +149,20 @@ void GeantSolid::UpdateGeometry() {
} }
void GeantSolid::UpdateTransform() { void GeantSolid::UpdateTransform() {
if (!m_Content || !m_SolidActor) if (!m_SolidActor)
return; return;
// Apply the Geant4 transform (position/rotation/scaling) if (m_Volume) {
G4ThreeVector pos = m_Content->GetPosition(); // Apply the TRS transform directly from the PhysicalVolume
const G4RotationMatrix *rot = m_Content->GetRotation(); vtkNew<vtkMatrix4x4> vtkMat;
G4ThreeVector scale = m_Content->GetScaling(); Matrix4fToVtk(m_Volume->GetMatrix(), vtkMat);
m_SolidActor->SetUserMatrix(vtkMat);
std::cout << "GeantSolid: Updating transform. Pos: " << pos.x() << " " << pos.y() << " " << pos.z() } else {
<< " Scale: " << scale.x() << " " << scale.y() << " " << scale.z() << std::endl; // Identity for unplaced solids
m_SolidActor->SetUserMatrix(nullptr);
vtkNew<vtkTransform> 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<vtkMatrix4x4> mat;
mat->DeepCopy(elements);
transform->Concatenate(mat);
}
transform->Scale(scale.x(), scale.y(), scale.z());
m_SolidActor->SetUserTransform(transform);
m_SolidActor->Modified();
} }
m_SolidActor->Modified();
}
void GeantSolid::InstallPipe() { void GeantSolid::InstallPipe() {
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New(); vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();

View File

@@ -43,10 +43,9 @@ namespace Vtk {
* a valid G4VSolid via GetG4Solid(). * a valid G4VSolid via GetG4Solid().
*/ */
class GeantSolid : public Prop3D, public Polydata { class GeantSolid : public Prop3D, public Polydata {
typedef Geant::Solid Content;
public: public:
GeantSolid(Content *content); GeantSolid(Geant::PhysicalVolume *content);
GeantSolid(Geant::Solid *solid);
~GeantSolid(); ~GeantSolid();
virtual class vtkPolyData *GetPolyData() const override; virtual class vtkPolyData *GetPolyData() const override;
@@ -57,14 +56,17 @@ public:
virtual void UpdateGeometry(); virtual void UpdateGeometry();
virtual void UpdateTransform(); 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: protected:
virtual void InstallPipe(); virtual void InstallPipe();
Content *m_Content; Geant::PhysicalVolume *m_Volume;
vtkActor *m_SolidActor; Geant::Solid *m_Solid;
uLib::Connection m_UpdateConnection; vtkActor *m_SolidActor;
uLib::Connection m_UpdateConnection;
}; };
} // namespace Vtk } // namespace Vtk

View File

@@ -18,9 +18,11 @@
namespace uLib { namespace uLib {
namespace Vtk { namespace Vtk {
TessellatedSolid::TessellatedSolid(Geant::TessellatedSolid *content) TessellatedSolid::TessellatedSolid(Geant::PhysicalVolume *content)
: GeantSolid(content), m_TessContent(content) { : GeantSolid(content), m_TessSolid(nullptr) {
this->Update(); if (content && content->GetLogical()) {
m_TessSolid = dynamic_cast<Geant::TessellatedSolid *>(content->GetLogical()->GetSolid());
}
} }
TessellatedSolid::~TessellatedSolid() {} TessellatedSolid::~TessellatedSolid() {}
@@ -31,13 +33,13 @@ void TessellatedSolid::Update() {
} }
void TessellatedSolid::UpdateGeometry() { 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 // Fallback to base tessellation if no model mesh
GeantSolid::UpdateGeometry(); GeantSolid::UpdateGeometry();
return; return;
} }
const TriangleMesh &mesh = m_TessContent->GetMesh(); const TriangleMesh &mesh = *m_TessSolid->GetMesh();
vtkNew<vtkPoints> points; vtkNew<vtkPoints> points;
for (const auto& pt : mesh.Points()) { for (const auto& pt : mesh.Points()) {

View File

@@ -22,14 +22,14 @@ namespace Vtk {
*/ */
class TessellatedSolid : public GeantSolid { class TessellatedSolid : public GeantSolid {
public: public:
TessellatedSolid(Geant::TessellatedSolid *content); TessellatedSolid(Geant::PhysicalVolume *content);
virtual ~TessellatedSolid(); virtual ~TessellatedSolid();
virtual void Update() override; virtual void Update() override;
virtual void UpdateGeometry() override; virtual void UpdateGeometry() override;
protected: protected:
Geant::TessellatedSolid *m_TessContent; Geant::TessellatedSolid *m_TessSolid;
}; };
} // namespace Vtk } // namespace Vtk

View File

@@ -6,6 +6,7 @@
#include "Vtk/HEP/Detectors/vtkDetectorChamber.h" #include "Vtk/HEP/Detectors/vtkDetectorChamber.h"
#include "Vtk/HEP/Geant/vtkBoxSolid.h" #include "Vtk/HEP/Geant/vtkBoxSolid.h"
#include "Vtk/HEP/Geant/vtkTessellatedSolid.h"
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
@@ -150,8 +151,20 @@ Prop3D *ObjectsContext::CreateProp3D(uLib::Object *obj) {
return new Cylinder(cylinder); return new Cylinder(cylinder);
} else if (auto *assembly = dynamic_cast<uLib::Assembly *>(obj)) { } else if (auto *assembly = dynamic_cast<uLib::Assembly *>(obj)) {
return new Assembly(assembly); return new Assembly(assembly);
} else if (auto *pv = dynamic_cast<uLib::Geant::PhysicalVolume *>(obj)) {
uLib::Geant::Solid *solid = pv->GetLogical()->GetSolid();
if (auto *box = dynamic_cast<uLib::Geant::BoxSolid *>(solid)) {
return new BoxSolid(pv);
} else if (auto *tess = dynamic_cast<uLib::Geant::TessellatedSolid *>(solid)) {
return new TessellatedSolid(pv);
} else {
return new GeantSolid(pv);
}
} else if (auto *box = dynamic_cast<uLib::Geant::BoxSolid *>(obj)) { } else if (auto *box = dynamic_cast<uLib::Geant::BoxSolid *>(obj)) {
return new BoxSolid(box); return new BoxSolid(box);
} else if (auto *solid = dynamic_cast<uLib::Geant::Solid *>(obj)) {
// Unplaced solid visualization
return new GeantSolid(solid);
} }
// Fallback if we don't know the exact class but it might be a context itself // Fallback if we don't know the exact class but it might be a context itself