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);