diff --git a/CI/physmon/reference/performance_amvf_gridseeder_seeded_hist.root b/CI/physmon/reference/performance_amvf_gridseeder_seeded_hist.root index df4b1db76b0..882a5fc6d30 100644 Binary files a/CI/physmon/reference/performance_amvf_gridseeder_seeded_hist.root and b/CI/physmon/reference/performance_amvf_gridseeder_seeded_hist.root differ diff --git a/Core/include/Acts/Detector/DetectorVolume.hpp b/Core/include/Acts/Detector/DetectorVolume.hpp index d16a06ca9cc..c0e6a91fb8c 100644 --- a/Core/include/Acts/Detector/DetectorVolume.hpp +++ b/Core/include/Acts/Detector/DetectorVolume.hpp @@ -484,6 +484,9 @@ class DetectorVolume : public std::enable_shared_from_this { /// @brief A detector volume factory which first constructs the detector volume /// and then constructs the portals. This ensures that the std::shared_ptr /// holding the detector volume is not weak when assigning to the portals. +/// +/// @note Optional containment check is invoked by setting the number +/// of segments nSeg to be greater than 0 class DetectorVolumeFactory { public: /// Create a detector volume - from factory @@ -494,11 +497,19 @@ class DetectorVolumeFactory { const std::vector>& surfaces, const std::vector>& volumes, DetectorVolumeUpdater detectorVolumeUpdater, - SurfaceCandidatesUpdater surfaceCandidateUpdater) { + SurfaceCandidatesUpdater surfaceCandidateUpdater, int nSeg = -1) { auto dVolume = DetectorVolume::makeShared( gctx, name, transform, std::move(bounds), surfaces, volumes, std::move(detectorVolumeUpdater), std::move(surfaceCandidateUpdater)); dVolume->construct(gctx, portalGenerator); + + /// Volume extent is constructed from the portals + /// So the surface/subvolume containment + /// check has to happen here + if (nSeg > 0 && !dVolume->checkContainment(gctx, nSeg)) { + throw std::invalid_argument( + "DetectorVolume: surfaces or subvolumes are not contained by volume"); + } return dVolume; } diff --git a/Core/include/Acts/Geometry/ConeVolumeBounds.hpp b/Core/include/Acts/Geometry/ConeVolumeBounds.hpp index 93b7283e9ae..c875f27b6b8 100644 --- a/Core/include/Acts/Geometry/ConeVolumeBounds.hpp +++ b/Core/include/Acts/Geometry/ConeVolumeBounds.hpp @@ -56,9 +56,10 @@ class ConeVolumeBounds : public VolumeBounds { /// @param halflengthZ The minimum z value of the inner and outer cones /// @param averagePhi The phi orientation of the sector /// @param halfPhiSector The opening angle phi sector - ConeVolumeBounds(double innerAlpha, double innerOffsetZ, double outerAlpha, - double outerOffsetZ, double halflengthZ, double averagePhi, - double halfPhiSector) noexcept(false); + ConeVolumeBounds(ActsScalar innerAlpha, ActsScalar innerOffsetZ, + ActsScalar outerAlpha, ActsScalar outerOffsetZ, + ActsScalar halflengthZ, ActsScalar averagePhi, + ActsScalar halfPhiSector) noexcept(false); /// Constructor - for general cylidner-cone setups /// @@ -71,14 +72,14 @@ class ConeVolumeBounds : public VolumeBounds { /// /// @note depending on cylinderR > coneR it is constructing a cone with /// cylindrical cutout or a cylinder with conical cutout - ConeVolumeBounds(double cylinderR, double alpha, double offsetZ, - double halflengthZ, double averagePhi, - double halfPhiSector) noexcept(false); + ConeVolumeBounds(ActsScalar cylinderR, ActsScalar alpha, ActsScalar offsetZ, + ActsScalar halflengthZ, ActsScalar averagePhi, + ActsScalar halfPhiSector) noexcept(false); /// Constructor - from a fixed size array /// /// @param values The bound values - ConeVolumeBounds(const std::array& values) noexcept(false) + ConeVolumeBounds(const std::array& values) noexcept(false) : m_values(values) { checkConsistency(); buildSurfaceBounds(); @@ -93,14 +94,14 @@ class ConeVolumeBounds : public VolumeBounds { /// Return the bound values as dynamically sized vector /// /// @return this returns a copy of the internal values - std::vector values() const final; + std::vector values() const final; /// This method checks if position in the 3D volume /// frame is inside the cylinder /// /// @param pos is the position in volume frame to be checked /// @param tol is the absolute tolerance to be applied - bool inside(const Vector3& pos, double tol = 0.) const final; + bool inside(const Vector3& pos, ActsScalar tol = 0.) const final; /// Oriented surfaces, i.e. the decomposed boundary surfaces and the /// according navigation direction into the volume given the normal @@ -126,30 +127,30 @@ class ConeVolumeBounds : public VolumeBounds { /// Access to the bound values /// @param bValue the class nested enum for the array access - double get(BoundValues bValue) const { return m_values[bValue]; } + ActsScalar get(BoundValues bValue) const { return m_values[bValue]; } // Return the derived innerRmin - double innerRmin() const; + ActsScalar innerRmin() const; // Return the derived innerRmin - double innerRmax() const; + ActsScalar innerRmax() const; // Return the derived inner tan(alpha) - double innerTanAlpha() const; + ActsScalar innerTanAlpha() const; // Return the derived outerRmin - double outerRmin() const; + ActsScalar outerRmin() const; // Return the derived outerRmax - double outerRmax() const; + ActsScalar outerRmax() const; // Return the derived outer tan(alpha) - double outerTanAlpha() const; + ActsScalar outerTanAlpha() const; /// Output Method for std::ostream /// - /// @param sl is ostream operator to be dumped into - std::ostream& toStream(std::ostream& sl) const final; + /// @param os is ostream operator to be dumped into + std::ostream& toStream(std::ostream& os) const final; private: /// Check the input values for consistency, @@ -159,14 +160,8 @@ class ConeVolumeBounds : public VolumeBounds { /// Create the surface bounds void buildSurfaceBounds(); - /// Templated dump methods - /// @tparam stream_t The type of the stream for dumping - /// @param dt The stream object - template - stream_t& dumpT(stream_t& dt) const; - /// The bound values - std::array m_values; + std::array m_values; std::shared_ptr m_innerCylinderBounds{nullptr}; std::shared_ptr m_innerConeBounds{nullptr}; std::shared_ptr m_outerConeBounds{nullptr}; @@ -176,54 +171,12 @@ class ConeVolumeBounds : public VolumeBounds { std::shared_ptr m_sectorBounds{nullptr}; /// Derived values - double m_innerRmin = 0.; - double m_innerRmax = 0.; - double m_innerTanAlpha = 0.; - double m_outerRmin = 0.; - double m_outerRmax = 0.; - double m_outerTanAlpha = 0.; + ActsScalar m_innerRmin = 0.; + ActsScalar m_innerRmax = 0.; + ActsScalar m_innerTanAlpha = 0.; + ActsScalar m_outerRmin = 0.; + ActsScalar m_outerRmax = 0.; + ActsScalar m_outerTanAlpha = 0.; }; -inline double ConeVolumeBounds::innerRmin() const { - return m_innerRmin; -} - -inline double ConeVolumeBounds::innerRmax() const { - return m_innerRmax; -} - -inline double ConeVolumeBounds::innerTanAlpha() const { - return m_innerTanAlpha; -} - -inline double ConeVolumeBounds::outerRmin() const { - return m_outerRmin; -} - -inline double ConeVolumeBounds::outerRmax() const { - return m_outerRmax; -} - -inline double ConeVolumeBounds::outerTanAlpha() const { - return m_outerTanAlpha; -} - -inline std::vector ConeVolumeBounds::values() const { - std::vector valvector; - valvector.insert(valvector.begin(), m_values.begin(), m_values.end()); - return valvector; -} - -template -stream_t& ConeVolumeBounds::dumpT(stream_t& dt) const { - dt << std::setiosflags(std::ios::fixed); - dt << std::setprecision(5); - dt << "Acts::ConeVolumeBounds : (innerAlpha, innerOffsetZ, outerAlpha,"; - dt << " outerOffsetZ, halflenghZ, averagePhi, halfPhiSector) = "; - dt << get(eInnerAlpha) << ", " << get(eInnerOffsetZ) << ", "; - dt << get(eOuterAlpha) << ", " << get(eOuterOffsetZ) << ", "; - dt << get(eHalfLengthZ) << ", " << get(eAveragePhi) << std::endl; - return dt; -} - } // namespace Acts diff --git a/Core/include/Acts/Geometry/CuboidVolumeBounds.hpp b/Core/include/Acts/Geometry/CuboidVolumeBounds.hpp index 52f8697688b..5605dd7532d 100644 --- a/Core/include/Acts/Geometry/CuboidVolumeBounds.hpp +++ b/Core/include/Acts/Geometry/CuboidVolumeBounds.hpp @@ -63,12 +63,14 @@ class CuboidVolumeBounds : public VolumeBounds { /// @param halex is the half length of the cube in x /// @param haley is the half length of the cube in y /// @param halez is the half length of the cube in z - CuboidVolumeBounds(double halex, double haley, double halez) noexcept(false); + CuboidVolumeBounds(ActsScalar halex, ActsScalar haley, + ActsScalar halez) noexcept(false); /// Constructor - from a fixed size array /// /// @param values iw the bound values - CuboidVolumeBounds(const std::array& values) noexcept(false) + CuboidVolumeBounds(const std::array& values) noexcept( + false) : m_values(values) { checkConsistency(); buildSurfaceBounds(); @@ -91,14 +93,14 @@ class CuboidVolumeBounds : public VolumeBounds { /// Return the bound values as dynamically sized vector /// /// @return this returns a copy of the internal values - std::vector values() const final; + std::vector values() const final; /// This method checks if position in the 3D volume /// frame is inside the cylinder /// /// @param pos is the position in volume frame to be checked /// @param tol is the absolute tolerance to be applied - bool inside(const Vector3& pos, double tol = 0.) const override; + bool inside(const Vector3& pos, ActsScalar tol = 0.) const override; /// Oriented surfaces, i.e. the decomposed boundary surfaces and the /// according navigation direction into the volume given the normal @@ -122,31 +124,33 @@ class CuboidVolumeBounds : public VolumeBounds { const Vector3& envelope = {0, 0, 0}, const Volume* entity = nullptr) const final; - /// Binning borders in double + /// Get the canonical binning values, i.e. the binning values + /// for that fully describe the shape's extent + /// + /// @return vector of canonical binning values + std::vector canonicalBinning() const override { + return {Acts::binX, Acts::binY, Acts::binZ}; + }; + + /// Binning borders in ActsScalar /// /// @param bValue is the binning schema used /// /// @return float offset to be used for the binning - double binningBorder(BinningValue bValue) const final; + ActsScalar binningBorder(BinningValue bValue) const final; /// Access to the bound values /// @param bValue the class nested enum for the array access - double get(BoundValues bValue) const { return m_values[bValue]; } + ActsScalar get(BoundValues bValue) const { return m_values[bValue]; } /// Output Method for std::ostream /// - /// @param sl is ostream operator to be dumped into - std::ostream& toStream(std::ostream& sl) const override; + /// @param os is ostream operator to be dumped into + std::ostream& toStream(std::ostream& os) const override; private: - /// Templated dumpT method - /// @tparam stream_t The type for the dump stream - /// @param dt The dump stream object - template - stream_t& dumpT(stream_t& dt) const; - /// The bound values ordered in a fixed size array - std::array m_values; + std::array m_values; std::shared_ptr m_xyBounds{nullptr}; std::shared_ptr m_yzBounds{nullptr}; @@ -159,34 +163,4 @@ class CuboidVolumeBounds : public VolumeBounds { /// will throw a logic_exception if consistency is not given void checkConsistency() noexcept(false); }; - -inline bool CuboidVolumeBounds::inside(const Vector3& pos, double tol) const { - return (std::abs(pos.x()) <= get(eHalfLengthX) + tol && - std::abs(pos.y()) <= get(eHalfLengthY) + tol && - std::abs(pos.z()) <= get(eHalfLengthZ) + tol); -} - -inline std::vector CuboidVolumeBounds::values() const { - std::vector valvector; - valvector.insert(valvector.begin(), m_values.begin(), m_values.end()); - return valvector; -} - -inline void CuboidVolumeBounds::checkConsistency() noexcept(false) { - if (get(eHalfLengthX) <= 0 || get(eHalfLengthY) <= 0 || - get(eHalfLengthZ) <= 0.) { - throw std::invalid_argument( - "CuboidVolumeBounds: invalid input, zero or negative."); - } -} - -template -stream_t& CuboidVolumeBounds::dumpT(stream_t& dt) const { - dt << std::setiosflags(std::ios::fixed); - dt << std::setprecision(5); - dt << "Acts::CuboidVolumeBounds: (halfLengthX, halfLengthY, halfLengthZ) = "; - dt << "(" << get(eHalfLengthX) << ", " << get(eHalfLengthY) << ", " - << get(eHalfLengthZ) << ")"; - return dt; -} } // namespace Acts diff --git a/Core/include/Acts/Geometry/CutoutCylinderVolumeBounds.hpp b/Core/include/Acts/Geometry/CutoutCylinderVolumeBounds.hpp index 52031d2514f..3033b83595e 100644 --- a/Core/include/Acts/Geometry/CutoutCylinderVolumeBounds.hpp +++ b/Core/include/Acts/Geometry/CutoutCylinderVolumeBounds.hpp @@ -114,6 +114,14 @@ class CutoutCylinderVolumeBounds : public VolumeBounds { const Vector3& envelope = {0, 0, 0}, const Volume* entity = nullptr) const final; + /// Get the canonical binning values, i.e. the binning values + /// for that fully describe the shape's extent + /// + /// @return vector of canonical binning values + std::vector canonicalBinning() const override { + return {Acts::binR, Acts::binPhi, Acts::binZ}; + }; + /// Write information about this instance to an outstream /// /// @param sl The outstream diff --git a/Core/include/Acts/Geometry/CylinderVolumeBounds.hpp b/Core/include/Acts/Geometry/CylinderVolumeBounds.hpp index 4f8eb9dddca..6676659ebc0 100644 --- a/Core/include/Acts/Geometry/CylinderVolumeBounds.hpp +++ b/Core/include/Acts/Geometry/CylinderVolumeBounds.hpp @@ -94,10 +94,10 @@ class CylinderVolumeBounds : public VolumeBounds { /// @param avgphi The average phi value /// @param bevelMinZ The bevel angle, in radians, for the negative side /// @param bevelMaxZ The bevel angle, in radians, for the positive side - CylinderVolumeBounds(double rmin, double rmax, double halfz, - double halfphi = M_PI, double avgphi = 0., - double bevelMinZ = 0., - double bevelMaxZ = 0.) noexcept(false) + CylinderVolumeBounds(ActsScalar rmin, ActsScalar rmax, ActsScalar halfz, + ActsScalar halfphi = M_PI, ActsScalar avgphi = 0., + ActsScalar bevelMinZ = 0., + ActsScalar bevelMaxZ = 0.) noexcept(false) : m_values({rmin, rmax, halfz, halfphi, avgphi, bevelMinZ, bevelMaxZ}) { checkConsistency(); buildSurfaceBounds(); @@ -106,7 +106,8 @@ class CylinderVolumeBounds : public VolumeBounds { /// Constructor - from a fixed size array /// /// @param values The bound values - CylinderVolumeBounds(const std::array& values) noexcept(false) + CylinderVolumeBounds(const std::array& values) noexcept( + false) : m_values(values) { checkConsistency(); buildSurfaceBounds(); @@ -117,14 +118,14 @@ class CylinderVolumeBounds : public VolumeBounds { /// @param cBounds the cylinder bounds /// @param thickness of the extrusion CylinderVolumeBounds(const CylinderBounds& cBounds, - double thickness) noexcept(false); + ActsScalar thickness) noexcept(false); /// Constructor - extruded from radial bounds and thickness /// /// @param rBounds the Radial bounds /// @param thickness CylinderVolumeBounds(const RadialBounds& rBounds, - double thickness) noexcept(false); + ActsScalar thickness) noexcept(false); /// Copy Constructor /// @@ -141,14 +142,14 @@ class CylinderVolumeBounds : public VolumeBounds { /// Return the bound values as dynamically sized vector /// /// @return this returns a copy of the internal values - std::vector values() const final; + std::vector values() const final; /// This method checks if position in the 3D volume /// frame is inside the cylinder /// /// @param pos is a global position to be checked /// @param tol is the tolerance for the check - bool inside(const Vector3& pos, double tol = 0.) const override; + bool inside(const Vector3& pos, ActsScalar tol = 0.) const override; /// Oriented surfaces, i.e. the decomposed boundary surfaces and the /// according navigation direction into the volume given the normal @@ -172,26 +173,35 @@ class CylinderVolumeBounds : public VolumeBounds { const Vector3& envelope = {0, 0, 0}, const Volume* entity = nullptr) const final; + /// Get the canonical binning values, i.e. the binning values + /// for that fully describe the shape's extent + /// + /// @return vector of canonical binning values + std::vector canonicalBinning() const override { + return {Acts::binR, Acts::binPhi, Acts::binZ}; + }; + /// Binning offset - overloaded for some R-binning types /// /// @param bValue is the type used for the binning Vector3 binningOffset(BinningValue bValue) const override; - /// Binning borders in double + /// Binning borders in ActsScalar /// /// @param bValue is the type used for the binning - double binningBorder(BinningValue bValue) const override; + ActsScalar binningBorder(BinningValue bValue) const override; /// Output Method for std::ostream - std::ostream& toStream(std::ostream& sl) const override; + /// @param os is the output stream + std::ostream& toStream(std::ostream& os) const override; /// Access to the bound values /// @param bValue the class nested enum for the array access - double get(BoundValues bValue) const { return m_values[bValue]; } + ActsScalar get(BoundValues bValue) const { return m_values[bValue]; } private: - /// The internal version of the bounds can be float/double - std::array m_values{}; + /// The internal version of the bounds can be float/ActsScalar + std::array m_values{}; /// Bounds of the inner CylinderBounds std::shared_ptr m_innerCylinderBounds{nullptr}; /// Bounds of the inner CylinderBounds @@ -207,85 +217,6 @@ class CylinderVolumeBounds : public VolumeBounds { /// Helper method to create the surface bounds void buildSurfaceBounds(); - - /// Templated dumpT method - /// @tparam stream_t The type for the dump stream - /// @param dt The dump stream object - template - stream_t& dumpT(stream_t& dt) const; }; -inline bool CylinderVolumeBounds::inside(const Vector3& pos, double tol) const { - using VectorHelpers::perp; - using VectorHelpers::phi; - double ros = perp(pos); - bool insidePhi = cos(phi(pos)) >= cos(get(eHalfPhiSector)) - tol; - bool insideR = insidePhi - ? ((ros >= get(eMinR) - tol) && (ros <= get(eMaxR) + tol)) - : false; - bool insideZ = - insideR ? (std::abs(pos.z()) <= get(eHalfLengthZ) + tol) : false; - return (insideZ && insideR && insidePhi); -} - -inline Vector3 CylinderVolumeBounds::binningOffset(BinningValue bValue) - const { // the medium radius is taken for r-type binning - if (bValue == Acts::binR || bValue == Acts::binRPhi) { - return Vector3(0.5 * (get(eMinR) + get(eMaxR)), 0., 0.); - } - return VolumeBounds::binningOffset(bValue); -} - -inline double CylinderVolumeBounds::binningBorder(BinningValue bValue) const { - if (bValue == Acts::binR) { - return 0.5 * (get(eMaxR) - get(eMinR)); - } - if (bValue == Acts::binZ) { - return get(eHalfLengthZ); - } - return VolumeBounds::binningBorder(bValue); -} - -template -stream_t& CylinderVolumeBounds::dumpT(stream_t& dt) const { - dt << std::setiosflags(std::ios::fixed); - dt << std::setprecision(5); - dt << "Acts::CylinderVolumeBounds: (rMin, rMax, halfZ, halfPhi, " - "averagePhi, minBevelZ, maxBevelZ) = "; - dt << get(eMinR) << ", " << get(eMaxR) << ", " << get(eHalfLengthZ) << ", " - << get(eHalfPhiSector) << ", " << get(eAveragePhi) << ", " - << get(eBevelMinZ) << ", " << get(eBevelMaxZ); - return dt; -} - -inline std::vector CylinderVolumeBounds::values() const { - std::vector valvector; - valvector.insert(valvector.begin(), m_values.begin(), m_values.end()); - return valvector; -} - -inline void CylinderVolumeBounds::checkConsistency() noexcept(false) { - if (get(eMinR) < 0. || get(eMaxR) <= 0. || get(eMinR) >= get(eMaxR)) { - throw std::invalid_argument("CylinderVolumeBounds: invalid radial input."); - } - if (get(eHalfLengthZ) <= 0) { - throw std::invalid_argument( - "CylinderVolumeBounds: invalid longitudinal input."); - } - if (get(eHalfPhiSector) < 0. || get(eHalfPhiSector) > M_PI) { - throw std::invalid_argument( - "CylinderVolumeBounds: invalid phi sector setup."); - } - if (get(eAveragePhi) != detail::radian_sym(get(eAveragePhi))) { - throw std::invalid_argument( - "CylinderVolumeBounds: invalid phi positioning."); - } - if (get(eBevelMinZ) != detail::radian_sym(get(eBevelMinZ))) { - throw std::invalid_argument("CylinderBounds: invalid bevel at min Z."); - } - if (get(eBevelMaxZ) != detail::radian_sym(get(eBevelMaxZ))) { - throw std::invalid_argument("CylinderBounds: invalid bevel at max Z."); - } -} - } // namespace Acts diff --git a/Core/include/Acts/Geometry/CylinderVolumeBuilder.hpp b/Core/include/Acts/Geometry/CylinderVolumeBuilder.hpp index 8b242e139f8..c2b0e52c2ea 100644 --- a/Core/include/Acts/Geometry/CylinderVolumeBuilder.hpp +++ b/Core/include/Acts/Geometry/CylinderVolumeBuilder.hpp @@ -527,7 +527,8 @@ class CylinderVolumeBuilder : public ITrackingVolumeBuilder { /// processing MutableTrackingVolumePtr trackingVolume( const GeometryContext& gctx, TrackingVolumePtr existingVolume = nullptr, - VolumeBoundsPtr externalBounds = nullptr) const override; + std::shared_ptr externalBounds = + nullptr) const override; /// Set configuration method /// diff --git a/Core/include/Acts/Geometry/CylinderVolumeHelper.hpp b/Core/include/Acts/Geometry/CylinderVolumeHelper.hpp index 5762552d7ec..84ce33f41cb 100644 --- a/Core/include/Acts/Geometry/CylinderVolumeHelper.hpp +++ b/Core/include/Acts/Geometry/CylinderVolumeHelper.hpp @@ -79,7 +79,8 @@ class CylinderVolumeHelper : public ITrackingVolumeHelper { MutableTrackingVolumePtr createTrackingVolume( const GeometryContext& gctx, const LayerVector& layers, std::shared_ptr volumeMaterial, - VolumeBoundsPtr volumeBounds, MutableTrackingVolumeVector mtvVector = {}, + std::shared_ptr volumeBounds, + MutableTrackingVolumeVector mtvVector = {}, const Transform3& transform = Transform3::Identity(), const std::string& volumeName = "UndefinedVolume", BinningType bType = arbitrary) const override; diff --git a/Core/include/Acts/Geometry/Extent.hpp b/Core/include/Acts/Geometry/Extent.hpp index 9d650264ea3..5d22e39081a 100644 --- a/Core/include/Acts/Geometry/Extent.hpp +++ b/Core/include/Acts/Geometry/Extent.hpp @@ -13,7 +13,6 @@ #include "Acts/Definitions/Algebra.hpp" #include "Acts/Utilities/BinningType.hpp" #include "Acts/Utilities/Enumerate.hpp" -#include "Acts/Utilities/Range1D.hpp" #include "Acts/Utilities/RangeXD.hpp" #include @@ -122,17 +121,17 @@ class Extent { /// @param bValue is the binning value to be returned /// /// @return a one dimensional arrange - Range1D& range(BinningValue bValue); + auto range(BinningValue bValue) { return m_range[bValue]; } /// Return the individual 1-dimensional range /// /// @param bValue is the binning value to be returned /// /// @return a one dimensional arrange - const Range1D& range(BinningValue bValue) const; + Range1D range(BinningValue bValue) const; /// Return the N-dimension range - const RangeXD range() const; + const RangeXD& range() const; /// Return an D-dimensional sub range according to the /// the given @param binValues @@ -227,16 +226,11 @@ class Extent { std::array, binValues> m_valueHistograms; }; -inline Range1D& Acts::Extent::range(BinningValue bValue) { +inline Range1D Acts::Extent::range(BinningValue bValue) const { return m_range[bValue]; } -inline const Range1D& Acts::Extent::range( - BinningValue bValue) const { - return m_range[bValue]; -} - -inline const RangeXD Extent::range() const { +inline const RangeXD& Extent::range() const { return m_range; } diff --git a/Core/include/Acts/Geometry/GenericCuboidVolumeBounds.hpp b/Core/include/Acts/Geometry/GenericCuboidVolumeBounds.hpp index d205f51d92a..138ab0d7692 100644 --- a/Core/include/Acts/Geometry/GenericCuboidVolumeBounds.hpp +++ b/Core/include/Acts/Geometry/GenericCuboidVolumeBounds.hpp @@ -89,6 +89,14 @@ class GenericCuboidVolumeBounds : public VolumeBounds { const Vector3& envelope = {0, 0, 0}, const Volume* entity = nullptr) const final; + /// Get the canonical binning values, i.e. the binning values + /// for that fully describe the shape's extent + /// + /// @return vector of canonical binning values + std::vector canonicalBinning() const override { + return {Acts::binX, Acts::binY, Acts::binZ}; + }; + /// @param sl is the output stream to be written into std::ostream& toStream(std::ostream& sl) const override; diff --git a/Core/include/Acts/Geometry/ITrackingVolumeBuilder.hpp b/Core/include/Acts/Geometry/ITrackingVolumeBuilder.hpp index d858ab76817..eb477c203f8 100644 --- a/Core/include/Acts/Geometry/ITrackingVolumeBuilder.hpp +++ b/Core/include/Acts/Geometry/ITrackingVolumeBuilder.hpp @@ -22,7 +22,6 @@ class Layer; class Volume; using TrackingVolumePtr = std::shared_ptr; using MutableTrackingVolumePtr = std::shared_ptr; -using VolumeBoundsPtr = std::shared_ptr; using LayerPtr = std::shared_ptr; using LayerVector = std::vector; /// @class ITrackingVolumeBuilder @@ -51,7 +50,7 @@ class ITrackingVolumeBuilder { /// @return shared pointer to a newly created TrackingVolume virtual MutableTrackingVolumePtr trackingVolume( const GeometryContext& gctx, TrackingVolumePtr oppositeVolume = nullptr, - VolumeBoundsPtr outsideBounds = nullptr) const = 0; + std::shared_ptr outsideBounds = nullptr) const = 0; }; } // namespace Acts diff --git a/Core/include/Acts/Geometry/ITrackingVolumeHelper.hpp b/Core/include/Acts/Geometry/ITrackingVolumeHelper.hpp index 664915b519f..df3e75f2549 100644 --- a/Core/include/Acts/Geometry/ITrackingVolumeHelper.hpp +++ b/Core/include/Acts/Geometry/ITrackingVolumeHelper.hpp @@ -26,7 +26,6 @@ class IVolumeMaterial; using LayerPtr = std::shared_ptr; using TrackingVolumePtr = std::shared_ptr; using MutableTrackingVolumePtr = std::shared_ptr; -using VolumeBoundsPtr = std::shared_ptr; using LayerVector = std::vector; using TrackingVolumeVector = std::vector; @@ -64,7 +63,8 @@ class ITrackingVolumeHelper { virtual MutableTrackingVolumePtr createTrackingVolume( const GeometryContext& gctx, const LayerVector& layers, std::shared_ptr volumeMaterial, - VolumeBoundsPtr volumeBounds, MutableTrackingVolumeVector mtvVector = {}, + std::shared_ptr volumeBounds, + MutableTrackingVolumeVector mtvVector = {}, const Transform3& transform = Transform3::Identity(), const std::string& volumeName = "UndefinedVolume", BinningType btype = arbitrary) const = 0; diff --git a/Core/include/Acts/Geometry/TrackingGeometryBuilder.hpp b/Core/include/Acts/Geometry/TrackingGeometryBuilder.hpp index e7f20ac649a..a3d1bf4a011 100644 --- a/Core/include/Acts/Geometry/TrackingGeometryBuilder.hpp +++ b/Core/include/Acts/Geometry/TrackingGeometryBuilder.hpp @@ -41,7 +41,7 @@ class TrackingGeometryBuilder : public ITrackingGeometryBuilder { /// The list of tracking volume builders std::vector( const GeometryContext& gctx, const TrackingVolumePtr&, - const VolumeBoundsPtr&)>> + const std::shared_ptr&)>> trackingVolumeBuilders; /// The tracking volume helper for detector construction diff --git a/Core/include/Acts/Geometry/TrackingVolume.hpp b/Core/include/Acts/Geometry/TrackingVolume.hpp index 00a4e020dd4..2b12114c42f 100644 --- a/Core/include/Acts/Geometry/TrackingVolume.hpp +++ b/Core/include/Acts/Geometry/TrackingVolume.hpp @@ -125,7 +125,8 @@ class TrackingVolume : public Volume { /// /// @return shared pointer to a new TrackingVolume static MutableTrackingVolumePtr create( - const Transform3& transform, VolumeBoundsPtr volumeBounds, + const Transform3& transform, + std::shared_ptr volumeBounds, const std::shared_ptr& containedVolumes = nullptr, const std::string& volumeName = "undefined") { @@ -146,7 +147,8 @@ class TrackingVolume : public Volume { /// /// @return shared pointer to a new TrackingVolume static MutableTrackingVolumePtr create( - const Transform3& transform, VolumeBoundsPtr volumeBounds, + const Transform3& transform, + std::shared_ptr volumeBounds, std::shared_ptr volumeMaterial, std::unique_ptr containedLayers = nullptr, std::shared_ptr containedVolumes = nullptr, @@ -410,14 +412,6 @@ class TrackingVolume : public Volume { /// - positiveFaceXY GlueVolumesDescriptor& glueVolumesDescriptor(); - /// Register the color code - /// - /// @param icolor is a color number - void registerColorCode(unsigned int icolor); - - /// Get the color code - unsigned int colorCode() const; - /// Return the MotherVolume - if it exists const TrackingVolume* motherVolume() const; @@ -435,7 +429,8 @@ class TrackingVolume : public Volume { /// @param volbounds is the description of the volume boundaries /// @param containedVolumeArray are the static volumes that fill this volume /// @param volumeName is a string identifier - TrackingVolume(const Transform3& transform, VolumeBoundsPtr volbounds, + TrackingVolume(const Transform3& transform, + std::shared_ptr volbounds, const std::shared_ptr& containedVolumeArray = nullptr, const std::string& volumeName = "undefined"); @@ -452,7 +447,8 @@ class TrackingVolume : public Volume { /// @param denseVolumeVector The contained dense volumes /// @param volumeName is a string identifier TrackingVolume( - const Transform3& transform, VolumeBoundsPtr volumeBounds, + const Transform3& transform, + std::shared_ptr volumeBounds, std::shared_ptr volumeMaterial, std::unique_ptr staticLayerArray = nullptr, std::shared_ptr containedVolumeArray = nullptr, @@ -515,9 +511,6 @@ class TrackingVolume : public Volume { /// Volume name for debug reasons & screen output std::string m_name; - - /// color code for displaying - unsigned int m_colorCode{20}; }; inline const std::string& TrackingVolume::volumeName() const { @@ -551,14 +544,6 @@ TrackingVolume::confinedVolumes() const { return m_confinedVolumes; } -inline void TrackingVolume::registerColorCode(unsigned int icolor) { - m_colorCode = icolor; -} - -inline unsigned int TrackingVolume::colorCode() const { - return m_colorCode; -} - inline const TrackingVolume* TrackingVolume::motherVolume() const { return m_motherVolume; } diff --git a/Core/include/Acts/Geometry/TrapezoidVolumeBounds.hpp b/Core/include/Acts/Geometry/TrapezoidVolumeBounds.hpp index d4999183ca1..bc00685e228 100644 --- a/Core/include/Acts/Geometry/TrapezoidVolumeBounds.hpp +++ b/Core/include/Acts/Geometry/TrapezoidVolumeBounds.hpp @@ -68,8 +68,8 @@ class TrapezoidVolumeBounds : public VolumeBounds { /// @param maxhalex is the half length in x at maximal y /// @param haley is the half length in y /// @param halez is the half length in z - TrapezoidVolumeBounds(double minhalex, double maxhalex, double haley, - double halez) noexcept(false); + TrapezoidVolumeBounds(ActsScalar minhalex, ActsScalar maxhalex, + ActsScalar haley, ActsScalar halez) noexcept(false); /// Constructor - the trapezoid boundaries (arbitrary trapezoid) /// @@ -78,13 +78,14 @@ class TrapezoidVolumeBounds : public VolumeBounds { /// @param halez is the half length in z /// @param alpha is the opening angle at -x,-y /// @param beta is the opening angle at +x,-y - TrapezoidVolumeBounds(double minhalex, double haley, double halez, - double alpha, double beta) noexcept(false); + TrapezoidVolumeBounds(ActsScalar minhalex, ActsScalar haley, ActsScalar halez, + ActsScalar alpha, ActsScalar beta) noexcept(false); /// Constructor - from a fixed size array /// /// @param values The bound values - TrapezoidVolumeBounds(const std::array& values) noexcept(false) + TrapezoidVolumeBounds(const std::array& values) noexcept( + false) : m_values(values) { checkConsistency(); buildSurfaceBounds(); @@ -102,7 +103,7 @@ class TrapezoidVolumeBounds : public VolumeBounds { /// Return the bound values as dynamically sized vector /// /// @return this returns a copy of the internal values - std::vector values() const final; + std::vector values() const final; /// This method checks if position in the 3D volume frame /// is inside the cylinder @@ -111,7 +112,7 @@ class TrapezoidVolumeBounds : public VolumeBounds { /// @param tol is the tolerance applied /// /// @return boolean indicator if position is inside - bool inside(const Vector3& pos, double tol = 0.) const override; + bool inside(const Vector3& pos, ActsScalar tol = 0.) const override; /// Oriented surfaces, i.e. the decomposed boundary surfaces and the /// according navigation direction into the volume given the normal @@ -136,15 +137,16 @@ class TrapezoidVolumeBounds : public VolumeBounds { const Volume* entity = nullptr) const final; /// Output Method for std::ostream - std::ostream& toStream(std::ostream& sl) const override; + /// @param os is the output stream + std::ostream& toStream(std::ostream& os) const override; /// Access to the bound values /// @param bValue the class nested enum for the array access - double get(BoundValues bValue) const { return m_values[bValue]; } + ActsScalar get(BoundValues bValue) const { return m_values[bValue]; } private: - /// The internal version of the bounds can be float/double - std::array m_values{}; + /// The internal version of the bounds can be float/ActsScalar + std::array m_values{}; /// The face PlaneSurface parallel to local xy plane std::shared_ptr m_faceXYTrapezoidBounds{nullptr}; /// Thhe face PlaneSurface attached to alpha (negative local x) @@ -162,43 +164,6 @@ class TrapezoidVolumeBounds : public VolumeBounds { /// Helper method to create the surface bounds void buildSurfaceBounds(); - - /// Templated dump methods - /// @tparam stream_t The type of the stream for dumping - /// @param dt The stream object - template - stream_t& dumpT(stream_t& dt) const; }; -template -stream_t& TrapezoidVolumeBounds::dumpT(stream_t& dt) const { - dt << std::setiosflags(std::ios::fixed); - dt << std::setprecision(5); - dt << "Acts::TrapezoidVolumeBounds: (minhalfX, halfY, halfZ, alpha, beta) " - "= "; - dt << "(" << get(eHalfLengthXnegY) << ", " << get(eHalfLengthXposY) << ", " - << get(eHalfLengthY) << ", " << get(eHalfLengthZ); - dt << ", " << get(eAlpha) << ", " << get(eBeta) << ")"; - return dt; -} - -inline std::vector TrapezoidVolumeBounds::values() const { - std::vector valvector; - valvector.insert(valvector.begin(), m_values.begin(), m_values.end()); - return valvector; -} - -inline void TrapezoidVolumeBounds::checkConsistency() noexcept(false) { - if (get(eHalfLengthXnegY) < 0. || get(eHalfLengthXposY) < 0.) { - throw std::invalid_argument( - "TrapezoidVolumeBounds: invalid trapezoid parameters in x."); - } - if (get(eHalfLengthY) <= 0.) { - throw std::invalid_argument("TrapezoidVolumeBounds: invalid y extrusion."); - } - if (get(eHalfLengthZ) <= 0.) { - throw std::invalid_argument("TrapezoidVolumeBounds: invalid z extrusion."); - } -} - } // namespace Acts diff --git a/Core/include/Acts/Geometry/Volume.hpp b/Core/include/Acts/Geometry/Volume.hpp index c8159118e11..037bfdfaeb7 100644 --- a/Core/include/Acts/Geometry/Volume.hpp +++ b/Core/include/Acts/Geometry/Volume.hpp @@ -20,7 +20,6 @@ namespace Acts { class VolumeBounds; -using VolumeBoundsPtr = std::shared_ptr; /// @class Volume /// @@ -40,7 +39,8 @@ class Volume : public virtual GeometryObject { /// @param volbounds is the volume boundary definitions /// @note This will automatically build an oriented bounding box with an /// envelope value of (0.05, 0.05, 0.05)mm - Volume(const Transform3& transform, VolumeBoundsPtr volbounds); + Volume(const Transform3& transform, + std::shared_ptr volbounds); /// Copy Constructor - with optional shift /// @@ -70,6 +70,9 @@ class Volume : public virtual GeometryObject { /// returns the volumeBounds() const VolumeBounds& volumeBounds() const; + /// Set volume bounds and update volume bounding boxes implicitly + void assignVolumeBounds(std::shared_ptr volbounds); + /// Construct bounding box for this shape /// @param envelope Optional envelope to add / subtract from min/max /// @return Constructed bounding box pointing to this volume @@ -85,7 +88,7 @@ class Volume : public virtual GeometryObject { /// @param tol is the tolerance parameter /// /// @return boolean indicator if the position is inside - bool inside(const Vector3& gpos, double tol = 0.) const; + bool inside(const Vector3& gpos, ActsScalar tol = 0.) const; /// The binning position method /// - as default the center is given, but may be overloaded @@ -101,26 +104,10 @@ class Volume : public virtual GeometryObject { Transform3 m_transform; Transform3 m_itransform; Vector3 m_center; - VolumeBoundsPtr m_volumeBounds; + std::shared_ptr m_volumeBounds; BoundingBox m_orientedBoundingBox; }; -inline const Transform3& Volume::transform() const { - return m_transform; -} - -inline const Transform3& Volume::itransform() const { - return m_itransform; -} - -inline const Vector3& Volume::center() const { - return m_center; -} - -inline const VolumeBounds& Volume::volumeBounds() const { - return (*(m_volumeBounds.get())); -} - /**Overload of << operator for std::ostream for debug output*/ std::ostream& operator<<(std::ostream& sl, const Volume& vol); diff --git a/Core/include/Acts/Geometry/VolumeBounds.hpp b/Core/include/Acts/Geometry/VolumeBounds.hpp index 860977172f7..23bdcd4f819 100644 --- a/Core/include/Acts/Geometry/VolumeBounds.hpp +++ b/Core/include/Acts/Geometry/VolumeBounds.hpp @@ -26,8 +26,6 @@ class Surface; class VolumeBounds; class Direction; -using VolumeBoundsPtr = std::shared_ptr; - using OrientedSurface = std::pair, Direction>; using OrientedSurfaces = std::vector; @@ -115,6 +113,18 @@ class VolumeBounds { const Transform3* trf = nullptr, const Vector3& envelope = {0, 0, 0}, const Volume* entity = nullptr) const = 0; + /// Get the canonical binning values, i.e. the binning values + /// for that fully describe the shape's extent + /// + /// @return vector of canonical binning values + /// + /// @note This is the default implementation that + /// returns the bounding box binning. Individual shapes + /// should override this method + virtual std::vector canonicalBinning() const { + return {Acts::binX, Acts::binY, Acts::binZ}; + }; + /// Binning offset - overloaded for some R-binning types /// /// @param bValue is the binning schema used diff --git a/Core/include/Acts/Utilities/DBScan.hpp b/Core/include/Acts/Utilities/DBScan.hpp index f978dde06a2..79f862ce573 100644 --- a/Core/include/Acts/Utilities/DBScan.hpp +++ b/Core/include/Acts/Utilities/DBScan.hpp @@ -159,8 +159,8 @@ class DBScan { // hypercube with a length of 2 epsilon). typename Tree::range_t range; for (std::size_t dim = 0; dim < kDims; dim++) { - range[dim] = std::make_pair(currentPoint[dim] - m_eps, - currentPoint[dim] + m_eps); + range[dim] = Range1D(currentPoint[dim] - m_eps, + currentPoint[dim] + m_eps); } // We use the KDTree to find the neighbours. // An extra cut needs to be applied to only keep the neighbours that diff --git a/Core/include/Acts/Utilities/KDTree.hpp b/Core/include/Acts/Utilities/KDTree.hpp index d78f8cf021c..ddf7e1877af 100644 --- a/Core/include/Acts/Utilities/KDTree.hpp +++ b/Core/include/Acts/Utilities/KDTree.hpp @@ -49,7 +49,7 @@ class KDTree { using value_t = Type; /// @brief The type describing a multi-dimensional orthogonal range. - using range_t = RangeXD; + using range_t = RangeXD; /// @brief The type of coordinates for points. using coordinate_t = Vector; @@ -303,7 +303,7 @@ class KDTree { range_t r; for (std::size_t j = 0; j < Dims; ++j) { - r[j] = {min_v[j], nextRepresentable(max_v[j])}; + r[j] = Range1D{min_v[j], nextRepresentable(max_v[j])}; } return r; diff --git a/Core/include/Acts/Utilities/Range1D.hpp b/Core/include/Acts/Utilities/Range1D.hpp deleted file mode 100644 index 3a9e24f7d64..00000000000 --- a/Core/include/Acts/Utilities/Range1D.hpp +++ /dev/null @@ -1,323 +0,0 @@ -// This file is part of the Acts project. -// -// Copyright (C) 2021 CERN for the benefit of the Acts project -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#pragma once - -#include -#include - -namespace Acts { -/// @brief A one-dimensional range between two points. -/// -/// This type describes a one-demensional range of values, designed to be used -/// in the construction of more complex multi-dimensional types. The class -/// provides functionality for growing and shrinking the range, as well as some -/// other utilities. These ranges are half-open, including the minimum but -/// excluding the maximum. -/// -/// @tparam Type The scalar type of the values contained in this range. -template -class Range1D { - public: - /// @brief Construct a new degenerate range object - /// - /// This constructor coonstructs a degenerate range object with a maximum - /// lower than the minimum. In other words, this range is empty. - Range1D() - : m_min(std::numeric_limits::lowest()), - m_max(std::numeric_limits::max()) {} - - /// @brief Construct a new range object from a lower and upper bound - /// - /// Construct a new range object given the values for the minimum and - /// maximum. Note that it is perfectly possible to construct a degenerate - /// range in this way. - /// - /// @param min The minimum value in the range (inclusive) - /// @param max The maximum value in the range (exclusive) - Range1D(Type min, Type max) : m_min(min), m_max(max) {} - - /// @brief Construct a new range object from a pair of bounds - /// - /// Construct a new range object from a pair of values, the first of which - /// is taken to be the minimum, and the second of which is taken to be the - /// maximum. - /// - /// @param p The pair of values to use as the minimum and maximum - Range1D(const std::pair& p) : m_min(p.first), m_max(p.second) {} - - /// @brief Construct a new range object from an existing range - /// - /// This simply copies the values from the existing range to the new one. - /// It's the copy constructor. - /// - /// @param o The range to copy - Range1D(const Range1D& o) : m_min(o.min()), m_max(o.max()) {} - - /// @brief Set the minimum value - /// - /// Override the minimum value of the range, regardless of what was already - /// set. - /// - /// @note If you want to shrink or expand the range, use the shrink and - /// expand methods. - /// - /// @param v The value to use as the new minimum - void setMin(const Type& v) { m_min = v; } - - /// @brief Set the maximum value - /// - /// Override the maximum value of the range, regardless of what was already - /// set. - /// - /// @note If you want to shrink or expand the range, use the shrink and - /// expand methods. - /// - /// @param v The value to use as the new maximum - void setMax(const Type& v) { m_max = v; } - - /// @brief Set the minimum and maximum value - /// - /// Override both the minimum and maximum value of the range, regardless of - /// what they were set to. - /// - /// @note If you want to shrink or expand the range, use the shrink and - /// expand methods. - /// - /// @note After this operation, the range should be exactly equal to [min, - /// max] - /// - /// @param min The new minimum value of the range - /// @param max The new maximum value of the range - void set(const Type& min, const Type& max) { - m_min = min; - m_max = max; - } - - /// @brief Shrink a range by increasing the minimum value - /// - /// Shrink the range by increasing the minimum value. If the given value is - /// smaller than the current minimum (in other words, if the proposed new - /// range would be larger than the current range), this is a no-op. - /// - /// @param v The proposed new minimum for the range - void shrinkMin(const Type& v) { m_min = std::max(m_min, v); } - - /// @brief Shrink a range by decreasing the maximum value - /// - /// Shrink the range by decreasing the maximum value. If the given value is - /// larger than the current maximum (in other words, if the proposed new - /// range would be larger than the current range), this is a no-op. - /// - /// @param v The proposed new maximum for the range - void shrinkMax(const Type& v) { m_max = std::min(m_max, v); } - - /// @brief Shrink a range on both ends - /// - /// Shrink a range by increasing the minimum value as well as decreasing the - /// maximum value. If either of the values are already smaller or larger - /// (respectively) than the proposed values, then that particular boundary of - /// the interval is not shrunk. - /// - /// @note After this operation, the range is always equal to or smaller than - /// [min, max]. - /// - /// @param min The proposed new minimum for the range - /// @param max The proposed new maximum for the range - void shrink(const Type& min, const Type& max) { - shrinkMin(min); - shrinkMax(max); - } - - /// @brief Expand a range by decreasing the minimum value - /// - /// Expand the range by decreasing the minimum value. If the given value is - /// larger than the current minimum (in other words, if the proposed new - /// range would be smaller than the current range), this is a no-op. - /// - /// @param v The proposed new minimum for the range - void expandMin(const Type& v) { m_min = std::min(m_min, v); } - - /// @brief Expand a range by increasing the maximum value - /// - /// Expand the range by increasing the maximum value. If the given value is - /// smaller than the current maximum (in other words, if the proposed new - /// range would be smaller than the current range), this is a no-op. - /// - /// @param v The proposed new maximum for the range - void expandMax(const Type& v) { m_max = std::max(m_max, v); } - - /// @brief Expand a range on both ends - /// - /// Expand a range by decreasing the minimum value as well as increasing the - /// maximum value. If either of the values are already larger or smaller - /// (respectively) than the proposed values, then that particular boundary of - /// the interval is not expanded. - /// - /// @note After this operation, the range is always equal to or larger than - /// [min, max]. - /// - /// @param min The proposed new minimum for the range - /// @param max The proposed new maximum for the range - void expand(const Type& min, const Type& max) { - expandMin(min); - expandMax(max); - } - - /// @brief Return the minimum value of the range (inclusive) - Type min(void) const { return m_min; } - - /// @brief Return the maximum value of the range (inclusive) - Type max(void) const { return m_max; } - - /// @brief Compute the size of the range - /// - /// The size of a range is defined as the difference between the minimum and - /// the maximum. For degenerate ranges, this is zero. - /// - /// @warning Due to the nature of numbers, the result of this function can be - /// somewhat ambiguous. For natural numbers, you could argue that the range - /// [n, n] has size 0 or size 1. In this case we say it has size 0. The - /// uncountable nature of the reals means this doesn't matter for them, but - /// this can be awkward when working with integers. - /// - /// @return The size of the range - Type size(void) const { - return std::max(static_cast(0), m_max - m_min); - } - - /// @brief Determine if this range is degenerate or not - /// - /// A degenerate range has a minimum higher than the maximum, and thus - /// cannot contain any values. - /// - /// @return true The range is degenerate and has size zero - /// @return false The range is not degenerate - bool degenerate(void) const { return m_min >= m_max; } - - /// @brief Determine if the range contains a given value - /// - /// A value is inside a range if and only if it is greater than the minimum - /// and smaller than the maximum. - /// - /// @param v The value to check - /// - /// @return true The value is inside the range - /// @return false The value is not inside the range - bool contains(const Type& v) const { return m_min <= v && v < m_max; } - - /// @brief Determine whether the range intersects another range - /// - /// The intersection of a range is the space where both ranges overlap. If - /// the ranges overlap at all, they are said to intersect. This operation - /// is commutative. - /// - /// @param o The other range to check - /// - /// @return true The ranges intersect - /// @return false The ranges do not intersect - bool operator&&(const Range1D& o) const { - return m_min < o.max() && o.min() < m_max; - } - - /// @brief Determine whether the range is equal to another range - /// - /// Two ranges are equal if and only if their minima and maxima are the - /// same. - /// - /// @warning This method relies on the existence of a well-defined notion - /// of equality for the underlying types. Using this method on floating - /// ranges may have unintended effecrs. - /// - /// @param o The other range to check - /// - /// @return true The ranges are equal - /// @return false The ranges are not equal - bool operator==(const Range1D& o) const { - return min() == o.min() && max() == o.max(); - } - - /// @brief Determine whether the left-hand range is a subset of the - /// right-hand range - /// - /// A range is a subset of another range if and only if all values - /// contained in the first range are also contained in the second range. - /// - /// @param o The other range to check - /// - /// @return true The left-hand range is a subset of the right-hand range - /// @return false The left-hand range is not a subset of the right-hand - /// range - bool operator<=(const Range1D& o) const { - return min() >= o.min() && max() <= o.max(); - } - - /// @brief Determine whether the left-hand range is a superset of the - /// right-hand range - /// - /// A range is a superset of another range if and only if all values - /// contained in the second range are also contained in the first range. - /// - /// @param o The other range to check - /// - /// @return true The left-hand range is a superset of thr right-hand range - /// @return false The left-hand range is not a superset of the right-hand - /// range - bool operator>=(const Range1D& o) const { - return min() <= o.min() && max() >= o.max(); - } - - /// @brief Assignment operator - /// - /// Copy the right-hand range into the left-hand range, which means setting - /// the minimum and maximum to equal the minimum and maximum of the - /// right-hand side. - /// - /// @param o The range of values to copy - /// - /// @return This range - Range1D& operator=(const Range1D& o) { - m_min = o.min(); - m_max = o.max(); - - return *this; - } - - /// @brief Compute the intersection of two ranges - /// - /// The intersection of two ranges is the range containing all values - /// contained in both ranges. If the two ranges do not intersect, the - /// intersection is a degenerate range. This operation is commutative. - /// - /// @param o The range to compute the intersection with - /// - /// @return The intersection range between the two ranges - Range1D operator&(const Range1D& o) const { - return Range1D(std::max(m_min, o.min()), std::min(m_max, o.max())); - } - - /// @brief Set the range to the intersection of itself and another range - /// - /// This is an assignment version of operator&, which updates the range on - /// which it is called to ensure that the new range is the intersection of - /// the old range and the new range. - /// - /// @param o The range to compute the intersection with - /// - /// @return This object - Range1D& operator&=(const Range1D& o) { - m_min = std::max(m_min, o.min()); - m_max = std::min(m_max, o.max()); - - return *this; - } - - private: - Type m_min, m_max; -}; -} // namespace Acts diff --git a/Core/include/Acts/Utilities/RangeXD.hpp b/Core/include/Acts/Utilities/RangeXD.hpp index 2f6acaaa56f..d614004234e 100644 --- a/Core/include/Acts/Utilities/RangeXD.hpp +++ b/Core/include/Acts/Utilities/RangeXD.hpp @@ -8,10 +8,9 @@ #pragma once -#include "Acts/Utilities/Range1D.hpp" - #include #include +#include #include #include #include @@ -29,20 +28,59 @@ namespace Acts { template typename Vector = std::array> class RangeXD { + private: + // @TODO: Replace with std::span or boost::span once available + template + struct SingleElementContainer { + Type* element; + + Type& operator[](std::size_t i) { + (void)i; + assert(i == 0); + + return *element; + } + }; + public: - /// @brief The type used to describe coordinates in our range - using coordinate_t = Vector; + RangeXD() { + for (std::size_t i = 0; i < Dims; ++i) { + min(i) = std::numeric_limits::lowest(); + max(i) = std::numeric_limits::max(); + } + } + + /// @brief Construct a range from a pair of minimum and maximum values + /// @param minima The minimum values of the range + /// @param maxima The maximum values of the range + RangeXD(Vector minima, Vector maxima) + : m_minima(minima), m_maxima(maxima) {} + + /// @brief Construct a range from a pair of single minimum and maximum values + /// @note Only available for one-dimensional ranges + /// @param minimum The minimum value of the range + /// @param maximum The maximum value of the range + template > + RangeXD(Type minimum, Type maximum) + : m_minima({minimum}), m_maxima({maximum}) {} + + /// @brief Construct a range from a pair of minimum and maximum values + /// @note Only available for one-dimensional ranges + /// @param p The pair of minimum and maximum values + template > + RangeXD(const std::pair& p) + : m_minima({p.first}), m_maxima({p.second}) {} /// @brief Determine whether this range is degenerate /// - /// A degenerate multi-dimensional range has no volume and cannot contain any - /// values. This is the case if any of its dimensions are degenerate. + /// A degenerate multi-dimensional range has no volume and cannot contain + /// any values. This is the case if any of its dimensions are degenerate. /// /// @return true The range is degenerate /// @return false The range is not degenerate - bool degenerate(void) const { + bool degenerate() const { for (std::size_t i = 0; i < Dims; ++i) { - if (m_dims[i].degenerate()) { + if (min(i) >= max(i)) { return true; } } @@ -58,9 +96,10 @@ class RangeXD { /// /// @return true The coordinate is inside the range /// @return false The coordinate is outside the range - bool contains(const coordinate_t& v) const { + template