From 87e917ac518c6beafe0ea8f1659cbe8ca9203f31 Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Tue, 21 Jan 2025 11:19:45 +0200 Subject: [PATCH 01/22] adding cuboid volume stack --- .../Acts/Geometry/CuboidVolumeStack.hpp | 207 +++ Core/src/Geometry/CuboidVolumeStack.cpp | 894 +++++++++++++ .../Core/Geometry/CuboidVolumeStackTests.cpp | 1147 +++++++++++++++++ 3 files changed, 2248 insertions(+) create mode 100644 Core/include/Acts/Geometry/CuboidVolumeStack.hpp create mode 100644 Core/src/Geometry/CuboidVolumeStack.cpp create mode 100644 Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp diff --git a/Core/include/Acts/Geometry/CuboidVolumeStack.hpp b/Core/include/Acts/Geometry/CuboidVolumeStack.hpp new file mode 100644 index 00000000000..642c2ed6ddc --- /dev/null +++ b/Core/include/Acts/Geometry/CuboidVolumeStack.hpp @@ -0,0 +1,207 @@ +// 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/Utilities/AxisDefinitions.hpp" +#include "Acts/Utilities/Logger.hpp" + +#include + +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: + /// 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** + /// x, y, or z value is extended + First, + /// Given two volumes, the *right* one, i.e. the one with the higher + /// **local** x, y, or z 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 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& volumes, AxisDirection direction, + AttachmentStrategy strategy = AttachmentStrategy::Midpoint, + ResizeStrategy resizeStrategy = ResizeStrategy::Expand, + const Logger& logger = Acts::getDummyLogger()); + + /// 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& volumes, Vector3 direction, + AttachmentStrategy strategy = AttachmentStrategy::Midpoint, + ResizeStrategy resizeStrategy = ResizeStrategy::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 volbounds, + std::optional transform = std::nullopt, + const Logger& logger = getDummyLogger()) override; + + /// Access the gap volume that were created during attachment or resizing. + /// @return the vector of gap volumes + const std::vector>& gaps() const; + + 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& 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(AttachmentStrategy 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& 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& 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 checkOverlapAndAttach( + std::vector& volumes, AttachmentStrategy 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 synchronizeBounds(std::vector& 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 addGapVolume( + const Transform3& transform, const std::shared_ptr& 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{}; + + ResizeStrategy m_resizeStrategy{}; + Transform3 m_groupTransform{}; + std::vector> m_gaps{}; + std::vector& 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, + CuboidVolumeStack::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, + CuboidVolumeStack::ResizeStrategy strategy); + +} // namespace Acts diff --git a/Core/src/Geometry/CuboidVolumeStack.cpp b/Core/src/Geometry/CuboidVolumeStack.cpp new file mode 100644 index 00000000000..1ec295468a3 --- /dev/null +++ b/Core/src/Geometry/CuboidVolumeStack.cpp @@ -0,0 +1,894 @@ +// 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/. + +#include "Acts/Geometry/CuboidVolumeStack.hpp" + +#include "Acts/Definitions/Algebra.hpp" +#include "Acts/Definitions/Tolerance.hpp" +#include "Acts/Geometry/CuboidVolumeBounds.hpp" +#include "Acts/Utilities/AxisDefinitions.hpp" +#include "Acts/Utilities/Logger.hpp" + +#include +#include +#include +#include +#include +#include +#include + +namespace Acts { + +struct CuboidVolumeStack::VolumeTuple { + Volume* volume{}; + const CuboidVolumeBounds* bounds{}; + std::shared_ptr updatedBounds{}; + Transform3 localTransform = Transform3::Identity(); + Transform3 globalTransform = Transform3::Identity(); + + bool transformDirty = false; + + VolumeTuple(Volume& volume_, const Transform3& groupTransform) + : volume{&volume_}, + localTransform{groupTransform.inverse() * volume_.transform()}, + globalTransform{volume_.transform()} { + bounds = dynamic_cast(&volume_.volumeBounds()); + assert(bounds != nullptr); + updatedBounds = std::make_shared(*bounds); + } + + double mid(AxisDirection direction) const { + return localTransform.translation()[static_cast(direction)]; + } + double halfLength(AxisDirection direction) const { + return updatedBounds->get( + static_cast(direction)); + } + double min(AxisDirection direction) const { + return mid(direction) - halfLength(direction); + } + double max(AxisDirection direction) const { + return mid(direction) + halfLength(direction); + } + + void set( + std::initializer_list> + keyValues) { + updatedBounds->set(keyValues); + } + + void setLocalTransform(const Transform3& transform, + const Transform3& groupTransform) { + localTransform = transform; + globalTransform = groupTransform * localTransform; + transformDirty = true; + } + + void commit(const Logger& logger) { + // make a copy so we can't accidentally modify in-place + auto copy = std::make_shared(*updatedBounds); + + std::optional transform = std::nullopt; + if (transformDirty) { + transform = globalTransform; + } + + volume->update(std::move(updatedBounds), transform, logger); + bounds = copy.get(); + updatedBounds = std::move(copy); + transformDirty = false; + } +}; + +CuboidVolumeStack::CuboidVolumeStack(std::vector& volumes, + AxisDirection direction, + AttachmentStrategy strategy, + ResizeStrategy resizeStrategy, + const Logger& logger) + : Volume(initialVolume(volumes)), + m_dir(direction), + m_resizeStrategy(resizeStrategy), + m_volumes(volumes) { + std::size_t dirIdx = static_cast(m_dir); + m_dirOrth1 = static_cast((dirIdx + 1) % 3); + m_dirOrth2 = static_cast((dirIdx + 2) % 3); + + initializeOuterVolume(strategy, logger); +} + +CuboidVolumeStack::CuboidVolumeStack(std::vector& volumes, + Vector3 direction, + AttachmentStrategy strategy, + ResizeStrategy resizeStrategy, + const Logger& logger) + : Volume(initialVolume(volumes)), + m_resizeStrategy(resizeStrategy), + m_volumes(volumes) { + // TODO: What's a good tolerance here? + const auto& tolerance = s_onSurfaceTolerance; + Vector3 localDirVector = + m_volumes.front()->transform().rotation().inverse() * direction; + if ((localDirVector - Vector3::UnitX()).norm() < tolerance) { + m_dir = AxisDirection::AxisX; + } else if ((localDirVector - Vector3::UnitY()).norm() < tolerance) { + m_dir = AxisDirection::AxisY; + } else if ((localDirVector - Vector3::UnitZ()).norm() < tolerance) { + m_dir = AxisDirection::AxisZ; + } else { + throw std::invalid_argument( + "CuboidVolumeStack: Invalid axis direction"); + } + + std::size_t dirIdx = static_cast(m_dir); + m_dirOrth1 = static_cast((dirIdx + 1) % 3); + m_dirOrth2 = static_cast((dirIdx + 2) % 3); + + initializeOuterVolume(strategy, logger); +} + +Volume& CuboidVolumeStack::initialVolume(const std::vector& volumes) { + if (volumes.empty()) { + throw std::invalid_argument( + "CuboidVolumeStack requires at least one volume"); + } + return *volumes.front(); +} + +void CuboidVolumeStack::initializeOuterVolume(AttachmentStrategy strategy, + const Logger& logger) { + ACTS_DEBUG("Creating CuboidVolumeStack from " << m_volumes.size() + << " volumes in direction " + << axisDirectionName(m_dir)); + if (m_volumes.empty()) { + throw std::invalid_argument( + "CuboidVolumeStack requires at least one volume"); + } + + if (m_dir != Acts::AxisDirection::AxisX && + m_dir != Acts::AxisDirection::AxisY && + m_dir != Acts::AxisDirection::AxisZ) { + throw std::invalid_argument(axisDirectionName(m_dir) + + " is not supported "); + } + + // For alignment check, we have to pick one of the volumes as the base + m_groupTransform = m_volumes.front()->transform(); + ACTS_VERBOSE("Initial group transform is:\n" << m_groupTransform.matrix()); + + std::vector volumeTuples; + volumeTuples.reserve(m_volumes.size()); + + for (const auto& volume : m_volumes) { + const auto* cuboidBounds = + dynamic_cast(&volume->volumeBounds()); + if (cuboidBounds == nullptr) { + throw std::invalid_argument{ + "CuboidVolumeStack requires all volumes to " + "have CuboidVolumeBounds"}; + } + + volumeTuples.emplace_back(*volume, m_groupTransform); + } + + ACTS_DEBUG("*** Initial volume configuration:"); + printVolumeSequence(volumeTuples, logger, Acts::Logging::DEBUG); + + if (m_volumes.size() == 1) { + ACTS_VERBOSE("Only one volume, returning"); + setTransform(m_volumes.front()->transform()); + const auto* bounds = dynamic_cast( + &m_volumes.front()->volumeBounds()); + assert(bounds != nullptr && "Volume bounds are not cuboid bounds"); + Volume::update(std::make_shared(*bounds), std::nullopt, + logger); + ACTS_VERBOSE("Transform is now: " << m_transform.matrix()); + return; + } + + ACTS_VERBOSE("Checking volume alignment"); + checkVolumeAlignment(volumeTuples, logger); + + std::size_t dirIdx = static_cast(m_dir); + ACTS_VERBOSE("Sorting by volume " << axisDirectionName(m_dir) << " position"); + std::ranges::sort(volumeTuples, {}, [&dirIdx](const auto& v) { + return v.localTransform.translation()[dirIdx]; + }); + ACTS_VERBOSE("Checking for overlaps and attaching volumes in " + << axisDirectionName(m_dir)); + std::vector gapVolumes = + checkOverlapAndAttach(volumeTuples, strategy, logger); + + ACTS_VERBOSE("Appending " << gapVolumes.size() + << " gap volumes to the end of the volume vector"); + std::copy(gapVolumes.begin(), gapVolumes.end(), + std::back_inserter(volumeTuples)); + + ACTS_VERBOSE("*** Volume configuration after " << axisDirectionName(m_dir) + << " attachment:"); + printVolumeSequence(volumeTuples, logger, Acts::Logging::VERBOSE); + + ACTS_VERBOSE("Synchronizing bounds in " << axisDirectionName(m_dirOrth1) + << "/" + << axisDirectionName(m_dirOrth2)); + const auto [hl1, hl2] = synchronizeBounds(volumeTuples, logger); + + for (auto& vt : volumeTuples) { + ACTS_VERBOSE("Updated bounds for volume at " + << axisDirectionName(m_dir) << ": " + << vt.localTransform.translation()[dirIdx]); + ACTS_VERBOSE(*vt.updatedBounds); + + vt.commit(logger); + } + + ACTS_VERBOSE("*** Volume configuration after " + << axisDirectionName(m_dirOrth1) << "/" + << axisDirectionName(m_dirOrth2) << " synchronization:"); + printVolumeSequence(volumeTuples, logger, Acts::Logging::VERBOSE); + + std::ranges::sort(volumeTuples, {}, + [*this](const auto& v) { return v.mid(m_dir); }); + + m_volumes.clear(); + for (const auto& vt : volumeTuples) { + m_volumes.push_back(vt.volume); + } + + ACTS_DEBUG("*** Volume configuration after final " << axisDirectionName(m_dir) + << " sorting:"); + printVolumeSequence(volumeTuples, logger, Acts::Logging::DEBUG); + + double min = volumeTuples.front().min(m_dir); + double max = volumeTuples.back().max(m_dir); + + double mid = (min + max) / 2.0; + double hl = (max - min) / 2.0; + + Translation3 translation(Vector3::Unit(dirIdx) * mid); + m_transform = m_groupTransform * translation; + std::array bounds; + bounds.at(dirIdx) = hl; + bounds.at(static_cast(m_dirOrth1)) = hl1; + bounds.at(static_cast(m_dirOrth2)) = hl2; + + Volume::update(std::make_shared(bounds), std::nullopt, + logger); + ACTS_DEBUG("Outer bounds are:\n" << volumeBounds()); + ACTS_DEBUG("Outer transform / new group transform is:\n" + << m_transform.matrix()); + + // Update group transform to the new center + // @TODO: We probably can reuse m_transform + m_groupTransform = m_transform; +} + +void CuboidVolumeStack::overlapPrint(const CuboidVolumeStack::VolumeTuple& a, + const CuboidVolumeStack::VolumeTuple& b, + const Logger& logger) { + if (logger().doPrint(Acts::Logging::DEBUG)) { + std::stringstream ss; + ss << std::fixed; + ss << std::setprecision(3); + ss << std::setfill(' '); + + int w = 9; + + ACTS_VERBOSE("Checking overlap between"); + ss << " - " << " " << axisDirectionName(m_dir) << ": [ " << std::setw(w) + << a.min(m_dir) << " <- " << std::setw(w) << a.mid(m_dir) << " -> " + << std::setw(w) << a.max(m_dir) << " ]"; + ACTS_VERBOSE(ss.str()); + + ss.str(""); + ss << " - " << " " << axisDirectionName(m_dir) << ": [ " << std::setw(w) + << b.min(m_dir) << " <- " << std::setw(w) << b.mid(m_dir) << " -> " + << std::setw(w) << b.max(m_dir) << " ]"; + ACTS_VERBOSE(ss.str()); + } +} + +std::vector +CuboidVolumeStack::checkOverlapAndAttach( + std::vector& volumes, + CuboidVolumeStack::AttachmentStrategy strategy, const Logger& logger) { + // Preconditions: volumes are sorted along stacking direction + auto dirIdx = static_cast(m_dir); + auto dirBoundIdx = static_cast(m_dir); + + std::vector gapVolumes; + for (std::size_t i = 0; i < volumes.size() - 1; i++) { + std::size_t j = i + 1; + auto& a = volumes.at(i); + auto& b = volumes.at(j); + + overlapPrint(a, b, logger); + + // TODO: What's a good tolerance? + constexpr auto tolerance = s_onSurfaceTolerance; + if (a.max(m_dir) - tolerance > b.min(m_dir)) { + ACTS_ERROR(" -> Overlap in " << axisDirectionName(m_dir)); + throw std::invalid_argument("Volumes overlap in " + + axisDirectionName(m_dir)); + } else { + ACTS_VERBOSE(" -> No overlap"); + } + + if (std::abs(a.max(m_dir) - b.min(m_dir)) < tolerance) { + ACTS_VERBOSE("No gap between volumes, no attachment needed"); + } else { + double gapWidth = b.min(m_dir) - a.max(m_dir); + ACTS_VERBOSE("Gap width: " << gapWidth); + + ACTS_VERBOSE("Synchronizing bounds in " + << axisDirectionName(m_dir) + << " with strategy: " << strategy); + switch (strategy) { + case AttachmentStrategy::Midpoint: { + ACTS_VERBOSE(" -> Strategy: Expand both volumes to midpoint"); + + double aMidNew = (a.min(m_dir) + a.max(m_dir)) / 2.0 + gapWidth / 4.0; + double aHlNew = a.halfLength(m_dir) + gapWidth / 4.0; + ACTS_VERBOSE(" - New halflength for first volume: " << aHlNew); + ACTS_VERBOSE(" - New bounds for first volume: [" + << (aMidNew - aHlNew) << " <- " << aMidNew << " -> " + << (aMidNew + aHlNew) << "]"); + + assert(std::abs(a.min(m_dir) - (aMidNew - aHlNew)) < 1e-9 && + "Volume shrunk"); + assert(aHlNew >= a.halfLength(m_dir) && "Volume shrunk"); + + double bMidNew = (b.min(m_dir) + b.max(m_dir)) / 2.0 - gapWidth / 4.0; + double bHlNew = b.halfLength(m_dir) + gapWidth / 4.0; + ACTS_VERBOSE(" - New halflength for second volume: " << bHlNew); + ACTS_VERBOSE(" - New bounds for second volume: [" + << (bMidNew - bHlNew) << " <- " << bMidNew << " -> " + << (bMidNew + bHlNew) << "]"); + + assert(bHlNew >= b.halfLength(m_dir) && "Volume shrunk"); + assert(std::abs(b.max(m_dir) - (bMidNew + bHlNew)) < 1e-9 && + "Volume shrunk"); + + Translation3 translationA(Vector3::Unit(dirIdx) * aMidNew); + a.setLocalTransform(Transform3{translationA}, m_groupTransform); + a.updatedBounds->set(dirBoundIdx, aHlNew); + + Translation3 translationB(Vector3::Unit(dirIdx) * bMidNew); + b.setLocalTransform(Transform3{translationB}, m_groupTransform); + b.updatedBounds->set(dirBoundIdx, bHlNew); + + break; + } + case AttachmentStrategy::First: { + ACTS_VERBOSE(" -> Strategy: Expand first volume"); + double aMidNew = (a.min(m_dir) + b.min(m_dir)) / 2.0; + double aHlNew = (b.min(m_dir) - a.min(m_dir)) / 2.0; + ACTS_VERBOSE(" - Gap width: " << gapWidth); + ACTS_VERBOSE(" - New bounds for first volume: [" + << (aMidNew - aHlNew) << " <- " << aMidNew << " -> " + << (aMidNew + aHlNew) << "]"); + + assert(std::abs(a.min(m_dir) - (aMidNew - aHlNew)) < 1e-9 && + "Volume shrunk"); + assert(aHlNew >= a.halfLength(m_dir) && "Volume shrunk"); + + Translation3 translationA(Vector3::Unit(dirIdx) * aMidNew); + a.setLocalTransform(Transform3{translationA}, m_groupTransform); + a.updatedBounds->set(dirBoundIdx, aHlNew); + + break; + } + case AttachmentStrategy::Second: { + ACTS_VERBOSE(" -> Strategy: Expand second volume"); + double bMidNew = (a.max(m_dir) + b.max(m_dir)) / 2.0; + double bHlNew = (b.max(m_dir) - a.max(m_dir)) / 2.0; + ACTS_VERBOSE(" - New halflength for second volume: " << bHlNew); + ACTS_VERBOSE(" - New bounds for second volume: [" + << (bMidNew - bHlNew) << " <- " << bMidNew << " -> " + << (bMidNew + bHlNew) << "]"); + + assert(bHlNew >= b.halfLength(m_dir) && "Volume shrunk"); + assert(std::abs(b.max(m_dir) - (bMidNew + bHlNew)) < 1e-9 && + "Volume shrunk"); + + Translation3 translationB(Vector3::Unit(dirIdx) * bMidNew); + b.setLocalTransform(Transform3{translationB}, m_groupTransform); + b.updatedBounds->set(dirBoundIdx, bHlNew); + break; + } + case AttachmentStrategy::Gap: { + ACTS_VERBOSE(" -> Strategy: Create a gap volume"); + double gapHl = (b.min(m_dir) - a.max(m_dir)) / 2.0; + double gapMid = (b.min(m_dir) + a.max(m_dir)) / 2.0; + + ACTS_VERBOSE(" - Gap half length: " << gapHl << " at " + << axisDirectionName(m_dir) + << ": " << gapMid); + + Translation3 gapTranslation(Vector3::Unit(dirIdx) * gapMid); + + double min1 = std::min(a.min(m_dirOrth1), b.min(m_dirOrth1)); + double max1 = std::max(a.max(m_dirOrth1), b.max(m_dirOrth1)); + + double min2 = std::min(a.min(m_dirOrth2), b.min(m_dirOrth2)); + double max2 = std::max(a.max(m_dirOrth2), b.max(m_dirOrth2)); + + Transform3 gapLocalTransform{gapTranslation}; + Transform3 gapGlobalTransform = m_groupTransform * gapLocalTransform; + + std::array gapBoundsVals; + gapBoundsVals[dirIdx] = gapHl; + gapBoundsVals[static_cast(m_dirOrth1)] = + (max1 - min1) / 2; + gapBoundsVals[static_cast(m_dirOrth2)] = + (max2 - min2) / 2; + auto gapBounds = std::make_shared(gapBoundsVals); + auto gap = addGapVolume(gapGlobalTransform, gapBounds); + gapVolumes.emplace_back(*gap, m_groupTransform); + + break; + } + default: + ACTS_ERROR("Attachment strategy " << strategy << " not implemented"); + std::stringstream ss; + ss << strategy; + throw std::invalid_argument("Attachment strategy " + ss.str() + + " not implemented"); + } + } + } + + return gapVolumes; +} + +void CuboidVolumeStack::printVolumeSequence( + const std::vector& volumes, const Logger& logger, + Acts::Logging::Level lvl) { + if (!logger().doPrint(lvl)) { + return; + } + for (const auto& vt : volumes) { + std::stringstream ss; + ss << std::fixed; + ss << std::setprecision(3); + ss << std::setfill(' '); + + int w = 9; + + for (const auto& axis : + {AxisDirection::AxisX, AxisDirection::AxisY, AxisDirection::AxisZ}) { + ss << axisDirectionName(axis) << ": [ " << std::setw(w) << vt.min(axis) + << " <- " << std::setw(w) << vt.mid(axis) << " -> " << std::setw(w) + << vt.max(axis) << " ]\n"; + } + logger().log(lvl, ss.str()); + } +} + +void CuboidVolumeStack::checkVolumeAlignment( + const std::vector& volumes, const Logger& logger) const { + std::size_t n = 0; + std::size_t dirIdx = static_cast(m_dir); + std::size_t dirOrth1Idx = static_cast(m_dirOrth1); + std::size_t dirOrth2Idx = static_cast(m_dirOrth2); + + for (auto& vt : volumes) { + ACTS_VERBOSE("Checking volume #" + << n << " at " << axisDirectionName(m_dir) << ": " + << vt.localTransform.translation()[dirIdx]); + ACTS_VERBOSE("- Local transform is:\n" << vt.localTransform.matrix()); + + // @TODO: Rotation precision? + constexpr auto tolerance = s_onSurfaceTolerance; + + // In the group coordinate system: + + // a) the volumes cannot have any relative rotation + if ((vt.localTransform.rotation().matrix() - RotationMatrix3::Identity()) + .norm() > tolerance) { + ACTS_ERROR("Volumes are not aligned: rotation is different"); + throw std::invalid_argument( + "Volumes are not aligned: rotation is different"); + } + + ACTS_VERBOSE(" -> Rotation is ok!"); + + // b) the volumes cannot have translation in orthogonal directions + if (std::abs(vt.localTransform.translation()[dirOrth1Idx]) > tolerance || + std::abs(vt.localTransform.translation()[dirOrth2Idx]) > tolerance) { + ACTS_ERROR("Volumes are not aligned: translation in " + << axisDirectionName(m_dirOrth1) << " or " + << axisDirectionName(m_dirOrth2)); + throw std::invalid_argument("Volumes are not aligned: translation in " + + axisDirectionName(m_dirOrth1) + " or " + + axisDirectionName(m_dirOrth2)); + } + ACTS_VERBOSE(" -> Translation in " << axisDirectionName(m_dirOrth1) << "/" + << axisDirectionName(m_dirOrth2) + << " is ok!"); + + n++; + } +} + +std::pair CuboidVolumeStack::synchronizeBounds( + std::vector& volumes, const Logger& logger) { + auto boundDirOrth1 = static_cast(m_dirOrth1); + auto boundDirOrth2 = static_cast(m_dirOrth2); + + const double maxHl1 = + std::max_element(volumes.begin(), volumes.end(), + [&boundDirOrth1](const auto& a, const auto& b) { + return a.bounds->get(boundDirOrth1) < + b.bounds->get(boundDirOrth1); + }) + ->bounds->get(boundDirOrth1); + const double maxHl2 = + std::max_element(volumes.begin(), volumes.end(), + [&boundDirOrth2](const auto& a, const auto& b) { + return a.bounds->get(boundDirOrth2) < + b.bounds->get(boundDirOrth2); + }) + ->bounds->get(boundDirOrth2); + ACTS_VERBOSE("Found: half length " << axisDirectionName(m_dirOrth1) << ":" + << maxHl1 << ", half length " + << axisDirectionName(m_dirOrth2) << ":" + << maxHl2); + + for (auto& vt : volumes) { + vt.set({ + {boundDirOrth1, maxHl1}, + {boundDirOrth2, maxHl2}, + }); + } + + return {maxHl1, maxHl2}; +} + +void CuboidVolumeStack::update(std::shared_ptr volbounds, + std::optional transform, + const Logger& logger) { + ACTS_DEBUG("Resizing CuboidVolumeStack with strategy: " << m_resizeStrategy); + ACTS_DEBUG("Currently have " << m_volumes.size() << " children"); + ACTS_DEBUG(m_gaps.size() << " gaps"); + for (const auto& v : m_volumes) { + ACTS_DEBUG(" - volume bounds: \n" << v->volumeBounds()); + ACTS_DEBUG(" transform: \n" << v->transform().matrix()); + } + + ACTS_DEBUG("New bounds are: \n" << *volbounds); + + auto bounds = std::dynamic_pointer_cast(volbounds); + if (bounds == nullptr) { + throw std::invalid_argument( + "CuboidVolumeStack requires CuboidVolumeBounds"); + } + + if (bounds == nullptr) { + throw std::invalid_argument("New bounds are nullptr"); + } + + if (*bounds == volumeBounds()) { + ACTS_VERBOSE("Bounds are the same, no resize needed"); + return; + } + + ACTS_VERBOSE("Group transform is:\n" << m_groupTransform.matrix()); + ACTS_VERBOSE("Current transform is:\n" << m_transform.matrix()); + if (transform.has_value()) { + ACTS_VERBOSE("Input transform:\n" << transform.value().matrix()); + } + + VolumeTuple oldVolume{*this, m_transform}; + VolumeTuple newVolume{*this, m_transform}; + newVolume.updatedBounds = std::make_shared(*bounds); + newVolume.globalTransform = transform.value_or(m_transform); + newVolume.localTransform = m_transform.inverse() * newVolume.globalTransform; + + if (!transform.has_value()) { + ACTS_VERBOSE("Local transform does not change"); + } else { + ACTS_VERBOSE("Local transform changes from\n" + << m_groupTransform.matrix() << "\nto\n" + << newVolume.localTransform.matrix()); + ACTS_VERBOSE("Checking transform consistency"); + + std::vector volTemp{newVolume}; + checkVolumeAlignment(volTemp, logger); + } + + constexpr auto tolerance = 1e-1; + auto same = [](double a, double b) { return std::abs(a - b) < tolerance; }; + + for (const auto& dir : {m_dir, m_dirOrth1, m_dirOrth2}) { + const double newMin = newVolume.min(dir); + const double newMax = newVolume.max(dir); + const double newMid = newVolume.mid(dir); + const double newHl = newVolume.halfLength(dir); + + const double oldMin = oldVolume.min(dir); + const double oldMax = oldVolume.max(dir); + const double oldMid = oldVolume.mid(dir); + const double oldHl = oldVolume.halfLength(dir); + + ACTS_VERBOSE("Previous bounds are: " << axisDirectionName(dir) << ": [ " + << oldMin << " <- " << oldMid << " -> " + << oldMax << " ] (" << oldHl << ")\n"); + ACTS_VERBOSE("New bounds are: " << axisDirectionName(dir) << ": [ " + << newMin << " <- " << newMid << " -> " + << newMax << " ] (" << newHl << ")\n"); + + if (!same(newMin, oldMin) && newMin > oldMin) { + ACTS_ERROR("Shrinking the stack size in " + << axisDirectionName(dir) << " is not supported: " << newMin + << " -> " << oldMin); + throw std::invalid_argument("Shrinking the stack in " + + axisDirectionName(dir) + " is not supported"); + } + + if (!same(newMax, oldMax) && newMax < oldMax) { + ACTS_ERROR("Shrinking the stack size in " + << axisDirectionName(dir) << " is not supported: " << newMax + << " -> " << oldMax); + throw std::invalid_argument("Shrinking the stack in " + + axisDirectionName(dir) + " is not supported"); + } + } + auto isGap = [this](const Volume* vol) { + return std::ranges::any_of( + m_gaps, [&](const auto& gap) { return vol == gap.get(); }); + }; + ACTS_VERBOSE("Stack direction is " << axisDirectionName(m_dir)); + + std::vector volumeTuples; + volumeTuples.reserve(m_volumes.size()); + std::transform(m_volumes.begin(), m_volumes.end(), + std::back_inserter(volumeTuples), [this](const auto& volume) { + return VolumeTuple{*volume, m_groupTransform}; + }); + + ACTS_VERBOSE("*** Initial volume configuration:"); + printVolumeSequence(volumeTuples, logger, Acts::Logging::DEBUG); + for (const auto& dir : {m_dirOrth1, m_dirOrth2}) { + if (!same(newVolume.min(dir), oldVolume.min(dir)) || + !same(newVolume.max(dir), oldVolume.max(dir))) { + ACTS_VERBOSE("Resize all volumes to new " << axisDirectionName(dir) + << " bounds"); + for (auto& volume : volumeTuples) { + volume.set({{static_cast(dir), + newVolume.halfLength(dir)}}); + } + ACTS_VERBOSE("*** Volume configuration after " << axisDirectionName(dir) + << " resizing:"); + printVolumeSequence(volumeTuples, logger, Acts::Logging::DEBUG); + } else { + ACTS_VERBOSE(axisDirectionName(dir) + << " bounds are the same, no " << axisDirectionName(dir) + << " resize needed"); + } + } + + if (same(newVolume.halfLength(m_dir), oldVolume.halfLength(m_dir))) { + ACTS_VERBOSE("Halflength " << axisDirectionName(m_dir) << "is the same, no " + << axisDirectionName(m_dir) << "resize needed"); + } else { + std::size_t dirIdx = static_cast(m_dir); + std::size_t dirOrth1Idx = static_cast(m_dirOrth1); + std::size_t dirOrth2Idx = static_cast(m_dirOrth2); + auto boundDirIdx = static_cast(m_dir); + if (m_resizeStrategy == ResizeStrategy::Expand) { + if (newVolume.min(m_dir) < oldVolume.min(m_dir)) { + ACTS_VERBOSE("Expanding first volume to new " + << axisDirectionName(m_dir) << "bounds"); + + auto& first = volumeTuples.front(); + double newMinFirst = newVolume.min(m_dir); + double newMidFirst = (newMinFirst + first.max(m_dir)) / 2.0; + double newHlFirst = (first.max(m_dir) - newMinFirst) / 2.0; + + ACTS_VERBOSE(" -> first " << axisDirectionName(m_dir) << ": [ " + << newMinFirst << " <- " << newMidFirst + << " -> " << first.max(m_dir) + << " ] (hl: " << newHlFirst << ")"); + + Translation3 translation(Vector3::Unit(dirIdx) * newMidFirst); + first.set({{boundDirIdx, newHlFirst}}); + first.setLocalTransform(Transform3{translation}, m_groupTransform); + } + + if (newVolume.max(m_dir) > oldVolume.max(m_dir)) { + ACTS_VERBOSE("Expanding last volume to new " << axisDirectionName(m_dir) + << " bounds"); + + auto& last = volumeTuples.back(); + double newMaxLast = newVolume.max(m_dir); + double newMidLast = (last.min(m_dir) + newMaxLast) / 2.0; + double newHlLast = (newMaxLast - last.min(m_dir)) / 2.0; + + ACTS_VERBOSE(" -> last " << axisDirectionName(m_dir) << ": [ " + << last.min(m_dir) << " <- " << newMidLast + << " -> " << newMaxLast + << " ] (hl: " << newHlLast << ")"); + + Translation3 translation(Vector3::Unit(dirIdx) * newMidLast); + last.set({{boundDirIdx, newHlLast}}); + last.setLocalTransform(Transform3{translation}, m_groupTransform); + } + } else if (m_resizeStrategy == ResizeStrategy::Gap) { + ACTS_VERBOSE("Creating gap volumes to fill the new " + << axisDirectionName(m_dir) << " bounds"); + + auto printGapDimensions = [&](const VolumeTuple& gap, + const std::string& prefix = "") { + for (const auto& dir : {m_dir, m_dirOrth1, m_dirOrth2}) { + ACTS_VERBOSE(" -> gap" << prefix << ": " << axisDirectionName(dir) + << ": [ " << gap.min(m_dir) << " <- " + << gap.mid(dir) << " -> " << gap.max(dir) + << " ]"); + } + }; + + if (!same(newVolume.min(m_dir), oldVolume.min(m_dir)) && + newVolume.min(m_dir) < oldVolume.min(m_dir)) { + double gap1Min = newVolume.min(m_dir); + double gap1Max = oldVolume.min(m_dir); + double gap1Hl = (gap1Max - gap1Min) / 2.0; + double gap1P = (gap1Max + gap1Min) / 2.0; + + // check if we need a new gap volume or reuse an existing one + auto& candidate = volumeTuples.front(); + if (isGap(candidate.volume)) { + ACTS_VERBOSE("~> Reusing existing gap volume at negative " + << axisDirectionName(m_dir)); + + gap1Hl = candidate.bounds->get( + static_cast(m_dir)) + + gap1Hl; + gap1Max = gap1Min + gap1Hl * 2; + gap1P = (gap1Max + gap1Min) / 2.0; + + printGapDimensions(candidate, " before"); + + std::array gap1BoundsVals; + gap1BoundsVals[dirIdx] = gap1Hl; + gap1BoundsVals[dirOrth1Idx] = newVolume.halfLength(m_dirOrth1); + gap1BoundsVals[dirOrth2Idx] = newVolume.halfLength(m_dirOrth2); + auto gap1Bounds = + std::make_shared(gap1BoundsVals); + Translation3 gap1Translation(Vector3::Unit(dirIdx) * gap1P); + Transform3 gap1Transform = m_groupTransform * gap1Translation; + candidate.volume->update(std::move(gap1Bounds), gap1Transform); + candidate = VolumeTuple{*candidate.volume, m_groupTransform}; + ACTS_VERBOSE("After:"); + printGapDimensions(candidate, " after "); + + } else { + ACTS_VERBOSE("~> Creating new gap volume at negative "); + std::array gap1BoundsVals; + gap1BoundsVals[dirIdx] = gap1Hl; + gap1BoundsVals[dirOrth1Idx] = newVolume.halfLength(m_dirOrth1); + gap1BoundsVals[dirOrth2Idx] = newVolume.halfLength(m_dirOrth2); + auto gap1Bounds = + std::make_shared(gap1BoundsVals); + Translation3 gap1Translation(Vector3::Unit(dirIdx) * gap1P); + Transform3 gap1Transform = m_groupTransform * gap1Translation; + auto gap1 = addGapVolume(gap1Transform, std::move(gap1Bounds)); + volumeTuples.insert(volumeTuples.begin(), + VolumeTuple{*gap1, m_groupTransform}); + printGapDimensions(volumeTuples.front()); + } + } + + if (!same(newVolume.max(m_dir), oldVolume.max(m_dir)) && + newVolume.max(m_dir) > oldVolume.max(m_dir)) { + double gap2Min = oldVolume.max(m_dir); + double gap2Max = newVolume.max(m_dir); + double gap2Hl = (gap2Max - gap2Min) / 2.0; + double gap2P = (gap2Max + gap2Min) / 2.0; + + // check if we need a new gap volume or reuse an existing one + auto& candidate = volumeTuples.back(); + if (isGap(candidate.volume)) { + ACTS_VERBOSE("~> Reusing existing gap volume at positive "); + + gap2Hl = candidate.bounds->get( + static_cast(m_dir)) + + gap2Hl; + gap2Min = newVolume.max(m_dir) - gap2Hl * 2; + gap2P = (gap2Max + gap2Min) / 2.0; + + std::array gap2BoundsVals; + gap2BoundsVals[dirIdx] = gap2Hl; + gap2BoundsVals[dirOrth1Idx] = newVolume.halfLength(m_dirOrth1); + gap2BoundsVals[dirOrth2Idx] = newVolume.halfLength(m_dirOrth2); + auto gap2Bounds = + std::make_shared(gap2BoundsVals); + Translation3 gap2Translation(Vector3::Unit(dirIdx) * gap2P); + Transform3 gap2Transform = m_groupTransform * gap2Translation; + + candidate.volume->update(std::move(gap2Bounds), gap2Transform); + candidate = VolumeTuple{*candidate.volume, m_groupTransform}; + printGapDimensions(candidate, " after "); + } else { + ACTS_VERBOSE("~> Creating new gap volume at positive "); + std::array gap2BoundsVals; + gap2BoundsVals[dirIdx] = gap2Hl; + gap2BoundsVals[dirOrth1Idx] = newVolume.halfLength(m_dirOrth1); + gap2BoundsVals[dirOrth2Idx] = newVolume.halfLength(m_dirOrth2); + auto gap2Bounds = + std::make_shared(gap2BoundsVals); + Translation3 gap2Translation(Vector3::Unit(dirIdx) * gap2P); + Transform3 gap2Transform = m_groupTransform * gap2Translation; + auto gap2 = addGapVolume(gap2Transform, std::move(gap2Bounds)); + volumeTuples.emplace_back(*gap2, m_groupTransform); + printGapDimensions(volumeTuples.back()); + } + } + } + + ACTS_VERBOSE("*** Volume configuration after " << axisDirectionName(m_dir) + << " resizing:"); + printVolumeSequence(volumeTuples, logger, Acts::Logging::DEBUG); + } + + ACTS_VERBOSE("Commit and update outer vector of volumes"); + m_volumes.clear(); + for (auto& vt : volumeTuples) { + vt.commit(logger); + m_volumes.push_back(vt.volume); + } + + m_transform = newVolume.globalTransform; + // @TODO: We probably can reuse m_transform + m_groupTransform = m_transform; + Volume::update(std::move(bounds), std::nullopt, logger); +} + +std::shared_ptr CuboidVolumeStack::addGapVolume( + const Transform3& transform, const std::shared_ptr& bounds) { + auto gapVolume = std::make_shared(transform, bounds); + m_gaps.push_back(gapVolume); + return gapVolume; +} + +const std::vector>& CuboidVolumeStack::gaps() const { + return m_gaps; +} + +std::ostream& operator<<(std::ostream& os, + CuboidVolumeStack::AttachmentStrategy strategy) { + switch (strategy) { + case CuboidVolumeStack::AttachmentStrategy::First: + os << "First"; + break; + case CuboidVolumeStack::AttachmentStrategy::Second: + os << "Second"; + break; + case CuboidVolumeStack::AttachmentStrategy::Midpoint: + os << "Midpoint"; + break; + case CuboidVolumeStack::AttachmentStrategy::Gap: + os << "Gap"; + break; + } + return os; +} + +std::ostream& operator<<(std::ostream& os, + CuboidVolumeStack::ResizeStrategy strategy) { + switch (strategy) { + case CuboidVolumeStack::ResizeStrategy::Expand: + os << "Expand"; + break; + case CuboidVolumeStack::ResizeStrategy::Gap: + os << "Gap"; + break; + } + return os; +} + +} // namespace Acts diff --git a/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp b/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp new file mode 100644 index 00000000000..e40d07bad1b --- /dev/null +++ b/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp @@ -0,0 +1,1147 @@ +// 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/. + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Acts/Definitions/Algebra.hpp" +#include "Acts/Definitions/Units.hpp" +#include "Acts/Geometry/CuboidVolumeBounds.hpp" +#include "Acts/Geometry/CuboidVolumeStack.hpp" +#include "Acts/Tests/CommonHelpers/FloatComparisons.hpp" +#include "Acts/Utilities/AxisDefinitions.hpp" +#include "Acts/Utilities/Logger.hpp" +#include "Acts/Utilities/Zip.hpp" + +using namespace Acts::UnitLiterals; + +namespace Acts::Test { + +auto logger = Acts::getDefaultLogger("UnitTests", Acts::Logging::VERBOSE); + +struct Fixture { + Logging::Level m_level; + Fixture() { + m_level = Acts::Logging::getFailureThreshold(); + Acts::Logging::setFailureThreshold(Acts::Logging::FATAL); + } + + ~Fixture() { Acts::Logging::setFailureThreshold(m_level); } +}; + +BOOST_FIXTURE_TEST_SUITE(Geometry, Fixture) + +static const std::vector strategies = { + CuboidVolumeStack::AttachmentStrategy::Gap, + CuboidVolumeStack::AttachmentStrategy::First, + CuboidVolumeStack::AttachmentStrategy::Second, + CuboidVolumeStack::AttachmentStrategy::Midpoint, +}; + +static const std::vector resizeStrategies = { + CuboidVolumeStack::ResizeStrategy::Expand, + CuboidVolumeStack::ResizeStrategy::Gap, +}; + +BOOST_AUTO_TEST_SUITE(CuboidVolumeStackTest) + +BOOST_DATA_TEST_CASE(BaselineLocal, + (boost::unit_test::data::xrange(-135, 180, 45) * + boost::unit_test::data::xrange(0, 2, 1) * + boost::unit_test::data::make(0.8, 1.0, 1.2) * + boost::unit_test::data::make(Vector3{0_mm, 0_mm, 0_mm}, + Vector3{20_mm, 0_mm, 0_mm}, + Vector3{0_mm, 20_mm, 0_mm}, + Vector3{20_mm, 20_mm, 0_mm}, + Vector3{0_mm, 0_mm, 20_mm}) * + boost::unit_test::data::make(strategies) * + boost::unit_test::data::make(Acts::AxisDirection::AxisX, + Acts::AxisDirection::AxisY, + Acts::AxisDirection::AxisZ)), + angle, rotate, shift, offset, strategy, dir) { + double halfDir = 400_mm; + + std::size_t dirIdx = static_cast(dir); + std::size_t dirOrth1Idx = (dirIdx + 1) % 3; + std::size_t dirOrth2Idx = (dirIdx + 2) % 3; + + auto dirOrth1 = static_cast(dirOrth1Idx); + auto dirOrth2 = static_cast(dirOrth2Idx); + + auto boundDir = static_cast(dir); + auto boundDirOrth1 = static_cast(dirOrth1); + auto boundDirOrth2 = static_cast(dirOrth2); + + std::array bounds1Vals; + bounds1Vals.at(boundDir) = halfDir; + bounds1Vals.at(boundDirOrth1) = 100_mm; + bounds1Vals.at(boundDirOrth2) = 400_mm; + auto bounds1 = std::make_shared(bounds1Vals); + + std::array bounds2Vals; + bounds2Vals.at(boundDir) = halfDir; + bounds2Vals.at(boundDirOrth1) = 200_mm; + bounds2Vals.at(boundDirOrth2) = 600_mm; + auto bounds2 = std::make_shared(bounds2Vals); + + std::array bounds3Vals; + bounds3Vals.at(boundDir) = halfDir; + bounds3Vals.at(boundDirOrth1) = 300_mm; + bounds3Vals.at(boundDirOrth2) = 500_mm; + auto bounds3 = std::make_shared(bounds3Vals); + + Transform3 base = AngleAxis3(angle * 1_degree, Vector3::Unit(dirOrth1Idx)) * + Translation3(offset); + + Translation3 translation1(Vector3::Unit(dirIdx) * (-2 * halfDir * shift)); + Transform3 transform1 = base * translation1; + auto vol1 = std::make_shared(transform1, bounds1); + + Transform3 transform2 = base; + auto vol2 = std::make_shared(transform2, bounds2); + + Translation3 translation3(Vector3::Unit(dirIdx) * (2 * halfDir * shift)); + Transform3 transform3 = base * translation3; + auto vol3 = std::make_shared(transform3, bounds3); + + std::vector volumes = {vol1.get(), vol2.get(), vol3.get()}; + // Rotate to simulate unsorted volumes: all results should be the same! + std::rotate(volumes.begin(), volumes.begin() + rotate, volumes.end()); + + auto origVolumes = volumes; + + std::vector originalBounds; + std::transform( + volumes.begin(), volumes.end(), std::back_inserter(originalBounds), + [](const auto& vol) { + return *dynamic_cast(&vol->volumeBounds()); + }); + + if (shift < 1.0) { + BOOST_CHECK_THROW( + CuboidVolumeStack(volumes, dir, strategy, + CuboidVolumeStack::ResizeStrategy::Gap, *logger), + std::invalid_argument); + return; + } + CuboidVolumeStack stack(volumes, dir, strategy, + CuboidVolumeStack::ResizeStrategy::Gap, *logger); + + auto stackBounds = + dynamic_cast(&stack.volumeBounds()); + BOOST_REQUIRE(stackBounds != nullptr); + + BOOST_CHECK_EQUAL(stackBounds->get(boundDirOrth1), 300_mm); + BOOST_CHECK_EQUAL(stackBounds->get(boundDirOrth2), 600_mm); + BOOST_CHECK_EQUAL(stackBounds->get(boundDir), halfDir + 2 * halfDir * shift); + CHECK_CLOSE_OR_SMALL(stack.transform().matrix(), base.matrix(), 1e-10, 1e-14); + + // All volumes (including gaps) are cuboids and have the same orthogonal + // bounds + for (const auto& volume : volumes) { + const auto* cuboidBounds = + dynamic_cast(&volume->volumeBounds()); + BOOST_REQUIRE(cuboidBounds != nullptr); + BOOST_CHECK_EQUAL(cuboidBounds->get(boundDirOrth1), 300_mm); + BOOST_CHECK_EQUAL(cuboidBounds->get(boundDirOrth2), 600_mm); + } + + // Volumes are sorted in (local) stacking direction + for (std::size_t i = 0; i < volumes.size() - 1; ++i) { + const auto& a = volumes.at(i); + const auto& b = volumes.at(i + 1); + + BOOST_CHECK_LT((base.inverse() * a->center())[dirIdx], + (base.inverse() * b->center())[dirIdx]); + } + + if (shift <= 1.0) { + // No gap volumes were added + BOOST_CHECK_EQUAL(volumes.size(), 3); + + // No expansion, original volumes did not move + BOOST_CHECK_EQUAL(vol1->transform().matrix(), transform1.matrix()); + BOOST_CHECK_EQUAL(vol2->transform().matrix(), transform2.matrix()); + BOOST_CHECK_EQUAL(vol3->transform().matrix(), transform3.matrix()); + + for (const auto& [volume, bounds] : zip(origVolumes, originalBounds)) { + const auto* newBounds = + dynamic_cast(&volume->volumeBounds()); + BOOST_CHECK_EQUAL(newBounds->get(boundDir), bounds.get(boundDir)); + } + } else { + if (strategy == CuboidVolumeStack::AttachmentStrategy::Gap) { + // Gap volumes were added + BOOST_CHECK_EQUAL(volumes.size(), 5); + auto gap1 = volumes.at(1); + auto gap2 = volumes.at(3); + + BOOST_TEST_MESSAGE("Gap 1: " << gap1->transform().matrix()); + BOOST_TEST_MESSAGE("Gap 2: " << gap2->transform().matrix()); + + const auto* gapBounds1 = + dynamic_cast(&gap1->volumeBounds()); + const auto* gapBounds2 = + dynamic_cast(&gap2->volumeBounds()); + + double gapHlDir = (shift - 1.0) * halfDir; + + BOOST_CHECK(std::abs(gapBounds1->get(boundDir) - gapHlDir) < 1e-10); + BOOST_CHECK(std::abs(gapBounds2->get(boundDir) - gapHlDir) < 1e-10); + + double gap1Dir = (-2 * halfDir * shift) + halfDir + gapHlDir; + double gap2Dir = (2 * halfDir * shift) - halfDir - gapHlDir; + + Translation3 gap1Translation(Vector3::Unit(dirIdx) * gap1Dir); + Translation3 gap2Translation(Vector3::Unit(dirIdx) * gap2Dir); + + Transform3 gap1Transform = base * gap1Translation; + Transform3 gap2Transform = base * gap2Translation; + + CHECK_CLOSE_OR_SMALL(gap1->transform().matrix(), gap1Transform.matrix(), + 1e-10, 1e-14); + CHECK_CLOSE_OR_SMALL(gap2->transform().matrix(), gap2Transform.matrix(), + 1e-10, 1e-14); + + // Original volumes did not changes bounds + for (const auto& [volume, bounds] : zip(origVolumes, originalBounds)) { + const auto* newBounds = + dynamic_cast(&volume->volumeBounds()); + BOOST_CHECK_EQUAL(newBounds->get(boundDir), bounds.get(boundDir)); + } + + // No expansion, original volumes did not move + BOOST_CHECK_EQUAL(vol1->transform().matrix(), transform1.matrix()); + BOOST_CHECK_EQUAL(vol2->transform().matrix(), transform2.matrix()); + BOOST_CHECK_EQUAL(vol3->transform().matrix(), transform3.matrix()); + } else if (strategy == CuboidVolumeStack::AttachmentStrategy::First) { + // No gap volumes were added + BOOST_CHECK_EQUAL(volumes.size(), 3); + + double wGap = (shift - 1.0) * halfDir * 2; + + // Volume 1 got bigger and shifted right + auto newBounds1 = + dynamic_cast(&vol1->volumeBounds()); + BOOST_CHECK_EQUAL(newBounds1->get(boundDir), halfDir + wGap / 2.0); + double pDir1 = -2 * halfDir * shift + wGap / 2.0; + Translation3 expectedTranslation1(Vector3::Unit(dirIdx) * pDir1); + Transform3 expectedTransform1 = base * expectedTranslation1; + CHECK_CLOSE_OR_SMALL(vol1->transform().matrix(), + expectedTransform1.matrix(), 1e-10, 1e-14); + + // Volume 2 got bigger and shifted left + auto newBounds2 = + dynamic_cast(&vol2->volumeBounds()); + BOOST_CHECK_EQUAL(newBounds2->get(boundDir), halfDir + wGap / 2.0); + double pDir2 = wGap / 2.0; + Translation3 expectedTranslation2(Vector3::Unit(dirIdx) * pDir2); + Transform3 expectedTransform2 = base * expectedTranslation2; + CHECK_CLOSE_OR_SMALL(vol2->transform().matrix(), + expectedTransform2.matrix(), 1e-10, 1e-14); + + // Volume 3 stayed the same + auto newBounds3 = + dynamic_cast(&vol3->volumeBounds()); + BOOST_CHECK_EQUAL(newBounds3->get(boundDir), halfDir); + double pDir3 = 2 * halfDir * shift; + Translation3 expectedTranslation3(Vector3::Unit(dirIdx) * pDir3); + Transform3 expectedTransform3 = base * expectedTranslation3; + CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(), + expectedTransform3.matrix(), 1e-10, 1e-14); + } else if (strategy == CuboidVolumeStack::AttachmentStrategy::Second) { + // No gap volumes were added + BOOST_CHECK_EQUAL(volumes.size(), 3); + + double wGap = (shift - 1.0) * halfDir * 2; + + // Volume 1 stayed the same + auto newBounds1 = + dynamic_cast(&vol1->volumeBounds()); + BOOST_CHECK_EQUAL(newBounds1->get(boundDir), halfDir); + double pDir1 = -2 * halfDir * shift; + Translation3 expectedTranslation1(Vector3::Unit(dirIdx) * pDir1); + Transform3 expectedTransform1 = base * expectedTranslation1; + CHECK_CLOSE_OR_SMALL(vol1->transform().matrix(), + expectedTransform1.matrix(), 1e-10, 1e-14); + + // Volume 2 got bigger and shifted left + auto newBounds2 = + dynamic_cast(&vol2->volumeBounds()); + BOOST_CHECK_EQUAL(newBounds2->get(boundDir), halfDir + wGap / 2.0); + double pDir2 = -wGap / 2.0; + Translation3 expectedTranslation2(Vector3::Unit(dirIdx) * pDir2); + Transform3 expectedTransform2 = base * expectedTranslation2; + CHECK_CLOSE_OR_SMALL(vol2->transform().matrix(), + expectedTransform2.matrix(), 1e-10, 1e-14); + + // Volume 3 got bigger and shifted left + auto newBounds3 = + dynamic_cast(&vol3->volumeBounds()); + BOOST_CHECK_EQUAL(newBounds3->get(boundDir), halfDir + wGap / 2.0); + double pDir3 = 2 * halfDir * shift - wGap / 2.0; + Translation3 expectedTranslation3(Vector3::Unit(dirIdx) * pDir3); + Transform3 expectedTransform3 = base * expectedTranslation3; + CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(), + expectedTransform3.matrix(), 1e-10, 1e-14); + } else if (strategy == CuboidVolumeStack::AttachmentStrategy::Midpoint) { + // No gap volumes were added + BOOST_CHECK_EQUAL(volumes.size(), 3); + + double wGap = (shift - 1.0) * halfDir * 2; + + // Volume 1 got bigger and shifted right + auto newBounds1 = + dynamic_cast(&vol1->volumeBounds()); + BOOST_CHECK_EQUAL(newBounds1->get(boundDir), halfDir + wGap / 4.0); + double pDir1 = -2 * halfDir * shift + wGap / 4.0; + Translation3 expectedTranslation1(Vector3::Unit(dirIdx) * pDir1); + Transform3 expectedTransform1 = base * expectedTranslation1; + CHECK_CLOSE_OR_SMALL(vol1->transform().matrix(), + expectedTransform1.matrix(), 1e-10, 1e-14); + + // Volume 2 got bigger but didn't move + auto newBounds2 = + dynamic_cast(&vol2->volumeBounds()); + BOOST_CHECK_EQUAL(newBounds2->get(boundDir), halfDir + wGap / 2.0); + CHECK_CLOSE_OR_SMALL(vol2->transform().matrix(), base.matrix(), 1e-10, + 1e-14); + + // Volume 3 got bigger and shifted left + auto newBounds3 = + dynamic_cast(&vol3->volumeBounds()); + BOOST_CHECK_EQUAL(newBounds3->get(boundDir), halfDir + wGap / 4.0); + double pDir3 = 2 * halfDir * shift - wGap / 4.0; + Translation3 expectedTranslation3(Vector3::Unit(dirIdx) * pDir3); + Transform3 expectedTransform3 = base * expectedTranslation3; + CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(), + expectedTransform3.matrix(), 1e-10, 1e-14); + } + } +} + +BOOST_DATA_TEST_CASE(BaselineGlobal, + (boost::unit_test::data::xrange(-135, 180, 45) * + boost::unit_test::data::xrange(0, 2, 1) * + boost::unit_test::data::make(1.0, 1.2) * + boost::unit_test::data::make(Vector3{0_mm, 0_mm, 0_mm}, + Vector3{20_mm, 0_mm, 0_mm}, + Vector3{0_mm, 20_mm, 0_mm}, + Vector3{20_mm, 20_mm, 0_mm}, + Vector3{0_mm, 0_mm, 20_mm}) * + boost::unit_test::data::make(strategies)), + angle, rotate, shift, offset, strategy) { + double halfDir = 400_mm; + + auto bounds1 = std::make_shared(100_mm, 400_mm, halfDir); + auto bounds2 = std::make_shared(200_mm, 600_mm, halfDir); + auto bounds3 = std::make_shared(300_mm, 500_mm, halfDir); + + AngleAxis3 baseRotation = AngleAxis3(angle, Vector3::UnitX()); + Transform3 base = baseRotation * Translation3(offset); + + Vector3 orientation = baseRotation * Vector3::UnitZ(); + + Translation3 translation1(Vector3::UnitZ() * (-2 * halfDir * shift)); + Transform3 transform1 = base * translation1; + auto vol1Orientation = std::make_shared(transform1, bounds1); + auto vol1AxisDirection = std::make_shared(transform1, bounds1); + + Transform3 transform2 = base; + auto vol2Orientation = std::make_shared(transform2, bounds2); + auto vol2AxisDirection = std::make_shared(transform2, bounds2); + + Translation3 translation3(Vector3::UnitZ() * (2 * halfDir * shift)); + Transform3 transform3 = base * translation3; + auto vol3Orientation = std::make_shared(transform3, bounds3); + auto vol3AxisDirection = std::make_shared(transform3, bounds3); + + std::vector volumesOrientation = { + vol1Orientation.get(), vol2Orientation.get(), vol3Orientation.get()}; + std::vector volumesAxisDirection = {vol1AxisDirection.get(), + vol2AxisDirection.get(), + vol3AxisDirection.get()}; + + // Rotate to simulate unsorted volumes: all results should be the same! + std::rotate(volumesOrientation.begin(), volumesOrientation.begin() + rotate, + volumesOrientation.end()); + std::rotate(volumesAxisDirection.begin(), + volumesAxisDirection.begin() + rotate, + volumesAxisDirection.end()); + + CuboidVolumeStack stackOrientation(volumesOrientation, orientation, strategy, + CuboidVolumeStack::ResizeStrategy::Gap, + *logger); + CuboidVolumeStack stackAxisDirection( + volumesAxisDirection, AxisDirection::AxisZ, strategy, + CuboidVolumeStack::ResizeStrategy::Gap, *logger); + + auto stackBoundsOrientation = + dynamic_cast(&stackOrientation.volumeBounds()); + auto stackBoundsAxisDirection = dynamic_cast( + &stackAxisDirection.volumeBounds()); + + // Global vector direction and local axis direction should + // produce the same results + BOOST_CHECK_NE(stackBoundsOrientation, nullptr); + BOOST_CHECK_NE(stackBoundsAxisDirection, nullptr); + BOOST_CHECK_EQUAL(*stackBoundsOrientation, *stackBoundsAxisDirection); + CHECK_CLOSE_OR_SMALL(stackOrientation.transform().matrix(), + stackAxisDirection.transform().matrix(), 1e-10, 1e-12); +} + +BOOST_DATA_TEST_CASE(Asymmetric, + boost::unit_test::data::make(Acts::AxisDirection::AxisX, + Acts::AxisDirection::AxisY, + Acts::AxisDirection::AxisZ), + dir) { + double halfDir1 = 200_mm; + double pDir1 = -1100_mm; + double halfDir2 = 600_mm; + double pDir2 = -200_mm; + double halfDir3 = 400_mm; + double pDir3 = 850_mm; + + std::size_t dirIdx = static_cast(dir); + std::size_t dirOrth1Idx = (dirIdx + 1) % 3; + std::size_t dirOrth2Idx = (dirIdx + 2) % 3; + + auto dirOrth1 = static_cast(dirOrth1Idx); + auto dirOrth2 = static_cast(dirOrth2Idx); + + auto boundDir = static_cast(dir); + auto boundDirOrth1 = static_cast(dirOrth1); + auto boundDirOrth2 = static_cast(dirOrth2); + + std::array bounds1Vals; + bounds1Vals[dirIdx] = halfDir1; + bounds1Vals[dirOrth1Idx] = 100_mm; + bounds1Vals[dirOrth2Idx] = 400_mm; + auto bounds1 = std::make_shared(bounds1Vals); + + std::array bounds2Vals; + bounds2Vals[dirIdx] = halfDir2; + bounds2Vals[dirOrth1Idx] = 200_mm; + bounds2Vals[dirOrth2Idx] = 600_mm; + auto bounds2 = std::make_shared(bounds2Vals); + + std::array bounds3Vals; + bounds3Vals[dirIdx] = halfDir3; + bounds3Vals[dirOrth1Idx] = 300_mm; + bounds3Vals[dirOrth2Idx] = 500_mm; + auto bounds3 = std::make_shared(bounds3Vals); + + Translation3 translation1(Vector3::Unit(dirIdx) * pDir1); + Transform3 transform1(translation1); + auto vol1 = std::make_shared(transform1, bounds1); + + Translation3 translation2(Vector3::Unit(dirIdx) * pDir2); + Transform3 transform2(translation2); + auto vol2 = std::make_shared(transform2, bounds2); + + Translation3 translation3(Vector3::Unit(dirIdx) * pDir3); + Transform3 transform3(translation3); + auto vol3 = std::make_shared(transform3, bounds3); + + std::vector volumes = {vol2.get(), vol1.get(), vol3.get()}; + + CuboidVolumeStack stack(volumes, dir, + CuboidVolumeStack::AttachmentStrategy::Gap, + CuboidVolumeStack::ResizeStrategy::Gap, *logger); + BOOST_CHECK_EQUAL(volumes.size(), 5); + + auto stackBounds = + dynamic_cast(&stack.volumeBounds()); + BOOST_REQUIRE(stackBounds != nullptr); + + BOOST_CHECK_EQUAL(stackBounds->get(boundDirOrth1), 300_mm); + BOOST_CHECK_EQUAL(stackBounds->get(boundDirOrth2), 600_mm); + BOOST_CHECK_EQUAL(stackBounds->get(boundDir), + (std::abs(pDir1 - halfDir1) + pDir3 + halfDir3) / 2.0); + + double midDir = (pDir1 - halfDir1 + pDir3 + halfDir3) / 2.0; + Translation3 expectedTranslation(Vector3::Unit(dirIdx) * midDir); + Transform3 expectedTransform = Transform3::Identity() * expectedTranslation; + CHECK_CLOSE_OR_SMALL(stack.transform().matrix(), expectedTransform.matrix(), + 1e-10, 1e-14); +} + +BOOST_DATA_TEST_CASE(UpdateStack, + (boost::unit_test::data::xrange(-135, 180, 45) * + boost::unit_test::data::make(Vector3{0_mm, 0_mm, 0_mm}, + Vector3{20_mm, 0_mm, 0_mm}, + Vector3{0_mm, 20_mm, 0_mm}, + Vector3{20_mm, 20_mm, 0_mm}, + Vector3{0_mm, 0_mm, 20_mm}) * + boost::unit_test::data::make(-100_mm, 0_mm, 100_mm) * + boost::unit_test::data::make(resizeStrategies) * + boost::unit_test::data::make(Acts::AxisDirection::AxisX, + Acts::AxisDirection::AxisY, + Acts::AxisDirection::AxisZ)), + angle, offset, zshift, strategy, dir) { + double halfDir = 400_mm; + + std::size_t dirIdx = static_cast(dir); + std::size_t dirOrth1Idx = (dirIdx + 1) % 3; + std::size_t dirOrth2Idx = (dirIdx + 2) % 3; + + auto dirOrth1 = static_cast(dirOrth1Idx); + auto dirOrth2 = static_cast(dirOrth2Idx); + + auto boundDir = static_cast(dir); + auto boundDirOrth1 = static_cast(dirOrth1); + auto boundDirOrth2 = static_cast(dirOrth2); + + std::array bounds1Vals; + bounds1Vals[dirIdx] = halfDir; + bounds1Vals[dirOrth1Idx] = 100_mm; + bounds1Vals[dirOrth2Idx] = 600_mm; + auto bounds1 = std::make_shared(bounds1Vals); + + std::array bounds2Vals; + bounds2Vals[dirIdx] = halfDir; + bounds2Vals[dirOrth1Idx] = 100_mm; + bounds2Vals[dirOrth2Idx] = 600_mm; + auto bounds2 = std::make_shared(bounds2Vals); + + std::array bounds3Vals; + bounds3Vals[dirIdx] = halfDir; + bounds3Vals[dirOrth1Idx] = 100_mm; + bounds3Vals[dirOrth2Idx] = 600_mm; + auto bounds3 = std::make_shared(bounds3Vals); + + Vector3 shift = Vector3::Unit(dirIdx) * zshift; + Transform3 base = AngleAxis3(angle * 1_degree, Vector3::Unit(dirOrth1Idx)) * + Translation3(offset + shift); + + Translation3 translation1(Vector3::Unit(dirIdx) * -2 * halfDir); + Transform3 transform1 = base * translation1; + auto vol1 = std::make_shared(transform1, bounds1); + + Transform3 transform2 = base; + auto vol2 = std::make_shared(transform2, bounds2); + + Translation3 translation3(Vector3::Unit(dirIdx) * 2 * halfDir); + Transform3 transform3 = base * translation3; + auto vol3 = std::make_shared(transform3, bounds3); + + std::vector volumes = {vol1.get(), vol2.get(), vol3.get()}; + std::vector originalVolumes = volumes; + + std::vector originalTransforms = {transform1, transform2, + transform3}; + + CuboidVolumeStack stack( + volumes, dir, + CuboidVolumeStack::AttachmentStrategy::Gap, // should not make a + // difference + strategy, *logger); + + const auto* originalBounds = + dynamic_cast(&stack.volumeBounds()); + + auto assertOriginalBounds = [&]() { + const auto* bounds = + dynamic_cast(&stack.volumeBounds()); + BOOST_REQUIRE(bounds != nullptr); + BOOST_CHECK_EQUAL(bounds, originalBounds); + BOOST_CHECK_EQUAL(bounds->get(boundDirOrth1), 100_mm); + BOOST_CHECK_EQUAL(bounds->get(boundDirOrth2), 600_mm); + BOOST_CHECK_EQUAL(bounds->get(boundDir), 3 * halfDir); + }; + + assertOriginalBounds(); + + { + // Assign a copy of the identical bounds gives identical bounds + auto bounds = std::make_shared( + dynamic_cast(stack.volumeBounds())); + stack.update(bounds, std::nullopt, *logger); + assertOriginalBounds(); + } + + { + // Cannot decrease half length + auto bounds = std::make_shared( + dynamic_cast(stack.volumeBounds())); + bounds->set(boundDirOrth1, 20_mm); + BOOST_CHECK_THROW(stack.update(bounds, std::nullopt, *logger), + std::invalid_argument); + assertOriginalBounds(); + } + + { + // Cannot decrease half length + auto bounds = std::make_shared( + dynamic_cast(stack.volumeBounds())); + bounds->set(boundDirOrth2, 200_mm); + BOOST_CHECK_THROW(stack.update(bounds, std::nullopt, *logger), + std::invalid_argument); + assertOriginalBounds(); + } + + { + // Cannot decrease half length + auto bounds = std::make_shared( + dynamic_cast(stack.volumeBounds())); + bounds->set(boundDir, 2 * halfDir); + BOOST_CHECK_THROW(stack.update(bounds, std::nullopt, *logger), + std::invalid_argument); + assertOriginalBounds(); + } + + { + // Increase half length + auto bounds = std::make_shared( + dynamic_cast(stack.volumeBounds())); + bounds->set(boundDirOrth1, 700_mm); + stack.update(bounds, std::nullopt, *logger); + const auto* updatedBounds = + dynamic_cast(&stack.volumeBounds()); + BOOST_REQUIRE(updatedBounds != nullptr); + BOOST_CHECK_EQUAL(updatedBounds->get(boundDirOrth1), 700_mm); + BOOST_CHECK_EQUAL(updatedBounds->get(boundDirOrth2), 600_mm); + BOOST_CHECK_EQUAL(updatedBounds->get(boundDir), 3 * halfDir); + + // No gap volumes were added + BOOST_CHECK_EQUAL(volumes.size(), 3); + + // All volumes increase half x to accommodate + for (const auto& [volume, origTransform] : + zip(volumes, originalTransforms)) { + const auto* newBounds = + dynamic_cast(&volume->volumeBounds()); + BOOST_CHECK_EQUAL(newBounds->get(boundDirOrth1), 700_mm); + BOOST_CHECK_EQUAL(newBounds->get(boundDirOrth2), 600_mm); + BOOST_CHECK_EQUAL(newBounds->get(boundDir), halfDir); + + // Position stayed the same + BOOST_CHECK_EQUAL(volume->transform().matrix(), origTransform.matrix()); + } + } + { + // Increase half length + auto bounds = std::make_shared( + dynamic_cast(stack.volumeBounds())); + bounds->set(boundDirOrth2, 700_mm); + stack.update(bounds, std::nullopt, *logger); + const auto* updatedBounds = + dynamic_cast(&stack.volumeBounds()); + BOOST_REQUIRE(updatedBounds != nullptr); + BOOST_CHECK_EQUAL(updatedBounds->get(boundDirOrth1), 700_mm); + BOOST_CHECK_EQUAL(updatedBounds->get(boundDirOrth2), 700_mm); + BOOST_CHECK_EQUAL(updatedBounds->get(boundDir), 3 * halfDir); + + // No gap volumes were added + BOOST_CHECK_EQUAL(volumes.size(), 3); + + // All volumes increase half y to accommodate + for (const auto& [volume, origTransform] : + zip(volumes, originalTransforms)) { + const auto* newBounds = + dynamic_cast(&volume->volumeBounds()); + BOOST_CHECK_EQUAL(newBounds->get(boundDirOrth1), 700_mm); + BOOST_CHECK_EQUAL(newBounds->get(boundDirOrth2), 700_mm); + BOOST_CHECK_EQUAL(newBounds->get(boundDir), halfDir); + + // Position stayed the same + BOOST_CHECK_EQUAL(volume->transform().matrix(), origTransform.matrix()); + } + } + + { + // Increase half length + auto bounds = std::make_shared( + dynamic_cast(stack.volumeBounds())); + bounds->set(boundDir, 4 * halfDir); + stack.update(bounds, std::nullopt, *logger); + const auto* updatedBounds = + dynamic_cast(&stack.volumeBounds()); + BOOST_REQUIRE(updatedBounds != nullptr); + BOOST_CHECK_EQUAL(updatedBounds->get(boundDir), 4 * halfDir); + BOOST_CHECK_EQUAL(updatedBounds->get(boundDirOrth1), 700_mm); + BOOST_CHECK_EQUAL(updatedBounds->get(boundDirOrth2), 700_mm); + + if (strategy == CuboidVolumeStack::ResizeStrategy::Expand) { + // No gap volumes were added + BOOST_CHECK_EQUAL(volumes.size(), 3); + + // Volume 1 got bigger and shifted left + auto newBounds1 = + dynamic_cast(&vol1->volumeBounds()); + BOOST_CHECK_EQUAL(newBounds1->get(boundDir), halfDir + halfDir / 2.0); + auto expectedTranslation1 = + Translation3(Vector3::Unit(dirIdx) * (-2 * halfDir - halfDir / 2.0)); + Transform3 expectedTransform1 = base * expectedTranslation1; + BOOST_CHECK_EQUAL(vol1->transform().matrix(), + expectedTransform1.matrix()); + + // Volume 2 stayed the same + auto newBounds2 = + dynamic_cast(&vol2->volumeBounds()); + BOOST_CHECK_EQUAL(newBounds2->get(boundDir), halfDir); + BOOST_CHECK_EQUAL(vol2->transform().matrix(), transform2.matrix()); + + // Volume 3 got bigger and shifted right + auto newBounds3 = + dynamic_cast(&vol3->volumeBounds()); + BOOST_CHECK_EQUAL(newBounds3->get(boundDir), halfDir + halfDir / 2.0); + auto expectedTranslation3 = + Translation3(Vector3::Unit(dirIdx) * (2 * halfDir + halfDir / 2.0)); + Transform3 expectedTransform3 = base * expectedTranslation3; + BOOST_CHECK_EQUAL(vol3->transform().matrix(), + expectedTransform3.matrix()); + } else if (strategy == CuboidVolumeStack::ResizeStrategy::Gap) { + // Gap volumes were added + BOOST_CHECK_EQUAL(volumes.size(), 5); + + for (const auto& [volume, origTransform] : + zip(originalVolumes, originalTransforms)) { + const auto* newBounds = + dynamic_cast(&volume->volumeBounds()); + BOOST_CHECK_EQUAL(newBounds->get(boundDirOrth1), 700_mm); + BOOST_CHECK_EQUAL(newBounds->get(boundDirOrth2), 700_mm); + BOOST_CHECK_EQUAL(newBounds->get(boundDir), halfDir); + // Position stayed the same + BOOST_CHECK_EQUAL(volume->transform().matrix(), origTransform.matrix()); + } + + auto gap1 = volumes.front(); + auto gap2 = volumes.back(); + + const auto* gapBounds1 = + dynamic_cast(&gap1->volumeBounds()); + const auto* gapBounds2 = + dynamic_cast(&gap2->volumeBounds()); + + BOOST_CHECK_EQUAL(gapBounds1->get(boundDir), halfDir / 2.0); + BOOST_CHECK_EQUAL(gapBounds2->get(boundDir), halfDir / 2.0); + auto gap1Translation = + Translation3(Vector3::Unit(dirIdx) * (-3 * halfDir - halfDir / 2.0)); + Transform3 gap1Transform = base * gap1Translation; + + auto gap2Translation = + Translation3(Vector3::Unit(dirIdx) * (3 * halfDir + halfDir / 2.0)); + Transform3 gap2Transform = base * gap2Translation; + CHECK_CLOSE_OR_SMALL(gap1->transform().matrix(), gap1Transform.matrix(), + 1e-10, 1e-14); + CHECK_CLOSE_OR_SMALL(gap2->transform().matrix(), gap2Transform.matrix(), + 1e-10, 1e-14); + } + } +} + +BOOST_DATA_TEST_CASE( + UpdateStackOneSided, + ((boost::unit_test::data::make(-1.0, 1.0) ^ + boost::unit_test::data::make(CuboidVolumeStack::ResizeStrategy::Gap, + CuboidVolumeStack::ResizeStrategy::Expand)) * + boost::unit_test::data::make(Acts::AxisDirection::AxisX, + Acts::AxisDirection::AxisY, + Acts::AxisDirection::AxisZ)), + f, strategy, dir) { + std::size_t dirIdx = static_cast(dir); + std::size_t dirOrth1Idx = (dirIdx + 1) % 3; + std::size_t dirOrth2Idx = (dirIdx + 2) % 3; + + auto dirOrth1 = static_cast(dirOrth1Idx); + auto dirOrth2 = static_cast(dirOrth2Idx); + + auto boundDir = static_cast(dir); + auto boundDirOrth1 = static_cast(dirOrth1); + auto boundDirOrth2 = static_cast(dirOrth2); + + std::array bounds1Vals; + bounds1Vals[dirIdx] = 400_mm; + bounds1Vals[dirOrth1Idx] = 100_mm; + bounds1Vals[dirOrth2Idx] = 300_mm; + auto bounds1 = std::make_shared(bounds1Vals); + + std::array bounds2Vals; + bounds2Vals[dirIdx] = 400_mm; + bounds2Vals[dirOrth1Idx] = 100_mm; + bounds2Vals[dirOrth2Idx] = 300_mm; + auto bounds2 = std::make_shared(bounds2Vals); + + auto trf = Transform3::Identity(); + + auto translation1 = Translation3(Vector3::Unit(dirIdx) * -500_mm); + auto trf1 = trf * translation1; + auto vol1 = std::make_shared(trf1, bounds1); + + auto translation2 = Translation3(Vector3::Unit(dirIdx) * 500_mm); + auto trf2 = trf * translation2; + auto vol2 = std::make_shared(trf2, bounds2); + + std::vector volumes = {vol1.get(), vol2.get()}; + + CuboidVolumeStack stack{volumes, dir, + CuboidVolumeStack::AttachmentStrategy::Gap, strategy, + *logger}; + const auto* originalBounds = + dynamic_cast(&stack.volumeBounds()); + + // Increase half length by 50mm + auto newBounds = std::make_shared( + dynamic_cast(stack.volumeBounds())); + newBounds->set(boundDir, 950_mm); + // Shift to +stacking direction by 50mm + auto delta = Translation3(Vector3::Unit(dirIdx) * f * 50_mm); + trf *= delta; + // -> left edge should stay at -400mm, right edge should be at 500mm or the + // other direction + auto checkUnchanged = [&]() { + const auto* bounds = + dynamic_cast(&stack.volumeBounds()); + BOOST_REQUIRE(bounds != nullptr); + BOOST_CHECK_EQUAL(*bounds, *originalBounds); + }; + + // Invalid: shift too far in merging direction + BOOST_CHECK_THROW( + auto errDelta = Translation3(Vector3::Unit(dirIdx) * f * 20_mm); + stack.update(newBounds, trf * errDelta, *logger), std::invalid_argument); + checkUnchanged(); + + // Invalid: shift in orthogonal direction + BOOST_CHECK_THROW( + auto errDelta = Translation3(Vector3::Unit(dirOrth1Idx) * 10_mm); + stack.update(newBounds, trf * errDelta, *logger), std::invalid_argument); + checkUnchanged(); + + // Invalid: shift in orthogonal direction + BOOST_CHECK_THROW( + auto errDelta = Translation3(Vector3::Unit(dirOrth2Idx) * 10_mm); + stack.update(newBounds, trf * errDelta, *logger), std::invalid_argument); + checkUnchanged(); + + // Invalid: rotation + BOOST_CHECK_THROW( + stack.update(newBounds, + trf * AngleAxis3{10_degree, Vector3::Unit(dirOrth1Idx)}, + *logger), + std::invalid_argument); + checkUnchanged(); + + stack.update(newBounds, trf, *logger); + + BOOST_CHECK_EQUAL(stack.transform().matrix(), trf.matrix()); + const auto* bounds = + dynamic_cast(&stack.volumeBounds()); + BOOST_REQUIRE(bounds != nullptr); + BOOST_CHECK_EQUAL(bounds->get(boundDir), 950_mm); + + // All volumes including gaps should have same size in orthogonal plane + for (const auto* vol : volumes) { + const auto* volBounds = + dynamic_cast(&vol->volumeBounds()); + BOOST_REQUIRE(volBounds != nullptr); + BOOST_CHECK_EQUAL(volBounds->get(boundDirOrth1), 100_mm); + BOOST_CHECK_EQUAL(volBounds->get(boundDirOrth2), 300_mm); + } + + if (strategy == CuboidVolumeStack::ResizeStrategy::Expand) { + // No gaps were added, there was one gap initially + BOOST_CHECK_EQUAL(volumes.size(), 3); + const Volume* vol = nullptr; + if (f < 0.0) { + // first volume should have gotten bigger + vol = volumes.front(); + } else { + // last volume should have gotten bigger + vol = volumes.back(); + } + + const auto* volBounds = + dynamic_cast(&vol->volumeBounds()); + BOOST_REQUIRE(volBounds != nullptr); + BOOST_CHECK_EQUAL(volBounds->get(boundDir), 450_mm); + BOOST_CHECK_EQUAL(vol->center()[dirIdx], f * 550_mm); + } else if (strategy == CuboidVolumeStack::ResizeStrategy::Gap) { + // One gap volume was added + BOOST_CHECK_EQUAL(volumes.size(), 4); + + const Volume* gap = nullptr; + if (f < 0.0) { + gap = volumes.front(); + } else { + gap = volumes.back(); + } + const auto* gapBounds = + dynamic_cast(&gap->volumeBounds()); + BOOST_REQUIRE(gapBounds != nullptr); + + BOOST_CHECK_EQUAL(gapBounds->get(boundDir), 50_mm); + BOOST_CHECK_EQUAL(gap->center()[dirIdx], f * 950_mm); + } +} + +// original size +// <---------------> +// +---------------+ +// | | +// | | +// | Volume 1 | +// | | +// | | +// +---------------+ +// first resize +// <--------------------------> +// +---------------+----------+ +// | | | +// | | | +// | Volume 1 | Gap | +// | | | Gap is +// | | | reused!--+ +// +---------------+----------+ | +// second resize | +// <-----------------------------------> | +// +---------------+-------------------+ | +// | | | | +// | | | | +// | Volume 1 | Gap |<-----+ +// | | | +// | | | +// +---------------+-------------------+ +// +BOOST_DATA_TEST_CASE(ResizeGapMultiple, + boost::unit_test::data::make(Acts::AxisDirection::AxisX, + Acts::AxisDirection::AxisY, + Acts::AxisDirection::AxisZ), + dir) { + std::size_t dirIdx = static_cast(dir); + std::size_t dirOrth1Idx = (dirIdx + 1) % 3; + std::size_t dirOrth2Idx = (dirIdx + 2) % 3; + + auto dirOrth1 = static_cast(dirOrth1Idx); + auto dirOrth2 = static_cast(dirOrth2Idx); + + auto boundDir = static_cast(dir); + auto boundDirOrth1 = static_cast(dirOrth1); + auto boundDirOrth2 = static_cast(dirOrth2); + + std::array boundsVals; + boundsVals[dirIdx] = 100; + boundsVals[dirOrth1Idx] = 70; + boundsVals[dirOrth2Idx] = 100; + auto bounds = std::make_shared(boundsVals); + + Transform3 trf = Transform3::Identity(); + Volume vol{trf, bounds}; + + BOOST_TEST_CONTEXT("Positive") { + std::vector volumes = {&vol}; + CuboidVolumeStack stack(volumes, dir, + CuboidVolumeStack::AttachmentStrategy::Gap, + CuboidVolumeStack::ResizeStrategy::Gap, *logger); + + BOOST_CHECK_EQUAL(volumes.size(), 1); + BOOST_CHECK(stack.gaps().empty()); + + std::array newBounds1Vals; + newBounds1Vals[dirIdx] = 200; + newBounds1Vals[dirOrth1Idx] = 70; + newBounds1Vals[dirOrth2Idx] = 100; + auto newBounds1 = std::make_shared(newBounds1Vals); + newBounds1->set( + {{boundDir, 200}, {boundDirOrth1, 70}, {boundDirOrth2, 100}}); + stack.update(newBounds1, trf * Translation3{Vector3::Unit(dirIdx) * 100}, + *logger); + BOOST_CHECK_EQUAL(volumes.size(), 2); + BOOST_CHECK_EQUAL(stack.gaps().size(), 1); + + BOOST_CHECK_EQUAL(stack.gaps().front()->center()[dirIdx], 200.0); + const auto* updatedBounds = dynamic_cast( + &stack.gaps().front()->volumeBounds()); + BOOST_REQUIRE_NE(updatedBounds, nullptr); + BOOST_CHECK_EQUAL(updatedBounds->get(boundDir), 100.0); + + std::array newBounds2Vals; + newBounds2Vals[dirIdx] = 300; + newBounds2Vals[dirOrth1Idx] = 70; + newBounds2Vals[dirOrth2Idx] = 100; + auto newBounds2 = std::make_shared(newBounds2Vals); + newBounds2->set( + {{boundDir, 300}, {boundDirOrth1, 70}, {boundDirOrth2, 100}}); + stack.update(newBounds2, trf * Translation3{Vector3::Unit(dirIdx) * 200}, + *logger); + + BOOST_CHECK_EQUAL(volumes.size(), 2); + // No additional gap volume was added! + BOOST_CHECK_EQUAL(stack.gaps().size(), 1); + + BOOST_CHECK_EQUAL(stack.gaps().front()->center()[dirIdx], 300.0); + updatedBounds = dynamic_cast( + &stack.gaps().front()->volumeBounds()); + BOOST_REQUIRE_NE(updatedBounds, nullptr); + BOOST_CHECK_EQUAL(updatedBounds->get(boundDir), 200.0); + } + + BOOST_TEST_CONTEXT("Negative") { + std::vector volumes = {&vol}; + CuboidVolumeStack stack(volumes, dir, + CuboidVolumeStack::AttachmentStrategy::Gap, + CuboidVolumeStack::ResizeStrategy::Gap, *logger); + + BOOST_CHECK_EQUAL(volumes.size(), 1); + BOOST_CHECK(stack.gaps().empty()); + + std::array newBounds1Vals; + newBounds1Vals[dirIdx] = 200; + newBounds1Vals[dirOrth1Idx] = 70; + newBounds1Vals[dirOrth2Idx] = 100; + auto newBounds1 = std::make_shared(newBounds1Vals); + newBounds1->set( + {{boundDir, 200}, {boundDirOrth1, 70}, {boundDirOrth2, 100}}); + stack.update(newBounds1, trf * Translation3{Vector3::Unit(dirIdx) * -100}, + *logger); + BOOST_CHECK_EQUAL(volumes.size(), 2); + BOOST_CHECK_EQUAL(stack.gaps().size(), 1); + + BOOST_CHECK_EQUAL(stack.gaps().front()->center()[dirIdx], -200.0); + const auto* updatedBounds = dynamic_cast( + &stack.gaps().front()->volumeBounds()); + BOOST_REQUIRE_NE(updatedBounds, nullptr); + BOOST_CHECK_EQUAL(updatedBounds->get(boundDir), 100.0); + + std::array newBounds2Vals; + newBounds2Vals[dirIdx] = 300; + newBounds2Vals[dirOrth1Idx] = 70; + newBounds2Vals[dirOrth2Idx] = 100; + auto newBounds2 = std::make_shared(newBounds2Vals); + newBounds2->set( + {{boundDir, 300}, {boundDirOrth1, 70}, {boundDirOrth2, 100}}); + stack.update(newBounds2, trf * Translation3{Vector3::Unit(dirIdx) * -200}, + *logger); + + BOOST_CHECK_EQUAL(volumes.size(), 2); + // No additional gap volume was added! + BOOST_CHECK_EQUAL(stack.gaps().size(), 1); + + BOOST_CHECK_EQUAL(stack.gaps().front()->center()[dirIdx], -300.0); + updatedBounds = dynamic_cast( + &stack.gaps().front()->volumeBounds()); + BOOST_REQUIRE_NE(updatedBounds, nullptr); + BOOST_CHECK_EQUAL(updatedBounds->get(boundDir), 200.0); + } +} + +BOOST_DATA_TEST_CASE(InvalidDirection, boost::unit_test::data::make(strategies), + strategy) { + std::vector volumes; + auto vol1 = std::make_shared( + Transform3::Identity(), + std::make_shared(100_mm, 400_mm, 400_mm)); + volumes.push_back(vol1.get()); + + // Single volume invalid direction still gives an error + BOOST_CHECK_THROW(CuboidVolumeStack(volumes, AxisDirection::AxisR, strategy), + std::invalid_argument); + + auto vol2 = std::make_shared( + Transform3::Identity(), + std::make_shared(100_mm, 400_mm, 400_mm)); + volumes.push_back(vol2.get()); + + BOOST_CHECK_THROW(CuboidVolumeStack(volumes, AxisDirection::AxisR, strategy), + std::invalid_argument); +} + +BOOST_DATA_TEST_CASE(InvalidInput, + (boost::unit_test::data::make(strategies) * + boost::unit_test::data::make(Acts::AxisDirection::AxisX, + Acts::AxisDirection::AxisY, + Acts::AxisDirection::AxisZ)), + strategy, direction) { + BOOST_TEST_CONTEXT("Empty Volume") { + std::vector volumes; + BOOST_CHECK_THROW(CuboidVolumeStack(volumes, direction, strategy), + std::invalid_argument); + } + + BOOST_TEST_CONTEXT("Volumes rotated relative to each other") { + // At this time, all rotations are considered invalid, even around + // orientation + for (const Vector3 axis : {Vector3::UnitX(), Vector3::UnitY()}) { + std::vector volumes; + auto vol1 = std::make_shared( + Transform3{Translation3{Vector3{0_mm, 0_mm, -500_mm}}}, + std::make_shared(100_mm, 400_mm, 400_mm)); + volumes.push_back(vol1.get()); + + BOOST_TEST_MESSAGE("Axis: " << axis); + auto vol2 = std::make_shared( + Transform3{Translation3{Vector3{0_mm, 0_mm, 500_mm}} * + AngleAxis3(1_degree, axis)}, + std::make_shared(100_mm, 400_mm, 400_mm)); + volumes.push_back(vol2.get()); + + BOOST_CHECK_THROW( + CuboidVolumeStack(volumes, direction, strategy, + CuboidVolumeStack::ResizeStrategy::Gap, *logger), + std::invalid_argument); + } + } + + BOOST_TEST_CONTEXT( + "Volumes shifted in the orthogonal plane relative to each other") { + for (const Vector3& shift : + {Vector3{5_mm, 0, 0}, Vector3{0, -5_mm, 0}, Vector3{2_mm, -2_mm, 0}}) { + std::vector volumes; + auto vol1 = std::make_shared( + Transform3{Translation3{Vector3{0_mm, 0_mm, -500_mm}}}, + std::make_shared(100_mm, 400_mm, 400_mm)); + volumes.push_back(vol1.get()); + + auto vol2 = std::make_shared( + Transform3{Translation3{Vector3{0_mm, 0_mm, 500_mm} + shift}}, + std::make_shared(100_mm, 400_mm, 400_mm)); + volumes.push_back(vol2.get()); + + BOOST_CHECK_THROW( + CuboidVolumeStack(volumes, direction, strategy, + CuboidVolumeStack::ResizeStrategy::Gap, *logger), + std::invalid_argument); + } + } +} + +BOOST_DATA_TEST_CASE(JoinCuboidVolumeSingle, + (boost::unit_test::data::make(Acts::AxisDirection::AxisX, + Acts::AxisDirection::AxisY, + Acts::AxisDirection::AxisZ) * + boost::unit_test::data::make(strategies)), + direction, strategy) { + auto vol = std::make_shared( + Transform3::Identity() * Translation3{14_mm, 24_mm, 0_mm} * + AngleAxis3(73_degree, Vector3::UnitX()), + std::make_shared(100_mm, 400_mm, 400_mm)); + + std::vector volumes{vol.get()}; + + CuboidVolumeStack stack(volumes, direction, strategy, + CuboidVolumeStack::ResizeStrategy::Gap, *logger); + + // Cuboid stack has the same transform as bounds as the single input + // volume + BOOST_CHECK_EQUAL(volumes.size(), 1); + BOOST_CHECK_EQUAL(volumes.at(0), vol.get()); + BOOST_CHECK_EQUAL(vol->transform().matrix(), stack.transform().matrix()); + BOOST_CHECK_EQUAL(vol->volumeBounds(), stack.volumeBounds()); +} + +BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_SUITE_END() + +} // namespace Acts::Test From 950ab98f743950ec52aae50239d2e42c0edd5725 Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Tue, 21 Jan 2025 11:39:14 +0200 Subject: [PATCH 02/22] lint --- Core/src/Geometry/CuboidVolumeStack.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Core/src/Geometry/CuboidVolumeStack.cpp b/Core/src/Geometry/CuboidVolumeStack.cpp index 1ec295468a3..08730db5ff9 100644 --- a/Core/src/Geometry/CuboidVolumeStack.cpp +++ b/Core/src/Geometry/CuboidVolumeStack.cpp @@ -120,8 +120,7 @@ CuboidVolumeStack::CuboidVolumeStack(std::vector& volumes, } else if ((localDirVector - Vector3::UnitZ()).norm() < tolerance) { m_dir = AxisDirection::AxisZ; } else { - throw std::invalid_argument( - "CuboidVolumeStack: Invalid axis direction"); + throw std::invalid_argument("CuboidVolumeStack: Invalid axis direction"); } std::size_t dirIdx = static_cast(m_dir); From 51c60b49264e81fb9a16bd143ca859e7f70b24d5 Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Tue, 21 Jan 2025 11:40:15 +0200 Subject: [PATCH 03/22] cmake --- Tests/UnitTests/Core/Geometry/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/UnitTests/Core/Geometry/CMakeLists.txt b/Tests/UnitTests/Core/Geometry/CMakeLists.txt index 41c218129fe..89b54d8972c 100644 --- a/Tests/UnitTests/Core/Geometry/CMakeLists.txt +++ b/Tests/UnitTests/Core/Geometry/CMakeLists.txt @@ -32,6 +32,7 @@ add_unittest(TrapezoidVolumeBounds TrapezoidVolumeBoundsTests.cpp) add_unittest(VolumeBounds VolumeBoundsTests.cpp) add_unittest(Volume VolumeTests.cpp) add_unittest(CylinderVolumeStack CylinderVolumeStackTests.cpp) +add_unittest(CuboidVolumeStack CuboidVolumeStackTests.cpp) add_unittest(PortalLink PortalLinkTests.cpp) add_unittest(Portal PortalTests.cpp) add_unittest(PortalShell PortalShellTests.cpp) From e86ced7ccd0fb0ef067166cabe7534bee93ad14c Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Tue, 21 Jan 2025 11:54:11 +0200 Subject: [PATCH 04/22] docs --- docs/_extensions/lazy_autodoc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/_extensions/lazy_autodoc.py b/docs/_extensions/lazy_autodoc.py index a2f455c561a..4263042fa91 100644 --- a/docs/_extensions/lazy_autodoc.py +++ b/docs/_extensions/lazy_autodoc.py @@ -96,6 +96,7 @@ def run() -> None: "Acts::GenericCuboidVolumeBounds", "Acts::TrapezoidVolumeBounds", "Acts::CylinderVolumeStack", + "Acts::CuboidVolumeStack", "Acts::GeometryObject", "Acts::TrackContainer", "Acts::ConeLayer", From a2df0d7d9a105fc0ffe9c3dfedeb8d10b206adb4 Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Tue, 21 Jan 2025 11:58:45 +0200 Subject: [PATCH 05/22] tolerance --- Core/src/Geometry/CuboidVolumeStack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/Geometry/CuboidVolumeStack.cpp b/Core/src/Geometry/CuboidVolumeStack.cpp index 08730db5ff9..72ae9e607fc 100644 --- a/Core/src/Geometry/CuboidVolumeStack.cpp +++ b/Core/src/Geometry/CuboidVolumeStack.cpp @@ -600,7 +600,7 @@ void CuboidVolumeStack::update(std::shared_ptr volbounds, checkVolumeAlignment(volTemp, logger); } - constexpr auto tolerance = 1e-1; + constexpr auto tolerance = s_onSurfaceTolerance; auto same = [](double a, double b) { return std::abs(a - b) < tolerance; }; for (const auto& dir : {m_dir, m_dirOrth1, m_dirOrth2}) { From cebbde7787fb180e05720f8d362101ac09fa5325 Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Tue, 21 Jan 2025 12:19:55 +0200 Subject: [PATCH 06/22] cmake --- Core/src/Geometry/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/src/Geometry/CMakeLists.txt b/Core/src/Geometry/CMakeLists.txt index 189c4396112..18a58033eaa 100644 --- a/Core/src/Geometry/CMakeLists.txt +++ b/Core/src/Geometry/CMakeLists.txt @@ -35,6 +35,7 @@ target_sources( Volume.cpp VolumeBounds.cpp CylinderVolumeStack.cpp + CuboidVolumeStack.cpp Portal.cpp GridPortalLink.cpp GridPortalLinkMerging.cpp From e066a128d275791afbbb2351bdd34206527e1dee Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Tue, 21 Jan 2025 14:47:15 +0200 Subject: [PATCH 07/22] dereference warnings --- .../Core/Geometry/CuboidVolumeStackTests.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp b/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp index e40d07bad1b..dc5ca60965b 100644 --- a/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp +++ b/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp @@ -22,8 +22,12 @@ #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp" #include "Acts/Utilities/AxisDefinitions.hpp" #include "Acts/Utilities/Logger.hpp" +#include "Acts/Utilities/ThrowAssert.hpp" #include "Acts/Utilities/Zip.hpp" +#include +#include + using namespace Acts::UnitLiterals; namespace Acts::Test { @@ -122,11 +126,13 @@ BOOST_DATA_TEST_CASE(BaselineLocal, auto origVolumes = volumes; std::vector originalBounds; - std::transform( - volumes.begin(), volumes.end(), std::back_inserter(originalBounds), - [](const auto& vol) { - return *dynamic_cast(&vol->volumeBounds()); - }); + std::transform(volumes.begin(), volumes.end(), + std::back_inserter(originalBounds), [](const auto& vol) { + const auto* res = + static_cast(&vol->volumeBounds()); + throw_assert(res != nullptr, ""); + return *res; + }); if (shift < 1.0) { BOOST_CHECK_THROW( From 856aa29d5858db87fdbd2459956a527b516404c5 Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Tue, 21 Jan 2025 14:56:56 +0200 Subject: [PATCH 08/22] sonarcloud fixes --- Core/src/Geometry/CuboidVolumeStack.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Core/src/Geometry/CuboidVolumeStack.cpp b/Core/src/Geometry/CuboidVolumeStack.cpp index 72ae9e607fc..ae76107d79e 100644 --- a/Core/src/Geometry/CuboidVolumeStack.cpp +++ b/Core/src/Geometry/CuboidVolumeStack.cpp @@ -94,7 +94,7 @@ CuboidVolumeStack::CuboidVolumeStack(std::vector& volumes, m_dir(direction), m_resizeStrategy(resizeStrategy), m_volumes(volumes) { - std::size_t dirIdx = static_cast(m_dir); + auto dirIdx = static_cast(m_dir); m_dirOrth1 = static_cast((dirIdx + 1) % 3); m_dirOrth2 = static_cast((dirIdx + 2) % 3); @@ -123,7 +123,7 @@ CuboidVolumeStack::CuboidVolumeStack(std::vector& volumes, throw std::invalid_argument("CuboidVolumeStack: Invalid axis direction"); } - std::size_t dirIdx = static_cast(m_dir); + auto dirIdx = static_cast(m_dir); m_dirOrth1 = static_cast((dirIdx + 1) % 3); m_dirOrth2 = static_cast((dirIdx + 2) % 3); @@ -192,7 +192,7 @@ void CuboidVolumeStack::initializeOuterVolume(AttachmentStrategy strategy, ACTS_VERBOSE("Checking volume alignment"); checkVolumeAlignment(volumeTuples, logger); - std::size_t dirIdx = static_cast(m_dir); + auto dirIdx = static_cast(m_dir); ACTS_VERBOSE("Sorting by volume " << axisDirectionName(m_dir) << " position"); std::ranges::sort(volumeTuples, {}, [&dirIdx](const auto& v) { return v.localTransform.translation()[dirIdx]; @@ -471,9 +471,9 @@ void CuboidVolumeStack::printVolumeSequence( void CuboidVolumeStack::checkVolumeAlignment( const std::vector& volumes, const Logger& logger) const { std::size_t n = 0; - std::size_t dirIdx = static_cast(m_dir); - std::size_t dirOrth1Idx = static_cast(m_dirOrth1); - std::size_t dirOrth2Idx = static_cast(m_dirOrth2); + auto dirIdx = static_cast(m_dir); + auto dirOrth1Idx = static_cast(m_dirOrth1); + auto dirOrth2Idx = static_cast(m_dirOrth2); for (auto& vt : volumes) { ACTS_VERBOSE("Checking volume #" @@ -675,9 +675,9 @@ void CuboidVolumeStack::update(std::shared_ptr volbounds, ACTS_VERBOSE("Halflength " << axisDirectionName(m_dir) << "is the same, no " << axisDirectionName(m_dir) << "resize needed"); } else { - std::size_t dirIdx = static_cast(m_dir); - std::size_t dirOrth1Idx = static_cast(m_dirOrth1); - std::size_t dirOrth2Idx = static_cast(m_dirOrth2); + auto dirIdx = static_cast(m_dir); + auto dirOrth1Idx = static_cast(m_dirOrth1); + auto dirOrth2Idx = static_cast(m_dirOrth2); auto boundDirIdx = static_cast(m_dir); if (m_resizeStrategy == ResizeStrategy::Expand) { if (newVolume.min(m_dir) < oldVolume.min(m_dir)) { From 8fbac95f39787a5412fb9a4f2ce9e568881a06c0 Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Tue, 21 Jan 2025 16:21:46 +0200 Subject: [PATCH 09/22] tidy --- .../Acts/Geometry/CuboidVolumeStack.hpp | 2 +- Core/src/Geometry/CuboidVolumeStack.cpp | 14 ++++---- .../Core/Geometry/CuboidVolumeStackTests.cpp | 32 +++++++++---------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Core/include/Acts/Geometry/CuboidVolumeStack.hpp b/Core/include/Acts/Geometry/CuboidVolumeStack.hpp index 642c2ed6ddc..ea8ae133656 100644 --- a/Core/include/Acts/Geometry/CuboidVolumeStack.hpp +++ b/Core/include/Acts/Geometry/CuboidVolumeStack.hpp @@ -90,7 +90,7 @@ class CuboidVolumeStack : public Volume { /// in @c x or @c y. /// @pre The volumes all need to have @c CuboidVolumeBounds /// @note Preconditions are checked on construction - CuboidVolumeStack(std::vector& volumes, Vector3 direction, + CuboidVolumeStack(std::vector& volumes, const Vector3& direction, AttachmentStrategy strategy = AttachmentStrategy::Midpoint, ResizeStrategy resizeStrategy = ResizeStrategy::Expand, const Logger& logger = Acts::getDummyLogger()); diff --git a/Core/src/Geometry/CuboidVolumeStack.cpp b/Core/src/Geometry/CuboidVolumeStack.cpp index ae76107d79e..0b0c6d7f506 100644 --- a/Core/src/Geometry/CuboidVolumeStack.cpp +++ b/Core/src/Geometry/CuboidVolumeStack.cpp @@ -102,7 +102,7 @@ CuboidVolumeStack::CuboidVolumeStack(std::vector& volumes, } CuboidVolumeStack::CuboidVolumeStack(std::vector& volumes, - Vector3 direction, + const Vector3& direction, AttachmentStrategy strategy, ResizeStrategy resizeStrategy, const Logger& logger) @@ -250,7 +250,7 @@ void CuboidVolumeStack::initializeOuterVolume(AttachmentStrategy strategy, Translation3 translation(Vector3::Unit(dirIdx) * mid); m_transform = m_groupTransform * translation; - std::array bounds; + std::array bounds{}; bounds.at(dirIdx) = hl; bounds.at(static_cast(m_dirOrth1)) = hl1; bounds.at(static_cast(m_dirOrth2)) = hl2; @@ -419,7 +419,7 @@ CuboidVolumeStack::checkOverlapAndAttach( Transform3 gapLocalTransform{gapTranslation}; Transform3 gapGlobalTransform = m_groupTransform * gapLocalTransform; - std::array gapBoundsVals; + std::array gapBoundsVals{}; gapBoundsVals[dirIdx] = gapHl; gapBoundsVals[static_cast(m_dirOrth1)] = (max1 - min1) / 2; @@ -752,7 +752,7 @@ void CuboidVolumeStack::update(std::shared_ptr volbounds, printGapDimensions(candidate, " before"); - std::array gap1BoundsVals; + std::array gap1BoundsVals{}; gap1BoundsVals[dirIdx] = gap1Hl; gap1BoundsVals[dirOrth1Idx] = newVolume.halfLength(m_dirOrth1); gap1BoundsVals[dirOrth2Idx] = newVolume.halfLength(m_dirOrth2); @@ -767,7 +767,7 @@ void CuboidVolumeStack::update(std::shared_ptr volbounds, } else { ACTS_VERBOSE("~> Creating new gap volume at negative "); - std::array gap1BoundsVals; + std::array gap1BoundsVals{}; gap1BoundsVals[dirIdx] = gap1Hl; gap1BoundsVals[dirOrth1Idx] = newVolume.halfLength(m_dirOrth1); gap1BoundsVals[dirOrth2Idx] = newVolume.halfLength(m_dirOrth2); @@ -800,7 +800,7 @@ void CuboidVolumeStack::update(std::shared_ptr volbounds, gap2Min = newVolume.max(m_dir) - gap2Hl * 2; gap2P = (gap2Max + gap2Min) / 2.0; - std::array gap2BoundsVals; + std::array gap2BoundsVals{}; gap2BoundsVals[dirIdx] = gap2Hl; gap2BoundsVals[dirOrth1Idx] = newVolume.halfLength(m_dirOrth1); gap2BoundsVals[dirOrth2Idx] = newVolume.halfLength(m_dirOrth2); @@ -814,7 +814,7 @@ void CuboidVolumeStack::update(std::shared_ptr volbounds, printGapDimensions(candidate, " after "); } else { ACTS_VERBOSE("~> Creating new gap volume at positive "); - std::array gap2BoundsVals; + std::array gap2BoundsVals{}; gap2BoundsVals[dirIdx] = gap2Hl; gap2BoundsVals[dirOrth1Idx] = newVolume.halfLength(m_dirOrth1); gap2BoundsVals[dirOrth2Idx] = newVolume.halfLength(m_dirOrth2); diff --git a/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp b/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp index dc5ca60965b..cd24dd7b1a9 100644 --- a/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp +++ b/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp @@ -87,19 +87,19 @@ BOOST_DATA_TEST_CASE(BaselineLocal, auto boundDirOrth1 = static_cast(dirOrth1); auto boundDirOrth2 = static_cast(dirOrth2); - std::array bounds1Vals; + std::array bounds1Vals{}; bounds1Vals.at(boundDir) = halfDir; bounds1Vals.at(boundDirOrth1) = 100_mm; bounds1Vals.at(boundDirOrth2) = 400_mm; auto bounds1 = std::make_shared(bounds1Vals); - std::array bounds2Vals; + std::array bounds2Vals{}; bounds2Vals.at(boundDir) = halfDir; bounds2Vals.at(boundDirOrth1) = 200_mm; bounds2Vals.at(boundDirOrth2) = 600_mm; auto bounds2 = std::make_shared(bounds2Vals); - std::array bounds3Vals; + std::array bounds3Vals{}; bounds3Vals.at(boundDir) = halfDir; bounds3Vals.at(boundDirOrth1) = 300_mm; bounds3Vals.at(boundDirOrth2) = 500_mm; @@ -430,19 +430,19 @@ BOOST_DATA_TEST_CASE(Asymmetric, auto boundDirOrth1 = static_cast(dirOrth1); auto boundDirOrth2 = static_cast(dirOrth2); - std::array bounds1Vals; + std::array bounds1Vals{}; bounds1Vals[dirIdx] = halfDir1; bounds1Vals[dirOrth1Idx] = 100_mm; bounds1Vals[dirOrth2Idx] = 400_mm; auto bounds1 = std::make_shared(bounds1Vals); - std::array bounds2Vals; + std::array bounds2Vals{}; bounds2Vals[dirIdx] = halfDir2; bounds2Vals[dirOrth1Idx] = 200_mm; bounds2Vals[dirOrth2Idx] = 600_mm; auto bounds2 = std::make_shared(bounds2Vals); - std::array bounds3Vals; + std::array bounds3Vals{}; bounds3Vals[dirIdx] = halfDir3; bounds3Vals[dirOrth1Idx] = 300_mm; bounds3Vals[dirOrth2Idx] = 500_mm; @@ -509,19 +509,19 @@ BOOST_DATA_TEST_CASE(UpdateStack, auto boundDirOrth1 = static_cast(dirOrth1); auto boundDirOrth2 = static_cast(dirOrth2); - std::array bounds1Vals; + std::array bounds1Vals{}; bounds1Vals[dirIdx] = halfDir; bounds1Vals[dirOrth1Idx] = 100_mm; bounds1Vals[dirOrth2Idx] = 600_mm; auto bounds1 = std::make_shared(bounds1Vals); - std::array bounds2Vals; + std::array bounds2Vals{}; bounds2Vals[dirIdx] = halfDir; bounds2Vals[dirOrth1Idx] = 100_mm; bounds2Vals[dirOrth2Idx] = 600_mm; auto bounds2 = std::make_shared(bounds2Vals); - std::array bounds3Vals; + std::array bounds3Vals{}; bounds3Vals[dirIdx] = halfDir; bounds3Vals[dirOrth1Idx] = 100_mm; bounds3Vals[dirOrth2Idx] = 600_mm; @@ -768,13 +768,13 @@ BOOST_DATA_TEST_CASE( auto boundDirOrth1 = static_cast(dirOrth1); auto boundDirOrth2 = static_cast(dirOrth2); - std::array bounds1Vals; + std::array bounds1Vals{}; bounds1Vals[dirIdx] = 400_mm; bounds1Vals[dirOrth1Idx] = 100_mm; bounds1Vals[dirOrth2Idx] = 300_mm; auto bounds1 = std::make_shared(bounds1Vals); - std::array bounds2Vals; + std::array bounds2Vals{}; bounds2Vals[dirIdx] = 400_mm; bounds2Vals[dirOrth1Idx] = 100_mm; bounds2Vals[dirOrth2Idx] = 300_mm; @@ -937,7 +937,7 @@ BOOST_DATA_TEST_CASE(ResizeGapMultiple, auto boundDirOrth1 = static_cast(dirOrth1); auto boundDirOrth2 = static_cast(dirOrth2); - std::array boundsVals; + std::array boundsVals{}; boundsVals[dirIdx] = 100; boundsVals[dirOrth1Idx] = 70; boundsVals[dirOrth2Idx] = 100; @@ -955,7 +955,7 @@ BOOST_DATA_TEST_CASE(ResizeGapMultiple, BOOST_CHECK_EQUAL(volumes.size(), 1); BOOST_CHECK(stack.gaps().empty()); - std::array newBounds1Vals; + std::array newBounds1Vals{}; newBounds1Vals[dirIdx] = 200; newBounds1Vals[dirOrth1Idx] = 70; newBounds1Vals[dirOrth2Idx] = 100; @@ -973,7 +973,7 @@ BOOST_DATA_TEST_CASE(ResizeGapMultiple, BOOST_REQUIRE_NE(updatedBounds, nullptr); BOOST_CHECK_EQUAL(updatedBounds->get(boundDir), 100.0); - std::array newBounds2Vals; + std::array newBounds2Vals{}; newBounds2Vals[dirIdx] = 300; newBounds2Vals[dirOrth1Idx] = 70; newBounds2Vals[dirOrth2Idx] = 100; @@ -1003,7 +1003,7 @@ BOOST_DATA_TEST_CASE(ResizeGapMultiple, BOOST_CHECK_EQUAL(volumes.size(), 1); BOOST_CHECK(stack.gaps().empty()); - std::array newBounds1Vals; + std::array newBounds1Vals{}; newBounds1Vals[dirIdx] = 200; newBounds1Vals[dirOrth1Idx] = 70; newBounds1Vals[dirOrth2Idx] = 100; @@ -1021,7 +1021,7 @@ BOOST_DATA_TEST_CASE(ResizeGapMultiple, BOOST_REQUIRE_NE(updatedBounds, nullptr); BOOST_CHECK_EQUAL(updatedBounds->get(boundDir), 100.0); - std::array newBounds2Vals; + std::array newBounds2Vals{}; newBounds2Vals[dirIdx] = 300; newBounds2Vals[dirOrth1Idx] = 70; newBounds2Vals[dirOrth2Idx] = 100; From 06f3a1a303351c946cf33a92fea37216693ec948 Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Wed, 22 Jan 2025 14:27:49 +0200 Subject: [PATCH 10/22] idx fixes, strategies, bounds --- .../Acts/Geometry/CuboidVolumeBounds.hpp | 9 + .../Acts/Geometry/CuboidVolumeStack.hpp | 76 ++-- .../CylinderContainerBlueprintNode.hpp | 26 +- .../Acts/Geometry/CylinderVolumeStack.hpp | 52 +-- .../detail/VolumeAttachmentStrategy.hpp | 32 ++ .../Geometry/detail/VolumeResizeStrategy.hpp | 25 ++ Core/src/Geometry/CMakeLists.txt | 2 + Core/src/Geometry/CuboidVolumeBounds.cpp | 40 +++ Core/src/Geometry/CuboidVolumeStack.cpp | 240 ++++++------- .../CylinderContainerBlueprintNode.cpp | 12 +- Core/src/Geometry/CylinderVolumeStack.cpp | 94 ++--- .../detail/VolumeAttachmentStrategy.cpp | 30 ++ .../Geometry/detail/VolumeResizeStrategy.cpp | 25 ++ Examples/Python/src/Blueprint.cpp | 11 +- Examples/Python/src/Geometry.cpp | 19 +- .../Core/Geometry/BlueprintApiTests.cpp | 16 +- .../Core/Geometry/BlueprintTests.cpp | 3 +- .../Core/Geometry/CuboidVolumeBoundsTests.cpp | 11 + .../Core/Geometry/CuboidVolumeStackTests.cpp | 337 ++++++++---------- .../Geometry/CylinderVolumeStackTests.cpp | 152 ++++---- 20 files changed, 631 insertions(+), 581 deletions(-) create mode 100644 Core/include/Acts/Geometry/detail/VolumeAttachmentStrategy.hpp create mode 100644 Core/include/Acts/Geometry/detail/VolumeResizeStrategy.hpp create mode 100644 Core/src/Geometry/detail/VolumeAttachmentStrategy.cpp create mode 100644 Core/src/Geometry/detail/VolumeResizeStrategy.cpp diff --git a/Core/include/Acts/Geometry/CuboidVolumeBounds.hpp b/Core/include/Acts/Geometry/CuboidVolumeBounds.hpp index 39344352eda..8bc5cac731e 100644 --- a/Core/include/Acts/Geometry/CuboidVolumeBounds.hpp +++ b/Core/include/Acts/Geometry/CuboidVolumeBounds.hpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -71,6 +72,9 @@ class CuboidVolumeBounds : public VolumeBounds { /// @param values iw the bound values CuboidVolumeBounds(const std::array& values); + CuboidVolumeBounds( + std::initializer_list> keyValues); + /// Copy Constructor /// /// @param bobo is the source volume bounds to be copied @@ -149,6 +153,11 @@ class CuboidVolumeBounds : public VolumeBounds { /// @param keyValues the initializer list of key value pairs void set(std::initializer_list> keyValues); + /// Convert axis direction to a corresponding bound value + /// in local coordinate convetion + /// @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 diff --git a/Core/include/Acts/Geometry/CuboidVolumeStack.hpp b/Core/include/Acts/Geometry/CuboidVolumeStack.hpp index ea8ae133656..d29feaa9308 100644 --- a/Core/include/Acts/Geometry/CuboidVolumeStack.hpp +++ b/Core/include/Acts/Geometry/CuboidVolumeStack.hpp @@ -10,9 +10,12 @@ #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 #include namespace Acts { @@ -30,29 +33,6 @@ namespace Acts { /// @note The size adjustment convention is that volumes are never shrunk class CuboidVolumeStack : 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** - /// x, y, or z value is extended - First, - /// Given two volumes, the *right* one, i.e. the one with the higher - /// **local** x, y, or z 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 axis direction @@ -69,10 +49,11 @@ class CuboidVolumeStack : public Volume { /// in @c x or @c y. /// @pre The volumes all need to have @c CuboidVolumeBounds /// @note Preconditions are checked on construction - CuboidVolumeStack(std::vector& volumes, AxisDirection direction, - AttachmentStrategy strategy = AttachmentStrategy::Midpoint, - ResizeStrategy resizeStrategy = ResizeStrategy::Expand, - const Logger& logger = Acts::getDummyLogger()); + CuboidVolumeStack( + std::vector& volumes, AxisDirection direction, + VolumeAttachmentStrategy strategy = VolumeAttachmentStrategy::Midpoint, + VolumeResizeStrategy resizeStrategy = VolumeResizeStrategy::Expand, + const Logger& logger = Acts::getDummyLogger()); /// Constructor from a vector of volumes and direction /// @param volumes is the vector of volumes @@ -90,10 +71,11 @@ class CuboidVolumeStack : public Volume { /// in @c x or @c y. /// @pre The volumes all need to have @c CuboidVolumeBounds /// @note Preconditions are checked on construction - CuboidVolumeStack(std::vector& volumes, const Vector3& direction, - AttachmentStrategy strategy = AttachmentStrategy::Midpoint, - ResizeStrategy resizeStrategy = ResizeStrategy::Expand, - const Logger& logger = Acts::getDummyLogger()); + CuboidVolumeStack( + std::vector& 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 @@ -113,6 +95,17 @@ class CuboidVolumeStack : public Volume { /// @return the vector of gap volumes const std::vector>& gaps() const; + /// Conert 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 --> + /// @param direction is the axis direction to find the orthogonal for + static std::pair getOrthogonalAxes( + AxisDirection direction); + private: /// Helper to get the first volume in the input, and throw an exception if /// there is not one. @@ -124,7 +117,8 @@ class CuboidVolumeStack : public Volume { /// internal attachment and produces the overall outer volume bounds. /// @param strategy is the attachment strategy /// @param logger is the logger - void initializeOuterVolume(AttachmentStrategy strategy, const Logger& logger); + void initializeOuterVolume(VolumeAttachmentStrategy strategy, + const Logger& logger); struct VolumeTuple; @@ -157,7 +151,7 @@ class CuboidVolumeStack : public Volume { /// @param logger is the logger /// @return vector of gap volumes. Can be empty if none were created. std::vector checkOverlapAndAttach( - std::vector& volumes, AttachmentStrategy strategy, + std::vector& volumes, VolumeAttachmentStrategy strategy, const Logger& logger); /// Helper function to synchronize the bounds of the volumes @@ -184,24 +178,10 @@ class CuboidVolumeStack : public Volume { AxisDirection m_dirOrth1{}; AxisDirection m_dirOrth2{}; - ResizeStrategy m_resizeStrategy{}; + VolumeResizeStrategy m_resizeStrategy{}; Transform3 m_groupTransform{}; std::vector> m_gaps{}; std::vector& 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, - CuboidVolumeStack::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, - CuboidVolumeStack::ResizeStrategy strategy); - } // namespace Acts diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index decd92facd9..d05bdac55e4 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -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" @@ -37,10 +39,10 @@ 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; @@ -101,13 +103,13 @@ 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 @@ -115,11 +117,11 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { /// 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 @@ -138,11 +140,11 @@ 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 m_childVolumes; diff --git a/Core/include/Acts/Geometry/CylinderVolumeStack.hpp b/Core/include/Acts/Geometry/CylinderVolumeStack.hpp index 5cfa24d0ad2..f669f7d9daa 100644 --- a/Core/include/Acts/Geometry/CylinderVolumeStack.hpp +++ b/Core/include/Acts/Geometry/CylinderVolumeStack.hpp @@ -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" @@ -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 @@ -74,8 +53,8 @@ class CylinderVolumeStack : public Volume { /// @note Preconditions are checked on construction CylinderVolumeStack( std::vector& 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 @@ -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; @@ -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 checkOverlapAndAttachInZ( - std::vector& volumes, AttachmentStrategy strategy, + std::vector& volumes, VolumeAttachmentStrategy strategy, const Logger& logger); /// Helper function to synchronize the r bounds of the volumes @@ -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 checkOverlapAndAttachInR( - std::vector& volumes, AttachmentStrategy strategy, + std::vector& volumes, VolumeAttachmentStrategy strategy, const Logger& logger); /// Helper function to synchronize the z bounds of the volumes @@ -183,24 +163,10 @@ class CylinderVolumeStack : public Volume { const Transform3& transform, const std::shared_ptr& bounds); AxisDirection m_direction{}; - ResizeStrategy m_resizeStrategy{}; + VolumeResizeStrategy m_resizeStrategy{}; Transform3 m_groupTransform{}; std::vector> m_gaps{}; std::vector& 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 diff --git a/Core/include/Acts/Geometry/detail/VolumeAttachmentStrategy.hpp b/Core/include/Acts/Geometry/detail/VolumeAttachmentStrategy.hpp new file mode 100644 index 00000000000..68af1b14026 --- /dev/null +++ b/Core/include/Acts/Geometry/detail/VolumeAttachmentStrategy.hpp @@ -0,0 +1,32 @@ +// 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 + +namespace Acts { + +/// The attachment strategy defines how the volumes are attached +/// Attachment always happens pair-wise +enum class VolumeAttachmentStrategy { + /// Given two volumes, the *left* one, i.e. the one with the lower **local** + /// x, y, or z value is extended + First, + /// Given two volumes, the *right* one, i.e. the one with the higher + /// **local** x, y, or z 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, +}; + +std::ostream& operator<<(std::ostream& os, VolumeAttachmentStrategy strategy); + +} // namespace Acts diff --git a/Core/include/Acts/Geometry/detail/VolumeResizeStrategy.hpp b/Core/include/Acts/Geometry/detail/VolumeResizeStrategy.hpp new file mode 100644 index 00000000000..3124de68b6c --- /dev/null +++ b/Core/include/Acts/Geometry/detail/VolumeResizeStrategy.hpp @@ -0,0 +1,25 @@ +// 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 + +namespace Acts { + +/// The resize strategy defines how the volumes are resized +enum class VolumeResizeStrategy { + /// 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, +}; + +std::ostream& operator<<(std::ostream& os, VolumeResizeStrategy strategy); + +} // namespace Acts diff --git a/Core/src/Geometry/CMakeLists.txt b/Core/src/Geometry/CMakeLists.txt index 18a58033eaa..19585591c45 100644 --- a/Core/src/Geometry/CMakeLists.txt +++ b/Core/src/Geometry/CMakeLists.txt @@ -51,4 +51,6 @@ target_sources( StaticBlueprintNode.cpp LayerBlueprintNode.cpp MaterialDesignatorBlueprintNode.cpp + detail/VolumeAttachmentStrategy.cpp + detail/VolumeResizeStrategy.cpp ) diff --git a/Core/src/Geometry/CuboidVolumeBounds.cpp b/Core/src/Geometry/CuboidVolumeBounds.cpp index 9b01eb54ae8..90d66e7eff1 100644 --- a/Core/src/Geometry/CuboidVolumeBounds.cpp +++ b/Core/src/Geometry/CuboidVolumeBounds.cpp @@ -9,11 +9,15 @@ #include "Acts/Geometry/CuboidVolumeBounds.hpp" #include "Acts/Definitions/Direction.hpp" +#include "Acts/Surfaces/LineSurface.hpp" #include "Acts/Surfaces/PlaneSurface.hpp" #include "Acts/Surfaces/RectangleBounds.hpp" #include "Acts/Surfaces/Surface.hpp" #include "Acts/Utilities/BoundingBox.hpp" +#include +#include +#include #include namespace Acts { @@ -30,6 +34,24 @@ CuboidVolumeBounds::CuboidVolumeBounds(const std::array& values) buildSurfaceBounds(); } +CuboidVolumeBounds::CuboidVolumeBounds( + std::initializer_list> keyValues) { + // Consistency check will fail if + // not all the bounds are constructed + std::array values = {-1, -1, -1}; + for (const auto& [key, value] : keyValues) { + values[key] = value; + } + if (std::any_of(values.begin(), values.end(), + [](const auto& val) { return val == -1; })) { + throw std::logic_error("Missing bound values"); + } + + m_values = values; + checkConsistency(); + buildSurfaceBounds(); +} + std::vector CuboidVolumeBounds::values() const { return {m_values.begin(), m_values.end()}; } @@ -150,4 +172,22 @@ void CuboidVolumeBounds::set( } } +CuboidVolumeBounds::BoundValues CuboidVolumeBounds::fromAxisDirection( + AxisDirection direction) { + using enum AxisDirection; + switch (direction) { + case AxisX: + return BoundValues::eHalfLengthX; + break; + case AxisY: + return BoundValues::eHalfLengthY; + break; + case AxisZ: + return BoundValues::eHalfLengthZ; + break; + default: + throw std::invalid_argument("Invalid axis direction"); + } +} + } // namespace Acts diff --git a/Core/src/Geometry/CuboidVolumeStack.cpp b/Core/src/Geometry/CuboidVolumeStack.cpp index 0b0c6d7f506..b06214886b5 100644 --- a/Core/src/Geometry/CuboidVolumeStack.cpp +++ b/Core/src/Geometry/CuboidVolumeStack.cpp @@ -15,11 +15,13 @@ #include "Acts/Utilities/Logger.hpp" #include -#include #include +#include #include #include +#include #include +#include #include namespace Acts { @@ -43,11 +45,10 @@ struct CuboidVolumeStack::VolumeTuple { } double mid(AxisDirection direction) const { - return localTransform.translation()[static_cast(direction)]; + return localTransform.translation()[axisToIndex(direction)]; } double halfLength(AxisDirection direction) const { - return updatedBounds->get( - static_cast(direction)); + return updatedBounds->get(CuboidVolumeBounds::fromAxisDirection(direction)); } double min(AxisDirection direction) const { return mid(direction) - halfLength(direction); @@ -85,47 +86,74 @@ struct CuboidVolumeStack::VolumeTuple { } }; +std::size_t CuboidVolumeStack::axisToIndex(AxisDirection direction) { + switch (direction) { + case AxisDirection::AxisX: + return 0; + break; + case AxisDirection::AxisY: + return 1; + break; + case AxisDirection::AxisZ: + return 2; + break; + default: + throw std::invalid_argument("Invalid axis direction"); + } +} + +std::pair CuboidVolumeStack::getOrthogonalAxes( + AxisDirection direction) { + switch (direction) { + case AxisDirection::AxisX: + return {AxisDirection::AxisY, AxisDirection::AxisZ}; + break; + case AxisDirection::AxisY: + return {AxisDirection::AxisZ, AxisDirection::AxisX}; + break; + case AxisDirection::AxisZ: + return {AxisDirection::AxisX, AxisDirection::AxisY}; + break; + default: + throw std::invalid_argument("Invalid axis direction"); + } +} + CuboidVolumeStack::CuboidVolumeStack(std::vector& volumes, AxisDirection direction, - AttachmentStrategy strategy, - ResizeStrategy resizeStrategy, + VolumeAttachmentStrategy strategy, + VolumeResizeStrategy resizeStrategy, const Logger& logger) : Volume(initialVolume(volumes)), m_dir(direction), m_resizeStrategy(resizeStrategy), m_volumes(volumes) { - auto dirIdx = static_cast(m_dir); - m_dirOrth1 = static_cast((dirIdx + 1) % 3); - m_dirOrth2 = static_cast((dirIdx + 2) % 3); + std::tie(m_dirOrth1, m_dirOrth2) = getOrthogonalAxes(m_dir); initializeOuterVolume(strategy, logger); } CuboidVolumeStack::CuboidVolumeStack(std::vector& volumes, const Vector3& direction, - AttachmentStrategy strategy, - ResizeStrategy resizeStrategy, + VolumeAttachmentStrategy strategy, + VolumeResizeStrategy resizeStrategy, const Logger& logger) : Volume(initialVolume(volumes)), m_resizeStrategy(resizeStrategy), m_volumes(volumes) { - // TODO: What's a good tolerance here? - const auto& tolerance = s_onSurfaceTolerance; Vector3 localDirVector = m_volumes.front()->transform().rotation().inverse() * direction; - if ((localDirVector - Vector3::UnitX()).norm() < tolerance) { + if ((localDirVector - Vector3::UnitX()).norm() < 1e-4) { m_dir = AxisDirection::AxisX; - } else if ((localDirVector - Vector3::UnitY()).norm() < tolerance) { + } else if ((localDirVector - Vector3::UnitY()).norm() < 1e-4) { m_dir = AxisDirection::AxisY; - } else if ((localDirVector - Vector3::UnitZ()).norm() < tolerance) { + } else if ((localDirVector - Vector3::UnitZ()).norm() < 1e-4) { m_dir = AxisDirection::AxisZ; } else { throw std::invalid_argument("CuboidVolumeStack: Invalid axis direction"); } - auto dirIdx = static_cast(m_dir); - m_dirOrth1 = static_cast((dirIdx + 1) % 3); - m_dirOrth2 = static_cast((dirIdx + 2) % 3); + std::tie(m_dirOrth1, m_dirOrth2) = getOrthogonalAxes(m_dir); initializeOuterVolume(strategy, logger); } @@ -138,7 +166,7 @@ Volume& CuboidVolumeStack::initialVolume(const std::vector& volumes) { return *volumes.front(); } -void CuboidVolumeStack::initializeOuterVolume(AttachmentStrategy strategy, +void CuboidVolumeStack::initializeOuterVolume(VolumeAttachmentStrategy strategy, const Logger& logger) { ACTS_DEBUG("Creating CuboidVolumeStack from " << m_volumes.size() << " volumes in direction " @@ -192,9 +220,9 @@ void CuboidVolumeStack::initializeOuterVolume(AttachmentStrategy strategy, ACTS_VERBOSE("Checking volume alignment"); checkVolumeAlignment(volumeTuples, logger); - auto dirIdx = static_cast(m_dir); + auto dirIdx = axisToIndex(m_dir); ACTS_VERBOSE("Sorting by volume " << axisDirectionName(m_dir) << " position"); - std::ranges::sort(volumeTuples, {}, [&dirIdx](const auto& v) { + std::ranges::sort(volumeTuples, {}, [dirIdx](const auto& v) { return v.localTransform.translation()[dirIdx]; }); ACTS_VERBOSE("Checking for overlaps and attaching volumes in " @@ -245,18 +273,17 @@ void CuboidVolumeStack::initializeOuterVolume(AttachmentStrategy strategy, double min = volumeTuples.front().min(m_dir); double max = volumeTuples.back().max(m_dir); - double mid = (min + max) / 2.0; - double hl = (max - min) / 2.0; + double mid = std::midpoint(min, max); + double hl = std::midpoint(max, -min); Translation3 translation(Vector3::Unit(dirIdx) * mid); m_transform = m_groupTransform * translation; - std::array bounds{}; - bounds.at(dirIdx) = hl; - bounds.at(static_cast(m_dirOrth1)) = hl1; - bounds.at(static_cast(m_dirOrth2)) = hl2; - - Volume::update(std::make_shared(bounds), std::nullopt, - logger); + auto bounds = std::make_shared( + std::initializer_list>{ + {CuboidVolumeBounds::fromAxisDirection(m_dir), hl}, + {CuboidVolumeBounds::fromAxisDirection(m_dirOrth1), hl1}, + {CuboidVolumeBounds::fromAxisDirection(m_dirOrth2), hl2}}); + Volume::update(bounds, std::nullopt, logger); ACTS_DEBUG("Outer bounds are:\n" << volumeBounds()); ACTS_DEBUG("Outer transform / new group transform is:\n" << m_transform.matrix()); @@ -292,12 +319,12 @@ void CuboidVolumeStack::overlapPrint(const CuboidVolumeStack::VolumeTuple& a, } std::vector -CuboidVolumeStack::checkOverlapAndAttach( - std::vector& volumes, - CuboidVolumeStack::AttachmentStrategy strategy, const Logger& logger) { +CuboidVolumeStack::checkOverlapAndAttach(std::vector& volumes, + VolumeAttachmentStrategy strategy, + const Logger& logger) { // Preconditions: volumes are sorted along stacking direction - auto dirIdx = static_cast(m_dir); - auto dirBoundIdx = static_cast(m_dir); + auto dirIdx = axisToIndex(m_dir); + auto dirBoundIdx = CuboidVolumeBounds::fromAxisDirection(m_dir); std::vector gapVolumes; for (std::size_t i = 0; i < volumes.size() - 1; i++) { @@ -327,7 +354,7 @@ CuboidVolumeStack::checkOverlapAndAttach( << axisDirectionName(m_dir) << " with strategy: " << strategy); switch (strategy) { - case AttachmentStrategy::Midpoint: { + case VolumeAttachmentStrategy::Midpoint: { ACTS_VERBOSE(" -> Strategy: Expand both volumes to midpoint"); double aMidNew = (a.min(m_dir) + a.max(m_dir)) / 2.0 + gapWidth / 4.0; @@ -362,7 +389,7 @@ CuboidVolumeStack::checkOverlapAndAttach( break; } - case AttachmentStrategy::First: { + case VolumeAttachmentStrategy::First: { ACTS_VERBOSE(" -> Strategy: Expand first volume"); double aMidNew = (a.min(m_dir) + b.min(m_dir)) / 2.0; double aHlNew = (b.min(m_dir) - a.min(m_dir)) / 2.0; @@ -381,7 +408,7 @@ CuboidVolumeStack::checkOverlapAndAttach( break; } - case AttachmentStrategy::Second: { + case VolumeAttachmentStrategy::Second: { ACTS_VERBOSE(" -> Strategy: Expand second volume"); double bMidNew = (a.max(m_dir) + b.max(m_dir)) / 2.0; double bHlNew = (b.max(m_dir) - a.max(m_dir)) / 2.0; @@ -399,7 +426,7 @@ CuboidVolumeStack::checkOverlapAndAttach( b.updatedBounds->set(dirBoundIdx, bHlNew); break; } - case AttachmentStrategy::Gap: { + case VolumeAttachmentStrategy::Gap: { ACTS_VERBOSE(" -> Strategy: Create a gap volume"); double gapHl = (b.min(m_dir) - a.max(m_dir)) / 2.0; double gapMid = (b.min(m_dir) + a.max(m_dir)) / 2.0; @@ -419,13 +446,14 @@ CuboidVolumeStack::checkOverlapAndAttach( Transform3 gapLocalTransform{gapTranslation}; Transform3 gapGlobalTransform = m_groupTransform * gapLocalTransform; - std::array gapBoundsVals{}; - gapBoundsVals[dirIdx] = gapHl; - gapBoundsVals[static_cast(m_dirOrth1)] = - (max1 - min1) / 2; - gapBoundsVals[static_cast(m_dirOrth2)] = - (max2 - min2) / 2; - auto gapBounds = std::make_shared(gapBoundsVals); + auto gapBounds = std::make_shared( + std::initializer_list< + std::pair>{ + {CuboidVolumeBounds::fromAxisDirection(m_dir), gapHl}, + {CuboidVolumeBounds::fromAxisDirection(m_dirOrth1), + (max1 - min1) / 2}, + {CuboidVolumeBounds::fromAxisDirection(m_dirOrth2), + (max2 - min2) / 2}}); auto gap = addGapVolume(gapGlobalTransform, gapBounds); gapVolumes.emplace_back(*gap, m_groupTransform); @@ -471,9 +499,9 @@ void CuboidVolumeStack::printVolumeSequence( void CuboidVolumeStack::checkVolumeAlignment( const std::vector& volumes, const Logger& logger) const { std::size_t n = 0; - auto dirIdx = static_cast(m_dir); - auto dirOrth1Idx = static_cast(m_dirOrth1); - auto dirOrth2Idx = static_cast(m_dirOrth2); + auto dirIdx = axisToIndex(m_dir); + auto dirOrth1Idx = axisToIndex(m_dirOrth1); + auto dirOrth2Idx = axisToIndex(m_dirOrth2); for (auto& vt : volumes) { ACTS_VERBOSE("Checking volume #" @@ -516,19 +544,19 @@ void CuboidVolumeStack::checkVolumeAlignment( std::pair CuboidVolumeStack::synchronizeBounds( std::vector& volumes, const Logger& logger) { - auto boundDirOrth1 = static_cast(m_dirOrth1); - auto boundDirOrth2 = static_cast(m_dirOrth2); + auto boundDirOrth1 = CuboidVolumeBounds::fromAxisDirection(m_dirOrth1); + auto boundDirOrth2 = CuboidVolumeBounds::fromAxisDirection(m_dirOrth2); const double maxHl1 = std::max_element(volumes.begin(), volumes.end(), - [&boundDirOrth1](const auto& a, const auto& b) { + [boundDirOrth1](const auto& a, const auto& b) { return a.bounds->get(boundDirOrth1) < b.bounds->get(boundDirOrth1); }) ->bounds->get(boundDirOrth1); const double maxHl2 = std::max_element(volumes.begin(), volumes.end(), - [&boundDirOrth2](const auto& a, const auto& b) { + [boundDirOrth2](const auto& a, const auto& b) { return a.bounds->get(boundDirOrth2) < b.bounds->get(boundDirOrth2); }) @@ -658,7 +686,7 @@ void CuboidVolumeStack::update(std::shared_ptr volbounds, ACTS_VERBOSE("Resize all volumes to new " << axisDirectionName(dir) << " bounds"); for (auto& volume : volumeTuples) { - volume.set({{static_cast(dir), + volume.set({{CuboidVolumeBounds::fromAxisDirection(dir), newVolume.halfLength(dir)}}); } ACTS_VERBOSE("*** Volume configuration after " << axisDirectionName(dir) @@ -675,11 +703,9 @@ void CuboidVolumeStack::update(std::shared_ptr volbounds, ACTS_VERBOSE("Halflength " << axisDirectionName(m_dir) << "is the same, no " << axisDirectionName(m_dir) << "resize needed"); } else { - auto dirIdx = static_cast(m_dir); - auto dirOrth1Idx = static_cast(m_dirOrth1); - auto dirOrth2Idx = static_cast(m_dirOrth2); - auto boundDirIdx = static_cast(m_dir); - if (m_resizeStrategy == ResizeStrategy::Expand) { + auto dirIdx = axisToIndex(m_dir); + auto boundDirIdx = CuboidVolumeBounds::fromAxisDirection(m_dir); + if (m_resizeStrategy == VolumeResizeStrategy::Expand) { if (newVolume.min(m_dir) < oldVolume.min(m_dir)) { ACTS_VERBOSE("Expanding first volume to new " << axisDirectionName(m_dir) << "bounds"); @@ -717,7 +743,7 @@ void CuboidVolumeStack::update(std::shared_ptr volbounds, last.set({{boundDirIdx, newHlLast}}); last.setLocalTransform(Transform3{translation}, m_groupTransform); } - } else if (m_resizeStrategy == ResizeStrategy::Gap) { + } else if (m_resizeStrategy == VolumeResizeStrategy::Gap) { ACTS_VERBOSE("Creating gap volumes to fill the new " << axisDirectionName(m_dir) << " bounds"); @@ -745,19 +771,21 @@ void CuboidVolumeStack::update(std::shared_ptr volbounds, << axisDirectionName(m_dir)); gap1Hl = candidate.bounds->get( - static_cast(m_dir)) + + CuboidVolumeBounds::fromAxisDirection(m_dir)) + gap1Hl; gap1Max = gap1Min + gap1Hl * 2; gap1P = (gap1Max + gap1Min) / 2.0; printGapDimensions(candidate, " before"); - std::array gap1BoundsVals{}; - gap1BoundsVals[dirIdx] = gap1Hl; - gap1BoundsVals[dirOrth1Idx] = newVolume.halfLength(m_dirOrth1); - gap1BoundsVals[dirOrth2Idx] = newVolume.halfLength(m_dirOrth2); - auto gap1Bounds = - std::make_shared(gap1BoundsVals); + auto gap1Bounds = std::make_shared( + std::initializer_list< + std::pair>{ + {CuboidVolumeBounds::fromAxisDirection(m_dir), gap1Hl}, + {CuboidVolumeBounds::fromAxisDirection(m_dirOrth1), + newVolume.halfLength(m_dirOrth1)}, + {CuboidVolumeBounds::fromAxisDirection(m_dirOrth2), + newVolume.halfLength(m_dirOrth2)}}); Translation3 gap1Translation(Vector3::Unit(dirIdx) * gap1P); Transform3 gap1Transform = m_groupTransform * gap1Translation; candidate.volume->update(std::move(gap1Bounds), gap1Transform); @@ -767,12 +795,14 @@ void CuboidVolumeStack::update(std::shared_ptr volbounds, } else { ACTS_VERBOSE("~> Creating new gap volume at negative "); - std::array gap1BoundsVals{}; - gap1BoundsVals[dirIdx] = gap1Hl; - gap1BoundsVals[dirOrth1Idx] = newVolume.halfLength(m_dirOrth1); - gap1BoundsVals[dirOrth2Idx] = newVolume.halfLength(m_dirOrth2); - auto gap1Bounds = - std::make_shared(gap1BoundsVals); + auto gap1Bounds = std::make_shared( + std::initializer_list< + std::pair>{ + {CuboidVolumeBounds::fromAxisDirection(m_dir), gap1Hl}, + {CuboidVolumeBounds::fromAxisDirection(m_dirOrth1), + newVolume.halfLength(m_dirOrth1)}, + {CuboidVolumeBounds::fromAxisDirection(m_dirOrth2), + newVolume.halfLength(m_dirOrth2)}}); Translation3 gap1Translation(Vector3::Unit(dirIdx) * gap1P); Transform3 gap1Transform = m_groupTransform * gap1Translation; auto gap1 = addGapVolume(gap1Transform, std::move(gap1Bounds)); @@ -795,17 +825,19 @@ void CuboidVolumeStack::update(std::shared_ptr volbounds, ACTS_VERBOSE("~> Reusing existing gap volume at positive "); gap2Hl = candidate.bounds->get( - static_cast(m_dir)) + + CuboidVolumeBounds::fromAxisDirection(m_dir)) + gap2Hl; gap2Min = newVolume.max(m_dir) - gap2Hl * 2; gap2P = (gap2Max + gap2Min) / 2.0; - std::array gap2BoundsVals{}; - gap2BoundsVals[dirIdx] = gap2Hl; - gap2BoundsVals[dirOrth1Idx] = newVolume.halfLength(m_dirOrth1); - gap2BoundsVals[dirOrth2Idx] = newVolume.halfLength(m_dirOrth2); - auto gap2Bounds = - std::make_shared(gap2BoundsVals); + auto gap2Bounds = std::make_shared( + std::initializer_list< + std::pair>{ + {CuboidVolumeBounds::fromAxisDirection(m_dir), gap2Hl}, + {CuboidVolumeBounds::fromAxisDirection(m_dirOrth1), + newVolume.halfLength(m_dirOrth1)}, + {CuboidVolumeBounds::fromAxisDirection(m_dirOrth2), + newVolume.halfLength(m_dirOrth2)}}); Translation3 gap2Translation(Vector3::Unit(dirIdx) * gap2P); Transform3 gap2Transform = m_groupTransform * gap2Translation; @@ -814,12 +846,14 @@ void CuboidVolumeStack::update(std::shared_ptr volbounds, printGapDimensions(candidate, " after "); } else { ACTS_VERBOSE("~> Creating new gap volume at positive "); - std::array gap2BoundsVals{}; - gap2BoundsVals[dirIdx] = gap2Hl; - gap2BoundsVals[dirOrth1Idx] = newVolume.halfLength(m_dirOrth1); - gap2BoundsVals[dirOrth2Idx] = newVolume.halfLength(m_dirOrth2); - auto gap2Bounds = - std::make_shared(gap2BoundsVals); + auto gap2Bounds = std::make_shared( + std::initializer_list< + std::pair>{ + {CuboidVolumeBounds::fromAxisDirection(m_dir), gap2Hl}, + {CuboidVolumeBounds::fromAxisDirection(m_dirOrth1), + newVolume.halfLength(m_dirOrth1)}, + {CuboidVolumeBounds::fromAxisDirection(m_dirOrth2), + newVolume.halfLength(m_dirOrth2)}}); Translation3 gap2Translation(Vector3::Unit(dirIdx) * gap2P); Transform3 gap2Transform = m_groupTransform * gap2Translation; auto gap2 = addGapVolume(gap2Transform, std::move(gap2Bounds)); @@ -858,36 +892,4 @@ const std::vector>& CuboidVolumeStack::gaps() const { return m_gaps; } -std::ostream& operator<<(std::ostream& os, - CuboidVolumeStack::AttachmentStrategy strategy) { - switch (strategy) { - case CuboidVolumeStack::AttachmentStrategy::First: - os << "First"; - break; - case CuboidVolumeStack::AttachmentStrategy::Second: - os << "Second"; - break; - case CuboidVolumeStack::AttachmentStrategy::Midpoint: - os << "Midpoint"; - break; - case CuboidVolumeStack::AttachmentStrategy::Gap: - os << "Gap"; - break; - } - return os; -} - -std::ostream& operator<<(std::ostream& os, - CuboidVolumeStack::ResizeStrategy strategy) { - switch (strategy) { - case CuboidVolumeStack::ResizeStrategy::Expand: - os << "Expand"; - break; - case CuboidVolumeStack::ResizeStrategy::Gap: - os << "Gap"; - break; - } - return os; -} - } // namespace Acts diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index 0da0e409c0b..aef3461a57b 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -24,8 +24,8 @@ namespace Acts { CylinderContainerBlueprintNode::CylinderContainerBlueprintNode( const std::string& name, AxisDirection direction, - CylinderVolumeStack::AttachmentStrategy attachmentStrategy, - CylinderVolumeStack::ResizeStrategy resizeStrategy) + VolumeAttachmentStrategy attachmentStrategy, + VolumeResizeStrategy resizeStrategy) : m_name(name), m_direction(direction), m_attachmentStrategy(attachmentStrategy), @@ -207,7 +207,7 @@ CylinderContainerBlueprintNode& CylinderContainerBlueprintNode::setDirection( CylinderContainerBlueprintNode& CylinderContainerBlueprintNode::setAttachmentStrategy( - CylinderVolumeStack::AttachmentStrategy attachmentStrategy) { + VolumeAttachmentStrategy attachmentStrategy) { if (m_stack != nullptr) { throw std::runtime_error("Cannot change direction after build"); } @@ -217,7 +217,7 @@ CylinderContainerBlueprintNode::setAttachmentStrategy( CylinderContainerBlueprintNode& CylinderContainerBlueprintNode::setResizeStrategy( - CylinderVolumeStack::ResizeStrategy resizeStrategy) { + VolumeResizeStrategy resizeStrategy) { if (m_stack != nullptr) { throw std::runtime_error("Cannot change direction after build"); } @@ -244,12 +244,12 @@ AxisDirection CylinderContainerBlueprintNode::direction() const { return m_direction; } -CylinderVolumeStack::AttachmentStrategy +VolumeAttachmentStrategy CylinderContainerBlueprintNode::attachmentStrategy() const { return m_attachmentStrategy; } -CylinderVolumeStack::ResizeStrategy +VolumeResizeStrategy CylinderContainerBlueprintNode::resizeStrategy() const { return m_resizeStrategy; } diff --git a/Core/src/Geometry/CylinderVolumeStack.cpp b/Core/src/Geometry/CylinderVolumeStack.cpp index 61696bd61af..888216352d1 100644 --- a/Core/src/Geometry/CylinderVolumeStack.cpp +++ b/Core/src/Geometry/CylinderVolumeStack.cpp @@ -86,8 +86,8 @@ struct CylinderVolumeStack::VolumeTuple { CylinderVolumeStack::CylinderVolumeStack(std::vector& volumes, AxisDirection direction, - AttachmentStrategy strategy, - ResizeStrategy resizeStrategy, + VolumeAttachmentStrategy strategy, + VolumeResizeStrategy resizeStrategy, const Logger& logger) : Volume(initialVolume(volumes)), m_direction(direction), @@ -105,9 +105,9 @@ Volume& CylinderVolumeStack::initialVolume( return *volumes.front(); } -void CylinderVolumeStack::initializeOuterVolume(AxisDirection direction, - AttachmentStrategy strategy, - const Logger& logger) { +void CylinderVolumeStack::initializeOuterVolume( + AxisDirection direction, VolumeAttachmentStrategy strategy, + const Logger& logger) { ACTS_DEBUG("Creating CylinderVolumeStack from " << m_volumes.size() << " volumes in direction " << axisDirectionName(direction)); @@ -300,26 +300,24 @@ void CylinderVolumeStack::overlapPrint( ACTS_VERBOSE("Checking overlap between"); if (direction == AxisDirection::AxisZ) { - ss << " - " - << " z: [ " << std::setw(w) << a.minZ() << " <- " << std::setw(w) - << a.midZ() << " -> " << std::setw(w) << a.maxZ() << " ]"; + ss << " - " << " z: [ " << std::setw(w) << a.minZ() << " <- " + << std::setw(w) << a.midZ() << " -> " << std::setw(w) << a.maxZ() + << " ]"; ACTS_VERBOSE(ss.str()); ss.str(""); - ss << " - " - << " z: [ " << std::setw(w) << b.minZ() << " <- " << std::setw(w) - << b.midZ() << " -> " << std::setw(w) << b.maxZ() << " ]"; + ss << " - " << " z: [ " << std::setw(w) << b.minZ() << " <- " + << std::setw(w) << b.midZ() << " -> " << std::setw(w) << b.maxZ() + << " ]"; ACTS_VERBOSE(ss.str()); } else { - ss << " - " - << " r: [ " << std::setw(w) << a.minR() << " <-> " << std::setw(w) - << a.maxR() << " ]"; + ss << " - " << " r: [ " << std::setw(w) << a.minR() << " <-> " + << std::setw(w) << a.maxR() << " ]"; ACTS_VERBOSE(ss.str()); ss.str(""); - ss << " - " - << " r: [ " << std::setw(w) << b.minR() << " <-> " << std::setw(w) - << b.maxR() << " ]"; + ss << " - " << " r: [ " << std::setw(w) << b.minR() << " <-> " + << std::setw(w) << b.maxR() << " ]"; ACTS_VERBOSE(ss.str()); } } @@ -328,7 +326,8 @@ void CylinderVolumeStack::overlapPrint( std::vector CylinderVolumeStack::checkOverlapAndAttachInZ( std::vector& volumes, - CylinderVolumeStack::AttachmentStrategy strategy, const Logger& logger) { + VolumeAttachmentStrategy strategy, + const Logger& logger) { // Preconditions: volumes are sorted by z std::vector gapVolumes; for (std::size_t i = 0; i < volumes.size() - 1; i++) { @@ -354,7 +353,7 @@ CylinderVolumeStack::checkOverlapAndAttachInZ( ACTS_VERBOSE("Synchronizing bounds in z with strategy: " << strategy); switch (strategy) { - case AttachmentStrategy::Midpoint: { + case VolumeAttachmentStrategy::Midpoint: { ACTS_VERBOSE(" -> Strategy: Expand both volumes to midpoint"); double aZMidNew = (a.minZ() + a.maxZ()) / 2.0 + gapWidth / 4.0; @@ -389,7 +388,7 @@ CylinderVolumeStack::checkOverlapAndAttachInZ( break; } - case AttachmentStrategy::First: { + case VolumeAttachmentStrategy::First: { ACTS_VERBOSE(" -> Strategy: Expand first volume"); double aZMidNew = (a.minZ() + b.minZ()) / 2.0; double aHlZNew = (b.minZ() - a.minZ()) / 2.0; @@ -408,7 +407,7 @@ CylinderVolumeStack::checkOverlapAndAttachInZ( break; } - case AttachmentStrategy::Second: { + case VolumeAttachmentStrategy::Second: { ACTS_VERBOSE(" -> Strategy: Expand second volume"); double bZMidNew = (a.maxZ() + b.maxZ()) / 2.0; double bHlZNew = (b.maxZ() - a.maxZ()) / 2.0; @@ -426,7 +425,7 @@ CylinderVolumeStack::checkOverlapAndAttachInZ( b.updatedBounds->set(CylinderVolumeBounds::eHalfLengthZ, bHlZNew); break; } - case AttachmentStrategy::Gap: { + case VolumeAttachmentStrategy::Gap: { ACTS_VERBOSE(" -> Strategy: Create a gap volume"); double gapHlZ = (b.minZ() - a.maxZ()) / 2.0; double gapMidZ = (b.minZ() + a.maxZ()) / 2.0; @@ -463,7 +462,8 @@ CylinderVolumeStack::checkOverlapAndAttachInZ( std::vector CylinderVolumeStack::checkOverlapAndAttachInR( std::vector& volumes, - CylinderVolumeStack::AttachmentStrategy strategy, const Logger& logger) { + VolumeAttachmentStrategy strategy, + const Logger& logger) { std::vector gapVolumes; for (std::size_t i = 0; i < volumes.size() - 1; i++) { std::size_t j = i + 1; @@ -488,7 +488,7 @@ CylinderVolumeStack::checkOverlapAndAttachInR( ACTS_VERBOSE("Synchronizing bounds in r with strategy: " << strategy); switch (strategy) { - case AttachmentStrategy::Midpoint: { + case VolumeAttachmentStrategy::Midpoint: { ACTS_VERBOSE(" -> Strategy: Expand both volumes to midpoint"); a.set({{CylinderVolumeBounds::eMaxR, a.maxR() + gapWidth / 2.0}}); @@ -496,21 +496,21 @@ CylinderVolumeStack::checkOverlapAndAttachInR( break; } - case AttachmentStrategy::First: { + case VolumeAttachmentStrategy::First: { ACTS_VERBOSE(" -> Strategy: Expand first volume"); a.set({{CylinderVolumeBounds::eMaxR, b.minR()}}); break; } - case AttachmentStrategy::Second: { + case VolumeAttachmentStrategy::Second: { ACTS_VERBOSE(" -> Strategy: Expand second volume"); b.set({{CylinderVolumeBounds::eMinR, a.maxR()}}); break; } - case AttachmentStrategy::Gap: { + case VolumeAttachmentStrategy::Gap: { ACTS_VERBOSE(" -> Strategy: Create a gap volume"); auto gapBounds = std::make_shared( @@ -789,7 +789,7 @@ void CylinderVolumeStack::update(std::shared_ptr volbounds, if (same(newHlZ, oldHlZ)) { ACTS_VERBOSE("Halflength z is the same, no z resize needed"); } else { - if (m_resizeStrategy == ResizeStrategy::Expand) { + if (m_resizeStrategy == VolumeResizeStrategy::Expand) { if (newMinZ < oldMinZ) { ACTS_VERBOSE("Expanding first volume to new z bounds"); @@ -823,7 +823,7 @@ void CylinderVolumeStack::update(std::shared_ptr volbounds, last.setLocalTransform(Transform3{Translation3{0, 0, newMidZLast}}, m_groupTransform); } - } else if (m_resizeStrategy == ResizeStrategy::Gap) { + } else if (m_resizeStrategy == VolumeResizeStrategy::Gap) { ACTS_VERBOSE("Creating gap volumes to fill the new z bounds"); auto printGapDimensions = [&](const VolumeTuple& gap, @@ -948,7 +948,7 @@ void CylinderVolumeStack::update(std::shared_ptr volbounds, if (oldMinR == newMinR && oldMaxR == newMaxR) { ACTS_VERBOSE("Radii are the same, no r resize needed"); } else { - if (m_resizeStrategy == ResizeStrategy::Expand) { + if (m_resizeStrategy == VolumeResizeStrategy::Expand) { if (oldMinR > newMinR) { // expand innermost volume auto& first = volumeTuples.front(); @@ -971,7 +971,7 @@ void CylinderVolumeStack::update(std::shared_ptr volbounds, << last.minR() << " <-> " << last.maxR() << " ]"); } - } else if (m_resizeStrategy == ResizeStrategy::Gap) { + } else if (m_resizeStrategy == VolumeResizeStrategy::Gap) { auto printGapDimensions = [&](const VolumeTuple& gap, const std::string& prefix = "") { ACTS_VERBOSE(" -> gap" << prefix << ": [ " << gap.minZ() << " <- " @@ -1092,36 +1092,4 @@ const std::vector>& CylinderVolumeStack::gaps() const { return m_gaps; } -std::ostream& operator<<(std::ostream& os, - CylinderVolumeStack::AttachmentStrategy strategy) { - switch (strategy) { - case CylinderVolumeStack::AttachmentStrategy::First: - os << "First"; - break; - case CylinderVolumeStack::AttachmentStrategy::Second: - os << "Second"; - break; - case CylinderVolumeStack::AttachmentStrategy::Midpoint: - os << "Midpoint"; - break; - case CylinderVolumeStack::AttachmentStrategy::Gap: - os << "Gap"; - break; - } - return os; -} - -std::ostream& operator<<(std::ostream& os, - CylinderVolumeStack::ResizeStrategy strategy) { - switch (strategy) { - case CylinderVolumeStack::ResizeStrategy::Expand: - os << "Expand"; - break; - case CylinderVolumeStack::ResizeStrategy::Gap: - os << "Gap"; - break; - } - return os; -} - } // namespace Acts diff --git a/Core/src/Geometry/detail/VolumeAttachmentStrategy.cpp b/Core/src/Geometry/detail/VolumeAttachmentStrategy.cpp new file mode 100644 index 00000000000..8f6c55e9884 --- /dev/null +++ b/Core/src/Geometry/detail/VolumeAttachmentStrategy.cpp @@ -0,0 +1,30 @@ +// 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/. + +#include "Acts/Geometry/detail/VolumeAttachmentStrategy.hpp" + +namespace Acts { +std::ostream& operator<<(std::ostream& os, VolumeAttachmentStrategy strategy) { + switch (strategy) { + case VolumeAttachmentStrategy::First: + os << "First"; + break; + case VolumeAttachmentStrategy::Second: + os << "Second"; + break; + case VolumeAttachmentStrategy::Midpoint: + os << "Midpoint"; + break; + case VolumeAttachmentStrategy::Gap: + os << "Gap"; + break; + } + return os; +} + +} // namespace Acts \ No newline at end of file diff --git a/Core/src/Geometry/detail/VolumeResizeStrategy.cpp b/Core/src/Geometry/detail/VolumeResizeStrategy.cpp new file mode 100644 index 00000000000..bb289d8ce2f --- /dev/null +++ b/Core/src/Geometry/detail/VolumeResizeStrategy.cpp @@ -0,0 +1,25 @@ +// 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/. + +#include "Acts/Geometry/detail/VolumeResizeStrategy.hpp" + +namespace Acts { + +std::ostream& operator<<(std::ostream& os, VolumeResizeStrategy strategy) { + switch (strategy) { + case VolumeResizeStrategy::Expand: + os << "Expand"; + break; + case VolumeResizeStrategy::Gap: + os << "Gap"; + break; + } + return os; +} + +} // namespace Acts diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index c0ebdd4f5e8..0fc16095e21 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -15,6 +15,8 @@ #include "Acts/Geometry/LayerBlueprintNode.hpp" #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" +#include "Acts/Geometry/detail/VolumeAttachmentStrategy.hpp" +#include "Acts/Geometry/detail/VolumeResizeStrategy.hpp" #include "Acts/Navigation/NavigationStream.hpp" #include "Acts/Plugins/Python/Utilities.hpp" #include "Acts/Utilities/AxisDefinitions.hpp" @@ -339,13 +341,10 @@ void addBlueprint(Context& ctx) { std::shared_ptr>( m, "CylinderContainerBlueprintNode") .def(py::init(), + VolumeAttachmentStrategy, VolumeResizeStrategy>(), py::arg("name"), py::arg("direction"), - py::arg("attachmentStrategy") = - CylinderVolumeStack::AttachmentStrategy::Gap, - py::arg("resizeStrategy") = - CylinderVolumeStack::ResizeStrategy::Gap) + py::arg("attachmentStrategy") = VolumeAttachmentStrategy::Gap, + py::arg("resizeStrategy") = VolumeResizeStrategy::Gap) .def_property( "attachmentStrategy", &Acts::CylinderContainerBlueprintNode::attachmentStrategy, diff --git a/Examples/Python/src/Geometry.cpp b/Examples/Python/src/Geometry.cpp index ec15814e940..1cc85e4583d 100644 --- a/Examples/Python/src/Geometry.cpp +++ b/Examples/Python/src/Geometry.cpp @@ -34,6 +34,8 @@ #include "Acts/Geometry/TrackingGeometry.hpp" #include "Acts/Geometry/Volume.hpp" #include "Acts/Geometry/VolumeBounds.hpp" +#include "Acts/Geometry/detail/VolumeAttachmentStrategy.hpp" +#include "Acts/Geometry/detail/VolumeResizeStrategy.hpp" #include "Acts/Material/ISurfaceMaterial.hpp" #include "Acts/Plugins/Python/Utilities.hpp" #include "Acts/Surfaces/Surface.hpp" @@ -294,16 +296,15 @@ void addGeometry(Context& ctx) { { auto cylStack = py::class_(m, "CylinderVolumeStack"); - py::enum_(cylStack, - "AttachmentStrategy") - .value("Gap", CylinderVolumeStack::AttachmentStrategy::Gap) - .value("First", CylinderVolumeStack::AttachmentStrategy::First) - .value("Second", CylinderVolumeStack::AttachmentStrategy::Second) - .value("Midpoint", CylinderVolumeStack::AttachmentStrategy::Midpoint); + py::enum_(cylStack, "AttachmentStrategy") + .value("Gap", VolumeAttachmentStrategy::Gap) + .value("First", VolumeAttachmentStrategy::First) + .value("Second", VolumeAttachmentStrategy::Second) + .value("Midpoint", VolumeAttachmentStrategy::Midpoint); - py::enum_(cylStack, "ResizeStrategy") - .value("Gap", CylinderVolumeStack::ResizeStrategy::Gap) - .value("Expand", CylinderVolumeStack::ResizeStrategy::Expand); + py::enum_(cylStack, "ResizeStrategy") + .value("Gap", VolumeResizeStrategy::Gap) + .value("Expand", VolumeResizeStrategy::Expand); } addBlueprint(ctx); diff --git a/Tests/UnitTests/Core/Geometry/BlueprintApiTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintApiTests.cpp index dd42e620a17..1617efa50d2 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintApiTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintApiTests.cpp @@ -23,6 +23,8 @@ #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" #include "Acts/Geometry/TrackingGeometry.hpp" #include "Acts/Geometry/TrackingVolume.hpp" +#include "Acts/Geometry/detail/VolumeAttachmentStrategy.hpp" +#include "Acts/Geometry/detail/VolumeResizeStrategy.hpp" #include "Acts/Navigation/INavigationPolicy.hpp" #include "Acts/Navigation/NavigationStream.hpp" #include "Acts/Surfaces/RectangleBounds.hpp" @@ -271,13 +273,12 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { mat.addCylinderContainer("Detector", AxisDirection::AxisR, [&](auto& det) { det.addCylinderContainer("Pixel", AxisDirection::AxisZ, [&](auto& cyl) { - cyl.setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap) - .setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); + cyl.setAttachmentStrategy(VolumeAttachmentStrategy::Gap) + .setResizeStrategy(VolumeResizeStrategy::Gap); cyl.addCylinderContainer( "PixelNegativeEndcap", AxisDirection::AxisZ, [&](auto& ec) { - ec.setAttachmentStrategy( - CylinderVolumeStack::AttachmentStrategy::Gap); + ec.setAttachmentStrategy(VolumeAttachmentStrategy::Gap); auto makeLayer = [&](const Transform3& trf, auto& layer) { std::vector> surfaces; @@ -308,9 +309,8 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { cyl.addCylinderContainer( "PixelBarrel", AxisDirection::AxisR, [&](auto& brl) { - brl.setAttachmentStrategy( - CylinderVolumeStack::AttachmentStrategy::Gap) - .setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); + brl.setAttachmentStrategy(VolumeAttachmentStrategy::Gap) + .setResizeStrategy(VolumeResizeStrategy::Gap); auto makeLayer = [&](const std::string& name, double r, std::size_t nStaves, int nSensorsPerStave) { @@ -343,7 +343,7 @@ BOOST_AUTO_TEST_CASE(NodeApiTestContainers) { auto& ec = cyl.addCylinderContainer("PixelPosWrapper", AxisDirection::AxisR); - ec.setResizeStrategy(CylinderVolumeStack::ResizeStrategy::Gap); + ec.setResizeStrategy(VolumeResizeStrategy::Gap); ec.addStaticVolume(std::make_unique( base * Translation3{Vector3{0, 0, 600_mm}}, std::make_shared(150_mm, 390_mm, 200_mm), diff --git a/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp index 6d7a1a30fb9..33973661c9a 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp @@ -22,6 +22,7 @@ #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" #include "Acts/Geometry/TrackingVolume.hpp" +#include "Acts/Geometry/detail/VolumeAttachmentStrategy.hpp" #include "Acts/Material/BinnedSurfaceMaterial.hpp" #include "Acts/Material/ProtoSurfaceMaterial.hpp" #include "Acts/Surfaces/RectangleBounds.hpp" @@ -214,7 +215,7 @@ BOOST_AUTO_TEST_CASE(CylinderContainer) { auto root = std::make_unique(cfg); auto& cyl = root->addCylinderContainer("Container", AxisDirection::AxisZ); - cyl.setAttachmentStrategy(CylinderVolumeStack::AttachmentStrategy::Gap); + cyl.setAttachmentStrategy(VolumeAttachmentStrategy::Gap); double z0 = -200_mm; double hlZ = 30_mm; diff --git a/Tests/UnitTests/Core/Geometry/CuboidVolumeBoundsTests.cpp b/Tests/UnitTests/Core/Geometry/CuboidVolumeBoundsTests.cpp index 79688dad718..126a803ca73 100644 --- a/Tests/UnitTests/Core/Geometry/CuboidVolumeBoundsTests.cpp +++ b/Tests/UnitTests/Core/Geometry/CuboidVolumeBoundsTests.cpp @@ -38,6 +38,12 @@ BOOST_AUTO_TEST_CASE(CuboidVolumeConstruction) { // Test Construction CuboidVolumeBounds box(hx, hy, hz); + // Test initilizer list construction + CuboidVolumeBounds init( + {{CuboidVolumeBounds::BoundValues::eHalfLengthX, hx}, + {CuboidVolumeBounds::BoundValues::eHalfLengthY, hy}, + {CuboidVolumeBounds::BoundValues::eHalfLengthZ, hz}}); + // Test copy construction CuboidVolumeBounds copied(box); BOOST_CHECK_EQUAL(box, copied); @@ -71,6 +77,11 @@ BOOST_AUTO_TEST_CASE(CuboidVolumeException) { BOOST_CHECK_THROW(CuboidVolumeBounds(hx, -hy, -hz), std::logic_error); // Other iterations : all BOOST_CHECK_THROW(CuboidVolumeBounds(-hx, -hy, -hz), std::logic_error); + // Initilizer list with missing bound values + BOOST_CHECK_THROW( + CuboidVolumeBounds({{CuboidVolumeBounds::BoundValues::eHalfLengthX, hx}, + {CuboidVolumeBounds::BoundValues::eHalfLengthZ, hz}}), + std::logic_error); } BOOST_AUTO_TEST_CASE(CuboidVolumeProperties) { diff --git a/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp b/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp index cd24dd7b1a9..1ff76615757 100644 --- a/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp +++ b/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp @@ -19,6 +19,8 @@ #include "Acts/Definitions/Units.hpp" #include "Acts/Geometry/CuboidVolumeBounds.hpp" #include "Acts/Geometry/CuboidVolumeStack.hpp" +#include "Acts/Geometry/detail/VolumeAttachmentStrategy.hpp" +#include "Acts/Geometry/detail/VolumeResizeStrategy.hpp" #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp" #include "Acts/Utilities/AxisDefinitions.hpp" #include "Acts/Utilities/Logger.hpp" @@ -26,7 +28,9 @@ #include "Acts/Utilities/Zip.hpp" #include +#include #include +#include using namespace Acts::UnitLiterals; @@ -46,16 +50,16 @@ struct Fixture { BOOST_FIXTURE_TEST_SUITE(Geometry, Fixture) -static const std::vector strategies = { - CuboidVolumeStack::AttachmentStrategy::Gap, - CuboidVolumeStack::AttachmentStrategy::First, - CuboidVolumeStack::AttachmentStrategy::Second, - CuboidVolumeStack::AttachmentStrategy::Midpoint, +static const std::vector strategies = { + VolumeAttachmentStrategy::Gap, + VolumeAttachmentStrategy::First, + VolumeAttachmentStrategy::Second, + VolumeAttachmentStrategy::Midpoint, }; -static const std::vector resizeStrategies = { - CuboidVolumeStack::ResizeStrategy::Expand, - CuboidVolumeStack::ResizeStrategy::Gap, +static const std::vector resizeStrategies = { + VolumeResizeStrategy::Expand, + VolumeResizeStrategy::Gap, }; BOOST_AUTO_TEST_SUITE(CuboidVolumeStackTest) @@ -76,34 +80,32 @@ BOOST_DATA_TEST_CASE(BaselineLocal, angle, rotate, shift, offset, strategy, dir) { double halfDir = 400_mm; - std::size_t dirIdx = static_cast(dir); - std::size_t dirOrth1Idx = (dirIdx + 1) % 3; - std::size_t dirOrth2Idx = (dirIdx + 2) % 3; + auto [dirOrth1, dirOrth2] = CuboidVolumeStack::getOrthogonalAxes(dir); - auto dirOrth1 = static_cast(dirOrth1Idx); - auto dirOrth2 = static_cast(dirOrth2Idx); + auto dirIdx = CuboidVolumeStack::axisToIndex(dir); + auto dirOrth1Idx = CuboidVolumeStack::axisToIndex(dirOrth1); - auto boundDir = static_cast(dir); - auto boundDirOrth1 = static_cast(dirOrth1); - auto boundDirOrth2 = static_cast(dirOrth2); + auto boundDir = CuboidVolumeBounds::fromAxisDirection(dir); + auto boundDirOrth1 = CuboidVolumeBounds::fromAxisDirection(dirOrth1); + auto boundDirOrth2 = CuboidVolumeBounds::fromAxisDirection(dirOrth2); - std::array bounds1Vals{}; - bounds1Vals.at(boundDir) = halfDir; - bounds1Vals.at(boundDirOrth1) = 100_mm; - bounds1Vals.at(boundDirOrth2) = 400_mm; - auto bounds1 = std::make_shared(bounds1Vals); + auto bounds1 = std::make_shared( + std::initializer_list>{ + {boundDir, halfDir}, + {boundDirOrth1, 100_mm}, + {boundDirOrth2, 400_mm}}); - std::array bounds2Vals{}; - bounds2Vals.at(boundDir) = halfDir; - bounds2Vals.at(boundDirOrth1) = 200_mm; - bounds2Vals.at(boundDirOrth2) = 600_mm; - auto bounds2 = std::make_shared(bounds2Vals); + auto bounds2 = std::make_shared( + std::initializer_list>{ + {boundDir, halfDir}, + {boundDirOrth1, 200_mm}, + {boundDirOrth2, 600_mm}}); - std::array bounds3Vals{}; - bounds3Vals.at(boundDir) = halfDir; - bounds3Vals.at(boundDirOrth1) = 300_mm; - bounds3Vals.at(boundDirOrth2) = 500_mm; - auto bounds3 = std::make_shared(bounds3Vals); + auto bounds3 = std::make_shared( + std::initializer_list>{ + {boundDir, halfDir}, + {boundDirOrth1, 300_mm}, + {boundDirOrth2, 500_mm}}); Transform3 base = AngleAxis3(angle * 1_degree, Vector3::Unit(dirOrth1Idx)) * Translation3(offset); @@ -129,20 +131,19 @@ BOOST_DATA_TEST_CASE(BaselineLocal, std::transform(volumes.begin(), volumes.end(), std::back_inserter(originalBounds), [](const auto& vol) { const auto* res = - static_cast(&vol->volumeBounds()); + dynamic_cast(&vol->volumeBounds()); throw_assert(res != nullptr, ""); return *res; }); if (shift < 1.0) { - BOOST_CHECK_THROW( - CuboidVolumeStack(volumes, dir, strategy, - CuboidVolumeStack::ResizeStrategy::Gap, *logger), - std::invalid_argument); + BOOST_CHECK_THROW(CuboidVolumeStack(volumes, dir, strategy, + VolumeResizeStrategy::Gap, *logger), + std::invalid_argument); return; } - CuboidVolumeStack stack(volumes, dir, strategy, - CuboidVolumeStack::ResizeStrategy::Gap, *logger); + CuboidVolumeStack stack(volumes, dir, strategy, VolumeResizeStrategy::Gap, + *logger); auto stackBounds = dynamic_cast(&stack.volumeBounds()); @@ -187,7 +188,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, BOOST_CHECK_EQUAL(newBounds->get(boundDir), bounds.get(boundDir)); } } else { - if (strategy == CuboidVolumeStack::AttachmentStrategy::Gap) { + if (strategy == VolumeAttachmentStrategy::Gap) { // Gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 5); auto gap1 = volumes.at(1); @@ -231,7 +232,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, BOOST_CHECK_EQUAL(vol1->transform().matrix(), transform1.matrix()); BOOST_CHECK_EQUAL(vol2->transform().matrix(), transform2.matrix()); BOOST_CHECK_EQUAL(vol3->transform().matrix(), transform3.matrix()); - } else if (strategy == CuboidVolumeStack::AttachmentStrategy::First) { + } else if (strategy == VolumeAttachmentStrategy::First) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -266,7 +267,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Transform3 expectedTransform3 = base * expectedTranslation3; CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(), expectedTransform3.matrix(), 1e-10, 1e-14); - } else if (strategy == CuboidVolumeStack::AttachmentStrategy::Second) { + } else if (strategy == VolumeAttachmentStrategy::Second) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -301,7 +302,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Transform3 expectedTransform3 = base * expectedTranslation3; CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(), expectedTransform3.matrix(), 1e-10, 1e-14); - } else if (strategy == CuboidVolumeStack::AttachmentStrategy::Midpoint) { + } else if (strategy == VolumeAttachmentStrategy::Midpoint) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -387,11 +388,10 @@ BOOST_DATA_TEST_CASE(BaselineGlobal, volumesAxisDirection.end()); CuboidVolumeStack stackOrientation(volumesOrientation, orientation, strategy, - CuboidVolumeStack::ResizeStrategy::Gap, - *logger); - CuboidVolumeStack stackAxisDirection( - volumesAxisDirection, AxisDirection::AxisZ, strategy, - CuboidVolumeStack::ResizeStrategy::Gap, *logger); + VolumeResizeStrategy::Gap, *logger); + CuboidVolumeStack stackAxisDirection(volumesAxisDirection, + AxisDirection::AxisZ, strategy, + VolumeResizeStrategy::Gap, *logger); auto stackBoundsOrientation = dynamic_cast(&stackOrientation.volumeBounds()); @@ -419,34 +419,31 @@ BOOST_DATA_TEST_CASE(Asymmetric, double halfDir3 = 400_mm; double pDir3 = 850_mm; - std::size_t dirIdx = static_cast(dir); - std::size_t dirOrth1Idx = (dirIdx + 1) % 3; - std::size_t dirOrth2Idx = (dirIdx + 2) % 3; + auto [dirOrth1, dirOrth2] = CuboidVolumeStack::getOrthogonalAxes(dir); - auto dirOrth1 = static_cast(dirOrth1Idx); - auto dirOrth2 = static_cast(dirOrth2Idx); + auto dirIdx = CuboidVolumeStack::axisToIndex(dir); - auto boundDir = static_cast(dir); - auto boundDirOrth1 = static_cast(dirOrth1); - auto boundDirOrth2 = static_cast(dirOrth2); + auto boundDir = CuboidVolumeBounds::fromAxisDirection(dir); + auto boundDirOrth1 = CuboidVolumeBounds::fromAxisDirection(dirOrth1); + auto boundDirOrth2 = CuboidVolumeBounds::fromAxisDirection(dirOrth2); - std::array bounds1Vals{}; - bounds1Vals[dirIdx] = halfDir1; - bounds1Vals[dirOrth1Idx] = 100_mm; - bounds1Vals[dirOrth2Idx] = 400_mm; - auto bounds1 = std::make_shared(bounds1Vals); + auto bounds1 = std::make_shared( + std::initializer_list>{ + {boundDir, halfDir1}, + {boundDirOrth1, 100_mm}, + {boundDirOrth2, 400_mm}}); - std::array bounds2Vals{}; - bounds2Vals[dirIdx] = halfDir2; - bounds2Vals[dirOrth1Idx] = 200_mm; - bounds2Vals[dirOrth2Idx] = 600_mm; - auto bounds2 = std::make_shared(bounds2Vals); + auto bounds2 = std::make_shared( + std::initializer_list>{ + {boundDir, halfDir2}, + {boundDirOrth1, 200_mm}, + {boundDirOrth2, 600_mm}}); - std::array bounds3Vals{}; - bounds3Vals[dirIdx] = halfDir3; - bounds3Vals[dirOrth1Idx] = 300_mm; - bounds3Vals[dirOrth2Idx] = 500_mm; - auto bounds3 = std::make_shared(bounds3Vals); + auto bounds3 = std::make_shared( + std::initializer_list>{ + {boundDir, halfDir3}, + {boundDirOrth1, 300_mm}, + {boundDirOrth2, 500_mm}}); Translation3 translation1(Vector3::Unit(dirIdx) * pDir1); Transform3 transform1(translation1); @@ -462,9 +459,8 @@ BOOST_DATA_TEST_CASE(Asymmetric, std::vector volumes = {vol2.get(), vol1.get(), vol3.get()}; - CuboidVolumeStack stack(volumes, dir, - CuboidVolumeStack::AttachmentStrategy::Gap, - CuboidVolumeStack::ResizeStrategy::Gap, *logger); + CuboidVolumeStack stack(volumes, dir, VolumeAttachmentStrategy::Gap, + VolumeResizeStrategy::Gap, *logger); BOOST_CHECK_EQUAL(volumes.size(), 5); auto stackBounds = @@ -498,34 +494,32 @@ BOOST_DATA_TEST_CASE(UpdateStack, angle, offset, zshift, strategy, dir) { double halfDir = 400_mm; - std::size_t dirIdx = static_cast(dir); - std::size_t dirOrth1Idx = (dirIdx + 1) % 3; - std::size_t dirOrth2Idx = (dirIdx + 2) % 3; + auto [dirOrth1, dirOrth2] = CuboidVolumeStack::getOrthogonalAxes(dir); - auto dirOrth1 = static_cast(dirOrth1Idx); - auto dirOrth2 = static_cast(dirOrth2Idx); + auto dirIdx = CuboidVolumeStack::axisToIndex(dir); + auto dirOrth1Idx = CuboidVolumeStack::axisToIndex(dirOrth1); - auto boundDir = static_cast(dir); - auto boundDirOrth1 = static_cast(dirOrth1); - auto boundDirOrth2 = static_cast(dirOrth2); + auto boundDir = CuboidVolumeBounds::fromAxisDirection(dir); + auto boundDirOrth1 = CuboidVolumeBounds::fromAxisDirection(dirOrth1); + auto boundDirOrth2 = CuboidVolumeBounds::fromAxisDirection(dirOrth2); - std::array bounds1Vals{}; - bounds1Vals[dirIdx] = halfDir; - bounds1Vals[dirOrth1Idx] = 100_mm; - bounds1Vals[dirOrth2Idx] = 600_mm; - auto bounds1 = std::make_shared(bounds1Vals); + auto bounds1 = std::make_shared( + std::initializer_list>{ + {boundDir, halfDir}, + {boundDirOrth1, 100_mm}, + {boundDirOrth2, 600_mm}}); - std::array bounds2Vals{}; - bounds2Vals[dirIdx] = halfDir; - bounds2Vals[dirOrth1Idx] = 100_mm; - bounds2Vals[dirOrth2Idx] = 600_mm; - auto bounds2 = std::make_shared(bounds2Vals); + auto bounds2 = std::make_shared( + std::initializer_list>{ + {boundDir, halfDir}, + {boundDirOrth1, 100_mm}, + {boundDirOrth2, 600_mm}}); - std::array bounds3Vals{}; - bounds3Vals[dirIdx] = halfDir; - bounds3Vals[dirOrth1Idx] = 100_mm; - bounds3Vals[dirOrth2Idx] = 600_mm; - auto bounds3 = std::make_shared(bounds3Vals); + auto bounds3 = std::make_shared( + std::initializer_list>{ + {boundDir, halfDir}, + {boundDirOrth1, 100_mm}, + {boundDirOrth2, 600_mm}}); Vector3 shift = Vector3::Unit(dirIdx) * zshift; Transform3 base = AngleAxis3(angle * 1_degree, Vector3::Unit(dirOrth1Idx)) * @@ -548,11 +542,10 @@ BOOST_DATA_TEST_CASE(UpdateStack, std::vector originalTransforms = {transform1, transform2, transform3}; - CuboidVolumeStack stack( - volumes, dir, - CuboidVolumeStack::AttachmentStrategy::Gap, // should not make a - // difference - strategy, *logger); + CuboidVolumeStack stack(volumes, dir, + VolumeAttachmentStrategy::Gap, // should not make a + // difference + strategy, *logger); const auto* originalBounds = dynamic_cast(&stack.volumeBounds()); @@ -679,7 +672,7 @@ BOOST_DATA_TEST_CASE(UpdateStack, BOOST_CHECK_EQUAL(updatedBounds->get(boundDirOrth1), 700_mm); BOOST_CHECK_EQUAL(updatedBounds->get(boundDirOrth2), 700_mm); - if (strategy == CuboidVolumeStack::ResizeStrategy::Expand) { + if (strategy == VolumeResizeStrategy::Expand) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -708,7 +701,7 @@ BOOST_DATA_TEST_CASE(UpdateStack, Transform3 expectedTransform3 = base * expectedTranslation3; BOOST_CHECK_EQUAL(vol3->transform().matrix(), expectedTransform3.matrix()); - } else if (strategy == CuboidVolumeStack::ResizeStrategy::Gap) { + } else if (strategy == VolumeResizeStrategy::Gap) { // Gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 5); @@ -751,34 +744,33 @@ BOOST_DATA_TEST_CASE(UpdateStack, BOOST_DATA_TEST_CASE( UpdateStackOneSided, ((boost::unit_test::data::make(-1.0, 1.0) ^ - boost::unit_test::data::make(CuboidVolumeStack::ResizeStrategy::Gap, - CuboidVolumeStack::ResizeStrategy::Expand)) * + boost::unit_test::data::make(VolumeResizeStrategy::Gap, + VolumeResizeStrategy::Expand)) * boost::unit_test::data::make(Acts::AxisDirection::AxisX, Acts::AxisDirection::AxisY, Acts::AxisDirection::AxisZ)), f, strategy, dir) { - std::size_t dirIdx = static_cast(dir); - std::size_t dirOrth1Idx = (dirIdx + 1) % 3; - std::size_t dirOrth2Idx = (dirIdx + 2) % 3; + auto [dirOrth1, dirOrth2] = CuboidVolumeStack::getOrthogonalAxes(dir); - auto dirOrth1 = static_cast(dirOrth1Idx); - auto dirOrth2 = static_cast(dirOrth2Idx); + auto dirIdx = CuboidVolumeStack::axisToIndex(dir); + auto dirOrth1Idx = CuboidVolumeStack::axisToIndex(dirOrth1); + auto dirOrth2Idx = CuboidVolumeStack::axisToIndex(dirOrth2); - auto boundDir = static_cast(dir); - auto boundDirOrth1 = static_cast(dirOrth1); - auto boundDirOrth2 = static_cast(dirOrth2); + auto boundDir = CuboidVolumeBounds::fromAxisDirection(dir); + auto boundDirOrth1 = CuboidVolumeBounds::fromAxisDirection(dirOrth1); + auto boundDirOrth2 = CuboidVolumeBounds::fromAxisDirection(dirOrth2); - std::array bounds1Vals{}; - bounds1Vals[dirIdx] = 400_mm; - bounds1Vals[dirOrth1Idx] = 100_mm; - bounds1Vals[dirOrth2Idx] = 300_mm; - auto bounds1 = std::make_shared(bounds1Vals); + auto bounds1 = std::make_shared( + std::initializer_list>{ + {boundDir, 400_mm}, + {boundDirOrth1, 100_mm}, + {boundDirOrth2, 300_mm}}); - std::array bounds2Vals{}; - bounds2Vals[dirIdx] = 400_mm; - bounds2Vals[dirOrth1Idx] = 100_mm; - bounds2Vals[dirOrth2Idx] = 300_mm; - auto bounds2 = std::make_shared(bounds2Vals); + auto bounds2 = std::make_shared( + std::initializer_list>{ + {boundDir, 400_mm}, + {boundDirOrth1, 100_mm}, + {boundDirOrth2, 300_mm}}); auto trf = Transform3::Identity(); @@ -792,8 +784,7 @@ BOOST_DATA_TEST_CASE( std::vector volumes = {vol1.get(), vol2.get()}; - CuboidVolumeStack stack{volumes, dir, - CuboidVolumeStack::AttachmentStrategy::Gap, strategy, + CuboidVolumeStack stack{volumes, dir, VolumeAttachmentStrategy::Gap, strategy, *logger}; const auto* originalBounds = dynamic_cast(&stack.volumeBounds()); @@ -857,7 +848,7 @@ BOOST_DATA_TEST_CASE( BOOST_CHECK_EQUAL(volBounds->get(boundDirOrth2), 300_mm); } - if (strategy == CuboidVolumeStack::ResizeStrategy::Expand) { + if (strategy == VolumeResizeStrategy::Expand) { // No gaps were added, there was one gap initially BOOST_CHECK_EQUAL(volumes.size(), 3); const Volume* vol = nullptr; @@ -874,7 +865,7 @@ BOOST_DATA_TEST_CASE( BOOST_REQUIRE(volBounds != nullptr); BOOST_CHECK_EQUAL(volBounds->get(boundDir), 450_mm); BOOST_CHECK_EQUAL(vol->center()[dirIdx], f * 550_mm); - } else if (strategy == CuboidVolumeStack::ResizeStrategy::Gap) { + } else if (strategy == VolumeResizeStrategy::Gap) { // One gap volume was added BOOST_CHECK_EQUAL(volumes.size(), 4); @@ -926,42 +917,32 @@ BOOST_DATA_TEST_CASE(ResizeGapMultiple, Acts::AxisDirection::AxisY, Acts::AxisDirection::AxisZ), dir) { - std::size_t dirIdx = static_cast(dir); - std::size_t dirOrth1Idx = (dirIdx + 1) % 3; - std::size_t dirOrth2Idx = (dirIdx + 2) % 3; - - auto dirOrth1 = static_cast(dirOrth1Idx); - auto dirOrth2 = static_cast(dirOrth2Idx); + auto [dirOrth1, dirOrth2] = CuboidVolumeStack::getOrthogonalAxes(dir); - auto boundDir = static_cast(dir); - auto boundDirOrth1 = static_cast(dirOrth1); - auto boundDirOrth2 = static_cast(dirOrth2); + auto dirIdx = CuboidVolumeStack::axisToIndex(dir); - std::array boundsVals{}; - boundsVals[dirIdx] = 100; - boundsVals[dirOrth1Idx] = 70; - boundsVals[dirOrth2Idx] = 100; - auto bounds = std::make_shared(boundsVals); + auto boundDir = CuboidVolumeBounds::fromAxisDirection(dir); + auto boundDirOrth1 = CuboidVolumeBounds::fromAxisDirection(dirOrth1); + auto boundDirOrth2 = CuboidVolumeBounds::fromAxisDirection(dirOrth2); + auto bounds = std::make_shared( + std::initializer_list>{ + {boundDir, 100}, {boundDirOrth1, 70}, {boundDirOrth2, 100}}); Transform3 trf = Transform3::Identity(); Volume vol{trf, bounds}; BOOST_TEST_CONTEXT("Positive") { std::vector volumes = {&vol}; - CuboidVolumeStack stack(volumes, dir, - CuboidVolumeStack::AttachmentStrategy::Gap, - CuboidVolumeStack::ResizeStrategy::Gap, *logger); + CuboidVolumeStack stack(volumes, dir, VolumeAttachmentStrategy::Gap, + VolumeResizeStrategy::Gap, *logger); BOOST_CHECK_EQUAL(volumes.size(), 1); BOOST_CHECK(stack.gaps().empty()); - std::array newBounds1Vals{}; - newBounds1Vals[dirIdx] = 200; - newBounds1Vals[dirOrth1Idx] = 70; - newBounds1Vals[dirOrth2Idx] = 100; - auto newBounds1 = std::make_shared(newBounds1Vals); - newBounds1->set( - {{boundDir, 200}, {boundDirOrth1, 70}, {boundDirOrth2, 100}}); + auto newBounds1 = std::make_shared( + std::initializer_list< + std::pair>{ + {boundDir, 200}, {boundDirOrth1, 70}, {boundDirOrth2, 100}}); stack.update(newBounds1, trf * Translation3{Vector3::Unit(dirIdx) * 100}, *logger); BOOST_CHECK_EQUAL(volumes.size(), 2); @@ -973,13 +954,10 @@ BOOST_DATA_TEST_CASE(ResizeGapMultiple, BOOST_REQUIRE_NE(updatedBounds, nullptr); BOOST_CHECK_EQUAL(updatedBounds->get(boundDir), 100.0); - std::array newBounds2Vals{}; - newBounds2Vals[dirIdx] = 300; - newBounds2Vals[dirOrth1Idx] = 70; - newBounds2Vals[dirOrth2Idx] = 100; - auto newBounds2 = std::make_shared(newBounds2Vals); - newBounds2->set( - {{boundDir, 300}, {boundDirOrth1, 70}, {boundDirOrth2, 100}}); + auto newBounds2 = std::make_shared( + std::initializer_list< + std::pair>{ + {boundDir, 300}, {boundDirOrth1, 70}, {boundDirOrth2, 100}}); stack.update(newBounds2, trf * Translation3{Vector3::Unit(dirIdx) * 200}, *logger); @@ -996,20 +974,16 @@ BOOST_DATA_TEST_CASE(ResizeGapMultiple, BOOST_TEST_CONTEXT("Negative") { std::vector volumes = {&vol}; - CuboidVolumeStack stack(volumes, dir, - CuboidVolumeStack::AttachmentStrategy::Gap, - CuboidVolumeStack::ResizeStrategy::Gap, *logger); + CuboidVolumeStack stack(volumes, dir, VolumeAttachmentStrategy::Gap, + VolumeResizeStrategy::Gap, *logger); BOOST_CHECK_EQUAL(volumes.size(), 1); BOOST_CHECK(stack.gaps().empty()); - std::array newBounds1Vals{}; - newBounds1Vals[dirIdx] = 200; - newBounds1Vals[dirOrth1Idx] = 70; - newBounds1Vals[dirOrth2Idx] = 100; - auto newBounds1 = std::make_shared(newBounds1Vals); - newBounds1->set( - {{boundDir, 200}, {boundDirOrth1, 70}, {boundDirOrth2, 100}}); + auto newBounds1 = std::make_shared( + std::initializer_list< + std::pair>{ + {boundDir, 200}, {boundDirOrth1, 70}, {boundDirOrth2, 100}}); stack.update(newBounds1, trf * Translation3{Vector3::Unit(dirIdx) * -100}, *logger); BOOST_CHECK_EQUAL(volumes.size(), 2); @@ -1021,13 +995,10 @@ BOOST_DATA_TEST_CASE(ResizeGapMultiple, BOOST_REQUIRE_NE(updatedBounds, nullptr); BOOST_CHECK_EQUAL(updatedBounds->get(boundDir), 100.0); - std::array newBounds2Vals{}; - newBounds2Vals[dirIdx] = 300; - newBounds2Vals[dirOrth1Idx] = 70; - newBounds2Vals[dirOrth2Idx] = 100; - auto newBounds2 = std::make_shared(newBounds2Vals); - newBounds2->set( - {{boundDir, 300}, {boundDirOrth1, 70}, {boundDirOrth2, 100}}); + auto newBounds2 = std::make_shared( + std::initializer_list< + std::pair>{ + {boundDir, 300}, {boundDirOrth1, 70}, {boundDirOrth2, 100}}); stack.update(newBounds2, trf * Translation3{Vector3::Unit(dirIdx) * -200}, *logger); @@ -1093,10 +1064,9 @@ BOOST_DATA_TEST_CASE(InvalidInput, std::make_shared(100_mm, 400_mm, 400_mm)); volumes.push_back(vol2.get()); - BOOST_CHECK_THROW( - CuboidVolumeStack(volumes, direction, strategy, - CuboidVolumeStack::ResizeStrategy::Gap, *logger), - std::invalid_argument); + BOOST_CHECK_THROW(CuboidVolumeStack(volumes, direction, strategy, + VolumeResizeStrategy::Gap, *logger), + std::invalid_argument); } } @@ -1115,10 +1085,9 @@ BOOST_DATA_TEST_CASE(InvalidInput, std::make_shared(100_mm, 400_mm, 400_mm)); volumes.push_back(vol2.get()); - BOOST_CHECK_THROW( - CuboidVolumeStack(volumes, direction, strategy, - CuboidVolumeStack::ResizeStrategy::Gap, *logger), - std::invalid_argument); + BOOST_CHECK_THROW(CuboidVolumeStack(volumes, direction, strategy, + VolumeResizeStrategy::Gap, *logger), + std::invalid_argument); } } } @@ -1137,7 +1106,7 @@ BOOST_DATA_TEST_CASE(JoinCuboidVolumeSingle, std::vector volumes{vol.get()}; CuboidVolumeStack stack(volumes, direction, strategy, - CuboidVolumeStack::ResizeStrategy::Gap, *logger); + VolumeResizeStrategy::Gap, *logger); // Cuboid stack has the same transform as bounds as the single input // volume diff --git a/Tests/UnitTests/Core/Geometry/CylinderVolumeStackTests.cpp b/Tests/UnitTests/Core/Geometry/CylinderVolumeStackTests.cpp index 59987bfb42e..2935410ba6e 100644 --- a/Tests/UnitTests/Core/Geometry/CylinderVolumeStackTests.cpp +++ b/Tests/UnitTests/Core/Geometry/CylinderVolumeStackTests.cpp @@ -19,6 +19,8 @@ #include "Acts/Definitions/Units.hpp" #include "Acts/Geometry/CylinderVolumeBounds.hpp" #include "Acts/Geometry/CylinderVolumeStack.hpp" +#include "Acts/Geometry/detail/VolumeAttachmentStrategy.hpp" +#include "Acts/Geometry/detail/VolumeResizeStrategy.hpp" #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp" #include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/Logger.hpp" @@ -44,17 +46,16 @@ struct Fixture { BOOST_FIXTURE_TEST_SUITE(Geometry, Fixture) -static const std::vector strategies = { - CylinderVolumeStack::AttachmentStrategy::Gap, - CylinderVolumeStack::AttachmentStrategy::First, - CylinderVolumeStack::AttachmentStrategy::Second, - CylinderVolumeStack::AttachmentStrategy::Midpoint, +static const std::vector strategies = { + VolumeAttachmentStrategy::Gap, + VolumeAttachmentStrategy::First, + VolumeAttachmentStrategy::Second, + VolumeAttachmentStrategy::Midpoint, }; -static const std::vector resizeStrategies = - { - CylinderVolumeStack::ResizeStrategy::Expand, - CylinderVolumeStack::ResizeStrategy::Gap, +static const std::vector resizeStrategies = { + VolumeResizeStrategy::Expand, + VolumeResizeStrategy::Gap, }; BOOST_AUTO_TEST_SUITE(CylinderVolumeStackTest) @@ -109,13 +110,12 @@ BOOST_DATA_TEST_CASE(Baseline, if (shift < 1.0) { BOOST_CHECK_THROW( CylinderVolumeStack(volumes, AxisDirection::AxisZ, strategy, - CylinderVolumeStack::ResizeStrategy::Gap, *logger), + VolumeResizeStrategy::Gap, *logger), std::invalid_argument); return; } CylinderVolumeStack cylStack(volumes, AxisDirection::AxisZ, strategy, - CylinderVolumeStack::ResizeStrategy::Gap, - *logger); + VolumeResizeStrategy::Gap, *logger); auto stackBounds = dynamic_cast(&cylStack.volumeBounds()); @@ -162,7 +162,7 @@ BOOST_DATA_TEST_CASE(Baseline, bounds.get(CylinderVolumeBounds::eHalfLengthZ)); } } else { - if (strategy == CylinderVolumeStack::AttachmentStrategy::Gap) { + if (strategy == VolumeAttachmentStrategy::Gap) { // Gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 5); auto gap1 = volumes.at(1); @@ -207,7 +207,7 @@ BOOST_DATA_TEST_CASE(Baseline, BOOST_CHECK_EQUAL(vol2->transform().matrix(), transform2.matrix()); BOOST_CHECK_EQUAL(vol3->transform().matrix(), transform3.matrix()); - } else if (strategy == CylinderVolumeStack::AttachmentStrategy::First) { + } else if (strategy == VolumeAttachmentStrategy::First) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -242,7 +242,7 @@ BOOST_DATA_TEST_CASE(Baseline, Transform3 expectedTransform3 = base * Translation3{0_mm, 0_mm, pZ3}; CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(), expectedTransform3.matrix(), 1e-10, 1e-14); - } else if (strategy == CylinderVolumeStack::AttachmentStrategy::Second) { + } else if (strategy == VolumeAttachmentStrategy::Second) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -277,7 +277,7 @@ BOOST_DATA_TEST_CASE(Baseline, Transform3 expectedTransform3 = base * Translation3{0_mm, 0_mm, pZ3}; CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(), expectedTransform3.matrix(), 1e-10, 1e-14); - } else if (strategy == CylinderVolumeStack::AttachmentStrategy::Midpoint) { + } else if (strategy == VolumeAttachmentStrategy::Midpoint) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -342,9 +342,8 @@ BOOST_AUTO_TEST_CASE(Asymmetric) { std::vector volumes = {vol2.get(), vol1.get(), vol3.get()}; CylinderVolumeStack cylStack(volumes, AxisDirection::AxisZ, - CylinderVolumeStack::AttachmentStrategy::Gap, - CylinderVolumeStack::ResizeStrategy::Gap, - *logger); + VolumeAttachmentStrategy::Gap, + VolumeResizeStrategy::Gap, *logger); BOOST_CHECK_EQUAL(volumes.size(), 5); auto stackBounds = @@ -385,8 +384,7 @@ BOOST_DATA_TEST_CASE(RotationInZ, boost::unit_test::data::make(strategies), std::vector volumes = {vol1.get(), vol2.get()}; CylinderVolumeStack cylStack(volumes, AxisDirection::AxisZ, strategy, - CylinderVolumeStack::ResizeStrategy::Gap, - *logger); + VolumeResizeStrategy::Gap, *logger); auto stackBounds = dynamic_cast(&cylStack.volumeBounds()); @@ -406,13 +404,13 @@ BOOST_DATA_TEST_CASE(RotationInZ, boost::unit_test::data::make(strategies), BOOST_CHECK_EQUAL(bounds->get(CylinderVolumeBounds::eMaxR), 400_mm); } - if (strategy == CylinderVolumeStack::AttachmentStrategy::Gap) { + if (strategy == VolumeAttachmentStrategy::Gap) { // Volumes stayed at the same position, not resized BOOST_CHECK_EQUAL(vol1->center()[eZ], -hlZ - gap / 2.0 + shift); BOOST_CHECK_EQUAL(vol2->center()[eZ], hlZ + gap / 2.0 + shift); BOOST_CHECK_EQUAL(newBounds1->get(CylinderVolumeBounds::eHalfLengthZ), hlZ); BOOST_CHECK_EQUAL(newBounds2->get(CylinderVolumeBounds::eHalfLengthZ), hlZ); - } else if (strategy == CylinderVolumeStack::AttachmentStrategy::First) { + } else if (strategy == VolumeAttachmentStrategy::First) { // Left volume moved, got resized BOOST_CHECK_EQUAL(vol1->center()[eZ], -hlZ + shift); BOOST_CHECK_EQUAL(newBounds1->get(CylinderVolumeBounds::eHalfLengthZ), @@ -420,7 +418,7 @@ BOOST_DATA_TEST_CASE(RotationInZ, boost::unit_test::data::make(strategies), // Right volume stayed the same BOOST_CHECK_EQUAL(vol2->center()[eZ], hlZ + gap / 2.0 + shift); BOOST_CHECK_EQUAL(newBounds2->get(CylinderVolumeBounds::eHalfLengthZ), hlZ); - } else if (strategy == CylinderVolumeStack::AttachmentStrategy::Second) { + } else if (strategy == VolumeAttachmentStrategy::Second) { // Left volume stayed the same BOOST_CHECK_EQUAL(vol1->center()[eZ], -hlZ - gap / 2.0 + shift); BOOST_CHECK_EQUAL(newBounds1->get(CylinderVolumeBounds::eHalfLengthZ), hlZ); @@ -428,7 +426,7 @@ BOOST_DATA_TEST_CASE(RotationInZ, boost::unit_test::data::make(strategies), BOOST_CHECK_EQUAL(vol2->center()[eZ], hlZ + shift); BOOST_CHECK_EQUAL(newBounds2->get(CylinderVolumeBounds::eHalfLengthZ), hlZ + gap / 2.0); - } else if (strategy == CylinderVolumeStack::AttachmentStrategy::Midpoint) { + } else if (strategy == VolumeAttachmentStrategy::Midpoint) { // Left volume moved, got resized BOOST_CHECK_EQUAL(vol1->center()[eZ], -hlZ - gap / 4.0 + shift); BOOST_CHECK_EQUAL(newBounds1->get(CylinderVolumeBounds::eHalfLengthZ), @@ -481,8 +479,8 @@ BOOST_DATA_TEST_CASE(UpdateStack, CylinderVolumeStack cylStack( volumes, AxisDirection::AxisZ, - CylinderVolumeStack::AttachmentStrategy::Gap, // should not make a - // difference + VolumeAttachmentStrategy::Gap, // should not make a + // difference strategy, *logger); const auto* originalBounds = @@ -621,7 +619,7 @@ BOOST_DATA_TEST_CASE(UpdateStack, BOOST_CHECK_EQUAL(cylBounds->get(CylinderVolumeBounds::eMinR), 50_mm); BOOST_CHECK_EQUAL(cylBounds->get(CylinderVolumeBounds::eMaxR), 700_mm); - if (strategy == CylinderVolumeStack::ResizeStrategy::Expand) { + if (strategy == VolumeResizeStrategy::Expand) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -651,7 +649,7 @@ BOOST_DATA_TEST_CASE(UpdateStack, base * Translation3{0_mm, 0_mm, 2 * hlZ + hlZ / 2.0}; BOOST_CHECK_EQUAL(vol3->transform().matrix(), expectedTransform3.matrix()); - } else if (strategy == CylinderVolumeStack::ResizeStrategy::Gap) { + } else if (strategy == VolumeResizeStrategy::Gap) { // Gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 5); @@ -696,8 +694,8 @@ BOOST_DATA_TEST_CASE(UpdateStack, BOOST_DATA_TEST_CASE( UpdateStackOneSided, (boost::unit_test::data::make(-1.0, 1.0) ^ - boost::unit_test::data::make(CylinderVolumeStack::ResizeStrategy::Gap, - CylinderVolumeStack::ResizeStrategy::Expand)), + boost::unit_test::data::make(VolumeResizeStrategy::Gap, + VolumeResizeStrategy::Expand)), f, strategy) { auto trf = Transform3::Identity(); @@ -712,8 +710,8 @@ BOOST_DATA_TEST_CASE( std::vector volumes = {vol1.get(), vol2.get()}; CylinderVolumeStack cylStack{volumes, AxisDirection::AxisZ, - CylinderVolumeStack::AttachmentStrategy::Gap, - strategy, *logger}; + VolumeAttachmentStrategy::Gap, strategy, + *logger}; const auto* originalBounds = dynamic_cast(&cylStack.volumeBounds()); @@ -778,7 +776,7 @@ BOOST_DATA_TEST_CASE( BOOST_CHECK_EQUAL(volBounds->get(CylinderVolumeBounds::eMaxR), 300_mm); } - if (strategy == CylinderVolumeStack::ResizeStrategy::Expand) { + if (strategy == VolumeResizeStrategy::Expand) { // No gaps were added, there was one gap initially BOOST_CHECK_EQUAL(volumes.size(), 3); const Volume* vol = nullptr; @@ -796,7 +794,7 @@ BOOST_DATA_TEST_CASE( BOOST_CHECK_EQUAL(volBounds->get(CylinderVolumeBounds::eHalfLengthZ), 450_mm); BOOST_CHECK_EQUAL(vol->center()[eZ], f * 550_mm); - } else if (strategy == CylinderVolumeStack::ResizeStrategy::Gap) { + } else if (strategy == VolumeResizeStrategy::Gap) { // One gap volume was added BOOST_CHECK_EQUAL(volumes.size(), 4); @@ -824,8 +822,8 @@ BOOST_AUTO_TEST_CASE(ResizeReproduction1) { std::vector volumes = {&vol1}; CylinderVolumeStack stack(volumes, AxisDirection::AxisZ, - CylinderVolumeStack::AttachmentStrategy::Gap, - CylinderVolumeStack::ResizeStrategy::Gap, *logger); + VolumeAttachmentStrategy::Gap, + VolumeResizeStrategy::Gap, *logger); Transform3 trf2 = Transform3::Identity() * Translation3{Vector3::UnitZ() * -1500}; @@ -850,8 +848,8 @@ BOOST_AUTO_TEST_CASE(ResizeReproduction2) { std::vector volumes = {&vol1}; CylinderVolumeStack stack(volumes, AxisDirection::AxisZ, - CylinderVolumeStack::AttachmentStrategy::Gap, - CylinderVolumeStack::ResizeStrategy::Gap, *logger); + VolumeAttachmentStrategy::Gap, + VolumeResizeStrategy::Gap, *logger); Transform3 trf2 = Transform3::Identity() * Translation3{Vector3::UnitZ() * 260.843}; @@ -903,9 +901,8 @@ BOOST_AUTO_TEST_CASE(ResizeGapMultiple) { BOOST_TEST_CONTEXT("Positive") { std::vector volumes = {&vol}; CylinderVolumeStack stack(volumes, AxisDirection::AxisZ, - CylinderVolumeStack::AttachmentStrategy::Gap, - CylinderVolumeStack::ResizeStrategy::Gap, - *logger); + VolumeAttachmentStrategy::Gap, + VolumeResizeStrategy::Gap, *logger); BOOST_CHECK_EQUAL(volumes.size(), 1); BOOST_CHECK(stack.gaps().empty()); @@ -940,9 +937,8 @@ BOOST_AUTO_TEST_CASE(ResizeGapMultiple) { BOOST_TEST_CONTEXT("Negative") { std::vector volumes = {&vol}; CylinderVolumeStack stack(volumes, AxisDirection::AxisZ, - CylinderVolumeStack::AttachmentStrategy::Gap, - CylinderVolumeStack::ResizeStrategy::Gap, - *logger); + VolumeAttachmentStrategy::Gap, + VolumeResizeStrategy::Gap, *logger); BOOST_CHECK_EQUAL(volumes.size(), 1); BOOST_CHECK(stack.gaps().empty()); @@ -1036,14 +1032,13 @@ BOOST_DATA_TEST_CASE(Baseline, if (f < 0.0) { BOOST_CHECK_THROW( CylinderVolumeStack(volumes, AxisDirection::AxisR, strategy, - CylinderVolumeStack::ResizeStrategy::Gap, *logger), + VolumeResizeStrategy::Gap, *logger), std::invalid_argument); return; } CylinderVolumeStack cylStack(volumes, AxisDirection::AxisR, strategy, - CylinderVolumeStack::ResizeStrategy::Gap, - *logger); + VolumeResizeStrategy::Gap, *logger); auto stackBounds = dynamic_cast(&cylStack.volumeBounds()); @@ -1125,7 +1120,7 @@ BOOST_DATA_TEST_CASE(Baseline, dynamic_cast(&vol2->volumeBounds()); const auto* newBounds3 = dynamic_cast(&vol3->volumeBounds()); - if (strategy == CylinderVolumeStack::AttachmentStrategy::Gap) { + if (strategy == VolumeAttachmentStrategy::Gap) { // Two gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 5); @@ -1160,7 +1155,7 @@ BOOST_DATA_TEST_CASE(Baseline, BOOST_CHECK_EQUAL(gapBounds2->get(CylinderVolumeBounds::eMaxR), fInner * 600_mm); - } else if (strategy == CylinderVolumeStack::AttachmentStrategy::First) { + } else if (strategy == VolumeAttachmentStrategy::First) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -1182,7 +1177,7 @@ BOOST_DATA_TEST_CASE(Baseline, BOOST_CHECK_EQUAL(newBounds3->get(CylinderVolumeBounds::eMaxR), fOuter * 900_mm); - } else if (strategy == CylinderVolumeStack::AttachmentStrategy::Second) { + } else if (strategy == VolumeAttachmentStrategy::Second) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -1203,7 +1198,7 @@ BOOST_DATA_TEST_CASE(Baseline, fOuter * 600_mm); BOOST_CHECK_EQUAL(newBounds3->get(CylinderVolumeBounds::eMaxR), fOuter * 900_mm); - } else if (strategy == CylinderVolumeStack::AttachmentStrategy::Midpoint) { + } else if (strategy == VolumeAttachmentStrategy::Midpoint) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -1278,8 +1273,8 @@ BOOST_DATA_TEST_CASE(UpdateStack, cylStack = std::make_unique( volumes, AxisDirection::AxisR, - CylinderVolumeStack::AttachmentStrategy::Gap, // should not make a - // difference + VolumeAttachmentStrategy::Gap, // should not make a + // difference strategy, *logger); originalOuterBounds = @@ -1367,7 +1362,7 @@ BOOST_DATA_TEST_CASE(UpdateStack, BOOST_CHECK_EQUAL(cylBounds->get(CylinderVolumeBounds::eMaxR), 900_mm); BOOST_CHECK_EQUAL(cylBounds->get(CylinderVolumeBounds::eHalfLengthZ), hlZ); - if (strategy == CylinderVolumeStack::ResizeStrategy::Expand) { + if (strategy == VolumeResizeStrategy::Expand) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -1389,7 +1384,7 @@ BOOST_DATA_TEST_CASE(UpdateStack, BOOST_CHECK_EQUAL(*newBounds3, originalBounds[2]); BOOST_CHECK_EQUAL(vol3->transform().matrix(), base.matrix()); - } else if (strategy == CylinderVolumeStack::ResizeStrategy::Gap) { + } else if (strategy == VolumeResizeStrategy::Gap) { // One gap volume was added BOOST_CHECK_EQUAL(volumes.size(), 4); @@ -1424,7 +1419,7 @@ BOOST_DATA_TEST_CASE(UpdateStack, BOOST_CHECK_EQUAL(cylBounds->get(CylinderVolumeBounds::eMinR), 100_mm); BOOST_CHECK_EQUAL(cylBounds->get(CylinderVolumeBounds::eHalfLengthZ), hlZ); - if (strategy == CylinderVolumeStack::ResizeStrategy::Expand) { + if (strategy == VolumeResizeStrategy::Expand) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -1446,7 +1441,7 @@ BOOST_DATA_TEST_CASE(UpdateStack, BOOST_CHECK_EQUAL(*newBounds2, originalBounds[1]); BOOST_CHECK_EQUAL(vol2->transform().matrix(), base.matrix()); - } else if (strategy == CylinderVolumeStack::ResizeStrategy::Gap) { + } else if (strategy == VolumeResizeStrategy::Gap) { // One gap volume was added BOOST_CHECK_EQUAL(volumes.size(), 4); @@ -1485,7 +1480,7 @@ BOOST_DATA_TEST_CASE(UpdateStack, BOOST_CHECK_EQUAL(cylBounds->get(CylinderVolumeBounds::eMinR), 0_mm); BOOST_CHECK_EQUAL(cylBounds->get(CylinderVolumeBounds::eHalfLengthZ), hlZ); - if (strategy == CylinderVolumeStack::ResizeStrategy::Expand) { + if (strategy == VolumeResizeStrategy::Expand) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -1509,7 +1504,7 @@ BOOST_DATA_TEST_CASE(UpdateStack, // Position stayed the same BOOST_CHECK_EQUAL(vol3->transform().matrix(), base.matrix()); - } else if (strategy == CylinderVolumeStack::ResizeStrategy::Gap) { + } else if (strategy == VolumeResizeStrategy::Gap) { // One gap volume was added BOOST_CHECK_EQUAL(volumes.size(), 5); @@ -1581,8 +1576,8 @@ BOOST_DATA_TEST_CASE(UpdateStack, BOOST_DATA_TEST_CASE( UpdateStackOneSided, (boost::unit_test::data::make(-1.0, 1.0) ^ - boost::unit_test::data::make(CylinderVolumeStack::ResizeStrategy::Gap, - CylinderVolumeStack::ResizeStrategy::Expand)), + boost::unit_test::data::make(VolumeResizeStrategy::Gap, + VolumeResizeStrategy::Expand)), f, strategy) { // Strategy should not affect the sizing here at all @@ -1597,8 +1592,8 @@ BOOST_DATA_TEST_CASE( std::vector volumes = {vol1.get(), vol2.get()}; CylinderVolumeStack cylStack{volumes, AxisDirection::AxisR, - CylinderVolumeStack::AttachmentStrategy::Gap, - strategy, *logger}; + VolumeAttachmentStrategy::Gap, strategy, + *logger}; const auto* originalBounds = dynamic_cast(&cylStack.volumeBounds()); @@ -1673,9 +1668,8 @@ BOOST_AUTO_TEST_CASE(ResizeGapMultiple) { BOOST_TEST_CONTEXT("Outer") { std::vector volumes = {&vol}; CylinderVolumeStack stack(volumes, AxisDirection::AxisR, - CylinderVolumeStack::AttachmentStrategy::Gap, - CylinderVolumeStack::ResizeStrategy::Gap, - *logger); + VolumeAttachmentStrategy::Gap, + VolumeResizeStrategy::Gap, *logger); BOOST_CHECK_EQUAL(volumes.size(), 1); BOOST_CHECK(stack.gaps().empty()); @@ -1708,9 +1702,8 @@ BOOST_AUTO_TEST_CASE(ResizeGapMultiple) { BOOST_TEST_CONTEXT("Inner") { std::vector volumes = {&vol}; CylinderVolumeStack stack(volumes, AxisDirection::AxisR, - CylinderVolumeStack::AttachmentStrategy::Gap, - CylinderVolumeStack::ResizeStrategy::Gap, - *logger); + VolumeAttachmentStrategy::Gap, + VolumeResizeStrategy::Gap, *logger); BOOST_CHECK_EQUAL(volumes.size(), 1); BOOST_CHECK(stack.gaps().empty()); @@ -1795,9 +1788,8 @@ BOOST_DATA_TEST_CASE(JoinCylinderVolumesInvalidInput, std::make_shared(100_mm, 400_mm, 400_mm)); volumes.push_back(vol2.get()); - BOOST_CHECK_THROW(CylinderVolumeStack( - volumes, direction, strategy, - CylinderVolumeStack::ResizeStrategy::Gap, *logger), + BOOST_CHECK_THROW(CylinderVolumeStack(volumes, direction, strategy, + VolumeResizeStrategy::Gap, *logger), std::invalid_argument); } } @@ -1816,9 +1808,8 @@ BOOST_DATA_TEST_CASE(JoinCylinderVolumesInvalidInput, std::make_shared(100_mm, 400_mm, 400_mm)); volumes.push_back(vol2.get()); - BOOST_CHECK_THROW(CylinderVolumeStack( - volumes, direction, strategy, - CylinderVolumeStack::ResizeStrategy::Gap, *logger), + BOOST_CHECK_THROW(CylinderVolumeStack(volumes, direction, strategy, + VolumeResizeStrategy::Gap, *logger), std::invalid_argument); } } @@ -1852,8 +1843,7 @@ BOOST_DATA_TEST_CASE(JoinCylinderVolumesInvalidInput, { // have valid stack, try to assign extra CylinderVolumeStack cylStack(volumes, direction, strategy, - CylinderVolumeStack::ResizeStrategy::Gap, - *logger); + VolumeResizeStrategy::Gap, *logger); BOOST_CHECK_THROW(cylStack.update(invalid, std::nullopt, *logger), std::invalid_argument); } @@ -1874,8 +1864,7 @@ BOOST_DATA_TEST_CASE(JoinCylinderVolumesInvalidInput, volumes.push_back(vol.get()); BOOST_CHECK_THROW( CylinderVolumeStack(volumes, direction, strategy, - CylinderVolumeStack::ResizeStrategy::Gap, - *logger), + VolumeResizeStrategy::Gap, *logger), std::invalid_argument); } } @@ -1896,8 +1885,7 @@ BOOST_DATA_TEST_CASE(JoinCylinderVolumeSingle, std::vector volumes{vol.get()}; CylinderVolumeStack cylStack(volumes, direction, strategy, - CylinderVolumeStack::ResizeStrategy::Gap, - *logger); + VolumeResizeStrategy::Gap, *logger); // Cylinder stack has the same transform as bounds as the single input // volume From 18cc4c756665546cac3261e17f9e47a95f186d7f Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Wed, 22 Jan 2025 14:39:19 +0200 Subject: [PATCH 11/22] lint --- .../Acts/Geometry/CylinderContainerBlueprintNode.hpp | 6 ++---- Core/src/Geometry/CylinderContainerBlueprintNode.cpp | 7 +++---- Core/src/Geometry/detail/VolumeAttachmentStrategy.cpp | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index d05bdac55e4..339cc033f95 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -41,8 +41,7 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { const std::string& name, AxisDirection direction, VolumeAttachmentStrategy attachmentStrategy = VolumeAttachmentStrategy::Midpoint, - VolumeResizeStrategy resizeStrategy = - VolumeResizeStrategy::Expand); + VolumeResizeStrategy resizeStrategy = VolumeResizeStrategy::Expand); /// @copydoc BlueprintNode::name const std::string& name() const override; @@ -143,8 +142,7 @@ class CylinderContainerBlueprintNode final : public BlueprintNode { VolumeAttachmentStrategy m_attachmentStrategy{ VolumeAttachmentStrategy::Midpoint}; - VolumeResizeStrategy m_resizeStrategy{ - VolumeResizeStrategy::Expand}; + VolumeResizeStrategy m_resizeStrategy{VolumeResizeStrategy::Expand}; // Is only initialized during `build` std::vector m_childVolumes; diff --git a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp index aef3461a57b..1d50558fc14 100644 --- a/Core/src/Geometry/CylinderContainerBlueprintNode.cpp +++ b/Core/src/Geometry/CylinderContainerBlueprintNode.cpp @@ -244,13 +244,12 @@ AxisDirection CylinderContainerBlueprintNode::direction() const { return m_direction; } -VolumeAttachmentStrategy -CylinderContainerBlueprintNode::attachmentStrategy() const { +VolumeAttachmentStrategy CylinderContainerBlueprintNode::attachmentStrategy() + const { return m_attachmentStrategy; } -VolumeResizeStrategy -CylinderContainerBlueprintNode::resizeStrategy() const { +VolumeResizeStrategy CylinderContainerBlueprintNode::resizeStrategy() const { return m_resizeStrategy; } diff --git a/Core/src/Geometry/detail/VolumeAttachmentStrategy.cpp b/Core/src/Geometry/detail/VolumeAttachmentStrategy.cpp index 8f6c55e9884..7dda009e7d4 100644 --- a/Core/src/Geometry/detail/VolumeAttachmentStrategy.cpp +++ b/Core/src/Geometry/detail/VolumeAttachmentStrategy.cpp @@ -27,4 +27,4 @@ std::ostream& operator<<(std::ostream& os, VolumeAttachmentStrategy strategy) { return os; } -} // namespace Acts \ No newline at end of file +} // namespace Acts From d70019c3ce0e460f6c0746f0e281e628f4f658ba Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Wed, 22 Jan 2025 14:46:55 +0200 Subject: [PATCH 12/22] lint --- Core/include/Acts/Geometry/CuboidVolumeBounds.hpp | 2 +- Core/include/Acts/Geometry/CuboidVolumeStack.hpp | 2 +- Core/src/Geometry/detail/VolumeAttachmentStrategy.cpp | 3 +++ Core/src/Geometry/detail/VolumeResizeStrategy.cpp | 3 +++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Core/include/Acts/Geometry/CuboidVolumeBounds.hpp b/Core/include/Acts/Geometry/CuboidVolumeBounds.hpp index 8bc5cac731e..db2656daeb6 100644 --- a/Core/include/Acts/Geometry/CuboidVolumeBounds.hpp +++ b/Core/include/Acts/Geometry/CuboidVolumeBounds.hpp @@ -154,7 +154,7 @@ class CuboidVolumeBounds : public VolumeBounds { void set(std::initializer_list> keyValues); /// Convert axis direction to a corresponding bound value - /// in local coordinate convetion + /// in local coordinate convention /// @param direction the axis direction to convert static BoundValues fromAxisDirection(AxisDirection direction); diff --git a/Core/include/Acts/Geometry/CuboidVolumeStack.hpp b/Core/include/Acts/Geometry/CuboidVolumeStack.hpp index d29feaa9308..e91e721e9e8 100644 --- a/Core/include/Acts/Geometry/CuboidVolumeStack.hpp +++ b/Core/include/Acts/Geometry/CuboidVolumeStack.hpp @@ -95,7 +95,7 @@ class CuboidVolumeStack : public Volume { /// @return the vector of gap volumes const std::vector>& gaps() const; - /// Conert axis direction to an array index according to + /// 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); diff --git a/Core/src/Geometry/detail/VolumeAttachmentStrategy.cpp b/Core/src/Geometry/detail/VolumeAttachmentStrategy.cpp index 7dda009e7d4..4164c7aa1bf 100644 --- a/Core/src/Geometry/detail/VolumeAttachmentStrategy.cpp +++ b/Core/src/Geometry/detail/VolumeAttachmentStrategy.cpp @@ -23,6 +23,9 @@ std::ostream& operator<<(std::ostream& os, VolumeAttachmentStrategy strategy) { case VolumeAttachmentStrategy::Gap: os << "Gap"; break; + default: + os << "Unknown"; + break; } return os; } diff --git a/Core/src/Geometry/detail/VolumeResizeStrategy.cpp b/Core/src/Geometry/detail/VolumeResizeStrategy.cpp index bb289d8ce2f..8ea7ebaa4bd 100644 --- a/Core/src/Geometry/detail/VolumeResizeStrategy.cpp +++ b/Core/src/Geometry/detail/VolumeResizeStrategy.cpp @@ -18,6 +18,9 @@ std::ostream& operator<<(std::ostream& os, VolumeResizeStrategy strategy) { case VolumeResizeStrategy::Gap: os << "Gap"; break; + default: + os << "Unknown"; + break; } return os; } From c19d2428a1930ae5a18b2edc7183dcc2b8d9ed13 Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Wed, 22 Jan 2025 14:48:52 +0200 Subject: [PATCH 13/22] cleanup --- Core/src/Geometry/CuboidVolumeStack.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Core/src/Geometry/CuboidVolumeStack.cpp b/Core/src/Geometry/CuboidVolumeStack.cpp index b06214886b5..e9f5f3859bb 100644 --- a/Core/src/Geometry/CuboidVolumeStack.cpp +++ b/Core/src/Geometry/CuboidVolumeStack.cpp @@ -595,10 +595,6 @@ void CuboidVolumeStack::update(std::shared_ptr volbounds, "CuboidVolumeStack requires CuboidVolumeBounds"); } - if (bounds == nullptr) { - throw std::invalid_argument("New bounds are nullptr"); - } - if (*bounds == volumeBounds()) { ACTS_VERBOSE("Bounds are the same, no resize needed"); return; From 704fd12552f2430d3d76a0a941b28109e10945b7 Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Wed, 22 Jan 2025 14:55:50 +0200 Subject: [PATCH 14/22] lint --- Core/src/Geometry/CylinderVolumeStack.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Core/src/Geometry/CylinderVolumeStack.cpp b/Core/src/Geometry/CylinderVolumeStack.cpp index 888216352d1..5761260c1f1 100644 --- a/Core/src/Geometry/CylinderVolumeStack.cpp +++ b/Core/src/Geometry/CylinderVolumeStack.cpp @@ -324,10 +324,9 @@ void CylinderVolumeStack::overlapPrint( } std::vector -CylinderVolumeStack::checkOverlapAndAttachInZ( - std::vector& volumes, - VolumeAttachmentStrategy strategy, - const Logger& logger) { +CylinderVolumeStack::checkOverlapAndAttachInZ(std::vector& volumes, + VolumeAttachmentStrategy strategy, + const Logger& logger) { // Preconditions: volumes are sorted by z std::vector gapVolumes; for (std::size_t i = 0; i < volumes.size() - 1; i++) { @@ -460,10 +459,9 @@ CylinderVolumeStack::checkOverlapAndAttachInZ( } std::vector -CylinderVolumeStack::checkOverlapAndAttachInR( - std::vector& volumes, - VolumeAttachmentStrategy strategy, - const Logger& logger) { +CylinderVolumeStack::checkOverlapAndAttachInR(std::vector& volumes, + VolumeAttachmentStrategy strategy, + const Logger& logger) { std::vector gapVolumes; for (std::size_t i = 0; i < volumes.size() - 1; i++) { std::size_t j = i + 1; From 412420383fd8752cfe8c2c53c8c4ef40b2fc7dbd Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Wed, 22 Jan 2025 16:09:55 +0200 Subject: [PATCH 15/22] tidy and numerical limits --- Core/src/Geometry/CuboidVolumeBounds.cpp | 11 +++---- .../Core/Geometry/CuboidVolumeStackTests.cpp | 30 +++++++++---------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/Core/src/Geometry/CuboidVolumeBounds.cpp b/Core/src/Geometry/CuboidVolumeBounds.cpp index 90d66e7eff1..41f05ef09f8 100644 --- a/Core/src/Geometry/CuboidVolumeBounds.cpp +++ b/Core/src/Geometry/CuboidVolumeBounds.cpp @@ -36,18 +36,15 @@ CuboidVolumeBounds::CuboidVolumeBounds(const std::array& values) CuboidVolumeBounds::CuboidVolumeBounds( std::initializer_list> keyValues) { - // Consistency check will fail if - // not all the bounds are constructed - std::array values = {-1, -1, -1}; + m_values = {-1, -1, -1}; for (const auto& [key, value] : keyValues) { - values[key] = value; + m_values[key] = value; } - if (std::any_of(values.begin(), values.end(), + // Throw error here instead of consistency check for clarity + if (std::any_of(m_values.begin(), m_values.end(), [](const auto& val) { return val == -1; })) { throw std::logic_error("Missing bound values"); } - - m_values = values; checkConsistency(); buildSurfaceBounds(); } diff --git a/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp b/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp index 1ff76615757..35a1efbb7a7 100644 --- a/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp +++ b/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp @@ -152,7 +152,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, BOOST_CHECK_EQUAL(stackBounds->get(boundDirOrth1), 300_mm); BOOST_CHECK_EQUAL(stackBounds->get(boundDirOrth2), 600_mm); BOOST_CHECK_EQUAL(stackBounds->get(boundDir), halfDir + 2 * halfDir * shift); - CHECK_CLOSE_OR_SMALL(stack.transform().matrix(), base.matrix(), 1e-10, 1e-14); + CHECK_CLOSE_OR_SMALL(stack.transform().matrix(), base.matrix(), 1e-10, 1e-12); // All volumes (including gaps) are cuboids and have the same orthogonal // bounds @@ -217,9 +217,9 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Transform3 gap2Transform = base * gap2Translation; CHECK_CLOSE_OR_SMALL(gap1->transform().matrix(), gap1Transform.matrix(), - 1e-10, 1e-14); + 1e-10, 1e-12); CHECK_CLOSE_OR_SMALL(gap2->transform().matrix(), gap2Transform.matrix(), - 1e-10, 1e-14); + 1e-10, 1e-12); // Original volumes did not changes bounds for (const auto& [volume, bounds] : zip(origVolumes, originalBounds)) { @@ -246,7 +246,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Translation3 expectedTranslation1(Vector3::Unit(dirIdx) * pDir1); Transform3 expectedTransform1 = base * expectedTranslation1; CHECK_CLOSE_OR_SMALL(vol1->transform().matrix(), - expectedTransform1.matrix(), 1e-10, 1e-14); + expectedTransform1.matrix(), 1e-10, 1e-12); // Volume 2 got bigger and shifted left auto newBounds2 = @@ -256,7 +256,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Translation3 expectedTranslation2(Vector3::Unit(dirIdx) * pDir2); Transform3 expectedTransform2 = base * expectedTranslation2; CHECK_CLOSE_OR_SMALL(vol2->transform().matrix(), - expectedTransform2.matrix(), 1e-10, 1e-14); + expectedTransform2.matrix(), 1e-10, 1e-12); // Volume 3 stayed the same auto newBounds3 = @@ -266,7 +266,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Translation3 expectedTranslation3(Vector3::Unit(dirIdx) * pDir3); Transform3 expectedTransform3 = base * expectedTranslation3; CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(), - expectedTransform3.matrix(), 1e-10, 1e-14); + expectedTransform3.matrix(), 1e-10, 1e-12); } else if (strategy == VolumeAttachmentStrategy::Second) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -281,7 +281,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Translation3 expectedTranslation1(Vector3::Unit(dirIdx) * pDir1); Transform3 expectedTransform1 = base * expectedTranslation1; CHECK_CLOSE_OR_SMALL(vol1->transform().matrix(), - expectedTransform1.matrix(), 1e-10, 1e-14); + expectedTransform1.matrix(), 1e-10, 1e-12); // Volume 2 got bigger and shifted left auto newBounds2 = @@ -291,7 +291,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Translation3 expectedTranslation2(Vector3::Unit(dirIdx) * pDir2); Transform3 expectedTransform2 = base * expectedTranslation2; CHECK_CLOSE_OR_SMALL(vol2->transform().matrix(), - expectedTransform2.matrix(), 1e-10, 1e-14); + expectedTransform2.matrix(), 1e-10, 1e-12); // Volume 3 got bigger and shifted left auto newBounds3 = @@ -301,7 +301,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Translation3 expectedTranslation3(Vector3::Unit(dirIdx) * pDir3); Transform3 expectedTransform3 = base * expectedTranslation3; CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(), - expectedTransform3.matrix(), 1e-10, 1e-14); + expectedTransform3.matrix(), 1e-10, 1e-12); } else if (strategy == VolumeAttachmentStrategy::Midpoint) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -316,14 +316,14 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Translation3 expectedTranslation1(Vector3::Unit(dirIdx) * pDir1); Transform3 expectedTransform1 = base * expectedTranslation1; CHECK_CLOSE_OR_SMALL(vol1->transform().matrix(), - expectedTransform1.matrix(), 1e-10, 1e-14); + expectedTransform1.matrix(), 1e-10, 1e-12); // Volume 2 got bigger but didn't move auto newBounds2 = dynamic_cast(&vol2->volumeBounds()); BOOST_CHECK_EQUAL(newBounds2->get(boundDir), halfDir + wGap / 2.0); CHECK_CLOSE_OR_SMALL(vol2->transform().matrix(), base.matrix(), 1e-10, - 1e-14); + 1e-12); // Volume 3 got bigger and shifted left auto newBounds3 = @@ -333,7 +333,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Translation3 expectedTranslation3(Vector3::Unit(dirIdx) * pDir3); Transform3 expectedTransform3 = base * expectedTranslation3; CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(), - expectedTransform3.matrix(), 1e-10, 1e-14); + expectedTransform3.matrix(), 1e-10, 1e-12); } } } @@ -476,7 +476,7 @@ BOOST_DATA_TEST_CASE(Asymmetric, Translation3 expectedTranslation(Vector3::Unit(dirIdx) * midDir); Transform3 expectedTransform = Transform3::Identity() * expectedTranslation; CHECK_CLOSE_OR_SMALL(stack.transform().matrix(), expectedTransform.matrix(), - 1e-10, 1e-14); + 1e-10, 1e-12); } BOOST_DATA_TEST_CASE(UpdateStack, @@ -734,9 +734,9 @@ BOOST_DATA_TEST_CASE(UpdateStack, Translation3(Vector3::Unit(dirIdx) * (3 * halfDir + halfDir / 2.0)); Transform3 gap2Transform = base * gap2Translation; CHECK_CLOSE_OR_SMALL(gap1->transform().matrix(), gap1Transform.matrix(), - 1e-10, 1e-14); + 1e-10, 1e-12); CHECK_CLOSE_OR_SMALL(gap2->transform().matrix(), gap2Transform.matrix(), - 1e-10, 1e-14); + 1e-10, 1e-12); } } } From f8020f60a4a97ebb2c9967290d32f31cf67707bd Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Wed, 22 Jan 2025 16:20:43 +0200 Subject: [PATCH 16/22] breaks --- Core/src/Geometry/CuboidVolumeBounds.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/Core/src/Geometry/CuboidVolumeBounds.cpp b/Core/src/Geometry/CuboidVolumeBounds.cpp index 41f05ef09f8..6ed99943deb 100644 --- a/Core/src/Geometry/CuboidVolumeBounds.cpp +++ b/Core/src/Geometry/CuboidVolumeBounds.cpp @@ -175,13 +175,10 @@ CuboidVolumeBounds::BoundValues CuboidVolumeBounds::fromAxisDirection( switch (direction) { case AxisX: return BoundValues::eHalfLengthX; - break; case AxisY: return BoundValues::eHalfLengthY; - break; case AxisZ: return BoundValues::eHalfLengthZ; - break; default: throw std::invalid_argument("Invalid axis direction"); } From da5aa81a784981f9e8390abb5c625aaa4ed5d9eb Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Wed, 22 Jan 2025 16:36:49 +0200 Subject: [PATCH 17/22] lower macos threshold --- .../Core/Geometry/CuboidVolumeStackTests.cpp | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp b/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp index 35a1efbb7a7..816b14d7cc9 100644 --- a/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp +++ b/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp @@ -152,7 +152,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, BOOST_CHECK_EQUAL(stackBounds->get(boundDirOrth1), 300_mm); BOOST_CHECK_EQUAL(stackBounds->get(boundDirOrth2), 600_mm); BOOST_CHECK_EQUAL(stackBounds->get(boundDir), halfDir + 2 * halfDir * shift); - CHECK_CLOSE_OR_SMALL(stack.transform().matrix(), base.matrix(), 1e-10, 1e-12); + CHECK_CLOSE_OR_SMALL(stack.transform().matrix(), base.matrix(), 1e-10, 1e-10); // All volumes (including gaps) are cuboids and have the same orthogonal // bounds @@ -217,9 +217,9 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Transform3 gap2Transform = base * gap2Translation; CHECK_CLOSE_OR_SMALL(gap1->transform().matrix(), gap1Transform.matrix(), - 1e-10, 1e-12); + 1e-10, 1e-10); CHECK_CLOSE_OR_SMALL(gap2->transform().matrix(), gap2Transform.matrix(), - 1e-10, 1e-12); + 1e-10, 1e-10); // Original volumes did not changes bounds for (const auto& [volume, bounds] : zip(origVolumes, originalBounds)) { @@ -246,7 +246,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Translation3 expectedTranslation1(Vector3::Unit(dirIdx) * pDir1); Transform3 expectedTransform1 = base * expectedTranslation1; CHECK_CLOSE_OR_SMALL(vol1->transform().matrix(), - expectedTransform1.matrix(), 1e-10, 1e-12); + expectedTransform1.matrix(), 1e-10, 1e-10); // Volume 2 got bigger and shifted left auto newBounds2 = @@ -256,7 +256,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Translation3 expectedTranslation2(Vector3::Unit(dirIdx) * pDir2); Transform3 expectedTransform2 = base * expectedTranslation2; CHECK_CLOSE_OR_SMALL(vol2->transform().matrix(), - expectedTransform2.matrix(), 1e-10, 1e-12); + expectedTransform2.matrix(), 1e-10, 1e-10); // Volume 3 stayed the same auto newBounds3 = @@ -266,7 +266,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Translation3 expectedTranslation3(Vector3::Unit(dirIdx) * pDir3); Transform3 expectedTransform3 = base * expectedTranslation3; CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(), - expectedTransform3.matrix(), 1e-10, 1e-12); + expectedTransform3.matrix(), 1e-10, 1e-10); } else if (strategy == VolumeAttachmentStrategy::Second) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -281,7 +281,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Translation3 expectedTranslation1(Vector3::Unit(dirIdx) * pDir1); Transform3 expectedTransform1 = base * expectedTranslation1; CHECK_CLOSE_OR_SMALL(vol1->transform().matrix(), - expectedTransform1.matrix(), 1e-10, 1e-12); + expectedTransform1.matrix(), 1e-10, 1e-10); // Volume 2 got bigger and shifted left auto newBounds2 = @@ -291,7 +291,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Translation3 expectedTranslation2(Vector3::Unit(dirIdx) * pDir2); Transform3 expectedTransform2 = base * expectedTranslation2; CHECK_CLOSE_OR_SMALL(vol2->transform().matrix(), - expectedTransform2.matrix(), 1e-10, 1e-12); + expectedTransform2.matrix(), 1e-10, 1e-10); // Volume 3 got bigger and shifted left auto newBounds3 = @@ -301,7 +301,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Translation3 expectedTranslation3(Vector3::Unit(dirIdx) * pDir3); Transform3 expectedTransform3 = base * expectedTranslation3; CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(), - expectedTransform3.matrix(), 1e-10, 1e-12); + expectedTransform3.matrix(), 1e-10, 1e-10); } else if (strategy == VolumeAttachmentStrategy::Midpoint) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -316,14 +316,14 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Translation3 expectedTranslation1(Vector3::Unit(dirIdx) * pDir1); Transform3 expectedTransform1 = base * expectedTranslation1; CHECK_CLOSE_OR_SMALL(vol1->transform().matrix(), - expectedTransform1.matrix(), 1e-10, 1e-12); + expectedTransform1.matrix(), 1e-10, 1e-10); // Volume 2 got bigger but didn't move auto newBounds2 = dynamic_cast(&vol2->volumeBounds()); BOOST_CHECK_EQUAL(newBounds2->get(boundDir), halfDir + wGap / 2.0); CHECK_CLOSE_OR_SMALL(vol2->transform().matrix(), base.matrix(), 1e-10, - 1e-12); + 1e-10); // Volume 3 got bigger and shifted left auto newBounds3 = @@ -333,7 +333,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Translation3 expectedTranslation3(Vector3::Unit(dirIdx) * pDir3); Transform3 expectedTransform3 = base * expectedTranslation3; CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(), - expectedTransform3.matrix(), 1e-10, 1e-12); + expectedTransform3.matrix(), 1e-10, 1e-10); } } } @@ -404,7 +404,7 @@ BOOST_DATA_TEST_CASE(BaselineGlobal, BOOST_CHECK_NE(stackBoundsAxisDirection, nullptr); BOOST_CHECK_EQUAL(*stackBoundsOrientation, *stackBoundsAxisDirection); CHECK_CLOSE_OR_SMALL(stackOrientation.transform().matrix(), - stackAxisDirection.transform().matrix(), 1e-10, 1e-12); + stackAxisDirection.transform().matrix(), 1e-10, 1e-10); } BOOST_DATA_TEST_CASE(Asymmetric, @@ -476,7 +476,7 @@ BOOST_DATA_TEST_CASE(Asymmetric, Translation3 expectedTranslation(Vector3::Unit(dirIdx) * midDir); Transform3 expectedTransform = Transform3::Identity() * expectedTranslation; CHECK_CLOSE_OR_SMALL(stack.transform().matrix(), expectedTransform.matrix(), - 1e-10, 1e-12); + 1e-10, 1e-10); } BOOST_DATA_TEST_CASE(UpdateStack, @@ -734,9 +734,9 @@ BOOST_DATA_TEST_CASE(UpdateStack, Translation3(Vector3::Unit(dirIdx) * (3 * halfDir + halfDir / 2.0)); Transform3 gap2Transform = base * gap2Translation; CHECK_CLOSE_OR_SMALL(gap1->transform().matrix(), gap1Transform.matrix(), - 1e-10, 1e-12); + 1e-10, 1e-10); CHECK_CLOSE_OR_SMALL(gap2->transform().matrix(), gap2Transform.matrix(), - 1e-10, 1e-12); + 1e-10, 1e-10); } } } From cbc63ed5230d54d23b15b9090e587a2d3d8117eb Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Wed, 22 Jan 2025 17:16:31 +0200 Subject: [PATCH 18/22] lower macos threshold --- .../Core/Geometry/CuboidVolumeStackTests.cpp | 146 +++++++++--------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp b/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp index 816b14d7cc9..1e20163910a 100644 --- a/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp +++ b/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp @@ -149,10 +149,10 @@ BOOST_DATA_TEST_CASE(BaselineLocal, dynamic_cast(&stack.volumeBounds()); BOOST_REQUIRE(stackBounds != nullptr); - BOOST_CHECK_EQUAL(stackBounds->get(boundDirOrth1), 300_mm); - BOOST_CHECK_EQUAL(stackBounds->get(boundDirOrth2), 600_mm); - BOOST_CHECK_EQUAL(stackBounds->get(boundDir), halfDir + 2 * halfDir * shift); - CHECK_CLOSE_OR_SMALL(stack.transform().matrix(), base.matrix(), 1e-10, 1e-10); + BOOST_CHECK_CLOSE(stackBounds->get(boundDirOrth1), 300_mm, 1e-6); + BOOST_CHECK_CLOSE(stackBounds->get(boundDirOrth2), 600_mm, 1e-6); + BOOST_CHECK_CLOSE(stackBounds->get(boundDir), halfDir + 2 * halfDir * shift, 1e-6); + CHECK_CLOSE_OR_SMALL(stack.transform().matrix(), base.matrix(), 1e-10, 1e-12); // All volumes (including gaps) are cuboids and have the same orthogonal // bounds @@ -160,8 +160,8 @@ BOOST_DATA_TEST_CASE(BaselineLocal, const auto* cuboidBounds = dynamic_cast(&volume->volumeBounds()); BOOST_REQUIRE(cuboidBounds != nullptr); - BOOST_CHECK_EQUAL(cuboidBounds->get(boundDirOrth1), 300_mm); - BOOST_CHECK_EQUAL(cuboidBounds->get(boundDirOrth2), 600_mm); + BOOST_CHECK_CLOSE(cuboidBounds->get(boundDirOrth1), 300_mm, 1e-6); + BOOST_CHECK_CLOSE(cuboidBounds->get(boundDirOrth2), 600_mm, 1e-6); } // Volumes are sorted in (local) stacking direction @@ -185,7 +185,7 @@ BOOST_DATA_TEST_CASE(BaselineLocal, for (const auto& [volume, bounds] : zip(origVolumes, originalBounds)) { const auto* newBounds = dynamic_cast(&volume->volumeBounds()); - BOOST_CHECK_EQUAL(newBounds->get(boundDir), bounds.get(boundDir)); + BOOST_CHECK_CLOSE(newBounds->get(boundDir), bounds.get(boundDir), 1e-6); } } else { if (strategy == VolumeAttachmentStrategy::Gap) { @@ -204,8 +204,8 @@ BOOST_DATA_TEST_CASE(BaselineLocal, double gapHlDir = (shift - 1.0) * halfDir; - BOOST_CHECK(std::abs(gapBounds1->get(boundDir) - gapHlDir) < 1e-10); - BOOST_CHECK(std::abs(gapBounds2->get(boundDir) - gapHlDir) < 1e-10); + BOOST_CHECK(std::abs(gapBounds1->get(boundDir) - gapHlDir) < 1e-12); + BOOST_CHECK(std::abs(gapBounds2->get(boundDir) - gapHlDir) < 1e-12); double gap1Dir = (-2 * halfDir * shift) + halfDir + gapHlDir; double gap2Dir = (2 * halfDir * shift) - halfDir - gapHlDir; @@ -217,15 +217,15 @@ BOOST_DATA_TEST_CASE(BaselineLocal, Transform3 gap2Transform = base * gap2Translation; CHECK_CLOSE_OR_SMALL(gap1->transform().matrix(), gap1Transform.matrix(), - 1e-10, 1e-10); + 1e-10, 1e-12); CHECK_CLOSE_OR_SMALL(gap2->transform().matrix(), gap2Transform.matrix(), - 1e-10, 1e-10); + 1e-10, 1e-12); // Original volumes did not changes bounds for (const auto& [volume, bounds] : zip(origVolumes, originalBounds)) { const auto* newBounds = dynamic_cast(&volume->volumeBounds()); - BOOST_CHECK_EQUAL(newBounds->get(boundDir), bounds.get(boundDir)); + BOOST_CHECK_CLOSE(newBounds->get(boundDir), bounds.get(boundDir), 1e-6); } // No expansion, original volumes did not move @@ -241,32 +241,32 @@ BOOST_DATA_TEST_CASE(BaselineLocal, // Volume 1 got bigger and shifted right auto newBounds1 = dynamic_cast(&vol1->volumeBounds()); - BOOST_CHECK_EQUAL(newBounds1->get(boundDir), halfDir + wGap / 2.0); + BOOST_CHECK_CLOSE(newBounds1->get(boundDir), halfDir + wGap / 2.0, 1e-6); double pDir1 = -2 * halfDir * shift + wGap / 2.0; Translation3 expectedTranslation1(Vector3::Unit(dirIdx) * pDir1); Transform3 expectedTransform1 = base * expectedTranslation1; CHECK_CLOSE_OR_SMALL(vol1->transform().matrix(), - expectedTransform1.matrix(), 1e-10, 1e-10); + expectedTransform1.matrix(), 1e-10, 1e-12); // Volume 2 got bigger and shifted left auto newBounds2 = dynamic_cast(&vol2->volumeBounds()); - BOOST_CHECK_EQUAL(newBounds2->get(boundDir), halfDir + wGap / 2.0); + BOOST_CHECK_CLOSE(newBounds2->get(boundDir), halfDir + wGap / 2.0, 1e-6); double pDir2 = wGap / 2.0; Translation3 expectedTranslation2(Vector3::Unit(dirIdx) * pDir2); Transform3 expectedTransform2 = base * expectedTranslation2; CHECK_CLOSE_OR_SMALL(vol2->transform().matrix(), - expectedTransform2.matrix(), 1e-10, 1e-10); + expectedTransform2.matrix(), 1e-10, 1e-12); // Volume 3 stayed the same auto newBounds3 = dynamic_cast(&vol3->volumeBounds()); - BOOST_CHECK_EQUAL(newBounds3->get(boundDir), halfDir); + BOOST_CHECK_CLOSE(newBounds3->get(boundDir), halfDir, 1e-6); double pDir3 = 2 * halfDir * shift; Translation3 expectedTranslation3(Vector3::Unit(dirIdx) * pDir3); Transform3 expectedTransform3 = base * expectedTranslation3; CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(), - expectedTransform3.matrix(), 1e-10, 1e-10); + expectedTransform3.matrix(), 1e-10, 1e-12); } else if (strategy == VolumeAttachmentStrategy::Second) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -276,32 +276,32 @@ BOOST_DATA_TEST_CASE(BaselineLocal, // Volume 1 stayed the same auto newBounds1 = dynamic_cast(&vol1->volumeBounds()); - BOOST_CHECK_EQUAL(newBounds1->get(boundDir), halfDir); + BOOST_CHECK_CLOSE(newBounds1->get(boundDir), halfDir, 1e-6); double pDir1 = -2 * halfDir * shift; Translation3 expectedTranslation1(Vector3::Unit(dirIdx) * pDir1); Transform3 expectedTransform1 = base * expectedTranslation1; CHECK_CLOSE_OR_SMALL(vol1->transform().matrix(), - expectedTransform1.matrix(), 1e-10, 1e-10); + expectedTransform1.matrix(), 1e-10, 1e-12); // Volume 2 got bigger and shifted left auto newBounds2 = dynamic_cast(&vol2->volumeBounds()); - BOOST_CHECK_EQUAL(newBounds2->get(boundDir), halfDir + wGap / 2.0); + BOOST_CHECK_CLOSE(newBounds2->get(boundDir), halfDir + wGap / 2.0, 1e-6); double pDir2 = -wGap / 2.0; Translation3 expectedTranslation2(Vector3::Unit(dirIdx) * pDir2); Transform3 expectedTransform2 = base * expectedTranslation2; CHECK_CLOSE_OR_SMALL(vol2->transform().matrix(), - expectedTransform2.matrix(), 1e-10, 1e-10); + expectedTransform2.matrix(), 1e-10, 1e-12); // Volume 3 got bigger and shifted left auto newBounds3 = dynamic_cast(&vol3->volumeBounds()); - BOOST_CHECK_EQUAL(newBounds3->get(boundDir), halfDir + wGap / 2.0); + BOOST_CHECK_CLOSE(newBounds3->get(boundDir), halfDir + wGap / 2.0, 1e-6); double pDir3 = 2 * halfDir * shift - wGap / 2.0; Translation3 expectedTranslation3(Vector3::Unit(dirIdx) * pDir3); Transform3 expectedTransform3 = base * expectedTranslation3; CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(), - expectedTransform3.matrix(), 1e-10, 1e-10); + expectedTransform3.matrix(), 1e-10, 1e-12); } else if (strategy == VolumeAttachmentStrategy::Midpoint) { // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -311,29 +311,29 @@ BOOST_DATA_TEST_CASE(BaselineLocal, // Volume 1 got bigger and shifted right auto newBounds1 = dynamic_cast(&vol1->volumeBounds()); - BOOST_CHECK_EQUAL(newBounds1->get(boundDir), halfDir + wGap / 4.0); + BOOST_CHECK_CLOSE(newBounds1->get(boundDir), halfDir + wGap / 4.0, 1e-6); double pDir1 = -2 * halfDir * shift + wGap / 4.0; Translation3 expectedTranslation1(Vector3::Unit(dirIdx) * pDir1); Transform3 expectedTransform1 = base * expectedTranslation1; CHECK_CLOSE_OR_SMALL(vol1->transform().matrix(), - expectedTransform1.matrix(), 1e-10, 1e-10); + expectedTransform1.matrix(), 1e-10, 1e-12); // Volume 2 got bigger but didn't move auto newBounds2 = dynamic_cast(&vol2->volumeBounds()); - BOOST_CHECK_EQUAL(newBounds2->get(boundDir), halfDir + wGap / 2.0); + BOOST_CHECK_CLOSE(newBounds2->get(boundDir), halfDir + wGap / 2.0, 1e-6); CHECK_CLOSE_OR_SMALL(vol2->transform().matrix(), base.matrix(), 1e-10, - 1e-10); + 1e-12); // Volume 3 got bigger and shifted left auto newBounds3 = dynamic_cast(&vol3->volumeBounds()); - BOOST_CHECK_EQUAL(newBounds3->get(boundDir), halfDir + wGap / 4.0); + BOOST_CHECK_CLOSE(newBounds3->get(boundDir), halfDir + wGap / 4.0, 1e-6); double pDir3 = 2 * halfDir * shift - wGap / 4.0; Translation3 expectedTranslation3(Vector3::Unit(dirIdx) * pDir3); Transform3 expectedTransform3 = base * expectedTranslation3; CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(), - expectedTransform3.matrix(), 1e-10, 1e-10); + expectedTransform3.matrix(), 1e-10, 1e-12); } } } @@ -404,7 +404,7 @@ BOOST_DATA_TEST_CASE(BaselineGlobal, BOOST_CHECK_NE(stackBoundsAxisDirection, nullptr); BOOST_CHECK_EQUAL(*stackBoundsOrientation, *stackBoundsAxisDirection); CHECK_CLOSE_OR_SMALL(stackOrientation.transform().matrix(), - stackAxisDirection.transform().matrix(), 1e-10, 1e-10); + stackAxisDirection.transform().matrix(), 1e-10, 1e-12); } BOOST_DATA_TEST_CASE(Asymmetric, @@ -467,16 +467,16 @@ BOOST_DATA_TEST_CASE(Asymmetric, dynamic_cast(&stack.volumeBounds()); BOOST_REQUIRE(stackBounds != nullptr); - BOOST_CHECK_EQUAL(stackBounds->get(boundDirOrth1), 300_mm); - BOOST_CHECK_EQUAL(stackBounds->get(boundDirOrth2), 600_mm); - BOOST_CHECK_EQUAL(stackBounds->get(boundDir), - (std::abs(pDir1 - halfDir1) + pDir3 + halfDir3) / 2.0); + BOOST_CHECK_CLOSE(stackBounds->get(boundDirOrth1), 300_mm, 1e-6); + BOOST_CHECK_CLOSE(stackBounds->get(boundDirOrth2), 600_mm, 1e-6); + BOOST_CHECK_CLOSE(stackBounds->get(boundDir), + (std::abs(pDir1 - halfDir1) + pDir3 + halfDir3) / 2.0, 1e-6); double midDir = (pDir1 - halfDir1 + pDir3 + halfDir3) / 2.0; Translation3 expectedTranslation(Vector3::Unit(dirIdx) * midDir); Transform3 expectedTransform = Transform3::Identity() * expectedTranslation; CHECK_CLOSE_OR_SMALL(stack.transform().matrix(), expectedTransform.matrix(), - 1e-10, 1e-10); + 1e-10, 1e-12); } BOOST_DATA_TEST_CASE(UpdateStack, @@ -555,9 +555,9 @@ BOOST_DATA_TEST_CASE(UpdateStack, dynamic_cast(&stack.volumeBounds()); BOOST_REQUIRE(bounds != nullptr); BOOST_CHECK_EQUAL(bounds, originalBounds); - BOOST_CHECK_EQUAL(bounds->get(boundDirOrth1), 100_mm); - BOOST_CHECK_EQUAL(bounds->get(boundDirOrth2), 600_mm); - BOOST_CHECK_EQUAL(bounds->get(boundDir), 3 * halfDir); + BOOST_CHECK_CLOSE(bounds->get(boundDirOrth1), 100_mm, 1e-6); + BOOST_CHECK_CLOSE(bounds->get(boundDirOrth2), 600_mm, 1e-6); + BOOST_CHECK_CLOSE(bounds->get(boundDir), 3 * halfDir, 1e-6); }; assertOriginalBounds(); @@ -609,9 +609,9 @@ BOOST_DATA_TEST_CASE(UpdateStack, const auto* updatedBounds = dynamic_cast(&stack.volumeBounds()); BOOST_REQUIRE(updatedBounds != nullptr); - BOOST_CHECK_EQUAL(updatedBounds->get(boundDirOrth1), 700_mm); - BOOST_CHECK_EQUAL(updatedBounds->get(boundDirOrth2), 600_mm); - BOOST_CHECK_EQUAL(updatedBounds->get(boundDir), 3 * halfDir); + BOOST_CHECK_CLOSE(updatedBounds->get(boundDirOrth1), 700_mm, 1e-6); + BOOST_CHECK_CLOSE(updatedBounds->get(boundDirOrth2), 600_mm, 1e-6); + BOOST_CHECK_CLOSE(updatedBounds->get(boundDir), 3 * halfDir, 1e-6); // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -621,9 +621,9 @@ BOOST_DATA_TEST_CASE(UpdateStack, zip(volumes, originalTransforms)) { const auto* newBounds = dynamic_cast(&volume->volumeBounds()); - BOOST_CHECK_EQUAL(newBounds->get(boundDirOrth1), 700_mm); - BOOST_CHECK_EQUAL(newBounds->get(boundDirOrth2), 600_mm); - BOOST_CHECK_EQUAL(newBounds->get(boundDir), halfDir); + BOOST_CHECK_CLOSE(newBounds->get(boundDirOrth1), 700_mm, 1e-6); + BOOST_CHECK_CLOSE(newBounds->get(boundDirOrth2), 600_mm, 1e-6); + BOOST_CHECK_CLOSE(newBounds->get(boundDir), halfDir, 1e-6); // Position stayed the same BOOST_CHECK_EQUAL(volume->transform().matrix(), origTransform.matrix()); @@ -638,9 +638,9 @@ BOOST_DATA_TEST_CASE(UpdateStack, const auto* updatedBounds = dynamic_cast(&stack.volumeBounds()); BOOST_REQUIRE(updatedBounds != nullptr); - BOOST_CHECK_EQUAL(updatedBounds->get(boundDirOrth1), 700_mm); - BOOST_CHECK_EQUAL(updatedBounds->get(boundDirOrth2), 700_mm); - BOOST_CHECK_EQUAL(updatedBounds->get(boundDir), 3 * halfDir); + BOOST_CHECK_CLOSE(updatedBounds->get(boundDirOrth1), 700_mm, 1e-6); + BOOST_CHECK_CLOSE(updatedBounds->get(boundDirOrth2), 700_mm, 1e-6); + BOOST_CHECK_CLOSE(updatedBounds->get(boundDir), 3 * halfDir, 1e-6); // No gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 3); @@ -650,9 +650,9 @@ BOOST_DATA_TEST_CASE(UpdateStack, zip(volumes, originalTransforms)) { const auto* newBounds = dynamic_cast(&volume->volumeBounds()); - BOOST_CHECK_EQUAL(newBounds->get(boundDirOrth1), 700_mm); - BOOST_CHECK_EQUAL(newBounds->get(boundDirOrth2), 700_mm); - BOOST_CHECK_EQUAL(newBounds->get(boundDir), halfDir); + BOOST_CHECK_CLOSE(newBounds->get(boundDirOrth1), 700_mm, 1e-6); + BOOST_CHECK_CLOSE(newBounds->get(boundDirOrth2), 700_mm, 1e-6); + BOOST_CHECK_CLOSE(newBounds->get(boundDir), halfDir, 1e-6); // Position stayed the same BOOST_CHECK_EQUAL(volume->transform().matrix(), origTransform.matrix()); @@ -668,9 +668,9 @@ BOOST_DATA_TEST_CASE(UpdateStack, const auto* updatedBounds = dynamic_cast(&stack.volumeBounds()); BOOST_REQUIRE(updatedBounds != nullptr); - BOOST_CHECK_EQUAL(updatedBounds->get(boundDir), 4 * halfDir); - BOOST_CHECK_EQUAL(updatedBounds->get(boundDirOrth1), 700_mm); - BOOST_CHECK_EQUAL(updatedBounds->get(boundDirOrth2), 700_mm); + BOOST_CHECK_CLOSE(updatedBounds->get(boundDir), 4 * halfDir, 1e-6); + BOOST_CHECK_CLOSE(updatedBounds->get(boundDirOrth1), 700_mm, 1e-6); + BOOST_CHECK_CLOSE(updatedBounds->get(boundDirOrth2), 700_mm, 1e-6); if (strategy == VolumeResizeStrategy::Expand) { // No gap volumes were added @@ -679,7 +679,7 @@ BOOST_DATA_TEST_CASE(UpdateStack, // Volume 1 got bigger and shifted left auto newBounds1 = dynamic_cast(&vol1->volumeBounds()); - BOOST_CHECK_EQUAL(newBounds1->get(boundDir), halfDir + halfDir / 2.0); + BOOST_CHECK_CLOSE(newBounds1->get(boundDir), halfDir + halfDir / 2.0, 1e-6); auto expectedTranslation1 = Translation3(Vector3::Unit(dirIdx) * (-2 * halfDir - halfDir / 2.0)); Transform3 expectedTransform1 = base * expectedTranslation1; @@ -689,13 +689,13 @@ BOOST_DATA_TEST_CASE(UpdateStack, // Volume 2 stayed the same auto newBounds2 = dynamic_cast(&vol2->volumeBounds()); - BOOST_CHECK_EQUAL(newBounds2->get(boundDir), halfDir); + BOOST_CHECK_CLOSE(newBounds2->get(boundDir), halfDir, 1e-6); BOOST_CHECK_EQUAL(vol2->transform().matrix(), transform2.matrix()); // Volume 3 got bigger and shifted right auto newBounds3 = dynamic_cast(&vol3->volumeBounds()); - BOOST_CHECK_EQUAL(newBounds3->get(boundDir), halfDir + halfDir / 2.0); + BOOST_CHECK_CLOSE(newBounds3->get(boundDir), halfDir + halfDir / 2.0, 1e-6); auto expectedTranslation3 = Translation3(Vector3::Unit(dirIdx) * (2 * halfDir + halfDir / 2.0)); Transform3 expectedTransform3 = base * expectedTranslation3; @@ -709,9 +709,9 @@ BOOST_DATA_TEST_CASE(UpdateStack, zip(originalVolumes, originalTransforms)) { const auto* newBounds = dynamic_cast(&volume->volumeBounds()); - BOOST_CHECK_EQUAL(newBounds->get(boundDirOrth1), 700_mm); - BOOST_CHECK_EQUAL(newBounds->get(boundDirOrth2), 700_mm); - BOOST_CHECK_EQUAL(newBounds->get(boundDir), halfDir); + BOOST_CHECK_CLOSE(newBounds->get(boundDirOrth1), 700_mm, 1e-6); + BOOST_CHECK_CLOSE(newBounds->get(boundDirOrth2), 700_mm, 1e-6); + BOOST_CHECK_CLOSE(newBounds->get(boundDir), halfDir, 1e-6); // Position stayed the same BOOST_CHECK_EQUAL(volume->transform().matrix(), origTransform.matrix()); } @@ -724,8 +724,8 @@ BOOST_DATA_TEST_CASE(UpdateStack, const auto* gapBounds2 = dynamic_cast(&gap2->volumeBounds()); - BOOST_CHECK_EQUAL(gapBounds1->get(boundDir), halfDir / 2.0); - BOOST_CHECK_EQUAL(gapBounds2->get(boundDir), halfDir / 2.0); + BOOST_CHECK_CLOSE(gapBounds1->get(boundDir), halfDir / 2.0, 1e-6); + BOOST_CHECK_CLOSE(gapBounds2->get(boundDir), halfDir / 2.0, 1e-6); auto gap1Translation = Translation3(Vector3::Unit(dirIdx) * (-3 * halfDir - halfDir / 2.0)); Transform3 gap1Transform = base * gap1Translation; @@ -734,9 +734,9 @@ BOOST_DATA_TEST_CASE(UpdateStack, Translation3(Vector3::Unit(dirIdx) * (3 * halfDir + halfDir / 2.0)); Transform3 gap2Transform = base * gap2Translation; CHECK_CLOSE_OR_SMALL(gap1->transform().matrix(), gap1Transform.matrix(), - 1e-10, 1e-10); + 1e-10, 1e-12); CHECK_CLOSE_OR_SMALL(gap2->transform().matrix(), gap2Transform.matrix(), - 1e-10, 1e-10); + 1e-10, 1e-12); } } } @@ -837,15 +837,15 @@ BOOST_DATA_TEST_CASE( const auto* bounds = dynamic_cast(&stack.volumeBounds()); BOOST_REQUIRE(bounds != nullptr); - BOOST_CHECK_EQUAL(bounds->get(boundDir), 950_mm); + BOOST_CHECK_CLOSE(bounds->get(boundDir), 950_mm, 1e-6); // All volumes including gaps should have same size in orthogonal plane for (const auto* vol : volumes) { const auto* volBounds = dynamic_cast(&vol->volumeBounds()); BOOST_REQUIRE(volBounds != nullptr); - BOOST_CHECK_EQUAL(volBounds->get(boundDirOrth1), 100_mm); - BOOST_CHECK_EQUAL(volBounds->get(boundDirOrth2), 300_mm); + BOOST_CHECK_CLOSE(volBounds->get(boundDirOrth1), 100_mm, 1e-6); + BOOST_CHECK_CLOSE(volBounds->get(boundDirOrth2), 300_mm, 1e-6); } if (strategy == VolumeResizeStrategy::Expand) { @@ -863,7 +863,7 @@ BOOST_DATA_TEST_CASE( const auto* volBounds = dynamic_cast(&vol->volumeBounds()); BOOST_REQUIRE(volBounds != nullptr); - BOOST_CHECK_EQUAL(volBounds->get(boundDir), 450_mm); + BOOST_CHECK_CLOSE(volBounds->get(boundDir), 450_mm, 1e-6); BOOST_CHECK_EQUAL(vol->center()[dirIdx], f * 550_mm); } else if (strategy == VolumeResizeStrategy::Gap) { // One gap volume was added @@ -879,7 +879,7 @@ BOOST_DATA_TEST_CASE( dynamic_cast(&gap->volumeBounds()); BOOST_REQUIRE(gapBounds != nullptr); - BOOST_CHECK_EQUAL(gapBounds->get(boundDir), 50_mm); + BOOST_CHECK_CLOSE(gapBounds->get(boundDir), 50_mm, 1e-6); BOOST_CHECK_EQUAL(gap->center()[dirIdx], f * 950_mm); } } @@ -952,7 +952,7 @@ BOOST_DATA_TEST_CASE(ResizeGapMultiple, const auto* updatedBounds = dynamic_cast( &stack.gaps().front()->volumeBounds()); BOOST_REQUIRE_NE(updatedBounds, nullptr); - BOOST_CHECK_EQUAL(updatedBounds->get(boundDir), 100.0); + BOOST_CHECK_CLOSE(updatedBounds->get(boundDir), 100.0, 1e-6); auto newBounds2 = std::make_shared( std::initializer_list< @@ -969,7 +969,7 @@ BOOST_DATA_TEST_CASE(ResizeGapMultiple, updatedBounds = dynamic_cast( &stack.gaps().front()->volumeBounds()); BOOST_REQUIRE_NE(updatedBounds, nullptr); - BOOST_CHECK_EQUAL(updatedBounds->get(boundDir), 200.0); + BOOST_CHECK_CLOSE(updatedBounds->get(boundDir), 200.0, 1e-6); } BOOST_TEST_CONTEXT("Negative") { @@ -993,7 +993,7 @@ BOOST_DATA_TEST_CASE(ResizeGapMultiple, const auto* updatedBounds = dynamic_cast( &stack.gaps().front()->volumeBounds()); BOOST_REQUIRE_NE(updatedBounds, nullptr); - BOOST_CHECK_EQUAL(updatedBounds->get(boundDir), 100.0); + BOOST_CHECK_CLOSE(updatedBounds->get(boundDir), 100.0, 1e-6); auto newBounds2 = std::make_shared( std::initializer_list< @@ -1010,7 +1010,7 @@ BOOST_DATA_TEST_CASE(ResizeGapMultiple, updatedBounds = dynamic_cast( &stack.gaps().front()->volumeBounds()); BOOST_REQUIRE_NE(updatedBounds, nullptr); - BOOST_CHECK_EQUAL(updatedBounds->get(boundDir), 200.0); + BOOST_CHECK_CLOSE(updatedBounds->get(boundDir), 200.0, 1e-6); } } From 98041910c760dc9300d2508821cc38790c295c03 Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Wed, 22 Jan 2025 17:48:19 +0200 Subject: [PATCH 19/22] another macos fix --- .../Core/Geometry/CuboidVolumeStackTests.cpp | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp b/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp index 1e20163910a..b9f57d2fe4f 100644 --- a/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp +++ b/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp @@ -151,7 +151,8 @@ BOOST_DATA_TEST_CASE(BaselineLocal, BOOST_CHECK_CLOSE(stackBounds->get(boundDirOrth1), 300_mm, 1e-6); BOOST_CHECK_CLOSE(stackBounds->get(boundDirOrth2), 600_mm, 1e-6); - BOOST_CHECK_CLOSE(stackBounds->get(boundDir), halfDir + 2 * halfDir * shift, 1e-6); + BOOST_CHECK_CLOSE(stackBounds->get(boundDir), halfDir + 2 * halfDir * shift, + 1e-6); CHECK_CLOSE_OR_SMALL(stack.transform().matrix(), base.matrix(), 1e-10, 1e-12); // All volumes (including gaps) are cuboids and have the same orthogonal @@ -470,7 +471,8 @@ BOOST_DATA_TEST_CASE(Asymmetric, BOOST_CHECK_CLOSE(stackBounds->get(boundDirOrth1), 300_mm, 1e-6); BOOST_CHECK_CLOSE(stackBounds->get(boundDirOrth2), 600_mm, 1e-6); BOOST_CHECK_CLOSE(stackBounds->get(boundDir), - (std::abs(pDir1 - halfDir1) + pDir3 + halfDir3) / 2.0, 1e-6); + (std::abs(pDir1 - halfDir1) + pDir3 + halfDir3) / 2.0, + 1e-6); double midDir = (pDir1 - halfDir1 + pDir3 + halfDir3) / 2.0; Translation3 expectedTranslation(Vector3::Unit(dirIdx) * midDir); @@ -679,28 +681,31 @@ BOOST_DATA_TEST_CASE(UpdateStack, // Volume 1 got bigger and shifted left auto newBounds1 = dynamic_cast(&vol1->volumeBounds()); - BOOST_CHECK_CLOSE(newBounds1->get(boundDir), halfDir + halfDir / 2.0, 1e-6); + BOOST_CHECK_CLOSE(newBounds1->get(boundDir), halfDir + halfDir / 2.0, + 1e-6); auto expectedTranslation1 = Translation3(Vector3::Unit(dirIdx) * (-2 * halfDir - halfDir / 2.0)); Transform3 expectedTransform1 = base * expectedTranslation1; - BOOST_CHECK_EQUAL(vol1->transform().matrix(), - expectedTransform1.matrix()); + CHECK_CLOSE_OR_SMALL(vol1->transform().matrix(), + expectedTransform1.matrix(), 1e-10, 1e-12); // Volume 2 stayed the same auto newBounds2 = dynamic_cast(&vol2->volumeBounds()); BOOST_CHECK_CLOSE(newBounds2->get(boundDir), halfDir, 1e-6); - BOOST_CHECK_EQUAL(vol2->transform().matrix(), transform2.matrix()); + CHECK_CLOSE_OR_SMALL(vol2->transform().matrix(), transform2.matrix(), + 1e-10, 1e-12); // Volume 3 got bigger and shifted right auto newBounds3 = dynamic_cast(&vol3->volumeBounds()); - BOOST_CHECK_CLOSE(newBounds3->get(boundDir), halfDir + halfDir / 2.0, 1e-6); + BOOST_CHECK_CLOSE(newBounds3->get(boundDir), halfDir + halfDir / 2.0, + 1e-6); auto expectedTranslation3 = Translation3(Vector3::Unit(dirIdx) * (2 * halfDir + halfDir / 2.0)); Transform3 expectedTransform3 = base * expectedTranslation3; - BOOST_CHECK_EQUAL(vol3->transform().matrix(), - expectedTransform3.matrix()); + CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(), + expectedTransform3.matrix(), 1e-10, 1e-12); } else if (strategy == VolumeResizeStrategy::Gap) { // Gap volumes were added BOOST_CHECK_EQUAL(volumes.size(), 5); @@ -713,7 +718,8 @@ BOOST_DATA_TEST_CASE(UpdateStack, BOOST_CHECK_CLOSE(newBounds->get(boundDirOrth2), 700_mm, 1e-6); BOOST_CHECK_CLOSE(newBounds->get(boundDir), halfDir, 1e-6); // Position stayed the same - BOOST_CHECK_EQUAL(volume->transform().matrix(), origTransform.matrix()); + CHECK_CLOSE_OR_SMALL(volume->transform().matrix(), + origTransform.matrix(), 1e-10, 1e-12); } auto gap1 = volumes.front(); @@ -833,7 +839,7 @@ BOOST_DATA_TEST_CASE( stack.update(newBounds, trf, *logger); - BOOST_CHECK_EQUAL(stack.transform().matrix(), trf.matrix()); + CHECK_CLOSE_OR_SMALL(stack.transform().matrix(), trf.matrix(), 1e-10, 1e-12); const auto* bounds = dynamic_cast(&stack.volumeBounds()); BOOST_REQUIRE(bounds != nullptr); From da406deff6fb2496f0c33bde8b277f6c22107118 Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Wed, 22 Jan 2025 19:51:23 +0200 Subject: [PATCH 20/22] tidy --- Core/src/Geometry/CuboidVolumeBounds.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/Geometry/CuboidVolumeBounds.cpp b/Core/src/Geometry/CuboidVolumeBounds.cpp index 6ed99943deb..42ca25ebc1a 100644 --- a/Core/src/Geometry/CuboidVolumeBounds.cpp +++ b/Core/src/Geometry/CuboidVolumeBounds.cpp @@ -35,8 +35,8 @@ CuboidVolumeBounds::CuboidVolumeBounds(const std::array& values) } CuboidVolumeBounds::CuboidVolumeBounds( - std::initializer_list> keyValues) { - m_values = {-1, -1, -1}; + std::initializer_list> keyValues) + : m_values({-1, -1, -1}) { for (const auto& [key, value] : keyValues) { m_values[key] = value; } From 78aa5b0ebac539b4ec861a5c54059d8f3aeb2cc5 Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Thu, 23 Jan 2025 15:15:28 +0200 Subject: [PATCH 21/22] strategies and python bindings --- Core/include/Acts/Geometry/CuboidVolumeStack.hpp | 4 ++-- .../Acts/Geometry/CylinderContainerBlueprintNode.hpp | 4 ++-- Core/include/Acts/Geometry/CylinderVolumeStack.hpp | 4 ++-- .../{detail => }/VolumeAttachmentStrategy.hpp | 0 .../Geometry/{detail => }/VolumeResizeStrategy.hpp | 0 Core/src/Geometry/CMakeLists.txt | 4 ++-- .../{detail => }/VolumeAttachmentStrategy.cpp | 2 +- .../Geometry/{detail => }/VolumeResizeStrategy.cpp | 2 +- Examples/Python/src/Blueprint.cpp | 4 ++-- Examples/Python/src/Geometry.cpp | 11 ++++------- Tests/UnitTests/Core/Geometry/BlueprintApiTests.cpp | 4 ++-- Tests/UnitTests/Core/Geometry/BlueprintTests.cpp | 2 +- .../Core/Geometry/CuboidVolumeStackTests.cpp | 4 ++-- .../Core/Geometry/CylinderVolumeStackTests.cpp | 4 ++-- 14 files changed, 23 insertions(+), 26 deletions(-) rename Core/include/Acts/Geometry/{detail => }/VolumeAttachmentStrategy.hpp (100%) rename Core/include/Acts/Geometry/{detail => }/VolumeResizeStrategy.hpp (100%) rename Core/src/Geometry/{detail => }/VolumeAttachmentStrategy.cpp (93%) rename Core/src/Geometry/{detail => }/VolumeResizeStrategy.cpp (92%) diff --git a/Core/include/Acts/Geometry/CuboidVolumeStack.hpp b/Core/include/Acts/Geometry/CuboidVolumeStack.hpp index e91e721e9e8..4485ce170c5 100644 --- a/Core/include/Acts/Geometry/CuboidVolumeStack.hpp +++ b/Core/include/Acts/Geometry/CuboidVolumeStack.hpp @@ -10,8 +10,8 @@ #include "Acts/Definitions/Algebra.hpp" #include "Acts/Geometry/Volume.hpp" -#include "Acts/Geometry/detail/VolumeAttachmentStrategy.hpp" -#include "Acts/Geometry/detail/VolumeResizeStrategy.hpp" +#include "Acts/Geometry/VolumeAttachmentStrategy.hpp" +#include "Acts/Geometry/VolumeResizeStrategy.hpp" #include "Acts/Utilities/AxisDefinitions.hpp" #include "Acts/Utilities/Logger.hpp" diff --git a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp index 339cc033f95..9731715de1e 100644 --- a/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp +++ b/Core/include/Acts/Geometry/CylinderContainerBlueprintNode.hpp @@ -11,8 +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/Geometry/VolumeAttachmentStrategy.hpp" +#include "Acts/Geometry/VolumeResizeStrategy.hpp" #include "Acts/Utilities/AxisDefinitions.hpp" #include "Acts/Utilities/Logger.hpp" diff --git a/Core/include/Acts/Geometry/CylinderVolumeStack.hpp b/Core/include/Acts/Geometry/CylinderVolumeStack.hpp index f669f7d9daa..44fa11b5ecf 100644 --- a/Core/include/Acts/Geometry/CylinderVolumeStack.hpp +++ b/Core/include/Acts/Geometry/CylinderVolumeStack.hpp @@ -11,8 +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/Geometry/VolumeAttachmentStrategy.hpp" +#include "Acts/Geometry/VolumeResizeStrategy.hpp" #include "Acts/Utilities/AxisDefinitions.hpp" #include "Acts/Utilities/Logger.hpp" diff --git a/Core/include/Acts/Geometry/detail/VolumeAttachmentStrategy.hpp b/Core/include/Acts/Geometry/VolumeAttachmentStrategy.hpp similarity index 100% rename from Core/include/Acts/Geometry/detail/VolumeAttachmentStrategy.hpp rename to Core/include/Acts/Geometry/VolumeAttachmentStrategy.hpp diff --git a/Core/include/Acts/Geometry/detail/VolumeResizeStrategy.hpp b/Core/include/Acts/Geometry/VolumeResizeStrategy.hpp similarity index 100% rename from Core/include/Acts/Geometry/detail/VolumeResizeStrategy.hpp rename to Core/include/Acts/Geometry/VolumeResizeStrategy.hpp diff --git a/Core/src/Geometry/CMakeLists.txt b/Core/src/Geometry/CMakeLists.txt index 19585591c45..2ed76752198 100644 --- a/Core/src/Geometry/CMakeLists.txt +++ b/Core/src/Geometry/CMakeLists.txt @@ -51,6 +51,6 @@ target_sources( StaticBlueprintNode.cpp LayerBlueprintNode.cpp MaterialDesignatorBlueprintNode.cpp - detail/VolumeAttachmentStrategy.cpp - detail/VolumeResizeStrategy.cpp + VolumeAttachmentStrategy.cpp + VolumeResizeStrategy.cpp ) diff --git a/Core/src/Geometry/detail/VolumeAttachmentStrategy.cpp b/Core/src/Geometry/VolumeAttachmentStrategy.cpp similarity index 93% rename from Core/src/Geometry/detail/VolumeAttachmentStrategy.cpp rename to Core/src/Geometry/VolumeAttachmentStrategy.cpp index 4164c7aa1bf..425328b7bd4 100644 --- a/Core/src/Geometry/detail/VolumeAttachmentStrategy.cpp +++ b/Core/src/Geometry/VolumeAttachmentStrategy.cpp @@ -6,7 +6,7 @@ // 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/. -#include "Acts/Geometry/detail/VolumeAttachmentStrategy.hpp" +#include "Acts/Geometry/VolumeAttachmentStrategy.hpp" namespace Acts { std::ostream& operator<<(std::ostream& os, VolumeAttachmentStrategy strategy) { diff --git a/Core/src/Geometry/detail/VolumeResizeStrategy.cpp b/Core/src/Geometry/VolumeResizeStrategy.cpp similarity index 92% rename from Core/src/Geometry/detail/VolumeResizeStrategy.cpp rename to Core/src/Geometry/VolumeResizeStrategy.cpp index 8ea7ebaa4bd..c8a382edad9 100644 --- a/Core/src/Geometry/detail/VolumeResizeStrategy.cpp +++ b/Core/src/Geometry/VolumeResizeStrategy.cpp @@ -6,7 +6,7 @@ // 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/. -#include "Acts/Geometry/detail/VolumeResizeStrategy.hpp" +#include "Acts/Geometry/VolumeResizeStrategy.hpp" namespace Acts { diff --git a/Examples/Python/src/Blueprint.cpp b/Examples/Python/src/Blueprint.cpp index 0fc16095e21..8f14f1c89e9 100644 --- a/Examples/Python/src/Blueprint.cpp +++ b/Examples/Python/src/Blueprint.cpp @@ -15,8 +15,8 @@ #include "Acts/Geometry/LayerBlueprintNode.hpp" #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" -#include "Acts/Geometry/detail/VolumeAttachmentStrategy.hpp" -#include "Acts/Geometry/detail/VolumeResizeStrategy.hpp" +#include "Acts/Geometry/VolumeAttachmentStrategy.hpp" +#include "Acts/Geometry/VolumeResizeStrategy.hpp" #include "Acts/Navigation/NavigationStream.hpp" #include "Acts/Plugins/Python/Utilities.hpp" #include "Acts/Utilities/AxisDefinitions.hpp" diff --git a/Examples/Python/src/Geometry.cpp b/Examples/Python/src/Geometry.cpp index 1cc85e4583d..9ee03e85f32 100644 --- a/Examples/Python/src/Geometry.cpp +++ b/Examples/Python/src/Geometry.cpp @@ -34,8 +34,8 @@ #include "Acts/Geometry/TrackingGeometry.hpp" #include "Acts/Geometry/Volume.hpp" #include "Acts/Geometry/VolumeBounds.hpp" -#include "Acts/Geometry/detail/VolumeAttachmentStrategy.hpp" -#include "Acts/Geometry/detail/VolumeResizeStrategy.hpp" +#include "Acts/Geometry/VolumeAttachmentStrategy.hpp" +#include "Acts/Geometry/VolumeResizeStrategy.hpp" #include "Acts/Material/ISurfaceMaterial.hpp" #include "Acts/Plugins/Python/Utilities.hpp" #include "Acts/Surfaces/Surface.hpp" @@ -99,7 +99,6 @@ void addBlueprint(Context& ctx); void addGeometry(Context& ctx) { auto m = ctx.get("main"); - { py::class_(m, "GeometryIdentifier") .def(py::init<>()) @@ -294,15 +293,13 @@ void addGeometry(Context& ctx) { .def("__str__", &Extent::toString); { - auto cylStack = py::class_(m, "CylinderVolumeStack"); - - py::enum_(cylStack, "AttachmentStrategy") + py::enum_(m, "VolumeAttachmentStrategy") .value("Gap", VolumeAttachmentStrategy::Gap) .value("First", VolumeAttachmentStrategy::First) .value("Second", VolumeAttachmentStrategy::Second) .value("Midpoint", VolumeAttachmentStrategy::Midpoint); - py::enum_(cylStack, "ResizeStrategy") + py::enum_(m, "VolumeResizeStrategy") .value("Gap", VolumeResizeStrategy::Gap) .value("Expand", VolumeResizeStrategy::Expand); } diff --git a/Tests/UnitTests/Core/Geometry/BlueprintApiTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintApiTests.cpp index 1617efa50d2..e3f748a07e8 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintApiTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintApiTests.cpp @@ -23,8 +23,8 @@ #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" #include "Acts/Geometry/TrackingGeometry.hpp" #include "Acts/Geometry/TrackingVolume.hpp" -#include "Acts/Geometry/detail/VolumeAttachmentStrategy.hpp" -#include "Acts/Geometry/detail/VolumeResizeStrategy.hpp" +#include "Acts/Geometry/VolumeAttachmentStrategy.hpp" +#include "Acts/Geometry/VolumeResizeStrategy.hpp" #include "Acts/Navigation/INavigationPolicy.hpp" #include "Acts/Navigation/NavigationStream.hpp" #include "Acts/Surfaces/RectangleBounds.hpp" diff --git a/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp b/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp index 33973661c9a..15a6263b8c7 100644 --- a/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp +++ b/Tests/UnitTests/Core/Geometry/BlueprintTests.cpp @@ -22,7 +22,7 @@ #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp" #include "Acts/Geometry/StaticBlueprintNode.hpp" #include "Acts/Geometry/TrackingVolume.hpp" -#include "Acts/Geometry/detail/VolumeAttachmentStrategy.hpp" +#include "Acts/Geometry/VolumeAttachmentStrategy.hpp" #include "Acts/Material/BinnedSurfaceMaterial.hpp" #include "Acts/Material/ProtoSurfaceMaterial.hpp" #include "Acts/Surfaces/RectangleBounds.hpp" diff --git a/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp b/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp index b9f57d2fe4f..ca35feb302a 100644 --- a/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp +++ b/Tests/UnitTests/Core/Geometry/CuboidVolumeStackTests.cpp @@ -19,8 +19,8 @@ #include "Acts/Definitions/Units.hpp" #include "Acts/Geometry/CuboidVolumeBounds.hpp" #include "Acts/Geometry/CuboidVolumeStack.hpp" -#include "Acts/Geometry/detail/VolumeAttachmentStrategy.hpp" -#include "Acts/Geometry/detail/VolumeResizeStrategy.hpp" +#include "Acts/Geometry/VolumeAttachmentStrategy.hpp" +#include "Acts/Geometry/VolumeResizeStrategy.hpp" #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp" #include "Acts/Utilities/AxisDefinitions.hpp" #include "Acts/Utilities/Logger.hpp" diff --git a/Tests/UnitTests/Core/Geometry/CylinderVolumeStackTests.cpp b/Tests/UnitTests/Core/Geometry/CylinderVolumeStackTests.cpp index 2935410ba6e..08523bd2b75 100644 --- a/Tests/UnitTests/Core/Geometry/CylinderVolumeStackTests.cpp +++ b/Tests/UnitTests/Core/Geometry/CylinderVolumeStackTests.cpp @@ -19,8 +19,8 @@ #include "Acts/Definitions/Units.hpp" #include "Acts/Geometry/CylinderVolumeBounds.hpp" #include "Acts/Geometry/CylinderVolumeStack.hpp" -#include "Acts/Geometry/detail/VolumeAttachmentStrategy.hpp" -#include "Acts/Geometry/detail/VolumeResizeStrategy.hpp" +#include "Acts/Geometry/VolumeAttachmentStrategy.hpp" +#include "Acts/Geometry/VolumeResizeStrategy.hpp" #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp" #include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/Logger.hpp" From b29763059f53ac41869fc229bfbfbf06b69a0b3e Mon Sep 17 00:00:00 2001 From: ssdetlab Date: Thu, 23 Jan 2025 15:23:38 +0200 Subject: [PATCH 22/22] lint --- Examples/Python/src/Geometry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Examples/Python/src/Geometry.cpp b/Examples/Python/src/Geometry.cpp index 9ee03e85f32..b0fbc40ed3e 100644 --- a/Examples/Python/src/Geometry.cpp +++ b/Examples/Python/src/Geometry.cpp @@ -33,8 +33,8 @@ #include "Acts/Geometry/ProtoLayer.hpp" #include "Acts/Geometry/TrackingGeometry.hpp" #include "Acts/Geometry/Volume.hpp" -#include "Acts/Geometry/VolumeBounds.hpp" #include "Acts/Geometry/VolumeAttachmentStrategy.hpp" +#include "Acts/Geometry/VolumeBounds.hpp" #include "Acts/Geometry/VolumeResizeStrategy.hpp" #include "Acts/Material/ISurfaceMaterial.hpp" #include "Acts/Plugins/Python/Utilities.hpp"