File indexing completed on 2026-03-29 07:47:31
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsPlugins/GeoModel/detail/GeoUnionDoubleTrdConverter.hpp"
0010
0011 #include "Acts/Surfaces/PlaneSurface.hpp"
0012 #include "Acts/Surfaces/TrapezoidBounds.hpp"
0013 #include "ActsPlugins/GeoModel/GeoModelConversionError.hpp"
0014 #include "ActsPlugins/GeoModel/detail/GeoShiftConverter.hpp"
0015
0016 #include <GeoModelHelpers/GeoShapeUtils.h>
0017
0018 namespace {
0019
0020 double distanceLinePoint(const Acts::Vector3 &lineA, const Acts::Vector3 &lineB,
0021 const Acts::Vector3 &p) {
0022 auto dir = lineB - lineA;
0023 auto ap = p - lineA;
0024 return ap.cross(dir).norm() / dir.norm();
0025 }
0026
0027
0028 bool trapezoidsAreMergeable(const std::vector<Acts::Vector3> &vtxsa,
0029 const std::vector<Acts::Vector3> &vtxsb) {
0030
0031
0032
0033 auto P1 = vtxsa[0] + 0.5 * (vtxsb[3] - vtxsa[0]);
0034 auto dist1 = distanceLinePoint(vtxsa[3], vtxsb[0], P1);
0035
0036 auto P2 = vtxsa[1] + 0.5 * (vtxsb[2] - vtxsa[1]);
0037 auto dist2 = distanceLinePoint(vtxsa[2], vtxsb[1], P2);
0038
0039 if (dist1 > 1.e-3 || dist2 > 1.e-3) {
0040 return false;
0041 }
0042
0043
0044 return true;
0045 }
0046
0047
0048
0049 std::vector<Acts::Vector3> extactVertices(const Acts::TrapezoidBounds &bounds,
0050 const Acts::Transform3 &shiftTrf) {
0051 std::vector<Acts::Vector3> vertices{};
0052 std::ranges::transform(bounds.vertices(0), std::back_inserter(vertices),
0053 [&shiftTrf](const Acts::Vector2 &vertex) {
0054 return shiftTrf *
0055 Acts::Vector3{vertex.x(), vertex.y(), 0.};
0056 });
0057 return vertices;
0058 }
0059 }
0060
0061 using namespace Acts;
0062
0063 namespace ActsPlugins::detail {
0064
0065 Result<GeoModelSensitiveSurface> GeoUnionDoubleTrdConverter::operator()(
0066 const PVConstLink &geoPV, const GeoShapeUnion &geoUnion,
0067 const Transform3 &absTransform, SurfaceBoundFactory &boundFactory,
0068 bool sensitive) const {
0069 const auto shiftA = dynamic_pointer_cast<const GeoShapeShift>(
0070 compressShift(geoUnion.getOpA()));
0071 const auto shiftB = dynamic_pointer_cast<const GeoShapeShift>(
0072 compressShift(geoUnion.getOpB()));
0073
0074 if (shiftA == nullptr || shiftB == nullptr) {
0075 return GeoModelConversionError::WrongShapeForConverter;
0076 }
0077
0078 auto shiftARes = detail::GeoShiftConverter{}(geoPV, *shiftA, absTransform,
0079 boundFactory, sensitive);
0080 if (!shiftARes.ok()) {
0081 return shiftARes.error();
0082 }
0083 auto shiftBRes = detail::GeoShiftConverter{}(geoPV, *shiftB, absTransform,
0084 boundFactory, sensitive);
0085 if (!shiftBRes.ok()) {
0086 return shiftBRes.error();
0087 }
0088
0089 const auto &[elA, surfaceA] = shiftARes.value();
0090 const auto &[elB, surfaceB] = shiftBRes.value();
0091
0092 if (!(surfaceA && surfaceB)) {
0093 return GeoModelConversionError::WrongShapeForConverter;
0094 }
0095
0096 if (surfaceA->bounds().type() != Acts::SurfaceBounds::eTrapezoid ||
0097 surfaceB->bounds().type() != Acts::SurfaceBounds::eTrapezoid) {
0098 return GeoModelConversionError::WrongShapeForConverter;
0099 }
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116 const auto &boundsA =
0117 static_cast<const TrapezoidBounds &>(surfaceA->bounds());
0118 const auto &boundsB =
0119 static_cast<const TrapezoidBounds &>(surfaceB->bounds());
0120
0121
0122 const auto vtxsa = extactVertices(boundsA, shiftA->getX());
0123 const auto vtxsb = extactVertices(boundsB, shiftB->getX());
0124
0125 if (!trapezoidsAreMergeable(vtxsa, vtxsb)) {
0126 return GeoModelConversionError::WrongShapeForConverter;
0127 }
0128
0129
0130
0131 Acts::Vector3 mpA = vtxsa[3] + 0.5 * (vtxsa[2] - vtxsa[3]);
0132 Acts::Vector3 mpB = vtxsb[0] + 0.5 * (vtxsb[1] - vtxsb[0]);
0133
0134 auto halfLengthY = 0.5 * (mpB - mpA).norm();
0135
0136 const auto gap =
0137 halfLengthY - (boundsA.values()[TrapezoidBounds::eHalfLengthY] +
0138 boundsB.values()[TrapezoidBounds::eHalfLengthY]);
0139
0140 if (gap > gapTolerance) {
0141 return GeoModelConversionError::WrongShapeForConverter;
0142 }
0143
0144
0145 auto hlxny = boundsA.values()[TrapezoidBounds::eHalfLengthXposY];
0146 auto hlxpy = boundsB.values()[TrapezoidBounds::eHalfLengthXnegY];
0147
0148 auto trapezoidBounds =
0149 boundFactory.makeBounds<TrapezoidBounds>(hlxpy, hlxny, halfLengthY);
0150
0151
0152 auto transform = absTransform * shiftA->getX();
0153 transform.translate(Vector3{
0154 0.f, boundsA.values()[TrapezoidBounds::eHalfLengthY] - halfLengthY, 0.f});
0155
0156
0157 if (!sensitive) {
0158 auto surface =
0159 Surface::makeShared<PlaneSurface>(transform, trapezoidBounds);
0160 return std::make_tuple(nullptr, surface);
0161 }
0162
0163
0164 auto detectorElement =
0165 GeoModelDetectorElement::createDetectorElement<PlaneSurface>(
0166 geoPV, trapezoidBounds, transform, elA->thickness());
0167 auto surface = detectorElement->surface().getSharedPtr();
0168
0169 return std::make_tuple(detectorElement, surface);
0170 }
0171
0172 }