![]() |
|
|||
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"
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |