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: Gen3 geometry Portals #3501

Merged
merged 31 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d8d558c
--------------------------------------------
paulgessinger Aug 9, 2024
9b52372
Revert "revert: Portal"
paulgessinger Aug 21, 2024
8709ac2
portal: Portal construction from link, resolveVolume interface
paulgessinger Aug 21, 2024
4304075
portal: portal volume lookup works, surface setting wip
paulgessinger Aug 9, 2024
1ffee4f
portal: work on portal tests
paulgessinger Aug 12, 2024
e781314
portal: wip fusing tests
paulgessinger Aug 13, 2024
99209e4
portal: Portal construction update
paulgessinger Aug 21, 2024
eeecbe4
portal: split up Portal and PortalLinkBase
paulgessinger Aug 21, 2024
9397be4
portal: TODO
paulgessinger Aug 21, 2024
855e92f
portal: Merging and fusing in presense of material
paulgessinger Aug 21, 2024
310792a
portal: Take geometry context where needed
paulgessinger Aug 22, 2024
a0b405f
portal: resolveVolume returns Result
paulgessinger Aug 23, 2024
69665fa
portal: Remove geometry context from constructors where they are not …
paulgessinger Aug 26, 2024
0087dc0
portal: Add documentation comments
paulgessinger Aug 26, 2024
6b3f962
spell fix + doxygen
paulgessinger Aug 27, 2024
fcbe5e7
portal: add default constructor to config member
paulgessinger Aug 27, 2024
68bad37
portal: Rename helper argument struct
paulgessinger Aug 27, 2024
cac7cf8
portal: use const ref instead of mutable
paulgessinger Aug 27, 2024
6aa2f38
feat(geo): Portal gets fill with trivial method
paulgessinger Aug 27, 2024
11c496c
Merge remote-tracking branch 'origin/main' into feat/gen3-portals
paulgessinger Aug 28, 2024
f40616e
portal: move exception strings to cpp file
paulgessinger Aug 28, 2024
0bc1d5e
portal: rename struct members
paulgessinger Aug 28, 2024
15462e8
portal: fix some typos
paulgessinger Aug 28, 2024
0292e99
portal: PR feedback round 2
paulgessinger Aug 28, 2024
f323f36
Merge branch 'main' into feat/gen3-portals
AJPfleger Aug 28, 2024
76e3261
Merge branch 'main' into feat/gen3-portals
AJPfleger Aug 28, 2024
99454dd
Merge branch 'main' into feat/gen3-portals
AJPfleger Aug 28, 2024
47bd311
Merge branch 'main' into feat/gen3-portals
kodiakhq[bot] Aug 28, 2024
14e7a3f
Merge branch 'main' into feat/gen3-portals
asalzburger Aug 29, 2024
9f7a507
Merge branch 'main' into feat/gen3-portals
AJPfleger Aug 29, 2024
e5c78f9
Merge branch 'main' into feat/gen3-portals
kodiakhq[bot] Aug 29, 2024
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
2 changes: 2 additions & 0 deletions Core/include/Acts/Definitions/Algebra.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,6 @@ using AngleAxis3 = Eigen::AngleAxis<ActsScalar>;
using Transform2 = Eigen::Transform<ActsScalar, 2, Eigen::AffineCompact>;
using Transform3 = Eigen::Transform<ActsScalar, 3, Eigen::Affine>;

constexpr ActsScalar s_transformEquivalentTolerance = 1e-9;

} // namespace Acts
234 changes: 234 additions & 0 deletions Core/include/Acts/Geometry/Portal.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
// This file is part of the Acts project.
//
// Copyright (C) 2024 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 http://mozilla.org/MPL/2.0/.

#pragma once

#include "Acts/Definitions/Algebra.hpp"
#include "Acts/Definitions/Direction.hpp"
#include "Acts/Utilities/BinningType.hpp"
#include "Acts/Utilities/Logger.hpp"
#include "Acts/Utilities/Result.hpp"

#include <memory>

namespace Acts {

class RegularSurface;
class GeometryContext;
class TrackingVolume;
class CylinderSurface;
class PlaneSurface;
class DiscSurface;
class Surface;

class PortalLinkBase;

/// Exception thrown when portals cannot be merged
class PortalMergingException : public std::exception {
const char* what() const noexcept override;
};

/// Exception thrown when portals cannot be fused
class PortalFusingException : public std::exception {
const char* what() const noexcept override;
};

/// A portal connects two or more neighboring volumes. Each volume has a set of
/// portals that describes which volumes lie behind the portal in that
/// direction. Portals use associated portal links to perform lookups of target
/// volumes.
/// Each portal has two links, and a corresponding surface. One link is
/// associated with the direction along the surface's normal vector, and one
/// with the opposite direction.
class Portal {
public:
/// Constructor for a portal from a single link
/// @param direction The direction of the link
/// @param link The portal link
Portal(Direction direction, std::unique_ptr<PortalLinkBase> link);

/// Constructor for a portal from a surface and volume, where a trivial portal
/// link is automatically constructed.
/// @param direction The direction of the link
/// @param surface The surface from which to create the portal link
/// @param volume The volume this portal connects to in the @p direction
/// relative to the normal of @p surface.
Portal(Direction direction, std::shared_ptr<RegularSurface> surface,
TrackingVolume& volume);

/// Constructor for a portal from two links. One of the links can be
/// `nullptr`, but at least one of them needs to be set. If both are set, they
/// need to be valid compatible links that can be fused.
/// @param gctx The geometry context
/// @param alongNormal The link along the normal of the surface
/// @param oppositeNormal The link opposite to the normal of the
Portal(const GeometryContext& gctx,
andiwand marked this conversation as resolved.
Show resolved Hide resolved
std::unique_ptr<PortalLinkBase> alongNormal,
std::unique_ptr<PortalLinkBase> oppositeNormal);

/// Helper struct for the arguments to the portal constructor below using
/// designated initializers.
struct Arguments {
/// Aggregate over a surface and a volume with optional semantics
struct Link {
Link() = default;
/// Constructor from a surface and a volume
Link(std::shared_ptr<RegularSurface> surfaceIn, TrackingVolume& volumeIn)
: surface(std::move(surfaceIn)), volume(&volumeIn) {}

/// The associated surface
std::shared_ptr<RegularSurface> surface = nullptr;
/// The associated volume
TrackingVolume* volume = nullptr;
};

/// Entry for the link along normal
/// Entry for the link opposite normal
Link alongNormal{};
Link oppositeNormal{};
};

/// Constructor that takes a geometry context and an rvalue reference to a
/// helper struct from above. This pattern allows you to use designated
/// initializers to construct this object like:
/// ```cpp
/// Portal{gctx, {.oppositeNormal = {cyl1, *vol1}}};
/// Portal{gctx, {.alongNormal = {cyl2, *vol2}}};
/// ```
/// @param gctx The geometry context
/// @param args The struct containing the arguments
Portal(const GeometryContext& gctx, Arguments&& args);

/// Fuse two portals together. Fusing is the combination of two portal links
/// on the same logical surfaces. The actual surface instances can be
/// different, as long as they are geometrically equivalent (within numerical
/// precision). The resulting portal will have one portal along the shared
/// surface's normal vector, and one opposite that vector.
///
/// portal1 portal2
/// +---+ +---+
/// | | | |
/// | | | |
/// <----+ | + | +---->
/// | | | |
/// | | | |
/// +---+ +---+
///
/// @note The input portals need to have compatible link loadaout, e.g. one
/// portal needs to have the *along normal* slot filled, and the
/// otherone one needs to have the *opposite normal* slot filled. If
/// portals share a filled slot, the function throws an exception.
/// @note This is a destructive operation on the portals involved
/// @param gctx The geometry context
/// @param aPortal The first portal
/// @param bPortal The second portal
/// @param logger The logger to push output to
static Portal fuse(const GeometryContext& gctx, Portal& aPortal,
Portal& bPortal, const Logger& logger = getDummyLogger());

/// Merge two adjacent portals with each other to produce a new portal that
/// encompasses both inputs. It is the complementary operation to the fusing
/// of portals. To be able to merge portals, the surfaces of their associated
/// links need to be *mergeable*, and the portal links need to be compatible.
/// This means that both portals need to have a link along the portal surface
/// normal, opposite the normal, or both. If the equipped links are opposite
/// relative to one another (e.g. one along one opposite), the function will
/// throw an exception.
///
/// ^ ^
/// | |
/// portal1| portal2|
/// +-------+-------+ +-------+-------+
/// | | + | |
/// +-------+-------+ +-------+-------+
/// | |
/// | |
/// v v
///
/// @note This is a destructive operation on both portals, their
/// links will be moved to produce merged links, which can fail
/// if the portal links are not compatible
/// @param gctx The geometry context
/// @param aPortal The first portal
/// @param bPortal The second portal
/// @param direction The direction of the merge (e.g. along z)
/// @param logger The logger to push output to
static Portal merge(const GeometryContext& gctx, Portal& aPortal,
Portal& bPortal, BinningValue direction,
const Logger& logger = getDummyLogger());

/// Resolve the volume for a 3D position and a direction
/// The @p direction is used to select the right portal link, if it is set.
/// In case no link is found in the specified direction, a `nullptr` is
/// returned.
/// @param gctx The geometry context
/// @param position The 3D position
/// @param direction The direction
/// @return The target volume (can be `nullptr`)
Result<const TrackingVolume*> resolveVolume(const GeometryContext& gctx,
const Vector3& position,
const Vector3& direction) const;

/// Set a link on the portal into the slot specified by the direction.
/// @note The surface associated with @p link must be logically equivalent
/// to the one of the link that's already set on the portal.
/// @param gctx The geometry context
/// @param direction The direction
/// @param link The link to set
void setLink(const GeometryContext& gctx, Direction direction,
std::unique_ptr<PortalLinkBase> link);

/// Helper function create a trivial portal link based on a surface.
/// @param gctx The geometry context
/// @param direction The direction of the link to create
/// @param surface The surface
/// @note The @p surface must be logically equivalent
/// to the one of the link that's already set on the portal.
/// @param volume The target volume
void setLink(const GeometryContext& gctx, Direction direction,
std::shared_ptr<RegularSurface> surface, TrackingVolume& volume);

/// Get the link associated with the @p direction. Can be null if the associated link is unset.
/// @param direction The direction
/// @return The link (can be null)
const PortalLinkBase* getLink(Direction direction) const;

/// Returns true if the portal is valid, that means it has at least one
/// non-null link associated.Portals can be in an invalid state after they get
/// merged or fused with other portals.
/// @return True if the portal is valid
bool isValid() const;

/// Create and attach a trivial portal link to the empty slot of this portal
/// @param volume The target volume to connect to
void fill(TrackingVolume& volume);

/// Access the portal surface that is shared between the two links
/// @return The portal surface
const RegularSurface& surface() const;

private:
/// Helper to check surface equivalence without checking material status. This
/// is needed because we allow fusing portals with surfaces that are
/// equivalent but one of them has material while the other does not. The
/// normal surface comparison would determine these surfaces as not
/// equivalent.
/// @param gctx The geometry context
/// @param a The first surface
/// @param b The second surface
/// @return True if the surfaces are equivalent
static bool isSameSurface(const GeometryContext& gctx, const Surface& a,
const Surface& b);
andiwand marked this conversation as resolved.
Show resolved Hide resolved

std::shared_ptr<RegularSurface> m_surface;

std::unique_ptr<PortalLinkBase> m_alongNormal;
std::unique_ptr<PortalLinkBase> m_oppositeNormal;
};

} // namespace Acts
1 change: 1 addition & 0 deletions Core/src/Geometry/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ target_sources(
Volume.cpp
VolumeBounds.cpp
CylinderVolumeStack.cpp
Portal.cpp
GridPortalLink.cpp
GridPortalLinkMerging.cpp
TrivialPortalLink.cpp
Expand Down
Loading
Loading