File indexing completed on 2025-08-06 08:10:22
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Detector/detail/SupportSurfacesHelper.hpp"
0010
0011 #include "Acts/Definitions/Tolerance.hpp"
0012 #include "Acts/Surfaces/CylinderBounds.hpp"
0013 #include "Acts/Surfaces/CylinderSurface.hpp"
0014 #include "Acts/Surfaces/DiscSurface.hpp"
0015 #include "Acts/Surfaces/PlaneSurface.hpp"
0016 #include "Acts/Surfaces/RadialBounds.hpp"
0017 #include "Acts/Surfaces/RectangleBounds.hpp"
0018 #include "Acts/Surfaces/TrapezoidBounds.hpp"
0019 #include "Acts/Utilities/BinningType.hpp"
0020
0021 #include <algorithm>
0022 #include <cmath>
0023 #include <stdexcept>
0024 #include <utility>
0025
0026 Acts::Experimental::detail::SupportSurfacesHelper::SupportSurfaceComponents
0027 Acts::Experimental::detail::SupportSurfacesHelper::CylindricalSupport::
0028 operator()(const Extent& lExtent) const {
0029
0030 if (!lExtent.constrains(binZ) || !lExtent.constrains(binR)) {
0031 throw std::invalid_argument(
0032 "SupportSurfacesHelper::CylindricalSupport::operator() - z or "
0033 "r are not constrained.");
0034 }
0035
0036
0037 ActsScalar minZ = lExtent.min(binZ) + std::abs(zClearance[0u]);
0038 ActsScalar maxZ = lExtent.max(binZ) - std::abs(zClearance[1u]);
0039
0040
0041 ActsScalar hPhiSector = M_PI;
0042 ActsScalar avgPhi = 0.;
0043 if (lExtent.constrains(binPhi)) {
0044
0045 ActsScalar minPhi = lExtent.min(binPhi) + std::abs(phiClearance[0u]);
0046 ActsScalar maxPhi = lExtent.max(binPhi) - std::abs(phiClearance[1u]);
0047 hPhiSector = 0.5 * (maxPhi - minPhi);
0048 avgPhi = 0.5 * (minPhi + maxPhi);
0049 }
0050
0051 Transform3 transform = Transform3::Identity();
0052 if (std::abs(minZ + maxZ) > s_onSurfaceTolerance) {
0053 transform.pretranslate(Vector3(0., 0., 0.5 * (minZ + maxZ)));
0054 }
0055
0056
0057 ActsScalar r =
0058 rOffset < 0 ? lExtent.min(binR) + rOffset : lExtent.max(binR) + rOffset;
0059 if (rOffset == 0.) {
0060 r = lExtent.medium(binR);
0061 }
0062
0063 return {
0064 type, {r, 0.5 * (maxZ - minZ), hPhiSector, avgPhi, 0., 0.}, transform};
0065 }
0066
0067 Acts::Experimental::detail::SupportSurfacesHelper::SupportSurfaceComponents
0068 Acts::Experimental::detail::SupportSurfacesHelper::DiscSupport::operator()(
0069 const Extent& lExtent) const {
0070
0071 if (!lExtent.constrains(binZ) || !lExtent.constrains(binR)) {
0072 throw std::invalid_argument(
0073 "SupportSurfacesHelper::DiscSupport::operator() - z or "
0074 "r are not constrained.");
0075 }
0076
0077
0078 ActsScalar minR = lExtent.min(binR) + std::abs(rClearance[0u]);
0079 ActsScalar maxR = lExtent.max(binR) - std::abs(rClearance[1u]);
0080
0081
0082 ActsScalar hPhiSector = M_PI;
0083 ActsScalar avgPhi = 0.;
0084 if (lExtent.constrains(binPhi)) {
0085
0086 ActsScalar minPhi = lExtent.min(binPhi) + std::abs(phiClearance[0u]);
0087 ActsScalar maxPhi = lExtent.max(binPhi) - std::abs(phiClearance[1u]);
0088 hPhiSector = 0.5 * (maxPhi - minPhi);
0089 avgPhi = 0.5 * (minPhi + maxPhi);
0090 }
0091
0092
0093 ActsScalar z =
0094 zOffset < 0 ? lExtent.min(binZ) + zOffset : lExtent.max(binZ) + zOffset;
0095 if (zOffset == 0.) {
0096 z = lExtent.medium(binZ);
0097 }
0098
0099 Transform3 transform = Transform3::Identity();
0100 transform.pretranslate(Vector3(0., 0., z));
0101
0102
0103 return {type, {minR, maxR, hPhiSector, avgPhi}, transform};
0104 }
0105
0106 Acts::Experimental::detail::SupportSurfacesHelper::SupportSurfaceComponents
0107 Acts::Experimental::detail::SupportSurfacesHelper::RectangularSupport::
0108 operator()(const Extent& lExtent) const {
0109
0110 if (!(lExtent.constrains(binX) && lExtent.constrains(binY) &&
0111 lExtent.constrains(binZ))) {
0112 throw std::invalid_argument(
0113 "SupportSurfacesHelper::RectangularSupport::operator() - x, y or "
0114 "z are not constrained.");
0115 }
0116
0117
0118 std::array<BinningValue, 2> locals = {binX, binY};
0119 if (pPlacement == binX) {
0120 locals = {binY, binZ};
0121 } else if (pPlacement == binY) {
0122 locals = {binZ, binX};
0123 }
0124
0125
0126 ActsScalar minX = lExtent.min(locals[0]) + std::abs(loc0Clearance[0u]);
0127 ActsScalar maxX = lExtent.max(locals[0]) - std::abs(loc0Clearance[1u]);
0128 ActsScalar minY = lExtent.min(locals[1]) + std::abs(loc1Clearance[0u]);
0129 ActsScalar maxY = lExtent.max(locals[1]) - std::abs(loc1Clearance[1u]);
0130
0131 ActsScalar gPlacement = lExtent.medium(pPlacement) + pOffset;
0132 Vector3 placement = Vector3::Zero();
0133 placement[pPlacement] = gPlacement;
0134
0135 Transform3 transform = Transform3::Identity();
0136 transform.pretranslate(placement);
0137
0138 return {type, {minX, minY, maxX, maxY}, transform};
0139 }
0140
0141 std::vector<std::shared_ptr<Acts::Surface>>
0142 Acts::Experimental::detail::SupportSurfacesHelper::cylindricalSupport(
0143 const SupportSurfaceComponents& components, unsigned int splits) {
0144
0145 auto [type, values, transform] = components;
0146
0147
0148 if (values.size() != 6u) {
0149 throw std::invalid_argument(
0150 "SupportSurfacesHelper::cylindricalSupport(...) - "
0151 "values vector has wrong size, requires 6 parameters.");
0152 }
0153
0154
0155 if (type != Surface::SurfaceType::Cylinder) {
0156 throw std::invalid_argument(
0157 "SupportSurfacesHelper::cylindricalSupport(...) - "
0158 "surface type is not a cylinder.");
0159 }
0160
0161 std::array<ActsScalar, 6u> bounds = {};
0162 std::copy_n(values.begin(), 6u, bounds.begin());
0163
0164
0165 std::vector<std::shared_ptr<Acts::Surface>> cSupport;
0166 if (splits == 1u) {
0167
0168 cSupport.push_back(Surface::makeShared<CylinderSurface>(
0169 transform, std::make_shared<CylinderBounds>(bounds)));
0170 } else {
0171
0172 ActsScalar r = bounds[0u];
0173 ActsScalar halfZ = bounds[1u];
0174 ActsScalar minPhi = bounds[3u] - bounds[2u];
0175 ActsScalar maxPhi = bounds[3u] + bounds[2u];
0176 ActsScalar dHalfPhi = (maxPhi - minPhi) / (2 * splits);
0177 ActsScalar cosPhiHalf = std::cos(dHalfPhi);
0178 ActsScalar sinPhiHalf = std::sin(dHalfPhi);
0179 ActsScalar planeR = r * cosPhiHalf;
0180 ActsScalar planeHalfX = r * sinPhiHalf;
0181 ActsScalar planeZ = transform.translation().z();
0182
0183 auto sRectangle =
0184 std::make_shared<Acts::RectangleBounds>(planeHalfX, halfZ);
0185
0186 for (unsigned int iphi = 0; iphi < splits; ++iphi) {
0187
0188 ActsScalar phi = -M_PI + (iphi + 0.5) * 2 * dHalfPhi;
0189 ActsScalar cosPhi = std::cos(phi);
0190 ActsScalar sinPhi = std::sin(phi);
0191 ActsScalar planeX = planeR * cosPhi;
0192 ActsScalar planeY = planeR * sinPhi;
0193
0194 Acts::Vector3 planeCenter(planeX, planeY, planeZ);
0195 Acts::Vector3 planeAxisZ(cosPhi, sinPhi, 0.);
0196 Acts::Vector3 planeAxisY(0., 0., 1.);
0197 Acts::Vector3 planeAxisX = planeAxisY.cross(planeAxisZ);
0198
0199 RotationMatrix3 planeRotation;
0200 planeRotation.col(0) = planeAxisX;
0201 planeRotation.col(1) = planeAxisY;
0202 planeRotation.col(2) = planeAxisZ;
0203
0204 Transform3 sTransform{planeRotation};
0205 sTransform.pretranslate(planeCenter);
0206
0207 cSupport.push_back(
0208 Surface::makeShared<PlaneSurface>(sTransform, sRectangle));
0209 }
0210 }
0211
0212 return cSupport;
0213 }
0214
0215 std::vector<std::shared_ptr<Acts::Surface>>
0216 Acts::Experimental::detail::SupportSurfacesHelper::discSupport(
0217 const SupportSurfaceComponents& components, unsigned int splits) {
0218
0219 auto [type, values, transform] = components;
0220
0221
0222 if (values.size() != 4u) {
0223 throw std::invalid_argument(
0224 "SupportSurfacesHelper::discSupport(...) - "
0225 "values vector has wrong size, requires 4 parameters.");
0226 }
0227
0228
0229 if (type != Surface::SurfaceType::Disc) {
0230 throw std::invalid_argument(
0231 "SupportSurfacesHelper::discSupport(...) - "
0232 "surface type is not a disc.");
0233 }
0234
0235 std::array<ActsScalar, 4u> bounds = {};
0236 std::copy_n(values.begin(), 4u, bounds.begin());
0237
0238
0239 std::vector<std::shared_ptr<Acts::Surface>> dSupport;
0240 if (splits == 1u) {
0241
0242 dSupport.push_back(Surface::makeShared<DiscSurface>(
0243 transform, std::make_shared<RadialBounds>(bounds)));
0244 } else {
0245
0246 ActsScalar minR = bounds[0u];
0247 ActsScalar maxR = bounds[1u];
0248 ActsScalar minPhi = bounds[3u] - bounds[2u];
0249 ActsScalar maxPhi = bounds[3u] + bounds[2u];
0250 ActsScalar dHalfPhi = (maxPhi - minPhi) / (2 * splits);
0251 ActsScalar cosPhiHalf = std::cos(dHalfPhi);
0252 ActsScalar sinPhiHalf = std::sin(dHalfPhi);
0253 ActsScalar maxLocY = maxR * cosPhiHalf;
0254 ActsScalar minLocY = minR * cosPhiHalf;
0255 ActsScalar hR = 0.5 * (maxLocY + minLocY);
0256 ActsScalar hY = 0.5 * (maxLocY - minLocY);
0257 ActsScalar hXminY = minR * sinPhiHalf;
0258 ActsScalar hXmaxY = maxR * sinPhiHalf;
0259
0260 auto sTrapezoid =
0261 std::make_shared<Acts::TrapezoidBounds>(hXminY, hXmaxY, hY);
0262 Vector3 zAxis = transform.rotation().col(2);
0263 ActsScalar zPosition = transform.translation().z();
0264
0265 for (unsigned int iphi = 0; iphi < splits; ++iphi) {
0266
0267 ActsScalar phi = -M_PI + (iphi + 0.5) * 2 * dHalfPhi;
0268 auto sTransform = Transform3(
0269 Translation3(hR * std::cos(phi), hR * std::sin(phi), zPosition) *
0270 AngleAxis3(phi - 0.5 * M_PI, zAxis));
0271
0272 dSupport.push_back(
0273 Surface::makeShared<PlaneSurface>(sTransform, sTrapezoid));
0274 }
0275 }
0276 return dSupport;
0277 }
0278
0279 std::vector<std::shared_ptr<Acts::Surface>>
0280 Acts::Experimental::detail::SupportSurfacesHelper::rectangularSupport(
0281 const SupportSurfaceComponents& components) {
0282
0283 auto [type, values, transform] = components;
0284
0285
0286 if (values.size() != 4u) {
0287 throw std::invalid_argument(
0288 "SupportSurfacesHelper::rectangularSupport(...) - "
0289 "values vector has wrong size, requires 4 parameters.");
0290 }
0291
0292
0293 if (type != Surface::SurfaceType::Plane) {
0294 throw std::invalid_argument(
0295 "SupportSurfacesHelper::rectangularSupport(...) - "
0296 "surface type is not a plane.");
0297 }
0298
0299 std::array<ActsScalar, 4u> bounds = {};
0300 std::copy_n(values.begin(), 4u, bounds.begin());
0301
0302 return {Surface::makeShared<PlaneSurface>(
0303 transform, std::make_shared<RectangleBounds>(bounds))};
0304 }
0305
0306 void Acts::Experimental::detail::SupportSurfacesHelper::addSupport(
0307 std::vector<std::shared_ptr<Surface>>& layerSurfaces,
0308 std::vector<std::size_t>& assignToAll, const Extent& layerExtent,
0309 const SurfaceComponentsCreator& componentCreator,
0310 unsigned int supportSplits) {
0311
0312 auto supportComponents = componentCreator(layerExtent);
0313 const auto& sType = std::get<0>(supportComponents);
0314
0315 std::vector<std::shared_ptr<Acts::Surface>> supportSurfaces = {};
0316
0317 if (sType == Surface::SurfaceType::Cylinder) {
0318 supportSurfaces = cylindricalSupport(supportComponents, supportSplits);
0319 } else if (sType == Surface::SurfaceType::Disc) {
0320 supportSurfaces = discSupport(supportComponents, supportSplits);
0321 } else if (sType == Surface::SurfaceType::Plane) {
0322 supportSurfaces = rectangularSupport(supportComponents);
0323 } else {
0324 throw std::invalid_argument(
0325 "SupportSurfacesHelper: currently only cylindrical/disc/rectangle "
0326 "support building is possible.");
0327 }
0328
0329
0330
0331 if (supportSplits == 1u && supportSurfaces.size() == 1u) {
0332 assignToAll.push_back(layerSurfaces.size());
0333 }
0334
0335 layerSurfaces.insert(layerSurfaces.end(), supportSurfaces.begin(),
0336 supportSurfaces.end());
0337 }