Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-21 07:46:27

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 /// @note This file is foreseen for the `Geometry` module to replace `Extent`
0012 
0013 #include "Acts/Definitions/Algebra.hpp"
0014 #include "Acts/Utilities/AxisDefinitions.hpp"
0015 #include "Acts/Utilities/Enumerate.hpp"
0016 #include "Acts/Utilities/Helpers.hpp"
0017 #include "Acts/Utilities/RangeXD.hpp"
0018 
0019 #include <array>
0020 #include <bitset>
0021 #include <optional>
0022 #include <ostream>
0023 #include <string>
0024 #include <vector>
0025 
0026 namespace Acts {
0027 
0028 /// @brief Type alias for envelope values in different directions
0029 /// @details Stores the envelope values for both positive and negative directions
0030 using Envelope = std::array<double, 2>;
0031 
0032 /// Zero envelope constant for no extension
0033 constexpr Envelope zeroEnvelope = {0, 0};
0034 
0035 /// This struct models a multi-dimensional enveloper along the axis directions
0036 struct ExtentEnvelope {
0037   /// Access a single envelope configuration
0038   /// @param aDir the axis definition
0039   /// @return the envelope
0040   Envelope& operator[](AxisDirection aDir) {
0041     return m_values.at(toUnderlying(aDir));
0042   }
0043 
0044   /// Access a single envelope configuration
0045   /// @param aDir the axis direction
0046   /// @return the envelope
0047   const Envelope& operator[](AxisDirection aDir) const {
0048     return m_values.at(toUnderlying(aDir));
0049   }
0050 
0051   /// Constructor from a single envelope that is assigned to all values
0052   /// @param envelope the envelope to be assigned
0053   explicit ExtentEnvelope(const Envelope& envelope = zeroEnvelope) {
0054     for (auto& val : m_values) {
0055       val = envelope;
0056     }
0057   }
0058 
0059   /// Setter that allows for method chaining
0060   /// @param aDir the axis direction
0061   /// @param envelope the envelope to be set
0062   /// @return a reference to the envelope for chaining
0063   ExtentEnvelope& set(AxisDirection aDir, const Envelope& envelope) {
0064     m_values[toUnderlying(aDir)] = envelope;
0065     return *this;
0066   }
0067 
0068   /// Static factory for a zero envelope
0069   /// @return the zero envelope
0070   constexpr static ExtentEnvelope Zero() {
0071     return ExtentEnvelope{{
0072         zeroEnvelope,
0073         zeroEnvelope,
0074         zeroEnvelope,
0075         zeroEnvelope,
0076         zeroEnvelope,
0077         zeroEnvelope,
0078         zeroEnvelope,
0079         zeroEnvelope,
0080         zeroEnvelope,
0081     }};
0082   }
0083 
0084   /// Helper struct for designated initializer construction
0085   struct Arguments {
0086     /// Envelope for x-coordinate direction
0087     Envelope x = zeroEnvelope;
0088     /// Envelope for y-coordinate direction
0089     Envelope y = zeroEnvelope;
0090     /// Envelope for z-coordinate direction
0091     Envelope z = zeroEnvelope;
0092     /// Envelope for radial coordinate direction
0093     Envelope r = zeroEnvelope;
0094     /// Envelope for azimuthal angle direction
0095     Envelope phi = zeroEnvelope;
0096     /// Envelope for r*phi coordinate direction
0097     Envelope rPhi = zeroEnvelope;
0098     /// Envelope for polar angle direction
0099     Envelope theta = zeroEnvelope;
0100     /// Envelope for pseudorapidity direction
0101     Envelope eta = zeroEnvelope;
0102     /// Envelope for magnitude direction
0103     Envelope mag = zeroEnvelope;
0104   };
0105 
0106   /// Constructor using a helper struct for designated initializaion
0107   /// @param args the arguments
0108   constexpr explicit ExtentEnvelope(Arguments&& args) {
0109     using enum AxisDirection;
0110     m_values[toUnderlying(AxisX)] = args.x;
0111     m_values[toUnderlying(AxisY)] = args.y;
0112     m_values[toUnderlying(AxisZ)] = args.z;
0113     m_values[toUnderlying(AxisR)] = args.r;
0114     m_values[toUnderlying(AxisPhi)] = args.phi;
0115     m_values[toUnderlying(AxisTheta)] = args.theta;
0116     m_values[toUnderlying(AxisEta)] = args.eta;
0117     m_values[toUnderlying(AxisMag)] = args.mag;
0118   }
0119 
0120   /// Comparison operator between envelope sets
0121   /// @param lhs the left hand side
0122   /// @param rhs the right hand side
0123   /// @return true if the envelopes are equal
0124   friend bool operator==(const ExtentEnvelope& lhs, const ExtentEnvelope& rhs) {
0125     return lhs.m_values == rhs.m_values;
0126   }
0127 
0128  private:
0129   std::array<Envelope, numAxisDirections()> m_values{};
0130 };
0131 
0132 /// A class representing the geometric extent of an object in its possible
0133 /// dimensions, these can be all dimensions that are described as AxisDirections
0134 ///
0135 /// The extent object can have an optional envelope in all of those values
0136 /// @note that the consistency of the different envelopes is not checked
0137 ///
0138 class Extent {
0139  public:
0140   /// Constructor with (optional) @param envelope
0141   explicit Extent(const ExtentEnvelope& envelope = ExtentEnvelope::Zero());
0142 
0143   /// Define a comparison operator
0144   /// @param e The extent to compare with
0145   /// @return True if the extents are equal, false otherwise
0146   bool operator==(const Extent& e) const;
0147 
0148   /// Extend with a position vertex
0149   ///
0150   /// @param vtx the vertex to be used for extending
0151   /// @param aDirs the axis directions
0152   /// @param applyEnv boolean to steer if envelope should be applied
0153   /// @param fillHistograms is a boolean flag to steer whether the values
0154   ///        to fill this extent should be stored
0155   void extend(const Vector3& vtx,
0156               const std::vector<AxisDirection>& aDirs = allAxisDirections(),
0157               bool applyEnv = true, bool fillHistograms = false);
0158 
0159   /// Extend with a set of vectors by iterators
0160   ///
0161   /// @param start the start iterator of the loop
0162   /// @param end the end iterator of the loop
0163   /// @param aDirs the axis directions
0164   /// @param applyEnv boolean to steer if envelope should be applied
0165   /// @param fillHistograms is a boolean flag to steer whether the values
0166   ///        to fill this extent should be stored
0167   template <typename vector_iterator_t>
0168   void extend(const vector_iterator_t& start, const vector_iterator_t& end,
0169               const std::vector<AxisDirection>& aDirs = allAxisDirections(),
0170               bool applyEnv = true, bool fillHistograms = false) {
0171     for (vector_iterator_t vIt = start; vIt < end; ++vIt) {
0172       extend(*vIt, aDirs, applyEnv, fillHistograms);
0173     }
0174   }
0175 
0176   /// Extend with another geometric extent, usually pushes the
0177   /// current range to the boundaries of the rhs extent,
0178   /// unless the current extent is already bigger.
0179   ///
0180   /// @note the extent can also simply set an envelope
0181   /// which then is applied to the current one
0182   ///
0183   /// @param rhs is the other source Extent
0184   /// @param aDirs the axis directions
0185   /// @param applyEnv boolean to steer if envelope should be applied
0186   ///        on the constraint values, if only an envelope is given
0187   ///        but the value not constraint, then it is always applied
0188   ///
0189   /// @note that the histogram values can not be filled in this call
0190   void extend(const Extent& rhs,
0191               const std::vector<AxisDirection>& aDirs = allAxisDirections(),
0192               bool applyEnv = true);
0193 
0194   /// Constrain an extent by another one, this is
0195   /// - values that are already constrained are not touched
0196   /// - values not constrained by @param rhs are not touched
0197   /// - values that are constrained by the external one, but not
0198   /// by the current one, are touched
0199   ///
0200   /// @param envelope an envelope applied to the constrained value
0201   void addConstrain(const Extent& rhs,
0202                     const ExtentEnvelope& envelope = ExtentEnvelope::Zero());
0203 
0204   /// Set a range for a dedicated binning value
0205   ///
0206   /// @param aDir the axis direction
0207   /// @param min the minimum parameter
0208   /// @param max the maximum parameter
0209   void set(AxisDirection aDir, double min, double max);
0210 
0211   /// Set a min value for a dedicated binning value
0212   ///
0213   /// @param aDir the axis direction
0214   /// @param min the minimum parameter
0215   void setMin(AxisDirection aDir, double min);
0216 
0217   /// Set a max value for a dedicated binning value
0218   ///
0219   /// @param aDir the axis direction
0220   /// @param max the maximum parameter
0221   void setMax(AxisDirection aDir, double max);
0222 
0223   /// (re-)Set the envelope
0224   ///
0225   /// @param envelope new envelope to be set
0226   void setEnvelope(const ExtentEnvelope& envelope = ExtentEnvelope::Zero());
0227 
0228   /// Return the individual 1-dimensional range
0229   ///
0230   /// @param aDir is the axis direction to be returned
0231   ///
0232   /// @return a one dimensional arrange
0233   auto range(AxisDirection aDir) { return m_range[toUnderlying(aDir)]; }
0234 
0235   /// Return the individual 1-dimensional range
0236   ///
0237   /// @param aDir is the axis direction to be returned
0238   ///
0239   /// @return a one dimensional arrange
0240   Range1D<double> range(AxisDirection aDir) const;
0241 
0242   /// Return the N-dimension range
0243   /// @return Reference to the complete multi-dimensional range
0244   const RangeXD<numAxisDirections(), double>& range() const;
0245 
0246   /// Return an D-dimensional sub range according to the
0247   /// the given binvalues
0248   /// @tparam kSUBDIM the number of sub dimensions
0249   /// @param axisDirections the axis directions
0250   /// @return the sub range
0251   template <unsigned int kSUBDIM>
0252   RangeXD<kSUBDIM, double> range(
0253       const std::array<AxisDirection, kSUBDIM>& axisDirections) const {
0254     RangeXD<kSUBDIM, double> rRange;
0255     for (auto [i, v] : enumerate(axisDirections)) {
0256       rRange[i] = range(v);
0257     }
0258     return rRange;
0259   }
0260 
0261   /// Return the envelope - non-const access
0262   /// @return Reference to the envelope for modification
0263   ExtentEnvelope& envelope();
0264 
0265   /// Return the envelope - const access
0266   /// @return Const reference to the envelope
0267   const ExtentEnvelope& envelope() const;
0268 
0269   /// Return the histogram store
0270   ///
0271   /// The histogram store can be used for automated binning detection
0272   const std::array<std::vector<double>, numAxisDirections()>& valueHistograms()
0273       const;
0274 
0275   /// Access the minimum parameter
0276   ///
0277   /// @param aDir the axis direction
0278   /// @return Minimum value along the specified axis direction
0279   double min(AxisDirection aDir) const {
0280     return m_range[toUnderlying(aDir)].min();
0281   }
0282 
0283   /// Access the maximum parameter
0284   ///
0285   /// @param aDir the axis direction
0286   /// @return Maximum value along the specified axis direction
0287   double max(AxisDirection aDir) const {
0288     return m_range[toUnderlying(aDir)].max();
0289   }
0290 
0291   /// Access the midpoint
0292   ///
0293   /// @param aDir the axis direction
0294   /// @return Midpoint value along the specified axis direction
0295   double medium(AxisDirection aDir) const {
0296     return 0.5 * (m_range[toUnderlying(aDir)].min() +
0297                   m_range[toUnderlying(aDir)].max());
0298   }
0299 
0300   /// Access the parameter interval (i.e. the range span)
0301   ///
0302   /// @param aDir the axis direction
0303   /// @return Interval size along the specified axis direction
0304   double interval(AxisDirection aDir) const {
0305     return m_range[toUnderlying(aDir)].size();
0306   }
0307 
0308   /// Contains check
0309   ///
0310   /// @param rhs the extent that is check if it is contained
0311   /// @param aDir is the axis direction, if set to nullopt
0312   ///               the check on all is done
0313   ///
0314   /// @return true if the rhs is contained
0315   bool contains(const Extent& rhs,
0316                 std::optional<AxisDirection> aDir = std::nullopt) const;
0317 
0318   /// Contains check for a single point
0319   ///
0320   /// @param vtx the point that is check if it is contained
0321   ///
0322   /// @return true if the rhs is contained
0323   bool contains(const Vector3& vtx) const;
0324 
0325   /// Intersection checks
0326   ///
0327   /// @param rhs the extent that is check for intersection
0328   /// @param aDir is the axis direction, if set to nulloptr
0329   ///               the check on all is done
0330   ///
0331   /// @return true if the rhs intersects
0332   bool intersects(const Extent& rhs,
0333                   std::optional<AxisDirection> aDir = std::nullopt) const;
0334 
0335   /// Check if this object constrains a given direction
0336   ///
0337   /// @param aDir is the axis direction
0338   /// @return True if the specified axis direction is constrained, false otherwise
0339   bool constrains(AxisDirection aDir) const;
0340 
0341   /// Check if this object constrains any direction
0342   /// @return True if any axis direction is constrained, false otherwise
0343   bool constrains() const;
0344 
0345   /// Convert to output stream for screen output
0346   ///
0347   /// @param indent indentation for the screen display
0348   /// @return String representation of the extent
0349   std::string toString(const std::string& indent = "") const;
0350 
0351  private:
0352   /// A bitset that remembers the constraint values
0353   std::bitset<numAxisDirections()> m_constrains{0};
0354   /// The actual range store
0355   RangeXD<numAxisDirections(), double> m_range;
0356   /// A potential envelope
0357   ExtentEnvelope m_envelope = ExtentEnvelope::Zero();
0358   /// (Optional) Value histograms for bin detection
0359   std::array<std::vector<double>, numAxisDirections()> m_valueHistograms;
0360 };
0361 
0362 inline Range1D<double> Acts::Extent::range(AxisDirection aDir) const {
0363   return m_range[toUnderlying(aDir)];
0364 }
0365 
0366 inline const RangeXD<numAxisDirections(), double>& Extent::range() const {
0367   return m_range;
0368 }
0369 
0370 inline ExtentEnvelope& Extent::envelope() {
0371   return m_envelope;
0372 }
0373 
0374 inline const ExtentEnvelope& Extent::envelope() const {
0375   return m_envelope;
0376 }
0377 
0378 /// Return the value histograms
0379 /// @return Reference to the value histograms array
0380 inline const std::array<std::vector<double>, numAxisDirections()>&
0381 Extent::valueHistograms() const {
0382   return m_valueHistograms;
0383 }
0384 
0385 /// Overload of << operator for std::ostream for debug output
0386 /// @param sl Output stream
0387 /// @param rhs Extent to output
0388 /// @return Reference to output stream
0389 std::ostream& operator<<(std::ostream& sl, const Extent& rhs);
0390 
0391 }  // namespace Acts