File indexing completed on 2026-09-18 09:32:38
0001
0002
0003
0004
0005 #ifndef VECGEOM_BASE_SIDEPLANES_H_
0006 #define VECGEOM_BASE_SIDEPLANES_H_
0007
0008 #include "VecGeom/base/Global.h"
0009 #include "VecGeom/volumes/kernel/GenericKernels.h"
0010
0011
0012 #include <VecCore/VecCore>
0013
0014 namespace vecgeom {
0015 inline namespace VECGEOM_IMPL_NAMESPACE {
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 template <int N, typename Type>
0032 struct PlaneShell {
0033
0034
0035 Precision fA[N];
0036 Precision fB[N];
0037 Precision fC[N];
0038 Precision fD[N];
0039
0040 public:
0041
0042
0043
0044 VECCORE_ATT_HOST_DEVICE
0045 PlaneShell(Precision *const a, Precision *const b, Precision *const c, Precision *const d)
0046 {
0047 memcpy(&(this->fA), a, N * sizeof(Type));
0048 memcpy(&(this->fB), b, N * sizeof(Type));
0049 memcpy(&(this->fC), c, N * sizeof(Type));
0050 memcpy(&(this->fD), d, N * sizeof(Type));
0051 }
0052
0053
0054
0055
0056
0057 VECCORE_ATT_HOST_DEVICE
0058 PlaneShell()
0059 {
0060 memset(&(this->fA), 0, N * sizeof(Type));
0061 memset(&(this->fB), 0, N * sizeof(Type));
0062 memset(&(this->fC), 0, N * sizeof(Type));
0063 memset(&(this->fD), 0, N * sizeof(Type));
0064 }
0065
0066
0067
0068
0069 VECCORE_ATT_HOST_DEVICE
0070 PlaneShell(PlaneShell const &other)
0071 {
0072 memcpy(&(this->fA), &(other.fA), N * sizeof(Type));
0073 memcpy(&(this->fB), &(other.fB), N * sizeof(Type));
0074 memcpy(&(this->fC), &(other.fC), N * sizeof(Type));
0075 memcpy(&(this->fD), &(other.fD), N * sizeof(Type));
0076 }
0077
0078
0079
0080
0081 VECCORE_ATT_HOST_DEVICE
0082 PlaneShell &operator=(PlaneShell const &other)
0083 {
0084 memcpy(this->fA, other.fA, N * sizeof(Type));
0085 memcpy(this->fB, other.fB, N * sizeof(Type));
0086 memcpy(this->fC, other.fC, N * sizeof(Type));
0087 memcpy(this->fD, other.fD, N * sizeof(Type));
0088 return *this;
0089 }
0090
0091 VECCORE_ATT_HOST_DEVICE
0092 void Set(int i, Precision a, Precision b, Precision c, Precision d)
0093 {
0094 fA[i] = a;
0095 fB[i] = b;
0096 fC[i] = c;
0097 fD[i] = d;
0098 }
0099
0100 VECCORE_ATT_HOST_DEVICE
0101 unsigned int size() { return N; }
0102
0103 VECCORE_ATT_HOST_DEVICE
0104 ~PlaneShell() {}
0105
0106
0107
0108 template <typename Type2>
0109 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE void DistanceToPoint(Vector3D<Type2> const &point,
0110 Type2 *distances) const
0111 {
0112 for (int i = 0; i < N; ++i) {
0113 distances[i] = this->fA[i] * point.x() + this->fB[i] * point.y() + this->fC[i] * point.z() + this->fD[i];
0114 }
0115 }
0116
0117
0118
0119 template <typename Type2>
0120 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE void ProjectionToNormal(Vector3D<Type2> const &dir,
0121 Type2 *projection) const
0122 {
0123 for (int i = 0; i < N; ++i) {
0124 projection[i] = this->fA[i] * dir.x() + this->fB[i] * dir.y() + this->fC[i] * dir.z();
0125 }
0126 }
0127
0128 template <typename Real_v, bool ForInside>
0129 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE void GenericKernelForContainsAndInside(
0130 Vector3D<Real_v> const &point, vecCore::Mask_v<Real_v> &completelyInside,
0131 vecCore::Mask_v<Real_v> &completelyOutside) const
0132 {
0133
0134 Real_v dist[N];
0135 for (unsigned int i = 0; i < N; ++i) {
0136 dist[i] = this->fA[i] * point.x() + this->fB[i] * point.y() + this->fC[i] * point.z() + this->fD[i];
0137 }
0138
0139
0140 for (unsigned int i = 0; i < N; ++i) {
0141
0142 completelyOutside = completelyOutside || (dist[i] > Real_v(MakePlusTolerant<ForInside>(0.)));
0143 if (ForInside) {
0144 completelyInside = completelyInside && (dist[i] < Real_v(MakeMinusTolerant<ForInside>(0.)));
0145 }
0146
0147 }
0148 }
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158 template <typename Real_v>
0159 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE Real_v DistanceToIn(Vector3D<Real_v> const &point,
0160 Vector3D<Real_v> const &dir, Real_v &smin,
0161 Real_v &smax) const
0162 {
0163 using Bool_v = vecCore::Mask_v<Real_v>;
0164 Bool_v done(false);
0165 Real_v distIn(kInfLength);
0166
0167
0168 Real_v pdist[N];
0169 Real_v proj[N];
0170 Real_v vdist[N];
0171
0172 for (int i = 0; i < N; ++i) {
0173 pdist[i] = this->fA[i] * point.x() + this->fB[i] * point.y() + this->fC[i] * point.z() + this->fD[i];
0174 proj[i] = this->fA[i] * dir.x() + this->fB[i] * dir.y() + this->fC[i] * dir.z();
0175
0176
0177 vdist[i] = -pdist[i] / NonZero(proj[i]);
0178 }
0179
0180
0181 for (int i = 0; i < N; ++i) {
0182 done = done || (pdist[i] > Real_v(MakePlusTolerant<true>(0.)) && proj[i] >= Real_v(0.));
0183 done = done || (pdist[i] > Real_v(MakeMinusTolerant<true>(0.)) && proj[i] > Real_v(0.));
0184 }
0185 if (vecCore::EarlyReturnMaxLength(done, 1) && vecCore::MaskFull(done)) return distIn;
0186
0187
0188 for (int i = 0; i < N; ++i) {
0189
0190 Bool_v posPoint = pdist[i] > Real_v(MakeMinusTolerant<true>(0.));
0191 Bool_v posDir = proj[i] > 0;
0192
0193
0194 Bool_v interceptFromInside = (!posPoint && posDir);
0195 done = done || (interceptFromInside && vdist[i] < smin);
0196
0197 Bool_v interceptFromOutside = (posPoint && !posDir);
0198 done = done || (interceptFromOutside && vdist[i] > smax);
0199 if (vecCore::EarlyReturnMaxLength(done, 1) && vecCore::MaskFull(done)) return distIn;
0200
0201
0202 vecCore__MaskedAssignFunc(smin, interceptFromOutside && vdist[i] > smin, vdist[i]);
0203 vecCore__MaskedAssignFunc(smax, interceptFromInside && vdist[i] < smax, vdist[i]);
0204 }
0205
0206
0207
0208 vecCore::MaskedAssign(distIn, !done && smin <= smax, smin);
0209 return distIn;
0210 }
0211
0212
0213
0214
0215
0216 template <typename Real_v>
0217 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE Real_v DistanceToOut(Vector3D<Real_v> const &point,
0218 Vector3D<Real_v> const &dir) const
0219 {
0220
0221
0222 Real_v distOut(kInfLength);
0223
0224
0225
0226
0227
0228 Real_v pdist[N];
0229 Real_v proj[N];
0230 Real_v vdist[N];
0231 for (int i = 0; i < N; ++i) {
0232 pdist[i] = this->fA[i] * point.x() + this->fB[i] * point.y() + this->fC[i] * point.z() + this->fD[i];
0233 proj[i] = this->fA[i] * dir.x() + this->fB[i] * dir.y() + this->fC[i] * dir.z();
0234 vdist[i] = -pdist[i] / NonZero(proj[i]);
0235 }
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245 for (int i = 0; i < N; ++i) {
0246 vecCore__MaskedAssignFunc(distOut, pdist[i] > kHalfTolerance, Real_v(-1.));
0247 vecCore__MaskedAssignFunc(distOut, proj[i] > kTolerance && vdist[i] < distOut, vdist[i]);
0248
0249
0250 }
0251
0252 return distOut;
0253 }
0254
0255
0256 template <typename Real_v>
0257 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE void SafetyToIn(Vector3D<Real_v> const &point, Real_v &safety) const
0258 {
0259
0260 Real_v dist[N];
0261 for (int i = 0; i < N; ++i) {
0262 dist[i] = this->fA[i] * point.x() + this->fB[i] * point.y() + this->fC[i] * point.z() + this->fD[i];
0263 }
0264
0265
0266 for (int i = 0; i < N; ++i) {
0267 vecCore__MaskedAssignFunc(safety, dist[i] > safety, dist[i]);
0268 }
0269 }
0270
0271
0272 template <typename Real_v>
0273 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE void SafetyToOut(Vector3D<Real_v> const &point, Real_v &safety) const
0274 {
0275
0276 Real_v dist[N];
0277 for (int i = 0; i < N; ++i) {
0278 dist[i] = -(this->fA[i] * point.x() + this->fB[i] * point.y() + this->fC[i] * point.z() + this->fD[i]);
0279 }
0280
0281
0282 for (int i = 0; i < N; ++i) {
0283 vecCore__MaskedAssignFunc(safety, dist[i] < safety, dist[i]);
0284 }
0285 }
0286
0287 template <typename Real_v>
0288 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE size_t ClosestFace(Vector3D<Real_v> const &point, Real_v &safety) const
0289 {
0290
0291 Real_v dist[N];
0292 for (int i = 0; i < N; ++i) {
0293 dist[i] = Abs(this->fA[i] * point.x() + this->fB[i] * point.y() + this->fC[i] * point.z() + this->fD[i]);
0294 }
0295
0296
0297 using Bool_v = vecCore::Mask_v<Real_v>;
0298 using Index_v = vecCore::Index<Real_v>;
0299 Index_v closest = static_cast<Index_v>(-1);
0300 for (size_t i = 0; i < N; ++i) {
0301 Bool_v closer = dist[i] < safety;
0302 vecCore__MaskedAssignFunc(safety, closer, dist[i]);
0303 vecCore::MaskedAssign(closest, closer, i);
0304 }
0305
0306 return closest;
0307 }
0308
0309
0310
0311
0312
0313
0314 template <typename Real_v>
0315 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE Real_v NormalKernel(Vector3D<Real_v> const &point,
0316 Vector3D<Real_v> &normal, bool &edge) const
0317 {
0318 Real_v safety = InfinityLength<Real_v>();
0319
0320
0321 Real_v dist[N];
0322 Vector3D<Real_v> cornerNormal;
0323 unsigned char surfaces = 0;
0324 edge = false;
0325 for (int i = 0; i < N; ++i) {
0326 dist[i] = Abs(this->fA[i] * point.x() + this->fB[i] * point.y() + this->fC[i] * point.z() + this->fD[i]);
0327
0328 if (dist[i] < safety) {
0329 normal.Set(this->fA[i], this->fB[i], this->fC[i]);
0330 safety = dist[i];
0331 }
0332
0333 if (dist[i] < kTolerance) {
0334 surfaces++;
0335 cornerNormal += Vector3D<Real_v>(this->fA[i], this->fB[i], this->fC[i]);
0336 }
0337 }
0338 if (surfaces > 1) {
0339
0340 normal = cornerNormal;
0341 edge = true;
0342 }
0343
0344 return safety;
0345 }
0346 };
0347
0348 }
0349 }
0350
0351 #endif