diff --git a/app/gcompose/src/ContextPanel.cpp b/app/gcompose/src/ContextPanel.cpp index 3d9040b..1ead4b1 100644 --- a/app/gcompose/src/ContextPanel.cpp +++ b/app/gcompose/src/ContextPanel.cpp @@ -10,6 +10,7 @@ #include #include #include +#include ContextPanel::ContextPanel(QWidget* parent) : QWidget(parent) @@ -105,15 +106,34 @@ void ContextPanel::selectObject(uLib::Object* obj) { return; } - for (int i = 0; i < m_model->rowCount(); ++i) { - QModelIndex idx = m_model->index(i, 0); - if (idx.internalPointer() == obj) { - QSignalBlocker blocker(m_treeView->selectionModel()); - m_treeView->selectionModel()->select(idx, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); - m_treeView->scrollTo(idx); - m_propertiesPanel->setObject(obj); // Explicitly update properties too - return; + // Recursive search helper + std::function findIdx = [&](const QModelIndex& parent) -> QModelIndex { + for (int i = 0; i < m_model->rowCount(parent); ++i) { + QModelIndex idx = m_model->index(i, 0, parent); + if (idx.internalPointer() == obj) return idx; + + if (m_model->rowCount(idx) > 0) { + QModelIndex childIdx = findIdx(idx); + if (childIdx.isValid()) return childIdx; + } } + return QModelIndex(); + }; + + QModelIndex targetIdx = findIdx(QModelIndex()); + if (targetIdx.isValid()) { + QSignalBlocker blocker(m_treeView->selectionModel()); + + // Expand parents so the selection is visible + QModelIndex p = targetIdx.parent(); + while (p.isValid()) { + m_treeView->expand(p); + p = p.parent(); + } + + m_treeView->selectionModel()->select(targetIdx, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + m_treeView->scrollTo(targetIdx); + m_propertiesPanel->setObject(obj); } } diff --git a/src/HEP/Geant/Solid.cpp b/src/HEP/Geant/Solid.cpp index 11ff159..466d2f0 100644 --- a/src/HEP/Geant/Solid.cpp +++ b/src/HEP/Geant/Solid.cpp @@ -35,12 +35,14 @@ #include #include #include +#include #include "Math/Dense.h" #include "Math/Transform.h" #include "Solid.h" +#include "uLibInterface.hh" namespace uLib { namespace Geant { @@ -55,18 +57,17 @@ public: }; Solid::Solid() - : m_Name("unnamed_solid"), m_Material(NULL), m_Logical(NULL), m_Physical(NULL), - m_Position(new G4ThreeVector(0,0,0)), m_Rotation(NULL) {} + : m_Material(nullptr), m_Logical(nullptr) { +} Solid::Solid(const char *name) - : m_Name(name), m_Material(NULL), m_Logical(NULL), m_Physical(NULL), - m_Position(new G4ThreeVector(0,0,0)), m_Rotation(NULL) {} - -Solid::~Solid() { - if (m_Position) delete m_Position; - if (m_Rotation) delete m_Rotation; + : m_Name(name), m_Material(nullptr), m_Logical(nullptr) { } +Solid::~Solid() {} + +void Solid::Update() {} + void Solid::SetNistMaterial(const char *name) { G4NistManager *nist = G4NistManager::Instance(); G4Material *mat = nist->FindOrBuildMaterial(name); @@ -85,32 +86,12 @@ void Solid::SetMaterial(G4Material *material) { } void Solid::SetTransform(Matrix4f transform) { - uLib::AffineTransform t; - t.SetMatrix(transform); - - // 2. Extract position and rotation for Geant4 - Vector3f pos = t.GetPosition(); - if (!m_Position) m_Position = new G4ThreeVector(); - *m_Position = G4ThreeVector(pos(0), pos(1), pos(2)); - - // Create a G4 rotation matrix from the 4x4 matrix - Matrix3f m = t.GetRotation(); - if (!m_Rotation) m_Rotation = new G4RotationMatrix(); - m_Rotation->set(G4ThreeVector(m(0,0), m(1,0), m(2,0)), - G4ThreeVector(m(0,1), m(1,1), m(2,1)), - G4ThreeVector(m(0,2), m(1,2), m(2,2))); - - // 3. If object is already placed, update its transformation - if (m_Physical) { - m_Physical->SetTranslation(*m_Position); - m_Physical->SetRotation(m_Rotation); - } - - std::cout << "Solid " << GetName() << " position: " << pos << " rotation: " << m << std::endl; - - this->Updated(); + m_Transform.FromMatrix(transform); + m_Transform.Updated(); } + + void Solid::SetParent(Solid *parent) { if (!m_Logical) { std::cerr << "logical volume not created for solid " << GetName() << std::endl; @@ -133,8 +114,8 @@ void Solid::SetParent(Solid *parent) { // G4PVPlacement m_Physical = new G4PVPlacement( - m_Rotation, // Rotation - *m_Position, // Position (translation) inside the parent + ToG4Transform(m_Transform), // Rotation + GetPosition(), // Position (translation) inside the parent m_Logical, // The logical volume of this solid (the child) GetName(), // Name of the physical volume parentLogical, // The logical volume of the parent (nullptr if it's the World volume) @@ -182,15 +163,15 @@ void TessellatedSolid::Update() { BoxSolid::BoxSolid(const char *name) : BaseClass(name), + m_Density(1.0), m_ContainerBox(new ContainerBox()), - m_Solid(new G4Box(name, 0.5, 0.5, 0.5)) - { - Object::connect(m_ContainerBox, &ContainerBox::Updated, this, &BoxSolid::Update); - Update(); - } + m_Solid(new G4Box(name, 1, 1, 1)) + {} -BoxSolid::BoxSolid(const char *name, ContainerBox *box) : BaseClass(name) { - m_Solid = new G4Box(name, 0.5, 0.5, 0.5); +BoxSolid::BoxSolid(const char *name, ContainerBox *box) : + BaseClass(name), + m_Density(1.0) { + m_Solid = new G4Box(name, 1, 1, 1); m_ContainerBox = box; Object::connect(box, &ContainerBox::Updated, this, &BoxSolid::Update); if (m_Logical) { @@ -199,6 +180,7 @@ BoxSolid::BoxSolid(const char *name, ContainerBox *box) : BaseClass(name) { Update(); } + void BoxSolid::Update() { if (m_ContainerBox) { Vector3f size = m_ContainerBox->GetSize(); diff --git a/src/HEP/Geant/Solid.h b/src/HEP/Geant/Solid.h index 9b551bb..ee1221e 100644 --- a/src/HEP/Geant/Solid.h +++ b/src/HEP/Geant/Solid.h @@ -28,11 +28,15 @@ #include "Core/Object.h" #include "Geant/Matter.h" +#include "Math/Transform.h" #include #include "Math/ContainerBox.h" #include "Math/Dense.h" #include "Math/TriangleMesh.h" + + + class G4Material; class G4LogicalVolume; class G4TessellatedSolid; @@ -42,28 +46,17 @@ namespace uLib { namespace Geant { class Solid : public Object { -public: + uLibTypeMacro(Solid, Object) + ULIB_SERIALIZE_ACCESS + ULIB_DECLARE_PROPERTIES(Solid) + +public: Solid(); Solid(const char *name); virtual ~Solid(); - - void SetNistMaterial(const char *name); - void SetMaterial(G4Material *material); - void SetSizeUnit(const char *unit); - - // Implementiamo SetParent qui, per tutti. - virtual void SetParent(Solid *parent); - - // Setters per la posizione (necessari per il piazzamento) - void SetTransform(Matrix4f transform); - - uLibGetMacro(Material, G4Material *) - uLibGetSetMacro(Logical, G4LogicalVolume *) - uLibGetSetMacro(Physical, G4VPhysicalVolume *) - virtual G4VSolid* GetG4Solid() const { return nullptr; } inline const char *GetName() const { @@ -72,20 +65,57 @@ public: template < typename Ar > void serialize(Ar &ar, const unsigned int version) { - ar & boost::serialization::make_nvp("Name", m_Name); + ar & HRP("Name", m_Name); + ar & HRP("Material", m_Material); } -protected: +public slots: + virtual void Update(); + +protected: std::string m_Name; - G4Material *m_Material; - G4LogicalVolume *m_Logical; - G4VPhysicalVolume *m_Physical; // <-- Memorizza l'oggetto posizionato - G4ThreeVector *m_Position; // <-- Offset rispetto al centro del padre - G4RotationMatrix* m_Rotation; // <-- Rotazione rispetto al padre }; +class LogicalVolume : public Object { + + uLibTypeMacro(LogicalVolume, Object) + ULIB_SERIALIZE_ACCESS + ULIB_DECLARE_PROPERTIES(LogicalVolume) + +public: + + LogicalVolume(); + LogicalVolume(const char *name); + virtual ~LogicalVolume(); + + virtual G4VSolid* GetG4Solid() const { return nullptr; } + + inline const char *GetName() const { + return m_Logical ? m_Logical->GetName().c_str() : m_Name.c_str(); + } + + template < typename Ar > + void serialize(Ar &ar, const unsigned int version) { + ar & HRP("Name", m_Name); + ar & HRP("Material", m_Material); + } + + +public slots: + virtual void Update(); + +protected: + std::string m_Name; + Material *m_Material; + + G4LogicalVolume *m_Logical; +}; + + + + @@ -95,8 +125,10 @@ public: TessellatedSolid(); TessellatedSolid(const char *name); + void SetMesh(TriangleMesh &mesh); uLibGetMacro(Solid, G4TessellatedSolid *) + virtual G4VSolid* GetG4Solid() const override { return (G4VSolid*)m_Solid; } const TriangleMesh& GetMesh() const { return m_Mesh; } @@ -115,9 +147,11 @@ private : class BoxSolid : public Solid { + uLibTypeMacro(BoxSolid, Solid) + ULIB_SERIALIZE_ACCESS + ULIB_DECLARE_PROPERTIES(BoxSolid) public: - uLibTypeMacro(BoxSolid, Solid) BoxSolid(const char *name = ""); BoxSolid(const char *name, ContainerBox *box); @@ -128,14 +162,15 @@ public: template < typename Ar > void serialize(Ar &ar, const unsigned int version) { - ar & boost::serialization::base_object(*this); - ar & m_ContainerBox; + // ar & boost::serialization::base_object(*this); + ar & HRP("Density", m_Density, "g/cm3"); } public slots: void Update(); private: + float m_Density; ContainerBox *m_ContainerBox; G4Box *m_Solid; }; diff --git a/src/HEP/Geant/uLibInterface.hh b/src/HEP/Geant/uLibInterface.hh new file mode 100644 index 0000000..9f6cd0c --- /dev/null +++ b/src/HEP/Geant/uLibInterface.hh @@ -0,0 +1,51 @@ +#ifndef ULIB_GEANT_ULIB_INTERFACE_HH +#define ULIB_GEANT_ULIB_INTERFACE_HH + +#include "Math/Transform.h" +#include +#include +#include + +namespace uLib { +namespace Geant { + +/** + * @brief Converts a uLib::Matrix4f to a Geant4 G4Transform3D. + */ +inline G4Transform3D ToG4Transform(const Matrix4f& m) { + return G4Transform3D( + m(0, 0), m(0, 1), m(0, 2), m(0, 3), + m(1, 0), m(1, 1), m(1, 2), m(1, 3), + m(2, 0), m(2, 1), m(2, 2), m(2, 3) + ); +} + +/** + * @brief Converts a uLib::AffineTransform to a Geant4 G4Transform3D. + */ +inline G4Transform3D ToG4Transform(const AffineTransform& at) { + return ToG4Transform(at.GetMatrix()); +} + +/** + * @brief Converts a uLib::Vector3f to a Geant4 G4ThreeVector. + */ +inline G4ThreeVector ToG4Vector(const Vector3f& v) { + return G4ThreeVector(v(0), v(1), v(2)); +} + +/** + * @brief Converts a uLib::Matrix3f to a Geant4 G4RotationMatrix. + */ +inline G4RotationMatrix ToG4Rotation(const Matrix3f& m) { + G4RotationMatrix rot; + rot.set(G4ThreeVector(m(0, 0), m(1, 0), m(2, 0)), + G4ThreeVector(m(0, 1), m(1, 1), m(2, 1)), + G4ThreeVector(m(0, 2), m(1, 2), m(2, 2))); + return rot; +} + +} // namespace Geant +} // namespace uLib + +#endif // ULIB_GEANT_ULIB_INTERFACE_HH diff --git a/src/Math/Transform.h b/src/Math/Transform.h index 82d07d3..c6381e4 100644 --- a/src/Math/Transform.h +++ b/src/Math/Transform.h @@ -246,6 +246,7 @@ uLibTypeMacro(TRS, AffineTransform) ULIB_SERIALIZE_ACCESS } Matrix4f GetMatrix() const { return this->GetAffineMatrix().matrix(); } + }; inline std::ostream &operator<<(std::ostream &os, const TRS &trs) { diff --git a/src/Vtk/HEP/Geant/vtkBoxSolid.cpp b/src/Vtk/HEP/Geant/vtkBoxSolid.cpp index bd97cd3..5a0e871 100644 --- a/src/Vtk/HEP/Geant/vtkBoxSolid.cpp +++ b/src/Vtk/HEP/Geant/vtkBoxSolid.cpp @@ -26,36 +26,11 @@ namespace Vtk { BoxSolid::BoxSolid(Geant::BoxSolid *content) : GeantSolid(content), m_BoxContent(content) { - this->InstallPipe(); - - // Connect the model's Updated event to updateTransform to ensure VTK sync - m_UpdateConnection = Object::connect(m_BoxContent, &uLib::Object::Updated, this, &BoxSolid::Update); - - // Initial sync - this->Update(); } BoxSolid::~BoxSolid() { } -void BoxSolid::Update() { - ConnectionBlock blocker(m_UpdateConnection); - // Ensure base GeantSolid logic (G4Polyhedron and Transform) runs - this->GeantSolid::Update(); - // Ensure base Prop3D properties (color, opacity, etc) are applied - this->Prop3D::Update(); -} - -void BoxSolid::SyncFromVtk() { - this->Prop3D::SyncFromVtk(); - - if (auto* proxy = vtkProp3D::SafeDownCast(this->GetProxyProp())) { - if (vtkMatrix4x4* mat = proxy->GetUserMatrix()) { - m_BoxContent->SetTransform(VtkToMatrix4f(mat)); - } - } -} - void BoxSolid::serialize_display(uLib::Archive::display_properties_archive &ar, const unsigned int version) { // Expose Geant solid properties and underlying Box/TRS properties diff --git a/src/Vtk/HEP/Geant/vtkBoxSolid.h b/src/Vtk/HEP/Geant/vtkBoxSolid.h index 58c67cd..7a00df4 100644 --- a/src/Vtk/HEP/Geant/vtkBoxSolid.h +++ b/src/Vtk/HEP/Geant/vtkBoxSolid.h @@ -48,13 +48,6 @@ public: BoxSolid(Geant::BoxSolid *content); virtual ~BoxSolid(); - virtual void Update() override; - virtual void SyncFromVtk() override; - - virtual uLib::Object *GetContent() const override { - return m_BoxContent ? (::uLib::Object*)m_BoxContent->GetObject() : nullptr; - } - virtual void serialize_display(uLib::Archive::display_properties_archive &ar, const unsigned int version = 0) override; @@ -67,7 +60,6 @@ protected: virtual void InstallPipe() override; Geant::BoxSolid *m_BoxContent; - uLib::Connection m_UpdateConnection; ULIB_DECLARE_PROPERTIES(BoxSolid) }; diff --git a/src/Vtk/HEP/Geant/vtkGeantSolid.cpp b/src/Vtk/HEP/Geant/vtkGeantSolid.cpp index 404fa83..b5a0439 100644 --- a/src/Vtk/HEP/Geant/vtkGeantSolid.cpp +++ b/src/Vtk/HEP/Geant/vtkGeantSolid.cpp @@ -24,6 +24,7 @@ //////////////////////////////////////////////////////////////////////////////*/ #include "vtkGeantSolid.h" +#include "Core/Monitor.h" #include #include @@ -34,6 +35,7 @@ #include #include #include +#include "Vtk/Math/vtkDense.h" #include #include @@ -45,6 +47,14 @@ namespace Vtk { GeantSolid::GeantSolid(Content *content) : m_SolidActor(vtkActor::New()), m_Content(content) { this->InstallPipe(); + if (m_Content) { + m_UpdateConnection = Object::connect(m_Content, &uLib::Object::Updated, [this]() { + std::cout << "GeantSolid: Signal Updated received." << std::endl; + this->Update(); + }); + // Mandatory initial update to generate geometry and apply initial transform + this->Update(); + } } GeantSolid::~GeantSolid() { @@ -58,8 +68,21 @@ vtkPolyData *GeantSolid::GetPolyData() const { } void GeantSolid::Update() { + ConnectionBlock blocker(m_UpdateConnection); this->UpdateGeometry(); this->UpdateTransform(); + this->Prop3D::Update(); +} + +void GeantSolid::SyncFromVtk() { + if (!m_Content) return; + this->Prop3D::SyncFromVtk(); + + if (auto* proxy = vtkProp3D::SafeDownCast(this->GetProxyProp())) { + if (vtkMatrix4x4* mat = proxy->GetUserMatrix()) { + m_Content->SetTransform(VtkToMatrix4f(mat)); + } + } } void GeantSolid::UpdateGeometry() { @@ -114,33 +137,36 @@ void GeantSolid::UpdateTransform() { if (!m_Content || !m_SolidActor) return; - // 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(); + // Apply the Geant4 transform (position/rotation/scaling) + G4ThreeVector pos = m_Content->GetPosition(); + const G4RotationMatrix *rot = m_Content->GetRotation(); + G4ThreeVector scale = m_Content->GetScaling(); - vtkSmartPointer transform = vtkSmartPointer::New(); - transform->Identity(); - transform->Translate(pos.x(), pos.y(), pos.z()); + std::cout << "GeantSolid: Updating transform. Pos: " << pos.x() << " " << pos.y() << " " << pos.z() + << " Scale: " << scale.x() << " " << scale.y() << " " << scale.z() << std::endl; - 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); - } + 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(); } -} void GeantSolid::InstallPipe() { vtkSmartPointer polyData = vtkSmartPointer::New(); diff --git a/src/Vtk/HEP/Geant/vtkGeantSolid.h b/src/Vtk/HEP/Geant/vtkGeantSolid.h index 93ddea7..626c820 100644 --- a/src/Vtk/HEP/Geant/vtkGeantSolid.h +++ b/src/Vtk/HEP/Geant/vtkGeantSolid.h @@ -52,15 +52,19 @@ public: virtual class vtkPolyData *GetPolyData() const override; virtual void Update() override; + virtual void SyncFromVtk() override; virtual void UpdateGeometry(); virtual void UpdateTransform(); + virtual uLib::Object *GetContent() const override { return (uLib::Object*)m_Content; } + protected: virtual void InstallPipe(); - - vtkActor *m_SolidActor; + Content *m_Content; + vtkActor *m_SolidActor; + uLib::Connection m_UpdateConnection; }; } // namespace Vtk diff --git a/src/Vtk/vtkObjectsContext.h b/src/Vtk/vtkObjectsContext.h index 7448922..a067a72 100644 --- a/src/Vtk/vtkObjectsContext.h +++ b/src/Vtk/vtkObjectsContext.h @@ -33,6 +33,8 @@ public: /** @brief Synchronizes all managed prop3ds back to their models. */ virtual void SyncFromVtk() override; + virtual Object* GetContent() const override { return (Object*)m_Context; } + public: virtual void Prop3DAdded(Prop3D* prop3d); virtual void Prop3DRemoved(Prop3D* prop3d);