Skip to content

Commit

Permalink
feat: Adding cuboid portal shell (#4047)
Browse files Browse the repository at this point in the history
Adding `CuboidPortalShell` classes for Gen3 planar geometry support.  

The `CuboidStackPortalShell` class is able to handle arbitrary direction stacking, analogously to the `CuboidVolumeStack`. 

Splitting the `PortalShell` file into separate `PortalShellBase`, `CylinderPortalShell`, `CuboidPortalShell`.  

Adding `facesFromAxisDirection` convenience method to `CuboidVolumeBounds`. 

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

Based on the comprehensive summary, here are the updated release notes:

- **New Features**
  - Introduced specialized portal shell classes for cuboid and cylinder geometries.
  - Added support for single and stacked portal shells with enhanced portal management.
  - Implemented new methods for handling volume bounds and axis directions.

- **Improvements**
  - Enhanced geometry handling with more precise portal and volume boundary definitions.
  - Improved flexibility in defining portal shells for different geometric shapes.
  - Refined axis direction and volume bounds conversion methods.

- **Changes**
  - Refactored portal shell implementation, moving from generic to shape-specific approaches.
  - Updated method names for improved clarity (e.g., `fromAxisDirection` → `boundsFromAxisDirection`).
  - Removed generic portal shell classes in favor of specialized implementations.

- **Testing**
  - Added comprehensive unit tests for new cuboid and cylinder portal shell implementations.
  - Expanded test coverage for volume bounds and portal shell functionalities.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • Loading branch information
ssdetlab authored Feb 27, 2025
1 parent 5c7de7a commit f5df1e9
Show file tree
Hide file tree
Showing 20 changed files with 1,549 additions and 213 deletions.
155 changes: 155 additions & 0 deletions Core/include/Acts/Geometry/CuboidPortalShell.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
// 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/CuboidVolumeBounds.hpp"
#include "Acts/Geometry/PortalShell.hpp"
#include "Acts/Geometry/TrackingVolume.hpp"
#include "Acts/Utilities/AxisDefinitions.hpp"
#include "Acts/Utilities/Logger.hpp"

#include <array>
#include <memory>
#include <vector>

namespace Acts {

/// @class CuboidPortalShell
/// Base class for cuboid shaped portal shells, e.g. shells for cuboid
/// volumes
class CuboidPortalShell : public PortalShellBase {
public:
using Face = CuboidVolumeBounds::Face;

using enum CuboidVolumeBounds::Face;

/// Retrieve the portal associated to the given face. Can be nullptr if unset.
/// @param face The face to retrieve the portal for
/// @return The portal associated to the face
virtual Portal* portal(Face face) = 0;

/// Retrieve a shared_ptr for the portal associated to the given face. Can be
/// nullptr if unset.
/// @param face The face to retrieve the portal for
/// @return The portal associated to the face
virtual std::shared_ptr<Portal> portalPtr(Face face) = 0;

/// Set the portal associated to the given face.
/// @param portal The portal to set
/// @param face The face to set the portal
virtual void setPortal(std::shared_ptr<Portal> portal, Face face) = 0;

/// @copydoc PortalShellBase::fill
void fill(TrackingVolume& volume) override;

virtual const Transform3& transform() const = 0;
};

/// Output stream operator for the CuboidPortalShell::Face enum
/// @param os The output stream
/// @param face The face to output
/// @return The output stream
std::ostream& operator<<(std::ostream& os, CuboidPortalShell::Face face);

/// @class SingleCuboidPortalShell
/// This class describes a cuboid shell containing a single volume.
class SingleCuboidPortalShell : public CuboidPortalShell {
public:
/// Construct a single cuboid portal shell for the given volume
/// @param volume The volume to create the shell for
explicit SingleCuboidPortalShell(TrackingVolume& volume);

/// @copydoc PortalShellBase::size
std::size_t size() const final;

/// @copydoc CuboidPortalShell::portal
Portal* portal(Face face) final;

/// @copydoc CuboidPortalShell::portalPtr
std::shared_ptr<Portal> portalPtr(Face face) final;

/// @copydoc CuboidPortalShell::setPortal
void setPortal(std::shared_ptr<Portal> portal, Face face) final;

/// @copydoc PortalShellBase::applyToVolume
void applyToVolume() override;

/// @copydoc PortalShellBase::isValid
bool isValid() const override;

/// @copydoc PortalShellBase::label
std::string label() const override;

const Transform3& transform() const override {
return m_volume->transform();
};

private:
std::array<std::shared_ptr<Portal>, 6> m_portals{};

TrackingVolume* m_volume;
};

/// @class CuboidStackPortalShell
/// This class describes a cuboid shell containing multiple volumes.
class CuboidStackPortalShell final : public CuboidPortalShell {
public:
/// Construct the portal shell stack from the given shells
/// @param gctx The geometry context
/// @param shells The shells to stack
/// @note The shells must be ordered in the given direction
/// @param direction The stacking direction (along x/y/z axis) in local stack coordinates
/// @param logger A logging instance for debugging
CuboidStackPortalShell(const GeometryContext& gctx,
std::vector<CuboidPortalShell*> shells,
AxisDirection direction,
const Logger& logger = getDummyLogger());

/// @copydoc PortalShellBase::size
std::size_t size() const override;

/// @copydoc CuboidPortalShell::portal
Portal* portal(Face face) override;

/// @copydoc CuboidPortalShell::portalPtr
std::shared_ptr<Portal> portalPtr(Face face) override;

/// @copydoc CuboidPortalShell::setPortal
void setPortal(std::shared_ptr<Portal> portal, Face face) override;

void applyToVolume() override {
// No-op, because it's a composite portal shell
}

/// @copydoc PortalShellBase::isValid
bool isValid() const override;

/// @copydoc PortalShellBase::label
std::string label() const override;

/// Return the stack's group transform
const Transform3& transform() const override;

private:
/// Shell stacking direction in local stack coordinates
AxisDirection m_direction;

/// The cuboid face positioned first along the stacking direction
CuboidVolumeBounds::Face m_frontFace = NegativeXFace;
/// The cuboid face positioned last along the stacking direction
CuboidVolumeBounds::Face m_backFace = PositiveXFace;
/// The cuboid faces parallel to the stacking direction
std::array<CuboidVolumeBounds::Face, 4> m_sideFaces{
NegativeZFace, PositiveZFace, NegativeYFace, PositiveYFace};

std::vector<CuboidPortalShell*> m_shells;
};

} // namespace Acts
25 changes: 24 additions & 1 deletion Core/include/Acts/Geometry/CuboidVolumeBounds.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#pragma once

#include "Acts/Definitions/Algebra.hpp"
#include "Acts/Geometry/BoundarySurfaceFace.hpp"
#include "Acts/Geometry/Volume.hpp"
#include "Acts/Geometry/VolumeBounds.hpp"
#include "Acts/Utilities/AxisDefinitions.hpp"
Expand Down Expand Up @@ -58,6 +59,18 @@ class CuboidVolumeBounds : public VolumeBounds {
eSize
};

/// Enum describing the possible faces of a cuboid volume
/// @note These values are synchronized with the BoundarySurfaceFace enum.
/// Once Gen1 is removed, this can be changed.
enum class Face : unsigned int {
NegativeZFace = BoundarySurfaceFace::negativeFaceXY,
PositiveZFace = BoundarySurfaceFace::positiveFaceXY,
NegativeXFace = BoundarySurfaceFace::negativeFaceYZ,
PositiveXFace = BoundarySurfaceFace::positiveFaceYZ,
NegativeYFace = BoundarySurfaceFace::negativeFaceZX,
PositiveYFace = BoundarySurfaceFace::positiveFaceZX
};

CuboidVolumeBounds() = delete;

/// Constructor - the box boundaries
Expand Down Expand Up @@ -156,7 +169,17 @@ class CuboidVolumeBounds : public VolumeBounds {
/// Convert axis direction to a corresponding bound value
/// in local coordinate convention
/// @param direction the axis direction to convert
static BoundValues fromAxisDirection(AxisDirection direction);
static BoundValues boundsFromAxisDirection(AxisDirection direction);

/// Convert axis direction to a set of corresponding cuboid faces
/// in local coordinate convention
/// @param direction the axis direction to convert
/// @return A tuple of cuboid faces with the following ordering convention:
/// (1) negative face orthogonal to the axis direction
/// (2) positive face orthogonal to the axis direction
/// (3) list of side faces parallel to the axis direction
static std::tuple<Face, Face, std::array<Face, 4>> facesFromAxisDirection(
AxisDirection direction);

/// Output Method for std::ostream
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
#pragma once

#include "Acts/Geometry/BlueprintNode.hpp"
#include "Acts/Geometry/CylinderPortalShell.hpp"
#include "Acts/Geometry/CylinderVolumeStack.hpp"
#include "Acts/Geometry/PortalShell.hpp"
#include "Acts/Geometry/VolumeAttachmentStrategy.hpp"
#include "Acts/Geometry/VolumeResizeStrategy.hpp"
#include "Acts/Utilities/AxisDefinitions.hpp"
Expand Down
174 changes: 174 additions & 0 deletions Core/include/Acts/Geometry/CylinderPortalShell.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
// 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/Geometry/CylinderVolumeBounds.hpp"
#include "Acts/Geometry/PortalShell.hpp"
#include "Acts/Utilities/AxisDefinitions.hpp"
#include "Acts/Utilities/Logger.hpp"

#include <array>
#include <memory>

namespace Acts {

/// @class CylinderPortalShell
/// Base class for cylinder shaped portal shells, e.g. shells for cylinder
/// volumes
class CylinderPortalShell : public PortalShellBase {
public:
using Face = CylinderVolumeBounds::Face;

using enum CylinderVolumeBounds::Face;

/// Retrieve the portal associated to the given face. Can be nullptr if unset.
/// @param face The face to retrieve the portal for
/// @return The portal associated to the face
virtual Portal* portal(Face face) = 0;

/// Retrieve a shared_ptr for the portal associated to the given face. Can be
/// nullptr if unset.
/// @param face The face to retrieve the portal for
/// @return The portal associated to the face
virtual std::shared_ptr<Portal> portalPtr(Face face) = 0;

/// Set the portal associated to the given face.
/// @param portal The portal to set
/// @param face The face to set the portal
virtual void setPortal(std::shared_ptr<Portal> portal, Face face) = 0;

/// @copydoc PortalShellBase::fill
void fill(TrackingVolume& volume) override;
};

/// Output stream operator for the CylinderPortalShell::Face enum
/// @param os The output stream
/// @param face The face to output
/// @return The output stream
std::ostream& operator<<(std::ostream& os, CylinderPortalShell::Face face);

/// @class SingleCylinderPortalShell
/// This class describes a cylinder shell containing a single volume. The
/// available faces depend on the configuration of the cylinder volume bounds.
/// If a phi sector is configured, the shell will have corresponding portal
/// slots. If the inner radius is non-zero, the shell will have an inner
/// cylinder portal slot.
class SingleCylinderPortalShell : public CylinderPortalShell {
public:
using Base = CylinderPortalShell;

/// Construct a single cylinder portal shell for the given volume
/// @param volume The volume to create the shell for
explicit SingleCylinderPortalShell(TrackingVolume& volume);

/// @copydoc PortalShellBase::size
std::size_t size() const final;

/// @copydoc CylinderPortalShell::portal
Portal* portal(Face face) final;

/// @copydoc CylinderPortalShell::portalPtr
std::shared_ptr<Portal> portalPtr(Face face) final;

/// @copydoc CylinderPortalShell::setPortal
void setPortal(std::shared_ptr<Portal> portal, Face face) final;

/// @copydoc PortalShellBase::applyToVolume
void applyToVolume() override;

/// @copydoc PortalShellBase::isValid
bool isValid() const override;

/// @copydoc PortalShellBase::label
std::string label() const override;

private:
std::array<std::shared_ptr<Portal>, 6> m_portals{};

TrackingVolume* m_volume;
};

/// @class CylinderStackPortalShell
/// This class describes a cylinder shell containing multiple volumes. The
/// available faces depend on the configuration of the cylinder volume bounds.
/// @note The stack shell currently does not support phi sectors
/// The stack can be oriented along the (local) z or r direction, which drives
/// the stacking. Depending on the direction, portals on the shells of children
/// are merged or fused. Subsequently, portal access respects shared portals
/// between shells. Below is an illustration of a stack in the r direction:
///
/// Fused +-----------------+
/// portals ----+ | |
/// | | v OuterCylinder
/// | +------+------+
/// | | | |
/// | | | |<--+
/// +--+---+ v | |
/// +---+---------+ |
/// | | | | Shared portal
/// | | |<--+--- (grid)
/// | v | | PositiveDisc
/// +-------------+ |
/// r ^ | | |
/// | | |<--+
/// | | |
/// | +-------------+ InnerCylinder
/// +-----> ^ (if rMin>0)
/// z | |
/// +-----------------+
///
/// @note The shells must be ordered in the given direction
/// Depending on the stack direction, the portal lookup will return different
/// portals. In the illustration above, the `PositiveDisc` portal is shared
/// among all shells, while the `OuterCylinder` and `InnerCylinder` portals are
/// looked up from the innermost and outermost shell in the r direction.
class CylinderStackPortalShell : public CylinderPortalShell {
public:
using SingleShell = SingleCylinderPortalShell;

/// Construct the portal shell stack from the given shells
/// @param gctx The geometry context
/// @param shells The shells to stack
/// @note The shells must be ordered in the given direction
/// @param direction The stacking direction
/// @param logger A logging instance for debugging
CylinderStackPortalShell(const GeometryContext& gctx,
std::vector<CylinderPortalShell*> shells,
AxisDirection direction,
const Logger& logger = getDummyLogger());

/// @copydoc PortalShellBase::size
std::size_t size() const final;

/// @copydoc CylinderPortalShell::portal
Portal* portal(Face face) final;

/// @copydoc CylinderPortalShell::portalPtr
std::shared_ptr<Portal> portalPtr(Face face) final;

/// @copydoc CylinderPortalShell::setPortal
void setPortal(std::shared_ptr<Portal> portal, Face face) final;

void applyToVolume() override {
// No-op, because it's a composite portal shell
}

/// @copydoc PortalShellBase::isValid
bool isValid() const override;

/// @copydoc PortalShellBase::label
std::string label() const override;

private:
AxisDirection m_direction;
std::vector<CylinderPortalShell*> m_shells;
bool m_hasInnerCylinder{true};
};

} // namespace Acts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#pragma once

#include "Acts/Geometry/BlueprintNode.hpp"
#include "Acts/Geometry/PortalShell.hpp"
#include "Acts/Geometry/CylinderPortalShell.hpp"
#include "Acts/Utilities/ProtoAxis.hpp"

#include <variant>
Expand Down
Loading

0 comments on commit f5df1e9

Please sign in to comment.