Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:05:55

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