File indexing completed on 2026-09-14 09:26:27
0001
0002
0003
0004
0005
0006
0007 #ifndef VECGEOM_CONEUTILITIES_H_
0008 #define VECGEOM_CONEUTILITIES_H_
0009
0010 #include "VecGeom/base/Global.h"
0011 #include "VecGeom/volumes/Wedge_Evolution.h"
0012 #include "VecGeom/base/Vector3D.h"
0013 #include "VecGeom/volumes/ConeStruct.h"
0014 #include "VecGeom/volumes/kernel/GenericKernels.h"
0015 #include "VecGeom/volumes/kernel/shapetypes/ConeTypes.h"
0016 #include "VecGeom/volumes/kernel/TubeImplementation.h"
0017 #include <cstdio>
0018
0019 namespace vecgeom {
0020
0021 inline namespace VECGEOM_IMPL_NAMESPACE {
0022
0023 class UnplacedCone;
0024 template <typename T>
0025 struct ConeStruct;
0026 using UnplacedStruct_t = ConeStruct<Precision>;
0027
0028 namespace ConeUtilities {
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063 #if (1)
0064 template <typename Real_v, typename ShapeType, bool onSurfaceT, bool includeSurface = true>
0065 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void PointInCyclicalSector(UnplacedStruct_t const &volume,
0066 Real_v const &x, Real_v const &y,
0067 typename vecCore::Mask_v<Real_v> &ret)
0068 {
0069
0070 using namespace ::vecgeom::ConeTypes;
0071
0072
0073
0074
0075
0076
0077
0078 Real_v startx = volume.fAlongPhi1x;
0079 Real_v starty = volume.fAlongPhi1y;
0080
0081 Real_v endx = volume.fAlongPhi2x;
0082 Real_v endy = volume.fAlongPhi2y;
0083
0084 bool smallerthanpi;
0085
0086 if (SectorType<ShapeType>::value == kUnknownAngle)
0087 smallerthanpi = volume.fDPhi <= M_PI;
0088 else
0089 smallerthanpi = SectorType<ShapeType>::value == kOnePi || SectorType<ShapeType>::value == kSmallerThanPi;
0090
0091 Real_v startCheck = (-x * starty) + (y * startx);
0092 Real_v endCheck = (-endx * y) + (endy * x);
0093
0094 if (onSurfaceT) {
0095
0096 ret = (Abs(startCheck) <= kConeTolerance) || (Abs(endCheck) <= kConeTolerance);
0097 } else {
0098 if (smallerthanpi) {
0099 if (includeSurface)
0100 ret = (startCheck >= -kConeTolerance) & (endCheck >= -kConeTolerance);
0101 else
0102 ret = (startCheck >= kConeTolerance) & (endCheck >= kConeTolerance);
0103 } else {
0104 if (includeSurface)
0105 ret = (startCheck >= -kConeTolerance) || (endCheck >= -kConeTolerance);
0106 else
0107 ret = (startCheck >= kConeTolerance) || (endCheck >= kConeTolerance);
0108 }
0109 }
0110 }
0111
0112 #endif
0113
0114 #if (1)
0115 template <typename Real_v, bool ForInnerRadius>
0116 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static Real_v GetRadiusOfConeAtPoint(UnplacedStruct_t const &cone,
0117 Real_v const pointZ)
0118 {
0119
0120 if (ForInnerRadius) {
0121 if (cone.fRmin1 == cone.fRmin2) {
0122 return cone.fRmin1;
0123 } else {
0124 return cone.fInnerSlope * pointZ + cone.fInnerOffset;
0125 }
0126
0127 } else {
0128 if (cone.fOriginalRmax1 == cone.fOriginalRmax2) {
0129 return cone.fOriginalRmax1;
0130 } else {
0131 return cone.fOuterSlope * pointZ + cone.fOuterOffset;
0132 }
0133 }
0134 }
0135
0136 #endif
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153 template <typename Real_v, typename ConeType, bool PositiveDirectionOfPhiVector, bool insectorCheck>
0154 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void PhiPlaneTrajectoryIntersection(
0155 Precision alongX, Precision alongY, Precision normalX, Precision normalY, UnplacedStruct_t const &cone,
0156 Vector3D<Real_v> const &pos, Vector3D<Real_v> const &dir, Real_v &dist, typename vecCore::Mask_v<Real_v> &ok)
0157 {
0158 const Real_v zero(0.0);
0159 dist = kInfLength;
0160
0161
0162
0163
0164 if (insectorCheck)
0165 ok = ((dir.x() * normalX) + (dir.y() * normalY) > zero);
0166 else
0167 ok = ((dir.x() * normalX) + (dir.y() * normalY) < zero);
0168
0169
0170
0171 Real_v dirDotXY = (dir.y() * alongX) - (dir.x() * alongY);
0172 vecCore__MaskedAssignFunc(dist, dirDotXY != 0, ((alongY * pos.x()) - (alongX * pos.y())) / NonZero(dirDotXY));
0173 ok &= dist > -kConeTolerance;
0174
0175
0176 if (insectorCheck) {
0177 Real_v hitx = pos.x() + dist * dir.x();
0178 Real_v hity = pos.y() + dist * dir.y();
0179 Real_v hitz = pos.z() + dist * dir.z();
0180 Real_v r2 = (hitx * hitx) + (hity * hity);
0181 Real_v innerRadIrTol = GetRadiusOfConeAtPoint<Real_v, true>(cone, hitz) + kTolerance;
0182 Real_v outerRadIrTol = GetRadiusOfConeAtPoint<Real_v, false>(cone, hitz) - kTolerance;
0183
0184 ok &= Abs(hitz) <= cone.fTolIz && (r2 >= innerRadIrTol * innerRadIrTol) && (r2 <= outerRadIrTol * outerRadIrTol);
0185
0186
0187
0188
0189 if (PositiveDirectionOfPhiVector) {
0190 ok = ok && ((hitx * alongX) + (hity * alongY)) > zero;
0191 }
0192 } else {
0193 if (PositiveDirectionOfPhiVector) {
0194 Real_v hitx = pos.x() + dist * dir.x();
0195 Real_v hity = pos.y() + dist * dir.y();
0196 ok = ok && ((hitx * alongX) + (hity * alongY)) >= zero;
0197 }
0198 }
0199 }
0200
0201 template <typename Real_v, bool ForInnerSurface>
0202 VECCORE_ATT_HOST_DEVICE static Vector3D<Real_v> GetNormal(UnplacedStruct_t const &cone, Vector3D<Real_v> const &point)
0203 {
0204
0205
0206 Real_v rho = point.Perp();
0207 Vector3D<Real_v> norm(0., 0., 0.);
0208
0209 if (ForInnerSurface) {
0210
0211 Precision rmin1 = cone.fRmin1;
0212 Precision rmin2 = cone.fRmin2;
0213 if ((rmin1 == rmin2) && (rmin1 != 0.)) {
0214
0215 norm.Set(-point.x(), -point.y(), 0.);
0216 } else {
0217 Precision secRMin = cone.fSecRMin;
0218 norm.Set(-point.x(), -point.y(), cone.fZNormInner * (rho * secRMin));
0219 }
0220 } else {
0221 Precision rmax1 = cone.fRmax1;
0222 Precision rmax2 = cone.fRmax2;
0223 if ((rmax1 == rmax2) && (rmax1 != 0.)) {
0224
0225 norm.Set(point.x(), point.y(), 0.);
0226 } else {
0227 Precision secRMax = cone.fSecRMax;
0228 norm.Set(point.x(), point.y(), cone.fZNormOuter * (rho * secRMax));
0229 }
0230 }
0231 return norm;
0232 }
0233
0234 template <typename Real_v, bool ForInnerSurface>
0235 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static typename vecCore::Mask_v<Real_v> IsOnConicalSurface(
0236 UnplacedStruct_t const &cone, Vector3D<Real_v> const &point)
0237 {
0238
0239 using namespace ConeUtilities;
0240 using namespace ConeTypes;
0241 const Real_v rho = point.Perp2();
0242 const Real_v coneRad = GetRadiusOfConeAtPoint<Real_v, ForInnerSurface>(cone, point.z());
0243 const Real_v coneRad2 = coneRad * coneRad;
0244 const Real_v tolerance = (ForInnerSurface) ? cone.fInnerTolerance : cone.fOuterTolerance;
0245 return (rho >= (coneRad2 - tolerance * coneRad)) && (rho <= (coneRad2 + tolerance * coneRad)) &&
0246 (Abs(point.z()) < (cone.fDz + kConeTolerance));
0247 }
0248
0249
0250 template <typename Real_v, bool ForInnerSurface>
0251 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static typename vecCore::Mask_v<Real_v> IsMovingOutsideConicalSurface(
0252 UnplacedStruct_t const &cone, Vector3D<Real_v> const &point, Vector3D<Real_v> const &direction)
0253 {
0254 return direction.Dot(GetNormal<Real_v, ForInnerSurface>(cone, point)) >= Real_v(0.);
0255 }
0256
0257
0258 template <typename Real_v, bool ForInnerSurface>
0259 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static typename vecCore::Mask_v<Real_v> IsMovingInsideConicalSurface(
0260 UnplacedStruct_t const &cone, Vector3D<Real_v> const &point, Vector3D<Real_v> const &direction)
0261 {
0262 return direction.Dot(GetNormal<Real_v, ForInnerSurface>(cone, point)) <= Real_v(0.);
0263 }
0264
0265 template <typename Real_v>
0266 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static typename vecCore::Mask_v<Real_v> IsOnStartPhi(
0267 UnplacedStruct_t const &cone, Vector3D<Real_v> const &point)
0268 {
0269
0270 return cone.fPhiWedge.IsOnSurfaceGeneric(cone.fPhiWedge.GetAlong1(), cone.fPhiWedge.GetNormal1(), point);
0271 }
0272
0273 template <typename Real_v>
0274 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static typename vecCore::Mask_v<Real_v> IsOnEndPhi(
0275 UnplacedStruct_t const &cone, Vector3D<Real_v> const &point)
0276 {
0277
0278 return cone.fPhiWedge.IsOnSurfaceGeneric(cone.fPhiWedge.GetAlong2(), cone.fPhiWedge.GetNormal2(), point);
0279 }
0280
0281 template <typename Real_v, bool ForTopPlane>
0282 VECCORE_ATT_HOST_DEVICE static typename vecCore::Mask_v<Real_v> IsOnZPlaneAndMovingInside(
0283 UnplacedStruct_t const &cone, Vector3D<Real_v> const &point, Vector3D<Real_v> const &direction)
0284 {
0285
0286 Real_v rho = point.Perp2();
0287 Precision fDz = cone.fDz;
0288
0289 if (ForTopPlane) {
0290 return (rho > (cone.fSqRmin2 - kConeTolerance)) && (rho < (cone.fSqRmax2 + kConeTolerance)) &&
0291 (point.z() < (fDz + kConeTolerance)) && (point.z() > (fDz - kConeTolerance)) && (direction.z() < Real_v(0.));
0292 } else {
0293 return (rho > (cone.fSqRmin1 - kConeTolerance)) && (rho < (cone.fSqRmax1 + kConeTolerance)) &&
0294 (point.z() < (-fDz + kConeTolerance)) && (point.z() > (-fDz - kConeTolerance)) &&
0295 (direction.z() > Real_v(0.));
0296 }
0297 }
0298
0299 template <typename Real_v, bool ForTopPlane>
0300 VECCORE_ATT_HOST_DEVICE static typename vecCore::Mask_v<Real_v> IsOnZPlaneAndMovingOutside(
0301 UnplacedStruct_t const &cone, Vector3D<Real_v> const &point, Vector3D<Real_v> const &direction)
0302 {
0303
0304 Real_v rho = point.Perp2();
0305 Precision fDz = cone.fDz;
0306
0307 if (ForTopPlane) {
0308 return (rho > (cone.fSqRmin2 - kConeTolerance)) && (rho < (cone.fSqRmax2 + kConeTolerance)) &&
0309 (point.z() < (fDz + kConeTolerance)) && (point.z() > (fDz - kConeTolerance)) && (direction.z() > Real_v(0.));
0310 } else {
0311 return (rho > (cone.fSqRmin1 - kConeTolerance)) && (rho < (cone.fSqRmax1 + kConeTolerance)) &&
0312 (point.z() < (-fDz + kConeTolerance)) && (point.z() > (-fDz - kConeTolerance)) &&
0313 (direction.z() < Real_v(0.));
0314 }
0315 }
0316
0317 }
0318
0319
0320
0321
0322 template <class Real_v, class coneTypeT>
0323 class ConeHelpers {
0324
0325 public:
0326 ConeHelpers() {}
0327 ~ConeHelpers() {}
0328 template <bool ForDistToIn, bool ForInnerSurface>
0329 VECCORE_ATT_HOST_DEVICE static typename vecCore::Mask_v<Real_v>
0330 DetectIntersectionAndCalculateDistanceToConicalSurface(UnplacedStruct_t const &cone, Vector3D<Real_v> const &point,
0331 Vector3D<Real_v> const &direction, Real_v &distance)
0332 {
0333
0334 using namespace ConeUtilities;
0335 using namespace ConeTypes;
0336 typedef typename vecCore::Mask_v<Real_v> Bool_t;
0337 const Real_v zero(0.0);
0338
0339 distance = kInfLength;
0340 Bool_t onConicalSurface = IsOnConicalSurface<Real_v, ForInnerSurface>(cone, point);
0341 Vector3D<Real_v> normal = ConeUtilities::GetNormal<Real_v, ForInnerSurface>(cone, point);
0342 Bool_t tangentToSurface = vecCore::math::Abs(direction.Dot(normal)) == zero;
0343 Bool_t done = onConicalSurface && tangentToSurface;
0344 if (vecCore::MaskFull(done)) return Bool_t(false);
0345
0346
0347 const Bool_t precond = !done && onConicalSurface;
0348 if (!vecCore::MaskEmpty(precond)) {
0349 if (ForDistToIn) {
0350 Bool_t isOnSurfaceAndMovingInside =
0351 precond & ConeUtilities::IsMovingInsideConicalSurface<Real_v, ForInnerSurface>(cone, point, direction);
0352
0353 if (!checkPhiTreatment<coneTypeT>(cone)) {
0354 vecCore__MaskedAssignFunc(distance, isOnSurfaceAndMovingInside, zero);
0355 done |= isOnSurfaceAndMovingInside;
0356 if (vecCore::MaskFull(done)) return done;
0357 } else {
0358 Bool_t insector(false);
0359 ConeUtilities::PointInCyclicalSector<Real_v, coneTypeT, false, true>(cone, point.x(), point.y(), insector);
0360 vecCore__MaskedAssignFunc(distance, insector && isOnSurfaceAndMovingInside, zero);
0361 done |= (insector && isOnSurfaceAndMovingInside);
0362 if (vecCore::MaskFull(done)) return done;
0363 }
0364
0365 } else {
0366 Bool_t isOnSurfaceAndMovingOutside =
0367 precond & ConeUtilities::IsMovingOutsideConicalSurface<Real_v, ForInnerSurface>(cone, point, direction);
0368
0369 if (!checkPhiTreatment<coneTypeT>(cone)) {
0370 vecCore__MaskedAssignFunc(distance, isOnSurfaceAndMovingOutside, zero);
0371 done |= isOnSurfaceAndMovingOutside;
0372 if (vecCore::MaskFull(done)) return done;
0373 } else {
0374 Bool_t insector(false);
0375 ConeUtilities::PointInCyclicalSector<Real_v, coneTypeT, false, true>(cone, point.x(), point.y(), insector);
0376 vecCore__MaskedAssignFunc(distance, insector && isOnSurfaceAndMovingOutside, zero);
0377 done |= (insector && isOnSurfaceAndMovingOutside);
0378 if (vecCore::MaskFull(done)) return done;
0379 }
0380 }
0381 }
0382
0383 Real_v pDotV2D = point.x() * direction.x() + point.y() * direction.y();
0384
0385 Real_v a(0.), b(0.), c(0.);
0386 Bool_t ok(false);
0387 Precision fDz = cone.fDz;
0388 if (ForInnerSurface) {
0389
0390 Precision rmin1 = cone.fRmin1;
0391 Precision rmin2 = cone.fRmin2;
0392 if (rmin1 == rmin2) {
0393 b = pDotV2D;
0394 a = direction.Perp2();
0395 c = point.Perp2() - rmin2 * rmin2;
0396 } else {
0397
0398 Precision t = cone.fTanInnerApexAngle;
0399 Real_v newPz(0.);
0400 if (cone.fRmin2 > cone.fRmin1)
0401 newPz = (point.z() + fDz + cone.fInnerConeApex) * t;
0402 else
0403 newPz = (point.z() - fDz - cone.fInnerConeApex) * t;
0404
0405 Real_v dirT = direction.z() * t;
0406 a = (direction.x() * direction.x()) + (direction.y() * direction.y()) - dirT * dirT;
0407
0408 b = pDotV2D - (newPz * dirT);
0409 c = point.Perp2() - (newPz * newPz);
0410 }
0411
0412 Real_v b2 = b * b;
0413 Real_v ac = a * c;
0414 if (vecCore::MaskFull(b2 < ac)) return Bool_t(false);
0415 Real_v d2 = b2 - ac;
0416
0417 Real_v delta = Sqrt(vecCore::math::Abs(d2));
0418 if (ForDistToIn) {
0419 vecCore__MaskedAssignFunc(distance, !done && d2 >= zero && (b >= zero), (c / NonZero(-b - delta)));
0420 vecCore__MaskedAssignFunc(distance, !done && d2 >= zero && (b < zero), (-b + delta) / NonZero(a));
0421 } else {
0422 vecCore__MaskedAssignFunc(distance, !done && d2 >= zero && (b >= zero), (-b - delta) / NonZero(a));
0423 vecCore__MaskedAssignFunc(distance, !done && d2 >= zero && (b < zero), (c / NonZero(-b + delta)));
0424 }
0425
0426 if (vecCore::MaskFull(distance < zero)) return Bool_t(false);
0427 Real_v newZ = point.z() + (direction.z() * distance);
0428 ok = (Abs(newZ) < fDz);
0429
0430 } else {
0431
0432
0433 if (cone.fOriginalRmax1 == cone.fOriginalRmax2) {
0434 b = pDotV2D;
0435 a = direction.Perp2();
0436 c = point.Perp2() - cone.fOriginalRmax2 * cone.fOriginalRmax2;
0437 } else {
0438
0439 Precision t = cone.fTanOuterApexAngle;
0440 Real_v newPz(0.);
0441
0442 if (cone.fOriginalRmax2 > cone.fOriginalRmax1)
0443 newPz = (point.z() + fDz + cone.fOuterConeApex) * t;
0444 else
0445 newPz = (point.z() - fDz - cone.fOuterConeApex) * t;
0446 Real_v dirT = direction.z() * t;
0447 a = direction.x() * direction.x() + direction.y() * direction.y() - dirT * dirT;
0448 b = pDotV2D - (newPz * dirT);
0449 c = point.Perp2() - (newPz * newPz);
0450 }
0451 Real_v b2 = b * b;
0452 Real_v ac = a * c;
0453 if (vecCore::MaskFull(b2 < ac)) return Bool_t(false);
0454 Real_v d2 = b2 - ac;
0455 Real_v delta = Sqrt(vecCore::math::Abs(d2));
0456
0457 if (ForDistToIn) {
0458 vecCore__MaskedAssignFunc(distance, !done && d2 >= zero && (b > zero), (-b - delta) / NonZero(a));
0459 vecCore__MaskedAssignFunc(distance, !done && d2 >= zero && (b < zero), (c / NonZero(-b + delta)));
0460 } else {
0461 vecCore__MaskedAssignFunc(distance, !done && d2 >= zero && (b < zero), (-b + delta) / NonZero(a));
0462 vecCore__MaskedAssignFunc(distance, !done && d2 >= zero && (b >= zero), (c / NonZero(-b - delta)));
0463 ok = distance > zero;
0464 }
0465
0466 if (vecCore::MaskFull(distance < zero)) return Bool_t(false);
0467 if (ForDistToIn) {
0468 Real_v newZ = point.z() + (direction.z() * distance);
0469 ok = (Abs(newZ) < cone.fDz + kHalfTolerance);
0470 }
0471 }
0472 vecCore__MaskedAssignFunc(distance, distance < zero, Real_v(kInfLength));
0473
0474 if (checkPhiTreatment<coneTypeT>(cone)) {
0475 Real_v hitx(0), hity(0), hitz(0);
0476 Bool_t insector(false);
0477 vecCore__MaskedAssignFunc(hitx, distance < kInfLength, point.x() + distance * direction.x());
0478 vecCore__MaskedAssignFunc(hity, distance < kInfLength, point.y() + distance * direction.y());
0479 vecCore__MaskedAssignFunc(hitz, distance < kInfLength, point.z() + distance * direction.z());
0480
0481 ConeUtilities::PointInCyclicalSector<Real_v, coneTypeT, false, true>(cone, hitx, hity, insector);
0482 ok &= ((insector) && (distance < kInfLength));
0483 }
0484 return ok;
0485 }
0486
0487 template <bool ForInside>
0488 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void GenericKernelForContainsAndInside(
0489 UnplacedStruct_t const &cone, Vector3D<Real_v> const &point, typename vecCore::Mask_v<Real_v> &completelyinside,
0490 typename vecCore::Mask_v<Real_v> &completelyoutside)
0491 {
0492
0493 typedef typename vecCore::Mask_v<Real_v> Bool_t;
0494
0495
0496 Real_v absz = Abs(point[2]);
0497 completelyoutside = absz > MakePlusTolerant<true>(cone.fDz, kConeTolerance);
0498 if (ForInside) {
0499 completelyinside = absz < MakeMinusTolerant<true>(cone.fDz, kConeTolerance);
0500 }
0501 if (vecCore::MaskFull(completelyoutside)) {
0502 return;
0503 }
0504
0505
0506 Real_v rmax(0.);
0507 Real_v r2 = point.x() * point.x() + point.y() * point.y();
0508
0509 if (cone.fOriginalRmax1 == cone.fOriginalRmax2)
0510 rmax = Real_v(cone.fOriginalRmax1);
0511 else
0512 rmax = cone.fOuterSlope * point.z() + cone.fOuterOffset;
0513
0514 completelyoutside |= r2 > MakePlusTolerantSquare<true>(rmax, cone.fOuterTolerance);
0515 if (ForInside) {
0516 completelyinside &= r2 < MakeMinusTolerantSquare<true>(rmax, cone.fOuterTolerance);
0517 }
0518 if (vecCore::MaskFull(completelyoutside)) {
0519 return;
0520 }
0521
0522
0523 if (ConeTypes::checkRminTreatment<coneTypeT>(cone)) {
0524 Real_v rmin = cone.fInnerSlope * point.z() + cone.fInnerOffset;
0525
0526 completelyoutside |= r2 < MakeMinusTolerantSquare<true>(rmin, cone.fInnerTolerance);
0527 if (ForInside) {
0528 completelyinside &= r2 > MakePlusTolerantSquare<true>(rmin, cone.fInnerTolerance);
0529 }
0530 if (vecCore::MaskFull(completelyoutside)) {
0531 return;
0532 }
0533 }
0534
0535 if (ConeTypes::checkPhiTreatment<coneTypeT>(cone)) {
0536 Bool_t completelyoutsidephi;
0537 Bool_t completelyinsidephi;
0538 cone.fPhiWedge.GenericKernelForContainsAndInside<Real_v, true>(point, completelyinsidephi, completelyoutsidephi);
0539 completelyoutside |= completelyoutsidephi;
0540 if (ForInside) completelyinside &= completelyinsidephi;
0541 }
0542 }
0543
0544 template <typename Inside_v>
0545 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void Inside(UnplacedStruct_t const &cone,
0546 Vector3D<Real_v> const &point, Inside_v &inside)
0547 {
0548
0549 using Bool_v = vecCore::Mask_v<Real_v>;
0550 using InsideBool_v = vecCore::Mask_v<Inside_v>;
0551 Bool_v completelyinside(false), completelyoutside(false);
0552 GenericKernelForContainsAndInside<true>(cone, point, completelyinside, completelyoutside);
0553 inside = EInside::kSurface;
0554 vecCore::MaskedAssign(inside, (InsideBool_v)completelyoutside, Inside_v(EInside::kOutside));
0555 vecCore::MaskedAssign(inside, (InsideBool_v)completelyinside, Inside_v(EInside::kInside));
0556 }
0557 };
0558
0559 template <class coneTypeT>
0560 class ConeHelpers<Precision, coneTypeT> {
0561
0562 public:
0563 ConeHelpers() {}
0564 ~ConeHelpers() {}
0565
0566 template <bool ForDistToIn, bool ForInnerSurface>
0567 VECCORE_ATT_HOST_DEVICE static bool DetectIntersectionAndCalculateDistanceToConicalSurface(
0568 UnplacedStruct_t const &cone, Vector3D<Precision> const &point, Vector3D<Precision> const &direction,
0569 Precision &distance)
0570 {
0571
0572 using namespace ConeUtilities;
0573 using namespace ConeTypes;
0574 distance = kInfLength;
0575 bool onConicalSurface = IsOnConicalSurface<Precision, ForInnerSurface>(cone, point);
0576 Vector3D<Precision> normal = ConeUtilities::GetNormal<Precision, ForInnerSurface>(cone, point);
0577 bool tangentToSurface = vecCore::math::Abs(direction.Dot(normal)) == 0.;
0578 if (onConicalSurface && tangentToSurface) {
0579 return false;
0580 }
0581
0582 if (onConicalSurface) {
0583 if (ForDistToIn) {
0584 bool isMovingInside = IsMovingInsideConicalSurface<Precision, ForInnerSurface>(cone, point, direction);
0585
0586 if (!checkPhiTreatment<coneTypeT>(cone)) {
0587 if (isMovingInside) {
0588 distance = 0.;
0589 return true;
0590 }
0591 } else {
0592 bool insector(false);
0593 ConeUtilities::PointInCyclicalSector<Precision, coneTypeT, false, true>(cone, point.x(), point.y(), insector);
0594 if (insector && isMovingInside) {
0595 distance = 0.;
0596 return true;
0597 }
0598 }
0599 }
0600
0601 else {
0602 bool isMovingOutside = IsMovingOutsideConicalSurface<Precision, ForInnerSurface>(cone, point, direction);
0603
0604 if (!checkPhiTreatment<coneTypeT>(cone)) {
0605 if (isMovingOutside) {
0606 distance = 0.;
0607 return true;
0608 }
0609 } else {
0610 bool insector(false);
0611 ConeUtilities::PointInCyclicalSector<Precision, coneTypeT, false, true>(cone, point.x(), point.y(), insector);
0612
0613 if (insector && isMovingOutside) {
0614 distance = 0.;
0615 return true;
0616 }
0617 }
0618 }
0619 }
0620
0621 bool ok(false);
0622 Precision pDotV2D = point.x() * direction.x() + point.y() * direction.y();
0623
0624 Precision a(kInfLength), b(kInfLength), c(kInfLength);
0625 if (ForInnerSurface) {
0626
0627 if (cone.fRmin1 == cone.fRmin2) {
0628 b = pDotV2D;
0629 a = direction.Perp2();
0630 c = point.Perp2() - cone.fRmin2 * cone.fRmin2;
0631 } else {
0632
0633 Precision newPz(0.);
0634 if (cone.fRmin2 > cone.fRmin1)
0635 newPz = (point.z() + cone.fDz + cone.fInnerConeApex) * cone.fTanInnerApexAngle;
0636 else
0637 newPz = (point.z() - cone.fDz - cone.fInnerConeApex) * cone.fTanInnerApexAngle;
0638
0639 Precision dirT = direction.z() * cone.fTanInnerApexAngle;
0640 a = (direction.x() * direction.x()) + (direction.y() * direction.y()) - dirT * dirT;
0641
0642 b = pDotV2D - (newPz * dirT);
0643 c = point.Perp2() - (newPz * newPz);
0644 }
0645
0646 Precision b2 = b * b;
0647 Precision ac = a * c;
0648 if (b2 < ac) return false;
0649
0650 Precision d2 = b2 - ac;
0651
0652 Precision delta = Sqrt(d2);
0653 if (ForDistToIn) {
0654 if (b >= 0.) {
0655 distance = (c / NonZero(-b - delta));
0656 } else {
0657 distance = (-b + delta) / NonZero(a);
0658 }
0659 } else {
0660 if (b == 0. && delta == 0.) return false;
0661 if (b >= 0.) {
0662 distance = (-b - delta) / NonZero(a);
0663 } else {
0664 distance = (c / NonZero(-b + delta));
0665 }
0666 }
0667
0668 if (distance < 0.) return false;
0669 Precision newZ = point.z() + (direction.z() * distance);
0670 ok = (Abs(newZ) < cone.fDz);
0671
0672 } else {
0673
0674
0675 if (cone.fOriginalRmax1 == cone.fOriginalRmax2) {
0676
0677 a = direction.Perp2();
0678 b = pDotV2D;
0679 c = (point.Perp2() - cone.fOriginalRmax2 * cone.fOriginalRmax2);
0680 } else {
0681
0682 Precision newPz(0.);
0683
0684 if (cone.fOriginalRmax2 > cone.fOriginalRmax1)
0685 newPz = (point.z() + cone.fDz + cone.fOuterConeApex) * cone.fTanOuterApexAngle;
0686 else
0687 newPz = (point.z() - cone.fDz - cone.fOuterConeApex) * cone.fTanOuterApexAngle;
0688 Precision dirT = direction.z() * cone.fTanOuterApexAngle;
0689 a = direction.x() * direction.x() + direction.y() * direction.y() - dirT * dirT;
0690 b = (pDotV2D - (newPz * dirT));
0691 c = (point.Perp2() - (newPz * newPz));
0692 }
0693 Precision b2 = b * b;
0694 Precision ac = a * c;
0695 Precision d2 = b2 - ac;
0696 if (d2 < 0) return false;
0697 Precision delta = Sqrt(d2);
0698
0699 if (ForDistToIn) {
0700 if (b == 0. && delta == 0.) return false;
0701 if (b > 0.) {
0702 distance = (-b - delta) / NonZero(a);
0703 } else {
0704 distance = (c / NonZero(-b + delta));
0705 }
0706 Precision newZ = point.z() + (direction.z() * distance);
0707 ok = (Abs(newZ) < cone.fDz + kHalfTolerance);
0708 } else {
0709 if (b < 0.) {
0710 distance = (-b + delta) / NonZero(a);
0711 } else {
0712 distance = (c / NonZero(-b - delta));
0713 }
0714 ok = distance > 0.;
0715 }
0716
0717 if (distance < 0.) return false;
0718 }
0719
0720
0721
0722
0723 if (checkPhiTreatment<coneTypeT>(cone)) {
0724 Precision hitx(0), hity(0);
0725 bool insector(false);
0726 if (distance < kInfLength) {
0727 hitx = point.x() + distance * direction.x();
0728 hity = point.y() + distance * direction.y();
0729 }
0730
0731 ConeUtilities::PointInCyclicalSector<Precision, coneTypeT, false, true>(cone, hitx, hity, insector);
0732 ok &= ((insector) && (distance < kInfLength));
0733 }
0734 return ok;
0735 }
0736
0737 template <bool ForInside>
0738 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void GenericKernelForContainsAndInside(
0739 UnplacedStruct_t const &cone, Vector3D<Precision> const &point, bool &completelyinside, bool &completelyoutside)
0740 {
0741
0742
0743 Precision absz = Abs(point[2]);
0744 completelyoutside = absz > MakePlusTolerant<ForInside>(cone.fDz, kConeTolerance);
0745 if (ForInside) {
0746 completelyinside = absz < MakeMinusTolerant<ForInside>(cone.fDz, kConeTolerance);
0747 }
0748 if (completelyoutside) return;
0749
0750
0751 Precision r2 = point.x() * point.x() + point.y() * point.y();
0752
0753 Precision rmax = 0.;
0754 if (cone.fOriginalRmax1 == cone.fOriginalRmax2)
0755 rmax = cone.fOriginalRmax1;
0756 else
0757 rmax = cone.fOuterSlope * point.z() + cone.fOuterOffset;
0758
0759 completelyoutside |= r2 > MakePlusTolerantSquare<ForInside>(rmax, cone.fOuterTolerance);
0760 if (ForInside) {
0761 completelyinside &= r2 < MakeMinusTolerantSquare<ForInside>(rmax, cone.fOuterTolerance);
0762 }
0763 if (completelyoutside) return;
0764
0765
0766 if (ConeTypes::checkRminTreatment<coneTypeT>(cone)) {
0767 Precision rmin = cone.fInnerSlope * point.z() + cone.fInnerOffset;
0768
0769 completelyoutside |= r2 <= MakeMinusTolerantSquare<ForInside>(rmin, cone.fInnerTolerance);
0770 if (ForInside) {
0771 completelyinside &= r2 > MakePlusTolerantSquare<ForInside>(rmin, cone.fInnerTolerance);
0772 }
0773 if (completelyoutside) return;
0774 }
0775
0776 if (ConeTypes::checkPhiTreatment<coneTypeT>(cone)) {
0777 bool completelyoutsidephi(false);
0778 bool completelyinsidephi(false);
0779 cone.fPhiWedge.GenericKernelForContainsAndInside<Precision, ForInside>(point, completelyinsidephi,
0780 completelyoutsidephi);
0781 completelyoutside |= completelyoutsidephi;
0782 if (ForInside) completelyinside &= completelyinsidephi;
0783 }
0784 }
0785
0786 template <typename Inside_v>
0787 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void Inside(UnplacedStruct_t const &cone,
0788 Vector3D<Precision> const &point, Inside_v &inside)
0789 {
0790 bool completelyinside(false), completelyoutside(false);
0791 GenericKernelForContainsAndInside<true>(cone, point, completelyinside, completelyoutside);
0792 inside = EInside::kSurface;
0793 if (completelyoutside) inside = EInside::kOutside;
0794 if (completelyinside) inside = EInside::kInside;
0795 }
0796 };
0797 }
0798 }
0799
0800 #endif