File indexing completed on 2025-01-30 10:17:12
0001
0002
0003
0004
0005
0006
0007
0008 #pragma once
0009
0010 #include "corecel/Types.hh"
0011 #include "corecel/cont/Array.hh"
0012 #include "corecel/cont/Span.hh"
0013 #include "corecel/math/ArrayUtils.hh"
0014 #include "orange/OrangeTypes.hh"
0015
0016 #include "detail/QuadraticSolver.hh"
0017
0018 namespace celeritas
0019 {
0020
0021 template<Axis T>
0022 class ConeAligned;
0023 template<Axis T>
0024 class CylAligned;
0025 class Plane;
0026 class Sphere;
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 class SimpleQuadric
0041 {
0042 public:
0043
0044
0045 using Intersections = Array<real_type, 2>;
0046 using StorageSpan = Span<real_type const, 7>;
0047 using SpanConstReal3 = Span<real_type const, 3>;
0048
0049
0050
0051
0052
0053 static CELER_CONSTEXPR_FUNCTION SurfaceType surface_type()
0054 {
0055 return SurfaceType::sq;
0056 }
0057
0058
0059 static CELER_CONSTEXPR_FUNCTION bool simple_safety() { return false; }
0060
0061 public:
0062
0063
0064
0065 SimpleQuadric(Real3 const& abc, Real3 const& def, real_type g);
0066
0067
0068 template<class R>
0069 explicit inline CELER_FUNCTION SimpleQuadric(Span<R, StorageSpan::extent>);
0070
0071
0072 explicit SimpleQuadric(Plane const& other) noexcept;
0073
0074
0075 template<Axis T>
0076 explicit SimpleQuadric(CylAligned<T> const& other) noexcept;
0077
0078
0079 explicit SimpleQuadric(Sphere const& other) noexcept;
0080
0081
0082 template<Axis T>
0083 explicit SimpleQuadric(ConeAligned<T> const& other) noexcept;
0084
0085
0086
0087
0088 CELER_FUNCTION SpanConstReal3 second() const { return {&a_, 3}; }
0089
0090
0091 CELER_FUNCTION SpanConstReal3 first() const { return {&d_, 3}; }
0092
0093
0094 CELER_FUNCTION real_type zeroth() const { return g_; }
0095
0096
0097 CELER_FUNCTION StorageSpan data() const { return {&a_, 7}; }
0098
0099
0100
0101
0102 inline CELER_FUNCTION SignedSense calc_sense(Real3 const& pos) const;
0103
0104
0105 inline CELER_FUNCTION Intersections calc_intersections(
0106 Real3 const& pos, Real3 const& dir, SurfaceState on_surface) const;
0107
0108
0109 inline CELER_FUNCTION Real3 calc_normal(Real3 const& pos) const;
0110
0111 private:
0112
0113 real_type a_, b_, c_;
0114
0115 real_type d_, e_, f_;
0116
0117 real_type g_;
0118 };
0119
0120
0121
0122
0123
0124
0125
0126 template<class R>
0127 CELER_FUNCTION SimpleQuadric::SimpleQuadric(Span<R, StorageSpan::extent> data)
0128 : a_{data[0]}
0129 , b_{data[1]}
0130 , c_{data[2]}
0131 , d_{data[3]}
0132 , e_{data[4]}
0133 , f_{data[5]}
0134 , g_{data[6]}
0135 {
0136 }
0137
0138
0139
0140
0141
0142 CELER_FUNCTION SignedSense SimpleQuadric::calc_sense(Real3 const& pos) const
0143 {
0144 real_type const x = pos[to_int(Axis::x)];
0145 real_type const y = pos[to_int(Axis::y)];
0146 real_type const z = pos[to_int(Axis::z)];
0147
0148 return real_to_sense((a_ * ipow<2>(x) + b_ * ipow<2>(y) + c_ * ipow<2>(z))
0149 + (d_ * x + e_ * y + f_ * z) + (g_));
0150 }
0151
0152
0153
0154
0155
0156 CELER_FUNCTION auto
0157 SimpleQuadric::calc_intersections(Real3 const& pos,
0158 Real3 const& dir,
0159 SurfaceState on_surface) const -> Intersections
0160 {
0161 real_type const x = pos[to_int(Axis::x)];
0162 real_type const y = pos[to_int(Axis::y)];
0163 real_type const z = pos[to_int(Axis::z)];
0164 real_type const u = dir[to_int(Axis::x)];
0165 real_type const v = dir[to_int(Axis::y)];
0166 real_type const w = dir[to_int(Axis::z)];
0167
0168
0169 real_type a = (a_ * u) * u + (b_ * v) * v + (c_ * w) * w;
0170 real_type b = (2 * a_ * x + d_) * u + (2 * b_ * y + e_) * v
0171 + (2 * c_ * z + f_) * w;
0172 real_type c = (a_ * x + d_) * x + (b_ * y + e_) * y + (c_ * z + f_) * z
0173 + g_;
0174
0175 return detail::QuadraticSolver::solve_general(a, b / 2, c, on_surface);
0176 }
0177
0178
0179
0180
0181
0182 CELER_FUNCTION Real3 SimpleQuadric::calc_normal(Real3 const& pos) const
0183 {
0184 real_type const x = pos[to_int(Axis::x)];
0185 real_type const y = pos[to_int(Axis::y)];
0186 real_type const z = pos[to_int(Axis::z)];
0187
0188 Real3 norm{2 * a_ * x + d_, 2 * b_ * y + e_, 2 * c_ * z + f_};
0189 return make_unit_vector(norm);
0190 }
0191
0192
0193 }