#ifndef ALIFMHELIX_H
#define ALIFMHELIX_H
#include <math.h>
#include <utility>
#include <algorithm>
#include "AliFmThreeVector.h"
#include <TMath.h>
#if !defined(ST_NO_NAMESPACES)
using std::pair;
using std::swap;
using std::max;
#endif
#ifdef WIN32
#include "gcc2vs.h"
#endif
#ifdef __SUNPRO_CC
#include <ieeefp.h>
#define __FUNCTION__ "__FILE__:__LINE__"
#endif
class AliFmHelix {
public:
AliFmHelix(double c, double dip, double phase,
const AliFmThreeVector<double>& o, int h=-1);
virtual ~AliFmHelix();
double DipAngle() const;
double Curvature() const;
double Phase() const;
double XCenter() const;
double YCenter() const;
int H() const;
const AliFmThreeVector<double>& Origin() const;
void SetParameters(double c, double dip, double phase, const AliFmThreeVector<double>& o, int h);
double X(double s) const;
double Y(double s) const;
double Z(double s) const;
AliFmThreeVector<double> At(double s) const;
double Period() const;
pair<double, double> PathLength(double r) const;
pair<double, double> PathLength(double r, double x, double y, bool scanPeriods = true);
double PathLength(const AliFmThreeVector<double>& p, bool scanPeriods = true) const;
double PathLength(const AliFmThreeVector<double>& r,
const AliFmThreeVector<double>& n) const;
double PathLength(double x, double y) const;
pair<double, double> PathLengths(const AliFmHelix& h, bool scanPeriods = true) const;
double Distance(const AliFmThreeVector<double>& p, bool scanPeriods = true) const;
bool Valid(double world = 1.e+5) const {return !Bad(world);}
int Bad(double world = 1.e+5) const;
virtual void MoveOrigin(double s);
static const double fgkNoSolution;
protected:
AliFmHelix();
void SetCurvature(double d);
void SetPhase(double d);
void SetDipAngle(double d);
double FudgePathLength(const AliFmThreeVector<double>& v) const;
protected:
bool fSingularity;
AliFmThreeVector<double> fOrigin;
double fDipAngle;
double fCurvature;
double fPhase;
int fH;
double fCosDipAngle;
double fSinDipAngle;
double fCosPhase;
double fSinPhase;
#ifdef __ROOT__
ClassDef(AliFmHelix,1)
#endif
};
int operator== (const AliFmHelix&, const AliFmHelix&);
int operator!= (const AliFmHelix&, const AliFmHelix&);
ostream& operator<<(ostream&, const AliFmHelix&);
inline int AliFmHelix::H() const {return fH;}
inline double AliFmHelix::DipAngle() const {return fDipAngle;}
inline double AliFmHelix::Curvature() const {return fCurvature;}
inline double AliFmHelix::Phase() const {return fPhase;}
inline double AliFmHelix::X(double s) const
{
if (fSingularity)
return fOrigin.x() - s*fCosDipAngle*fSinPhase;
else
return fOrigin.x() + (cos(fPhase + s*fH*fCurvature*fCosDipAngle)-fCosPhase)/fCurvature;
}
inline double AliFmHelix::Y(double s) const
{
if (fSingularity)
return fOrigin.y() + s*fCosDipAngle*fCosPhase;
else
return fOrigin.y() + (sin(fPhase + s*fH*fCurvature*fCosDipAngle)-fSinPhase)/fCurvature;
}
inline double AliFmHelix::Z(double s) const
{
return fOrigin.z() + s*fSinDipAngle;
}
inline const AliFmThreeVector<double>& AliFmHelix::Origin() const {return fOrigin;}
inline AliFmThreeVector<double> AliFmHelix::At(double s) const
{
return AliFmThreeVector<double>(X(s), Y(s), Z(s));
}
inline double AliFmHelix::PathLength(double x, double y) const
{
return FudgePathLength(AliFmThreeVector<double>(x, y, 0));
}
inline int AliFmHelix::Bad(double WorldSize) const
{
int ierr;
if (!TMath::Finite(fDipAngle )) return 11;
if (!TMath::Finite(fCurvature )) return 12;
ierr = fOrigin.Bad(WorldSize);
if (ierr) return 3+ierr*100;
if (::fabs(fDipAngle) >1.58) return 21;
double qwe = ::fabs(::fabs(fDipAngle)-M_PI/2);
if (qwe < 1./WorldSize ) return 31;
if (::fabs(fCurvature) > WorldSize) return 22;
if (fCurvature < 0 ) return 32;
if (abs(fH) != 1 ) return 24;
return 0;
}
#endif