CMS 3D CMS Logo

IgSoIdealTrack.cc

Go to the documentation of this file.
00001 //<<<<<< INCLUDES                                                       >>>>>>
00002 
00003 #include "Iguana/Inventor/interface/IgSoIdealTrack.h"
00004 #include "Iguana/Inventor/interface/IgParticleChar.h"
00005 #include <Inventor/nodes/SoVertexProperty.h>
00006 #include <Inventor/nodes/SoPointSet.h>
00007 #include <Inventor/nodes/SoNurbsCurve.h>
00008 #include <Inventor/nodes/SoComplexity.h>
00009 #include <Inventor/nodes/SoCoordinate4.h>
00010 #include <cfloat>
00011 #include <vector>
00012 #include <cassert>
00013 #include <iostream>
00014 #include <limits>
00015 
00016 //<<<<<< PRIVATE DEFINES                                                >>>>>>
00017 
00018 #ifdef WIN32
00019 # define copysign _copysign
00020 #else
00021 # if (defined (__linux) && !defined (__KCC)) || (defined (MIPS) && defined (__KCC))
00022 extern "C" inline double copysign (double x, double y) throw ()
00023 {
00024         return (fabs (x) * y /fabs (y));
00025 }
00026 # endif
00027 #endif
00028 
00029 //<<<<<< PRIVATE CONSTANTS                                              >>>>>>
00030 
00031 #ifdef TGS_VERSION
00032 static const float maxNurbAngle =  M_PI / 2.; // was M_PI/2
00033 #else
00034 static const float maxNurbAngle = static_cast<float>( M_PI / 6. );
00035 #endif
00036 static const float maxAngle = static_cast<float>(4 * M_PI); // truncate curve after two loops
00037 
00038 //<<<<<< PRIVATE TYPES                                                  >>>>>>
00039 //<<<<<< PRIVATE VARIABLE DEFINITIONS                                   >>>>>>
00040 //<<<<<< PUBLIC VARIABLE DEFINITIONS                                    >>>>>>
00041 float   IgSoIdealTrack::bfield = 4.0F;          //< constant bfield in tesla
00042 float   IgSoIdealTrack::rmax = 1.4F;            //< max radius in central tracker
00043 float   IgSoIdealTrack::zmax = 3.2F;            //< max z extent
00044 
00045 //<<<<<< CLASS STRUCTURE INITIALIZATION                                 >>>>>>
00046 
00047 static const int     NORDER = 3;
00048 static const float   SPEEDOLIGHT = 0.00299792458F; // in (m/nsec*10^-2) 
00049 
00050 SO_KIT_SOURCE (IgSoIdealTrack);
00051 
00052 //<<<<<< PRIVATE FUNCTION DEFINITIONS                                   >>>>>>
00053 //<<<<<< PUBLIC FUNCTION DEFINITIONS                                    >>>>>>
00054 //<<<<<< MEMBER FUNCTION DEFINITIONS                                    >>>>>>
00055 
00056 // An OpenInventor object to represent an ideal track and ideal beam track
00057 
00058 void
00059 IgSoIdealTrack::initClass (void)
00060 {
00061         SO_KIT_INIT_CLASS (IgSoIdealTrack, IgSoShapeKit, "IgSoShapeKit");
00062         IgParticleChar::initParticles ();
00063 }
00064 
00065 IgSoIdealTrack::IgSoIdealTrack (void)
00066 : m_particleChar (IgParticleChar::getByName("muon")),
00067 m_ptot (1.F),
00068 m_pt (0.5F),
00069 m_charge (-1.F)
00070 {
00071         SO_KIT_CONSTRUCTOR (IgSoIdealTrack);
00072         SO_KIT_ADD_FIELD (phi,          (0.0F));
00073         SO_KIT_ADD_FIELD (radius,               (1.0F));
00074         SO_KIT_ADD_FIELD (zeta,         (0.01F));
00075         SO_KIT_ADD_FIELD (vertex,               (0.0F, 0.0F, 0.0F));
00076         SO_KIT_ADD_FIELD (t0,           (0.0F));
00077         SO_KIT_ADD_FIELD (dt,           (1.0F));
00078         SO_KIT_ADD_FIELD (tstart,               (0.0F));
00079         SO_KIT_ADD_FIELD (tend,         (500.F));
00080         SO_KIT_ADD_FIELD (particleType, ("unknown"));
00081         SO_KIT_ADD_CATALOG_ENTRY (material, SoMaterial, FALSE, separator,\x0, TRUE);
00082         SO_KIT_ADD_CATALOG_ENTRY (style, SoDrawStyle, FALSE, separator,\x0, TRUE);
00083         SO_KIT_ADD_CATALOG_ENTRY (complexity, SoComplexity, FALSE, separator,\x0, TRUE);
00084         SO_KIT_ADD_CATALOG_ENTRY (points, SoCoordinate4, FALSE, separator,\x0, TRUE);
00085         SO_KIT_ADD_CATALOG_ENTRY (curve, SoNurbsCurve, FALSE, separator,\x0, TRUE);
00086 #ifdef IG_DEBUG_PTS
00087         SO_KIT_ADD_CATALOG_ENTRY (debugStyle, SoDrawStyle, FALSE, separator,\x0, TRUE);
00088         SO_KIT_ADD_CATALOG_ENTRY (debugPoints, SoPointSet, FALSE, separator,\x0, TRUE);
00089 #endif // IG_DEBUG_PTS
00090         SO_KIT_INIT_INSTANCE ();
00091         setUpConnections (true, true);
00092 }
00093 
00094 IgSoIdealTrack::~IgSoIdealTrack (void)
00095 {
00096     if (dt.isConnected ())
00097       dt.disconnect ();
00098 }
00099 
00100 void
00101 IgSoIdealTrack::refresh (void)
00102 {
00103         // Initialise local variables (and members for the converters)
00104         float   radius  = this->radius.getValue ();
00105         float   zeta    = this->zeta.getValue ();
00106         SbVec3f vertex  = this->vertex.getValue ();
00107         float   phi     = this->phi.getValue ();
00108         float   tstart  = this->tstart.getValue ();
00109         float   tend    = this->tend.getValue ();
00110 
00111         float   t0      = this->t0.getValue ();
00112         float   dt      = this->dt.getValue ();
00113 
00114 //      if (t0 < tstart)
00115 //              t0 = tstart;
00116         if (t0 > tend)
00117                 t0 = tend;
00118 
00119         float t1 = dt+t0;
00120         if (t1 > tend)
00121                 t1 = tend;
00122 //      if (t1 < tstart)
00123 //              t1 = tstart;
00124 
00125         if (!fabs (tend - tstart) || !fabs (t1 - t0))
00126         {
00127                 setPart ("material",    m_particleChar->getMaterial ());
00128                 setPart ("style",       m_particleChar->getStyle ());
00129                 setPart ("complexity",  0);
00130                 setPart ("points",      0);
00131                 setPart ("curve",       0);
00132 #ifdef IG_DEBUG_PTS
00133                 setPart ("debugStyle",  0);
00134                 setPart ("debugPoints", 0);
00135 #endif // IG_DEBUG_PTS
00136                 return;
00137         }
00138 
00139 #ifdef IG_DEBUG_PTS
00140         SoDrawStyle     *debugStyle = new SoDrawStyle;
00141         SoPointSet      *debugPoints = new SoPointSet;
00142         SoVertexProperty        *debugVtx = new SoVertexProperty;
00143 #endif // IG_DEBUG_PTS
00144 
00145         SoComplexity    *complexity = new SoComplexity;
00146         SoCoordinate4   *points = new SoCoordinate4;
00147         SoNurbsCurve    *curve = new  SoNurbsCurve;
00148         complexity->value = 0.6F;
00149         int             npoints = 0;
00150         int             nknots = 0;
00151         int             nknot = 0;
00152         std::vector<SbVec4f> ctlPoints;
00153         std::vector<float>      knots;
00154 
00155         if ( bfield == 0 || m_charge == 0 )
00156         {
00157                 // Calculate the start & end points
00158                 float z0, z1, x0, y0, x1, y1;
00159                 z0 = timeToZ (t0);
00160                 z1 = timeToZ (t1);
00161                 SbVec2f xy0( timeToXY(t0) );
00162                 SbVec2f xy1( timeToXY( t1 ) );
00163                 xy0.getValue( x0, y0 );
00164                 xy1.getValue( x1, y1 );
00165 
00166                 // Calculate the control points & knot vector
00167                 npoints = 2;
00168                 nknots = 4;
00169                 ctlPoints.resize(static_cast<int>(npoints));
00170                 knots.resize(static_cast<int>(nknots)); // #ctlPoints + NORDER
00171                 knots[0] = 0; knots[1] = 0; knots[2] = 1; knots[3] = 1;
00172                 ctlPoints[0].setValue( x0, y0, z0, 1.F  );
00173                 ctlPoints[1].setValue( x1, y1, z1, 1.F );
00174 
00175                 // Set the coordinates
00176                 points->point.setValues (0, npoints, &ctlPoints[0]);
00177 
00178                 // Rebuild the curve
00179                 curve->numControlPoints = npoints;
00180                 curve->knotVector.setValues (0, nknots, &knots[0]);
00181 
00182         }
00183         else
00184         {
00185                 // invert r=p/qB
00186                 m_pt =  SPEEDOLIGHT * 100.F * bfield * m_charge * radius;
00187                 float pz = SPEEDOLIGHT * 100.F * bfield * m_charge * zeta;
00188                 m_ptot = sqrt (m_pt * m_pt + pz * pz);
00189 
00190                 // Calculate the start & end points
00191                 float x0, x1, y0, y1, z0, z1;
00192                 float phi0 = timeToAngle (t0);
00193                 float phi1 = timeToAngle (t1);
00194                 float delPhi = phi1 - phi0;
00195 
00196                 // Until we implement adjustable vector for control points,
00197                 // truncate curve at 2 loops
00198                 if (fabs (delPhi) > maxAngle)
00199                 {
00200                         delPhi = static_cast<float>(copysign (maxAngle, delPhi));
00201                         phi1 = delPhi + phi0;
00202                         t1 = angleToTime (phi1);
00203                 }
00204 
00205                 if (delPhi == 0)
00206                 {
00207                         z0 = timeToZ (t0);
00208                         z1 = timeToZ (t1);
00209                 }
00210                 else
00211                 {
00212                         z0 = vertex [2] - (phi0 - phi) * zeta;
00213                         z1 = vertex [2] - (phi1 - phi) * zeta;
00214                 }
00215 
00216                 float xc = vertex [0] + radius * sin (phi);
00217                 float yc = vertex [1] - radius * cos (phi);
00218                 x0 = xc - radius * sin (phi0);
00219                 y0 = yc + radius * cos (phi0);
00220                 x1 = xc - radius * sin (phi1);
00221                 y1 = yc + radius * cos (phi1);
00222 
00223                 // Calculate the control points & knot vector
00224                 // actually 2*(maxAngle/maxNurbAngle + 1), but avoid rounding prob
00225                 ctlPoints.resize (static_cast<int>(2*(maxAngle/maxNurbAngle +2)));
00226                 // #ctlPoints + NORDER
00227                 knots.resize (static_cast<int>(2*(maxAngle/maxNurbAngle +2)+NORDER)); 
00228 
00229                 // the first knot value has multiplicity NORDER (=3), put one in
00230                 // now, and let the normal routine put in the additional NORDER-1.
00231                 knots [nknots++] = static_cast<float>(nknot);
00232 
00233                 if (fabs (delPhi) < maxNurbAngle)
00234                 {
00235                         // if less than the max arc covered in one nurb segment, just use the points.
00236                         ctlPoints [npoints++] = SbVec4f (x0, y0, z0, 1.0);
00237 
00238                         // knot values for this point: nknots for NORDER-1 terms
00239                         knots [nknots++] = static_cast<float>(nknot);
00240                         knots [nknots++] = static_cast<float>(nknot++);
00241 
00242                         ctlPoints [npoints++] =
00243                                 SbVec4f (xc - sin (delPhi/2.F + phi0) * radius / fabs (cos (delPhi/2.F)),
00244                                 yc + cos (delPhi/2.F + phi0) * radius / fabs (cos (delPhi/2.F)),
00245                                 (z0 + z1) / 2.F,
00246                                 1.F)
00247                                 * fabs (cos (delPhi / 2.F));
00248                 }
00249                 else
00250                 {
00251                         // Must generate some filler points
00252                         //
00253                         //   x--------------------------------x
00254                         //               ||
00255                         //               \/
00256                         //   x-----o-----x------o----x---o----x
00257                         //
00258                         //   (one segment becomes three in this example.
00259                         //    nfill=1 => nfill=3, w/ 2 x points (normal weight)
00260                         //    and  3 o points to insert
00261 
00262                         int nfill = 1 + (int) (fabs (delPhi) / maxNurbAngle ); // ensure at least one fill division
00263                         if (nfill == 1)
00264                                 // ensure at least 5 points
00265                                 nfill = 2;
00266                         double delAngle = delPhi / nfill;
00267                         double delZ = (z1 - z0) / delPhi; // change in z wrt angle
00268 
00269                         for (int i = 0; i < nfill; ++i)
00270                         {
00271                                 double angle = phi0 + i * delAngle;
00272 
00273                                 if (i == 0)
00274                                         // put the first point at exactly the right point
00275                                         ctlPoints [npoints++] = SbVec4f (x0, y0, z0, 1.0F);
00276                                 else
00277                                         ctlPoints [npoints++] = SbVec4f (xc - radius * sin (angle),
00278                                         yc + radius * cos (angle),
00279                                         z0 + delZ * (angle - phi0),
00280                                         1.0F);
00281 
00282                                 // put in the knot values for this point: nknots for NORDER-1 terms
00283                                 knots [nknots++] = static_cast<float>(nknot);
00284                                 knots [nknots++] = static_cast<float>(nknot++);
00285 
00286                                 ctlPoints [npoints++] =
00287                                         SbVec4f (xc - radius * sin (angle + delAngle/2.F) / fabs (cos (delAngle/2.F)),
00288                                         yc + radius * cos (angle + delAngle/2.F) / fabs (cos (delAngle/2.F)),
00289                                         z0 + delZ * (angle + delAngle/2.F - phi0),
00290                                         1.0F)
00291                                         * fabs (cos (delAngle/2.F));
00292                         }
00293                 }
00294 
00295                 // The end point
00296                 ctlPoints [npoints++] = SbVec4f (x1, y1, z1, 1.0F);
00297                 knots [nknots++] = static_cast<float>(nknot);
00298                 knots [nknots++] = static_cast<float>(nknot);
00299                 knots [nknots++] = static_cast<float>(nknot);
00300                 // Set the coordinates
00301                 points->point.setValues (0, npoints, &ctlPoints[0]);
00302 
00303                 // Rebuild the curve
00304                 curve->numControlPoints = npoints;
00305                 curve->knotVector.setValues (0, nknots, &knots[0]);
00306         }
00307 #ifdef IG_DEBUG_PTS
00308         //          Add debugging polymarkers for control points
00309         for (int i = 0; i < npoints; ++i)
00310         {
00311                 SbVec3f pt;
00312                 ctlPoints [i].getReal (pt);
00313                 debugVtx->vertex.set1Value (i, pt);
00314         }
00315 
00316         debugStyle->pointSize = 4;
00317         debugStyle->style = SoDrawStyle::LINES;
00318         debugPoints->vertexProperty = debugVtx;
00319         setPart ("debugStyle",  debugStyle);
00320         setPart ("debugPoints", debugPoints);
00321 #endif // IG_DEBUG_PTS
00322 
00323 
00324 
00325         setPart ("material",    m_particleChar->getMaterial ());
00326         setPart ("style",               m_particleChar->getStyle ());
00327         setPart ("complexity",  complexity);
00328         setPart ("points",              points);
00329         setPart ("curve",               curve);
00330 
00331 
00332 #if 0 //DEBUG
00333         std::cout << "IgSoIdealTrack particle name: " << particleType.getValue ().getString ()
00334                 << " material: " << m_particleChar->getMaterial()
00335                 << std::endl;
00336 #endif //DEBUG
00337 }
00338 
00339 float
00340 IgSoIdealTrack::timeToAngle (float time)
00341 {
00342         float phi = this->phi.getValue ();
00343         float radius = this->radius.getValue ();
00344         float tstart = this->tstart.getValue ();
00345         float mass = m_particleChar->getMass ();
00346         float betat = m_pt / sqrt (mass * mass + m_ptot * m_ptot);
00347         if (fabs (radius))
00348                 return phi - betat * SPEEDOLIGHT * (time - tstart) / radius;
00349         else
00350                 return phi;
00351 }
00352 
00353 float
00354 IgSoIdealTrack::angleToTime (float angle)
00355 {
00356         float phi = this->phi.getValue ();
00357         float radius = this->radius.getValue ();
00358         float tstart = this->tstart.getValue ();
00359         float mass = m_particleChar->getMass ();
00360         float betat = m_pt / sqrt (mass * mass + m_ptot * m_ptot);
00361         return tstart - (radius * (angle - phi)) / (betat * SPEEDOLIGHT);
00362 }
00363 
00364 float
00365 IgSoIdealTrack::zToTime (float z)
00366 {
00367         SbVec3f vertex = this->vertex.getValue ();
00368         float zeta = this->zeta.getValue ();
00369         float tstart = this->tstart.getValue ();
00370         float mass = m_particleChar->getMass ();
00371 
00372         float betaz;
00373         if (bfield != 0 && m_charge != 0)
00374         {
00375                 betaz = (zeta * SPEEDOLIGHT * 100 * bfield * m_charge)
00376                         / sqrt (mass * mass + m_ptot * m_ptot); // = pz/E = z component of v
00377         }
00378         else
00379         {
00380                 betaz = zeta * m_ptot / sqrt( m_ptot*m_ptot + mass * mass );
00381         }
00382         if (fabs (betaz))
00383                 return tstart + (z - vertex [2]) / (betaz * SPEEDOLIGHT);
00384         else
00385                 return tstart;
00386 }
00387 
00388 float
00389 IgSoIdealTrack::timeToZ (float time)
00390 {
00391         SbVec3f vertex = this->vertex.getValue ();
00392         float zeta = this->zeta.getValue ();
00393         float tstart = this->tstart.getValue ();
00394         float mass = m_particleChar->getMass ();
00395         float betaz;
00396         if ( bfield != 0 && m_charge != 0 )
00397         {
00398                 betaz = (zeta * SPEEDOLIGHT * 100 * bfield * m_charge)
00399                         / sqrt (mass * mass + m_ptot * m_ptot); // = pz/E = z component of v
00400         }
00401         else
00402         {
00403                 betaz = zeta * m_ptot / sqrt (mass * mass + m_ptot * m_ptot);
00404         }
00405 
00406         return (time - tstart) * betaz * SPEEDOLIGHT + vertex [2];
00407 }
00408 
00409 SbVec2f
00410 IgSoIdealTrack::timeToXY (float time)
00411 {
00412         if ( bfield ==0 || m_charge == 0 )
00413         {
00414                 float mass = m_particleChar->getMass ();
00415                 float betat = m_pt / sqrt ( mass*mass + m_ptot * m_ptot );
00416                 float deltaT = time - tstart.getValue();
00417                 float x = vertex.getValue() [0] + cos(phi.getValue()) * betat * deltaT * SPEEDOLIGHT;
00418                 float y = vertex.getValue() [1] + sin(phi.getValue()) * betat * deltaT * SPEEDOLIGHT;
00419                 return SbVec2f ( x, y );
00420         }
00421         else
00422         {
00423                 float angle = timeToAngle (time);
00424                 SbVec3f vertex = this->vertex.getValue ();
00425                 double radius = this->radius.getValue ();
00426                 double phi = this->phi.getValue ();
00427                 double xc = vertex [0] + radius * sin (phi);
00428                 double yc = vertex [1] - radius * cos (phi);
00429                 return SbVec2f (xc - radius * sin (angle), yc + radius * cos (angle));
00430         }
00431 }
00432 
00442 void
00443 IgSoIdealTrack::initialise (double *vx, double *vy, double *vz, 
00444                                                         double *px, double *py, double *pz, 
00445                                                         float *t0, IgParticleChar *pc)
00446 { initialise (*vx, *vy, *vz, *px, *py, *pz, *t0, pc); }
00447 
00448 void
00449 IgSoIdealTrack::initialise (double vx, double vy, double vz, 
00450                                                         double px, double py, double pz, 
00451                                                         float t0, int pid)
00452 { initialise (vx, vy, vz, px, py, pz, t0, IgParticleChar::getByGeantID (pid)); }
00453 
00454 void
00455 IgSoIdealTrack::initialise (double vx, double vy, double vz,
00456                                                         double px, double py, double pz,
00457                                                         float t0, IgParticleChar *pc)
00458 {
00459         m_particleChar = pc;
00460         m_charge = pc->getCharge ();
00461         particleType = pc->getName ();
00462 
00463         SbVec3f vec3 = SbVec3f (px, py, pz);
00464         SbVec2f vec2 = SbVec2f (px, py);
00465         m_ptot = vec3.length ();
00466         m_pt = vec2.length ();
00467 
00468         double radius, zeta;
00469         // 100*SPEEDOFLIGHT gives right factor for p [GeV/c], B[Tesla], R[m], q[electron charges] (about 0.3)
00470         double qB = SPEEDOLIGHT * 100 * bfield * m_charge;  
00471         if (qB != 0)
00472         {
00473                 radius = m_pt / qB;
00474                 zeta = pz / qB;
00475         }
00476         else
00477         {
00478                 radius = std::numeric_limits<double>::infinity();
00479                 zeta = pz / m_ptot;
00480         }
00481 
00482 
00483         this->vertex = SbVec3f (vx, vy, vz);
00484         this->radius = static_cast<float>(radius);
00485         this->zeta = static_cast<float>(zeta);
00486         this->phi = static_cast<float>( px == 0.0 && px == 0.0 ? 0.0 : atan2(py, px) );
00487         this->t0 = t0;
00488         this->tstart = t0;
00489 
00490         initEndPts ();
00491 }
00492 
00493 void
00494 IgSoIdealTrack::initEndPts (void)
00495 {
00496         float   radius = this->radius.getValue ();
00497         float   zeta = this->zeta.getValue ();
00498         SbVec3f vertex = this->vertex.getValue ();
00499         float   phi = this->phi.getValue ();
00500         double  xc = vertex [0] + radius * sin (phi);
00501         double  yc = vertex [1] - radius * cos (phi);
00502         double  delPhi;  // end pt of track & total arc length in x-y plane
00503         double  x1;
00504         double  y1;
00505         double  z1;
00506         if ( radius == std::numeric_limits<double>::infinity() )
00507         {
00508                 // find intersection with cylinder: straight line case
00509                 if (zeta==0)
00510                 {
00511                         // no z momentum, must intersect side
00512                         double s = -cos(phi)*vertex[0] - sin(phi)*vertex[1]+ sqrt( pow(rmax,2) - pow(vertex[0],2)
00513                                 - pow(vertex[1],2)+ pow( cos(phi)*vertex[0]+sin(phi)*vertex[1], 2));
00514                         x1 = vertex[0] + s * cos(phi);
00515                         y1 = vertex[1] + s * sin(phi);
00516                         z1 = vertex[3];
00517                         float mass = m_particleChar->getMass ();
00518                         tend = s / ( sqrt(1.F - pow(zeta,2) ) * m_ptot / sqrt ( m_ptot*m_ptot + mass*mass) * SPEEDOLIGHT ); 
00519                 }
00520                 else if (m_pt ==0)
00521                 {
00522                         // no pt, must be parallel to z axis
00523                         x1 = vertex[0]; y1 = vertex[1];
00524                         z1 = zeta>0 ? zmax : -zmax;
00525                         tend = zToTime (z1);
00526                 }
00527                 else
00528                 {
00529                         double s = -cos(phi)*vertex[0] - sin(phi)*vertex[1] + sqrt( pow(rmax,2) - pow(vertex[0],2)
00530                                 - pow(vertex[1],2) + pow( cos(phi)*vertex[0]+sin(phi)*vertex[1], 2));
00531 
00532                         double zint =  s * zeta/sqrt( 1.f - pow(zeta,2)  ) + vertex[2];
00533                         if ( abs(zint) > zmax )
00534                         {
00535                                 zint = zint > 0.F ? zmax : -zmax;
00536                                 s = (zint - vertex[2]) * sqrt( 1 - pow(zeta,2) ) / zeta;
00537                         }
00538                         x1 = s * cos(phi) + vertex[0]; y1 = s * sin(phi) + vertex[1]; z1 = zint;
00539                         tend = zToTime (z1);
00540                 }
00541                 dt = tend.getValue () - tstart.getValue ();
00542         }
00543         else
00544         {
00545 
00546                 // See if there is an intersection between our helix and the
00547                 // visible edge boundary cylinder
00548                 if (xc == 0 && yc == 0)
00549                 {
00550                         // concentric with z-axis
00551                         if (fabs (radius) >= rmax)
00552                                 // outside max radius
00553                                 return;
00554 
00555                         x1 = vertex [0];
00556                         y1 = vertex [1];
00557                         delPhi = - 2. * copysign (1.0, m_charge * bfield) * M_PI * 2;
00558 
00559                         if (m_pt == 0.0)
00560                         {
00561                                 // z1 = pz
00562                                 z1 = copysign (zmax, zeta * m_charge * bfield);
00563                                 delPhi = 0.0;
00564                         }
00565                         else
00566                         {
00567                                 z1 = vertex [2] - delPhi * zeta;
00568                                 if (fabs (z1) > zmax)
00569                                         delPhi = -(copysign (zmax, z1) - vertex [2]) / zeta;
00570                         }
00571                 }
00572                 else
00573                 {
00574                         double x2, y2, delPhi1, delPhi2;
00575                         double gamma = yc ? -xc / yc : FLT_MAX;
00576                         double delta = (rmax * rmax - radius * radius - xc * xc - yc * yc) / (2 * yc);
00577                         double det = 4 * gamma * gamma * delta * delta
00578                                 - 4 * (1 + gamma * gamma) * (delta * delta - radius * radius);
00579 
00580                         if (det >= 0)
00581                         {
00582                                 // have intersection
00583                                 det = sqrt (det);
00584                                 x1 = (-2 * gamma * delta + det) / (2 * (1 + gamma * gamma));
00585                                 x2 = (-2 * gamma * delta - det) / (2 * (1 + gamma * gamma));
00586                                 y1 = gamma * x1 + delta;
00587                                 y2 = gamma * x2 + delta;
00588                                 x1 = xc + x1;
00589                                 x2 = xc + x2;
00590                                 y1 = yc + y1;
00591                                 y2 = yc + y2;
00592 
00593                                 // Determine which intersection it is... : pos for neg charge.
00594                                 delPhi1 = atan2 (-(x1 - xc) / radius, (y1 - yc) / radius) - phi;
00595                                 delPhi2 = atan2 (-(x2 - xc) / radius, (y2 - yc) / radius) - phi;
00596 
00597                                 if (m_charge * bfield < 0)
00598                                 {
00599                                         // arc increases wrt time for negative charge
00600                                         if (delPhi1 < 0)
00601                                                 delPhi1 += M_PI*2;
00602                                         if (delPhi2 < 0)
00603                                                 delPhi2 += M_PI*2;
00604                                 }
00605                                 else
00606                                 {
00607                                         // arc decreases wrt time for positive charge
00608                                         if (delPhi1 > 0)
00609                                                 delPhi1 -= M_PI*2;
00610                                         if (delPhi2 > 0)
00611                                                 delPhi2 -= M_PI*2;
00612                                 }
00613 
00614                                 if ((m_charge * bfield < 0 && delPhi1 < delPhi2)
00615                                         || (m_charge * bfield > 0 && delPhi1 > delPhi2))
00616                                         delPhi = delPhi1;
00617                                 else
00618                                 {
00619                                         x1 = x2;
00620                                         y1 = y2;
00621                                         delPhi = delPhi2;
00622                                 }
00623                         }
00624                         else
00625                         {
00626                                 // just put in two loops or z intersection
00627                                 delPhi = -2.0 * copysign (1.0, m_charge * bfield) * M_PI*2;
00628                                 x1 = vertex [0];
00629                                 y1 = vertex [1];
00630                                 z1 = timeToZ (angleToTime (delPhi + phi));
00631 
00632                                 if (fabs (z1) > zmax)
00633                                 {
00634                                         z1 = copysign (zmax, z1);
00635                                         delPhi = timeToAngle (zToTime (z1 - vertex [2])) - phi;
00636                                 }
00637                         }
00638                 }
00639 
00640                 if (delPhi)
00641                         tend = angleToTime (delPhi + phi);
00642                 else
00643                         tend = zToTime (z1);
00644 
00645                 dt = tend.getValue () - tstart.getValue ();
00646         }
00647 }

Generated on Tue Jun 9 17:38:46 2009 for CMSSW by  doxygen 1.5.4