Files
geant4/source/externals/clhep/src/LorentzRotationD.cc
T
2016-06-09 16:46:55 +02:00

213 lines
5.6 KiB
C++

// -*- C++ -*-
// ---------------------------------------------------------------------------
//
// This file is a part of the CLHEP - a Class Library for High Energy Physics.
//
// This is the implementation of those parts of the HepLorentzRotation class
// which involve decomposition into Boost*Rotation.
#ifdef GNUPRAGMA
#pragma implementation
#endif
#include "CLHEP/Vector/LorentzRotation.h"
namespace CLHEP {
// ---------- Decomposition:
void HepLorentzRotation::decompose
(HepBoost & boost, HepRotation & rotation) const {
// The boost will be the pure boost based on column 4 of the transformation
// matrix. Since the constructor takes the beta vector, and not beta*gamma,
// we first divide through by gamma = the tt element. This of course can
// never be zero since the last row has t**2 - v**2 = +1.
Hep3Vector betaVec ( xt(), yt(), zt() );
betaVec *= 1.0 / tt();
boost.set( betaVec );
// The rotation will be inverse of B times T.
HepBoost B( -betaVec );
HepLorentzRotation R( B * *this );
HepRep3x3 m3 ( R.xx(), R.xy(), R.xz(),
R.yx(), R.yy(), R.yz(),
R.zx(), R.zy(), R.zz() );
rotation.set( m3 );
rotation.rectify();
return;
}
void HepLorentzRotation::decompose
(Hep3Vector & boost, HepAxisAngle & rotation) const {
HepRotation r;
HepBoost b;
decompose(b,r);
boost = b.boostVector();
rotation = r.axisAngle();
return;
}
void HepLorentzRotation::decompose
(HepRotation & rotation, HepBoost & boost) const {
// In this case the pure boost is based on row 4 of the matrix.
Hep3Vector betaVec( tx(), ty(), tz() );
betaVec *= 1.0 / tt();
boost.set( betaVec );
// The rotation will be T times the inverse of B.
HepBoost B( -betaVec );
HepLorentzRotation R( *this * B );
HepRep3x3 m3 ( R.xx(), R.xy(), R.xz(),
R.yx(), R.yy(), R.yz(),
R.zx(), R.zy(), R.zz() );
rotation.set( m3 );
rotation.rectify();
return;
}
void HepLorentzRotation::decompose
(HepAxisAngle & rotation, Hep3Vector & boost) const {
HepRotation r;
HepBoost b;
decompose(r,b);
rotation = r.axisAngle();
boost = b.boostVector();
return;
}
double HepLorentzRotation::distance2( const HepBoost & b ) const {
HepBoost b1;
HepRotation r1;
decompose( b1, r1 );
double db2 = b1.distance2( b );
double dr2 = r1.norm2();
return ( db2 + dr2 );
}
double HepLorentzRotation::distance2( const HepRotation & r ) const {
HepBoost b1;
HepRotation r1;
decompose( b1, r1 );
double db2 = b1.norm2( );
double dr2 = r1.distance2( r );
return ( db2 + dr2 );
}
double HepLorentzRotation::distance2(
const HepLorentzRotation & lt ) const {
HepBoost b1;
HepRotation r1;
decompose( b1, r1 );
HepBoost b2;
HepRotation r2;
lt.decompose (b2, r2);
double db2 = b1.distance2( b2 );
double dr2 = r1.distance2( r2 );
return ( db2 + dr2 );
}
double HepLorentzRotation::howNear( const HepBoost & b ) const {
return std::sqrt( distance2( b ) );
}
double HepLorentzRotation::howNear( const HepRotation & r ) const {
return std::sqrt( distance2( r ) );
}
double HepLorentzRotation::howNear( const HepLorentzRotation & lt )const {
return std::sqrt( distance2( lt ) );
}
bool HepLorentzRotation::isNear(
const HepBoost & b, double epsilon ) const {
HepBoost b1;
HepRotation r1;
decompose( b1, r1 );
double db2 = b1.distance2(b);
if ( db2 > epsilon*epsilon ) {
return false; // Saves the time-consuming Rotation::norm2
}
double dr2 = r1.norm2();
return ( (db2 + dr2) <= epsilon*epsilon );
}
bool HepLorentzRotation::isNear(
const HepRotation & r, double epsilon ) const {
HepBoost b1;
HepRotation r1;
decompose( b1, r1 );
double db2 = b1.norm2();
if ( db2 > epsilon*epsilon ) {
return false; // Saves the time-consuming Rotation::distance2
}
double dr2 = r1.distance2(r);
return ( (db2 + dr2) <= epsilon*epsilon );
}
bool HepLorentzRotation::isNear(
const HepLorentzRotation & lt, double epsilon ) const {
HepBoost b1;
HepRotation r1;
decompose( b1, r1 );
HepBoost b2;
HepRotation r2;
lt.decompose (b2, r2);
double db2 = b1.distance2(b2);
if ( db2 > epsilon*epsilon ) {
return false; // Saves the time-consuming Rotation::distance2
}
double dr2 = r1.distance2(r2);
return ( (db2 + dr2) <= epsilon*epsilon );
}
double HepLorentzRotation::norm2() const {
HepBoost b;
HepRotation r;
decompose( b, r );
return b.norm2() + r.norm2();
}
void HepLorentzRotation::rectify() {
// Assuming the representation of this is close to a true LT,
// but may have drifted due to round-off error from many operations,
// this forms an "exact" orthosymplectic matrix for the LT again.
// There are several ways to do this, all equivalent to lowest order in
// the corrected error. We choose to form an LT based on the inverse boost
// extracted from row 4, and left-multiply by LT to form what would be
// a rotation if the LT were kosher. We drop the possibly non-zero t
// components of that, rectify that rotation and multiply back by the boost.
Hep3Vector beta (tx(), ty(), tz());
double gam = tt(); // NaN-proofing
if ( gam <= 0 ) {
std::cerr << "HepLorentzRotation::rectify() - "
<< "rectify() on a transformation with tt() <= 0 - will not help!"
<< std::endl;
gam = 1;
}
beta *= 1.0/gam;
HepLorentzRotation R = (*this) * HepBoost(-beta);
HepRep3x3 m3 ( R.xx(), R.xy(), R.xz(),
R.yx(), R.yy(), R.yz(),
R.zx(), R.zy(), R.zz() );
HepRotation Rgood (m3);
Rgood.rectify();
set ( Rgood, HepBoost(beta) );
}
} // namespace CLHEP