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#include <sstream>
18#include <stdexcept>
19
20#include <vector>
21#include <optional>
22#include <set>
23#include <iostream>
24
25
32
33namespace Amg {
34
35
36
37using SetVector3D = std::set<Amg::Vector3D, Vector3DComparer>;
38using SetVectorVector3D = std::set< std::vector< Amg::Vector3D>, VectorVector3DComparer>;
39
40
41
43inline double angle(const Amg::Vector3D& v1, const Amg::Vector3D& v2) {
44 const double dp = std::clamp(v1.dot(v2) / (v1.mag() * v2.mag()), -1. ,1.);
45 return std::acos(dp);
46}
47
48
50inline float distance2(const Amg::Vector3D& p1, const Amg::Vector3D& p2) {
51 float dx = p2.x()-p1.x(), dy = p2.y()-p1.y(), dz = p2.z()-p1.z();
52 return dx*dx + dy*dy + dz*dz;
53}
54
56inline float distance(const Amg::Vector3D& p1, const Amg::Vector3D& p2) {
57 return std::sqrt( distance2(p1, p2) );
58}
59
60
61
62
64inline void setPhi(Amg::Vector3D& v, double phi) {
65 double xy = v.perp();
67 v[0] = xy * sc.cs;
68 v[1] = xy * sc.sn;
69}
70
72inline void setThetaPhi(Amg::Vector3D& v, double theta, double phi) {
73 double mag = v.mag();
76 v[0] = mag * sct.sn * sc.cs;
77 v[1] = mag * sct.sn * sc.sn;
78 v[2] = mag * sct.cs;
79}
80
82inline void setRThetaPhi(Amg::Vector3D& v, double r, double theta, double phi) {
85 v[0] = r * sct.sn * sc.cs;
86 v[1] = r * sct.sn * sc.sn;
87 v[2] = r * sct.cs;
88}
89
91inline void setTheta(Amg::Vector3D& v, double theta) {
92 setThetaPhi(v, theta, v.phi());
93}
94
96inline void setPerp(Amg::Vector3D& v, double perp) {
97 double p = v.perp();
98 if (p != 0.0) {
99 double scale = perp / p;
100 v[0] *= scale;
101 v[1] *= scale;
102 }
103}
104
105inline double deltaPhi(const Amg::Vector3D& v1, const Amg::Vector3D& v2) {
106 double dphi = v2.phi() - v1.phi();
107 if (dphi > M_PI) {
108 dphi -= M_PI*2;
109 } else if (dphi <= -M_PI) {
110 dphi += M_PI*2;
111 }
112 return dphi;
113}
114inline double deltaR(const Amg::Vector3D& v1, const Amg::Vector3D& v2){
115 return std::hypot(v1.eta() - v2.eta(), deltaPhi(v1,v2));
116}
117
118/*
119 * the analogous to CLHEP HepGeom::Transform3D trans (localRot, theSurface.transform().translation());
120 */
122 const Amg::Vector3D& translation)
123{
124 Amg::Isometry3D trans{Amg::Isometry3D::Identity()};
125 trans.linear() = rotation;
126 trans.translation() = translation;
127 return trans;
128}
129
130/*
131 * Replacing the CLHEP::HepRotation::getAngleAxis() functionality
132 *
133 * Note:
134 * CLHEP has a 'HepRotation::getAngleAxis()' function, e.g.:
135 * ---
136 * CLHEP::HepRotation rotation = transform.getRotation();
137 * CLHEP::Hep3Vector rotationAxis;
138 * double rotationAngle;
139 * rotation.getAngleAxis(rotationAngle,rotationAxis);
140 * ---
141 */
142inline void getAngleAxisFromRotation(Amg::RotationMatrix3D& rotation, double& rotationAngle, Amg::Vector3D& rotationAxis)
143{
144 rotationAngle = 0.;
145
146 double xx = rotation(0,0);
147 double yy = rotation(1,1);
148 double zz = rotation(2,2);
149
150 double cosa = 0.5 * (xx + yy + zz - 1);
151 double cosa1 = 1 - cosa;
152
153 if (cosa1 <= 0) {
154 rotationAngle = 0;
155 rotationAxis = Amg::Vector3D(0,0,1);
156 }
157 else{
158 double x=0, y=0, z=0;
159 if (xx > cosa) x = std::sqrt((xx-cosa)/cosa1);
160 if (yy > cosa) y = std::sqrt((yy-cosa)/cosa1);
161 if (zz > cosa) z = std::sqrt((zz-cosa)/cosa1);
162 if (rotation(2,1) < rotation(1,2)) x = -x;
163 if (rotation(0,2) < rotation(2,0)) y = -y;
164 if (rotation(1,0) < rotation(0,1)) z = -z;
165 rotationAngle = (cosa < -1.) ? std::acos(-1.) : std::acos(cosa);
166 rotationAxis = Amg::Vector3D(x,y,z);
167 }
168
169 return;
170}
171
172
182
183
187 return Amg::Isometry3D{Amg::AngleAxis3D{angle, Amg::Vector3D::UnitX()}};
188}
189
192 return Amg::Isometry3D{Amg::AngleAxis3D{angle, Amg::Vector3D::UnitY()}};
193}
194
197 return Amg::Isometry3D{Amg::AngleAxis3D{angle, Amg::Vector3D::UnitZ()}};
198}
199
200inline Amg::Isometry3D getTranslateX3D(const double X) {
201 return Amg::Isometry3D{Amg::Translation3D{X * Amg::Vector3D::UnitX()}};
202}
203
204inline Amg::Isometry3D getTranslateY3D(const double Y) {
205 return Amg::Isometry3D{Amg::Translation3D{Y * Amg::Vector3D::UnitY()}};
206}
207
208inline Amg::Isometry3D getTranslateZ3D(const double Z) {
209 return Amg::Isometry3D{Amg::Translation3D{Z * Amg::Vector3D::UnitZ()}};
210}
211
212inline Amg::Isometry3D getTranslate3D(const double X, const double Y, const double Z) {
214}
215
219
220[[deprecated("Isometries don't need to be transformed.")]]
222 return iso;
223}
224
232 assert((trf.linear() * trf.linear().transpose() -
233 Amg::RotationMatrix3D::Identity()).cwiseAbs().maxCoeff() < 1.e-6);
234 Amg::Isometry3D iso{Amg::Isometry3D::Identity()};
235 iso.linear() = trf.linear();
236 iso.translation() = trf.translation();
237 return iso;
238}
239
243inline Amg::Vector3D dirFromAngles(const double phi, const double theta) {
244 const CxxUtils::sincos thetaCS{theta}, phiCS{phi};
245 return Amg::Vector3D{phiCS.cs * thetaCS.sn, phiCS.sn* thetaCS.sn, thetaCS.cs};
246}
247
253 const Amg::Vector3D& planeNorm) {
254 return (direction - planeNorm.dot(direction) * planeNorm).unit();
255}
256
262template<int N> double lineDistance(const AmgVector(N)& posA,
263 const AmgVector(N)& dirA,
264 const AmgVector(N)& posB,
265 const AmgVector(N)& dirB) {
266
267 const double dirDots = dirA.dot(dirB);
268 const double divisor = (1. - dirDots * dirDots);
269 const AmgVector(N) AminusB = posA - posB;
270 if (std::abs(divisor) < std::numeric_limits<double>::epsilon()) {
271 const AmgVector(N) d = AminusB - dirA.dot(AminusB)*dirA;
272 return std::sqrt(d.dot(d));
273 }
274 const AmgVector(N) lineTravel = AminusB.dot(dirA) * dirA -
275 AminusB.dot(dirB) * dirB;
276 return std::sqrt(std::max(0., AminusB.dot(AminusB) - lineTravel.dot(lineTravel) / divisor));
277}
278
283inline double signedDistance(const Amg::Vector3D& posA,
284 const Amg::Vector3D& dirA,
285 const Amg::Vector3D& posB,
286 const Amg::Vector3D& dirB) {
288 const double dirDots = dirA.dot(dirB);
289 const Amg::Vector3D AminusB = posA - posB;
290 if (std::abs(dirDots -1.) < std::numeric_limits<float>::epsilon()){
291 return (AminusB - dirA.dot(AminusB)*dirA).mag();
292 }
293 const Amg::Vector3D projDir = (dirA - dirDots*dirB).unit();
294 return AminusB.cross(dirB).dot(projDir);
295}
296
301template <int N> std::optional<double> intersect(const AmgVector(N)& posA,
302 const AmgVector(N)& dirA,
303 const AmgVector(N)& posB,
304 const AmgVector(N)& dirB) {
313 const double dirDots = dirA.dot(dirB);
314 const double divisor = (1. - dirDots * dirDots);
316 if (std::abs(divisor) < std::numeric_limits<double>::epsilon()) return std::nullopt;
317 const AmgVector(N) AminusB = posA - posB;
318 return (AminusB.dot(dirB) - AminusB.dot(dirA) * dirDots) / divisor;
319}
320
322template <int N>
323std::optional<double> intersect(const AmgVector(N)& pos,
324 const AmgVector(N)& dir,
325 const AmgVector(N)& planeNorm,
326 const double offset) {
330 const double normDot = planeNorm.dot(dir);
331 if (std::abs(normDot) < std::numeric_limits<double>::epsilon()) return std::nullopt;
332 return (offset - pos.dot(planeNorm)) / normDot;
333}
334
338 for (unsigned int d = 0; d < 3 ; ++d) {
339 const double defLength = Amg::Vector3D::Unit(d).dot(trans.linear() * Amg::Vector3D::Unit(d));
340 if (std::abs(defLength - 1.) > std::numeric_limits<float>::epsilon()) {
341 return false;
342 }
343 }
344 return true;
345}
346
347inline bool isIdentity(const Amg::Transform3D& trans) {
348 return doesNotDeform(trans) &&
349 trans.translation().mag() < std::numeric_limits<float>::epsilon();
350}
351
352
353} // end of Amg namespace
354
355#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
detray::unit< scalar_t > unit
#define AmgVector(rows)
static Double_t sc
TH1F * trans(TH1F *h, bool t=false)
int r
Definition globals.cxx:22
Definition of ATLAS Math & Geometry primitives (Amg).
Amg::Vector3D projectDirOntoPlane(const Amg::Vector3D &direction, const Amg::Vector3D &planeNorm)
Project the direction vector onto the plane and renormalize to unity.
Amg::Isometry3D getRotateX3D(double angle)
Rotate the coordinate system by an angle around the x-axis.
std::set< Amg::Vector3D, Vector3DComparer > SetVector3D
Amg::Isometry3D getTransformFromRotTransl(const Amg::RotationMatrix3D &rotation, const Amg::Vector3D &translation)
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
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.
Amg::Isometry3D getTranslateY3D(const double Y)
: Returns a shift transformation along the y-axis
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::RotationMatrix3D setPhi(Amg::RotationMatrix3D mat, double angle, int convention=0)
void getAngleAxisFromRotation(Amg::RotationMatrix3D &rotation, double &rotationAngle, Amg::Vector3D &rotationAxis)
Eigen::Isometry3d Isometry3D
Amg::Vector3D dirFromAngles(const double phi, const double theta)
Constructs a direction vector from the azimuthal & polar angles.
Amg::Isometry3D getTranslateX3D(const double X)
: Returns a shift transformation along the x-axis
double angle(const Amg::Vector3D &v1, const Amg::Vector3D &v2)
calculates the opening angle between two vectors
Amg::Isometry3D getTranslate3D(const double X, const double Y, const double Z)
: Returns a shift transformation along an arbitrary axis
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
Eigen::Affine3d Transform3D
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Amg::Isometry3D toIsometry3D(const Isometry3D &iso)
Amg::Rotation3D getRotation3DfromAngleAxis(double angle, Amg::Vector3D &axis)
get a AngleAxis from an angle and an axis.
Eigen::Matrix< double, 3, 1 > Vector3D
void setTheta(Amg::Vector3D &v, double theta)
sets the theta of a vector without changing phi nor the magnitude
Amg::Isometry3D getTranslateZ3D(const double Z)
: Returns a shift transformation along the z-axis
void setThetaPhi(Amg::Vector3D &v, double theta, double phi)
sets the theta and phi angle of a vector without changing the magnitude
Amg::Isometry3D getRotateY3D(double angle)
Rotate the coordinate system by an angle around the z-axis.
Amg::Isometry3D getRotateZ3D(double angle)
Rotate the coordinate system by an angle around the z-axis.
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