![]() |
|
|||
File indexing completed on 2025-02-22 10:47:12
0001 //----------------------------------*-C++-*----------------------------------// 0002 // Copyright 2023-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/surf/detail/QuadricCylConverter.hh 0007 //---------------------------------------------------------------------------// 0008 #pragma once 0009 0010 #include <optional> 0011 0012 #include "corecel/math/SoftEqual.hh" 0013 0014 #include "../CylAligned.hh" 0015 #include "../SimpleQuadric.hh" 0016 0017 namespace celeritas 0018 { 0019 namespace detail 0020 { 0021 //---------------------------------------------------------------------------// 0022 /*! 0023 * Try to convert a simple quadric to a cylinder. 0024 * 0025 * The simple quadric must have already undergone normalization (one 0026 * second-order term approximately zero, the others positive). 0027 */ 0028 class QuadricCylConverter 0029 { 0030 public: 0031 // Construct with tolerance 0032 inline QuadricCylConverter(real_type tol); 0033 0034 // Try converting to a cylinder with this orientation 0035 template<Axis T> 0036 std::optional<CylAligned<T>> 0037 operator()(AxisTag<T>, SimpleQuadric const& sq) const; 0038 0039 private: 0040 SoftEqual<> soft_equal_; 0041 }; 0042 0043 //---------------------------------------------------------------------------// 0044 // INLINE DEFINITIONS 0045 //---------------------------------------------------------------------------// 0046 /*! 0047 * Construct with tolerance. 0048 */ 0049 QuadricCylConverter::QuadricCylConverter(real_type tol) : soft_equal_{tol} {} 0050 0051 //---------------------------------------------------------------------------// 0052 /*! 0053 * Try converting to a cylinder with this orientation. 0054 * 0055 * Cone: 0056 * \verbatim 0057 (x - x_0)^2 + (y - y_0)^2 - r^2 = 0 0058 * \endverbatim 0059 * Expanded: 0060 * \verbatim 0061 x^2 + y^2 0062 - 2x_0 x - 2y_0 y 0063 + (x_0^2 + y_0^2 - r^2) = 0 0064 * \endverbatim 0065 * SQ: 0066 * \verbatim 0067 a x^2 + (a + \epsilon) y^2 + e x + f y + h = 0 0068 * \endverbatim 0069 * Normalized (\c epsilon = 0) 0070 * \verbatim 0071 x^2 + y^2 + e/b x + f/b y + g/b z + h/b = 0 0072 * \endverbatim 0073 * Match terms: 0074 * \verbatim 0075 -2 x_0 = e/b --> x_0 = e / (-2 * b) 0076 -2 y_0 = f/b --> y_0 = f / (-2 * b) 0077 (x_0^2 + y_0^2 - r^2) = h/b 0078 -> r^2 = x_0^2 + y_0^2 - h/b 0079 * \endverbatim 0080 */ 0081 template<Axis T> 0082 std::optional<CylAligned<T>> 0083 QuadricCylConverter::operator()(AxisTag<T>, SimpleQuadric const& sq) const 0084 { 0085 // Other coordinate system 0086 constexpr auto U = CylAligned<T>::u_axis(); 0087 constexpr auto V = CylAligned<T>::v_axis(); 0088 0089 auto second = sq.second(); 0090 if (!soft_equal_(0, second[to_int(T)])) 0091 { 0092 // Not the zero component we're looking for 0093 return {}; 0094 } 0095 if (!soft_equal_(0, sq.first()[to_int(T)])) 0096 { 0097 // Not an axis-aligned cylinder 0098 return {}; 0099 } 0100 if (!soft_equal_(second[to_int(U)], second[to_int(V)])) 0101 { 0102 // Not a *circular* cylinder 0103 return {}; 0104 } 0105 CELER_ASSERT(second[to_int(U)] > 0 && second[to_int(V)] > 0); 0106 0107 // Normalize so U, V second-order coefficients are 1 0108 auto const inv_norm = 2 / (second[to_int(U)] + second[to_int(V)]); 0109 0110 // Calculate origin from first-order coefficients 0111 Real3 origin{0, 0, 0}; 0112 origin[to_int(U)] = real_type{-0.5} * inv_norm * sq.first()[to_int(U)]; 0113 origin[to_int(V)] = real_type{-0.5} * inv_norm * sq.first()[to_int(V)]; 0114 0115 real_type radius_sq = ipow<2>(origin[to_int(U)]) 0116 + ipow<2>(origin[to_int(V)]) - sq.zeroth() * inv_norm; 0117 0118 if (radius_sq <= 0) 0119 { 0120 // No real solution 0121 return {}; 0122 } 0123 0124 // Clear potential signed zeros before returning 0125 origin += real_type{0}; 0126 return CylAligned<T>::from_radius_sq(origin, radius_sq); 0127 } 0128 0129 //---------------------------------------------------------------------------// 0130 } // namespace detail 0131 } // 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 |
![]() ![]() |