diff --git a/Core/include/Acts/Navigation/DetectorNavigator.hpp b/Core/include/Acts/Navigation/DetectorNavigator.hpp index 894238be91b..9fe20519124 100644 --- a/Core/include/Acts/Navigation/DetectorNavigator.hpp +++ b/Core/include/Acts/Navigation/DetectorNavigator.hpp @@ -36,7 +36,10 @@ class DetectorNavigator { struct Config { /// Detector for this Navigation const Detector* detector = nullptr; - + /// The octree for the world + const BoundingBox* topBox = nullptr; + /// The current frustum + std::shared_ptr frustum = nullptr; /// Configuration for this Navigator /// stop at every sensitive surface (whether it has material or not) bool resolveSensitive = true; diff --git a/Core/include/Acts/Navigation/InternalNavigation.hpp b/Core/include/Acts/Navigation/InternalNavigation.hpp index 4301676e1c5..e63034e4269 100644 --- a/Core/include/Acts/Navigation/InternalNavigation.hpp +++ b/Core/include/Acts/Navigation/InternalNavigation.hpp @@ -92,6 +92,64 @@ struct AllPortalsAndSurfacesNavigation : public IInternalNavigation { } }; +struct FrustumNavigation : public IInternalNavigation { + /// The frustum navigation + /// + /// @param gctx is the Geometry context of this call + /// @param nState is the navigation state to be updated + /// + /// @note that the intersections are ordered, such that the + /// smallest intersection pathlength >= overstep tolerance is the lowest + /// + /// @return an ordered list of portal and surface candidates + inline void update(const GeometryContext& gctx, + NavigationState& nState) const { + if (nState.currentDetector == nullptr) { + throw std::runtime_error( + "FrustumNavigation: no detector volume set to navigation state."); + } + // Create the frustum if it's not set + if (nState.frustum == nullptr) { + nState.frustum = std::make_shared(nState.position, nState.direction, M_PI/4); + } + //Check if we leave the frustum, reset candidates if so + const auto& normals = nState.frustum->normals(); + const bool outside = std::any_of(normals.begin(), normals.end(), [&nState](const auto& normal){ + return (nState.position - nState.frustum->origin()).dot(normal) >= 0;}); + if(outside){ + nState.surfaceCandidates.clear(); + nState.frustum = std::make_shared(nState.position, nState.direction, M_PI/4); + } + // A volume switch has happened, or we left the frustum, update list of portals & surfaces + if (nState.surfaceCandidates.empty()) { + // Fill internal portals if existing + auto topBoxCopy = nState.topBox; + while(topBoxCopy){ + if(topBoxCopy->intersect(*nState.frustum)){ + if(topBoxCopy->hasEntity()){ + const auto& portals = topBoxCopy->entity()->portals(); + const auto& surfaces = topBoxCopy->entity()->surfaces(); + PortalsFiller::fill(nState, portals); + SurfacesFiller::fill(nState, surfaces); + topBoxCopy = topBoxCopy->getSkip(); + } else { + topBoxCopy = topBoxCopy->getLeftChild(); + } + } else { + topBoxCopy = topBoxCopy->getSkip(); + } + } + } + // Assign the new volume + const auto& portals = nState.currentVolume->portals(); + const auto& surfaces = nState.currentVolume->surfaces(); + PortalsFiller::fill(nState, portals); + SurfacesFiller::fill(nState, surfaces); + // Update internal candidates + updateCandidates(gctx, nState); + } +}; + /// Generate a provider for all portals /// /// @return a connected navigationstate updator @@ -116,6 +174,16 @@ inline static InternalNavigationDelegate tryAllPortalsAndSurfaces() { return nStateUpdater; } +/// Generate a provider for portals and surfaces inside a frustum +/// +/// @return a connected navigationstate updator +inline static InternalNavigationDelegate tryFrustumPortalsAndSurfaces() { + auto fr = std::make_unique(); + InternalNavigationDelegate nStateUpdater; + nStateUpdater.connect<&FrustumNavigation::update>(std::move(fr)); + return nStateUpdater; +} + /// @brief This holds and extracts a collection of surfaces without much /// checking, this could be e.g. support surfaces for layer structures, /// e.g. diff --git a/Core/include/Acts/Navigation/NavigationState.hpp b/Core/include/Acts/Navigation/NavigationState.hpp index 1cd752d940a..ddafa69e405 100644 --- a/Core/include/Acts/Navigation/NavigationState.hpp +++ b/Core/include/Acts/Navigation/NavigationState.hpp @@ -80,6 +80,11 @@ struct NavigationState { /// The current portal, i.e the position is on portal const Portal* currentPortal = nullptr; + /// The octree for the world + const BoundingBox* topBox = nullptr; + /// The current frustum + std::shared_ptr frustum = nullptr; + /// That are the candidate surfaces to process SurfaceCandidates surfaceCandidates = {}; std::size_t surfaceCandidateIndex = 0;