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