Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /acts/Core/src/Geometry/Layer.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include "Acts/Geometry/Layer.hpp"
0010 
0011 #include "Acts/Material/IMaterialDecorator.hpp"
0012 #include "Acts/Propagator/Navigator.hpp"
0013 #include "Acts/Surfaces/BoundaryTolerance.hpp"
0014 #include "Acts/Surfaces/Surface.hpp"
0015 #include "Acts/Utilities/Helpers.hpp"
0016 #include "Acts/Utilities/Intersection.hpp"
0017 
0018 #include <algorithm>
0019 #include <vector>
0020 
0021 namespace Acts {
0022 
0023 Layer::Layer(std::unique_ptr<SurfaceArray> surfaceArray, double thickness,
0024              std::unique_ptr<ApproachDescriptor> ades, LayerType laytyp)
0025     : m_nextLayers(NextLayers(nullptr, nullptr)),
0026       m_surfaceArray(surfaceArray.release()),
0027       m_layerThickness(thickness),
0028       m_approachDescriptor(nullptr),
0029       m_representingVolume(nullptr),
0030       m_layerType(laytyp),
0031       m_ssRepresentingSurface(1) {
0032   if (ades) {
0033     ades->registerLayer(*this);
0034     m_approachDescriptor = std::move(ades);
0035     m_ssApproachSurfaces = 1;  // indicates existence
0036   }
0037   // indicates existence of sensitive surfaces
0038   if (m_surfaceArray) {
0039     m_ssSensitiveSurfaces = 1;
0040   }
0041 }
0042 
0043 const ApproachDescriptor* Layer::approachDescriptor() const {
0044   return m_approachDescriptor.get();
0045 }
0046 
0047 ApproachDescriptor* Layer::approachDescriptor() {
0048   return const_cast<ApproachDescriptor*>(m_approachDescriptor.get());
0049 }
0050 
0051 void Layer::closeGeometry(const IMaterialDecorator* materialDecorator,
0052                           const GeometryIdentifier& layerID,
0053                           const GeometryIdentifierHook& hook,
0054                           const Logger& logger) {
0055   // set the volumeID of this
0056   assignGeometryId(layerID);
0057   // assign to the representing surface
0058   Surface* rSurface = const_cast<Surface*>(&surfaceRepresentation());
0059   if (materialDecorator != nullptr) {
0060     materialDecorator->decorate(*rSurface);
0061   }
0062   ACTS_DEBUG("layerID: " << layerID);
0063 
0064   rSurface->assignGeometryId(layerID);
0065 
0066   // also find out how the sub structure is defined
0067   if (surfaceRepresentation().surfaceMaterial() != nullptr) {
0068     m_ssRepresentingSurface = 2;
0069   }
0070   // loop over the approach surfaces
0071   if (m_approachDescriptor) {
0072     // indicates the existence of approach surfaces
0073     m_ssApproachSurfaces = 1;
0074     // loop through the approachSurfaces and assign unique GeomeryID
0075     GeometryIdentifier::Value iasurface = 0;
0076     for (auto& aSurface : m_approachDescriptor->containedSurfaces()) {
0077       auto asurfaceID = GeometryIdentifier(layerID).withApproach(++iasurface);
0078       auto mutableASurface = const_cast<Surface*>(aSurface);
0079       mutableASurface->assignGeometryId(asurfaceID);
0080       if (materialDecorator != nullptr) {
0081         materialDecorator->decorate(*mutableASurface);
0082       }
0083       // if any of the approach surfaces has material
0084       if (aSurface->surfaceMaterial() != nullptr) {
0085         m_ssApproachSurfaces = 2;
0086       }
0087     }
0088   }
0089   // check if you have sensitive surfaces
0090   if (m_surfaceArray) {
0091     // indicates the existence of sensitive surfaces
0092     m_ssSensitiveSurfaces = 1;
0093     // loop sensitive surfaces and assign unique GeometryIdentifier
0094     GeometryIdentifier::Value issurface = 0;
0095     for (auto& sSurface : m_surfaceArray->surfaces()) {
0096       auto ssurfaceID = GeometryIdentifier(layerID).withSensitive(++issurface);
0097       ssurfaceID = hook.decorateIdentifier(ssurfaceID, *sSurface);
0098       auto mutableSSurface = const_cast<Surface*>(sSurface);
0099       mutableSSurface->assignGeometryId(ssurfaceID);
0100       if (materialDecorator != nullptr) {
0101         materialDecorator->decorate(*mutableSSurface);
0102       }
0103       // if any of the sensitive surfaces has material
0104       if (sSurface->surfaceMaterial() != nullptr) {
0105         m_ssSensitiveSurfaces = 2;
0106       }
0107     }
0108   }
0109 }
0110 
0111 boost::container::small_vector<SurfaceIntersection, 10>
0112 Layer::compatibleSurfaces(const GeometryContext& gctx, const Vector3& position,
0113                           const Vector3& direction,
0114                           const NavigationOptions<Surface>& options) const {
0115   // the list of valid intersection
0116   boost::container::small_vector<SurfaceIntersection, 10> sIntersections;
0117 
0118   // fast exit - there is nothing to
0119   if (!m_surfaceArray || !m_approachDescriptor) {
0120     return sIntersections;
0121   }
0122 
0123   double nearLimit = options.nearLimit;
0124   double farLimit = options.farLimit;
0125 
0126   auto isUnique = [&](const SurfaceIntersection& b) {
0127     return std::ranges::none_of(sIntersections, [&b](const auto& a) {
0128       return a.object() == b.object() && a.index() == b.index();
0129     });
0130   };
0131 
0132   // lemma 0 : accept the surface
0133   auto acceptSurface = [&options](const Surface& sf,
0134                                   bool sensitive = false) -> bool {
0135     // surface is sensitive and you're asked to resolve
0136     if (sensitive && options.resolveSensitive) {
0137       return true;
0138     }
0139     // next option: it's a material surface, and you want to have it
0140     if (options.resolveMaterial && sf.surfaceMaterial() != nullptr) {
0141       return true;
0142     }
0143     // last option: resolve all
0144     return options.resolvePassive;
0145   };
0146 
0147   // lemma 1 : check and fill the surface
0148   // [&sIntersections, &options, &parameters
0149   auto processSurface = [&](const Surface& sf, bool sensitive = false) {
0150     // veto if it's start surface
0151     if (options.startObject == &sf) {
0152       return;
0153     }
0154     // veto if it doesn't fit the prescription
0155     if (!acceptSurface(sf, sensitive)) {
0156       return;
0157     }
0158     BoundaryTolerance boundaryTolerance = options.boundaryTolerance;
0159     if (rangeContainsValue(options.externalSurfaces, sf.geometryId())) {
0160       boundaryTolerance = BoundaryTolerance::Infinite();
0161     }
0162     // the surface intersection
0163     SurfaceIntersection sfi =
0164         sf.intersect(gctx, position, direction, boundaryTolerance).closest();
0165     if (sfi.isValid() &&
0166         detail::checkPathLength(sfi.pathLength(), nearLimit, farLimit) &&
0167         isUnique(sfi)) {
0168       sIntersections.push_back(sfi);
0169     }
0170   };
0171 
0172   // (A) approach descriptor section
0173   //
0174   // the approach surfaces are in principle always testSurfaces
0175   // - the surface on approach is excluded via the veto
0176   // - the surfaces are only collected if needed
0177   if (m_approachDescriptor &&
0178       (options.resolveMaterial || options.resolvePassive)) {
0179     // the approach surfaces
0180     const std::vector<const Surface*>& approachSurfaces =
0181         m_approachDescriptor->containedSurfaces();
0182     // we loop through and veto
0183     // - if the approach surface is the parameter surface
0184     // - if the surface is not compatible with the collect
0185     for (auto& aSurface : approachSurfaces) {
0186       processSurface(*aSurface);
0187     }
0188   }
0189 
0190   // (B) sensitive surface section
0191   //
0192   // check the sensitive surfaces if you have some
0193   if (m_surfaceArray && (options.resolveMaterial || options.resolvePassive ||
0194                          options.resolveSensitive)) {
0195     // get the candidates
0196     const std::vector<const Surface*>& sensitiveSurfaces =
0197         m_surfaceArray->neighbors(position);
0198     // loop through and veto
0199     // - if the approach surface is the parameter surface
0200     // - if the surface is not compatible with the type(s) that are collected
0201     for (auto& sSurface : sensitiveSurfaces) {
0202       processSurface(*sSurface, true);
0203     }
0204   }
0205 
0206   // (C) representing surface section
0207   //
0208   // the layer surface itself is a testSurface
0209   const Surface* layerSurface = &surfaceRepresentation();
0210   processSurface(*layerSurface);
0211 
0212   return sIntersections;
0213 }
0214 
0215 SurfaceIntersection Layer::surfaceOnApproach(
0216     const GeometryContext& gctx, const Vector3& position,
0217     const Vector3& direction, const NavigationOptions<Layer>& options) const {
0218   // resolve directive based by options
0219   // - options.resolvePassive is on -> always
0220   // - options.resolveSensitive is on -> always
0221   // - options.resolveMaterial is on
0222   //   && either sensitive or approach surfaces have material
0223   bool resolvePS = options.resolveSensitive || options.resolvePassive;
0224   bool resolveMS = options.resolveMaterial &&
0225                    (m_ssSensitiveSurfaces > 1 || m_ssApproachSurfaces > 1 ||
0226                     (surfaceRepresentation().surfaceMaterial() != nullptr));
0227 
0228   // The Limits
0229   double nearLimit = options.nearLimit;
0230   double farLimit = options.farLimit;
0231 
0232   // Helper function to find valid intersection
0233   auto findValidIntersection =
0234       [&](const SurfaceMultiIntersection& sfmi) -> SurfaceIntersection {
0235     for (const auto& sfi : sfmi.split()) {
0236       if (sfi.isValid() &&
0237           detail::checkPathLength(sfi.pathLength(), nearLimit, farLimit)) {
0238         return sfi;
0239       }
0240     }
0241 
0242     // Return an invalid one
0243     return SurfaceIntersection::invalid();
0244   };
0245 
0246   // Approach descriptor present and resolving is necessary
0247   if (m_approachDescriptor && (resolvePS || resolveMS)) {
0248     SurfaceIntersection aSurface = m_approachDescriptor->approachSurface(
0249         gctx, position, direction, options.boundaryTolerance, nearLimit,
0250         farLimit);
0251     return aSurface;
0252   }
0253 
0254   // Intersect and check the representing surface
0255   const Surface& rSurface = surfaceRepresentation();
0256   auto sIntersection =
0257       rSurface.intersect(gctx, position, direction, options.boundaryTolerance);
0258   return findValidIntersection(sIntersection);
0259 }
0260 
0261 }  // namespace Acts