File indexing completed on 2026-04-09 07:46:08
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Surfaces/LineSurface.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Geometry/GeometryObject.hpp"
0013 #include "Acts/Surfaces/InfiniteBounds.hpp"
0014 #include "Acts/Surfaces/LineBounds.hpp"
0015 #include "Acts/Surfaces/SurfaceBounds.hpp"
0016 #include "Acts/Surfaces/SurfaceError.hpp"
0017 #include "Acts/Surfaces/detail/AlignmentHelper.hpp"
0018 #include "Acts/Utilities/Intersection.hpp"
0019 #include "Acts/Utilities/ThrowAssert.hpp"
0020
0021 #include <cmath>
0022 #include <limits>
0023 #include <utility>
0024
0025 namespace Acts {
0026
0027 LineSurface::LineSurface(const Transform3& transform, double radius,
0028 double halez)
0029 : Surface(transform),
0030 m_bounds(std::make_shared<const LineBounds>(radius, halez)) {}
0031
0032 LineSurface::LineSurface(const Transform3& transform,
0033 std::shared_ptr<const LineBounds> lbounds)
0034 : Surface(transform), m_bounds(std::move(lbounds)) {}
0035
0036 LineSurface::LineSurface(std::shared_ptr<const LineBounds> lbounds,
0037 const SurfacePlacementBase& placement)
0038 : Surface{placement}, m_bounds(std::move(lbounds)) {
0039 throw_assert(m_bounds, "LineBounds must not be nullptr");
0040 }
0041
0042 LineSurface::LineSurface(const LineSurface& other)
0043 : GeometryObject{}, Surface(other), m_bounds(other.m_bounds) {}
0044
0045 LineSurface::LineSurface(const GeometryContext& gctx, const LineSurface& other,
0046 const Transform3& shift)
0047 : Surface(gctx, other, shift), m_bounds(other.m_bounds) {}
0048
0049 LineSurface& LineSurface::operator=(const LineSurface& other) {
0050 if (this != &other) {
0051 Surface::operator=(other);
0052 m_bounds = other.m_bounds;
0053 }
0054 return *this;
0055 }
0056
0057 Vector3 LineSurface::localToGlobal(const GeometryContext& gctx,
0058 const Vector2& lposition,
0059 const Vector3& direction) const {
0060 Vector3 unitZ0 = lineDirection(gctx);
0061
0062
0063 Vector3 radiusAxisGlobal = unitZ0.cross(direction);
0064 Vector3 locZinGlobal =
0065 localToGlobalTransform(gctx) * Vector3(0., 0., lposition[1]);
0066
0067 return Vector3(locZinGlobal + lposition[0] * radiusAxisGlobal.normalized());
0068 }
0069
0070 Result<Vector2> LineSurface::globalToLocal(const GeometryContext& gctx,
0071 const Vector3& position,
0072 const Vector3& direction,
0073 double tolerance) const {
0074 using VectorHelpers::perp;
0075
0076
0077
0078 Vector3 localPosition =
0079 referenceFrame(gctx, position, direction).inverse() *
0080 (position - localToGlobalTransform(gctx).translation());
0081
0082
0083
0084
0085
0086
0087
0088 if (std::abs(localPosition.z()) > std::abs(tolerance)) {
0089 return Result<Vector2>::failure(SurfaceError::GlobalPositionNotOnSurface);
0090 }
0091
0092
0093 Vector2 localXY = localPosition.head<2>();
0094
0095 return Result<Vector2>::success(localXY);
0096 }
0097
0098 std::string LineSurface::name() const {
0099 return "Acts::LineSurface";
0100 }
0101
0102 RotationMatrix3 LineSurface::referenceFrame(const GeometryContext& gctx,
0103 const Vector3& ,
0104 const Vector3& direction) const {
0105 Vector3 unitZ0 = lineDirection(gctx);
0106 Vector3 unitD0 = unitZ0.cross(direction).normalized();
0107 Vector3 unitDistance = unitD0.cross(unitZ0);
0108
0109 RotationMatrix3 mFrame;
0110 mFrame.col(0) = unitD0;
0111 mFrame.col(1) = unitZ0;
0112 mFrame.col(2) = unitDistance;
0113
0114 return mFrame;
0115 }
0116
0117 double LineSurface::pathCorrection(const GeometryContext& ,
0118 const Vector3& ,
0119 const Vector3& ) const {
0120 return 1.;
0121 }
0122
0123 Vector3 LineSurface::referencePosition(const GeometryContext& gctx,
0124 AxisDirection ) const {
0125 return center(gctx);
0126 }
0127
0128 Vector3 LineSurface::normal(const GeometryContext& gctx, const Vector3& pos,
0129 const Vector3& direction) const {
0130 auto ref = referenceFrame(gctx, pos, direction);
0131 return ref.col(2);
0132 }
0133
0134 const SurfaceBounds& LineSurface::bounds() const {
0135 if (m_bounds) {
0136 return *m_bounds;
0137 }
0138 return s_noBounds;
0139 }
0140
0141 MultiIntersection3D LineSurface::intersect(
0142 const GeometryContext& gctx, const Vector3& position,
0143 const Vector3& direction, const BoundaryTolerance& boundaryTolerance,
0144 double tolerance) const {
0145
0146
0147 const Vector3& ma = position;
0148 const Vector3& ea = direction;
0149
0150
0151 Vector3 mb = localToGlobalTransform(gctx).translation();
0152
0153 Vector3 eb = lineDirection(gctx);
0154
0155
0156 Vector3 mab = mb - ma;
0157 double eaTeb = ea.dot(eb);
0158 double denom = 1 - eaTeb * eaTeb;
0159
0160
0161
0162 if (std::abs(denom) < std::abs(tolerance)) {
0163
0164 return MultiIntersection3D(Intersection3D::Invalid());
0165 }
0166
0167 double u = (mab.dot(ea) - mab.dot(eb) * eaTeb) / denom;
0168
0169 IntersectionStatus status = std::abs(u) > std::abs(tolerance)
0170 ? IntersectionStatus::reachable
0171 : IntersectionStatus::onSurface;
0172 Vector3 result = ma + u * ea;
0173
0174
0175 if (m_bounds && !boundaryTolerance.isInfinite()) {
0176 Vector3 vecLocal = result - mb;
0177 double cZ = vecLocal.dot(eb);
0178 double cR = (vecLocal - cZ * eb).norm();
0179 if (!m_bounds->inside({cR, cZ}, boundaryTolerance)) {
0180 status = IntersectionStatus::unreachable;
0181 }
0182 }
0183
0184 return MultiIntersection3D(Intersection3D(result, u, status));
0185 }
0186
0187 BoundToFreeMatrix LineSurface::boundToFreeJacobian(
0188 const GeometryContext& gctx, const Vector3& position,
0189 const Vector3& direction) const {
0190 assert(isOnSurface(gctx, position, direction, BoundaryTolerance::Infinite()));
0191
0192
0193 auto rframe = referenceFrame(gctx, position, direction);
0194
0195 Vector2 local = *globalToLocal(gctx, position, direction,
0196 std::numeric_limits<double>::max());
0197
0198
0199
0200
0201
0202 BoundToFreeMatrix jacToGlobal =
0203 Surface::boundToFreeJacobian(gctx, position, direction);
0204
0205
0206 double ipdn = 1. / direction.dot(rframe.col(2));
0207
0208 Vector3 dDPhiY = rframe.block<3, 1>(0, 1).cross(
0209 jacToGlobal.block<3, 1>(eFreeDir0, eBoundPhi));
0210
0211 Vector3 dDThetaY = rframe.block<3, 1>(0, 1).cross(
0212 jacToGlobal.block<3, 1>(eFreeDir0, eBoundTheta));
0213
0214 dDPhiY -= rframe.block<3, 1>(0, 0) * (rframe.block<3, 1>(0, 0).dot(dDPhiY));
0215 dDThetaY -=
0216 rframe.block<3, 1>(0, 0) * (rframe.block<3, 1>(0, 0).dot(dDThetaY));
0217
0218 jacToGlobal.block<3, 1>(eFreePos0, eBoundPhi) = dDPhiY * local.x() * ipdn;
0219 jacToGlobal.block<3, 1>(eFreePos0, eBoundTheta) = dDThetaY * local.x() * ipdn;
0220
0221 return jacToGlobal;
0222 }
0223
0224 FreeToPathMatrix LineSurface::freeToPathDerivative(
0225 const GeometryContext& gctx, const Vector3& position,
0226 const Vector3& direction) const {
0227 assert(isOnSurface(gctx, position, direction, BoundaryTolerance::Infinite()));
0228
0229
0230 Vector3 pcRowVec = position - center(gctx);
0231
0232 Vector3 localZAxis = lineDirection(gctx);
0233
0234 double pz = pcRowVec.dot(localZAxis);
0235
0236 double dz = localZAxis.dot(direction);
0237 double norm = 1 / (1 - dz * dz);
0238
0239
0240 FreeToPathMatrix freeToPath = FreeToPathMatrix::Zero();
0241
0242
0243 freeToPath.segment<3>(eFreePos0) =
0244 norm * (dz * localZAxis.transpose() - direction.transpose());
0245
0246
0247 freeToPath.segment<3>(eFreeDir0) =
0248 norm * (pz * localZAxis.transpose() - pcRowVec.transpose());
0249
0250 return freeToPath;
0251 }
0252
0253 AlignmentToPathMatrix LineSurface::alignmentToPathDerivative(
0254 const GeometryContext& gctx, const Vector3& position,
0255 const Vector3& direction) const {
0256 assert(isOnSurface(gctx, position, direction, BoundaryTolerance::Infinite()));
0257
0258
0259 Vector3 pcRowVec = position - center(gctx);
0260
0261 Vector3 localZAxis = lineDirection(gctx);
0262
0263 double pz = pcRowVec.dot(localZAxis);
0264
0265 double dz = localZAxis.dot(direction);
0266 double norm = 1 / (1 - dz * dz);
0267
0268 auto [rotToLocalXAxis, rotToLocalYAxis, rotToLocalZAxis] =
0269 detail::rotationToLocalAxesDerivative(
0270 localToGlobalTransform(gctx).rotation());
0271
0272
0273
0274 AlignmentToPathMatrix alignToPath = AlignmentToPathMatrix::Zero();
0275 alignToPath.segment<3>(eAlignmentCenter0) =
0276 norm * (direction.transpose() - dz * localZAxis.transpose());
0277 alignToPath.segment<3>(eAlignmentRotation0) =
0278 norm * (dz * pcRowVec.transpose() + pz * direction.transpose()) *
0279 rotToLocalZAxis;
0280
0281 return alignToPath;
0282 }
0283
0284 Matrix<2, 3> LineSurface::localCartesianToBoundLocalDerivative(
0285 const GeometryContext& gctx, const Vector3& position) const {
0286
0287 Vector3 localPosition = localToGlobalTransform(gctx).inverse() * position;
0288 double localPhi = VectorHelpers::phi(localPosition);
0289
0290 Matrix<2, 3> loc3DToLocBound = Matrix<2, 3>::Zero();
0291 loc3DToLocBound << std::cos(localPhi), std::sin(localPhi), 0, 0, 0, 1;
0292
0293 return loc3DToLocBound;
0294 }
0295
0296 Vector3 LineSurface::lineDirection(const GeometryContext& gctx) const {
0297 return localToGlobalTransform(gctx).linear().col(2);
0298 }
0299 const std::shared_ptr<const LineBounds>& LineSurface::boundsPtr() const {
0300 return m_bounds;
0301 }
0302 void LineSurface::assignSurfaceBounds(
0303 std::shared_ptr<const LineBounds> newBounds) {
0304 m_bounds = std::move(newBounds);
0305 }
0306
0307 }