ATLAS Offline Software
Loading...
Searching...
No Matches
ConeSurface.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
6// ConeSurface.cxx, (c) ATLAS Detector Software
8
9// Trk
12// Gaudi
13#include "GaudiKernel/MsgStream.h"
14//CxxUtils
16
17// default constructor
19 : Trk::Surface()
20 , m_bounds(nullptr)
21 , m_referencePoint(nullptr)
22 , m_rotSymmetryAxis(nullptr)
23{}
24
25// copy constructor
27 : Trk::Surface(csf)
28 , m_bounds(csf.m_bounds)
29 , m_referencePoint(nullptr)
30 , m_rotSymmetryAxis(nullptr)
31{}
32
33// copy constructor with shift
35 const Amg::Transform3D& transf)
36 : Trk::Surface(csf, transf)
37 , m_bounds(csf.m_bounds)
38 , m_referencePoint(nullptr)
39 , m_rotSymmetryAxis(nullptr)
40{}
41
42// constructor by opening angle and whether its symmetric or a single cone
44 double alpha,
45 bool symmetric)
46 : Trk::Surface(htrans)
47 , m_bounds(std::make_shared<const Trk::ConeBounds>(alpha, symmetric))
48 , m_referencePoint(nullptr)
49 , m_rotSymmetryAxis(nullptr)
50{}
51
52// constructor by opening angle and its z values
54 double alpha,
55 double zmin,
56 double zmax,
57 double halfPhi)
58 : Trk::Surface(htrans)
59 , m_bounds(std::make_shared<const Trk::ConeBounds>(alpha, zmin, zmax, halfPhi))
60 , m_referencePoint(nullptr)
61 , m_rotSymmetryAxis(nullptr)
62{}
63
64// constructor by ConeBounds
66 std::shared_ptr<const Trk::ConeBounds> cbounds)
67 : Trk::Surface(htrans)
68 , m_bounds(std::move(cbounds))
69 , m_referencePoint(nullptr)
70 , m_rotSymmetryAxis(nullptr)
71{
72}
73
74// constructor from transform, bounds not set.
76 : Trk::Surface(htrans)
77 , m_bounds(nullptr)
78 , m_referencePoint(nullptr)
79 , m_rotSymmetryAxis(nullptr)
80{}
81
84{
85 if (this != &csf) {
87 m_bounds = csf.m_bounds;
88 m_referencePoint.store(nullptr);
89 m_rotSymmetryAxis.store(nullptr);
90 }
91 return *this;
92}
93
98 double l1, double l2, double phi, double theta, double qop,
99 std::optional<AmgSymMatrix(5)> cov) const {
100 return std::make_unique<ParametersT<5, Charged, ConeSurface>>(
101 l1, l2, phi, theta, qop, *this, std::move(cov));
102}
103
107 const Amg::Vector3D& position, const Amg::Vector3D& momentum, double charge,
108 std::optional<AmgSymMatrix(5)> cov) const {
109 return std::make_unique<ParametersT<5, Charged, ConeSurface>>(
110 position, momentum, charge, *this, std::move(cov));
111}
112
117 double l1, double l2, double phi, double theta, double qop,
118 std::optional<AmgSymMatrix(5)> cov) const {
119 return std::make_unique<ParametersT<5, Neutral, ConeSurface>>(
120 l1, l2, phi, theta, qop, *this, std::move(cov));
121}
122
127 const Amg::Vector3D& position, const Amg::Vector3D& momentum, double charge,
128 std::optional<AmgSymMatrix(5)> cov) const {
129 return std::make_unique<ParametersT<5, Neutral, ConeSurface>>(
130 position, momentum, charge, *this, std::move(cov));
131}
132
133// TODO: is the 0 always the cone center?
134const Amg::Vector3D&
136{
137 if (!m_referencePoint) {
138 // this is what was in cylinder
139 // double rMedium = bounds().r();
140 // double phi = bounds().averagePhi();
141 // Trk::GlobalPosition gp(rMedium*cos(phi), rMedium*sin(phi), 0.);
142 Amg::Vector3D gp(0., 0., 0.);
143 m_referencePoint.set(std::make_unique<Amg::Vector3D>(transform() * gp));
144 }
145 return (*m_referencePoint);
146}
147
148bool
150{
151 // first check the type not to compare apples with oranges
152 if (sf.type()!=Trk::SurfaceType::Cone){
153 return false;
154 }
155 return (*this) == static_cast<const Trk::ConeSurface&>(sf);
156}
157
158const Amg::Vector3D&
160{
161 if (!m_rotSymmetryAxis) {
162 Amg::Vector3D zAxis(transform().rotation().col(2));
163 m_rotSymmetryAxis.set(std::make_unique<Amg::Vector3D>(zAxis));
164 }
165 return (*m_rotSymmetryAxis);
166}
167
168// return the measurement frame: it's the tangential plane
171{
173 // construct the measurement frame
174 Amg::Vector3D measY(transform().rotation().col(2)); // measured Y is the z axis
175 Amg::Vector3D measDepth =
176 Amg::Vector3D(pos.x(), pos.y(), 0.).unit(); // measured z is the position transverse normalized
177 Amg::Vector3D measX(measY.cross(measDepth).unit()); // measured X is what comoes out of it
178 // the columnes
179 mFrame.col(0) = measX;
180 mFrame.col(1) = measY;
181 mFrame.col(2) = measDepth;
182 // return the rotation matrix
184 // return it
185 return mFrame;
186}
187// Avoid out-of-line-eigen calls
189void
191{
192 // create the position in the local 3d frame
193 double r = locpos[Trk::locZ] * bounds().tanAlpha();
194 double phi = locpos[Trk::locRPhi] / r;
195 Amg::Vector3D loc3Dframe(r * cos(phi), r * sin(phi), locpos[Trk::locZ]);
196 // transport it to the globalframe
197 glopos = transform() * loc3Dframe;
198}
199
200bool
202{
203 Amg::Vector3D loc3Dframe(inverseTransformMultHelper(glopos));
204 double r = loc3Dframe.z() * bounds().tanAlpha();
205 locpos = Amg::Vector2D(r * atan2(loc3Dframe.y(), loc3Dframe.x()), loc3Dframe.z());
206 // now decide on the quility of the transformation
207 // double inttol = r*0.0001;
208 // inttol = (inttol<0.01) ? 0.01 : 0.01; // ?
209 double inttol = 0.01;
210 return ((loc3Dframe.perp() - r) <= inttol);
211}
212
215 const Amg::Vector3D& dir,
216 bool forceDir,
217 Trk::BoundaryCheck bchk) const
218{
219 // transform to a frame with the cone along z, with the tip at 0
220 const Amg::Transform3D surfaceTrans = inverseTransformHelper();
221 Amg::Vector3D tpos1 = surfaceTrans * pos;
222 Amg::Vector3D tdir = surfaceTrans.linear() * dir;
223 // see the header for the formula derivation
224 double tan2Alpha = bounds().tanAlpha() * bounds().tanAlpha();
225 double A = tdir.x() * tdir.x() + tdir.y() * tdir.y() - tan2Alpha * tdir.z() * tdir.z();
226 double B = 2 * (tdir.x() * tpos1.x() + tdir.y() * tpos1.y() - tan2Alpha * dir.z() * tpos1.z());
227 double C = tpos1.x() * tpos1.x() + tpos1.y() * tpos1.y() - tan2Alpha * tpos1.z() * tpos1.z();
228 if (A == 0.)
229 A += 1e-16; // avoid div by zero
230
231 // use Andreas' quad solver, much more stable than what I wrote
232 Trk::RealQuadraticEquation solns(A, B, C);
233
234 Amg::Vector3D solution(0., 0., 0.);
235 double path = 0.;
236 bool isValid = false;
237 if (solns.solutions != Trk::none) {
238 double t1 = solns.first;
239 Amg::Vector3D soln1Loc(tpos1 + t1 * dir);
240 isValid = forceDir ? (t1 > 0.) : true;
241 // there's only one solution
242 if (solns.solutions == Trk::one) {
243 solution = soln1Loc;
244 path = t1;
245 } else {
246 double t2 = solns.second;
247 Amg::Vector3D soln2Loc(tpos1 + t2 * dir);
248 // both solutions have the same sign
249 if (t1 * t2 > 0. || !forceDir) {
250 if (t1 * t1 < t2 * t2) {
251 solution = soln1Loc;
252 path = t1;
253 } else {
254 solution = soln2Loc;
255 path = t2;
256 }
257 } else {
258 if (t1 > 0.) {
259 solution = soln1Loc;
260 path = t1;
261 } else {
262 solution = soln2Loc;
263 path = t2;
264 }
265 }
266 }
267 }
268 solution = transform() * solution;
269
270 isValid = bchk ? (isValid && isOnSurface(solution)) : isValid;
271 return Trk::Intersection(solution, path, isValid);
272}
273
275
276// TODO understand what is going on here (copied from cylinder,
277// because i really don't see what the idea is here vs. the other
278// straightLineDistanceEstimate, and this is harder to see whats
279// happening.
282{
283 return straightLineDistanceEstimate(pos, dir, false);
284}
285
288{
289 double tol = 0.001;
290
291 Amg::Vector3D Cntr = center(); // tip of the cone (i.e. join between halves)
292 Amg::Vector3D N = normal(); // this is the z-direction of the cone in
293 // global coordiantes i believe
294
295 Amg::Vector3D dPos = pos - Cntr; // pos w.r.t. cone tip
296 double posLength = sqrt(dPos.dot(dPos));
297 if (posLength < tol) // at origin of cone => on cone (avoid div by zero)
298 return {1, 0., true, 0.};
299 double posProj = dPos.dot(N);
300 double posProjAngle = acos(posProj / posLength);
301 double currDist = posLength * sin(posProjAngle - atan(bounds().tanAlpha()));
302 // solution on the surface
303 if (std::abs(currDist) < tol)
304 return {1, currDist, true, 0.};
305
306 // transform to a frame with the cone along z, with the tip a 0
307 Amg::Vector3D locFramePos = inverseTransformMultHelper(pos);
308 Amg::Vector3D locFrameDir = transform().rotation().inverse() * dir.normalized();
309
310 // solutions are in the form of a solution to a quadratic eqn.
311 double tan2Alpha = bounds().tanAlpha() * bounds().tanAlpha();
312 double A = locFrameDir.x() * locFrameDir.x() + locFrameDir.y() * locFrameDir.y() -
313 tan2Alpha * locFrameDir.z() * locFrameDir.z();
314 double B = 2 * (locFrameDir.x() * locFramePos.x() + locFrameDir.y() * locFramePos.y() -
315 tan2Alpha * locFrameDir.z() * locFramePos.z());
316 double C = locFramePos.x() * locFramePos.x() + locFramePos.y() * locFramePos.y() -
317 tan2Alpha * locFramePos.z() * locFramePos.z();
318 if (A == 0.)
319 A += 1e-16; // avoid div by zero
320 // use Andreas' quad solver, much more stable than what I wrote
321 Trk::RealQuadraticEquation solns(A, B, C);
322
323 double d2bound = 0.;
324 if (bound && solns.solutions != Trk::none) {
325 std::optional<Amg::Vector2D> p = std::nullopt;
326 if (std::abs(solns.first) < std::abs(solns.second)){
327 p = Surface::globalToLocal(locFramePos + solns.first * locFrameDir);
328 }
329 else{
330 p = Surface::globalToLocal(locFramePos + solns.second * locFrameDir);
331 }
332 if (p) {
333 d2bound = bounds().minDistance(*p);
334 }
335 if (d2bound < 0){
336 d2bound = 0;
337 }
338 }
339 double totDist = d2bound > 0. ? sqrt(d2bound * d2bound + currDist * currDist) : currDist;
340
341 switch (solns.solutions) {
342 case Trk::none:{
343 return {0, totDist, true, 0., 0.};
344 }
345 case Trk::one:{
346 return {1, totDist, true, solns.first};
347 }
348 case Trk::two:{
349 if (std::abs(solns.first) < std::abs(solns.second)){
350 return {2, totDist, true, solns.first, solns.second};
351 }
352 return {2, totDist, true, solns.second, solns.first};
353 }
354 default:{
355 return {0, totDist, true, 0., 0.};
356 }
357 };
358}
359
360double
362{
363 // (cos phi cos alpha, sin phi cos alpha, sgn z sin alpha)
364 bool applyTransform = !(transform().isApprox(Amg::Transform3D::Identity()));
365 Amg::Vector3D posLocal = applyTransform ? inverseTransformMultHelper(pos) : pos;
366 double phi = posLocal.phi();
367 double sgn = posLocal.z() > 0. ? -1. : +1.;
368 Amg::Vector3D normalC(cos(phi) * bounds().cosAlpha(), sin(phi) * bounds().cosAlpha(), sgn * bounds().sinAlpha());
369 if (applyTransform)
370 normalC = transform().linear() * normalC;
371 // back in global frame
372 double cAlpha = normalC.dot(mom.unit());
373 return (cAlpha != 0.) ? std::abs(1. / cAlpha) : 1.; // ST undefined for cAlpha=0
374}
double charge(const T &p)
Definition AtlasPID.h:997
bool isValid(const T &p)
Av: we implement here an ATLAS-sepcific convention: all particles which are 99xxxxx are fine.
Definition AtlasPID.h:878
#define AmgSymMatrix(dim)
The BoundaryCheck class allows to steer the way surface boundaries are used for inside/outside checks...
Bounds for a conical Surface, the opening angle is stored in and always positively defined.
Definition ConeBounds.h:44
Class for a conical surface in the ATLAS detector.
Definition ConeSurface.h:51
CxxUtils::CachedUniquePtr< Amg::Vector3D > m_rotSymmetryAxis
virtual const ConeBounds & bounds() const override final
This method returns the ConeBounds by reference (NoBounds is not possible for cone)
virtual const Amg::Vector3D & rotSymmetryAxis() const
Return method for the rotational symmetry axis - the z-Axis of the HepTransform.
virtual const Amg::Vector3D & globalReferencePoint() const override final
Returns a global reference point: For the Cylinder this is Where denotes the averagePhi() of the cy...
virtual double pathCorrection(const Amg::Vector3D &, const Amg::Vector3D &) const override
the pathCorrection for derived classes with thickness
ConeSurface()
Default Constructor.
virtual Amg::Vector3D normal(const Amg::Vector2D &locpo) const override final
Return method for surface normal information at a given local point, overwrites the normal() from bas...
virtual DistanceSolution straightLineDistanceEstimate(const Amg::Vector3D &pos, const Amg::Vector3D &dir) const override final
fast straight line distance to Surface
virtual void localToGlobal(const Amg::Vector2D &locp, const Amg::Vector3D &mom, Amg::Vector3D &glob) const override final
Specialized for ConeSurface : LocalToGlobal method without dynamic memory allocation.
virtual Surface::ChargedTrackParametersUniquePtr createUniqueTrackParameters(double l1, double l2, double phi, double theta, double qop, std::optional< AmgSymMatrix(5)> cov=std::nullopt) const override final
Use the Surface as a ParametersBase constructor, from local parameters - charged.
std::shared_ptr< const ConeBounds > m_bounds
The global reference point (== a point on thesurface)
virtual bool operator==(const Surface &sf) const override
Equality operator.
ConeSurface & operator=(const ConeSurface &csf)
Assignment operator.
virtual NeutralTrackParametersUniquePtr createUniqueNeutralParameters(double l1, double l2, double phi, double theta, double qop, std::optional< AmgSymMatrix(5)> cov=std::nullopt) const override final
Use the Surface as a ParametersBase constructor, from local parameters - neutral.
virtual Amg::RotationMatrix3D measurementFrame(const Amg::Vector3D &glopos, const Amg::Vector3D &glomom) const override final
Return the measurement frame - this is needed for alignment, in particular for StraightLine and Perig...
virtual bool globalToLocal(const Amg::Vector3D &glob, const Amg::Vector3D &mom, Amg::Vector2D &loc) const override final
Specialized for ConeSurface : GlobalToLocal method without dynamic memory allocation - boolean checks...
CxxUtils::CachedUniquePtr< Amg::Vector3D > m_referencePoint
The rotational symmetry axis.
virtual Intersection straightLineIntersection(const Amg::Vector3D &pos, const Amg::Vector3D &dir, bool forceDir=false, BoundaryCheck bchk=false) const override final
fast straight line intersection schema - provides closest intersection and (signed) path length
Access to distance solutions.
Abstract Base Class for tracking surfaces.
Amg::Transform3D inverseTransformHelper() const
Helper method to factorize in one place common operations calculate inverse transofrm and multiply wi...
std::unique_ptr< ParametersBase< 5, Trk::Charged > > ChargedTrackParametersUniquePtr
Unique ptr types.
Surface & operator=(const Surface &sf)
Definition Surface.cxx:91
virtual bool globalToLocal(const Amg::Vector3D &glob, const Amg::Vector3D &mom, Amg::Vector2D &loc) const =0
Specified by each surface type: GlobalToLocal method without dynamic memory allocation - boolean chec...
Amg::Vector3D inverseTransformMultHelper(const Amg::Vector3D &glopos) const
Surface()
Default Constructor for inheriting classes.
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
virtual bool isOnSurface(const Amg::Vector3D &glopo, const BoundaryCheck &bchk=true, double tol1=0., double tol2=0.) const
This method returns true if the GlobalPosition is on the Surface for both, within or without check of...
Definition Surface.cxx:123
const Amg::Vector3D & center() const
Returns the center position of the Surface.
std::unique_ptr< ParametersBase< 5, Trk::Neutral > > NeutralTrackParametersUniquePtr
int r
Definition globals.cxx:22
#define ATH_FLATTEN
struct color C
Eigen::Matrix< double, 3, 3 > RotationMatrix3D
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
Ensure that the ATLAS eigen extensions are properly loaded.
@ locRPhi
Definition ParamDefs.h:40
@ theta
Definition ParamDefs.h:66
@ phi
Definition ParamDefs.h:75
@ locZ
local cylindrical
Definition ParamDefs.h:42
STL namespace.
hold the test vectors and ease the comparison