Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Adding cuboid volume stack #4040

Merged
merged 24 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Core/include/Acts/Geometry/CuboidVolumeBounds.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include <array>
#include <cmath>
#include <cstddef>
#include <iomanip>
#include <iosfwd>
#include <memory>
Expand Down Expand Up @@ -71,6 +72,9 @@ class CuboidVolumeBounds : public VolumeBounds {
/// @param values iw the bound values
CuboidVolumeBounds(const std::array<double, eSize>& values);

CuboidVolumeBounds(
std::initializer_list<std::pair<BoundValues, double>> keyValues);

/// Copy Constructor
///
/// @param bobo is the source volume bounds to be copied
Expand Down Expand Up @@ -149,6 +153,11 @@ class CuboidVolumeBounds : public VolumeBounds {
/// @param keyValues the initializer list of key value pairs
void set(std::initializer_list<std::pair<BoundValues, double>> keyValues);

/// Convert axis direction to a corresponding bound value
/// in local coordinate convention
/// @param direction the axis direction to convert
static BoundValues fromAxisDirection(AxisDirection direction);

/// Output Method for std::ostream
///
/// @param os is ostream operator to be dumped into
Expand Down
187 changes: 187 additions & 0 deletions Core/include/Acts/Geometry/CuboidVolumeStack.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
// This file is part of the ACTS project.
//
// Copyright (C) 2016 CERN for the benefit of the ACTS project
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

#pragma once

#include "Acts/Definitions/Algebra.hpp"
#include "Acts/Geometry/Volume.hpp"
#include "Acts/Geometry/detail/VolumeAttachmentStrategy.hpp"
#include "Acts/Geometry/detail/VolumeResizeStrategy.hpp"
#include "Acts/Utilities/AxisDefinitions.hpp"
#include "Acts/Utilities/Logger.hpp"

#include <cstddef>
#include <vector>

namespace Acts {

/// @class CuboidVolumeStack
/// This class implements a x-. y-. z-aligned stack
/// of cuboid volumes with synchronized bounds.
/// Externally, it presents as a single volume.
/// On construction, the input volumes are modified so that
/// they are connected in x, y, z and have synchronized bounds.
/// The way this is done can be configured using an *attachment*
/// and a *resize* strategy. Depending on the configuration,
/// the input volumes are either extended or gap volumes are created.
///
/// @note The size adjustment convention is that volumes are never shrunk
class CuboidVolumeStack : public Volume {
public:
/// Constructor from a vector of volumes and direction
/// @param volumes is the vector of volumes
/// @param direction is the axis direction
/// @param strategy is the attachment strategy
/// @param resizeStrategy is the resize strategy
/// @note @p resizeStrategy only affects resizing along
/// @p direction. Resizing in the other direction
/// is always delegated to the child volumes,
/// which might in turn be @c CuboidVolumeStack
/// @param logger is the logger
/// @pre The volumes need to have a common coordinate
/// system relative to @p direction. I.e. they need
/// to be aligned in @c z and cannot have a rotation
/// in @c x or @c y.
/// @pre The volumes all need to have @c CuboidVolumeBounds
/// @note Preconditions are checked on construction
CuboidVolumeStack(
std::vector<Volume*>& volumes, AxisDirection direction,
VolumeAttachmentStrategy strategy = VolumeAttachmentStrategy::Midpoint,
VolumeResizeStrategy resizeStrategy = VolumeResizeStrategy::Expand,
const Logger& logger = Acts::getDummyLogger());
ssdetlab marked this conversation as resolved.
Show resolved Hide resolved

/// Constructor from a vector of volumes and direction
/// @param volumes is the vector of volumes
/// @param direction is the vector specifying the global direction
/// @param strategy is the attachment strategy
/// @param resizeStrategy is the resize strategy
/// @note @p resizeStrategy only affects resizing along
/// @p direction. Resizing in the other direction
/// is always delegated to the child volumes,
/// which might in turn be @c CuboidVolumeStack
/// @param logger is the logger
/// @pre The volumes need to have a common coordinate
/// system relative to @p direction. I.e. they need
/// to be aligned in @c z and cannot have a rotation
/// in @c x or @c y.
/// @pre The volumes all need to have @c CuboidVolumeBounds
/// @note Preconditions are checked on construction
CuboidVolumeStack(
std::vector<Volume*>& volumes, const Vector3& direction,
VolumeAttachmentStrategy strategy = VolumeAttachmentStrategy::Midpoint,
VolumeResizeStrategy resizeStrategy = VolumeResizeStrategy::Expand,
const Logger& logger = Acts::getDummyLogger());

/// Update the volume bounds and transform. This
/// will update the bounds of all volumes in the stack
/// to accommodate the new bounds and optionally create
/// gap volumes according to the resize strategy set during
/// construction.
/// @param volbounds is the new bounds
/// @param transform is the new transform
/// @param logger is the logger
/// @pre The volume bounds need to be of type
/// @c CuboidVolumeBounds.
void update(std::shared_ptr<VolumeBounds> volbounds,
std::optional<Transform3> transform = std::nullopt,
const Logger& logger = getDummyLogger()) override;
ssdetlab marked this conversation as resolved.
Show resolved Hide resolved

/// Access the gap volume that were created during attachment or resizing.
/// @return the vector of gap volumes
const std::vector<std::shared_ptr<Volume>>& gaps() const;

/// Convert axis direction to an array index according to
/// stack convention. For example, AxisX --> 0
/// @param direction is the axis direction to convert
static std::size_t axisToIndex(AxisDirection direction);

/// Get axis directions orthogonal to the given one according
/// to stack convention. For example AxisX --> <AxisY, AxisZ>
/// @param direction is the axis direction to find the orthogonal for
static std::pair<AxisDirection, AxisDirection> getOrthogonalAxes(
AxisDirection direction);

private:
/// Helper to get the first volume in the input, and throw an exception if
/// there is not one.
/// @param volumes is the vector of volumes
/// @return the first volume
static Volume& initialVolume(const std::vector<Volume*>& volumes);

/// Helper function called during construction that performs the
/// internal attachment and produces the overall outer volume bounds.
/// @param strategy is the attachment strategy
/// @param logger is the logger
void initializeOuterVolume(VolumeAttachmentStrategy strategy,
const Logger& logger);

struct VolumeTuple;

/// Helper function to pretty print the internal volume representation
/// @param volumes is the vector of volumes
/// @param logger is the logger
/// @param lvl is the logging level
static void printVolumeSequence(const std::vector<VolumeTuple>& volumes,
const Logger& logger,
Acts::Logging::Level lvl);

/// Helper function that prints output helping in debugging overlaps
/// @param a is the first volume
/// @param b is the second volume
/// @param logger is the logger
void overlapPrint(const VolumeTuple& a, const VolumeTuple& b,
const Logger& logger);

/// Helper function that checks if volumes are properly aligned
/// for attachment.
/// @param volumes is the vector of volumes
/// @param logger is the logger
void checkVolumeAlignment(const std::vector<VolumeTuple>& volumes,
const Logger& logger) const;

/// Helper function that checks overlaps and attaches along the stacking
/// direction
/// @param volumes is the vector of volumes
/// @param strategy is the attachment strategy
/// @param logger is the logger
/// @return vector of gap volumes. Can be empty if none were created.
std::vector<VolumeTuple> checkOverlapAndAttach(
std::vector<VolumeTuple>& volumes, VolumeAttachmentStrategy strategy,
const Logger& logger);

/// Helper function to synchronize the bounds of the volumes
/// @param volumes is the vector of volumes
/// @param logger is the logger
/// @return tuple of the minimum and maximum radii
std::pair<double, double> synchronizeBounds(std::vector<VolumeTuple>& volumes,
const Logger& logger);

/// Helper function to create a gap volume with given bounds and register it.
/// @param transform is the transform of the gap volume
/// @param bounds is the bounds of the gap volume
/// @return the shared pointer to the gap volume
std::shared_ptr<Volume> addGapVolume(
const Transform3& transform, const std::shared_ptr<VolumeBounds>& bounds);

/// Merging direction of the stack
/// in local group coordinates
AxisDirection m_dir{};

/// Directions orthogonal to the
/// merging direction of the stack
/// in local group coordinates
AxisDirection m_dirOrth1{};
AxisDirection m_dirOrth2{};

VolumeResizeStrategy m_resizeStrategy{};
Transform3 m_groupTransform{};
std::vector<std::shared_ptr<Volume>> m_gaps{};
std::vector<Volume*>& m_volumes;
};

} // namespace Acts
24 changes: 12 additions & 12 deletions Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include "Acts/Geometry/BlueprintNode.hpp"
#include "Acts/Geometry/CylinderVolumeStack.hpp"
#include "Acts/Geometry/PortalShell.hpp"
#include "Acts/Geometry/detail/VolumeAttachmentStrategy.hpp"
#include "Acts/Geometry/detail/VolumeResizeStrategy.hpp"
#include "Acts/Utilities/AxisDefinitions.hpp"
#include "Acts/Utilities/Logger.hpp"

Expand All @@ -37,10 +39,9 @@ class CylinderContainerBlueprintNode final : public BlueprintNode {
/// see documentation of that class for more information
CylinderContainerBlueprintNode(
const std::string& name, AxisDirection direction,
CylinderVolumeStack::AttachmentStrategy attachmentStrategy =
CylinderVolumeStack::AttachmentStrategy::Midpoint,
CylinderVolumeStack::ResizeStrategy resizeStrategy =
CylinderVolumeStack::ResizeStrategy::Expand);
VolumeAttachmentStrategy attachmentStrategy =
VolumeAttachmentStrategy::Midpoint,
VolumeResizeStrategy resizeStrategy = VolumeResizeStrategy::Expand);

/// @copydoc BlueprintNode::name
const std::string& name() const override;
Expand Down Expand Up @@ -101,25 +102,25 @@ class CylinderContainerBlueprintNode final : public BlueprintNode {
/// @param attachmentStrategy The attachment strategy
/// @return This node for chaining
CylinderContainerBlueprintNode& setAttachmentStrategy(
CylinderVolumeStack::AttachmentStrategy attachmentStrategy);
VolumeAttachmentStrategy attachmentStrategy);

/// Setter for the resize strategy
/// @param resizeStrategy The resize strategy
/// @return This node for chaining
CylinderContainerBlueprintNode& setResizeStrategy(
CylinderVolumeStack::ResizeStrategy resizeStrategy);
VolumeResizeStrategy resizeStrategy);

/// Accessor to the stacking direction
/// @return The stacking direction
AxisDirection direction() const;

/// Accessor to the attachment strategy
/// @return The attachment strategy
CylinderVolumeStack::AttachmentStrategy attachmentStrategy() const;
VolumeAttachmentStrategy attachmentStrategy() const;

/// Accessor to the resize strategy
/// @return The resize strategy
CylinderVolumeStack::ResizeStrategy resizeStrategy() const;
VolumeResizeStrategy resizeStrategy() const;

private:
/// @copydoc BlueprintNode::addToGraphviz
Expand All @@ -138,11 +139,10 @@ class CylinderContainerBlueprintNode final : public BlueprintNode {

AxisDirection m_direction = AxisDirection::AxisZ;

CylinderVolumeStack::AttachmentStrategy m_attachmentStrategy{
CylinderVolumeStack::AttachmentStrategy::Midpoint};
VolumeAttachmentStrategy m_attachmentStrategy{
VolumeAttachmentStrategy::Midpoint};

CylinderVolumeStack::ResizeStrategy m_resizeStrategy{
CylinderVolumeStack::ResizeStrategy::Expand};
VolumeResizeStrategy m_resizeStrategy{VolumeResizeStrategy::Expand};

// Is only initialized during `build`
std::vector<Volume*> m_childVolumes;
Expand Down
52 changes: 9 additions & 43 deletions Core/include/Acts/Geometry/CylinderVolumeStack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include "Acts/Definitions/Algebra.hpp"
#include "Acts/Geometry/CylinderVolumeBounds.hpp"
#include "Acts/Geometry/Volume.hpp"
#include "Acts/Geometry/detail/VolumeAttachmentStrategy.hpp"
#include "Acts/Geometry/detail/VolumeResizeStrategy.hpp"
#include "Acts/Utilities/AxisDefinitions.hpp"
#include "Acts/Utilities/Logger.hpp"

Expand All @@ -32,29 +34,6 @@ namespace Acts {
/// result in overlaps of the resulting volumes bounds.
class CylinderVolumeStack : public Volume {
public:
/// The attachment strategy defines how the volumes are attached
/// Attachment always happens pair-wise
enum class AttachmentStrategy {
/// Given two volumes, the *left* one, i.e. the one with the lower **local**
/// z or r value is extended
First,
/// Given two volumes, the *right* one, i.e. the one with the higher
/// **local** z or r value is extended
Second,
/// Given two volumes, the *midpoint* between the two volumes is found
Midpoint,
/// A gap volume is created to fit between the two volumes
Gap,
};

/// The resize strategy defines how the volumes are resized
enum class ResizeStrategy {
/// Extend the volume connected to the respective edge to fit the new bounds
Expand,
/// Create a gap volume at the respective edge to fit the new bounds
Gap,
};

/// Constructor from a vector of volumes and direction
/// @param volumes is the vector of volumes
/// @param direction is the binning direction
Expand All @@ -74,8 +53,8 @@ class CylinderVolumeStack : public Volume {
/// @note Preconditions are checked on construction
CylinderVolumeStack(
std::vector<Volume*>& volumes, AxisDirection direction,
AttachmentStrategy strategy = AttachmentStrategy::Midpoint,
ResizeStrategy resizeStrategy = ResizeStrategy::Expand,
VolumeAttachmentStrategy strategy = VolumeAttachmentStrategy::Midpoint,
VolumeResizeStrategy resizeStrategy = VolumeResizeStrategy::Expand,
const Logger& logger = Acts::getDummyLogger());

/// Update the volume bounds and transform. This
Expand Down Expand Up @@ -109,7 +88,8 @@ class CylinderVolumeStack : public Volume {
/// @param strategy is the attachment strategy
/// @param logger is the logger
void initializeOuterVolume(AxisDirection direction,
AttachmentStrategy strategy, const Logger& logger);
VolumeAttachmentStrategy strategy,
const Logger& logger);

struct VolumeTuple;

Expand Down Expand Up @@ -142,7 +122,7 @@ class CylinderVolumeStack : public Volume {
/// @param logger is the logger
/// @return vector of gap volumes. Can be empty if none were created.
std::vector<VolumeTuple> checkOverlapAndAttachInZ(
std::vector<VolumeTuple>& volumes, AttachmentStrategy strategy,
std::vector<VolumeTuple>& volumes, VolumeAttachmentStrategy strategy,
const Logger& logger);

/// Helper function to synchronize the r bounds of the volumes
Expand All @@ -158,7 +138,7 @@ class CylinderVolumeStack : public Volume {
/// @param logger is the logger
/// @return vector of gap volumes. Can be empty if none were created.
std::vector<VolumeTuple> checkOverlapAndAttachInR(
std::vector<VolumeTuple>& volumes, AttachmentStrategy strategy,
std::vector<VolumeTuple>& volumes, VolumeAttachmentStrategy strategy,
const Logger& logger);

/// Helper function to synchronize the z bounds of the volumes
Expand All @@ -183,24 +163,10 @@ class CylinderVolumeStack : public Volume {
const Transform3& transform, const std::shared_ptr<VolumeBounds>& bounds);

AxisDirection m_direction{};
ResizeStrategy m_resizeStrategy{};
VolumeResizeStrategy m_resizeStrategy{};
Transform3 m_groupTransform{};
std::vector<std::shared_ptr<Volume>> m_gaps{};
std::vector<Volume*>& m_volumes;
};

/// Output operator for the attachment strategy
/// @param os is the output stream
/// @param strategy is the attachment strategy
/// @return the output stream
std::ostream& operator<<(std::ostream& os,
CylinderVolumeStack::AttachmentStrategy strategy);

/// Output operator for the resize strategy
/// @param os is the output stream
/// @param strategy is the resize strategy
/// @return the output stream
std::ostream& operator<<(std::ostream& os,
CylinderVolumeStack::ResizeStrategy strategy);

} // namespace Acts
Loading
Loading