File indexing completed on 2026-09-14 09:26:24
0001 #ifndef VECGEOM_VOLUMES_KERNEL_SEXTRUIMPLEMENTATION_H_
0002 #define VECGEOM_VOLUMES_KERNEL_SEXTRUIMPLEMENTATION_H_
0003
0004 #include "VecGeom/base/Vector3D.h"
0005 #include "VecGeom/volumes/PolygonalShell.h"
0006 #include "VecGeom/volumes/kernel/BoxImplementation.h"
0007
0008 namespace vecgeom {
0009
0010 VECGEOM_DEVICE_FORWARD_DECLARE(struct SExtruImplementation;);
0011 VECGEOM_DEVICE_DECLARE_CONV(struct, SExtruImplementation);
0012
0013 inline namespace VECGEOM_IMPL_NAMESPACE {
0014
0015 class PlacedSExtru;
0016 class PolygonalShell;
0017 class UnplacedSExtruVolume;
0018
0019 struct SExtruImplementation {
0020
0021 using PlacedShape_t = PlacedSExtru;
0022 using UnplacedStruct_t = PolygonalShell;
0023 using UnplacedVolume_t = UnplacedSExtruVolume;
0024
0025 template <typename Real_v, typename Bool_v>
0026 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void Contains(UnplacedStruct_t const &unplaced,
0027 Vector3D<Real_v> const &p, Bool_v &inside)
0028 {
0029 inside = Bool_v(false);
0030 auto done = p.z() > Real_v(unplaced.fUpperZ);
0031 done |= p.z() < Real_v(unplaced.fLowerZ);
0032 if (vecCore::MaskFull(done)) return;
0033 if (unplaced.fPolygon.IsConvex())
0034 inside = !done && unplaced.fPolygon.ContainsConvex(p);
0035 else
0036 inside = !done && unplaced.fPolygon.Contains(p);
0037 }
0038
0039 template <typename Real_v, typename Inside_t>
0040 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void Inside(UnplacedStruct_t const &unplaced,
0041 Vector3D<Real_v> const &point, Inside_t &inside)
0042 {
0043
0044 if (point.z() > unplaced.fUpperZ + kTolerance) {
0045 inside = vecgeom::kOutside;
0046 return;
0047 }
0048 if (point.z() < unplaced.fLowerZ - kTolerance) {
0049 inside = vecgeom::kOutside;
0050 return;
0051 }
0052
0053
0054 using Bool_v = vecCore::Mask_v<Real_v>;
0055 Bool_v onZ = Abs(point.z() - unplaced.fUpperZ) < kTolerance;
0056 onZ |= Abs(point.z() - unplaced.fLowerZ) < kTolerance;
0057
0058 if (unplaced.fPolygon.IsConvex()) {
0059 inside = unplaced.fPolygon.InsideConvex(point);
0060 if (onZ && inside != vecgeom::kOutside) inside = vecgeom::kSurface;
0061 return;
0062 }
0063
0064 if (onZ) {
0065 if (unplaced.fPolygon.Contains(point)) {
0066 inside = vecgeom::kSurface;
0067 return;
0068 }
0069 }
0070
0071
0072 if (unplaced.fLowerZ <= point.z() && point.z() <= unplaced.fUpperZ) {
0073 int unused;
0074 auto s = unplaced.fPolygon.SafetySqr(point, unused);
0075 if (s < kTolerance * kTolerance) {
0076 inside = vecgeom::kSurface;
0077 return;
0078 }
0079 }
0080
0081 Bool_v c;
0082 Contains(unplaced, point, c);
0083
0084 if (c)
0085 inside = vecgeom::kInside;
0086 else
0087 inside = vecgeom::kOutside;
0088 return;
0089 }
0090
0091 template <typename Real_v>
0092 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void DistanceToIn(UnplacedStruct_t const &polyshell,
0093 Vector3D<Real_v> const &p,
0094 Vector3D<Real_v> const &dir,
0095 Real_v const & , Real_v &distance)
0096 {
0097 if (polyshell.fPolygon.IsConvex()) {
0098 distance = polyshell.DistanceToInConvex(p, dir);
0099 return;
0100 }
0101 distance = Real_v(kInfLength);
0102
0103
0104
0105 const auto s = vecCore::Blend(dir.z() > Real_v(0.), p.z() - polyshell.fLowerZ, polyshell.fUpperZ - p.z());
0106
0107 const auto canhit = s < Real_v(kTolerance);
0108 if (!vecCore::MaskEmpty(canhit)) {
0109 const auto dist = -s / Abs(dir.z());
0110
0111 const auto xInters = p.x() + dist * dir.x();
0112 const auto yInters = p.y() + dist * dir.y();
0113
0114 const auto hits = polyshell.fPolygon.Contains(Vector3D<Real_v>(xInters, yInters, Real_v(0.)));
0115
0116 vecCore::MaskedAssign(distance, hits, dist);
0117 if (vecCore::MaskFull(hits)) {
0118 return;
0119 }
0120 }
0121
0122
0123 vecCore__MaskedAssignFunc(distance, distance == Real_v(kInfLength), polyshell.DistanceToIn(p, dir));
0124 return;
0125 }
0126
0127 template <typename Real_v>
0128 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void DistanceToOut(UnplacedStruct_t const &polyshell,
0129 Vector3D<Real_v> const &p,
0130 Vector3D<Real_v> const &dir,
0131 Real_v const & , Real_v &distance)
0132 {
0133 if (polyshell.fPolygon.IsConvex()) {
0134 distance = polyshell.DistanceToOutConvex(p, dir);
0135 return;
0136 }
0137 distance = Real_v(-1.);
0138
0139 const auto dshell = polyshell.DistanceToOut(p, dir);
0140 const auto hitshell = dshell < Real_v(kInfLength);
0141 if (vecCore::MaskFull(hitshell)) {
0142 distance = dshell;
0143 return;
0144 }
0145 const auto correctZ = vecCore::Blend(dir.z() > Real_v(0.), Real_v(polyshell.fUpperZ), Real_v(polyshell.fLowerZ));
0146 distance = (correctZ - p.z()) / dir.z();
0147 return;
0148 }
0149
0150 template <typename Real_v>
0151 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void SafetyToIn(UnplacedStruct_t const &polyshell,
0152 Vector3D<Real_v> const &point, Real_v &safety)
0153 {
0154 if (polyshell.fPolygon.IsConvex()) {
0155 Real_v safeZ = vecCore::math::Max(polyshell.fLowerZ - point.z(), point.z() - polyshell.fUpperZ);
0156 safety = vecCore::math::Max(safeZ, polyshell.fPolygon.SafetyConvex(point, false));
0157 return;
0158 }
0159
0160 Vector3D<Precision> aMin, aMax;
0161 polyshell.Extent(aMin, aMax);
0162
0163 using Bool_v = vecCore::Mask_v<Real_v>;
0164 Bool_v isInExtent;
0165 ABBoxImplementation::ABBoxContainsKernelGeneric(aMin, aMax, point, isInExtent);
0166
0167
0168 if (vecCore::MaskEmpty(isInExtent)) {
0169 const auto ssqr = ABBoxImplementation::ABBoxSafetySqr(aMin, aMax, point);
0170 if (ssqr <= 0.) {
0171 safety = 0.;
0172 return;
0173 }
0174 safety = std::sqrt(ssqr);
0175 return;
0176 }
0177
0178 const auto zSafety1 = polyshell.fLowerZ - point.z();
0179 const auto zSafety2 = polyshell.fUpperZ - point.z();
0180 if (Abs(zSafety1) < kTolerance || Abs(zSafety2) < kTolerance) {
0181
0182
0183 bool c;
0184 Contains(polyshell, point, c);
0185 if (c) {
0186 safety = 0.;
0187 return;
0188 }
0189 }
0190 int unused;
0191 safety = std::sqrt(polyshell.fPolygon.SafetySqr(point, unused));
0192 }
0193
0194 template <typename Real_v>
0195 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void SafetyToOut(UnplacedStruct_t const &polyshell,
0196 Vector3D<Real_v> const &point, Real_v &safety)
0197 {
0198 int unused;
0199 if (polyshell.fPolygon.IsConvex()) {
0200 Real_v safeZ = vecCore::math::Min(point.z() - polyshell.fLowerZ, polyshell.fUpperZ - point.z());
0201 safety = vecCore::math::Min(safeZ, polyshell.fPolygon.SafetyConvex(point, true));
0202 return;
0203 }
0204 safety = std::sqrt(polyshell.fPolygon.SafetySqr(point, unused));
0205 safety = Min(safety, polyshell.fUpperZ - point.z());
0206 safety = Min(safety, point.z() - polyshell.fLowerZ);
0207 }
0208
0209 template <typename Real_v>
0210 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static Vector3D<Real_v> NormalKernel(
0211 UnplacedStruct_t const &unplaced, Vector3D<Real_v> const &point, typename vecCore::Mask_v<Real_v> &valid)
0212 {
0213
0214
0215 valid = false;
0216 Vector3D<Real_v> normal(0., 0., 0.);
0217
0218
0219 using Bool_v = vecCore::Mask_v<Real_v>;
0220 Bool_v onUpperZ = Abs(point.z() - unplaced.fUpperZ) < kTolerance;
0221 Bool_v onLowerZ = Abs(point.z() - unplaced.fLowerZ) < kTolerance;
0222
0223 if (onUpperZ || onLowerZ) {
0224 if (unplaced.fPolygon.Contains(point)) {
0225 valid = true;
0226 if (onUpperZ)
0227 normal = Vector3D<Real_v>(0., 0., 1);
0228 else {
0229 normal = Vector3D<Real_v>(0., 0., -1.);
0230 }
0231 return normal;
0232 }
0233 }
0234
0235
0236 if (unplaced.fLowerZ <= point.z() && point.z() <= unplaced.fUpperZ) {
0237 int surfaceindex;
0238 auto s = unplaced.fPolygon.SafetySqr(point, surfaceindex);
0239 normal = Vector3D<Real_v>(-unplaced.fPolygon.fA[surfaceindex], -unplaced.fPolygon.fB[surfaceindex], 0.);
0240 if (s < kTolerance * kTolerance) {
0241 valid = true;
0242 }
0243 }
0244 return normal;
0245 }
0246
0247 };
0248 }
0249 }
0250
0251 #endif