File indexing completed on 2025-01-18 09:11:18
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Detector/DetectorVolume.hpp"
0010
0011 #include "Acts/Definitions/Direction.hpp"
0012 #include "Acts/Detector/Portal.hpp"
0013 #include "Acts/Geometry/Polyhedron.hpp"
0014 #include "Acts/Geometry/VolumeBounds.hpp"
0015 #include "Acts/Navigation/DetectorVolumeFinders.hpp"
0016 #include "Acts/Navigation/NavigationState.hpp"
0017 #include "Acts/Navigation/PortalNavigation.hpp"
0018 #include "Acts/Surfaces/Surface.hpp"
0019 #include "Acts/Utilities/Delegate.hpp"
0020 #include "Acts/Utilities/Enumerate.hpp"
0021
0022 #include <cassert>
0023 #include <iterator>
0024
0025 namespace Acts {
0026 class IVolumeMaterial;
0027 }
0028
0029 Acts::Experimental::DetectorVolume::DetectorVolume(
0030 const GeometryContext& gctx, std::string name, const Transform3& transform,
0031 std::shared_ptr<VolumeBounds> bounds,
0032 std::vector<std::shared_ptr<Surface>> surfaces,
0033 std::vector<std::shared_ptr<DetectorVolume>> volumes,
0034 ExternalNavigationDelegate externalNavigation,
0035 InternalNavigationDelegate internalNavigation)
0036 : m_name(std::move(name)),
0037 m_transform(transform),
0038 m_bounds(std::move(bounds)),
0039 m_surfaces(std::move(surfaces)),
0040 m_volumes(std::move(volumes)),
0041 m_externalNavigation(std::move(externalNavigation)),
0042 m_internalNavigation(std::move(internalNavigation)),
0043 m_volumeMaterial(nullptr) {
0044 if (m_bounds == nullptr) {
0045 throw std::invalid_argument(
0046 "DetectorVolume: construction with nullptr bounds.");
0047 }
0048 if (!m_externalNavigation.connected()) {
0049 throw std::invalid_argument(
0050 "DetectorVolume: external navigation delegate is not connected.");
0051 }
0052 if (!m_internalNavigation.connected()) {
0053 throw std::invalid_argument(
0054 "DetectorVolume: internal navigaiton delegate is not connected.");
0055 }
0056
0057 [[maybe_unused]] const auto& gctx_ref = gctx;
0058 }
0059
0060 Acts::Experimental::DetectorVolume::DetectorVolume(
0061 const GeometryContext& gctx, std::string name, const Transform3& transform,
0062 std::shared_ptr<VolumeBounds> bounds,
0063 InternalNavigationDelegate internalNavigation)
0064 : DetectorVolume(gctx, std::move(name), transform, std::move(bounds), {},
0065 {}, tryNoVolumes(), std::move(internalNavigation)) {}
0066
0067 std::shared_ptr<Acts::Experimental::DetectorVolume>
0068 Acts::Experimental::DetectorVolume::makeShared(
0069 const GeometryContext& gctx, std::string name, const Transform3& transform,
0070 std::shared_ptr<VolumeBounds> bounds,
0071 std::vector<std::shared_ptr<Surface>> surfaces,
0072 std::vector<std::shared_ptr<DetectorVolume>> volumes,
0073 ExternalNavigationDelegate externalNavigation,
0074 InternalNavigationDelegate internalNavigation) {
0075 return std::shared_ptr<DetectorVolume>(new DetectorVolume(
0076 gctx, std::move(name), transform, std::move(bounds), std::move(surfaces),
0077 std::move(volumes), std::move(externalNavigation),
0078 std::move(internalNavigation)));
0079 }
0080
0081 std::shared_ptr<Acts::Experimental::DetectorVolume>
0082 Acts::Experimental::DetectorVolume::makeShared(
0083 const GeometryContext& gctx, std::string name, const Transform3& transform,
0084 std::shared_ptr<VolumeBounds> bounds,
0085 InternalNavigationDelegate internalNavigation) {
0086 return std::shared_ptr<DetectorVolume>(
0087 new DetectorVolume(gctx, std::move(name), transform, std::move(bounds),
0088 std::move(internalNavigation)));
0089 }
0090
0091 const Acts::Transform3& Acts::Experimental::DetectorVolume::transform(
0092 const GeometryContext& ) const {
0093 return m_transform;
0094 }
0095
0096 Acts::Vector3 Acts::Experimental::DetectorVolume::center(
0097 const GeometryContext& gctx) const {
0098 return transform(gctx).translation();
0099 }
0100
0101 const Acts::VolumeBounds& Acts::Experimental::DetectorVolume::volumeBounds()
0102 const {
0103 return (*m_bounds.get());
0104 }
0105
0106 std::vector<std::shared_ptr<Acts::Experimental::Portal>>&
0107 Acts::Experimental::DetectorVolume::portalPtrs() {
0108 return m_portals.internal;
0109 }
0110
0111 std::vector<std::shared_ptr<Acts::Surface>>&
0112 Acts::Experimental::DetectorVolume::surfacePtrs() {
0113 return m_surfaces.internal;
0114 }
0115
0116 std::vector<std::shared_ptr<Acts::Experimental::DetectorVolume>>&
0117 Acts::Experimental::DetectorVolume::volumePtrs() {
0118 return m_volumes.internal;
0119 }
0120
0121 const std::vector<const Acts::Experimental::Portal*>&
0122 Acts::Experimental::DetectorVolume::portals() const {
0123 return m_portals.external;
0124 }
0125
0126 const std::vector<const Acts::Surface*>&
0127 Acts::Experimental::DetectorVolume::surfaces() const {
0128 return m_surfaces.external;
0129 }
0130
0131 const std::vector<const Acts::Experimental::DetectorVolume*>&
0132 Acts::Experimental::DetectorVolume::volumes() const {
0133 return m_volumes.external;
0134 }
0135
0136 const Acts::Experimental::ExternalNavigationDelegate&
0137 Acts::Experimental::DetectorVolume::externalNavigation() const {
0138 return m_externalNavigation;
0139 }
0140
0141 const Acts::Experimental::InternalNavigationDelegate&
0142 Acts::Experimental::DetectorVolume::internalNavigation() const {
0143 return m_internalNavigation;
0144 }
0145
0146 void Acts::Experimental::DetectorVolume::assignVolumeMaterial(
0147 std::shared_ptr<const IVolumeMaterial> material) {
0148 m_volumeMaterial = std::move(material);
0149 }
0150
0151 const Acts::IVolumeMaterial*
0152 Acts::Experimental::DetectorVolume::volumeMaterial() const {
0153 return m_volumeMaterial.get();
0154 }
0155
0156 const Acts::GeometryIdentifier& Acts::Experimental::DetectorVolume::geometryId()
0157 const {
0158 return m_geometryId;
0159 }
0160
0161 void Acts::Experimental::DetectorVolume::assignGeometryId(
0162 const GeometryIdentifier& geoID) {
0163 m_geometryId = geoID;
0164 }
0165
0166 const std::string& Acts::Experimental::DetectorVolume::name() const {
0167 return m_name;
0168 }
0169
0170 void Acts::Experimental::DetectorVolume::assignDetector(
0171 const Detector& detector) {
0172 m_detector = &detector;
0173
0174 for (auto& v : m_volumes.internal) {
0175 v->assignDetector(detector);
0176 }
0177 }
0178
0179 const Acts::Experimental::Detector*
0180 Acts::Experimental::DetectorVolume::detector() const {
0181 return m_detector;
0182 }
0183
0184 void Acts::Experimental::DetectorVolume::updatePortal(
0185 std::shared_ptr<Portal> portal, unsigned int pIndex) {
0186 if (pIndex >= m_portals.internal.size()) {
0187 throw std::invalid_argument(
0188 "DetectorVolume: trying to update a portal that does not exist.");
0189 }
0190 m_portals.internal[pIndex] = std::move(portal);
0191 m_portals = ObjectStore<std::shared_ptr<Portal>>(m_portals.internal);
0192 }
0193
0194 void Acts::Experimental::DetectorVolume::construct(
0195 const GeometryContext& gctx, const PortalGenerator& portalGenerator) {
0196
0197 auto portalSurfaces =
0198 portalGenerator(transform(gctx), *(m_bounds.get()), getSharedPtr());
0199 m_portals = ObjectStore<std::shared_ptr<Portal>>(portalSurfaces);
0200 createBoundingBox(gctx);
0201 }
0202
0203 std::shared_ptr<Acts::Experimental::DetectorVolume>
0204 Acts::Experimental::DetectorVolume::getSharedPtr() {
0205 return shared_from_this();
0206 }
0207
0208 std::shared_ptr<const Acts::Experimental::DetectorVolume>
0209 Acts::Experimental::DetectorVolume::getSharedPtr() const {
0210 return shared_from_this();
0211 }
0212
0213 bool Acts::Experimental::DetectorVolume::inside(const GeometryContext& gctx,
0214 const Vector3& position) const {
0215 Vector3 posInVolFrame(transform(gctx).inverse() * position);
0216 return volumeBounds().inside(posInVolFrame);
0217 }
0218
0219 bool Acts::Experimental::DetectorVolume::exclusivelyInside(
0220 const GeometryContext& gctx, const Vector3& position) const {
0221 if (!inside(gctx, position)) {
0222 return false;
0223 }
0224
0225 for (const auto& v : volumes()) {
0226 if (v->inside(gctx, position)) {
0227 return false;
0228 }
0229 }
0230 return true;
0231 }
0232
0233 void Acts::Experimental::DetectorVolume::updateNavigationState(
0234 const GeometryContext& gctx, NavigationState& nState) const {
0235 nState.currentVolume = this;
0236 m_internalNavigation(gctx, nState);
0237 nState.surfaceCandidateIndex = 0;
0238 }
0239
0240 void Acts::Experimental::DetectorVolume::assignInternalNavigation(
0241 InternalNavigationDelegate internalNavigation,
0242 const std::vector<std::shared_ptr<Surface>>& surfaces,
0243 const std::vector<std::shared_ptr<DetectorVolume>>& volumes) {
0244 m_internalNavigation = std::move(internalNavigation);
0245 m_surfaces = ObjectStore<std::shared_ptr<Surface>>(surfaces);
0246 m_volumes = ObjectStore<std::shared_ptr<DetectorVolume>>(volumes);
0247 }
0248
0249 Acts::Extent Acts::Experimental::DetectorVolume::extent(
0250 const GeometryContext& gctx, std::size_t nseg) const {
0251 Extent volumeExtent;
0252 for (const auto* p : portals()) {
0253 volumeExtent.extend(
0254 p->surface().polyhedronRepresentation(gctx, nseg).extent());
0255 }
0256 return volumeExtent;
0257 }
0258
0259 bool Acts::Experimental::DetectorVolume::checkContainment(
0260 const GeometryContext& gctx, std::size_t nseg) const {
0261
0262
0263
0264 auto binningValues = volumeBounds().canonicalAxes();
0265
0266
0267 auto volumeExtent = extent(gctx, nseg);
0268
0269 for (auto b : binningValues) {
0270 for (const auto* s : surfaces()) {
0271 auto sExtent = s->polyhedronRepresentation(gctx, nseg).extent();
0272 if (!volumeExtent.contains(sExtent, b)) {
0273 return false;
0274 }
0275 }
0276
0277 for (const auto* v : volumes()) {
0278 auto vExtent = v->extent(gctx, nseg);
0279 if (!volumeExtent.contains(vExtent, b)) {
0280 return false;
0281 }
0282 }
0283 }
0284
0285 return true;
0286 }
0287
0288 void Acts::Experimental::DetectorVolume::closePortals() {
0289 for (auto& p : m_portals.internal) {
0290
0291 for (auto [ivu, vu] : enumerate(p->portalNavigation())) {
0292 if (!vu.connected()) {
0293 auto eowDir = Direction::fromIndex(ivu);
0294 auto eow = std::make_unique<const EndOfWorld>();
0295 Acts::Experimental::ExternalNavigationDelegate eowLink;
0296 eowLink.connect<&EndOfWorld::update>(std::move(eow));
0297 p->assignPortalNavigation(eowDir, std::move(eowLink), {});
0298 }
0299 }
0300 }
0301
0302 for (auto& v : m_volumes.internal) {
0303 v->closePortals();
0304 }
0305 }
0306
0307 void Acts::Experimental::DetectorVolume::createBoundingBox(
0308 const GeometryContext& gctx) {
0309 std::vector<Vector3> vertices;
0310 for (auto p : m_portals.external) {
0311 auto surface = p->surface().polyhedronRepresentation(gctx, 1);
0312 auto pVertices = surface.vertices;
0313 for (const auto& v : pVertices) {
0314 vertices.push_back(v);
0315 }
0316 }
0317 Acts::Vector3 vmin = Acts::Vector3::Zero();
0318 Acts::Vector3 vmax = Acts::Vector3::Zero();
0319 for (const auto& v : vertices) {
0320 vmin = vmin.cwiseMin(v);
0321 vmax = vmax.cwiseMax(v);
0322 }
0323 std::shared_ptr<Acts::Experimental::DetectorVolume::BoundingBox> box =
0324 std::make_shared<Acts::Experimental::DetectorVolume::BoundingBox>(
0325 this, vmin, vmax);
0326 m_boundingBox = box;
0327 }
0328
0329 const Acts::Experimental::DetectorVolume::BoundingBox&
0330 Acts::Experimental::DetectorVolume::getBoundingBox() const {
0331 return *m_boundingBox;
0332 }