Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:05:55

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/detail/PolygonUtils.hh
0007 //! \brief Utility standalone functions for polygons in 2D or 3D space.
0008 //---------------------------------------------------------------------------//
0009 #pragma once
0010 
0011 #include <iostream>
0012 #include <vector>
0013 
0014 #include "corecel/cont/Array.hh"
0015 #include "corecel/cont/Range.hh"
0016 #include "corecel/cont/Span.hh"
0017 #include "corecel/math/ArrayOperators.hh"
0018 #include "corecel/math/ArrayUtils.hh"
0019 #include "orange/OrangeTypes.hh"
0020 
0021 namespace celeritas
0022 {
0023 namespace orangeinp
0024 {
0025 namespace detail
0026 {
0027 //---------------------------------------------------------------------------//
0028 /*!
0029  *  Polygon orientation based on ordering of vertices.
0030  */
0031 enum class Orientation
0032 {
0033     clockwise = -1,
0034     collinear = 0,
0035     counterclockwise = 1,
0036 };
0037 
0038 //---------------------------------------------------------------------------//
0039 // FREE FUNCTIONS
0040 //---------------------------------------------------------------------------//
0041 /*!
0042  * Find orientation of ordered vertices in 2D coordinates.
0043  */
0044 inline Orientation
0045 calc_orientation(Real2 const& a, Real2 const& b, Real2 const& c)
0046 {
0047     auto crossp = (b[0] - a[0]) * (c[1] - b[1]) - (b[1] - a[1]) * (c[0] - b[0]);
0048     return crossp < 0   ? Orientation::clockwise
0049            : crossp > 0 ? Orientation::counterclockwise
0050                         : Orientation::collinear;
0051 }
0052 
0053 //---------------------------------------------------------------------------//
0054 /*!
0055  * Test whether a 2D polygon has the given orientation.
0056  *
0057  * The list of input corners must have at least 3 points to be a polygon.
0058  */
0059 inline bool has_orientation(Span<Real2 const> corners, Orientation o)
0060 {
0061     CELER_EXPECT(corners.size() > 2);
0062     for (auto i : range(corners.size()))
0063     {
0064         auto j = (i + 1) % corners.size();
0065         auto k = (i + 2) % corners.size();
0066         if (calc_orientation(corners[i], corners[j], corners[k]) != o)
0067             return false;
0068     }
0069     return true;
0070 }
0071 
0072 //---------------------------------------------------------------------------//
0073 /*!
0074  * Whether the orientation is the same or degenerate if allowed.
0075  */
0076 inline bool
0077 is_same_orientation(Orientation a, Orientation b, bool degen_ok = false)
0078 {
0079     if (a == Orientation::collinear || b == Orientation::collinear)
0080     {
0081         return degen_ok;
0082     }
0083     return (a == b);
0084 }
0085 
0086 //---------------------------------------------------------------------------//
0087 /*!
0088  * Check if a 2D polygon is convex.
0089  *
0090  * \param corners the vertices of the polygon
0091  * \param degen_ok allow consecutive collinear points
0092  */
0093 inline bool is_convex(Span<Real2 const> corners, bool degen_ok = false)
0094 {
0095     CELER_EXPECT(corners.size() > 2);
0096     auto ref = Orientation::collinear;
0097     for (auto i : range<size_type>(corners.size()))
0098     {
0099         auto j = (i + 1) % corners.size();
0100         auto k = (i + 2) % corners.size();
0101         auto cur = calc_orientation(corners[i], corners[j], corners[k]);
0102         if (ref == Orientation::collinear)
0103         {
0104             // First non-collinear point
0105             ref = cur;
0106         }
0107         if (!is_same_orientation(cur, ref, degen_ok))
0108         {
0109             // Prohibited collinear orientation, or different orientation from
0110             // reference
0111             return false;
0112         }
0113     }
0114     return true;
0115 }
0116 
0117 //---------------------------------------------------------------------------//
0118 }  // namespace detail
0119 }  // namespace orangeinp
0120 }  // namespace celeritas