attach vtk context to gcompose
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <cxxabi.h>
|
#include <cxxabi.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include "Core/Object.h"
|
||||||
|
|
||||||
ContextModel::ContextModel(QObject* parent)
|
ContextModel::ContextModel(QObject* parent)
|
||||||
: QAbstractItemModel(parent), m_rootContext(nullptr) {}
|
: QAbstractItemModel(parent), m_rootContext(nullptr) {}
|
||||||
@@ -12,6 +13,12 @@ ContextModel::~ContextModel() {}
|
|||||||
void ContextModel::setContext(uLib::ObjectsContext* context) {
|
void ContextModel::setContext(uLib::ObjectsContext* context) {
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
m_rootContext = context;
|
m_rootContext = context;
|
||||||
|
if (m_rootContext) {
|
||||||
|
uLib::Object::connect(m_rootContext, &uLib::Object::Updated, [this]() {
|
||||||
|
this->beginResetModel();
|
||||||
|
this->endResetModel();
|
||||||
|
});
|
||||||
|
}
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +125,14 @@ QVariant ContextModel::data(const QModelIndex& index, int role) const {
|
|||||||
uLib::Object* obj = static_cast<uLib::Object*>(index.internalPointer());
|
uLib::Object* obj = static_cast<uLib::Object*>(index.internalPointer());
|
||||||
|
|
||||||
if (role == Qt::DisplayRole) {
|
if (role == Qt::DisplayRole) {
|
||||||
return getDemangledName(typeid(*obj));
|
QString typeName = getDemangledName(typeid(*obj));
|
||||||
|
std::string instName = obj->GetInstanceName();
|
||||||
|
if (instName.empty()) return typeName;
|
||||||
|
return QString("%1 (%2)").arg(QString::fromStdString(instName)).arg(typeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role == Qt::EditRole) {
|
||||||
|
return QString::fromStdString(obj->GetInstanceName());
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
@@ -130,3 +144,18 @@ QVariant ContextModel::headerData(int section, Qt::Orientation orientation, int
|
|||||||
}
|
}
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags ContextModel::flags(const QModelIndex& index) const {
|
||||||
|
if (!index.isValid()) return Qt::NoItemFlags;
|
||||||
|
return Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ContextModel::setData(const QModelIndex& index, const QVariant& value, int role) {
|
||||||
|
if (index.isValid() && role == Qt::EditRole) {
|
||||||
|
uLib::Object* obj = static_cast<uLib::Object*>(index.internalPointer());
|
||||||
|
obj->SetInstanceName(value.toString().toStdString());
|
||||||
|
emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ public:
|
|||||||
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
int columnCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||||
|
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||||
|
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uLib::ObjectsContext* m_rootContext;
|
uLib::ObjectsContext* m_rootContext;
|
||||||
|
|||||||
@@ -4,8 +4,16 @@
|
|||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QTreeView>
|
#include <QTreeView>
|
||||||
|
#include <QSplitter>
|
||||||
|
#include <QList>
|
||||||
|
#include <QShortcut>
|
||||||
|
#include <QItemSelectionModel>
|
||||||
|
#include <Vtk/vtkQViewport.h>
|
||||||
|
#include <Vtk/vtkObjectsContext.h>
|
||||||
|
|
||||||
ContextPanel::ContextPanel(QWidget* parent) : QWidget(parent) {
|
ContextPanel::ContextPanel(QWidget* parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
, m_vtkContext(nullptr) {
|
||||||
m_layout = new QVBoxLayout(this);
|
m_layout = new QVBoxLayout(this);
|
||||||
m_layout->setContentsMargins(0, 0, 0, 0);
|
m_layout->setContentsMargins(0, 0, 0, 0);
|
||||||
m_layout->setSpacing(0);
|
m_layout->setSpacing(0);
|
||||||
@@ -32,12 +40,92 @@ ContextPanel::ContextPanel(QWidget* parent) : QWidget(parent) {
|
|||||||
m_model = new ContextModel(this);
|
m_model = new ContextModel(this);
|
||||||
m_treeView->setModel(m_model);
|
m_treeView->setModel(m_model);
|
||||||
|
|
||||||
m_layout->addWidget(m_treeView);
|
m_splitter = new QSplitter(Qt::Vertical, this);
|
||||||
|
m_splitter->addWidget(m_treeView);
|
||||||
|
|
||||||
|
m_vtkView = new uLib::Vtk::QViewport(m_splitter);
|
||||||
|
m_splitter->addWidget(m_vtkView);
|
||||||
|
|
||||||
|
QList<int> sizes;
|
||||||
|
sizes << 400 << 200;
|
||||||
|
m_splitter->setSizes(sizes);
|
||||||
|
|
||||||
|
m_layout->addWidget(m_splitter);
|
||||||
|
|
||||||
|
connect(m_treeView->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||||
|
this, &ContextPanel::onSelectionChanged);
|
||||||
|
|
||||||
|
auto* deleteShortcut = new QShortcut(QKeySequence::Delete, this);
|
||||||
|
connect(deleteShortcut, &QShortcut::activated, [this]() {
|
||||||
|
auto selectedIndexes = m_treeView->selectionModel()->selectedIndexes();
|
||||||
|
if (selectedIndexes.isEmpty() || !m_context) return;
|
||||||
|
|
||||||
|
// Collect objects to remove to avoid iterator invalidation issues if context signal emits during removal
|
||||||
|
std::vector<uLib::Object*> toRemove;
|
||||||
|
for (const auto& idx : selectedIndexes) {
|
||||||
|
if (idx.column() == 0) {
|
||||||
|
toRemove.push_back(static_cast<uLib::Object*>(idx.internalPointer()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto* obj : toRemove) {
|
||||||
|
m_context->RemoveObject(obj);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ContextPanel::~ContextPanel() {}
|
ContextPanel::~ContextPanel() {}
|
||||||
|
|
||||||
void ContextPanel::setContext(uLib::ObjectsContext* context) {
|
void ContextPanel::setContext(uLib::ObjectsContext* context) {
|
||||||
|
m_context = context;
|
||||||
m_model->setContext(context);
|
m_model->setContext(context);
|
||||||
m_treeView->expandAll();
|
m_treeView->expandAll();
|
||||||
|
|
||||||
|
if (m_vtkContext) {
|
||||||
|
m_vtkView->RemovePuppet(*m_vtkContext);
|
||||||
|
delete m_vtkContext;
|
||||||
|
}
|
||||||
|
m_vtkContext = new uLib::Vtk::vtkObjectsContext(context);
|
||||||
|
m_vtkView->AddPuppet(*m_vtkContext);
|
||||||
|
|
||||||
|
// Render viewport and add child puppets when context is updated
|
||||||
|
if (context) {
|
||||||
|
uLib::Object::connect(m_vtkContext, &uLib::Vtk::vtkObjectsContext::PuppetAdded, [this](uLib::Vtk::Puppet* p) {
|
||||||
|
if (this->m_vtkView && p) {
|
||||||
|
this->m_vtkView->AddPuppet(*p);
|
||||||
|
this->m_vtkView->ZoomAuto();
|
||||||
|
this->m_vtkView->Render();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add any puppets that were created during m_vtkContext's construction
|
||||||
|
for (auto* obj : context->GetObjects()) {
|
||||||
|
if (auto* p = m_vtkContext->GetPuppet(obj)) {
|
||||||
|
this->m_vtkView->AddPuppet(*p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uLib::Object::connect(context, &uLib::Object::Updated, [this]() {
|
||||||
|
if (this->m_vtkView) {
|
||||||
|
this->m_vtkView->ZoomAuto();
|
||||||
|
this->m_vtkView->Render();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
m_vtkView->Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContextPanel::onSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected) {
|
||||||
|
uLib::Object* target = nullptr;
|
||||||
|
if (!selected.indexes().isEmpty()) {
|
||||||
|
target = static_cast<uLib::Object*>(selected.indexes().first().internalPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
emit objectSelected(target);
|
||||||
|
|
||||||
|
if (m_vtkContext) {
|
||||||
|
auto* puppet = m_vtkContext->GetPuppet(target);
|
||||||
|
m_vtkView->SelectPuppet(puppet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define CONTEXT_PANEL_H
|
#define CONTEXT_PANEL_H
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include <QItemSelection>
|
||||||
|
|
||||||
class QTreeView;
|
class QTreeView;
|
||||||
class QVBoxLayout;
|
class QVBoxLayout;
|
||||||
@@ -9,9 +10,16 @@ class QLabel;
|
|||||||
class ContextModel;
|
class ContextModel;
|
||||||
|
|
||||||
namespace uLib {
|
namespace uLib {
|
||||||
|
class Object;
|
||||||
class ObjectsContext;
|
class ObjectsContext;
|
||||||
|
namespace Vtk {
|
||||||
|
class QViewport;
|
||||||
|
class vtkObjectsContext;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class QSplitter;
|
||||||
|
|
||||||
class ContextPanel : public QWidget {
|
class ContextPanel : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -20,12 +28,22 @@ public:
|
|||||||
|
|
||||||
void setContext(uLib::ObjectsContext* context);
|
void setContext(uLib::ObjectsContext* context);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void objectSelected(uLib::Object* obj);
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void onSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVBoxLayout* m_layout;
|
QVBoxLayout* m_layout;
|
||||||
QWidget* m_titleBar;
|
QWidget* m_titleBar;
|
||||||
QLabel* m_titleLabel;
|
QLabel* m_titleLabel;
|
||||||
QTreeView* m_treeView;
|
QTreeView* m_treeView;
|
||||||
ContextModel* m_model;
|
ContextModel* m_model;
|
||||||
|
QSplitter* m_splitter;
|
||||||
|
uLib::Vtk::QViewport* m_vtkView;
|
||||||
|
uLib::Vtk::vtkObjectsContext* m_vtkContext;
|
||||||
|
uLib::ObjectsContext* m_context;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONTEXT_PANEL_H
|
#endif // CONTEXT_PANEL_H
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
#include "MainPanel.h"
|
#include "MainPanel.h"
|
||||||
#include "ViewportPane.h"
|
#include "ViewportPane.h"
|
||||||
#include "ContextPanel.h"
|
#include "ContextPanel.h"
|
||||||
|
#include "Core/ObjectFactory.h"
|
||||||
|
#include "Core/ObjectsContext.h"
|
||||||
|
#include "Vtk/vtkObjectsContext.h"
|
||||||
|
#include "Vtk/vtkQViewport.h"
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QSplitter>
|
#include <QSplitter>
|
||||||
@@ -11,7 +15,7 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include "StyleManager.h"
|
#include "StyleManager.h"
|
||||||
|
|
||||||
MainPanel::MainPanel(QWidget* parent) : QWidget(parent) {
|
MainPanel::MainPanel(QWidget* parent) : QWidget(parent), m_context(nullptr), m_mainVtkContext(nullptr) {
|
||||||
auto* mainLayout = new QVBoxLayout(this);
|
auto* mainLayout = new QVBoxLayout(this);
|
||||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
mainLayout->setSpacing(0);
|
mainLayout->setSpacing(0);
|
||||||
@@ -44,8 +48,23 @@ MainPanel::MainPanel(QWidget* parent) : QWidget(parent) {
|
|||||||
themeMenu->addAction("Bright", this, &MainPanel::onBrightTheme);
|
themeMenu->addAction("Bright", this, &MainPanel::onBrightTheme);
|
||||||
btnTheme->setMenu(themeMenu);
|
btnTheme->setMenu(themeMenu);
|
||||||
|
|
||||||
|
// New Menu Button
|
||||||
|
auto* btnNew = new QPushButton("New", menuPanel);
|
||||||
|
btnNew->setObjectName("MenuButton");
|
||||||
|
auto* newMenu = new QMenu(btnNew);
|
||||||
|
|
||||||
|
auto classes = uLib::ObjectFactory::Instance().GetRegisteredClasses();
|
||||||
|
for (const auto& className : classes) {
|
||||||
|
auto* action = newMenu->addAction(QString::fromStdString(className));
|
||||||
|
connect(action, &QAction::triggered, [this, className]() {
|
||||||
|
this->onCreateObject(className);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
btnNew->setMenu(newMenu);
|
||||||
|
|
||||||
menuLayout->addWidget(logo);
|
menuLayout->addWidget(logo);
|
||||||
menuLayout->addWidget(btnFile);
|
menuLayout->addWidget(btnFile);
|
||||||
|
menuLayout->addWidget(btnNew);
|
||||||
menuLayout->addWidget(btnTheme);
|
menuLayout->addWidget(btnTheme);
|
||||||
menuLayout->addStretch();
|
menuLayout->addStretch();
|
||||||
|
|
||||||
@@ -58,6 +77,16 @@ MainPanel::MainPanel(QWidget* parent) : QWidget(parent) {
|
|||||||
m_firstPane = new ViewportPane(m_rootSplitter);
|
m_firstPane = new ViewportPane(m_rootSplitter);
|
||||||
m_rootSplitter->addWidget(m_firstPane);
|
m_rootSplitter->addWidget(m_firstPane);
|
||||||
|
|
||||||
|
connect(m_contextPanel, &ContextPanel::objectSelected, [this](uLib::Object* obj) {
|
||||||
|
if (auto* viewport = qobject_cast<uLib::Vtk::QViewport*>(m_firstPane->currentViewport())) {
|
||||||
|
uLib::Vtk::Puppet* puppet = nullptr;
|
||||||
|
if (m_mainVtkContext) {
|
||||||
|
puppet = m_mainVtkContext->GetPuppet(obj);
|
||||||
|
}
|
||||||
|
viewport->SelectPuppet(puppet);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Set initial sizes
|
// Set initial sizes
|
||||||
QList<int> sizes;
|
QList<int> sizes;
|
||||||
sizes << 200 << 1000;
|
sizes << 200 << 1000;
|
||||||
@@ -67,7 +96,52 @@ MainPanel::MainPanel(QWidget* parent) : QWidget(parent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainPanel::setContext(uLib::ObjectsContext* context) {
|
void MainPanel::setContext(uLib::ObjectsContext* context) {
|
||||||
|
m_context = context;
|
||||||
m_contextPanel->setContext(context);
|
m_contextPanel->setContext(context);
|
||||||
|
|
||||||
|
if (m_mainVtkContext) {
|
||||||
|
if (auto* viewport = qobject_cast<uLib::Vtk::QViewport*>(m_firstPane->currentViewport())) {
|
||||||
|
viewport->RemovePuppet(*m_mainVtkContext);
|
||||||
|
}
|
||||||
|
delete m_mainVtkContext;
|
||||||
|
m_mainVtkContext = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context) {
|
||||||
|
if (auto* viewport = qobject_cast<uLib::Vtk::QViewport*>(m_firstPane->currentViewport())) {
|
||||||
|
m_mainVtkContext = new uLib::Vtk::vtkObjectsContext(context);
|
||||||
|
viewport->AddPuppet(*m_mainVtkContext);
|
||||||
|
uLib::Object::connect(m_mainVtkContext, &uLib::Vtk::vtkObjectsContext::PuppetAdded, [viewport](uLib::Vtk::Puppet* p) {
|
||||||
|
if (viewport && p) {
|
||||||
|
viewport->AddPuppet(*p);
|
||||||
|
viewport->ZoomAuto();
|
||||||
|
viewport->Render();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add any puppets that were created during m_mainVtkContext's construction
|
||||||
|
for (auto* obj : context->GetObjects()) {
|
||||||
|
if (auto* p = m_mainVtkContext->GetPuppet(obj)) {
|
||||||
|
viewport->AddPuppet(*p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uLib::Object::connect(context, &uLib::Object::Updated, [viewport]() {
|
||||||
|
viewport->ZoomAuto();
|
||||||
|
viewport->Render();
|
||||||
|
});
|
||||||
|
viewport->ZoomAuto();
|
||||||
|
viewport->Render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainPanel::onCreateObject(const std::string& className) {
|
||||||
|
if (!m_context) return;
|
||||||
|
auto* obj = uLib::ObjectFactory::Instance().Create(className);
|
||||||
|
if (obj) {
|
||||||
|
m_context->AddObject(obj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainPanel::onOpen() {
|
void MainPanel::onOpen() {
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ class ContextPanel;
|
|||||||
|
|
||||||
namespace uLib {
|
namespace uLib {
|
||||||
class ObjectsContext;
|
class ObjectsContext;
|
||||||
|
namespace Vtk {
|
||||||
|
class vtkObjectsContext;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MainPanel : public QWidget {
|
class MainPanel : public QWidget {
|
||||||
@@ -26,10 +29,14 @@ private slots:
|
|||||||
void onDarkTheme();
|
void onDarkTheme();
|
||||||
void onBrightTheme();
|
void onBrightTheme();
|
||||||
|
|
||||||
|
void onCreateObject(const std::string& className);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSplitter* m_rootSplitter;
|
QSplitter* m_rootSplitter;
|
||||||
ViewportPane* m_firstPane;
|
ViewportPane* m_firstPane;
|
||||||
ContextPanel* m_contextPanel;
|
ContextPanel* m_contextPanel;
|
||||||
|
uLib::ObjectsContext* m_context;
|
||||||
|
uLib::Vtk::vtkObjectsContext* m_mainVtkContext;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MAINPANEL_H
|
#endif // MAINPANEL_H
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ int main(int argc, char** argv) {
|
|||||||
std::cout << "Starting gcompose Qt application..." << std::endl;
|
std::cout << "Starting gcompose Qt application..." << std::endl;
|
||||||
|
|
||||||
ContainerBox world_box(Vector3f(1, 1, 1));
|
ContainerBox world_box(Vector3f(1, 1, 1));
|
||||||
world_box.Scale(Vector3f(20_mm, 20_mm, 20_mm));
|
world_box.Scale(Vector3f(2_mm, 2_mm, 2_mm));
|
||||||
|
world_box.SetPosition(Vector3f(-1_mm, -1_mm, -1_mm));
|
||||||
|
|
||||||
Geant::Scene scene;
|
Geant::Scene scene;
|
||||||
scene.ConstructWorldBox(world_box.GetSize(), "G4_AIR");
|
scene.ConstructWorldBox(world_box.GetSize(), "G4_AIR");
|
||||||
@@ -46,13 +47,6 @@ int main(int argc, char** argv) {
|
|||||||
// 2. Initialize MainWindow (contains embedded VTK QViewport)
|
// 2. Initialize MainWindow (contains embedded VTK QViewport)
|
||||||
MainWindow window;
|
MainWindow window;
|
||||||
window.setContext(&globalContext);
|
window.setContext(&globalContext);
|
||||||
MainPanel* panel = window.getPanel();
|
|
||||||
ViewportPane* pane = panel->getFirstPane();
|
|
||||||
Vtk::QViewport* viewport = qobject_cast<Vtk::QViewport*>(pane->currentViewport());
|
|
||||||
|
|
||||||
Vtk::vtkContainerBox vtk_box(&world_box);
|
|
||||||
viewport->AddPuppet(vtk_box);
|
|
||||||
viewport->ZoomAuto();
|
|
||||||
|
|
||||||
std::cout << "Geant4 and VTK scenes are ready." << std::endl;
|
std::cout << "Geant4 and VTK scenes are ready." << std::endl;
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ set(HEADERS
|
|||||||
Macros.h
|
Macros.h
|
||||||
Mpl.h
|
Mpl.h
|
||||||
Object.h
|
Object.h
|
||||||
|
ObjectFactory.h
|
||||||
ObjectsContext.h
|
ObjectsContext.h
|
||||||
Options.h
|
Options.h
|
||||||
Serializable.h
|
Serializable.h
|
||||||
@@ -27,6 +28,7 @@ set(SOURCES
|
|||||||
Archives.cpp
|
Archives.cpp
|
||||||
Debug.cpp
|
Debug.cpp
|
||||||
Object.cpp
|
Object.cpp
|
||||||
|
ObjectFactory.cpp
|
||||||
ObjectsContext.cpp
|
ObjectsContext.cpp
|
||||||
Options.cpp
|
Options.cpp
|
||||||
Serializable.cpp
|
Serializable.cpp
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ public:
|
|||||||
std::string slostr;
|
std::string slostr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::string m_InstanceName;
|
||||||
Vector<Signal> sigv;
|
Vector<Signal> sigv;
|
||||||
Vector<Slot> slov;
|
Vector<Slot> slov;
|
||||||
};
|
};
|
||||||
@@ -147,6 +148,15 @@ GenericMFPtr *Object::findSlotImpl(const char *name) const {
|
|||||||
|
|
||||||
void Object::Updated() { ULIB_SIGNAL_EMIT(Object::Updated); }
|
void Object::Updated() { ULIB_SIGNAL_EMIT(Object::Updated); }
|
||||||
|
|
||||||
|
const std::string& Object::GetInstanceName() const {
|
||||||
|
return d->m_InstanceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Object::SetInstanceName(const std::string& name) {
|
||||||
|
d->m_InstanceName = name;
|
||||||
|
this->Updated();
|
||||||
|
}
|
||||||
|
|
||||||
// std::ostream &
|
// std::ostream &
|
||||||
// operator << (std::ostream &os, uLib::Object &ob)
|
// operator << (std::ostream &os, uLib::Object &ob)
|
||||||
// {
|
// {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#define U_CORE_OBJECT_H
|
#define U_CORE_OBJECT_H
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
// WARNING: COPILE ERROR if this goes after mpl/vector //
|
// WARNING: COPILE ERROR if this goes after mpl/vector //
|
||||||
// #include "Core/Vector.h"
|
// #include "Core/Vector.h"
|
||||||
@@ -74,6 +75,10 @@ public:
|
|||||||
Object(const Object ©);
|
Object(const Object ©);
|
||||||
~Object();
|
~Object();
|
||||||
|
|
||||||
|
virtual const char * GetClassName() const { return "Object"; }
|
||||||
|
|
||||||
|
const std::string& GetInstanceName() const;
|
||||||
|
void SetInstanceName(const std::string& name);
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// PARAMETERS //
|
// PARAMETERS //
|
||||||
|
|
||||||
|
|||||||
32
src/Core/ObjectFactory.cpp
Normal file
32
src/Core/ObjectFactory.cpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#include "ObjectFactory.h"
|
||||||
|
|
||||||
|
namespace uLib {
|
||||||
|
|
||||||
|
ObjectFactory& ObjectFactory::Instance() {
|
||||||
|
static ObjectFactory instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectFactory::Register(const std::string& className, FactoryFunction func) {
|
||||||
|
if (m_factoryMap.find(className) == m_factoryMap.end()) {
|
||||||
|
m_factoryMap[className] = func;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object* ObjectFactory::Create(const std::string& className) {
|
||||||
|
auto it = m_factoryMap.find(className);
|
||||||
|
if (it != m_factoryMap.end()) {
|
||||||
|
return (it->second)();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> ObjectFactory::GetRegisteredClasses() const {
|
||||||
|
std::vector<std::string> classes;
|
||||||
|
for (auto const& [name, func] : m_factoryMap) {
|
||||||
|
classes.push_back(name);
|
||||||
|
}
|
||||||
|
return classes;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace uLib
|
||||||
68
src/Core/ObjectFactory.h
Normal file
68
src/Core/ObjectFactory.h
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#ifndef U_CORE_OBJECTFACTORY_H
|
||||||
|
#define U_CORE_OBJECTFACTORY_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
#include "Core/Object.h"
|
||||||
|
|
||||||
|
namespace uLib {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Singleton factory for dynamic Object instantiation based on class name.
|
||||||
|
*/
|
||||||
|
class ObjectFactory {
|
||||||
|
public:
|
||||||
|
typedef std::function<Object*()> FactoryFunction;
|
||||||
|
|
||||||
|
/** @brief Get the singleton instance. */
|
||||||
|
static ObjectFactory& Instance();
|
||||||
|
|
||||||
|
/** @brief Register a factory function for a given class name. */
|
||||||
|
void Register(const std::string& className, FactoryFunction func);
|
||||||
|
|
||||||
|
/** @brief Create a new instance of the specified class. */
|
||||||
|
Object* Create(const std::string& className);
|
||||||
|
|
||||||
|
/** @brief Get the names of all registered classes. */
|
||||||
|
std::vector<std::string> GetRegisteredClasses() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ObjectFactory() = default;
|
||||||
|
~ObjectFactory() = default;
|
||||||
|
|
||||||
|
// Prevent copy and assignment
|
||||||
|
ObjectFactory(const ObjectFactory&) = delete;
|
||||||
|
ObjectFactory& operator=(const ObjectFactory&) = delete;
|
||||||
|
|
||||||
|
std::map<std::string, FactoryFunction> m_factoryMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper class to statically register a factory function.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class ObjectRegistrar {
|
||||||
|
public:
|
||||||
|
ObjectRegistrar(const std::string& className) {
|
||||||
|
ObjectFactory::Instance().Register(className, []() -> Object* { return new T(); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ULIB_REG_CONCAT_IMPL(a, b) a##b
|
||||||
|
#define ULIB_REG_CONCAT(a, b) ULIB_REG_CONCAT_IMPL(a, b)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Macro to register a class to the factory.
|
||||||
|
* Put this in the .cpp file of the class.
|
||||||
|
*/
|
||||||
|
#define ULIB_REGISTER_OBJECT(className) \
|
||||||
|
static uLib::ObjectRegistrar<className> ULIB_REG_CONCAT(g_ObjectRegistrar_, __LINE__)(#className);
|
||||||
|
|
||||||
|
#define ULIB_REGISTER_OBJECT_NAME(className, registeredName) \
|
||||||
|
static uLib::ObjectRegistrar<className> ULIB_REG_CONCAT(g_ObjectRegistrar_, __LINE__)(registeredName);
|
||||||
|
|
||||||
|
} // namespace uLib
|
||||||
|
|
||||||
|
#endif // U_CORE_OBJECTFACTORY_H
|
||||||
@@ -10,6 +10,7 @@ ObjectsContext::~ObjectsContext() {}
|
|||||||
void ObjectsContext::AddObject(Object* obj) {
|
void ObjectsContext::AddObject(Object* obj) {
|
||||||
if (obj && std::find(m_objects.begin(), m_objects.end(), obj) == m_objects.end()) {
|
if (obj && std::find(m_objects.begin(), m_objects.end(), obj) == m_objects.end()) {
|
||||||
m_objects.push_back(obj);
|
m_objects.push_back(obj);
|
||||||
|
ULIB_SIGNAL_EMIT(ObjectsContext::ObjectAdded, obj);
|
||||||
this->Updated(); // Signal that the context has been updated
|
this->Updated(); // Signal that the context has been updated
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,13 +18,18 @@ void ObjectsContext::AddObject(Object* obj) {
|
|||||||
void ObjectsContext::RemoveObject(Object* obj) {
|
void ObjectsContext::RemoveObject(Object* obj) {
|
||||||
auto it = std::find(m_objects.begin(), m_objects.end(), obj);
|
auto it = std::find(m_objects.begin(), m_objects.end(), obj);
|
||||||
if (it != m_objects.end()) {
|
if (it != m_objects.end()) {
|
||||||
|
Object* removedObj = *it;
|
||||||
m_objects.erase(it);
|
m_objects.erase(it);
|
||||||
|
ULIB_SIGNAL_EMIT(ObjectsContext::ObjectRemoved, removedObj);
|
||||||
this->Updated(); // Signal that the context has been updated
|
this->Updated(); // Signal that the context has been updated
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectsContext::Clear() {
|
void ObjectsContext::Clear() {
|
||||||
if (!m_objects.empty()) {
|
if (!m_objects.empty()) {
|
||||||
|
for (auto obj : m_objects) {
|
||||||
|
ULIB_SIGNAL_EMIT(ObjectsContext::ObjectRemoved, obj);
|
||||||
|
}
|
||||||
m_objects.clear();
|
m_objects.clear();
|
||||||
this->Updated();
|
this->Updated();
|
||||||
}
|
}
|
||||||
@@ -44,4 +50,12 @@ Object* ObjectsContext::GetObject(size_t index) const {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ObjectsContext::ObjectAdded(Object* obj) {
|
||||||
|
ULIB_SIGNAL_EMIT(ObjectsContext::ObjectAdded, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectsContext::ObjectRemoved(Object* obj) {
|
||||||
|
ULIB_SIGNAL_EMIT(ObjectsContext::ObjectRemoved, obj);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace uLib
|
} // namespace uLib
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ public:
|
|||||||
ObjectsContext();
|
ObjectsContext();
|
||||||
virtual ~ObjectsContext();
|
virtual ~ObjectsContext();
|
||||||
|
|
||||||
|
virtual const char * GetClassName() const { return "ObjectsContext"; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Adds an object to the context.
|
* @brief Adds an object to the context.
|
||||||
* @param obj Pointer to the object to add.
|
* @param obj Pointer to the object to add.
|
||||||
@@ -37,6 +39,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
const std::vector<Object*>& GetObjects() const;
|
const std::vector<Object*>& GetObjects() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
/** @brief Signal emitted when an object is added. */
|
||||||
|
virtual void ObjectAdded(Object* obj);
|
||||||
|
/** @brief Signal emitted when an object is removed. */
|
||||||
|
virtual void ObjectRemoved(Object* obj);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the number of objects in the context.
|
* @brief Returns the number of objects in the context.
|
||||||
* @return Size of the collection.
|
* @return Size of the collection.
|
||||||
|
|||||||
@@ -43,11 +43,23 @@ using namespace boost::placeholders;
|
|||||||
// Signals macro //
|
// Signals macro //
|
||||||
|
|
||||||
#define default(vlaue)
|
#define default(vlaue)
|
||||||
#define slots
|
#ifndef Q_MOC_RUN
|
||||||
|
#ifndef signals
|
||||||
#define signals /*virtual void init_signals();*/ public
|
#define signals /*virtual void init_signals();*/ public
|
||||||
|
#endif
|
||||||
|
#ifndef slots
|
||||||
|
#define slots
|
||||||
|
#endif
|
||||||
|
#ifndef emit
|
||||||
#define emit
|
#define emit
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifndef SLOT
|
||||||
#define SLOT(a) BOOST_STRINGIZE(a)
|
#define SLOT(a) BOOST_STRINGIZE(a)
|
||||||
|
#endif
|
||||||
|
#ifndef SIGNAL
|
||||||
#define SIGNAL(a) BOOST_STRINGIZE(a)
|
#define SIGNAL(a) BOOST_STRINGIZE(a)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define _ULIB_DETAIL_SIGNAL_EMIT(_name, ...) \
|
#define _ULIB_DETAIL_SIGNAL_EMIT(_name, ...) \
|
||||||
do { \
|
do { \
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "HEP/Detectors/DetectorChamber.h"
|
#include "HEP/Detectors/DetectorChamber.h"
|
||||||
|
#include "Core/ObjectFactory.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
namespace uLib {
|
namespace uLib {
|
||||||
@@ -43,4 +44,6 @@ MuonEvent DetectorChamber::ProjectMuonEvent(const MuonEvent &muon) const {
|
|||||||
return projectedMuon;
|
return projectedMuon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ULIB_REGISTER_OBJECT(DetectorChamber)
|
||||||
|
|
||||||
} // namespace uLib
|
} // namespace uLib
|
||||||
@@ -45,6 +45,8 @@ class DetectorChamber : public ContainerBox {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char * GetClassName() const { return "DetectorChamber"; }
|
||||||
|
|
||||||
DetectorChamber() : BaseClass() {
|
DetectorChamber() : BaseClass() {
|
||||||
m_ProjectionPlane.origin = HPoint3f(0, 0, 0);
|
m_ProjectionPlane.origin = HPoint3f(0, 0, 0);
|
||||||
m_ProjectionPlane.direction = HVector3f(0, 0, 1);
|
m_ProjectionPlane.direction = HVector3f(0, 0, 1);
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ namespace Geant {
|
|||||||
class EmitterPrimary : public G4VUserPrimaryGeneratorAction, public Object, public AffineTransform
|
class EmitterPrimary : public G4VUserPrimaryGeneratorAction, public Object, public AffineTransform
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char* GetClassName() const override { return "Geant.EmitterPrimary"; }
|
||||||
|
|
||||||
EmitterPrimary();
|
EmitterPrimary();
|
||||||
virtual ~EmitterPrimary();
|
virtual ~EmitterPrimary();
|
||||||
|
|
||||||
@@ -44,6 +47,9 @@ class EmitterPrimary : public G4VUserPrimaryGeneratorAction, public Object, publ
|
|||||||
class SkyPlaneEmitterPrimary : public EmitterPrimary
|
class SkyPlaneEmitterPrimary : public EmitterPrimary
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char* GetClassName() const override { return "Geant.SkyPlaneEmitterPrimary"; }
|
||||||
|
|
||||||
SkyPlaneEmitterPrimary();
|
SkyPlaneEmitterPrimary();
|
||||||
virtual ~SkyPlaneEmitterPrimary();
|
virtual ~SkyPlaneEmitterPrimary();
|
||||||
|
|
||||||
@@ -63,6 +69,9 @@ class SkyPlaneEmitterPrimary : public EmitterPrimary
|
|||||||
class CylinderEmitterPrimary : public EmitterPrimary
|
class CylinderEmitterPrimary : public EmitterPrimary
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char* GetClassName() const override { return "Geant.CylinderEmitterPrimary"; }
|
||||||
|
|
||||||
CylinderEmitterPrimary();
|
CylinderEmitterPrimary();
|
||||||
virtual ~CylinderEmitterPrimary();
|
virtual ~CylinderEmitterPrimary();
|
||||||
|
|
||||||
@@ -89,6 +98,9 @@ class CylinderEmitterPrimary : public EmitterPrimary
|
|||||||
class QuadMeshEmitterPrimary : public EmitterPrimary
|
class QuadMeshEmitterPrimary : public EmitterPrimary
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char* GetClassName() const override { return "Geant.QuadMeshEmitterPrimary"; }
|
||||||
|
|
||||||
QuadMeshEmitterPrimary();
|
QuadMeshEmitterPrimary();
|
||||||
virtual ~QuadMeshEmitterPrimary();
|
virtual ~QuadMeshEmitterPrimary();
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#ifndef U_GEANTEVENT_H
|
#ifndef U_GEANTEVENT_H
|
||||||
#define U_GEANTEVENT_H
|
#define U_GEANTEVENT_H
|
||||||
|
|
||||||
|
#include "Core/Object.h"
|
||||||
#include "Core/Types.h"
|
#include "Core/Types.h"
|
||||||
#include "Core/Vector.h"
|
#include "Core/Vector.h"
|
||||||
#include "Math/Dense.h"
|
#include "Math/Dense.h"
|
||||||
@@ -46,10 +47,12 @@ class SteppingAction;
|
|||||||
/// recording the change of momentum and direction at each step boundary.
|
/// recording the change of momentum and direction at each step boundary.
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class GeantEvent {
|
class GeantEvent : public Object {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char* GetClassName() const override { return "Geant.GeantEvent"; }
|
||||||
|
|
||||||
/// A single interaction step along the muon path.
|
/// A single interaction step along the muon path.
|
||||||
struct Delta {
|
struct Delta {
|
||||||
Scalarf m_Length; ///< step length through the solid
|
Scalarf m_Length; ///< step length through the solid
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ private:
|
|||||||
class Material : public Object {
|
class Material : public Object {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char* GetClassName() const override { return "Geant.Material"; }
|
||||||
|
|
||||||
uLibRefMacro(G4Data,G4Material *)
|
uLibRefMacro(G4Data,G4Material *)
|
||||||
private:
|
private:
|
||||||
G4Material *m_G4Data;
|
G4Material *m_G4Data;
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ class EmitterPrimary;
|
|||||||
|
|
||||||
class Scene : public Object {
|
class Scene : public Object {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char* GetClassName() const override { return "Geant.Scene"; }
|
||||||
|
|
||||||
Scene();
|
Scene();
|
||||||
~Scene();
|
~Scene();
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ namespace Geant {
|
|||||||
|
|
||||||
class Solid : public Object {
|
class Solid : public Object {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char* GetClassName() const override { return "Geant.Solid"; }
|
||||||
|
|
||||||
Solid();
|
Solid();
|
||||||
Solid(const char *name);
|
Solid(const char *name);
|
||||||
virtual ~Solid();
|
virtual ~Solid();
|
||||||
@@ -83,6 +86,9 @@ protected:
|
|||||||
class TessellatedSolid : public Solid {
|
class TessellatedSolid : public Solid {
|
||||||
typedef Solid BaseClass;
|
typedef Solid BaseClass;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char* GetClassName() const override { return "Geant.TessellatedSolid"; }
|
||||||
|
|
||||||
TessellatedSolid(const char *name);
|
TessellatedSolid(const char *name);
|
||||||
void SetMesh(TriangleMesh &mesh);
|
void SetMesh(TriangleMesh &mesh);
|
||||||
uLibGetMacro(Solid, G4TessellatedSolid *)
|
uLibGetMacro(Solid, G4TessellatedSolid *)
|
||||||
@@ -104,6 +110,9 @@ class BoxSolid : public Solid {
|
|||||||
typedef Solid BaseClass;
|
typedef Solid BaseClass;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char* GetClassName() const override { return "Geant.BoxSolid"; }
|
||||||
|
|
||||||
BoxSolid(const char *name, ContainerBox *box);
|
BoxSolid(const char *name, ContainerBox *box);
|
||||||
virtual G4VSolid* GetG4Solid() const override { return (G4VSolid*)m_Solid; }
|
virtual G4VSolid* GetG4Solid() const override { return (G4VSolid*)m_Solid; }
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ set(SOURCES VoxRaytracer.cpp
|
|||||||
QuadMesh.cpp
|
QuadMesh.cpp
|
||||||
Dense.cpp
|
Dense.cpp
|
||||||
Structured2DGrid.cpp
|
Structured2DGrid.cpp
|
||||||
Structured4DGrid.cpp)
|
Structured4DGrid.cpp
|
||||||
|
MathRegistrations.cpp)
|
||||||
|
|
||||||
set(LIBRARIES ${PACKAGE_LIBPREFIX}Core
|
set(LIBRARIES ${PACKAGE_LIBPREFIX}Core
|
||||||
Eigen3::Eigen
|
Eigen3::Eigen
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ class ContainerBox : public AffineTransform, public Object {
|
|||||||
typedef AffineTransform BaseClass;
|
typedef AffineTransform BaseClass;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char * GetClassName() const { return "ContainerBox"; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Default constructor.
|
* @brief Default constructor.
|
||||||
* Initializes the local transformation with this instance as its parent.
|
* Initializes the local transformation with this instance as its parent.
|
||||||
|
|||||||
@@ -45,6 +45,9 @@ class Cylinder : public AffineTransform, public Object {
|
|||||||
typedef AffineTransform BaseClass;
|
typedef AffineTransform BaseClass;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char * GetClassName() const { return "Cylinder"; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Default constructor.
|
* @brief Default constructor.
|
||||||
* Initializes with radius 1 and height 1.
|
* Initializes with radius 1 and height 1.
|
||||||
|
|||||||
@@ -28,15 +28,18 @@
|
|||||||
#ifndef U_GEOMETRY_H
|
#ifndef U_GEOMETRY_H
|
||||||
#define U_GEOMETRY_H
|
#define U_GEOMETRY_H
|
||||||
|
|
||||||
|
#include "Core/Object.h"
|
||||||
#include "Math/Dense.h"
|
#include "Math/Dense.h"
|
||||||
#include "Math/Transform.h"
|
#include "Math/Transform.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
namespace uLib {
|
namespace uLib {
|
||||||
|
|
||||||
class Geometry : public AffineTransform {
|
class Geometry : public AffineTransform, public Object {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char * GetClassName() const { return "Geometry"; }
|
||||||
|
|
||||||
virtual Vector3f ToLinear(const Vector3f& curved_space) const {
|
virtual Vector3f ToLinear(const Vector3f& curved_space) const {
|
||||||
return curved_space;
|
return curved_space;
|
||||||
}
|
}
|
||||||
@@ -87,6 +90,8 @@ class SphericalGeometry : public Geometry {
|
|||||||
public:
|
public:
|
||||||
SphericalGeometry() {}
|
SphericalGeometry() {}
|
||||||
|
|
||||||
|
virtual const char * GetClassName() const { return "SphericalGeometry"; }
|
||||||
|
|
||||||
Vector3f ToLinear(const Vector3f& spherical) const {
|
Vector3f ToLinear(const Vector3f& spherical) const {
|
||||||
float r = spherical.x();
|
float r = spherical.x();
|
||||||
float theta = spherical.y();
|
float theta = spherical.y();
|
||||||
@@ -109,6 +114,8 @@ class ToroidalGeometry : public Geometry {
|
|||||||
public:
|
public:
|
||||||
ToroidalGeometry(float Rtor) : m_Rtor(Rtor) {}
|
ToroidalGeometry(float Rtor) : m_Rtor(Rtor) {}
|
||||||
|
|
||||||
|
virtual const char * GetClassName() const { return "ToroidalGeometry"; }
|
||||||
|
|
||||||
Vector3f ToLinear(const Vector3f& toroidal) const {
|
Vector3f ToLinear(const Vector3f& toroidal) const {
|
||||||
float r = toroidal.x();
|
float r = toroidal.x();
|
||||||
float theta = toroidal.y();
|
float theta = toroidal.y();
|
||||||
|
|||||||
20
src/Math/MathRegistrations.cpp
Normal file
20
src/Math/MathRegistrations.cpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#include "Core/ObjectFactory.h"
|
||||||
|
#include "Math/ContainerBox.h"
|
||||||
|
#include "Math/Cylinder.h"
|
||||||
|
#include "Math/Geometry.h"
|
||||||
|
#include "Math/TriangleMesh.h"
|
||||||
|
#include "Math/QuadMesh.h"
|
||||||
|
#include "Math/VoxImage.h"
|
||||||
|
#include "Math/StructuredData.h"
|
||||||
|
|
||||||
|
namespace uLib {
|
||||||
|
|
||||||
|
ULIB_REGISTER_OBJECT(ContainerBox)
|
||||||
|
ULIB_REGISTER_OBJECT(Cylinder)
|
||||||
|
ULIB_REGISTER_OBJECT(CylindricalGeometry)
|
||||||
|
ULIB_REGISTER_OBJECT(SphericalGeometry)
|
||||||
|
ULIB_REGISTER_OBJECT(TriangleMesh)
|
||||||
|
ULIB_REGISTER_OBJECT(QuadMesh)
|
||||||
|
ULIB_REGISTER_OBJECT_NAME(VoxImage<Voxel>, "VoxImage")
|
||||||
|
|
||||||
|
} // namespace uLib
|
||||||
@@ -36,6 +36,8 @@ class Polydata : public Object {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char * GetClassName() const { return "Polydata"; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -37,6 +37,9 @@ namespace uLib {
|
|||||||
class QuadMesh : public AffineTransform, public Object
|
class QuadMesh : public AffineTransform, public Object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char * GetClassName() const { return "QuadMesh"; }
|
||||||
|
|
||||||
void PrintSelf(std::ostream &o);
|
void PrintSelf(std::ostream &o);
|
||||||
|
|
||||||
/** @brief Adds a point in global coordinates. Stored in local coordinates. */
|
/** @brief Adds a point in global coordinates. Stored in local coordinates. */
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ namespace uLib {
|
|||||||
class TriangleMesh : public AffineTransform, public Object
|
class TriangleMesh : public AffineTransform, public Object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char * GetClassName() const { return "TriangleMesh"; }
|
||||||
|
|
||||||
void PrintSelf(std::ostream &o);
|
void PrintSelf(std::ostream &o);
|
||||||
|
|
||||||
/** @brief Adds a point in global coordinates. Stored in local coordinates. */
|
/** @brief Adds a point in global coordinates. Stored in local coordinates. */
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ namespace Abstract {
|
|||||||
|
|
||||||
class VoxImage : public uLib::StructuredGrid {
|
class VoxImage : public uLib::StructuredGrid {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char * GetClassName() const { return "VoxImage"; }
|
||||||
|
|
||||||
typedef uLib::StructuredGrid BaseClass;
|
typedef uLib::StructuredGrid BaseClass;
|
||||||
|
|
||||||
virtual float GetValue(const Vector3i &id) const = 0;
|
virtual float GetValue(const Vector3i &id) const = 0;
|
||||||
|
|||||||
@@ -57,9 +57,12 @@ protected:
|
|||||||
} // namespace Abstract
|
} // namespace Abstract
|
||||||
|
|
||||||
template <typename VoxelT, typename AlgorithmT>
|
template <typename VoxelT, typename AlgorithmT>
|
||||||
class VoxImageFilter : public Abstract::VoxImageFilter {
|
class VoxImageFilter : public Abstract::VoxImageFilter, public Object {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
virtual const char * GetClassName() const { return "VoxImageFilter"; }
|
||||||
|
|
||||||
VoxImageFilter(const Vector3i &size);
|
VoxImageFilter(const Vector3i &size);
|
||||||
|
|
||||||
void Run();
|
void Run();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ set(HEADERS uLibVtkInterface.h
|
|||||||
vtkQViewport.h
|
vtkQViewport.h
|
||||||
vtkViewport.h
|
vtkViewport.h
|
||||||
vtkPolydata.h
|
vtkPolydata.h
|
||||||
|
vtkObjectsContext.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCES uLibVtkInterface.cxx
|
set(SOURCES uLibVtkInterface.cxx
|
||||||
@@ -14,6 +15,7 @@ set(SOURCES uLibVtkInterface.cxx
|
|||||||
vtkQViewport.cpp
|
vtkQViewport.cpp
|
||||||
vtkViewport.cpp
|
vtkViewport.cpp
|
||||||
vtkPolydata.cpp
|
vtkPolydata.cpp
|
||||||
|
vtkObjectsContext.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
## Pull in Math VTK wrappers (sets MATH_SOURCES / MATH_HEADERS)
|
## Pull in Math VTK wrappers (sets MATH_SOURCES / MATH_HEADERS)
|
||||||
|
|||||||
@@ -103,6 +103,10 @@ private:
|
|||||||
class PuppetData *d;
|
class PuppetData *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Vtk
|
} // namespace Vtk
|
||||||
} // namespace uLib
|
} // namespace uLib
|
||||||
|
|
||||||
|
|||||||
150
src/Vtk/vtkObjectsContext.cpp
Normal file
150
src/Vtk/vtkObjectsContext.cpp
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
#include "vtkObjectsContext.h"
|
||||||
|
#include "vtkContainerBox.h"
|
||||||
|
#include "HEP/Detectors/vtkDetectorChamber.h"
|
||||||
|
|
||||||
|
#include <vtkAssembly.h>
|
||||||
|
#include <vtkPropCollection.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
namespace uLib {
|
||||||
|
namespace Vtk {
|
||||||
|
|
||||||
|
vtkObjectsContext::vtkObjectsContext(uLib::ObjectsContext *context)
|
||||||
|
: m_Context(context), m_Assembly(::vtkAssembly::New()) {
|
||||||
|
this->SetProp(m_Assembly);
|
||||||
|
if (m_Context) {
|
||||||
|
Object::connect(m_Context, &uLib::ObjectsContext::ObjectAdded, this, &vtkObjectsContext::OnObjectAdded);
|
||||||
|
Object::connect(m_Context, &uLib::ObjectsContext::ObjectRemoved, this, &vtkObjectsContext::OnObjectRemoved);
|
||||||
|
this->Synchronize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vtkObjectsContext::~vtkObjectsContext() {
|
||||||
|
for (auto const& [obj, puppet] : m_Puppets) {
|
||||||
|
delete puppet;
|
||||||
|
}
|
||||||
|
m_Assembly->Delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
void vtkObjectsContext::Synchronize() {
|
||||||
|
if (!m_Context) return;
|
||||||
|
|
||||||
|
// 1. Identify objects to add and remove
|
||||||
|
const auto& objects = m_Context->GetObjects();
|
||||||
|
std::map<uLib::Object*, bool> currentObjects;
|
||||||
|
for (auto obj : objects) currentObjects[obj] = true;
|
||||||
|
|
||||||
|
// Remove puppets for objects no longer in context
|
||||||
|
for (auto it = m_Puppets.begin(); it != m_Puppets.end(); ) {
|
||||||
|
if (currentObjects.find(it->first) == currentObjects.end()) {
|
||||||
|
it->second->DisconnectRenderer(nullptr); // If we have a ref to a renderer we should disconnect but Puppet doesn't store it easily
|
||||||
|
// Actually Puppet::DisconnectRenderer(vtkRenderer*) needs the renderer.
|
||||||
|
// For now we just remove from assembly
|
||||||
|
vtkPropCollection* props = it->second->GetProps();
|
||||||
|
props->InitTraversal();
|
||||||
|
while(vtkProp* prop = props->GetNextProp()) {
|
||||||
|
if (vtkProp3D* p3d = vtkProp3D::SafeDownCast(prop))
|
||||||
|
m_Assembly->RemovePart(p3d);
|
||||||
|
}
|
||||||
|
this->PuppetRemoved(it->second);
|
||||||
|
delete it->second;
|
||||||
|
it = m_Puppets.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add puppets for new objects
|
||||||
|
for (auto obj : objects) {
|
||||||
|
if (m_Puppets.find(obj) == m_Puppets.end()) {
|
||||||
|
Puppet* puppet = this->CreatePuppet(obj);
|
||||||
|
if (puppet) {
|
||||||
|
m_Puppets[obj] = puppet;
|
||||||
|
vtkPropCollection* props = puppet->GetProps();
|
||||||
|
props->InitTraversal();
|
||||||
|
while(vtkProp* prop = props->GetNextProp()) {
|
||||||
|
if (vtkProp3D* p3d = vtkProp3D::SafeDownCast(prop))
|
||||||
|
m_Assembly->AddPart(p3d);
|
||||||
|
}
|
||||||
|
this->PuppetAdded(puppet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vtkObjectsContext::OnObjectAdded(uLib::Object* obj) {
|
||||||
|
if (!obj) return;
|
||||||
|
if (m_Puppets.find(obj) == m_Puppets.end()) {
|
||||||
|
Puppet* puppet = this->CreatePuppet(obj);
|
||||||
|
if (puppet) {
|
||||||
|
m_Puppets[obj] = puppet;
|
||||||
|
vtkPropCollection* props = puppet->GetProps();
|
||||||
|
props->InitTraversal();
|
||||||
|
while(vtkProp* prop = props->GetNextProp()) {
|
||||||
|
if (vtkProp3D* p3d = vtkProp3D::SafeDownCast(prop))
|
||||||
|
m_Assembly->AddPart(p3d);
|
||||||
|
}
|
||||||
|
this->PuppetAdded(puppet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vtkObjectsContext::OnObjectRemoved(uLib::Object* obj) {
|
||||||
|
if (!obj) return;
|
||||||
|
auto it = m_Puppets.find(obj);
|
||||||
|
if (it != m_Puppets.end()) {
|
||||||
|
// For now we just remove from assembly.
|
||||||
|
// Puppet::DisconnectRenderer(vtkRenderer*) needs the renderer, but we don't have it here easily.
|
||||||
|
vtkPropCollection* props = it->second->GetProps();
|
||||||
|
props->InitTraversal();
|
||||||
|
while(vtkProp* prop = props->GetNextProp()) {
|
||||||
|
if (vtkProp3D* p3d = vtkProp3D::SafeDownCast(prop))
|
||||||
|
m_Assembly->RemovePart(p3d);
|
||||||
|
}
|
||||||
|
this->PuppetRemoved(it->second);
|
||||||
|
delete it->second;
|
||||||
|
m_Puppets.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Puppet* vtkObjectsContext::GetPuppet(uLib::Object* obj) {
|
||||||
|
auto it = m_Puppets.find(obj);
|
||||||
|
if (it != m_Puppets.end()) return it->second;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vtkObjectsContext::Update() {
|
||||||
|
for (auto const& [obj, puppet] : m_Puppets) {
|
||||||
|
puppet->Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Puppet* vtkObjectsContext::CreatePuppet(uLib::Object* obj) {
|
||||||
|
if (!obj) return nullptr;
|
||||||
|
|
||||||
|
const char* className = obj->GetClassName();
|
||||||
|
if (std::strcmp(className, "ContainerBox") == 0) {
|
||||||
|
return new vtkContainerBox(static_cast<uLib::ContainerBox*>(obj));
|
||||||
|
} else if (std::strcmp(className, "DetectorChamber") == 0) {
|
||||||
|
return new vtkDetectorChamber(static_cast<uLib::DetectorChamber*>(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback if we don't know the exact class but it might be a context itself
|
||||||
|
if (auto subCtx = dynamic_cast<uLib::ObjectsContext*>(obj)) {
|
||||||
|
return new vtkObjectsContext(subCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vtkObjectsContext::PuppetAdded(Puppet* puppet) {
|
||||||
|
ULIB_SIGNAL_EMIT(vtkObjectsContext::PuppetAdded, puppet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vtkObjectsContext::PuppetRemoved(Puppet* puppet) {
|
||||||
|
ULIB_SIGNAL_EMIT(vtkObjectsContext::PuppetRemoved, puppet);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Vtk
|
||||||
|
} // namespace uLib
|
||||||
54
src/Vtk/vtkObjectsContext.h
Normal file
54
src/Vtk/vtkObjectsContext.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#ifndef U_VTKOBJECTSCONTEXT_H
|
||||||
|
#define U_VTKOBJECTSCONTEXT_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include "Core/ObjectsContext.h"
|
||||||
|
#include "uLibVtkInterface.h"
|
||||||
|
|
||||||
|
class vtkAssembly;
|
||||||
|
|
||||||
|
namespace uLib {
|
||||||
|
namespace Vtk {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief vtkObjectsContext manages VTK representations (Puppets) for a collection of uLib::Objects.
|
||||||
|
*/
|
||||||
|
class vtkObjectsContext : public uLib::Object, public Puppet {
|
||||||
|
public:
|
||||||
|
virtual const char* GetClassName() const override { return "vtkObjectsContext"; }
|
||||||
|
vtkObjectsContext(uLib::ObjectsContext *context);
|
||||||
|
virtual ~vtkObjectsContext();
|
||||||
|
|
||||||
|
/** @brief Synchronizes the VTK puppets with the core ObjectsContext. */
|
||||||
|
void Synchronize();
|
||||||
|
|
||||||
|
/** @brief Returns the puppet associated with a specific core object. */
|
||||||
|
Puppet* GetPuppet(uLib::Object* obj);
|
||||||
|
|
||||||
|
/** @brief Updates all managed puppets. */
|
||||||
|
virtual void Update() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void PuppetAdded(Puppet* puppet);
|
||||||
|
virtual void PuppetRemoved(Puppet* puppet);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** @brief Slot called when an object is added to the core context. */
|
||||||
|
void OnObjectAdded(uLib::Object* obj);
|
||||||
|
/** @brief Slot called when an object is removed from the core context. */
|
||||||
|
void OnObjectRemoved(uLib::Object* obj);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** @brief Factory method to create a puppet for a core object. */
|
||||||
|
Puppet* CreatePuppet(uLib::Object* obj);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uLib::ObjectsContext *m_Context;
|
||||||
|
std::map<uLib::Object*, Puppet*> m_Puppets;
|
||||||
|
vtkAssembly *m_Assembly;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Vtk
|
||||||
|
} // namespace uLib
|
||||||
|
|
||||||
|
#endif // U_VTKOBJECTSCONTEXT_H
|
||||||
Reference in New Issue
Block a user