|
||||
File indexing completed on 2025-01-18 10:05:56
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/IntersectRegion.hh 0007 //! \brief Contains IntersectRegionInterface and concrete daughters 0008 //---------------------------------------------------------------------------// 0009 #pragma once 0010 0011 #include "corecel/Macros.hh" 0012 #include "corecel/cont/Array.hh" 0013 #include "corecel/math/Turn.hh" 0014 #include "orange/OrangeTypes.hh" 0015 0016 namespace celeritas 0017 { 0018 struct JsonPimpl; 0019 0020 namespace orangeinp 0021 { 0022 class IntersectSurfaceBuilder; 0023 0024 //---------------------------------------------------------------------------// 0025 /*! 0026 * Interface class for building non-reentrant spatial regions. 0027 * 0028 * This is a building block for constructing more complex objects out of 0029 * smaller spatial regions. A \c shape object will have a single intersect 0030 * region, and a \c solid object region may have multiple adjacent intersect 0031 * regions. 0032 * 0033 * Convex regions should be as minimal as possible and rely on transformations 0034 * to change axes, displacement, etc. As a general rule, the exterior bounding 0035 * box of a intersect region should be <em>centered on the origin</em>, and 0036 * objects should be aligned along the \em z axis. 0037 * 0038 * When implementing this class, prefer to build simpler surfaces (planes) 0039 * before complex ones (cones) in case we implement short-circuiting logic, 0040 * since expressions are currently sorted. 0041 * 0042 * \note Additional methods such as volume calculation may be added here later. 0043 */ 0044 class IntersectRegionInterface 0045 { 0046 public: 0047 //! Construct surfaces that are AND-ed into this region 0048 virtual void build(IntersectSurfaceBuilder&) const = 0; 0049 0050 //! Write the region to a JSON object 0051 virtual void output(JsonPimpl*) const = 0; 0052 0053 protected: 0054 //!@{ 0055 //! Allow construction and assignment only through daughter classes 0056 IntersectRegionInterface() = default; 0057 virtual ~IntersectRegionInterface() = default; 0058 CELER_DEFAULT_COPY_MOVE(IntersectRegionInterface); 0059 //!@} 0060 }; 0061 0062 //---------------------------------------------------------------------------// 0063 /*! 0064 * A rectangular parallelepiped/cuboid centered on the origin. 0065 */ 0066 class Box final : public IntersectRegionInterface 0067 { 0068 public: 0069 // Construct with half-widths 0070 explicit Box(Real3 const& halfwidths); 0071 0072 // Build surfaces 0073 void build(IntersectSurfaceBuilder&) const final; 0074 0075 // Output to JSON 0076 void output(JsonPimpl*) const final; 0077 0078 //// ACCESSORS //// 0079 0080 //! Half-width for each axis 0081 Real3 const& halfwidths() const { return hw_; } 0082 0083 private: 0084 Real3 hw_; 0085 }; 0086 0087 //---------------------------------------------------------------------------// 0088 /*! 0089 * A closed cone along the Z axis centered on the origin. 0090 * 0091 * A quadric cone technically defines two opposing cones that touch at a single 0092 * vanishing point, but this cone is required to be truncated so that the 0093 * vanishing point is on our outside the cone. 0094 * 0095 * The midpoint along the Z axis of the cone is the origin. A cone is \em not 0096 * allowed to have equal radii: for that, use a cylinder. However, it \em may 0097 * have a single radius of zero, which puts the vanishing point on one end of 0098 * the cone. 0099 * 0100 * This intersect region, along with the Cylinder, is a base component of the 0101 * G4Polycone (PCON). 0102 */ 0103 class Cone final : public IntersectRegionInterface 0104 { 0105 public: 0106 // Construct with Z half-height and lo, hi radii 0107 Cone(Real2 const& radii, real_type halfheight); 0108 0109 //// INTERFACE //// 0110 0111 // Build surfaces 0112 void build(IntersectSurfaceBuilder&) const final; 0113 0114 // Output to JSON 0115 void output(JsonPimpl*) const final; 0116 0117 //// TEMPLATE INTERFACE //// 0118 0119 // Whether this encloses another cone 0120 bool encloses(Cone const& other) const; 0121 0122 //// ACCESSORS //// 0123 0124 //! Lower and upper radii 0125 Real2 const& radii() const { return radii_; } 0126 0127 //! Half-height along Z 0128 real_type halfheight() const { return hh_; } 0129 0130 private: 0131 Real2 radii_; 0132 real_type hh_; 0133 }; 0134 0135 //---------------------------------------------------------------------------// 0136 /*! 0137 * A Z-aligned cylinder centered on the origin. 0138 */ 0139 class Cylinder final : public IntersectRegionInterface 0140 { 0141 public: 0142 // Construct with radius 0143 Cylinder(real_type radius, real_type halfheight); 0144 0145 // Build surfaces 0146 void build(IntersectSurfaceBuilder&) const final; 0147 0148 // Output to JSON 0149 void output(JsonPimpl*) const final; 0150 0151 //// TEMPLATE INTERFACE //// 0152 0153 // Whether this encloses another cylinder 0154 bool encloses(Cylinder const& other) const; 0155 0156 //// ACCESSORS //// 0157 0158 //! Radius 0159 real_type radius() const { return radius_; } 0160 0161 //! Half-height along Z 0162 real_type halfheight() const { return hh_; } 0163 0164 private: 0165 real_type radius_; 0166 real_type hh_; 0167 }; 0168 0169 //---------------------------------------------------------------------------// 0170 /*! 0171 * An axis-alligned ellipsoid centered at the origin. 0172 */ 0173 class Ellipsoid final : public IntersectRegionInterface 0174 { 0175 public: 0176 // Construct with radius 0177 explicit Ellipsoid(Real3 const& radii); 0178 0179 // Build surfaces 0180 void build(IntersectSurfaceBuilder&) const final; 0181 0182 // Output to JSON 0183 void output(JsonPimpl*) const final; 0184 0185 //// ACCESSORS //// 0186 0187 //! Radius along each axis 0188 Real3 const& radii() const { return radii_; } 0189 0190 private: 0191 Real3 radii_; 0192 }; 0193 0194 //---------------------------------------------------------------------------// 0195 /*! 0196 * A generalized polygon with parallel flat faces along the z axis. 0197 * 0198 * A GenPrism, like VecGeom's GenTrap, ROOT's Arb8, and Geant4's 0199 * G4GenericTrap, represents a generalized volume with polyhedral faces on two 0200 * parallel planes perpendicular to the Z axis. Unlike those other codes, the 0201 * number of faces can be arbitrary in number. 0202 * 0203 * The faces have an orientation and ordering so that \em twisted faces can be 0204 * constructed by joining corresponding points using straight-line "vertical" 0205 * edges, directly matching the G4GenericTrap definition, but using a generic 0206 * quadric expression for each twisted face. 0207 * 0208 * Trapezoids constructed from the helper functions will have sides that are 0209 * same ordering as a prism: the rightward face is first (normal is along the 0210 * +x axis), then the others follow counterclockwise. 0211 */ 0212 class GenPrism final : public IntersectRegionInterface 0213 { 0214 public: 0215 //!@{ 0216 //! \name Type aliases 0217 using VecReal2 = std::vector<Real2>; 0218 //!@} 0219 0220 //! Regular trapezoidal top/bottom face 0221 struct TrapFace 0222 { 0223 //! Half the vertical distance between horizontal edges 0224 real_type hy{}; 0225 //! Top horizontal edge half-length 0226 real_type hx_lo{}; 0227 //! Bottom horizontal edge half-length 0228 real_type hx_hi{}; 0229 //! Shear angle, between horizontal line centers and Y axis 0230 Turn alpha; 0231 }; 0232 0233 public: 0234 // Helper function to construct a Trd shape from hz and two rectangles, 0235 // one for each z-face 0236 static GenPrism from_trd(real_type halfz, Real2 const& lo, Real2 const& hi); 0237 0238 // Helper function to construct a general trap from its half-height and 0239 // the two trapezoids defining its lower and upper faces 0240 static GenPrism from_trap(real_type hz, 0241 Turn theta, 0242 Turn phi, 0243 TrapFace const& lo, 0244 TrapFace const& hi); 0245 0246 // Construct from half Z height and 4 vertices for top and bottom planes 0247 GenPrism(real_type halfz, VecReal2 const& lo, VecReal2 const& hi); 0248 0249 // Build surfaces 0250 void build(IntersectSurfaceBuilder&) const final; 0251 0252 // Output to JSON 0253 void output(JsonPimpl*) const final; 0254 0255 //// ACCESSORS //// 0256 0257 //! Half-height along Z 0258 real_type halfheight() const { return hz_; } 0259 0260 //! Polygon on -z face 0261 VecReal2 const& lower() const { return lo_; } 0262 0263 //! Polygon on +z face 0264 VecReal2 const& upper() const { return hi_; } 0265 0266 //! Number of sides (points on the Z face) 0267 size_type num_sides() const { return lo_.size(); } 0268 0269 // Calculate the cosine of the twist angle for a given side 0270 real_type calc_twist_cosine(size_type size_idx) const; 0271 0272 private: 0273 enum class Degenerate 0274 { 0275 none, 0276 lo, 0277 hi 0278 }; 0279 0280 real_type hz_; //!< half-height 0281 VecReal2 lo_; //!< corners of the -z face 0282 VecReal2 hi_; //!< corners of the +z face 0283 Degenerate degen_{Degenerate::none}; //!< no plane on this z axis 0284 }; 0285 0286 //---------------------------------------------------------------------------// 0287 /*! 0288 * An open wedge shape from the Z axis. 0289 * 0290 * The wedge is defined by an interior angle that *must* be less than or equal 0291 * to 180 degrees (half a turn) and *must* be more than zero. It can be 0292 * subtracted, or its negation can be subtracted. The start angle is mapped 0293 * onto [0, 1) on construction. 0294 */ 0295 class InfWedge final : public IntersectRegionInterface 0296 { 0297 public: 0298 // Construct from a starting angle and interior angle 0299 InfWedge(Turn start, Turn interior); 0300 0301 // Build surfaces 0302 void build(IntersectSurfaceBuilder&) const final; 0303 0304 // Output to JSON 0305 void output(JsonPimpl*) const final; 0306 0307 //// ACCESSORS //// 0308 0309 //! Starting angle 0310 Turn start() const { return start_; } 0311 0312 //! Interior angle 0313 Turn interior() const { return interior_; } 0314 0315 private: 0316 Turn start_; 0317 Turn interior_; 0318 }; 0319 0320 //---------------------------------------------------------------------------// 0321 /*! 0322 * An involute "blade" centered on the origin. 0323 * 0324 * This is the intersection of two parallel involutes with a cylindrical shell. 0325 * The three radii, which must be in ascending order, are that of the involute, 0326 * the inner cylinder, and the outer cylinder. 0327 * 0328 * The "chirality" of the involute is viewed from the \em +z axis looking down: 0329 * whether it spirals to the right or left. 0330 */ 0331 class Involute final : public IntersectRegionInterface 0332 { 0333 public: 0334 // Construct with radius 0335 explicit Involute(Real3 const& radii, 0336 Real2 const& displacement, 0337 Chirality chirality, 0338 real_type halfheight); 0339 0340 // Build surfaces 0341 void build(IntersectSurfaceBuilder&) const final; 0342 0343 // Output to JSON 0344 void output(JsonPimpl*) const final; 0345 0346 //// ACCESSORS //// 0347 0348 //! Radii: Rdius of involute, minimum radius, maximum radius 0349 Real3 const& radii() const { return radii_; } 0350 //! Displacement angle 0351 Real2 const& displacement_angle() const { return a_; } 0352 //! Angular bounds of involute 0353 Real2 const& t_bounds() const { return t_bounds_; } 0354 //! Chirality of involute: turning left or right 0355 Chirality chirality() const { return sign_; } 0356 //! Halfheight 0357 real_type halfheight() const { return hh_; } 0358 0359 private: 0360 Real3 radii_; 0361 Real2 a_; 0362 Real2 t_bounds_; 0363 Chirality sign_; 0364 real_type hh_; 0365 }; 0366 0367 //---------------------------------------------------------------------------// 0368 /*! 0369 * A general parallelepiped centered on the origin. 0370 * 0371 * A parallelepiped is a shape having 3 pairs of parallel faces out of 0372 * which one is parallel with the XY plane (Z faces). All faces are 0373 * parallelograms in the general case. The Z faces have 2 edges parallel 0374 * with the X-axis. Note that all angle parameters are expressed in terms 0375 * of fractions of a 360deg turn. 0376 * 0377 * The shape has the center in the origin and it is defined by: 0378 * 0379 * - `halfedges:` a 3-vector (dY, dY, dZ) with half-lengths of the 0380 * projections of the edges on X, Y, Z. The lower Z face is positioned at 0381 * `-dZ`, and the upper one at `+dZ`. 0382 * - `alpha:` angle between the segment defined by the centers of the 0383 * X-parallel edges and Y axis. Validity range is `(-1/4, 1/4)`; 0384 * - `theta:` polar angle of the shape's main axis, e.g. the segment defined 0385 * by the centers of the Z faces. Validity range is `[0, 1/4)`; 0386 * - `phi:` azimuthal angle of the shape's main axis (as explained above). 0387 * Validity range is `[0, 1)`. 0388 */ 0389 class Parallelepiped final : public IntersectRegionInterface 0390 { 0391 public: 0392 // Construct with half widths and 3 angles 0393 Parallelepiped(Real3 const& halfedges, Turn alpha, Turn theta, Turn phi); 0394 0395 // Build surfaces 0396 void build(IntersectSurfaceBuilder&) const final; 0397 0398 // Output to JSON 0399 void output(JsonPimpl*) const final; 0400 0401 //// ACCESSORS //// 0402 0403 //! Half-lengths of edge projections along each axis 0404 Real3 const& halfedges() const { return hpr_; } 0405 //! Angle between slanted y-edges and the y-axis (in turns) 0406 Turn alpha() const { return alpha_; } 0407 //! Polar angle of main axis (in turns) 0408 Turn theta() const { return theta_; } 0409 //! Azimuthal angle of main axis (in turns) 0410 Turn phi() const { return phi_; } 0411 0412 private: 0413 // half-lengths 0414 Real3 hpr_; 0415 // angle between slanted y-edges and the y-axis 0416 Turn alpha_; 0417 // polar angle of main axis 0418 Turn theta_; 0419 // azimuthal angle of main axis 0420 Turn phi_; 0421 }; 0422 0423 //---------------------------------------------------------------------------// 0424 /*! 0425 * A regular, z-extruded polygon centered on the origin. 0426 * 0427 * This is the base component of a G4Polyhedra (PGON). The default rotation is 0428 * to put a y-aligned plane on the bottom of the shape, so looking at an x-y 0429 * slice given an apothem \em a, every shape has a surface at \f$ y = -a \f$: 0430 * - n=3 is a triangle with a flat bottom, point up 0431 * - n=4 is a square with axis-aligned sides 0432 * - n=6 is a flat-top hexagon 0433 * 0434 * The "orientation" parameter is a scaled counterclockwise rotation on 0435 * \f$[0, 1)\f$, where zero preserves the orientation described above, and 0436 * unity replicates the original shape but with the "p0" face being where the 0437 * "p1" originally was. With a value of 0.5: 0438 * - n=3 is a downward-pointing triangle 0439 * - n=4 is a diamond 0440 * - n=6 is a pointy-top hexagon 0441 */ 0442 class Prism final : public IntersectRegionInterface 0443 { 0444 public: 0445 // Construct with inner radius (apothem), half height, and orientation 0446 Prism(int num_sides, 0447 real_type apothem, 0448 real_type halfheight, 0449 real_type orientation); 0450 0451 // Build surfaces 0452 void build(IntersectSurfaceBuilder&) const final; 0453 0454 // Output to JSON 0455 void output(JsonPimpl*) const final; 0456 0457 //// TEMPLATE INTERFACE //// 0458 0459 // Whether this encloses another cylinder 0460 bool encloses(Prism const& other) const; 0461 0462 //// ACCESSORS //// 0463 0464 //! Number of sides 0465 int num_sides() const { return num_sides_; } 0466 //! Inner radius 0467 real_type apothem() const { return apothem_; } 0468 //! Half the Z height 0469 real_type halfheight() const { return hh_; } 0470 //! Rotation factor 0471 real_type orientation() const { return orientation_; } 0472 0473 private: 0474 // Number of sides 0475 int num_sides_; 0476 0477 // Distance from center to midpoint of its side 0478 real_type apothem_; 0479 0480 // Half the z height 0481 real_type hh_; 0482 0483 // Rotational offset (0 has bottom face at -Y, 1 is congruent) 0484 real_type orientation_; 0485 }; 0486 0487 //---------------------------------------------------------------------------// 0488 /*! 0489 * A sphere centered on the origin. 0490 * 0491 * \note Be aware there's also a sphere *surface* at orange/surf/Sphere.hh in a 0492 * different namespace. 0493 */ 0494 class Sphere final : public IntersectRegionInterface 0495 { 0496 public: 0497 // Construct with radius 0498 explicit Sphere(real_type radius); 0499 0500 // Build surfaces 0501 void build(IntersectSurfaceBuilder&) const final; 0502 0503 // Output to JSON 0504 void output(JsonPimpl*) const final; 0505 0506 //// TEMPLATE INTERFACE //// 0507 0508 // Whether this encloses another sphere 0509 bool encloses(Sphere const& other) const; 0510 0511 //// ACCESSORS //// 0512 0513 //! Radius 0514 real_type radius() const { return radius_; } 0515 0516 private: 0517 real_type radius_; 0518 }; 0519 0520 //---------------------------------------------------------------------------// 0521 } // namespace orangeinp 0522 } // 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 |