#include "Math/Vector3D.h" #include "Math/Point3D.h" #include "Math/Vector2D.h" #include "Math/Point2D.h" #include "Math/EulerAngles.h" #include "Math/Transform3D.h" #include "Math/Translation3D.h" #include "Math/Rotation3D.h" #include "Math/RotationX.h" #include "Math/RotationY.h" #include "Math/RotationZ.h" #include "Math/Quaternion.h" #include "Math/AxisAngle.h" #include "Math/EulerAngles.h" #include "Math/RotationZYX.h" #include "Math/LorentzRotation.h" #include "Math/VectorUtil.h" #ifndef NO_SMATRIX #include "Math/SMatrix.h" #endif #include using namespace ROOT::Math; using namespace ROOT::Math::VectorUtil; typedef DisplacementVector3D, GlobalCoordinateSystemTag> GlobalXYZVector; typedef DisplacementVector3D, LocalCoordinateSystemTag> LocalXYZVector; typedef DisplacementVector3D, GlobalCoordinateSystemTag> GlobalPolar3DVector; typedef PositionVector3D, GlobalCoordinateSystemTag> GlobalXYZPoint; typedef PositionVector3D, LocalCoordinateSystemTag> LocalXYZPoint; typedef PositionVector3D, GlobalCoordinateSystemTag> GlobalPolar3DPoint; typedef PositionVector3D, LocalCoordinateSystemTag> LocalPolar3DPoint; //#define TEST_COMPILE_ERROR int compare( double v1, double v2, const std::string & name = "", double scale = 1.0) { // ntest = ntest + 1; // numerical double limit for epsilon double eps = scale* std::numeric_limits::epsilon(); int iret = 0; double delta = v2 - v1; double d = 0; if (delta < 0 ) delta = - delta; if (v1 == 0 || v2 == 0) { if (delta > eps ) { iret = 1; } } // skip case v1 or v2 is infinity else { d = v1; if ( v1 < 0) d = -d; // add also case when delta is small by default if ( delta/d > eps && delta > eps ) iret = 1; } if (iret == 0) std::cout << "."; else { int pr = std::cout.precision (18); std::cout << "\nDiscrepancy in " << name << "() : " << v1 << " != " << v2 << " discr = " << int(delta/d/eps) << " (Allowed discrepancy is " << eps << ")\n"; std::cout.precision (pr); //nfail = nfail + 1; } return iret; } template bool IsEqual(const Transform & t1, const Transform & t2, unsigned int size) { // size should be an enum of the Transform class std::vector x1(size); std::vector x2(size); t1.GetComponents(x1.begin(), x1.end() ); t2.GetComponents(x2.begin(), x2.end() ); bool ret = true; unsigned int i = 0; while (ret && i < size) { // from TMath::AreEqualRel(x1,x2,2*eps) bool areEqual = std::abs(x1[i]-x2[i]) < std::numeric_limits::epsilon() * ( std::abs(x1[i]) + std::abs(x2[i] ) ); ret &= areEqual; i++; } return ret; } int testVector3D() { int iret = 0; std::cout << "testing Vector3D \t:\t"; // test the vector tags GlobalXYZVector vg(1.,2.,3.); GlobalXYZVector vg2(vg); GlobalPolar3DVector vpg(vg); iret |= compare(vpg.R(), vg2.R() ); // std::cout << vg2 << std::endl; double r = vg.Dot(vpg); iret |= compare(r, vg.Mag2() ); GlobalXYZVector vcross = vg.Cross(vpg); iret |= compare(vcross.R(), 0.0,"cross",10 ); // std::cout << vg.Dot(vpg) << std::endl; // std::cout << vg.Cross(vpg) << std::endl; GlobalXYZVector vg3 = vg + vpg; iret |= compare(vg3.R(), 2*vg.R() ); GlobalXYZVector vg4 = vg - vpg; iret |= compare(vg4.R(), 0.0,"diff",10 ); #ifdef TEST_COMPILE_ERROR LocalXYZVector vl; vl = vg; LocalXYZVector vl2(vg2); LocalXYZVector vl3(vpg); vg.Dot(vl); vg.Cross(vl); vg3 = vg + vl; vg4 = vg - vl; #endif if (iret == 0) std::cout << "\t\t\t\t\tOK\n"; else std::cout << "\t\t\t\tFAILED\n"; return iret; } int testPoint3D() { int iret = 0; std::cout << "testing Point3D \t:\t"; // test the vector tags GlobalXYZPoint pg(1.,2.,3.); GlobalXYZPoint pg2(pg); GlobalPolar3DPoint ppg(pg); iret |= compare(ppg.R(), pg2.R() ); //std::cout << pg2 << std::endl; GlobalXYZVector vg(pg); double r = pg.Dot(vg); iret |= compare(r, pg.Mag2() ); GlobalPolar3DVector vpg(pg); GlobalXYZPoint pcross = pg.Cross(vpg); iret |= compare(pcross.R(), 0.0,"cross",10 ); GlobalPolar3DPoint pg3 = ppg + vg; iret |= compare(pg3.R(), 2*pg.R() ); GlobalXYZVector vg4 = pg - ppg; iret |= compare(vg4.R(), 0.0,"diff",10 ); #ifdef TEST_COMPILE_ERROR LocalXYZPoint pl; pl = pg; LocalXYZVector pl2(pg2); LocalXYZVector pl3(ppg); pl.Dot(vg); pl.Cross(vg); pg3 = ppg + pg; pg3 = ppg + pl; vg4 = pg - pl; #endif // operator - XYZPoint q1(1.,2.,3.); XYZPoint q2 = -1.* q1; XYZVector v2 = -XYZVector(q1); iret |= compare(XYZVector(q2) == v2,true,"reflection"); if (iret == 0) std::cout << "\t\t\t\t\tOK\n"; else std::cout << "\t\t\t\tFAILED\n"; return iret; } typedef DisplacementVector2D, GlobalCoordinateSystemTag> GlobalXYVector; typedef DisplacementVector2D, LocalCoordinateSystemTag> LocalXYVector; typedef DisplacementVector2D, GlobalCoordinateSystemTag> GlobalPolar2DVector; int testVector2D() { int iret = 0; std::cout << "testing Vector2D \t:\t"; // test the vector tags GlobalXYVector vg(1.,2.); GlobalXYVector vg2(vg); GlobalPolar2DVector vpg(vg); iret |= compare(vpg.R(), vg2.R() ); // std::cout << vg2 << std::endl; double r = vg.Dot(vpg); iret |= compare(r, vg.Mag2() ); // std::cout << vg.Dot(vpg) << std::endl; GlobalXYVector vg3 = vg + vpg; iret |= compare(vg3.R(), 2*vg.R() ); GlobalXYVector vg4 = vg - vpg; iret |= compare(vg4.R(), 0.0,"diff",10 ); double angle = 1.; vg.Rotate(angle); iret |= compare(vg.Phi(), vpg.Phi() + angle ); iret |= compare(vg.R(), vpg.R() ); GlobalXYZVector v3d(1,2,0); GlobalXYZVector vr3d = RotationZ(angle) * v3d; iret |= compare(vg.X(), vr3d.X() ); iret |= compare(vg.Y(), vr3d.Y() ); GlobalXYVector vu = vg3.Unit(); iret |= compare(vu.R(), 1. ); #ifdef TEST_COMPILE_ERROR LocalXYVector vl; vl = vg; LocalXYVector vl2(vg2); LocalXYVector vl3(vpg); vg.Dot(vl); vg3 = vg + vl; vg4 = vg - vl; #endif if (iret == 0) std::cout << "\t\t\t\tOK\n"; else std::cout << "\t\t\tFAILED\n"; return iret; } typedef PositionVector2D, GlobalCoordinateSystemTag> GlobalXYPoint; typedef PositionVector2D, LocalCoordinateSystemTag> LocalXYPoint; typedef PositionVector2D, GlobalCoordinateSystemTag> GlobalPolar2DPoint; typedef PositionVector2D, LocalCoordinateSystemTag> LocalPolar2DPoint; int testPoint2D() { int iret = 0; std::cout << "testing Point2D \t:\t"; // test the vector tags GlobalXYPoint pg(1.,2.); GlobalXYPoint pg2(pg); GlobalPolar2DPoint ppg(pg); iret |= compare(ppg.R(), pg2.R() ); //std::cout << pg2 << std::endl; GlobalXYVector vg(pg); double r = pg.Dot(vg); iret |= compare(r, pg.Mag2() ); GlobalPolar2DVector vpg(pg); GlobalPolar2DPoint pg3 = ppg + vg; iret |= compare(pg3.R(), 2*pg.R() ); GlobalXYVector vg4 = pg - ppg; iret |= compare(vg4.R(), 0.0,"diff",10 ); #ifdef TEST_COMPILE_ERROR LocalXYPoint pl; pl = pg; LocalXYVector pl2(pg2); LocalXYVector pl3(ppg); pl.Dot(vg); pl.Cross(vg); pg3 = ppg + pg; pg3 = ppg + pl; vg4 = pg - pl; #endif // operator - XYPoint q1(1.,2.); XYPoint q2 = -1.* q1; XYVector v2 = -XYVector(q1); iret |= compare(XYVector(q2) == v2,true,"reflection"); double angle = 1.; pg.Rotate(angle); iret |= compare(pg.Phi(), ppg.Phi() + angle ); iret |= compare(pg.R(), ppg.R() ); GlobalXYZVector v3d(1,2,0); GlobalXYZVector vr3d = RotationZ(angle) * v3d; iret |= compare(pg.X(), vr3d.X() ); iret |= compare(pg.Y(), vr3d.Y() ); if (iret == 0) std::cout << "\t\t\t\tOK\n"; else std::cout << "\t\t\tFAILED\n"; return iret; } // missing LV test int testRotations3D() { int iret=0; std::cout << "testing 3D Rotations\t:\t"; Rotation3D rot = RotationZ(1.) * RotationY(2) * RotationX(3); GlobalXYZVector vg(1.,2.,3); GlobalXYZPoint pg(1.,2.,3); GlobalPolar3DVector vpg(vg); // GlobalXYZVector vg2 = rot.operator() (vg); GlobalXYZVector vg2 = rot(vg); iret |= compare(vg2.R(), vg.R(),"rot3D" ); GlobalXYZPoint pg2 = rot(pg); iret |= compare(pg2.X(), vg2.X(),"x diff"); iret |= compare(pg2.Y(), vg2.Y(),"y diff"); iret |= compare(pg2.Z(), vg2.Z(),"z diff"); Quaternion qrot(rot); pg2 = qrot(pg); iret |= compare(pg2.X(), vg2.X(),"x diff",10); iret |= compare(pg2.Y(), vg2.Y(),"y diff",10); iret |= compare(pg2.Z(), vg2.Z(),"z diff",10); GlobalPolar3DVector vpg2 = qrot * vpg; iret |= compare(vpg2.X(), vg2.X(),"x diff",10 ); iret |= compare(vpg2.Y(), vg2.Y(),"y diff",10 ); iret |= compare(vpg2.Z(), vg2.Z(),"z diff",10 ); AxisAngle arot(rot); pg2 = arot(pg); iret |= compare(pg2.X(), vg2.X(),"x diff",10 ); iret |= compare(pg2.Y(), vg2.Y(),"y diff",10 ); iret |= compare(pg2.Z(), vg2.Z(),"z diff",10 ); vpg2 = arot (vpg); iret |= compare(vpg2.X(), vg2.X(),"x diff",10 ); iret |= compare(vpg2.Y(), vg2.Y(),"y diff",10 ); iret |= compare(vpg2.Z(), vg2.Z(),"z diff",10 ); EulerAngles erot(rot); vpg2 = erot (vpg); iret |= compare(vpg2.X(), vg2.X(),"x diff",10 ); iret |= compare(vpg2.Y(), vg2.Y(),"y diff",10 ); iret |= compare(vpg2.Z(), vg2.Z(),"z diff",10 ); GlobalXYZVector vrx = RotationX(3) * vg; GlobalXYZVector vry = RotationY(2) * vrx; vpg2 = RotationZ(1) * GlobalPolar3DVector (vry); iret |= compare(vpg2.X(), vg2.X(),"x diff",10 ); iret |= compare(vpg2.Y(), vg2.Y(),"y diff",10 ); iret |= compare(vpg2.Z(), vg2.Z(),"z diff",10 ); // test Get/SetComponents XYZVector v1,v2,v3; rot.GetComponents(v1,v2,v3); const Rotation3D rot2(v1,v2,v3); //rot2.SetComponents(v1,v2,v3); double r1[9],r2[9]; rot.GetComponents(r1,r1+9); rot2.GetComponents(r2,r2+9); for (int i = 0; i < 9; ++i) { iret |= compare(r1[i],r2[i],"Get/SetComponents"); } // operator == fails for numerical precision //iret |= compare( (rot2==rot),true,"Get/SetComponens"); // test get/set with a matrix #ifndef NO_SMATRIX SMatrix mat; rot2.GetRotationMatrix(mat); rot.SetRotationMatrix(mat); iret |= compare( (rot2==rot),true,"Get/SetRotMatrix"); #endif //test inversion Rotation3D rotInv = rot.Inverse(); rot.Invert(); // invert in place bool comp = (rotInv == rot ); iret |= compare(comp,true,"inversion"); // rotation and scaling of points XYZPoint q1(1.,2,3); double a = 3; XYZPoint qr1 = rot( a * q1); XYZPoint qr2 = a * rot( q1); iret |= compare(qr1.X(), qr2.X(),"x diff",10 ); iret |= compare(qr1.Y(), qr2.Y(),"y diff",10 ); iret |= compare(qr1.Z(), qr2.Z(),"z diff",10 ); if (iret == 0) std::cout << "\tOK\n"; else std::cout << "\t FAILED\n"; return iret; } int testTransform3D() { std::cout << "testing 3D Transform\t:\t"; int iret = 0; EulerAngles r(1.,2.,3.); GlobalPolar3DVector v(1.,2.,3.); GlobalXYZVector w(v); Transform3D t1( v ); GlobalXYZPoint pg; t1.Transform( LocalXYZPoint(), pg ); iret |= compare(pg.X(), v.X(),"x diff",10 ); iret |= compare(pg.Y(), v.Y(),"y diff",10 ); iret |= compare(pg.Z(), v.Z(),"z diff",10 ); Transform3D t2( r, v ); GlobalPolar3DVector vr = r.Inverse()*v; // std::cout << GlobalXYZVector(v) << std::endl; // std::cout << GlobalXYZVector(vr) << std::endl; // std::cout << GlobalXYZVector (r(v)) << std::endl; // std::cout << GlobalXYZVector (r(vr)) << std::endl; // std::cout << vr << std::endl; // std::cout << r(vr) << std::endl; // std::cout << r << std::endl; // std::cout << r.Inverse() << std::endl; // std::cout << r * r.Inverse() << std::endl; // std::cout << Rotation3D(r) * Rotation3D(r.Inverse()) << std::endl; // std::cout << Rotation3D(r) * Rotation3D(r).Inverse() << std::endl; // test Translation3D Translation3D tr1(v); Translation3D tr2(v.X(),v.Y(),v.Z()); iret |= compare(tr1 ==tr2, 1,"eq transl",1 ); Translation3D tr3 = tr1 * tr1.Inverse(); GlobalPolar3DVector vp2 = tr3 * v; iret |= compare(vp2.X(), v.X(),"x diff",10 ); iret |= compare(vp2.Y(), v.Y(),"y diff",10 ); iret |= compare(vp2.Z(), v.Z(),"z diff",10 ); Transform3D t2b = tr1 * Rotation3D(r); // this above fails on Windows - use a comparison with tolerance // 12 is size of Transform3D internal vector iret |= compare( IsEqual(t2,t2b,12), true,"eq1 transf",1 ); //iret |= compare(t2 ==t2b, 1,"eq1 transf",1 ); Transform3D t2c( r, tr1); iret |= compare( IsEqual(t2,t2c,12), true,"eq2 transf",1 ); //iret |= compare(t2 ==t2c, 1,"eq2 transf",1 ); Transform3D t3 = Rotation3D(r) * Translation3D(vr); Rotation3D rrr; XYZVector vvv; t2b.GetDecomposition(rrr,vvv); iret |= compare(Rotation3D(r) ==rrr, 1,"eq transf rot",1 ); iret |= compare( tr1.Vect() == vvv, 1,"eq transf vec",1 ); // if (iret) std::cout << vvv << std::endl; // if (iret) std::cout << Translation3D(vr) << std::endl; Translation3D ttt; t2b.GetDecomposition(rrr,ttt); iret |= compare( tr1 == ttt, 1,"eq transf trans",1 ); // if (iret) std::cout << ttt << std::endl; EulerAngles err2; GlobalPolar3DVector vvv2; t2b.GetDecomposition(err2,vvv2); iret |= compare( r.Phi(), err2.Phi(),"transf rot phi",4 ); iret |= compare( r.Theta(), err2.Theta(),"transf rot theta",1 ); iret |= compare( r.Psi(), err2.Psi(),"transf rot psi",1 ); iret |= compare( v == vvv2, 1,"eq transf g vec",1 ); // create from other rotations RotationZYX rzyx(r); Transform3D t4( rzyx); iret |= compare( t4.Rotation() == Rotation3D(rzyx), 1,"eq trans rzyx",1 ); Transform3D trf2 = tr1 * r; iret |= compare( trf2 == t2b, 1,"trasl * e rot",1 ); Transform3D trf3 = r * Translation3D(vr); //iret |= compare( trf3 == t3, 1,"e rot * transl",1 ); // this above fails on i686-slc5-gcc43-opt - use a comparison with tolerance iret |= compare( IsEqual(trf3,t3,12), true,"e rot * transl",1 ); Transform3D t5(rzyx, v); Transform3D trf5 = Translation3D(v) * rzyx; //iret |= compare( trf5 == t5, 1,"trasl * rzyx",1 ); iret |= compare( IsEqual(trf5,t5,12), true,"trasl * rzyx",1 ); Transform3D t6(rzyx, rzyx * Translation3D(v).Vect() ); Transform3D trf6 = rzyx * Translation3D(v); iret |= compare( trf6 == t6, 1,"rzyx * transl",1 ); if (iret) std::cout << t6 << "\n---\n" << trf6 << std::endl; Transform3D trf7 = t4 * Translation3D(v); //iret |= compare( trf7 == trf6, 1,"tranf * transl",1 ); iret |= compare( IsEqual(trf7,trf6,12), true,"tranf * transl",1 ); Transform3D trf8 = Translation3D(v) * t4; iret |= compare( trf8 == trf5, 1,"trans * transf",1 ); Transform3D trf9 = Transform3D(v) * rzyx; iret |= compare( trf9 == trf5, 1,"tranf * rzyx",1 ); Transform3D trf10 = rzyx * Transform3D(v); iret |= compare( trf10 == trf6, 1,"rzyx * transf",1 ); Transform3D trf11 = Rotation3D(rzyx) * Transform3D(v); iret |= compare( trf11 == trf10, 1,"r3d * transf",1 ); RotationZYX rrr2 = trf10.Rotation(); //iret |= compare( rzyx == rrr2, 1,"gen Rotation()",1 ); iret |= compare( rzyx.Phi() , rrr2.Phi(),"gen Rotation() Phi",1 ); iret |= compare( rzyx.Theta(), rrr2.Theta(),"gen Rotation() Theta",10 ); iret |= compare( rzyx.Psi(), rrr2.Psi(),"gen Rotation() Psi",1 ); if (iret) std::cout << rzyx << "\n---\n" << rrr2 << std::endl; //std::cout << t2 << std::endl; //std::cout << t3 << std::endl; XYZPoint p1(-1.,2.,-3); XYZPoint p2 = t2 (p1); Polar3DPoint p3 = t3 ( Polar3DPoint(p1) ); iret |= compare(p3.X(), p2.X(),"x diff",10 ); iret |= compare(p3.Y(), p2.Y(),"y diff",10 ); iret |= compare(p3.Z(), p2.Z(),"z diff",10 ); GlobalXYZVector v1(1.,2.,3.); LocalXYZVector v2; t2.Transform (v1, v2); GlobalPolar3DVector v3; t3.Transform ( GlobalPolar3DVector(v1), v3 ); iret |= compare(v3.X(), v2.X(),"x diff",10 ); iret |= compare(v3.Y(), v2.Y(),"y diff",10 ); iret |= compare(v3.Z(), v2.Z(),"z diff",10 ); XYZPoint q1(1,2,3); XYZPoint q2(-1,-2,-3); XYZPoint q3 = q1 + XYZVector(q2); //std::cout << q3 << std::endl; XYZPoint qt3 = t3(q3); //std::cout << qt3 << std::endl; XYZPoint qt1 = t3(q1); XYZVector vt2 = t3( XYZVector(q2) ); XYZPoint qt4 = qt1 + vt2; iret |= compare(qt3.X(), qt4.X(),"x diff",10 ); iret |= compare(qt3.Y(), qt4.Y(),"y diff",10 ); iret |= compare(qt3.Z(), qt4.Z(),"z diff",10 ); //std::cout << qt4 << std::endl; // this fails // double a = 3; //XYZPoint q4 = a*q1; // std::cout << t3( a * q1) << std::endl; // std::cout << a * t3(q1) << std::endl; // test get/set with a matrix #ifndef NO_SMATRIX SMatrix mat; t3.GetTransformMatrix(mat); Transform3D t3b; t3b.SetTransformMatrix(mat); iret |= compare( (t3==t3b),true,"Get/SetTransformMatrix"); // test LR Boost b(0.2,0.4,0.8); LorentzRotation lr(b); SMatrix mat4; lr.GetRotationMatrix(mat4); LorentzRotation lr2; lr2.SetRotationMatrix(mat4); iret |= compare( (lr==lr2),true,"Get/SetLRotMatrix"); #endif if (iret == 0) std::cout << "OK\n"; else std::cout << "\t\t\tFAILED\n"; return iret; } int testVectorUtil() { std::cout << "testing VectorUtil \t:\t"; int iret = 0; // test new perp functions XYZVector v(1.,2.,3.); XYZVector vx = ProjVector(v,XYZVector(3,0,0) ); iret |= compare(vx.X(), v.X(),"x",1 ); iret |= compare(vx.Y(), 0,"y",1 ); iret |= compare(vx.Z(), 0,"z",1 ); XYZVector vpx = PerpVector(v,XYZVector(2,0,0) ); iret |= compare(vpx.X(), 0,"x",1 ); iret |= compare(vpx.Y(), v.Y(),"y",1 ); iret |= compare(vpx.Z(), v.Z(), "z",1 ); double perpy = Perp(v, XYZVector(0,2,0) ); iret |= compare(perpy, std::sqrt( v.Mag2() - v.y()*v.y()),"perpy" ); XYZPoint u(1,1,1); XYZPoint un = u/u.R(); XYZVector vl = ProjVector(v,u); XYZVector vl2 = XYZVector(un) * ( v.Dot(un ) ); iret |= compare(vl.X(), vl2.X(),"x",1 ); iret |= compare(vl.Y(), vl2.Y(),"y",1 ); iret |= compare(vl.Z(), vl2.Z(),"z",1 ); XYZVector vp = PerpVector(v,u); XYZVector vp2 = v - XYZVector ( un * ( v.Dot(un ) ) ); iret |= compare(vp.X(), vp2.X(),"x",10 ); iret |= compare(vp.Y(), vp2.Y(),"y",10 ); iret |= compare(vp.Z(), vp2.Z(),"z",10 ); double perp = Perp(v,u); iret |= compare(perp, vp.R(),"perp",1 ); double perp2 = Perp2(v,u); iret |= compare(perp2, vp.Mag2(),"perp2",1 ); if (iret == 0) std::cout << "\t\t\t\tOK\n"; else std::cout << "\t\t\t\t\t\tFAILED\n"; return iret; } int testGenVector() { int iret = 0; iret |= testVector3D(); iret |= testPoint3D(); iret |= testVector2D(); iret |= testPoint2D(); iret |= testRotations3D(); iret |= testTransform3D(); iret |= testVectorUtil(); if (iret !=0) std::cout << "\nTest GenVector FAILED!!!!!!!!!\n"; return iret; } int main() { int ret = testGenVector(); if (ret) std::cerr << "test FAILED !!! " << std::endl; else std::cout << "test OK " << std::endl; return ret; }