File indexing completed on 2025-07-02 07:51:08
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Geometry/LayerBlueprintNode.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0013 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0014 #include "Acts/Geometry/ProtoLayer.hpp"
0015 #include "Acts/Geometry/VolumeBounds.hpp"
0016 #include "Acts/Utilities/GraphViz.hpp"
0017
0018 namespace Acts::Experimental {
0019
0020 namespace detail {
0021 struct LayerBlueprintNodeImpl {
0022 using LayerType = LayerBlueprintNode::LayerType;
0023
0024 std::string m_name;
0025
0026 std::vector<std::shared_ptr<Surface>> m_surfaces{};
0027
0028
0029
0030 std::optional<MutableProtoLayer> m_protoLayer;
0031
0032 Transform3 m_transform = Transform3::Identity();
0033 ExtentEnvelope m_envelope = ExtentEnvelope::Zero();
0034 LayerType m_layerType = LayerType::Cylinder;
0035 std::array<bool, 3> m_useCenterOfGravity = {true, true, true};
0036 };
0037 }
0038
0039 LayerBlueprintNode::LayerBlueprintNode(std::string_view name)
0040 : StaticBlueprintNode(nullptr) {
0041 m_impl = std::make_unique<detail::LayerBlueprintNodeImpl>();
0042 m_impl->m_name = name;
0043 }
0044
0045 LayerBlueprintNode::~LayerBlueprintNode() = default;
0046
0047 detail::LayerBlueprintNodeImpl& LayerBlueprintNode::impl() {
0048 assert(m_impl != nullptr);
0049 return *m_impl;
0050 }
0051
0052 const detail::LayerBlueprintNodeImpl& LayerBlueprintNode::impl() const {
0053 assert(m_impl != nullptr);
0054 return *m_impl;
0055 }
0056
0057 Volume& LayerBlueprintNode::build(const BlueprintOptions& options,
0058 const GeometryContext& gctx,
0059 const Logger& logger) {
0060 if (impl().m_surfaces.empty()) {
0061 ACTS_ERROR("LayerBlueprintNode: no surfaces provided");
0062 throw std::invalid_argument("LayerBlueprintNode: no surfaces provided");
0063 }
0064
0065 ACTS_DEBUG(prefix() << "Building Layer " << name() << " from "
0066 << impl().m_surfaces.size() << " surfaces");
0067 ACTS_VERBOSE(prefix() << " -> layer type: " << impl().m_layerType);
0068 ACTS_VERBOSE(prefix() << " -> transform:\n" << impl().m_transform.matrix());
0069
0070 Extent extent;
0071
0072 if (!impl().m_protoLayer.has_value()) {
0073 impl().m_protoLayer.emplace(gctx, impl().m_surfaces,
0074 impl().m_transform.inverse());
0075 ACTS_VERBOSE(prefix() << "Built proto layer: "
0076 << impl().m_protoLayer.value());
0077 } else {
0078 ACTS_VERBOSE(prefix() << "Using provided proto layer");
0079 }
0080
0081 auto& protoLayer = impl().m_protoLayer.value();
0082 extent.addConstrain(protoLayer.extent, impl().m_envelope);
0083
0084 ACTS_VERBOSE(prefix() << " -> layer extent: " << extent);
0085
0086 buildVolume(extent, logger);
0087 assert(m_volume != nullptr && "Volume not built from proto layer");
0088
0089 for (auto& surface : impl().m_surfaces) {
0090 m_volume->addSurface(surface);
0091 }
0092
0093 return StaticBlueprintNode::build(options, gctx, logger);
0094 }
0095
0096 void LayerBlueprintNode::buildVolume(const Extent& extent,
0097 const Logger& logger) {
0098 ACTS_VERBOSE(prefix() << "Building volume for layer " << name());
0099 using enum AxisDirection;
0100 using enum LayerType;
0101
0102 std::shared_ptr<VolumeBounds> bounds;
0103 switch (impl().m_layerType) {
0104 case Cylinder:
0105 case Disc: {
0106 double minR = extent.min(AxisR);
0107 double maxR = extent.max(AxisR);
0108 double hlZ = extent.interval(AxisZ) / 2.0;
0109 bounds = std::make_shared<CylinderVolumeBounds>(minR, maxR, hlZ);
0110 break;
0111 }
0112 case Plane: {
0113 double hlX = extent.interval(AxisX) / 2.0;
0114 double hlY = extent.interval(AxisY) / 2.0;
0115 double hlZ = extent.interval(AxisZ) / 2.0;
0116 bounds = std::make_shared<CuboidVolumeBounds>(hlX, hlY, hlZ);
0117 break;
0118 }
0119 }
0120
0121 assert(bounds != nullptr);
0122
0123 ACTS_VERBOSE(prefix() << " -> bounds: " << *bounds);
0124
0125 Transform3 transform = impl().m_transform;
0126 Vector3 translation = Vector3::Zero();
0127 if (impl().m_useCenterOfGravity.at(toUnderlying(AxisX))) {
0128 translation.x() = extent.medium(AxisX);
0129 }
0130 if (impl().m_useCenterOfGravity.at(toUnderlying(AxisY))) {
0131 translation.y() = extent.medium(AxisY);
0132 }
0133 if (impl().m_useCenterOfGravity.at(toUnderlying(AxisZ))) {
0134 translation.z() = extent.medium(AxisZ);
0135 }
0136
0137 transform.translation() = translation;
0138
0139 ACTS_VERBOSE(prefix() << " -> adjusted transform:\n" << transform.matrix());
0140
0141 m_volume = std::make_unique<TrackingVolume>(transform, std::move(bounds),
0142 impl().m_name);
0143 }
0144
0145 const std::string& LayerBlueprintNode::name() const {
0146 return impl().m_name;
0147 }
0148
0149 LayerBlueprintNode& LayerBlueprintNode::setSurfaces(
0150 std::vector<std::shared_ptr<Surface>> surfaces) {
0151 impl().m_surfaces = std::move(surfaces);
0152 impl().m_protoLayer.reset();
0153 return *this;
0154 }
0155
0156 const std::vector<std::shared_ptr<Surface>>& LayerBlueprintNode::surfaces()
0157 const {
0158 return impl().m_surfaces;
0159 }
0160
0161 LayerBlueprintNode& LayerBlueprintNode::setProtoLayer(
0162 std::optional<MutableProtoLayer> protoLayer) {
0163 impl().m_protoLayer = std::move(protoLayer);
0164 impl().m_surfaces.clear();
0165
0166 for (auto& surface : impl().m_protoLayer.value().surfaces()) {
0167 impl().m_surfaces.push_back(surface->getSharedPtr());
0168 }
0169 return *this;
0170 }
0171
0172 const MutableProtoLayer* LayerBlueprintNode::protoLayer() const {
0173 return impl().m_protoLayer.has_value() ? &impl().m_protoLayer.value()
0174 : nullptr;
0175 }
0176
0177 LayerBlueprintNode& LayerBlueprintNode::setTransform(
0178 const Transform3& transform) {
0179 impl().m_transform = transform;
0180 return *this;
0181 }
0182
0183 const Transform3& LayerBlueprintNode::transform() const {
0184 return impl().m_transform;
0185 }
0186
0187 LayerBlueprintNode& LayerBlueprintNode::setEnvelope(
0188 const ExtentEnvelope& envelope) {
0189 impl().m_envelope = envelope;
0190 return *this;
0191 }
0192
0193 const ExtentEnvelope& LayerBlueprintNode::envelope() const {
0194 return impl().m_envelope;
0195 }
0196
0197 LayerBlueprintNode& LayerBlueprintNode::setLayerType(LayerType layerType) {
0198 impl().m_layerType = layerType;
0199 return *this;
0200 }
0201
0202 const LayerBlueprintNode::LayerType& LayerBlueprintNode::layerType() const {
0203 return impl().m_layerType;
0204 }
0205
0206 LayerBlueprintNode& LayerBlueprintNode::setUseCenterOfGravity(bool x, bool y,
0207 bool z) {
0208 impl().m_useCenterOfGravity = {x, y, z};
0209 return *this;
0210 }
0211
0212 void LayerBlueprintNode::addToGraphviz(std::ostream& os) const {
0213 std::stringstream ss;
0214 ss << "<br/><b>" + name() + "</b>";
0215 ss << "<br/>Layer";
0216 ss << "<br/><i>" << impl().m_layerType << "</i>";
0217
0218 GraphViz::Node node{
0219 .id = name(), .label = ss.str(), .shape = GraphViz::Shape::Diamond};
0220
0221 os << node;
0222
0223 BlueprintNode::addToGraphviz(os);
0224 }
0225
0226 }