Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-13 11:00:28

0001 // This file is part of VecGeom and is distributed under the
0002 // conditions in the file LICENSE.txt in the top directory.
0003 // For the full list of authors see CONTRIBUTORS.txt and `git log`.
0004 
0005 /// \brief Host-side clipped extent helper for AABB and convex polyhedral envelopes.
0006 /// \file volumes/utilities/BoundingEnvelope.h
0007 
0008 #ifndef VECGEOM_VOLUMES_UTILITIES_BOUNDINGENVELOPE_H_
0009 #define VECGEOM_VOLUMES_UTILITIES_BOUNDINGENVELOPE_H_
0010 
0011 #include "VecGeom/volumes/utilities/ClippedExtent.h"
0012 
0013 #include <vector>
0014 
0015 namespace vecgeom {
0016 
0017 namespace clipped_extent_detail {
0018 
0019 /// @brief One convex envelope face described by local vertex indices.
0020 struct BoundingEnvelopeFace {
0021   /// Indices into the owning convex piece vertex array.
0022   std::vector<int> vertices;
0023 };
0024 
0025 /// @brief One convex local envelope piece consumed by `BoundingEnvelope`.
0026 struct BoundingEnvelopeConvexPiece {
0027   /// Local-frame vertices of the convex piece.
0028   std::vector<Vector3D<Precision>> local_vertices;
0029   /// Faces defining the convex piece boundary.
0030   std::vector<BoundingEnvelopeFace> faces;
0031 };
0032 
0033 } // namespace clipped_extent_detail
0034 
0035 /// @brief Host-side clipped extent helper for conservative convex envelopes.
0036 ///
0037 /// @details
0038 /// A `BoundingEnvelope` stores one or more local-frame convex pieces. Queries
0039 /// transform those pieces to the mother frame, clip them against `VoxelLimits`,
0040 /// and return conservative axis-aligned bounds. Multiple pieces are combined as
0041 /// a union, so non-convex solids can be represented by conservative convex
0042 /// decompositions.
0043 class BoundingEnvelope {
0044 public:
0045   BoundingEnvelope() = default;
0046 
0047   /// @brief Construct an envelope from one local AABB.
0048   /// @param local_min Local lower AABB corner.
0049   /// @param local_max Local upper AABB corner.
0050   BoundingEnvelope(Vector3D<Precision> const &local_min, Vector3D<Precision> const &local_max);
0051 
0052   /// @brief Construct an envelope from one local AABB.
0053   /// @param local_min Local lower AABB corner.
0054   /// @param local_max Local upper AABB corner.
0055   /// @return Bounding envelope containing one AABB piece.
0056   static BoundingEnvelope FromLocalAABB(Vector3D<Precision> const &local_min, Vector3D<Precision> const &local_max)
0057   {
0058     return BoundingEnvelope(local_min, local_max);
0059   }
0060 
0061   /// @brief Add one prism with matching lower and upper polygon bases.
0062   /// @param lower_base Local vertices of the lower base polygon.
0063   /// @param lower_count Number of vertices in `lower_base`.
0064   /// @param upper_base Local vertices of the upper base polygon.
0065   /// @param upper_count Number of vertices in `upper_base`; must match `lower_count`.
0066   void AddLocalPrism(const Vector3D<Precision> *lower_base, int lower_count, const Vector3D<Precision> *upper_base,
0067                      int upper_count);
0068 
0069 #ifndef VECCORE_CUDA
0070   /// @brief Add a conservative angular decomposition of one local conical frustum.
0071   ///
0072   /// @details
0073   /// The frustum is split into convex phi cells. Outer circular arcs are
0074   /// circumscribed by scaling the outer radii on each cell boundary by
0075   /// `1 / cos(cell_delta_phi / 2)`, matching the envelope idea used by
0076   /// Geant4 polycone extents. Inner radii stay unscaled, which may over-cover
0077   /// the hole but does not under-cover the solid. `full_phi_segments` controls
0078   /// the number of cells used for a full `2*pi` revolution.
0079   ///
0080   /// @param rmin1 Inner radius at `z1`.
0081   /// @param rmax1 Outer radius at `z1`.
0082   /// @param rmin2 Inner radius at `z2`.
0083   /// @param rmax2 Outer radius at `z2`.
0084   /// @param z1 Lower or first z plane of the frustum.
0085   /// @param z2 Upper or second z plane of the frustum.
0086   /// @param phi_start Start angle in local coordinates.
0087   /// @param phi_delta Phi opening angle in radians.
0088   /// @param full_phi_segments Number of angular cells used for a full circle.
0089   void AddLocalConicalFrustum(Precision rmin1, Precision rmax1, Precision rmin2, Precision rmax2, Precision z1,
0090                               Precision z2, Precision phi_start, Precision phi_delta, int full_phi_segments = 24);
0091 
0092   /// @brief Add a conservative circumscribed envelope for a full local sphere.
0093   ///
0094   /// @details
0095   /// The sphere is decomposed into theta bands with regular phi polygons.
0096   /// Ring vertices are placed at angular cell centers and scaled by
0097   /// `1 / cos(half_cell_angle)`, so the meridian and phi polygons both
0098   /// circumscribe the spherical surface. The default 8 theta and 16 phi
0099   /// segments match the `G4Orb` clipped-extent envelope.
0100   ///
0101   /// @param radius Sphere radius.
0102   /// @param theta_segments Number of bands in polar angle.
0103   /// @param phi_segments Number of angular cells in a full circle.
0104   void AddLocalSphere(Precision radius, int theta_segments = 8, int phi_segments = 16);
0105 
0106   /// @brief Add a conservative full-phi elliptical frustum envelope.
0107   ///
0108   /// @details
0109   /// Each z end is covered by an affine-scaled tangent polygon of the local
0110   /// ellipse, using the same `1 / cos(cell_delta_phi / 2)` circumscription as
0111   /// circular frustum envelopes. The helper covers solid elliptical frusta with
0112   /// no inner hole; equal lower and upper radii produce an elliptical cylinder.
0113   ///
0114   /// @param x_radius1 Semi-axis in x at `z1`.
0115   /// @param y_radius1 Semi-axis in y at `z1`.
0116   /// @param x_radius2 Semi-axis in x at `z2`.
0117   /// @param y_radius2 Semi-axis in y at `z2`.
0118   /// @param z1 Lower or first z plane of the frustum.
0119   /// @param z2 Upper or second z plane of the frustum.
0120   /// @param full_phi_segments Number of angular cells used for a full ellipse.
0121   void AddLocalEllipticalFrustum(Precision x_radius1, Precision y_radius1, Precision x_radius2, Precision y_radius2,
0122                                  Precision z1, Precision z2, int full_phi_segments = 24);
0123 #endif
0124 
0125   /// @brief Add one finite convex polyhedral envelope piece from local vertices and faces.
0126   ///
0127   /// @details
0128   /// Faces are described by contiguous entries in `face_indices`; each
0129   /// `face_vertex_counts[i]` gives the number of vertex indices for face `i`.
0130   /// Face orientation is not significant: plane normals are oriented from the
0131   /// piece centroid when the envelope is clipped. This helper is intended for
0132   /// exact or conservative convex pieces such as tetrahedra, pyramids, and
0133   /// future convex decompositions; non-convex solids must add multiple convex
0134   /// pieces or use another conservative envelope.
0135   ///
0136   /// @param vertices Local-frame vertices.
0137   /// @param vertex_count Number of vertices.
0138   /// @param face_indices Contiguous face vertex indices.
0139   /// @param face_index_count Number of entries in `face_indices`.
0140   /// @param face_vertex_counts Number of vertices for each face.
0141   /// @param face_count Number of faces.
0142   void AddLocalConvexPolyhedron(const Vector3D<Precision> *vertices, int vertex_count, const int *face_indices,
0143                                 int face_index_count, const int *face_vertex_counts, int face_count);
0144 
0145   /// @brief Calculate one clipped mother-frame extent interval.
0146   /// @param axis Axis to project.
0147   /// @param limits Mother-frame clipping limits.
0148   /// @param transform Local-to-mother transform.
0149   /// @param[out] min Lower extent along `axis` when an overlap exists.
0150   /// @param[out] max Upper extent along `axis` when an overlap exists.
0151   /// @param tolerance Final symmetric inflation applied before limiting.
0152   /// @return True when the envelope intersects `limits`.
0153   bool CalculateExtent(Axis axis, VoxelLimits const &limits, Transformation3D const &transform, Precision &min,
0154                        Precision &max, Precision tolerance = kAABBPadding) const;
0155 
0156   /// @brief Calculate a clipped mother-frame AABB for all stored pieces.
0157   /// @param limits Mother-frame clipping limits.
0158   /// @param transform Local-to-mother transform.
0159   /// @param tolerance Final symmetric inflation applied before limiting.
0160   /// @return Conservative clipped box; `exists` is false when no piece overlaps.
0161   ClippedBox CalculateClippedBox(VoxelLimits const &limits, Transformation3D const &transform,
0162                                  Precision tolerance = kAABBPadding) const;
0163 
0164 private:
0165   std::vector<clipped_extent_detail::BoundingEnvelopeConvexPiece> fPieces;
0166 };
0167 
0168 } // namespace vecgeom
0169 
0170 #endif // VECGEOM_VOLUMES_UTILITIES_BOUNDINGENVELOPE_H_