File indexing completed on 2026-10-14 08:13:28
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Navigation/FrustumNavigationPolicy.hpp"
0010
0011 #include "Acts/Geometry/TrivialPortalLink.hpp"
0012
0013 namespace Acts::Experimental {
0014
0015 namespace {
0016
0017
0018
0019
0020
0021 bool leadsOutside(const PortalLinkBase *link, const TrackingVolume &volume) {
0022 const auto *trivialLink = dynamic_cast<const TrivialPortalLink *>(link);
0023 if (trivialLink == nullptr) {
0024 return false;
0025 }
0026
0027 const TrackingVolume *volumeLink = &trivialLink->volume();
0028 if (volumeLink == &volume || volumeLink->motherVolume() == &volume) {
0029 return false;
0030 }
0031 return true;
0032 }
0033
0034 }
0035
0036 FrustumNavigationPolicy::FrustumNavigationPolicy(const GeometryContext &gctx,
0037 const TrackingVolume &volume,
0038 const Logger &logger,
0039 const Config &config) {
0040 ACTS_VERBOSE("Constructing FrustumNavigationPolicy for volume "
0041 << volume.volumeName());
0042 m_id = volume.geometryId();
0043 std::vector<BoundingBox *> prims;
0044 m_boxes.push_back(std::make_unique<BoundingBox>(volume.boundingBox(gctx)));
0045 prims.push_back(m_boxes.back().get());
0046 for (auto &vol : volume.volumes()) {
0047 ACTS_VERBOSE("add volume " << vol.volumeName()
0048 << " to list of bounding boxes");
0049 m_boxes.push_back(std::make_unique<BoundingBox>(vol.boundingBox(gctx)));
0050 prims.push_back(m_boxes.back().get());
0051 }
0052 m_topBox =
0053 Acts::BoundingBoxHierarchy::makeOctree(m_boxes, prims, config.depth);
0054
0055 for (const auto &portal : volume.portals()) {
0056 if (leadsOutside(portal.getLink(Direction::AlongNormal()), volume) ||
0057 leadsOutside(portal.getLink(Direction::OppositeNormal()), volume)) {
0058 m_cachedPortals.push_back(&portal);
0059 }
0060 }
0061 }
0062
0063 void FrustumNavigationPolicy::initializeCandidates(
0064 const GeometryContext & , const NavigationArguments &args,
0065 NavigationPolicyState &state, AppendOnlyNavigationStream &stream,
0066 const Logger &logger) const {
0067 ACTS_VERBOSE("FrustumNavigationPolicy Candidates initialization for volume "
0068 << m_id);
0069 auto &s = state.as<State>();
0070
0071 s.frustum = Frustum3(args.position, args.direction, s.openingAngle);
0072 Frustum3 frustum = s.frustum;
0073 ACTS_VERBOSE("Frustum origin " << s.frustum.origin() << ", frustum dir "
0074 << s.frustum.dir());
0075 Acts::BoundingBoxHierarchy::visitIntersecting(
0076 frustum, m_topBox, [this, &stream, &logger](const Volume &entity) {
0077 const TrackingVolume *tvol =
0078 dynamic_cast<const TrackingVolume *>(&entity);
0079 ACTS_VERBOSE("Get portals from volume " << tvol->volumeName());
0080 if (tvol->geometryId() == m_id) {
0081 for (const Portal *portal : m_cachedPortals) {
0082 stream.addPortalCandidate(*portal);
0083 }
0084 } else {
0085 for (const auto &portal : tvol->portals()) {
0086 stream.addPortalCandidate(portal);
0087 }
0088 }
0089 });
0090 ACTS_VERBOSE(
0091 "FrustumNavigationPolicy Candidates initialization done for volume "
0092 << this->m_id);
0093 }
0094
0095 void FrustumNavigationPolicy::connect(NavigationDelegate &delegate) const {
0096 connectDefault<FrustumNavigationPolicy>(delegate);
0097 }
0098
0099 bool FrustumNavigationPolicy::isValid(const GeometryContext & ,
0100 const NavigationArguments &args,
0101 NavigationPolicyState &state,
0102 const Logger &logger) const {
0103
0104 auto &s = state.as<State>();
0105 double costheta =
0106 args.position.normalized().dot(s.frustum.origin().normalized());
0107
0108 if (costheta < std::cos(s.openingAngle / 2)) {
0109 ACTS_DEBUG("FrustumNavigationPolicy: outside frustum");
0110 return false;
0111 } else {
0112 ACTS_DEBUG("FrustumNavigationPolicy: frustum still ok");
0113 return true;
0114 }
0115 }
0116
0117 void FrustumNavigationPolicy::createState(
0118 const GeometryContext & , const NavigationArguments &args,
0119 NavigationPolicyStateManager &stateManager, const Logger &logger) const {
0120 ACTS_DEBUG("create FrustumNavigationPolicy state");
0121 auto &s = stateManager.pushState<State>();
0122 s.openingAngle = std::numbers::pi / 4;
0123 s.frustum = Frustum3(args.position, args.direction, s.openingAngle);
0124 }
0125
0126 void FrustumNavigationPolicy::popState(
0127 NavigationPolicyStateManager &stateManager, const Logger &logger) const {
0128 ACTS_DEBUG("remove FrustumNavigationPolicy state");
0129 stateManager.popState();
0130 }
0131 }