Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-23 09:15:35

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include "Acts/Plugins/GeoModel/detail/GeoUnionDoubleTrdConverter.hpp"
0010 
0011 #include "Acts/Plugins/GeoModel/GeoModelConversionError.hpp"
0012 #include "Acts/Plugins/GeoModel/detail/GeoShiftConverter.hpp"
0013 #include "Acts/Surfaces/PlaneSurface.hpp"
0014 #include "Acts/Surfaces/TrapezoidBounds.hpp"
0015 
0016 namespace {
0017 
0018 auto distanceLinePoint(const Acts::Vector3 &lineA, const Acts::Vector3 &lineB,
0019                        const Acts::Vector3 &p) {
0020   auto dir = lineB - lineA;
0021   auto ap = p - lineA;
0022   return ap.cross(dir).norm() / dir.norm();
0023 }
0024 
0025 /// Checks with the following properties if the trapezoids are mergeable
0026 bool trapezoidsAreMergeable(const std::vector<Acts::Vector3> &vtxsa,
0027                             const std::vector<Acts::Vector3> &vtxsb) {
0028   // Compute the distance of the lines connecting A3 and B0 and the midpoint of
0029   // the gap (resp. for other trapezoid side) These should be close to zero,
0030   // otherwise we cannot merge the trapezoids
0031   auto P1 = vtxsa[0] + 0.5 * (vtxsb[3] - vtxsa[0]);
0032   auto dist1 = distanceLinePoint(vtxsa[3], vtxsb[0], P1);
0033 
0034   auto P2 = vtxsa[1] + 0.5 * (vtxsb[2] - vtxsa[1]);
0035   auto dist2 = distanceLinePoint(vtxsa[2], vtxsb[1], P2);
0036 
0037   if (dist1 > 1.e-3 || dist2 > 1.e-3) {
0038     return false;
0039   }
0040 
0041   // We could verify other properties, but this seems sufficient for know
0042   return true;
0043 }
0044 
0045 }  // namespace
0046 
0047 namespace Acts::detail {
0048 
0049 Result<GeoModelSensitiveSurface> GeoUnionDoubleTrdConverter::operator()(
0050     const PVConstLink &geoPV, const GeoShapeUnion &geoUnion,
0051     const Transform3 &absTransform, bool sensitive) const {
0052   const auto shiftA = dynamic_cast<const GeoShapeShift *>(geoUnion.getOpA());
0053   const auto shiftB = dynamic_cast<const GeoShapeShift *>(geoUnion.getOpB());
0054 
0055   if (shiftA == nullptr || shiftB == nullptr) {
0056     return GeoModelConversionError::WrongShapeForConverter;
0057   }
0058 
0059   auto shiftARes =
0060       detail::GeoShiftConverter{}(geoPV, *shiftA, absTransform, sensitive);
0061   if (!shiftARes.ok()) {
0062     return shiftARes.error();
0063   }
0064   auto shiftBRes =
0065       detail::GeoShiftConverter{}(geoPV, *shiftB, absTransform, sensitive);
0066   if (!shiftBRes.ok()) {
0067     return shiftBRes.error();
0068   }
0069 
0070   const auto &[elA, surfaceA] = shiftARes.value();
0071   const auto &[elB, surfaceB] = shiftBRes.value();
0072 
0073   if (!(surfaceA && surfaceB)) {
0074     return GeoModelConversionError::WrongShapeForConverter;
0075   }
0076 
0077   if (surfaceA->bounds().type() != Acts::SurfaceBounds::eTrapezoid ||
0078       surfaceB->bounds().type() != Acts::SurfaceBounds::eTrapezoid) {
0079     return GeoModelConversionError::WrongShapeForConverter;
0080   }
0081 
0082   // At this point we know, that we have two trapezoids
0083   // We assume the following Layout for this:
0084   //
0085   //  0 ______________________ 1
0086   //    \                    /
0087   //     \        B         /
0088   //      \________________/
0089   //     3                 2
0090   //      0 _____________ 1
0091   //        \           /
0092   //         \    A    /
0093   //          \_______/
0094   //          3       2
0095 
0096   // First check now, if this actually is correct
0097   const auto vtxsa = surfaceA->polyhedronRepresentation({}, 0).vertices;
0098   const auto vtxsb = surfaceB->polyhedronRepresentation({}, 0).vertices;
0099 
0100   if (!trapezoidsAreMergeable(vtxsa, vtxsb)) {
0101     return GeoModelConversionError::WrongShapeForConverter;
0102   }
0103 
0104   // Compute half length y as the distance between the middle points of the
0105   // outer lines of the trapezoids
0106   Acts::Vector3 mpA = vtxsa[3] + 0.5 * (vtxsa[2] - vtxsa[3]);
0107   Acts::Vector3 mpB = vtxsb[0] + 0.5 * (vtxsb[1] - vtxsb[0]);
0108 
0109   auto halfLengthY = 0.5 * (mpB - mpA).norm();
0110 
0111   // Compute the gap between trapezoids
0112   const auto &boundsA =
0113       static_cast<const TrapezoidBounds &>(surfaceA->bounds());
0114   const auto &boundsB =
0115       static_cast<const TrapezoidBounds &>(surfaceB->bounds());
0116 
0117   const auto gap =
0118       halfLengthY - (boundsA.values()[TrapezoidBounds::eHalfLengthY] +
0119                      boundsB.values()[TrapezoidBounds::eHalfLengthY]);
0120 
0121   if (gap > gapTolerance) {
0122     return GeoModelConversionError::WrongShapeForConverter;
0123   }
0124 
0125   // For the x half lengths, we can take the values from the 2 trapezoids
0126   auto hlxny = boundsA.values()[TrapezoidBounds::eHalfLengthXposY];
0127   auto hlxpy = boundsB.values()[TrapezoidBounds::eHalfLengthXnegY];
0128 
0129   auto trapezoidBounds =
0130       std::make_shared<TrapezoidBounds>(hlxpy, hlxny, halfLengthY);
0131 
0132   // Create transform from the transform of surfaceA and translate it in y
0133   // direction using the half length
0134   auto transform = surfaceA->transform({});
0135   transform.translate(Vector3{
0136       0.f, boundsA.values()[TrapezoidBounds::eHalfLengthY] - halfLengthY, 0.f});
0137 
0138   // TODO extract this code snipped since it is copied quite a lot
0139   if (!sensitive) {
0140     auto surface =
0141         Surface::makeShared<PlaneSurface>(transform, trapezoidBounds);
0142     return std::make_tuple(nullptr, surface);
0143   }
0144 
0145   // Create the element and the surface (we assume both have equal thickness)
0146   auto detectorElement =
0147       GeoModelDetectorElement::createDetectorElement<PlaneSurface>(
0148           geoPV, trapezoidBounds, transform, elA->thickness());
0149   auto surface = detectorElement->surface().getSharedPtr();
0150 
0151   return std::make_tuple(detectorElement, surface);
0152 }
0153 
0154 }  // namespace Acts::detail