ATLAS Offline Software
Loading...
Searching...
No Matches
GeoPrimitivesHelpers.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
6// GeoPrimitivesHelpers.h, (c) ATLAS Detector software
8
9#ifndef GEOPRIMITIVES_GEOPRIMITIVESHELPERS_H
10#define GEOPRIMITIVES_GEOPRIMITIVESHELPERS_H
11
14#include "CxxUtils/sincos.h"
15
16#include "cmath"
17
18#include <vector>
19#include <optional>
20#include <set>
21#include <iostream>
22
23
30
31namespace Amg {
32
33
34
35using SetVector3D = std::set<Amg::Vector3D, Vector3DComparer>;
36using SetVectorVector3D = std::set< std::vector< Amg::Vector3D>, VectorVector3DComparer>;
37
38
39
41inline double angle(const Amg::Vector3D& v1, const Amg::Vector3D& v2) {
42 const double dp = std::clamp(v1.dot(v2) / (v1.mag() * v2.mag()), -1. ,1.);
43 return std::acos(dp);
44}
45
46
48inline float distance2(const Amg::Vector3D& p1, const Amg::Vector3D& p2) {
49 float dx = p2.x()-p1.x(), dy = p2.y()-p1.y(), dz = p2.z()-p1.z();
50 return dx*dx + dy*dy + dz*dz;
51}
52
54inline float distance(const Amg::Vector3D& p1, const Amg::Vector3D& p2) {
55 return std::sqrt( distance2(p1, p2) );
56}
57
58
59
60
62inline void setPhi(Amg::Vector3D& v, double phi) {
63 double xy = v.perp();
65 v[0] = xy * sc.cs;
66 v[1] = xy * sc.sn;
67}
68
70inline void setThetaPhi(Amg::Vector3D& v, double theta, double phi) {
71 double mag = v.mag();
74 v[0] = mag * sct.sn * sc.cs;
75 v[1] = mag * sct.sn * sc.sn;
76 v[2] = mag * sct.cs;
77}
78
80inline void setRThetaPhi(Amg::Vector3D& v, double r, double theta, double phi) {
83 v[0] = r * sct.sn * sc.cs;
84 v[1] = r * sct.sn * sc.sn;
85 v[2] = r * sct.cs;
86}
87
89inline void setTheta(Amg::Vector3D& v, double theta) {
90 setThetaPhi(v, theta, v.phi());
91}
92
94inline void setPerp(Amg::Vector3D& v, double perp) {
95 double p = v.perp();
96 if (p != 0.0) {
97 double scale = perp / p;
98 v[0] *= scale;
99 v[1] *= scale;
100 }
101}
102
104inline void setMag(Amg::Vector3D& v, double mag) {
105 double p = v.mag();
106 if (p != 0.0) {
107 double scale = mag / p;
108 v[0] *= scale;
109 v[1] *= scale;
110 v[2] *= scale;
111 }
112}
113inline double deltaPhi(const Amg::Vector3D& v1, const Amg::Vector3D& v2) {
114 double dphi = v2.phi() - v1.phi();
115 if (dphi > M_PI) {
116 dphi -= M_PI*2;
117 } else if (dphi <= -M_PI) {
118 dphi += M_PI*2;
119 }
120 return dphi;
121}
122inline double deltaR(const Amg::Vector3D& v1, const Amg::Vector3D& v2){
123 double a = v1.eta() - v2.eta();
124 double b = deltaPhi(v1,v2);
125 return sqrt(a*a + b*b);
126}
127
128
129
130
131
132
136inline void setVector3DCartesian(Amg::Vector3D& v1, double x1, double y1, double z1) { v1[0] = x1; v1[1] = y1; v1[2] = z1; }
140inline double mag2Vector3D(const Amg::Vector3D& v1) { return v1.x()*v1.x() + v1.y()*v1.y() + v1.z()*v1.z(); }
144inline double magVector3D(const Amg::Vector3D& v1) { return std::sqrt(mag2Vector3D(v1)); }
148inline double rVector3D(const Amg::Vector3D& v1) { return magVector3D(v1); }
149
157 Amg::Vector3D vect;
158 double vx = v.x(), vy = v.y(), vz = v.z();
160 tr(0,0)*vx + tr(0,1)*vy + tr(0,2)*vz + tr(0,3),
161 tr(1,0)*vx + tr(1,1)*vy + tr(1,2)*vz + tr(1,3),
162 tr(2,0)*vx + tr(2,1)*vy + tr(2,2)*vz + tr(2,3));
163 return vect;
164}
165
166
167
168
169/*
170 * the analogous to CLHEP HepGeom::Transform3D trans (localRot, theSurface.transform().translation());
171 */
173{
174 Amg::Transform3D trans = Amg::Transform3D::Identity();
175 trans = trans * rot;
176 trans.translation() = transl_vec;
177 return trans;
178}
179
180/*
181 * Replacing the CLHEP::HepRotation::getAngleAxis() functionality
182 *
183 * Note:
184 * CLHEP has a 'HepRotation::getAngleAxis()' function, e.g.:
185 * ---
186 * CLHEP::HepRotation rotation = transform.getRotation();
187 * CLHEP::Hep3Vector rotationAxis;
188 * double rotationAngle;
189 * rotation.getAngleAxis(rotationAngle,rotationAxis);
190 * ---
191 */
192inline void getAngleAxisFromRotation(Amg::RotationMatrix3D& rotation, double& rotationAngle, Amg::Vector3D& rotationAxis)
193{
194 rotationAngle = 0.;
195
196 double xx = rotation(0,0);
197 double yy = rotation(1,1);
198 double zz = rotation(2,2);
199
200 double cosa = 0.5 * (xx + yy + zz - 1);
201 double cosa1 = 1 - cosa;
202
203 if (cosa1 <= 0) {
204 rotationAngle = 0;
205 rotationAxis = Amg::Vector3D(0,0,1);
206 }
207 else{
208 double x=0, y=0, z=0;
209 if (xx > cosa) x = std::sqrt((xx-cosa)/cosa1);
210 if (yy > cosa) y = std::sqrt((yy-cosa)/cosa1);
211 if (zz > cosa) z = std::sqrt((zz-cosa)/cosa1);
212 if (rotation(2,1) < rotation(1,2)) x = -x;
213 if (rotation(0,2) < rotation(2,0)) y = -y;
214 if (rotation(1,0) < rotation(0,1)) z = -z;
215 rotationAngle = (cosa < -1.) ? std::acos(-1.) : std::acos(cosa);
216 rotationAxis = Amg::Vector3D(x,y,z);
217 }
218
219 return;
220}
221
226 return Amg::Vector3D(tr(0,3),tr(1,3),tr(2,3));
227} // TODO: check! it's perhaps useless, you acn use the transform.translation() method
228
229
230
238{
239 AngleAxis3D t;
240 t = Eigen::AngleAxis<double>(angle,axis);
241
242 Amg::Rotation3D rot;
243 rot = t;
244
245 return rot;
246}
247
248
253 Amg::Transform3D transf;
254 Amg::AngleAxis3D angleaxis(angle, Amg::Vector3D::UnitX());
255 transf = angleaxis;
256 return transf;
257}
258
262 Amg::Transform3D transf;
263 Amg::AngleAxis3D angleaxis(angle, Amg::Vector3D::UnitY());
264 transf = angleaxis;
265 return transf;
266}
267
271 Amg::Transform3D transf;
272 Amg::AngleAxis3D angleaxis(angle, Amg::Vector3D::UnitZ());
273 transf = angleaxis;
274 return transf;
275}
276
277inline Amg::Transform3D getTranslateX3D(const double X) {
278 return Amg::Transform3D{Amg::Translation3D{X * Amg::Vector3D::UnitX()}};
279}
280
281inline Amg::Transform3D getTranslateY3D(const double Y) {
282 return Amg::Transform3D{Amg::Translation3D{Y * Amg::Vector3D::UnitY()}};
283}
284
285inline Amg::Transform3D getTranslateZ3D(const double Z) {
286 return Amg::Transform3D{Amg::Translation3D{Z * Amg::Vector3D::UnitZ()}};
287}
288
289inline Amg::Transform3D getTranslate3D(const double X, const double Y, const double Z) {
291}
292
296
299inline Amg::Vector3D dirFromAngles(const double phi, const double theta) {
300 const CxxUtils::sincos thetaCS{theta}, phiCS{phi};
301 return Amg::Vector3D{phiCS.cs * thetaCS.sn, phiCS.sn* thetaCS.sn, thetaCS.cs};
302}
303
308template<int N> double lineDistance(const AmgVector(N)& posA,
309 const AmgVector(N)& dirA,
310 const AmgVector(N)& posB,
311 const AmgVector(N)& dirB) {
312
313 const double dirDots = dirA.dot(dirB);
314 const double divisor = (1. - dirDots * dirDots);
315 const AmgVector(N) AminusB = posA - posB;
316 if (std::abs(divisor) < std::numeric_limits<double>::epsilon()) {
317 const AmgVector(N) d = AminusB - dirA.dot(AminusB)*dirA;
318 return std::sqrt(d.dot(d));
319 }
320 const AmgVector(N) lineTravel = AminusB.dot(dirA) * dirA -
321 AminusB.dot(dirB) * dirB;
322 return std::sqrt(std::max(0., AminusB.dot(AminusB) - lineTravel.dot(lineTravel) / divisor));
323}
324
329inline double signedDistance(const Amg::Vector3D& posA,
330 const Amg::Vector3D& dirA,
331 const Amg::Vector3D& posB,
332 const Amg::Vector3D& dirB) {
334 const double dirDots = dirA.dot(dirB);
335 const Amg::Vector3D AminusB = posA - posB;
336 if (std::abs(dirDots -1.) < std::numeric_limits<float>::epsilon()){
337 return (AminusB - dirA.dot(AminusB)*dirA).mag();
338 }
339 const Amg::Vector3D projDir = (dirA - dirDots*dirB).unit();
340 return AminusB.cross(dirB).dot(projDir);
341}
342
347template <int N> std::optional<double> intersect(const AmgVector(N)& posA,
348 const AmgVector(N)& dirA,
349 const AmgVector(N)& posB,
350 const AmgVector(N)& dirB) {
359 const double dirDots = dirA.dot(dirB);
360 const double divisor = (1. - dirDots * dirDots);
362 if (std::abs(divisor) < std::numeric_limits<double>::epsilon()) return std::nullopt;
363 const AmgVector(N) AminusB = posA - posB;
364 return (AminusB.dot(dirB) - AminusB.dot(dirA) * dirDots) / divisor;
365}
366
368template <int N>
369std::optional<double> intersect(const AmgVector(N)& pos,
370 const AmgVector(N)& dir,
371 const AmgVector(N)& planeNorm,
372 const double offset) {
376 const double normDot = planeNorm.dot(dir);
377 if (std::abs(normDot) < std::numeric_limits<double>::epsilon()) return std::nullopt;
378 return (offset - pos.dot(planeNorm)) / normDot;
379}
380
383inline bool doesNotDeform(const Amg::Transform3D& trans) {
384 for (unsigned int d = 0; d < 3 ; ++d) {
385 const double defLength = Amg::Vector3D::Unit(d).dot(trans.linear() * Amg::Vector3D::Unit(d));
386 if (std::abs(defLength - 1.) > std::numeric_limits<float>::epsilon()) {
387 return false;
388 }
389 }
390 return true;
391}
392
393inline bool isIdentity(const Amg::Transform3D& trans) {
394 return doesNotDeform(trans) &&
395 trans.translation().mag() < std::numeric_limits<float>::epsilon();
396}
397
398
399} // end of Amg namespace
400
401#endif
#define M_PI
Scalar perp() const
perp method - perpendicular length
Scalar phi() const
phi method
Scalar theta() const
theta method
Scalar mag() const
mag method
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.
#define AmgVector(rows)
static Double_t a
static Double_t sc
int r
Definition globals.cxx:22
Definition of ATLAS Math & Geometry primitives (Amg)
Amg::Transform3D getRotateX3D(double angle)
get a rotation transformation around X-axis
void setVector3DCartesian(Amg::Vector3D &v1, double x1, double y1, double z1)
Sets components in cartesian coordinate system.
std::set< Amg::Vector3D, Vector3DComparer > SetVector3D
double mag2Vector3D(const Amg::Vector3D &v1)
Gets magnitude squared of the vector.
Amg::Transform3D getTranslate3D(const double X, const double Y, const double Z)
: Returns a shift transformation along an arbitrary axis
std::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the point B' along the line B that's closest to a second line A.
double deltaPhi(const Amg::Vector3D &v1, const Amg::Vector3D &v2)
Eigen::AngleAxisd AngleAxis3D
void setRThetaPhi(Amg::Vector3D &v, double r, double theta, double phi)
sets radius, the theta and phi angle of a vector.
double lineDistance(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
: Calculates the shortest distance between two lines
Amg::Vector3D getTranslationVectorFromTransform(const Amg::Transform3D &tr)
Get the Translation vector out of a Transformation.
Eigen::Quaternion< double > Rotation3D
double signedDistance(const Amg::Vector3D &posA, const Amg::Vector3D &dirA, const Amg::Vector3D &posB, const Amg::Vector3D &dirB)
Calculates the signed distance between two lines in 3D space.
double rVector3D(const Amg::Vector3D &v1)
Gets r-component in spherical coordinate system.
Eigen::Matrix< double, 3, 3 > RotationMatrix3D
bool isIdentity(const Amg::Transform3D &trans)
Checks whether the transformation is the Identity transformation.
bool doesNotDeform(const Amg::Transform3D &trans)
Checks whether the linear part of the transformation rotates or stetches any of the basis vectors.
std::set< std::vector< Amg::Vector3D >, VectorVector3DComparer > SetVectorVector3D
Amg::Transform3D getTranslateZ3D(const double Z)
: Returns a shift transformation along the z-axis
Amg::RotationMatrix3D setPhi(Amg::RotationMatrix3D mat, double angle, int convention=0)
void getAngleAxisFromRotation(Amg::RotationMatrix3D &rotation, double &rotationAngle, Amg::Vector3D &rotationAxis)
void setMag(Amg::Vector3D &v, double mag)
scales the vector length without changing the angles
Amg::Vector3D dirFromAngles(const double phi, const double theta)
Constructs a direction vector from the azimuthal & polar angles.
Amg::Transform3D getTransformFromRotTransl(Amg::RotationMatrix3D rot, Amg::Vector3D transl_vec)
double angle(const Amg::Vector3D &v1, const Amg::Vector3D &v2)
calculates the opening angle between two vectors
float distance2(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the squared distance between two point in 3D space
void setPerp(Amg::Vector3D &v, double perp)
scales the vector in the xy plane without changing the z coordinate nor the angles
Amg::Transform3D getTranslateY3D(const double Y)
: Returns a shift transformation along the y-axis
Amg::Transform3D getRotateZ3D(double angle)
get a rotation transformation around Z-axis
Eigen::Affine3d Transform3D
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Amg::Transform3D getTranslateX3D(const double X)
: Returns a shift transformation along the x-axis
Amg::Rotation3D getRotation3DfromAngleAxis(double angle, Amg::Vector3D &axis)
get a AngleAxis from an angle and an axis.
Amg::Vector3D transform(Amg::Vector3D &v, Amg::Transform3D &tr)
Transform a point from a Trasformation3D.
Eigen::Matrix< double, 3, 1 > Vector3D
Amg::Transform3D getRotateY3D(double angle)
get a rotation transformation around Y-axis
double magVector3D(const Amg::Vector3D &v1)
Gets magnitude of the vector.
void setTheta(Amg::Vector3D &v, double theta)
sets the theta of a vector without changing phi nor the magnitude
void setThetaPhi(Amg::Vector3D &v, double theta, double phi)
sets the theta and phi angle of a vector without changing the magnitude
Eigen::Translation< double, 3 > Translation3D
double deltaR(const Amg::Vector3D &v1, const Amg::Vector3D &v2)
Helper to simultaneously calculate sin and cos of the same angle.
Helper to simultaneously calculate sin and cos of the same angle.
Definition sincos.h:39