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