forked from celeritas-project/celeritas
-
Notifications
You must be signed in to change notification settings - Fork 0
/
BoundingZone.hh
130 lines (122 loc) · 5.22 KB
/
BoundingZone.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//----------------------------------*-C++-*----------------------------------//
// Copyright 2024 UT-Battelle, LLC, and other Celeritas developers.
// See the top-level COPYRIGHT file for details.
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
//---------------------------------------------------------------------------//
//! \file orange/orangeinp/detail/BoundingZone.hh
//---------------------------------------------------------------------------//
#pragma once
#include "orange/BoundingBox.hh"
#include "orange/BoundingBoxUtils.hh"
namespace celeritas
{
namespace orangeinp
{
namespace detail
{
//---------------------------------------------------------------------------//
/*!
* Exterior and interior CSG node bounding boxes.
*
* This class manages the "zone" enclosing a CSG region's boundary. It
* partitions space into three concentric zones: "known inside" the region,
* "maybe inside, maybe outside" the region, and "known outside" the region.
*
* \verbatim
* outside ; inside
* +-------------+ ; +-------------+
* | maybe .. | ; | maybe .. |
* | ....... . | ; | ....... . |
* | .+-----+ . | ; | .+-----+ . |
* | .| in | ..| ; | .| out | ..|
* | .| | .| ; | .| | .|
* | .+-----+ .. | ; | .+-----+ .. |
* | ........ | ; | ........ |
* +-------------+ ; +-------------+
* ;
* negated = false ; negated = true
* \endverbatim
*
* - Known outside is the typical bounding box case: nowhere outside the
* bounding box is inside the volume; i.e., the box completely encloses the
* volume (but may also enclose parts that *aren't* volume).
* - Known inside can be used for safety distance calculation.
* - Flipping the two cases when applying a "not" operator to a CSG node: so
* "known inside" becomes "known outside" and could potentially be flipped
* back in a subsequent simplification.
*
* The \c exterior box always encloses (or is identical to) \c interior in the
* bounding zone. The \c negated flag corresponds to taking the \em complement
* of a closed CSG region.
*
* If \c negated is \c false, then the exterior box is what we
* typically think of as a bounding box. If \c true, then even though the
* exterior bounding box encloses interior box, *all points inside
* the interior box are known to be outside the volume*. Regardless of
* negation, the area between the interior and exterior bounding boxes is \em
* indeterminate: a point in that space may be within the CSG region, or it may
* not.
*
* The behavior of boundaries (whether coincident boundary/shape should count
* as being "interior" or "exterior") shouldn't matter because we will always
* "bump" boundaries before using them for transport.
*
* The following table shows the semantics of set operations on the bounding
* zones. Below, \c ~zone means a zone with the \c negated flag set; \c ~box
* means "complement of a bbox": all space *except*
* inside box; and the union operator implies the (possibly disconnected and
* probably not box-shaped!) union of the two boxes. \c A_i is the interior
* (enclosed) box for A, and \c A_x is the exterior (enclosing) box.
*
* | Zone | known inside | known outside |
* | ------ | ------------ | ------------- |
* | `A` | `A_i` | `~A_x` |
* | `~A` | `~A_x` | `A_i` |
* | `A & B` | `A_i & B_i` | `~(A_x & B_x)` |
* | `~A & B ` | `~A_x & B_i` | `~(~A_i & B_x)` |
* | `~A & ~B` | `~A_x & ~B_x` | `~(~A_i & ~B_i)`|
* | `A | B` | `A_i | B_i` | `~(A_x | B_x)` |
* | `~A | B ` | `~A_x | B_i` | `~(~A_i | B_x)` |
* | `~A | ~B` | `~A_x | ~B_x` | `~(~A_i | ~B_i)`|
*
* The following set algebra can be used:
* - Involution: \verbatim ~~A <=> A \endverbatim
* - De Morgan's law 1: \verbatim ~A | ~B <=> ~(A & B) \endverbatim
* - De Morgan's law 1:\verbatim ~A & ~B <=> ~(A | B) \endverbatim
* - Set difference: \verbatim A & ~B <=> A - B \endverbatim
* - Negated set difference: \verbatim A | ~B <=> ~(B - A) \endverbatim
*
* The default bounding zone places all points in the \em indeterminate zone:
* the exterior is the "universe set" (infinite) and the interior is the "empty
* set" (null).
*/
struct BoundingZone
{
using BBox = ::celeritas::BoundingBox<>;
BBox interior;
BBox exterior = BBox::from_infinite();
bool negated{false}; //!< "exterior" means "known inside"
// Flip inside and outside
inline void negate();
};
// Calculate the intersection of two bounding zones
BoundingZone calc_intersection(BoundingZone const& a, BoundingZone const& b);
// Calculate the union of two bounding zones
BoundingZone calc_union(BoundingZone const& a, BoundingZone const& b);
//---------------------------------------------------------------------------//
/*!
* Flip inside and outside.
*
* This doesn't swap bounding boxes because the "exterior" box still is larger
* than the interior.
*/
void BoundingZone::negate()
{
CELER_EXPECT(!this->exterior || !this->interior
|| encloses(this->exterior, this->interior));
this->negated = !this->negated;
}
//---------------------------------------------------------------------------//
} // namespace detail
} // namespace orangeinp
} // namespace celeritas