Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:23:48

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file orange/orangeinp/detail/BoundingZone.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "geocel/BoundingBox.hh"
0010 #include "orange/BoundingBoxUtils.hh"
0011 
0012 namespace celeritas
0013 {
0014 namespace orangeinp
0015 {
0016 namespace detail
0017 {
0018 //---------------------------------------------------------------------------//
0019 /*!
0020  * Exterior and interior CSG node bounding boxes.
0021  *
0022  * This class manages the "zone" enclosing a CSG region's boundary. It
0023  * partitions space into three concentric zones: "known inside" the region,
0024  * "maybe inside, maybe outside" the region, and "known outside" the region.
0025  *
0026  * \verbatim
0027  *  outside           ; inside
0028  *   +-------------+  ;  +-------------+
0029  *   | maybe   ..  |  ;  | maybe   ..  |
0030  *   |  .......  . |  ;  |  .......  . |
0031  *   | .+-----+ .  |  ;  | .+-----+ .  |
0032  *   | .| in  |  ..|  ;  | .| out |  ..|
0033  *   | .|     |   .|  ;  | .|     |   .|
0034  *   | .+-----+ .. |  ;  | .+-----+ .. |
0035  *   | ........    |  ;  | ........    |
0036  *   +-------------+  ;  +-------------+
0037  *                    ;
0038  *   negated = false  ;  negated = true
0039  * \endverbatim
0040  *
0041  * - Known outside is the typical bounding box case: nowhere outside the
0042  *   bounding box is inside the volume; i.e., the box completely encloses the
0043  *   volume (but may also enclose parts that *aren't* volume).
0044  * - Known inside can be used for safety distance calculation.
0045  * - Flipping the two cases when applying a "not" operator to a CSG node: so
0046  *   "known inside" becomes "known outside" and could potentially be flipped
0047  *   back in a subsequent simplification.
0048  *
0049  * The \c exterior box always encloses (or is identical to) \c interior in the
0050  * bounding zone.  The \c negated flag corresponds to taking the \em complement
0051  * of a closed CSG region.
0052  *
0053  * If \c negated is \c false, then the exterior box is what we
0054  * typically think of as a bounding box. If \c true, then even though the
0055  * exterior bounding box encloses interior box, *all points inside
0056  * the interior box are known to be outside the volume*.  Regardless of
0057  * negation, the area between the interior and exterior bounding boxes is \em
0058  * indeterminate: a point in that space may be within the CSG region, or it may
0059  * not.
0060  *
0061  * The behavior of boundaries (whether coincident boundary/shape should count
0062  * as being "interior" or "exterior") shouldn't matter because we will always
0063  * "bump" boundaries before using them for transport.
0064  *
0065  * The following table shows the semantics of set operations on the bounding
0066  * zones.  Below, \c ~zone means a zone with the \c negated flag set; \c ~box
0067  * means "complement of a bbox": all space *except*
0068  * inside box; and the union operator implies the (possibly disconnected and
0069  * probably not box-shaped!) union of the two boxes. \c A_i is the interior
0070  * (enclosed) box for A, and \c A_x is the exterior (enclosing) box.
0071  *
0072  * | Zone      | known inside   | known outside   |
0073  * | ------    | ------------   | -------------   |
0074  * | `A`       | `A_i`          | `~A_x`          |
0075  * | `~A`      | `~A_x`         | `A_i`           |
0076  * | `A & B`   | `A_i & B_i`    | `~(A_x & B_x)`  |
0077  * | `~A & B ` | `~A_x & B_i`   | `~(~A_i & B_x)` |
0078  * | `~A & ~B` | `~A_x & ~B_x`  | `~(~A_i & ~B_i)`|
0079  * | `A | B`   | `A_i | B_i`    | `~(A_x | B_x)`  |
0080  * | `~A | B ` | `~A_x | B_i`   | `~(~A_i | B_x)` |
0081  * | `~A | ~B` | `~A_x | ~B_x`  | `~(~A_i | ~B_i)`|
0082  *
0083  * The following set algebra can be used:
0084  * - Involution: \verbatim ~~A <=> A \endverbatim
0085  * - De Morgan's law 1: \verbatim ~A | ~B <=> ~(A & B) \endverbatim
0086  * - De Morgan's law 2:\verbatim ~A & ~B <=> ~(A | B) \endverbatim
0087  * - Set difference: \verbatim A & ~B <=> A - B \endverbatim
0088  * - Negated set difference: \verbatim A | ~B <=> ~(B - A) \endverbatim
0089  *
0090  * The default bounding zone is the empty set: nothing is inside, everything is
0091  * known outside.
0092  */
0093 struct BoundingZone
0094 {
0095     using BBox = ::celeritas::BoundingBox<>;
0096 
0097     BBox interior;
0098     BBox exterior;
0099     bool negated{false};  //!< "exterior" means "known inside"
0100 
0101     // Flip inside and outside
0102     inline void negate();
0103 
0104     // Create an "everything is known inside" zone for intersecting
0105     static BoundingZone from_infinite();
0106 };
0107 
0108 //---------------------------------------------------------------------------//
0109 // FREE FUNCTIONS
0110 //---------------------------------------------------------------------------//
0111 // Calculate the intersection of two bounding zones
0112 BoundingZone calc_intersection(BoundingZone const& a, BoundingZone const& b);
0113 
0114 // Calculate the union of two bounding zones
0115 BoundingZone calc_union(BoundingZone const& a, BoundingZone const& b);
0116 
0117 // Get an infinite bbox if "negated", else get the exterior
0118 BBox get_exterior_bbox(BoundingZone const&);
0119 
0120 //---------------------------------------------------------------------------//
0121 /*!
0122  * Flip inside and outside.
0123  *
0124  * This doesn't swap bounding boxes because the "exterior" box still is larger
0125  * than the interior.
0126  */
0127 void BoundingZone::negate()
0128 {
0129     CELER_EXPECT(!this->exterior || !this->interior
0130                  || encloses(this->exterior, this->interior));
0131     this->negated = !this->negated;
0132 }
0133 
0134 //---------------------------------------------------------------------------//
0135 }  // namespace detail
0136 }  // namespace orangeinp
0137 }  // namespace celeritas