Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:11:09

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