Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-14 08:10:48

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 #include "Acts/Utilities/Frustum.hpp"
0012 #include "Acts/Utilities/Ray.hpp"
0013 #include "Acts/Visualization/IVisualization3D.hpp"
0014 
0015 #include <memory>
0016 #include <vector>
0017 
0018 namespace Acts {
0019 
0020 /// Implementation of an Axis Aligned Bounding Box. This type is compatible
0021 /// with 2D and 3D boxes
0022 template <typename entity_t, typename value_t, std::size_t DIM>
0023 class AxisAlignedBoundingBox {
0024  private:
0025   /// Private self type to capture template parameters
0026   using self_t = AxisAlignedBoundingBox<entity_t, value_t, DIM>;
0027 
0028   /// Strong type helper, not public
0029   /// This is only used to provide sensible tag-dispatch below.
0030   template <typename T, typename P>
0031   class NamedType {
0032    public:
0033     explicit NamedType(const T& value) : m_value(value) {}
0034     explicit NamedType(T&& value) : m_value(std::move(value)) {}
0035     T& get() { return m_value; }
0036     const T& get() const { return m_value; }
0037 
0038    private:
0039     T m_value;
0040   };
0041 
0042   /// SizeParameter Tag
0043   struct SizeParameter {};
0044 
0045  public:
0046   /// The value type used by this class
0047   using value_type = value_t;
0048 
0049   /// Re-export vertex type based on value type given
0050   using VertexType = Eigen::Matrix<value_t, DIM, 1>;
0051 
0052   /// Associated array value to `VertexType`
0053   using vertex_array_type = Eigen::Array<value_t, DIM, 1>;
0054 
0055   /// Type of stored entity
0056   using entity_type = entity_t;
0057 
0058   /// The transform type based on the `value_type`
0059   using transform_type = Eigen::Transform<value_type, DIM, Eigen::Affine>;
0060 
0061   /// Strong type to select the correct constructor
0062   using Size = NamedType<VertexType, struct SizeParameter>;
0063 
0064   /// Re-export dimension from template parameter
0065   static const std::size_t dim = DIM;
0066 
0067   /// Copy constructor from other bounding box.
0068   AxisAlignedBoundingBox(const self_t& other) = default;
0069 
0070   /// Copy assignment operator from other bounding box.
0071   /// @param other The other AABB
0072   AxisAlignedBoundingBox& operator=(const self_t& other) = default;
0073 
0074   /// Constructor from an entity pointer, and the min and max vertices.
0075   /// @param entity The entity to store
0076   /// @param vmin The minimum vertex.
0077   /// @param vmax The maximum vertex.
0078   AxisAlignedBoundingBox(const entity_t* entity, const VertexType& vmin,
0079                          const VertexType& vmax);
0080 
0081   /// Constructor from a center position, and a width and height.
0082   /// @param entity The entity to store
0083   /// @param center The center position
0084   /// @param size The size (width and height) of the box.
0085   /// @note The special type @c size is required to disambiguate this constructor
0086   /// from the other one above. It is a wrapper around a simple @c Vector3.
0087   AxisAlignedBoundingBox(const entity_t* entity, const VertexType& center,
0088                          const Size& size);
0089 
0090   /// Constructor from a list of child boxes. This box will wrap around all
0091   /// boxes
0092   /// contained in @p boxes, and additional envelope can be given.
0093   /// @param boxes Vector of child boxes to store in this bounding box.
0094   /// @param envelope Envelope that will be added/subtracted to the dimension.
0095   explicit AxisAlignedBoundingBox(
0096       const std::vector<self_t*>& boxes,
0097       vertex_array_type envelope = vertex_array_type::Zero());
0098 
0099   /// Helper function to calculate the size of a bounding box enclosing @p boxes.
0100   /// @param boxes The boxes to wrap (const pointers)
0101   /// @param envelope Optional envelop to add/subtract to dimension.
0102   /// @return Pair of vertices: min and max.
0103   static std::pair<VertexType, VertexType> wrap(
0104       const std::vector<const self_t*>& boxes,
0105       vertex_array_type envelope = vertex_array_type::Zero());
0106 
0107   /// Helper function to calculate the size of a bounding box enclosing @p boxes.
0108   /// Overload which accepts non-const boxes in @p boxes.
0109   /// @param boxes The boxes to wrap (non-const pointers)
0110   /// @param envelope Optional envelop to add/subtract to dimension.
0111   /// @return Pair of vertices: min and max.
0112   static std::pair<VertexType, VertexType> wrap(
0113       const std::vector<self_t*>& boxes,
0114       vertex_array_type envelope = vertex_array_type::Zero());
0115 
0116   /// Helper function to calculate the size of a bounding box enclosing @p boxes.
0117   /// Overload which accepts a vector in @p boxes which owns the instances
0118   /// @param boxes The boxes to wrap (by-value vector)
0119   /// @param envelope Optional envelop to add/subtract to dimension.
0120   /// @return Pair of vertices: min and max.
0121   static std::pair<VertexType, VertexType> wrap(
0122       const std::vector<self_t>& boxes,
0123       vertex_array_type envelope = vertex_array_type::Zero());
0124 
0125   /// Calculate whether a point is inside this box.
0126   /// @param point The point to test.
0127   /// @return Whether the point is inside or not.
0128   bool intersect(const VertexType& point) const;
0129 
0130   /// @brief Implements the slab method for Ray/AABB intersections.
0131   ///
0132   /// See https://tavianator.com/fast-branchless-raybounding-box-intersections/,
0133   /// https://tavianator.com/fast-branchless-raybounding-box-intersections-part-2-nans/,
0134   /// https://medium.com/@bromanz/another-view-on-the-classic-ray-aabb-intersection-algorithm-for-bvh-traversal-41125138b525
0135   /// The original algorithms is described in "Graphics Gems (1990)" [1]
0136   /// (https://doi.org/10.1016/B978-0-08-050753-8.50084-X)
0137   ///
0138   /// @note This implementation may treat parallel rays on any of the slabs
0139   ///       as **outside** due to how @c NaNs are handled by Eigen.
0140   ///       See https://eigen.tuxfamily.org/bz/show_bug.cgi?id=564
0141   /// @param ray The ray to intersect with
0142   /// @return Whether the ray intersects this AABB
0143   bool intersect(const Ray<value_type, DIM>& ray) const;
0144 
0145   /// Check if a frustum intersects with this bounding box.
0146   ///
0147   /// This method implements an algorithm similar to the one described in
0148   /// "Optimized View Frustum Culling Algorithms for Bounding Boxes (2012)" [2]
0149   /// (https://doi.org/10.1080/10867651.2000.10487517), but drops some of the
0150   /// more sophisticated optimization.
0151   ///
0152   /// @param fr The frustum
0153   /// @return Whether the frustum intersects this AABB
0154   template <std::size_t sides>
0155   bool intersect(const Frustum<value_type, DIM, sides>& fr) const;
0156 
0157   /// Set the skip node (bounding box)
0158   /// @param skip The target skip node pointer
0159   void setSkip(self_t* skip);
0160 
0161   /// Get the skip node for this box
0162   /// @return The skip node pointer
0163   const self_t* getSkip() const;
0164 
0165   /// Get the left child (i.e. the first of the children that are inside this
0166   /// bounding box).
0167   /// @return The lest most child.
0168   const self_t* getLeftChild() const;
0169 
0170   /// Check whether this node as an associated entity. If it does not have one,
0171   /// this is a purely abstract container box.
0172   /// @return Whether the box has an entity attached.
0173   bool hasEntity() const;
0174 
0175   /// Return the entity associated with this box. This might be nullptr if there
0176   /// is no entity attached.
0177   /// @return The entity pointer, might be nullptr
0178   const entity_t* entity() const;
0179 
0180   /// Set the entity associated with with this box.
0181   /// @param entity The entity
0182   void setEntity(const entity_t* entity);
0183 
0184   /// Get the center position of this bounding box.
0185   /// @return The center position
0186   const VertexType& center() const;
0187 
0188   /// Get the minimum vertex
0189   /// @return The minimum vertex
0190   const VertexType& min() const;
0191 
0192   /// Get the maximum vertex
0193   /// @return The maximum vertex
0194   const VertexType& max() const;
0195 
0196   /// Write information about this bounding box to a stream.
0197   /// @param os The output stream.
0198   /// @return The stream given as an argument.
0199   std::ostream& toStream(std::ostream& os) const;
0200 
0201   /// Transforms this bounding box using the given transform. This method
0202   /// modifies the box it is called on.
0203   /// @param trf The transform
0204   void transform(const transform_type& trf);
0205 
0206   /// Transforms this bounding box using the given transform. This method
0207   /// returns a copy of this box, with the transformation applied, and leaves
0208   /// this instance unchanged.
0209   /// @param trf The transform
0210   /// @return The transformed bounding box
0211   self_t transformed(const transform_type& trf) const;
0212 
0213   /// Draw this bounding box using the given visualization helper. This method
0214   /// is only available for the 3D case.
0215   /// @param helper The visualization helper to write to
0216   /// @param color The color to use for drawing
0217   /// @param trf An optional transform to apply first.
0218   void draw(IVisualization3D& helper, Color color = {120, 120, 120},
0219             const transform_type& trf = transform_type::Identity()) const
0220     requires(DIM == 3);
0221 
0222   /// Draw this bounding box as SVG. This method is only available for the 2D
0223   /// case.
0224   /// @param os The output stream to write to
0225   /// @param w The width of the output SVG.
0226   /// @param h The height of the output SVG.
0227   /// @param unit A scale factor to apply before drawing
0228   /// @param label A label to put next to the box.
0229   /// @param fillcolor Color to fill the box with.
0230   /// @return The outstream given in @p os.
0231   std::ostream& svg(std::ostream& os, value_type w, value_type h,
0232                     value_type unit = 10, const std::string& label = "",
0233                     const std::string& fillcolor = "grey") const
0234     requires(DIM == 2);
0235 
0236  private:
0237   std::pair<VertexType, VertexType> transformVertices(
0238       const transform_type& trf) const
0239     requires(DIM == 2);
0240 
0241   std::pair<VertexType, VertexType> transformVertices(
0242       const transform_type& trf) const
0243     requires(DIM == 3);
0244 
0245   const entity_t* m_entity;
0246   VertexType m_vmin;
0247   VertexType m_vmax;
0248   VertexType m_center;
0249   vertex_array_type m_width;
0250   vertex_array_type m_iwidth;
0251 
0252   self_t* m_left_child{nullptr};
0253   self_t* m_right_child{nullptr};
0254   self_t* m_skip{nullptr};
0255 };
0256 
0257 /// Build an octree from a list of bounding boxes.
0258 /// @note @p store and @p prims do not need to contain the same objects. @p store
0259 /// is only used to pass ownership back to the caller while preserving memory
0260 /// location.
0261 /// @tparam box_t Works will all box types.
0262 /// @param store Owns the created boxes by means of `std::unique_ptr`.
0263 /// @param prims Boxes to store. This is a read only vector.
0264 /// @param max_depth No subdivisions beyond this level.
0265 /// @param envelope1 Envelope to add/subtract to dimensions in all directions.
0266 /// @return Pointer to the top most bounding box, containing the entire octree
0267 template <typename box_t>
0268 box_t* make_octree(std::vector<std::unique_ptr<box_t>>& store,
0269                    const std::vector<box_t*>& prims, std::size_t max_depth = 1,
0270                    typename box_t::value_type envelope1 = 0);
0271 
0272 /// Overload of the << operator for bounding boxes.
0273 /// @tparam T entity type
0274 /// @tparam U value type
0275 /// @tparam V dimension
0276 /// @param os The output stream
0277 /// @param box The bounding box
0278 /// @return The given output stream.
0279 template <typename T, typename U, std::size_t V>
0280 std::ostream& operator<<(std::ostream& os,
0281                          const AxisAlignedBoundingBox<T, U, V>& box);
0282 
0283 }  // namespace Acts
0284 
0285 #include "Acts/Utilities/BoundingBox.ipp"