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