77 Int_t THelix::fgMinNSeg=5;        
 
   84 void  THelix::SetHelix(Double_t *p,  Double_t *v,  Double_t w,
 
   85                        Double_t *range, EHelixRangeType rType,
 
   93    Double_t * m = fRotMat->GetMatrix();
 
   94    Double_t vx0, vy0, vz0;
 
   95    vx0   = v[0] * m[0] + v[1] * m[1] + v[2] * m[2];
 
   96    vy0   = v[0] * m[3] + v[1] * m[4] + v[2] * m[5];
 
   97    vz0   = v[0] * m[6] + v[1] * m[7] + v[2] * m[8];
 
   98    fVt   = TMath::Sqrt(vx0*vx0 + vy0*vy0);
 
   99    fPhi0 = TMath::ATan2(vy0,vx0);
 
  101    fX0   = p[0] * m[0] +  p[1] * m[1] +  p[2] * m[2];
 
  102    fY0   = p[0] * m[3] +  p[1] * m[4] +  p[2] * m[5];
 
  103    fZ0   = p[0] * m[6] +  p[1] * m[7] +  p[2] * m[8];
 
  105       fX0 += fVt / fW * TMath::Sin(fPhi0);
 
  106       fY0 -= fVt / fW * TMath::Cos(fPhi0);
 
  112    if (range) {r1 = range[0]; r2 = range[1];}
 
  113    if (rType != kUnchanged) {
 
  114       fRange[0] = 0.0;   fRange[1] = TMath::Pi();   
 
  115       SetRange(r1,r2,rType);
 
  124    fX0 = fY0 = fZ0 = fVt = fPhi0 = fVz = fAxis[0] = fAxis[1] = 0.0;
 
  135 THelix::THelix(Double_t x,  Double_t y,  Double_t z,
 
  136                Double_t vx, Double_t vy, Double_t vz,
 
  150    SetHelix(p, v, w, range, kHelixZ);
 
  157 THelix::THelix(Double_t * p, Double_t * v, Double_t w,
 
  158                Double_t * range, EHelixRangeType rType, Double_t * axis)
 
  163       r[0] = range[0];   r[1] = range[1];
 
  165       r[0] = 0.0;        r[1] = 1.0;
 
  170       SetHelix(p, v, w, r, rType, axis);
 
  172       SetHelix(p, v, w, r, rType);
 
  183 THelix::THelix(
const THelix &h) : TPolyLine3D()
 
  192    for (Int_t i=0; i<3; i++) fAxis[i] = h.fAxis[i];
 
  193    fRotMat = 
new TRotMatrix(*(h.fRotMat));
 
  194    fRange[0] = h.fRange[0];
 
  195    fRange[1] = h.fRange[1];
 
  204 THelix& THelix::operator=(
const THelix& hx)
 
  207       TPolyLine3D::operator=(hx);
 
  215       for(Int_t i=0; i<3; i++)
 
  216          fAxis[i]=hx.fAxis[i];
 
  218       for(Int_t i=0; i<2; i++)
 
  219          fRange[i]=hx.fRange[i];
 
  229    if (fRotMat) 
delete fRotMat;
 
  236 THelix::THelix(
const THelix &helix) : TPolyLine3D(helix)
 
  239    ((THelix&)helix).THelix::Copy(*
this);
 
  246 void THelix::Copy(TObject &obj)
 const 
  249    TAttLine::Copy(((THelix&)obj));
 
  251    ((THelix&)obj).fX0        = fX0;
 
  252    ((THelix&)obj).fY0        = fY0;
 
  253    ((THelix&)obj).fZ0        = fZ0;
 
  254    ((THelix&)obj).fVt        = fVt;
 
  255    ((THelix&)obj).fPhi0      = fPhi0;
 
  256    ((THelix&)obj).fVz        = fVz;
 
  257    ((THelix&)obj).fW         = fW;
 
  258    for (Int_t i=0; i<3; i++)
 
  259       ((THelix&)obj).fAxis[i] = fAxis[i];
 
  261    if (((THelix&)obj).fRotMat)
 
  262       delete ((THelix&)obj).fRotMat;
 
  263    ((THelix&)obj).fRotMat    = 
new TRotMatrix(*fRotMat);
 
  265    ((THelix&)obj).fRange[0]  = fRange[0];
 
  266    ((THelix&)obj).fRange[1]  = fRange[1];
 
  268    ((THelix&)obj).fOption    = fOption;
 
  273    ((THelix&)obj).SetRange(fRange[0], fRange[1], kHelixT);
 
  280 void THelix::Draw(Option_t *option)
 
  289 void THelix::Print(Option_t *option)
 const 
  291    std::cout <<
"    THelix Printing N=" <<fN<<
" Option="<<option<<std::endl;
 
  298 void THelix::SavePrimitive(std::ostream &out, Option_t * )
 
  302    if (gROOT->ClassSaved(THelix::Class())) {
 
  307    out<<
"helix = new THelix("<<fX0<<
","<<fY0<<
","<<fZ0<<
"," 
  308       <<fVt*TMath::Cos(fPhi0)<<
","<<fVt*TMath::Sin(fPhi0)<<
","<<fVz<<
"," 
  309       <<fW<<
","<<fRange[0]<<
","<<fRange[1]<<
","<<(Int_t)kHelixT<<
"," 
  310       <<fAxis[0]<<
","<<fAxis[1]<<
","<<fAxis[2]<<
"," 
  311       <<quote<<fOption<<quote<<
");"<<std::endl;
 
  313    SaveLineAttributes(out,
"helix",1,1,1);
 
  315    out<<
"   helix->Draw();"<<std::endl;
 
  322 void THelix::SetAxis(Double_t * axis)
 
  325       Double_t len = TMath::Sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]);
 
  327          Error(
"SetAxis()", 
"Impossible! axis length %lf <= 0!", len);
 
  330       fAxis[0] = axis[0]/len;
 
  331       fAxis[1] = axis[1]/len;
 
  332       fAxis[2] = axis[2]/len;
 
  347 void THelix::SetAxis(Double_t x, Double_t y, Double_t z)
 
  349    Double_t axis[3];    axis[0] = x;    axis[1] = y;    axis[2] = z;
 
  357 void THelix::SetRange(Double_t * range, EHelixRangeType rType)
 
  360    Double_t halfpi = TMath::Pi()/2.0;
 
  362    Double_t vx = fVt * TMath::Cos(fPhi0);
 
  363    Double_t vy = fVt * TMath::Sin(fPhi0);
 
  366    if ( fW != 0 && fVz != 0 ) {         
 
  369             fRange[0] = range[0];  fRange[1] = range[1];  
break;
 
  372             for (i=0; i<2; i++ ) {
 
  373                a[i] = fW / fVt * (range[i] - fX0);
 
  374                if ( a[i] < -1 || a[i] > 1 ) {
 
  376                         "range out of bound (%lf:%lf): %lf.  Default used: %lf",
 
  377                         fX0-fVt/fW, fX0+fVt/fW, range[i], fRange[i]);
 
  380                phase = FindClosestPhase(fPhi0+halfpi, a[i]);
 
  381                fRange[i] = ( fPhi0 + halfpi - phase ) / fW;
 
  386             for (i=0; i<2; i++ ) {
 
  387                a[i] = fW / fVt * (range[i] - fY0);
 
  388                if ( a[i] < -1 || a[i] > 1 ) {
 
  390                         "range out of bound (%lf:%lf): %lf.  Default used: %lf",
 
  391                          fY0-fVt/fW, fY0+fVt/fW, range[i], fRange[i]);
 
  394                phase = FindClosestPhase(fPhi0, a[i]);
 
  395                fRange[i] = ( fPhi0 - phase ) / fW;
 
  401                for (i=0; i<2; i++ ) {
 
  402                   fRange[i] = (range[i] - fZ0) / fVz;
 
  406                      "Vz = 0 and attempts to set range along helix axis!");
 
  414             printf(
"setting range in lab axes is not implemented yet\n");
 
  417             Error(
"SetRange()",
"unknown range type %d", rType);
 
  420    } 
else if ( fW == 0 ) {                
 
  423             fRange[0] = range[0];  fRange[1] = range[1];
 
  427                fRange[0] = (range[0] - fX0) / vx;
 
  428                fRange[1] = (range[1] - fX0) / vx;
 
  431                      "Vx = 0 and attempts to set range on helix x axis!");
 
  437                fRange[0] = (range[0] - fY0) / vy;
 
  438                fRange[1] = (range[1] - fY0) / vy;
 
  441                      "Vy = 0 and attempts to set range on helix y axis!");
 
  447                fRange[0] = (range[0] - fZ0) / fVz;
 
  448                fRange[1] = (range[1] - fZ0) / fVz;
 
  451                      "Vz = 0 and attempts to set range on helix z axis!");
 
  458             printf(
"setting range in lab axes is not implemented yet\n");
 
  461             Error(
"SetRange()",
"unknown range type %d", rType);
 
  464    } 
else if ( fVz == 0 ) {               
 
  467             fRange[0] = range[0];  fRange[1] = range[1];  
break;
 
  470                fRange[0] = (range[0] - fX0) / vx;
 
  471                fRange[1] = (range[1] - fX0) / vx;
 
  474                      "Vx = 0 and attempts to set range on helix x axis!");
 
  480                fRange[0] = (range[0] - fY0) / vy;
 
  481                fRange[1] = (range[1] - fY0) / vy;
 
  484                      "Vy = 0 and attempts to set range on helix y axis!");
 
  490                   "Vz = 0 and attempts to set range on helix z axis!");
 
  495             printf(
"setting range in lab axes is not implemented yet\n");
 
  498             Error(
"SetRange()",
"unknown range type %d", rType);
 
  503    if ( fRange[0] > fRange[1] ) {
 
  504       Double_t temp = fRange[1];   fRange[1] = fRange[0];  fRange[0] = temp;
 
  508    Double_t degrad  = TMath::Pi() / 180.0;
 
  509    Double_t segment = 5.0 * degrad;             
 
  510    Double_t dt      = segment / TMath::Abs(fW); 
 
  512    Int_t    nSeg    = Int_t((fRange[1]-fRange[0]) / dt) + 1;
 
  513    if (nSeg < THelix::fgMinNSeg) {
 
  514       nSeg = THelix::fgMinNSeg;
 
  515       dt = (fRange[1]-fRange[0])/nSeg;
 
  518    Double_t * xl    = 
new Double_t[nSeg+1];     
 
  519    Double_t * yl    = 
new Double_t[nSeg+1];
 
  520    Double_t * zl    = 
new Double_t[nSeg+1];
 
  522    for (i=0; i<=nSeg; i++) {                    
 
  524       if (i==nSeg) t = fRange[1];                
 
  525       else         t = fRange[0] + dt * i;
 
  526       phase2 = -fW * t + fPhi0;
 
  527       xl[i] = fX0 - fVt/fW * TMath::Sin(phase2);
 
  528       yl[i] = fY0 + fVt/fW * TMath::Cos(phase2);
 
  529       zl[i] = fZ0 + fVz * t;
 
  534    Double_t * m = fRotMat->GetMatrix();
 
  535    TPolyLine3D::SetPolyLine(nSeg+1);
 
  536    for (i=0; i<=nSeg; i++) {                    
 
  537       xg =  xl[i] * m[0]  +  yl[i] * m[3]  +  zl[i] * m[6] ;
 
  538       yg =  xl[i] * m[1]  +  yl[i] * m[4]  +  zl[i] * m[7] ;
 
  539       zg =  xl[i] * m[2]  +  yl[i] * m[5]  +  zl[i] * m[8] ;
 
  540       TPolyLine3D::SetPoint(i,xg,yg,zg);
 
  543    delete[] xl;  
delete[] yl;    
delete[] zl;
 
  550 void THelix::SetRange(Double_t r1, Double_t r2, EHelixRangeType rType)
 
  553    range[0] = r1;       range[1] = r2;
 
  554    SetRange(range, rType);
 
  568 void THelix::SetRotMatrix()
 
  572    Double_t raddeg = 180.0 / TMath::Pi();
 
  573    Double_t halfpi = TMath::Pi()/2.0 * raddeg;
 
  575    Double_t theta3 = TMath::ACos(fAxis[2]) * raddeg;
 
  576    Double_t phi3   = TMath::ATan2(fAxis[1], fAxis[0]) * raddeg;
 
  578    Double_t theta1 = theta3 + halfpi;
 
  579    Double_t phi1   = phi3;
 
  581    Double_t theta2 = halfpi;
 
  582    Double_t phi2   = phi1 + halfpi;
 
  585    if (fRotMat) 
delete fRotMat;
 
  588    fRotMat = 
new TRotMatrix(
"HelixRotMat", 
"Master frame -> Helix frame",
 
  589                             theta1, phi1,  theta2, phi2,  theta3, phi3 );
 
  597 Double_t  THelix::FindClosestPhase(Double_t phi0,  Double_t cosine)
 
  599    const Double_t pi    = TMath::Pi();
 
  600    const Double_t twopi = TMath::Pi() * 2.0;
 
  601    Double_t phi1 = TMath::ACos(cosine);
 
  602    Double_t phi2 = - phi1;
 
  604    while ( phi1 - phi0 >  pi )   phi1 -= twopi;
 
  605    while ( phi1 - phi0 < -pi )   phi1 += twopi;
 
  607    while ( phi2 - phi0 >  pi )   phi2 -= twopi;
 
  608    while ( phi2 - phi0 < -pi )   phi2 += twopi;
 
  612    if ( TMath::Abs(phi1-phi0) < TMath::Abs(phi2-phi0) )  
return phi1;
 
  620 void THelix::Streamer(TBuffer &R__b)
 
  622    if (R__b.IsReading()) {
 
  624       Version_t R__v = R__b.ReadVersion(&R__s, &R__c); 
if (R__v) { }
 
  626          R__b.ReadClassBuffer(THelix::Class(), 
this, R__v, R__s, R__c);
 
  630       TPolyLine3D::Streamer(R__b);
 
  638       R__b.ReadStaticArray(fAxis);
 
  640       R__b.ReadStaticArray(fRange);
 
  641       R__b.CheckByteCount(R__s, R__c, THelix::IsA());
 
  645       R__b.WriteClassBuffer(THelix::Class(),
this);