Skip to content

File Beamline.h

File List > Beamline > Beamline.h

Go to the documentation of this file

#pragma once

#include <functional>
#include <glm.hpp>
#include <memory>
#include <variant>
#include <vector>

#include "Core.h"
#include "Design/DesignElement.h"
#include "Design/DesignSource.h"
#include "Node.h"

namespace rayx {

class RAYX_API Group : public BeamlineNode {
  public:
    Group();
    Group(std::string name);
    ~Group() = default;

    Group(const Group&)            = delete;
    Group& operator=(const Group&) = delete;

    Group(Group&& other) noexcept;
    Group& operator=(Group&& other) noexcept;

    bool isGroup() const override { return true; }

    // Iterators
    auto begin() { return m_children.begin(); }
    auto end() { return m_children.end(); }
    auto begin() const { return m_children.cbegin(); }
    auto end() const { return m_children.cend(); }
    auto cbegin() const { return m_children.cbegin(); }
    auto cend() const { return m_children.cend(); }

    void addChild(std::unique_ptr<BeamlineNode> child);

    [[nodiscard]] std::unique_ptr<BeamlineNode> releaseNodeFromChildren(const BeamlineNode* node);
    [[nodiscard]] std::unique_ptr<BeamlineNode> releaseNodeFromTree(const BeamlineNode* node);

    size_t numElements() const;
    size_t numSources() const;
    size_t numObjects() const;
    size_t numRayPaths() const;

    // recursive search

    const BeamlineNode* findNodeByName(const std::string& name) const;
    BeamlineNode* findNodeByName(const std::string& name);

    const Group* findGroupByName(const std::string& name) const;
    Group* findGroupByName(const std::string& name);

    const DesignSource* findSourceByName(const std::string& name) const;
    DesignSource* findSourceByName(const std::string& name);

    const DesignElement* findElementByName(const std::string& name) const;
    DesignElement* findElementByName(const std::string& name);

    const BeamlineNode* findNode(const std::function<bool(const BeamlineNode&)>& pred) const;
    BeamlineNode* findNode(const std::function<bool(const BeamlineNode&)>& pred);

    const Group* findGroup(const std::function<bool(const Group&)>& pred) const;
    Group* findGroup(const std::function<bool(const Group&)>& pred);

    const DesignSource* findSource(const std::function<bool(const DesignSource&)>& pred) const;
    DesignSource* findSource(const std::function<bool(const DesignSource&)>& pred);

    const DesignElement* findElement(const std::function<bool(const DesignElement&)>& pred) const;
    DesignElement* findElement(const std::function<bool(const DesignElement&)>& pred);

    // declarative fashion api

    const BeamlineNode* operator[](size_t index) const override;
    BeamlineNode* operator[](size_t index) override;

    const BeamlineNode* operator[](const std::string& name) const override;
    BeamlineNode* operator[](const std::string& name) override;

    std::unique_ptr<BeamlineNode> clone() const override;

    std::string getName() const override;
    void setName(std::string name) override;

    void ctraverse(const std::function<bool(const BeamlineNode&)>& callback) const;

    void traverse(const std::function<bool(BeamlineNode&)>& callback);

    // TODO: this should not be part of the API
    MaterialTables calcMinimalMaterialTables() const;

    // TODO: this should not be part of the API
    std::vector<OpticalElementAndTransform> compileElements() const;

    // TODO: why would we need this? ray-ui uses this function
    static void accumulateLightSourcesWorldPositions(const Group& group, const glm::dvec4& parentPos, const glm::dmat4& parentOri,
                                                     std::vector<glm::dvec4>& positions);

    std::vector<std::string> getElementNames() const;
    std::vector<std::string> getSourceNames() const;
    std::vector<std::string> getObjectNames() const;

    std::vector<const DesignElement*> getElements() const;
    std::vector<const DesignSource*> getSources() const;

    glm::dvec4 getPosition() const override { return m_position; }
    void setPosition(const glm::dvec4& pos) { m_position = pos; }

    glm::dmat4 getOrientation() const override { return m_orientation; }
    void setOrientation(const glm::dmat4& orientation) { m_orientation = orientation; }

    const std::vector<std::unique_ptr<BeamlineNode>>& getChildren() const { return m_children; }

    size_t findObjectIdByNode(const BeamlineNode* node) const;
    const BeamlineNode* findNodeByObjectId(const size_t objectId) const;
    BeamlineNode* findNodeByObjectId(const size_t objectId);

  private:
    // Position and orientation could in theory be put into one transform matrix but this follows the rml style
    glm::dvec4 m_position    = glm::dvec4(0, 0, 0, 1);
    glm::dmat4 m_orientation = glm::dmat4(1);
    // m_children vec is not checked for dangling or nullptrs anywhere, changes to the Group interface/implementation are to be made with care
    std::vector<std::unique_ptr<BeamlineNode>> m_children;
    std::string m_name;
};

using Beamline = Group;  // Conceptually, a Beamline is a Group

}  // namespace rayx