Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-01-06 10:19:25

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/RevolvedPolygon.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "ObjectInterface.hh"
0010 #include "Solid.hh"
0011 
0012 #include "detail/VolumeBuilder.hh"
0013 
0014 namespace celeritas
0015 {
0016 namespace orangeinp
0017 {
0018 //---------------------------------------------------------------------------//
0019 /*! An azimuthally sliced arbitrary polygon revolved around the \em z axis.
0020  *
0021  * The polygon must be specified in counterclockwise order and may not be self
0022  * intersecting. The polygon cannot cross the \em z axis, i.e., all vertices
0023  * must satisfy \em r >= 0.
0024  *
0025  * Construction is performed using a convex differences tree approach
0026  * \citep{tor-convexdecomp-1984, https://doi.org/10.1145/357346.357348}. The
0027  * convex hull of the polygon is first found and revolved around the \em z
0028  * axis. Regions that constitute the difference between the convex hull and the
0029  * original polygon are then subtracted. Each of these regions is created
0030  * recursively in the same fashion. The recursion depth is referred to as the
0031  * "level" and each contiguous region within a level is a "region", as shown
0032  * below:
0033  * \verbatim
0034    original polygon         convex hull          difference
0035      |___     ____         |____________       |   ______
0036    ^ |   \    |  |         |           |       |   \    |  level 1
0037    | |     \  |  |         |           |       |     \  |  region 0
0038    z |       \|  |         | level 0   |       |       \|
0039      |           |    =    | region 0  |   -   |
0040    a |           |         |           |       |
0041    x |    /\     |         |           |       |     /\     level 1
0042    i |___/  \____|         |___________|       |    /__\    region 1
0043    s |_____________        |_____________      |_____________
0044       r axis ->
0045    \endverbatim
0046  * Convex "regions" are constructed from "subregions", as shown below:
0047  * \verbatim
0048      |   ______             |________                     |___
0049    ^ |   \    |  level 1    |        | level 1            |   \     level 1
0050    | |     \  |  region 0   |        | region 0           |     \   region 0
0051    z |       \|             |________| subregion 0        |_______\ subregion 1
0052      |                 =    |          (a cylinder)  -    |         (a cone)
0053    a |                      |                             |
0054    x |                      |                             |
0055    i |                      |                             |
0056    s |_____________         |_____________                |_____________
0057         r axis ->
0058    \endverbatim
0059  * In this example, level 1 region 0 is formed from only two subregions, but
0060  * the general case is handled via:
0061  *
0062  * region = union(outer subregions) - union(inner subregions).
0063  *
0064  * The final step in construction is azimuthal truncation, which is done
0065  * through a union operation with a negated or non-negated EnclosedAzi.
0066  *
0067  * \internal When labeling nodes in the CSG output, the following shorthand
0068  * format is used: `label@level.region.subregion`. For example, the final
0069  * subregion in the example above might be named `my_shape@1.0.1`. For each
0070  * level, additional nodes are created in the form: `label@level.suffix` where
0071  * suffixes have the following meanings:
0072  *
0073  *  1) .cu : the union of all concave regions on the level,
0074  *  2) .ncu : the negation of .cu,
0075  *  3) .d : the difference between the level's convex hull and .cu.
0076  *
0077  * For each region, additional nodes are created in the form
0078  * label@level.region.suffix where suffixes have the following meanings:
0079  *
0080  * 1) .ou : the union of nodes that comprise the outer boundary of the region,
0081  * 2) .iu : the union of nodes that comprise the inner boundary of the region,
0082  * 3) .nui : the negation of .ui,
0083  * 4) .d : the difference between .ou and .iu.
0084  *
0085  * If the supplied EnclosedAzi object is not [0, 2pi], additional nodes with
0086  * the following extensions are added:
0087  *
0088  * 1) azi/~azi : the enclosed, possibly negated, azimuthal angle,
0089  * 2) restricted : the intersection of the revolved polygon and azi/~azi.
0090  */
0091 class RevolvedPolygon final : public ObjectInterface
0092 {
0093   public:
0094     //!@{
0095     //! \name Type aliases
0096     using SPConstObject = std::shared_ptr<ObjectInterface const>;
0097     using VecReal2 = std::vector<Real2>;
0098     //!@}
0099 
0100     // Construct from a polygon
0101     RevolvedPolygon(std::string&& label,
0102                     VecReal2&& polygon,
0103                     EnclosedAzi&& enclosed);
0104 
0105     //// INTERFACE ////
0106 
0107     //! Get the user-provided label
0108     std::string_view label() const final { return label_; }
0109 
0110     //! Construct a volume from this object
0111     NodeId build(VolumeBuilder&) const final;
0112 
0113     //! Write the shape to JSON
0114     void output(JsonPimpl*) const final;
0115 
0116     //// ACCESSORS ////
0117 
0118     //! Get the polygon
0119     VecReal2 const& polygon() const { return polygon_; };
0120 
0121     //! Get the azimuthal angular restriction
0122     EnclosedAzi const& enclosed_azi() const { return enclosed_; }
0123 
0124   private:
0125     /// TYPES ///
0126 
0127     // Helper struct for keeping track of levels/regions/subregions
0128     struct SubIndex
0129     {
0130         size_type level = 0;
0131         size_type region = 0;
0132         size_type subregion = 0;
0133     };
0134 
0135     //// HELPER METHODS ////
0136 
0137     // Recursively construct convex regions, subtracting out concavities
0138     NodeId make_levels(detail::VolumeBuilder& vb,
0139                        VecReal2 const& polygon,
0140                        SubIndex si) const;
0141 
0142     // Revolve a convex polygon around the \em z axis
0143     NodeId make_region(detail::VolumeBuilder& vb,
0144                        VecReal2 const& polygon,
0145                        SubIndex si) const;
0146 
0147     // Make a translated cylinder node
0148     NodeId make_cylinder(detail::VolumeBuilder& vb,
0149                          Real2 const& p0,
0150                          Real2 const& p1,
0151                          SubIndex const& si) const;
0152 
0153     // Make a translated cone node
0154     NodeId make_cone(detail::VolumeBuilder& vb,
0155                      Real2 const& p0,
0156                      Real2 const& p1,
0157                      SubIndex const& si) const;
0158 
0159     // Make a label extension for a level
0160     std::string make_level_ext(SubIndex si) const;
0161 
0162     // Make a label extension for a region within a level
0163     std::string make_region_ext(SubIndex si) const;
0164 
0165     // Make a label extension for a subregion within a region
0166     std::string make_subregion_ext(SubIndex si) const;
0167 
0168     //// DATA ////
0169 
0170     std::string label_;
0171     VecReal2 polygon_;
0172     EnclosedAzi enclosed_;
0173 };
0174 
0175 //---------------------------------------------------------------------------//
0176 }  // namespace orangeinp
0177 }  // namespace celeritas