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