From ca453a7f06b3e9a9c8f13874adf0b18488623798 Mon Sep 17 00:00:00 2001 From: Jannis Maier Date: Fri, 20 Dec 2024 16:58:05 +0100 Subject: [PATCH] WIP --- Intern/rayx-core/src/Beamline/Beamline.cpp | 25 +++++--- Intern/rayx-core/src/Beamline/Beamline.h | 21 ++++--- Intern/rayx-core/src/Design/Group.cpp | 73 ++++++++++++++++++++++ Intern/rayx-core/src/Design/Group.h | 52 +++++++++++++++ 4 files changed, 155 insertions(+), 16 deletions(-) create mode 100644 Intern/rayx-core/src/Design/Group.cpp create mode 100644 Intern/rayx-core/src/Design/Group.h diff --git a/Intern/rayx-core/src/Beamline/Beamline.cpp b/Intern/rayx-core/src/Beamline/Beamline.cpp index f070bbba..42952ece 100644 --- a/Intern/rayx-core/src/Beamline/Beamline.cpp +++ b/Intern/rayx-core/src/Beamline/Beamline.cpp @@ -5,35 +5,35 @@ #include "Debug/Instrumentor.h" namespace RAYX { -Beamline::Beamline() = default; -Beamline::~Beamline() = default; std::vector Beamline::getInputRays(int thread_count) const { RAYX_PROFILE_FUNCTION_STDOUT(); - if (m_DesignSources.size() == 0) { + std::vector sources = m_RootGroup.getAllSources(); + + if (sources.size() == 0) { return {}; } // count number of rays. uint32_t raycount = 0; - for (DesignSource dSource : m_DesignSources) { + for (DesignSource dSource : sources) { raycount += (uint32_t)dSource.getNumberOfRays(); } // We add all remaining rays into the rays of the first light source. // This is efficient because in most cases there is just one light source, and hence copying them again is unnecessary. - std::vector list = m_DesignSources[0].compile(thread_count); + std::vector list = sources[0].compile(thread_count); for (Ray& r : list) { r.m_sourceID = 0; // the first light source has ID 0. } - if (m_DesignSources.size() > 1) { + if (sources.size() > 1) { list.reserve(raycount); - for (size_t i = 1; i < m_DesignSources.size(); i++) { - std::vector sub = m_DesignSources[i].compile(thread_count); + for (size_t i = 1; i < sources.size(); i++) { + std::vector sub = sources[i].compile(thread_count); for (Ray& r : sub) { r.m_sourceID = static_cast(i); } @@ -44,10 +44,12 @@ std::vector Beamline::getInputRays(int thread_count) const { } MaterialTables Beamline::calcMinimalMaterialTables() const { + std::vector elements = m_RootGroup.getAllElements(); + std::array relevantMaterials{}; relevantMaterials.fill(false); - for (const auto& e : m_DesignElements) { + for (const auto& e : elements) { int material = static_cast(e.getMaterial()); // in [1, 92] if (1 <= material && material <= 92) { relevantMaterials[material - 1] = true; @@ -57,4 +59,9 @@ MaterialTables Beamline::calcMinimalMaterialTables() const { return loadMaterialTables(relevantMaterials); } +void Beamline::addNodeToRoot(BeamlineNode&& node) { + // Add to the root group + m_RootGroup.addChild(std::move(node)); +} + } // namespace RAYX diff --git a/Intern/rayx-core/src/Beamline/Beamline.h b/Intern/rayx-core/src/Beamline/Beamline.h index 1ff4c317..2ab9b824 100644 --- a/Intern/rayx-core/src/Beamline/Beamline.h +++ b/Intern/rayx-core/src/Beamline/Beamline.h @@ -7,22 +7,21 @@ #include "Core.h" #include "Design/DesignElement.h" #include "Design/DesignSource.h" +#include "Design/Group.h" #include "Material/Material.h" #include "Shader/Ray.h" namespace RAYX { -class LightSource; /* - * The Beamline class is a container for OpticalElements and LightSources. + * The Beamline class is a container for a hierarchical tree of OpticalElements and LightSources. * It represents a central structure in our simulation process. */ class RAYX_API Beamline { public: Beamline(); - ~Beamline(); - // iterates over the m_LightSources, and collects the rays they emit. + // Iterates over the m_DesignSources, and collects the rays they emit. std::vector getInputRays(int thread_count = 1) const; /** @@ -33,8 +32,16 @@ class RAYX_API Beamline { */ MaterialTables calcMinimalMaterialTables() const; - std::vector m_DesignElements; - std::vector m_DesignSources; + /** + * @brief Adds a node to the root Group of the beamline hierarchy. + * @param node The BeamlineNode to add (can be a DesignElement, DesignSource, or nested Group). + */ + void addNodeToRoot( + BeamlineNode&& node); // TODO: Adding only to root note seems good practice but means we need to create nested structures during parsing + + private: + // Root node of the beamline hierarchy. This group will always be positioned at 0,0,0 with an identity matrix for the orientation + Group m_RootGroup; // TODO: Should the group just be the new beamline? Both are the same thing conceptually }; -} // namespace RAYX +} // namespace RAYX \ No newline at end of file diff --git a/Intern/rayx-core/src/Design/Group.cpp b/Intern/rayx-core/src/Design/Group.cpp new file mode 100644 index 00000000..cbc30f41 --- /dev/null +++ b/Intern/rayx-core/src/Design/Group.cpp @@ -0,0 +1,73 @@ +#include "Group.h" +#include + +#include "DesignSource.h" +#include "DesignElement.h" + +namespace RAYX { + +// Implementation of Group's getNodeType +NodeType Group::getNodeType() const { + // A Group is inherently of NodeType::Group + return NodeType::Group; +} + +// Implementation of getNode to access a child node by index +const BeamlineNode& Group::getNode(size_t index) const { + if (index >= children.size()) { + throw std::out_of_range("Index out of range in Group::getNode"); + } + return children[index]; +} + +void Group::traverse(const std::function& callback) const { + // Apply the callback to each child + for (const auto& child : children) { + callback(child); + // If the child is a Group, recursively traverse it + if (std::holds_alternative(child)) { + std::get(child).traverse(callback); + } + } +} + +// Add a child node (move semantics) +void Group::addChild(BeamlineNode&& child) { children.push_back(std::move(child)); } + +// Add a child node (copy semantics) +void Group::addChild(const BeamlineNode& child) { children.push_back(child); } + +// Retrieve all DesignElements (deep) +std::vector Group::getAllElements() const { + std::vector elements; + traverse([&elements](const BeamlineNode& node) { + if (std::holds_alternative(node)) { + elements.push_back(std::get(node)); + } + }); + return elements; +} + +// Retrieve all DesignSources (deep) +std::vector Group::getAllSources() const { + std::vector sources; + traverse([&sources](const BeamlineNode& node) { + if (std::holds_alternative(node)) { + sources.push_back(std::get(node)); + } + }); + return sources; +} + +// Retrieve all Groups (deep) +std::vector Group::getAllGroups() const { + std::vector groups; + traverse([&groups](const BeamlineNode& node) { + if (std::holds_alternative(node)) { + groups.push_back(std::get(node)); + } + }); + return groups; +} + +} // namespace RAYX \ No newline at end of file diff --git a/Intern/rayx-core/src/Design/Group.h b/Intern/rayx-core/src/Design/Group.h new file mode 100644 index 00000000..431ff07f --- /dev/null +++ b/Intern/rayx-core/src/Design/Group.h @@ -0,0 +1,52 @@ +#pragma once + +#include +#include +#include +#include + +namespace RAYX { + +class Group; +class DesignElement; +class DesignSource; + +using BeamlineNode = std::variant; + +enum class NodeType { OpticalElement, LightSource, Group }; + +// Utility function to determine node type +inline NodeType getNodeType(const BeamlineNode& node) { + return std::visit( + [](auto&& element) -> NodeType { + using T = std::decay_t; + if constexpr (std::is_same_v) { + return NodeType::OpticalElement; + } else if constexpr (std::is_same_v) { + return NodeType::LightSource; + } else if constexpr (std::is_same_v) { + return NodeType::Group; + } + }, + node); +} + +class Group { + public: + NodeType getNodeType() const; + const BeamlineNode& getNode(size_t index) const; + + void traverse(const std::function& callback) const; + + void addChild(BeamlineNode&& child); + void addChild(const BeamlineNode& child); + + // New methods for retrieving elements, sources, and groups + std::vector getAllElements() const; + std::vector getAllSources() const; + std::vector getAllGroups() const; + + private: + std::vector children; // Children of the node +}; +} // namespace RAYX