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