6 #if !defined(ST_NO_NUMERIC_LIMITS)
8 # if !defined(ST_NO_NAMESPACES)
9 using std::numeric_limits;
13 #define FOR_PICO_HELIX
20 #include "StPicoHelix.h"
22 #include "PhysicalConstants.h"
24 #include "StarClassLibrary/PhysicalConstants.h"
29 const Double_t StPicoHelix::NoSolution = 3.e+33;
33 mDipAngle(0), mCurvature(0), mPhase(0),
34 mH(0), mCosDipAngle(0), mSinDipAngle(0),
35 mCosPhase(0), mSinPhase(0) {
41 const TVector3& o, Int_t h) {
56 mSinPhase = h.mSinPhase;
64 const TVector3& o, Int_t h) {
107 #ifndef ST_NO_NUMERIC_LIMITS
108 if ( ::fabs(
mCurvature) <= numeric_limits<Double_t>::epsilon() ) {
110 if ( ::fabs(
mCurvature) <= static_cast<Double_t>(0) ) {
125 if ( ::fabs(
mPhase) > M_PI) {
163 Double_t dx = p.x()-
mOrigin.x();
164 Double_t dy = p.y()-
mOrigin.y();
179 return ( this->at(
pathLength(p,scanPeriods) )-p ).Mag();
197 Double_t dx = p.x()-
mOrigin.x();
198 Double_t dy = p.y()-
mOrigin.y();
199 Double_t dz = p.z()-
mOrigin.z();
206 #ifndef ST_NO_NUMERIC_LIMITS
208 using namespace units;
210 const Double_t MaxPrecisionNeeded = micrometer;
211 const Int_t MaxIterations = 100;
219 Double_t t6, t7, t11, t12, t19;
234 Double_t dmin = ( at(s) - p).Mag() ;
236 for(j=1; j<MaxIterations; j++) {
237 d = ( at(s+j*ds) - p ).Mag();
247 for(j=-1; -j<MaxIterations; j--) {
248 d = ( at(s+j*ds ) - p ).Mag() ;
269 for (Int_t i=0; i<MaxIterations; i++) {
275 s -= (t11*t12*
mH*mCosDipAngle-t19*t7*
mH*mCosDipAngle -
277 (t12*t12*mCosDipAngle*mCosDipAngle+t11*t7*t34 +
278 t7*t7*mCosDipAngle*mCosDipAngle +
280 if (fabs(sOld-s) < MaxPrecisionNeeded)
break;
283 #ifndef ST_NO_NUMERIC_LIMITS
293 #ifndef ST_NO_NUMERIC_LIMITS
294 return numeric_limits<Double_t>::max();
307 pair<Double_t,Double_t> value;
308 pair<Double_t,Double_t> VALUE(999999999.,999999999.);
322 t12-t12*t13-t15+t13*t16);
328 value.second = (t1+t20)/(mCosDipAngle*mCosDipAngle);
332 Double_t t2 = mSinPhase;
341 Double_t t17 = t8*t8;
342 Double_t t19 = t11*t11;
343 Double_t t21 = t11*t3;
344 Double_t t23 = t5*t5;
345 Double_t t32 = t14*t14;
346 Double_t t35 = t14*t3;
347 Double_t t38 = 8.0*t4*t6 - 4.0*t1*t2*t8 - 4.0*t11*mCurvature*t6 +
348 4.0*t15*t6 + t17*t3 + t19*t3 + 2.0*t21*t8 + 4.0*t8*t23 -
349 4.0*t8*
mOrigin.x()*mCurvature*t5 - 4.0*t11*t23 -
350 4.0*t11*
mOrigin.y()*mCurvature*t2 + 4.0*t11 - 4.0*t14 +
351 t32*t3 + 4.0*t15*t4 - 2.0*t35*t11 - 2.0*t35*t8;
352 Double_t t40 = (-t3*t38);
359 Double_t t45 = 2.0*t5 - t35 + t21 + 2.0 - 2.0*t1*t2 -2.0*t43 - 2.0*t43*t5 + t8*t3;
362 value.first = (-
mPhase + 2.0*atan((-2.0*t1 + 2.0*t2 + t40)/t45))/t46;
363 value.second = -(
mPhase + 2.0*atan((2.0*t1 - 2.0*t2 + t40)/t45))/t46;
370 if ( ! std::isnan(value.first) ) {
371 if ( ::fabs(value.first-p) < ::fabs(value.first) ) {
372 value.first = value.first-p;
374 else if ( ::fabs(value.first+p) < ::fabs(value.first) ) {
375 value.first = value.first+p;
379 if (! std::isnan(value.second)) {
380 if ( ::fabs(value.second-p) < ::fabs(value.second) ) {
381 value.second = value.second-p;
383 else if ( ::fabs(value.second+p) < ::fabs(value.second) ) {
384 value.second = value.second+p;
389 if (value.first > value.second) {
390 swap(value.first,value.second);
402 pair<Double_t, Double_t> result = this->
pathLength(r);
410 const TVector3& n)
const {
433 const Double_t MaxPrecisionNeeded = micrometer;
434 const Int_t MaxIterations = 20;
443 Double_t sOld = s = 0;
447 const Double_t angMax = 0.21;
448 Double_t deltas = fabs(angMax/(
mCurvature*mCosDipAngle));
453 for (i=0; i<MaxIterations; i++) {
455 Double_t sina = sin(a);
456 Double_t cosa = cos(a);
457 f = A + n.x()*cosa + n.y()*sina + u*s;
458 fp = -n.x()*sina*t + n.y()*cosa*t + u;
460 if ( fabs(fp)*deltas <= fabs(f) ) {
462 if (fp<0.) sgn = -sgn;
463 if (f <0.) sgn = -sgn;
465 if (shift<0) shift*=0.9;
472 if ( ::fabs(sOld-s) < MaxPrecisionNeeded ) {
478 if (i == MaxIterations) {
487 Double_t minRange)
const {
493 return pair<Double_t, Double_t>(NoSolution, NoSolution);
512 s2 = (k-ab*g)/(ab*ab-1.);
514 return pair<Double_t, Double_t>(s1, s2);
522 Double_t dd = ::sqrt(dx*dx + dy*dy);
526 Double_t cosAlpha = (r1*r1 + dd*dd - r2*r2)/(2*r1*dd);
530 if ( ::fabs(cosAlpha) < 1) {
531 Double_t sinAlpha = sin(acos(cosAlpha));
532 x =
xcenter() + r1*(cosAlpha*dx - sinAlpha*dy)/dd;
533 y =
ycenter() + r1*(sinAlpha*dx + cosAlpha*dy)/dd;
535 x =
xcenter() + r1*(cosAlpha*dx + sinAlpha*dy)/dd;
536 y =
ycenter() + r1*(cosAlpha*dy - sinAlpha*dx)/dd;
543 Int_t rsign = ((r2-r1) > dd ? -1 : 1);
545 x =
xcenter() + rsign*r1*dx/dd;
546 y =
ycenter() + rsign*r1*dy/dd;
556 Double_t range = max(2*dmin, minRange);
557 Double_t ds = range/10;
558 Double_t slast=-999999, ss, d;
562 while (ds > minStepSize) {
564 for ( ss=s1; ss<s2+ds; ss+=ds ) {
585 else if (s == slast) {
596 return pair<Double_t, Double_t>(s, h.
pathLength(at(s)));
607 TVector3 newOrigin = at(s);
608 Double_t newPhase = atan2(newOrigin.y() -
ycenter(),
634 std::ostream& operator<<(std::ostream& os,
const StPicoHelix&
h) {
636 <<
"curvature = " << h.
curvature() <<
", "
637 <<
"dip angle = " << h.
dipAngle() <<
", "
638 <<
"phase = " << h.
phase() <<
", "
639 <<
"h = " << h.
h() <<
", "
640 <<
"origin = " << h.
origin().X()
641 <<
" , " << h.
origin().Y() <<
" , " << h.
origin().Z() <<
" "
Double_t xcenter() const
Return x-center of circle in xy-plane.
pair< Double_t, Double_t > pathLengths(const StPicoHelix &, Double_t minStepSize=10 *micrometer, Double_t minRange=10 *centimeter) const
path lengths at dca between two helices
Double_t x(Double_t s) const
coordinates of helix at point s
Double_t curvature() const
Return curvature: 1/R in xy-plane.
Double_t mCurvature
Curvature = 1/R.
Double_t mSinDipAngle
Sin of dip angle.
virtual ~StPicoHelix()
Destructor.
Double_t fudgePathLength(const TVector3 &) const
Value of S where distance in x-y plane is minimal.
Double_t dipAngle() const
Return dip angle.
Int_t h() const
Return -sign(q*B);.
Double_t mCosPhase
Cos of phase.
TVector3 mOrigin
starting point of a helix
pair< Double_t, Double_t > pathLength(Double_t r) const
path length at given r (cylindrical r)
const TVector3 & origin() const
Return origin of the helix = starting point.
Double_t period() const
returns period length of helix
virtual void moveOrigin(Double_t s)
Move the origin along the helix to s which becomes then s=0.
void setPhase(Double_t)
Set phase of the helix.
void setParameters(Double_t c, Double_t dip, Double_t phase, const TVector3 &o, Int_t h)
Set helix parameters.
void setDipAngle(Double_t)
Set dip angle of the helix.
Double_t distance(const TVector3 &p, Bool_t scanPeriods=true) const
minimal distance between point and helix
Double_t mDipAngle
Dip angle.
Helix parametrization that uses ROOT TVector3.
Double_t phase() const
Return phase: aziumth in xy-plane measured from ring center.
Bool_t mSingularity
true for straight line case (B=0)
Double_t mCosDipAngle
Cos of dip angle.
Double_t ycenter() const
Return y-center of circle in xy-plane.
void setCurvature(Double_t)
Set curvature of the helix.
StPicoHelix()
Default constructor.