File indexing completed on 2025-09-13 08:13:13
0001
0002
0003
0004
0005
0006
0007
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/Surfaces/SurfaceArray.hpp"
0016 #include "Acts/Utilities/Helpers.hpp"
0017 #include "Acts/Utilities/Intersection.hpp"
0018
0019 #include <algorithm>
0020 #include <vector>
0021
0022 namespace Acts {
0023
0024 Layer::Layer(std::unique_ptr<SurfaceArray> surfaceArray, double thickness,
0025 std::unique_ptr<ApproachDescriptor> ades, LayerType laytyp)
0026 : m_nextLayers(NextLayers(nullptr, nullptr)),
0027 m_surfaceArray(surfaceArray.release()),
0028 m_layerThickness(thickness),
0029 m_approachDescriptor(nullptr),
0030 m_representingVolume(nullptr),
0031 m_layerType(laytyp),
0032 m_ssRepresentingSurface(1) {
0033 if (ades) {
0034 ades->registerLayer(*this);
0035 m_approachDescriptor = std::move(ades);
0036 m_ssApproachSurfaces = 1;
0037 }
0038
0039 if (m_surfaceArray) {
0040 m_ssSensitiveSurfaces = 1;
0041 }
0042 }
0043
0044 Layer::~Layer() noexcept = default;
0045
0046 const ApproachDescriptor* Layer::approachDescriptor() const {
0047 return m_approachDescriptor.get();
0048 }
0049
0050 ApproachDescriptor* Layer::approachDescriptor() {
0051 return const_cast<ApproachDescriptor*>(m_approachDescriptor.get());
0052 }
0053
0054 void Layer::closeGeometry(const IMaterialDecorator* materialDecorator,
0055 const GeometryIdentifier& layerID,
0056 const GeometryIdentifierHook& hook,
0057 const Logger& logger) {
0058
0059 assignGeometryId(layerID);
0060
0061 Surface* rSurface = const_cast<Surface*>(&surfaceRepresentation());
0062 if (materialDecorator != nullptr) {
0063 materialDecorator->decorate(*rSurface);
0064 }
0065 ACTS_DEBUG("layerID: " << layerID);
0066
0067 rSurface->assignGeometryId(layerID);
0068
0069
0070 if (surfaceRepresentation().surfaceMaterial() != nullptr) {
0071 m_ssRepresentingSurface = 2;
0072 }
0073
0074 if (m_approachDescriptor) {
0075
0076 m_ssApproachSurfaces = 1;
0077
0078 GeometryIdentifier::Value iasurface = 0;
0079 for (auto& aSurface : m_approachDescriptor->containedSurfaces()) {
0080 auto asurfaceID = GeometryIdentifier(layerID).withApproach(++iasurface);
0081 auto mutableASurface = const_cast<Surface*>(aSurface);
0082 mutableASurface->assignGeometryId(asurfaceID);
0083 if (materialDecorator != nullptr) {
0084 materialDecorator->decorate(*mutableASurface);
0085 }
0086
0087 if (aSurface->surfaceMaterial() != nullptr) {
0088 m_ssApproachSurfaces = 2;
0089 }
0090 }
0091 }
0092
0093 if (m_surfaceArray) {
0094
0095 m_ssSensitiveSurfaces = 1;
0096
0097 GeometryIdentifier::Value issurface = 0;
0098 for (auto& sSurface : m_surfaceArray->surfaces()) {
0099 auto ssurfaceID = GeometryIdentifier(layerID).withSensitive(++issurface);
0100 ssurfaceID = hook.decorateIdentifier(ssurfaceID, *sSurface);
0101 auto mutableSSurface = const_cast<Surface*>(sSurface);
0102 mutableSSurface->assignGeometryId(ssurfaceID);
0103 if (materialDecorator != nullptr) {
0104 materialDecorator->decorate(*mutableSSurface);
0105 }
0106
0107 if (sSurface->surfaceMaterial() != nullptr) {
0108 m_ssSensitiveSurfaces = 2;
0109 }
0110 }
0111 }
0112 }
0113
0114 boost::container::small_vector<SurfaceIntersection, 10>
0115 Layer::compatibleSurfaces(const GeometryContext& gctx, const Vector3& position,
0116 const Vector3& direction,
0117 const NavigationOptions<Surface>& options) const {
0118
0119 boost::container::small_vector<SurfaceIntersection, 10> sIntersections;
0120
0121
0122 if (!m_surfaceArray || !m_approachDescriptor) {
0123 return sIntersections;
0124 }
0125
0126 double nearLimit = options.nearLimit;
0127 double farLimit = options.farLimit;
0128
0129 auto isUnique = [&](const SurfaceIntersection& b) {
0130 return std::ranges::none_of(sIntersections, [&b](const auto& a) {
0131 return &a.surface() == &b.surface() && a.index() == b.index();
0132 });
0133 };
0134
0135
0136 auto acceptSurface = [&options](const Surface& sf,
0137 bool sensitive = false) -> bool {
0138
0139 if (sensitive && options.resolveSensitive) {
0140 return true;
0141 }
0142
0143 if (options.resolveMaterial && sf.surfaceMaterial() != nullptr) {
0144 return true;
0145 }
0146
0147 return options.resolvePassive;
0148 };
0149
0150
0151
0152 auto processSurface = [&](const Surface& sf, bool sensitive = false) {
0153
0154 if (options.startObject == &sf) {
0155 return;
0156 }
0157
0158 if (!acceptSurface(sf, sensitive)) {
0159 return;
0160 }
0161 BoundaryTolerance boundaryTolerance = options.boundaryTolerance;
0162 if (rangeContainsValue(options.externalSurfaces, sf.geometryId())) {
0163 boundaryTolerance = BoundaryTolerance::Infinite();
0164 }
0165
0166 SurfaceIntersection sfi =
0167 sf.intersect(gctx, position, direction, boundaryTolerance).closest();
0168 if (sfi.isValid() &&
0169 detail::checkPathLength(sfi.pathLength(), nearLimit, farLimit) &&
0170 isUnique(sfi)) {
0171 sIntersections.push_back(sfi);
0172 }
0173 };
0174
0175
0176
0177
0178
0179
0180 if (m_approachDescriptor &&
0181 (options.resolveMaterial || options.resolvePassive)) {
0182
0183 const std::vector<const Surface*>& approachSurfaces =
0184 m_approachDescriptor->containedSurfaces();
0185
0186
0187
0188 for (auto& aSurface : approachSurfaces) {
0189 processSurface(*aSurface);
0190 }
0191 }
0192
0193
0194
0195
0196 if (m_surfaceArray && (options.resolveMaterial || options.resolvePassive ||
0197 options.resolveSensitive)) {
0198 Vector3 lookupPosition = position;
0199
0200
0201
0202 if (SurfaceIntersection intersection =
0203 surfaceRepresentation()
0204 .intersect(gctx, position, direction)
0205 .closest();
0206 intersection.isValid()) {
0207 lookupPosition = intersection.position();
0208 }
0209
0210
0211 const std::vector<const Surface*>& sensitiveSurfaces =
0212 m_surfaceArray->neighbors(lookupPosition);
0213
0214
0215
0216 for (auto& sSurface : sensitiveSurfaces) {
0217 processSurface(*sSurface, true);
0218 }
0219 }
0220
0221
0222
0223
0224 const Surface* layerSurface = &surfaceRepresentation();
0225 processSurface(*layerSurface);
0226
0227 return sIntersections;
0228 }
0229
0230 SurfaceIntersection Layer::surfaceOnApproach(
0231 const GeometryContext& gctx, const Vector3& position,
0232 const Vector3& direction, const NavigationOptions<Layer>& options) const {
0233
0234
0235
0236
0237
0238 bool resolvePS = options.resolveSensitive || options.resolvePassive;
0239 bool resolveMS = options.resolveMaterial &&
0240 (m_ssSensitiveSurfaces > 1 || m_ssApproachSurfaces > 1 ||
0241 (surfaceRepresentation().surfaceMaterial() != nullptr));
0242
0243
0244 double nearLimit = options.nearLimit;
0245 double farLimit = options.farLimit;
0246
0247
0248 auto findValidIntersection =
0249 [&](const SurfaceMultiIntersection& sfmi) -> SurfaceIntersection {
0250 for (const auto& sfi : sfmi.split()) {
0251 if (sfi.isValid() &&
0252 detail::checkPathLength(sfi.pathLength(), nearLimit, farLimit)) {
0253 return sfi;
0254 }
0255 }
0256
0257
0258 return SurfaceIntersection::invalid();
0259 };
0260
0261
0262 if (m_approachDescriptor && (resolvePS || resolveMS)) {
0263 SurfaceIntersection aSurface = m_approachDescriptor->approachSurface(
0264 gctx, position, direction, options.boundaryTolerance, nearLimit,
0265 farLimit);
0266 return aSurface;
0267 }
0268
0269
0270 const Surface& rSurface = surfaceRepresentation();
0271 auto sIntersection =
0272 rSurface.intersect(gctx, position, direction, options.boundaryTolerance);
0273 return findValidIntersection(sIntersection);
0274 }
0275
0276 }