File indexing completed on 2026-09-14 09:26:14
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef NAVIGATION_VNAVIGATOR_H_
0009 #define NAVIGATION_VNAVIGATOR_H_
0010
0011 #include "VecGeom/base/Global.h"
0012 #include "VecGeom/base/Vector3D.h"
0013 #include "VecGeom/base/SOA3D.h"
0014 #include "VecGeom/base/Transformation3D.h"
0015 #include "VecGeom/navigation/NavigationState.h"
0016 #include "VecGeom/navigation/GlobalLocator.h"
0017 #include "VecGeom/volumes/PlacedVolume.h"
0018 #include "VecGeom/volumes/LogicalVolume.h"
0019 #include "VecGeom/navigation/VSafetyEstimator.h"
0020 #include "VecGeom/navigation/NavStateFwd.h"
0021
0022 namespace vecgeom {
0023 inline namespace VECGEOM_IMPL_NAMESPACE {
0024
0025
0026 template <typename T>
0027 class Vector3D;
0028
0029 class LogicalVolume;
0030 class Transformation3D;
0031 class VPlacedVolume;
0032
0033
0034
0035 class VNavigator {
0036
0037 public:
0038 VNavigator() : fSafetyEstimator(nullptr) {}
0039
0040 VECCORE_ATT_HOST_DEVICE
0041 VSafetyEstimator const *GetSafetyEstimator() const { return fSafetyEstimator; }
0042
0043
0044
0045
0046
0047
0048
0049
0050 VECCORE_ATT_HOST_DEVICE
0051 virtual Precision ComputeStepAndPropagatedState(Vector3D<Precision> const & ,
0052 Vector3D<Precision> const & ,
0053 Precision ,
0054 NavigationState const & ,
0055 NavigationState & ) const = 0;
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066 virtual Precision ComputeStep(Vector3D<Precision> const & , Vector3D<Precision> const & ,
0067 Precision , NavigationState const & ,
0068 NavigationState & ) const = 0;
0069
0070
0071
0072
0073 VECCORE_ATT_HOST_DEVICE
0074 virtual Precision ComputeStepAndSafety(Vector3D<Precision> const & ,
0075 Vector3D<Precision> const & , Precision ,
0076 NavigationState & , bool , Precision & ,
0077 bool indicateDaughterHit = false) const = 0;
0078
0079
0080 VECCORE_ATT_HOST_DEVICE
0081 void FindNextBoundaryAndStep(Vector3D<Precision> const &globalpoint, Vector3D<Precision> const &globaldir,
0082 NavigationState const &in_state, NavigationState &out_state, Precision step_limit,
0083 Precision &step) const
0084 {
0085 step = ComputeStepAndPropagatedState(globalpoint, globaldir, step_limit, in_state, out_state);
0086 }
0087
0088
0089 void FindNextBoundaryAndStepAndSafety(Vector3D<Precision> const &globalpoint, Vector3D<Precision> const &globaldir,
0090 NavigationState const &in_state, NavigationState &out_state,
0091 Precision step_limit, Precision &step, bool calcsafety, Precision &safety) const
0092 {
0093 step = ComputeStepAndSafetyAndPropagatedState(globalpoint, globaldir, step_limit, in_state, out_state, calcsafety,
0094 safety);
0095 }
0096
0097
0098 VECCORE_ATT_HOST_DEVICE
0099 virtual Precision ComputeStepAndSafetyAndPropagatedState(Vector3D<Precision> const & ,
0100 Vector3D<Precision> const & ,
0101 Precision ,
0102 NavigationState const & ,
0103 NavigationState & , bool ,
0104 Precision & ) const = 0;
0105
0106
0107
0108
0109 VECCORE_ATT_HOST_DEVICE
0110 virtual bool CheckDaughterIntersections(LogicalVolume const * , Vector3D<Precision> const & ,
0111 Vector3D<Precision> const & ,
0112 NavigationState const * , NavigationState * ,
0113 Precision & , VPlacedVolume const *& ) const = 0;
0114
0115
0116
0117
0118 VECCORE_ATT_HOST_DEVICE
0119 virtual bool CheckDaughterIntersections(LogicalVolume const * , Vector3D<Precision> const & ,
0120 Vector3D<Precision> const & , VPlacedVolume const * ,
0121 Precision & , VPlacedVolume const *& ) const
0122 {
0123 VECGEOM_ASSERT(false);
0124 return false;
0125 }
0126
0127 protected:
0128
0129 VECCORE_ATT_HOST_DEVICE
0130 virtual void Relocate(Vector3D<Precision> const & , NavigationState const &__restrict__ ,
0131 NavigationState &__restrict__ ) const = 0;
0132
0133
0134
0135 VECGEOM_FORCE_INLINE
0136 VECCORE_ATT_HOST_DEVICE
0137 static Vector3D<Precision> MovePointAfterBoundary(Vector3D<Precision> const &localpoint,
0138 Vector3D<Precision> const &dir, Precision step)
0139 {
0140 const Precision extra = 1E-6;
0141 return localpoint + (step + extra) * dir;
0142 }
0143
0144 public:
0145 VECCORE_ATT_DEVICE
0146 virtual ~VNavigator(){};
0147
0148
0149 virtual const char *GetName() const = 0;
0150
0151 typedef VSafetyEstimator SafetyEstimator_t;
0152
0153 protected:
0154 VECCORE_ATT_HOST_DEVICE
0155 VNavigator(VSafetyEstimator *s) : fSafetyEstimator(s) {}
0156 VSafetyEstimator *fSafetyEstimator;
0157
0158
0159 VECGEOM_FORCE_INLINE
0160 VECCORE_ATT_HOST_DEVICE
0161 static Precision PrepareOutState(NavigationState const &__restrict__ in_state,
0162 NavigationState &__restrict__ out_state, Precision geom_step, Precision step_limit,
0163 VPlacedVolume const *hitcandidate, bool &doneafterthisstep)
0164 {
0165
0166 in_state.CopyTo(&out_state);
0167 doneafterthisstep = false;
0168
0169
0170
0171
0172
0173
0174 if (geom_step == kInfLength && step_limit > 0.) {
0175 geom_step = vecgeom::kTolerance;
0176 out_state.SetBoundaryState(true);
0177 do {
0178 out_state.Pop();
0179 } while (out_state.Top()->GetLogicalVolume()->GetUnplacedVolume()->IsAssembly());
0180 doneafterthisstep = true;
0181 return geom_step;
0182 }
0183
0184
0185
0186 if (geom_step > step_limit) {
0187
0188 geom_step = step_limit;
0189 out_state.SetBoundaryState(false);
0190 return geom_step;
0191 }
0192
0193
0194 out_state.SetBoundaryState(true);
0195 out_state.SetLastExited();
0196 if (hitcandidate) out_state.Push(hitcandidate);
0197
0198 if (geom_step < 0.) {
0199
0200
0201 geom_step = 0.;
0202 }
0203 return geom_step;
0204 }
0205
0206
0207 template <typename T>
0208 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static T TreatDistanceToMother(VPlacedVolume const *pvol,
0209 Vector3D<T> const &localpoint,
0210 Vector3D<T> const &localdir, T step_limit)
0211 {
0212 T step;
0213 VECGEOM_VALIDATE(pvol != nullptr, << "currentvolume is null in navigation");
0214 step = pvol->DistanceToOut(localpoint, localdir, step_limit);
0215 vecCore::MaskedAssign(step, step < T(0.), T(0.));
0216 return step;
0217 }
0218
0219
0220
0221
0222
0223
0224
0225
0226 template <typename T>
0227 VECGEOM_FORCE_INLINE VECCORE_ATT_HOST_DEVICE static void DoGlobalToLocalTransformation(
0228 NavigationState const &in_state, Vector3D<T> const &globalpoint, Vector3D<T> const &globaldir,
0229 Vector3D<T> &localpoint, Vector3D<T> &localdir)
0230 {
0231
0232 Transformation3D m;
0233 in_state.TopMatrix(m);
0234 localpoint = m.Transform(globalpoint);
0235 localdir = m.TransformDirection(globaldir);
0236 }
0237 };
0238
0239
0240
0241 template <typename Impl, bool MotherIsConvex = false>
0242 class VNavigatorHelper : public VNavigator {
0243 protected:
0244 using VNavigator::VNavigator;
0245
0246 public:
0247 VECCORE_ATT_HOST_DEVICE
0248 virtual Precision ComputeStepAndPropagatedState(Vector3D<Precision> const &globalpoint,
0249 Vector3D<Precision> const &globaldir, Precision step_limit,
0250 NavigationState const &in_state,
0251 NavigationState &out_state) const override
0252 {
0253 #ifdef DEBUGNAV
0254 static size_t counter = 0;
0255 counter++;
0256 #endif
0257
0258
0259 Vector3D<Precision> localpoint;
0260 Vector3D<Precision> localdir;
0261 Impl::DoGlobalToLocalTransformation(in_state, globalpoint, globaldir, localpoint, localdir);
0262
0263 VPlacedVolume const *hitcandidate = nullptr;
0264 auto pvol = in_state.Top();
0265 auto lvol = pvol->GetLogicalVolume();
0266 Precision step = Impl::TreatDistanceToMother(pvol, localpoint, localdir, step_limit);
0267
0268 if (lvol->GetDaughters().size() > 0)
0269 ((Impl *)this)
0270 ->Impl::CheckDaughterIntersections(lvol, localpoint, localdir, &in_state, &out_state, step, hitcandidate);
0271
0272
0273 bool done;
0274 step = Impl::PrepareOutState(in_state, out_state, step, step_limit, hitcandidate, done);
0275 if (done) {
0276 if (out_state.Top() != nullptr) {
0277 VECGEOM_ASSERT(!out_state.Top()->GetLogicalVolume()->GetUnplacedVolume()->IsAssembly());
0278 }
0279 return step;
0280 }
0281
0282 if (!out_state.IsOnBoundary()) return step;
0283
0284
0285
0286 ((Impl *)this)->Impl::Relocate(MovePointAfterBoundary(localpoint, localdir, step), in_state, out_state);
0287 if (out_state.Top() != nullptr) {
0288 while (out_state.Top()->IsAssembly()) {
0289 out_state.Pop();
0290 }
0291 VECGEOM_ASSERT(!out_state.Top()->GetLogicalVolume()->GetUnplacedVolume()->IsAssembly());
0292 }
0293 return step;
0294 }
0295
0296 virtual Precision ComputeStep(Vector3D<Precision> const &globalpoint, Vector3D<Precision> const &globaldir,
0297 Precision step_limit, NavigationState const &in_state,
0298 NavigationState &out_state) const override
0299 {
0300 #ifdef DEBUGNAV
0301 static size_t counter = 0;
0302 counter++;
0303 #endif
0304
0305
0306 Vector3D<Precision> localpoint;
0307 Vector3D<Precision> localdir;
0308 Impl::DoGlobalToLocalTransformation(in_state, globalpoint, globaldir, localpoint, localdir);
0309
0310 VPlacedVolume const *hitcandidate = nullptr;
0311 auto pvol = in_state.Top();
0312 auto lvol = pvol->GetLogicalVolume();
0313 Precision step = Impl::TreatDistanceToMother(pvol, localpoint, localdir, step_limit);
0314
0315 if (lvol->GetDaughters().size() > 0)
0316 ((Impl *)this)
0317 ->Impl::CheckDaughterIntersections(lvol, localpoint, localdir, &in_state, &out_state, step, hitcandidate);
0318
0319
0320 bool done;
0321 step = Impl::PrepareOutState(in_state, out_state, step, step_limit, hitcandidate, done);
0322 if (done) {
0323 if (out_state.Top() != nullptr) {
0324 VECGEOM_ASSERT(!out_state.Top()->GetLogicalVolume()->GetUnplacedVolume()->IsAssembly());
0325 }
0326 return step;
0327 }
0328
0329 if (!out_state.IsOnBoundary()) return step;
0330
0331 return step;
0332 }
0333
0334 VECCORE_ATT_HOST_DEVICE
0335 virtual Precision ComputeStepAndSafety(Vector3D<Precision> const &globalpoint, Vector3D<Precision> const &globaldir,
0336 Precision step_limit, NavigationState &in_state, bool calcsafety,
0337 Precision &safety, bool indicateDaughterHit = false) const override
0338 {
0339
0340 #ifdef DEBUGNAV
0341 static size_t counter = 0;
0342 counter++;
0343 #endif
0344
0345
0346 Vector3D<Precision> localpoint;
0347 Vector3D<Precision> localdir;
0348 NavigationState *out_state = nullptr;
0349
0350 Impl::DoGlobalToLocalTransformation(in_state, globalpoint, globaldir, localpoint, localdir);
0351
0352
0353 using SafetyE_t = typename Impl::SafetyEstimator_t;
0354 if (calcsafety) {
0355
0356 safety = ((SafetyE_t *)fSafetyEstimator)->SafetyE_t::ComputeSafetyForLocalPoint(localpoint, in_state.Top());
0357 }
0358
0359 VPlacedVolume const *hitcandidate = nullptr;
0360 auto pvol = in_state.Top();
0361 auto lvol = pvol->GetLogicalVolume();
0362 Precision step = step_limit;
0363
0364
0365 bool safetydone = calcsafety && safety >= step;
0366
0367 if (!safetydone) {
0368 step = Impl::TreatDistanceToMother(pvol, localpoint, localdir, step_limit);
0369
0370 if (lvol->GetDaughters().size() > 0)
0371 ((Impl *)this)
0372 ->Impl::CheckDaughterIntersections(lvol, localpoint, localdir, &in_state, out_state, step, hitcandidate);
0373 }
0374 if (indicateDaughterHit && hitcandidate) in_state.Push(hitcandidate);
0375 return Min(step, step_limit);
0376 }
0377
0378
0379
0380 VECCORE_ATT_HOST_DEVICE
0381 virtual Precision ComputeStepAndSafetyAndPropagatedState(Vector3D<Precision> const &globalpoint,
0382 Vector3D<Precision> const &globaldir, Precision step_limit,
0383 NavigationState const &__restrict__ in_state,
0384 NavigationState &__restrict__ out_state, bool calcsafety,
0385 Precision &safety_out) const override
0386 {
0387
0388 Vector3D<Precision> localpoint;
0389 Vector3D<Precision> localdir;
0390 Impl::DoGlobalToLocalTransformation(in_state, globalpoint, globaldir, localpoint, localdir);
0391
0392
0393 using SafetyE_t = typename Impl::SafetyEstimator_t;
0394 safety_out = 0.;
0395 if (calcsafety) {
0396
0397 safety_out = ((SafetyE_t *)fSafetyEstimator)->SafetyE_t::ComputeSafetyForLocalPoint(localpoint, in_state.Top());
0398 }
0399
0400 VPlacedVolume const *hitcandidate = nullptr;
0401 auto pvol = in_state.Top();
0402 auto lvol = pvol->GetLogicalVolume();
0403 Precision step = Impl::TreatDistanceToMother(pvol, localpoint, localdir, step_limit);
0404 ;
0405 if (lvol->GetDaughters().size() > 0)
0406
0407 ((Impl *)this)
0408 ->Impl::CheckDaughterIntersections(lvol, localpoint, localdir, &in_state, &out_state, step, hitcandidate);
0409
0410
0411 bool done;
0412 step = Impl::PrepareOutState(in_state, out_state, step, step_limit, hitcandidate, done);
0413 if (done) return step;
0414
0415
0416 if (!out_state.IsOnBoundary()) return step;
0417
0418
0419
0420 ((Impl *)this)->Impl::Relocate(MovePointAfterBoundary(localpoint, localdir, step), in_state, out_state);
0421 return step;
0422 }
0423
0424 protected:
0425
0426 VECGEOM_FORCE_INLINE
0427 VECCORE_ATT_HOST_DEVICE
0428 virtual void Relocate(Vector3D<Precision> const &pointafterboundary, NavigationState const &__restrict__ in_state,
0429 NavigationState &__restrict__ out_state) const override
0430 {
0431
0432
0433 if (out_state.Top() == in_state.Top()) {
0434 GlobalLocator::RelocatePointFromPathForceDifferent(pointafterboundary, out_state);
0435 #ifdef CHECK_RELOCATION_ERRORS
0436 VECGEOM_VALIDATE(in_state.Distance(out_state) != 0, << " error relocating when leaving ");
0437 #endif
0438 } else {
0439
0440 VPlacedVolume const *nextvol = out_state.Top();
0441 out_state.Pop();
0442 GlobalLocator::LocateGlobalPoint(nextvol, nextvol->GetTransformation()->Transform(pointafterboundary), out_state,
0443 false);
0444 #ifdef CHECK_RELOCATION_ERRORS
0445 VECGEOM_VALIDATE(in_state.Distance(out_state) != 0, << " error relocating when entering ");
0446 #endif
0447 return;
0448 }
0449 }
0450
0451 public:
0452 static const char *GetClassName() { return Impl::gClassNameString; }
0453
0454 virtual const char *GetName() const override { return GetClassName(); }
0455 };
0456 }
0457 }
0458
0459 #endif