|
|
|||
File indexing completed on 2026-11-13 10:48:06
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/Solid.hh 0006 //---------------------------------------------------------------------------// 0007 #pragma once 0008 0009 #include <optional> 0010 #include <type_traits> 0011 #include <utility> 0012 #include <vector> 0013 0014 #include "corecel/math/Turn.hh" 0015 0016 #include "IntersectRegion.hh" 0017 #include "ObjectInterface.hh" 0018 0019 namespace celeritas 0020 { 0021 namespace orangeinp 0022 { 0023 //---------------------------------------------------------------------------// 0024 /*! 0025 * Define the azimuthal truncation of a solid. 0026 * 0027 * This is a pie slice infinite along the z axis and outward from it. Its cross 0028 * section is in the \em x-y plane, and a start 0029 * angle of zero corresponding to the \em +x axis. An interior angle of one 0030 * results in no radial exclusion from the resulting solid. A interior angle of 0031 * more than 0.5 turns (180 degrees) results in a wedge being subtracted from 0032 * the solid, and an angle of less than or equal to 0.5 turns results in the 0033 * intersection of the solid with a wedge. 0034 * 0035 * An instance of this class evaluates to \em true if truncation is to take 0036 * place, or \em false if the enclosed angle is a full circle. 0037 * 0038 * \par Examples: 0039 * \code 0040 // Truncates a solid to the east-facing quadrant: 0041 EnclosedAzi{Turn{-0.125}, Turn{0.125}}; 0042 // Removes the second quadrant (northwest) from a solid: 0043 EnclosedAzi{Turn{0.50}, Turn{1.25}}; 0044 \endcode 0045 */ 0046 class EnclosedAzi 0047 { 0048 public: 0049 //!@{ 0050 //! \name Type aliases 0051 using SenseWedge = std::pair<Sense, InfAziWedge>; 0052 //!@} 0053 0054 public: 0055 //! Default to "all angles" 0056 EnclosedAzi() = default; 0057 0058 // Construct from a starting angle and stop angle 0059 EnclosedAzi(Turn start, Turn stop); 0060 0061 // Construct a wedge shape to intersect (inside) or subtract (outside) 0062 SenseWedge make_sense_region() const; 0063 0064 // Whether the enclosed angle is not a full circle 0065 constexpr explicit inline operator bool() const; 0066 0067 //! Starting angle 0068 Turn start() const { return start_; } 0069 0070 //! stop angle 0071 Turn stop() const { return stop_; } 0072 0073 private: 0074 Turn start_{0}; 0075 Turn stop_{1}; 0076 }; 0077 0078 //---------------------------------------------------------------------------// 0079 /*! 0080 * Define the polar truncation of a solid. 0081 * 0082 * This subtracts up to two infinite cones centered along the z axis from the 0083 * origin. 0084 * 0085 * A start angle of zero corresponding to the \em +z axis. An interior angle of 0086 * 0.5 results in no exclusion from the resulting solid. 0087 * 0088 * \par Examples: 0089 * \code 0090 // Truncates a solid to the top hemisphere (no cones, just equatorial plane) 0091 EnclosedPolar{Turn{0}, Turn{0.25}}; 0092 // Truncates a solid to northern latitudes (intersect two cones and a plane) 0093 EnclosedPolar{Turn{0.15}, Turn{0.2}}; 0094 // Truncates a solid to an equatorial region (18 degrees N to 36 S: the union 0095 // of two polar wedge cones) 0096 EnclosedPolar{Turn{0.2}, Turn{0.35}}; 0097 \endcode 0098 */ 0099 class EnclosedPolar 0100 { 0101 public: 0102 //!@{ 0103 //! \name Type aliases 0104 using VecPolarWedge = std::vector<InfPolarWedge>; 0105 //!@} 0106 0107 public: 0108 //! Default to "all angles" 0109 EnclosedPolar() = default; 0110 0111 // Construct from a starting angle and stop angle 0112 EnclosedPolar(Turn start, Turn stop); 0113 0114 // Construct one or two wedges to union then intersect with the solid 0115 VecPolarWedge make_regions() const; 0116 0117 // Whether the enclosed angle is not a full circle 0118 constexpr explicit inline operator bool() const; 0119 0120 //! Starting angle 0121 Turn start() const { return start_; } 0122 0123 //! stop angle 0124 Turn stop() const { return stop_; } 0125 0126 private: 0127 Turn start_{0}; 0128 Turn stop_{0.5}; 0129 }; 0130 0131 //---------------------------------------------------------------------------// 0132 /*! 0133 * A hollow shape with an optional start and end angle. 0134 * 0135 * Solids are a shape with (optionally) the same \em kind of shape subtracted 0136 * from it, and (optionally) an azimuthal section removed from it. 0137 */ 0138 class SolidBase : public ObjectInterface 0139 { 0140 public: 0141 // Construct a volume from this object 0142 NodeId build(VolumeBuilder&) const final; 0143 0144 // Write the shape to JSON 0145 void output(JsonPimpl*) const final; 0146 0147 //! Interior intersect region interface for construction and access 0148 virtual IntersectRegionInterface const& interior() const = 0; 0149 0150 //! Optional excluded region 0151 virtual IntersectRegionInterface const* excluded() const = 0; 0152 0153 //! Optional azimuthal angular restriction 0154 virtual EnclosedAzi const& enclosed_azi() const = 0; 0155 0156 //! Optional polar angular restriction 0157 virtual EnclosedPolar const& enclosed_polar() const = 0; 0158 0159 ~SolidBase() override = default; 0160 0161 protected: 0162 //!@{ 0163 //! Allow construction and assignment only through daughter classes 0164 SolidBase() = default; 0165 CELER_DEFAULT_COPY_MOVE(SolidBase); 0166 //!@} 0167 }; 0168 0169 //---------------------------------------------------------------------------// 0170 /*! 0171 * A shape that has undergone an intersection or combination of intersections. 0172 * 0173 * This shape may be any combination of: 0174 * 0175 * 1. hollow (excluded interior), 0176 * 2. truncated azimuthally (see \c EnclosedAzi), or 0177 * 3. truncated in polar angle (see \c EnclosedPolar). 0178 * 0179 * \par Examples: 0180 * \code 0181 * using T = Turn; using EA = EnclosedAzi; using EP = EnclosedPolar; 0182 // A cone with a thickness of 0.1 0183 Solid s{"cone", Cone{{1, 2}, 10.0}, Cone{{0.9, 1.9}, 10.0}}; 0184 // A cylinder segment in z={-2.5, 2.5}, r={0.5, 0.75}, theta={-45, 45} deg 0185 Solid s{"cyl", Cylinder{0.75, 5.0}, Cylinder{0.5, 5.0}, EA{T{0}, T{0.25}}; 0186 // The east-facing quarter of a cone shape 0187 Solid s{"econe", Cone{{1, 2}, 10.0}, {}, EA{T{-0.125}, T{0.25}}; 0188 // The -x,-y,+z octant of a sphere 0189 Solid s{"oct", Sphere{10.0}, {}, EA{T{0.5}, T{0.75}}, EP{T{0.0}, T{0.25}}) 0190 * \endcode 0191 */ 0192 template<class T> 0193 class Solid final : public SolidBase 0194 { 0195 static_assert(std::is_base_of_v<IntersectRegionInterface, T>); 0196 0197 public: 0198 //!@{ 0199 //! \name Type aliases 0200 using OptionalRegion = std::optional<T>; 0201 //!@} 0202 0203 public: 0204 // Return a solid *or* shape given an optional interior or enclosed angle 0205 static SPConstObject or_shape(std::string&& label, 0206 T&& interior, 0207 OptionalRegion&& excluded = {}, 0208 EnclosedAzi&& enclosed = {}, 0209 EnclosedPolar&& polar = {}); 0210 0211 // Construct with everything 0212 Solid(std::string&& label, 0213 T&& interior, 0214 OptionalRegion&& excluded, 0215 EnclosedAzi&& enclosed, 0216 EnclosedPolar&& polar); 0217 0218 //! Get the user-provided label 0219 std::string_view label() const final { return label_; } 0220 0221 //! Interior intersect region interface for construction and access 0222 IntersectRegionInterface const& interior() const final 0223 { 0224 return interior_; 0225 } 0226 0227 // Optional excluded 0228 IntersectRegionInterface const* excluded() const final; 0229 0230 //! Optional azimuthal restriction 0231 EnclosedAzi const& enclosed_azi() const final { return azi_; } 0232 0233 //! Optional polar restriction 0234 EnclosedPolar const& enclosed_polar() const final { return polar_; } 0235 0236 private: 0237 std::string label_; 0238 T interior_; 0239 OptionalRegion exclusion_; 0240 EnclosedAzi azi_; 0241 EnclosedPolar polar_; 0242 }; 0243 0244 //---------------------------------------------------------------------------// 0245 // DEDUCTION GUIDES 0246 //---------------------------------------------------------------------------// 0247 0248 template<class T, class... Us> 0249 Solid(std::string&&, T&&, Us...) -> Solid<T>; 0250 0251 //---------------------------------------------------------------------------// 0252 // TYPE ALIASES 0253 //---------------------------------------------------------------------------// 0254 0255 using ConeSolid = Solid<Cone>; 0256 using CutCylinderSolid = Solid<CutCylinder>; 0257 using CylinderSolid = Solid<Cylinder>; 0258 using EllipsoidSolid = Solid<Ellipsoid>; 0259 using HyperboloidSolid = Solid<Hyperboloid>; 0260 using PrismSolid = Solid<Prism>; 0261 using SphereSolid = Solid<Sphere>; 0262 using TorusSolid = Solid<Torus>; 0263 0264 //---------------------------------------------------------------------------// 0265 // EXPLICIT INSTANTIATION 0266 //---------------------------------------------------------------------------// 0267 0268 extern template class Solid<Cone>; 0269 extern template class Solid<CutCylinder>; 0270 extern template class Solid<Cylinder>; 0271 extern template class Solid<Ellipsoid>; 0272 extern template class Solid<Hyperboloid>; 0273 extern template class Solid<Prism>; 0274 extern template class Solid<Sphere>; 0275 extern template class Solid<Torus>; 0276 0277 //---------------------------------------------------------------------------// 0278 // INLINE DEFINITIONS 0279 //---------------------------------------------------------------------------// 0280 /*! 0281 * Whether the enclosed angle is not a full circle. 0282 * 0283 * Note that the constructor does not allow a full circle, so only the default 0284 * constructor can set values of zero and 1. 0285 */ 0286 constexpr EnclosedAzi::operator bool() const 0287 { 0288 return !(start_ == Turn{0} && stop_ == Turn{1}); 0289 } 0290 0291 //---------------------------------------------------------------------------// 0292 /*! 0293 * Whether the enclosed angle is less than the whole polar range. 0294 */ 0295 constexpr EnclosedPolar::operator bool() const 0296 { 0297 return !(start_ == Turn{0} && stop_ == Turn{0.5}); 0298 } 0299 0300 //---------------------------------------------------------------------------// 0301 /*! 0302 * Access the optional excluded. 0303 */ 0304 template<class T> 0305 IntersectRegionInterface const* Solid<T>::excluded() const 0306 { 0307 return exclusion_ ? &(*exclusion_) : nullptr; 0308 } 0309 0310 //---------------------------------------------------------------------------// 0311 } // namespace orangeinp 0312 } // namespace celeritas
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|