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/StackedExtrudedPolygon.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "ObjectInterface.hh"
0010 
0011 #include "detail/VolumeBuilder.hh"
0012 
0013 namespace celeritas
0014 {
0015 namespace orangeinp
0016 {
0017 //---------------------------------------------------------------------------//
0018 /*! A convex/concave polygon extruded along a polyline, with scaling.
0019  *
0020  * The polygon must be specified in counterclockwise order. The polyline must
0021  * be strictly monotonically increasing in z. Scaling factors can be any
0022  * positive value. Scaling is assumed to occur with respect to the polygon's
0023  * original coordinate system.
0024  *
0025  * Construction is performed using a convex decomposition approach
0026  * \citep{tor-convexdecomp-1984, https://doi.org/10.1145/357346.357348}. The
0027  * convex hull of the polygon is first found, then extruded along the polyline
0028  * (with scaling) form a stack of ExtrudedPolygon shapes. Regions that
0029  * constitute the difference between the polygon and its convex hull are then
0030  * subtracted. Each of these regions is created recursively in the same
0031  * fashion, i.e. finding the convex hull and creating a stack.
0032  *
0033  * Because this method creates many regions, these are kept track of using
0034  * three indices for debugging purposes: level, stack, and segment. The level
0035  * index denotes the current recursion depth. The stack index denotes the
0036  * convex region which is extruded into a stack on a given level. The segment
0037  * index denotes the z segment within the stack. An example of these indices is
0038  * shown below. Consider the following polygon, extruded along a single-segment
0039  * polyline:
0040  * \verbatim
0041              __________
0042             |          |
0043          ___|          |
0044         |              |
0045         |              |
0046         |              |
0047         |            __|
0048         |           |
0049         |___________|
0050    \endverbatim
0051  * The convex hull of this polygon is used to create the first region:
0052  * \verbatim
0053              __________
0054            /           |
0055          /             |
0056         |   level 0    |
0057         |   stack 0    |
0058         |   segment 0  |
0059         |              |
0060         |             /
0061         |___________/
0062    \endverbatim
0063  * Recursing one level deeper, we create two additional regions:
0064  * \verbatim
0065 
0066              ...........
0067            /|  level 1, stack 0, segment 0
0068          /__|          .
0069         .              .
0070         .              .
0071         .              .
0072         .           ___.
0073         .          |  /  level 1, stack 1, segment 0
0074         ...........|/
0075    \endverbatim
0076  * and subtract their union from the first region.
0077  *
0078  * \internal When labeing nodes in the CSG output, the following shorthand
0079  *   format is used: `label@level.stack.segment`. For example, the final region
0080  *   in the example above might be named `my_shape@1.1.0`. For each level,
0081  *   additional nodes are created in the form: `label@level.suffix` where
0082  *   suffixes have the following meanings:
0083  *   1) .cu : the union of all concave regions on this level,
0084  *   2) .ncu : the negation of the union of all concave regions on this level,
0085  *   3) .d : the difference between this level's convex hull and the concave
0086  *      regions on this level.
0087  */
0088 class StackedExtrudedPolygon final : public ObjectInterface
0089 {
0090   public:
0091     //!@{
0092     //! \name Type aliases
0093     using SPConstObject = std::shared_ptr<ObjectInterface const>;
0094     using VecReal = std::vector<real_type>;
0095     using VecReal2 = std::vector<Real2>;
0096     using VecReal3 = std::vector<Real3>;
0097     //!@}
0098 
0099     //! Construct, or return an ExtrudedPolygon shape if possible
0100     static SPConstObject or_solid(std::string&& label,
0101                                   VecReal2&& polygon,
0102                                   VecReal3&& polyline,
0103                                   VecReal&& scaling);
0104 
0105     // Construct from a polygon, polyline, and scaling factors
0106     StackedExtrudedPolygon(std::string&& label,
0107                            VecReal2&& polygon,
0108                            VecReal3&& polyline,
0109                            VecReal&& scaling);
0110 
0111     //// INTERFACE ////
0112 
0113     //! Get the user-provided label
0114     std::string_view label() const final { return label_; }
0115 
0116     //! Construct a volume from this object
0117     NodeId build(VolumeBuilder&) const final;
0118 
0119     //! Write the shape to JSON
0120     void output(JsonPimpl*) const final;
0121 
0122     //// ACCESSORS ////
0123 
0124     //! Get the polygon
0125     VecReal2 const& polygon() const { return polygon_; };
0126 
0127     //! Get the polyline
0128     VecReal3 const& polyline() const { return polyline_; };
0129 
0130     //! Get the scaling factors
0131     VecReal const& scaling() const { return scaling_; };
0132 
0133   private:
0134     /// TYPES ///
0135 
0136     // Helper struct for keeping track of embedded regions
0137     struct SubRegionIndex
0138     {
0139         size_type level = 0;
0140         size_type stack = 0;
0141     };
0142 
0143     //// HELPER METHODS ////
0144 
0145     // Recursively construct stacks, subtracting out concavities
0146     NodeId make_levels(detail::VolumeBuilder& vb,
0147                        VecReal2 const& polygon,
0148                        SubRegionIndex si) const;
0149 
0150     // Extrude a *convex* polygon along the polyline
0151     NodeId make_stack(detail::VolumeBuilder& vb,
0152                       VecReal2 const& polygon,
0153                       SubRegionIndex si) const;
0154 
0155     // Make a label for a level
0156     std::string make_level_ext(SubRegionIndex si) const;
0157 
0158     // Make a label for a stack within a level
0159     std::string make_stack_ext(SubRegionIndex si) const;
0160 
0161     // Make a label for a segment within a stack
0162     std::string
0163     make_segment_ext(SubRegionIndex si, size_type segment_idx) const;
0164 
0165     //// DATA ////
0166 
0167     std::string label_;
0168     VecReal2 polygon_;
0169     VecReal3 polyline_;
0170     VecReal scaling_;
0171 };
0172 
0173 //---------------------------------------------------------------------------//
0174 }  // namespace orangeinp
0175 }  // namespace celeritas