62 TGeoHelix::TGeoHelix()
68 fPointInit[0] = fPointInit[1] = fPointInit[2] = 0.;
69 fDirInit[0] = fDirInit[1] = fDirInit[2] = 0.;
70 fPoint[0] = fPoint[1] = fPoint[2] = 0.;
71 fDir[0] = fDir[1] = fDir[2] = 0.;
72 fB[0] = fB[1] = fB[2] = 0.;
75 TObject::SetBit(kHelixNeedUpdate, kTRUE);
76 TObject::SetBit(kHelixStraight, kFALSE);
77 TObject::SetBit(kHelixCircle, kFALSE);
83 TGeoHelix::TGeoHelix(Double_t curvature, Double_t hstep, Int_t charge)
85 SetXYcurvature(curvature);
91 fPointInit[0] = fPointInit[1] = fPointInit[2] = 0.;
92 fDirInit[0] = fDirInit[1] = fDirInit[2] = 0.;
93 fPoint[0] = fPoint[1] = fPoint[2] = 0.;
94 fDir[0] = fDir[1] = fDir[2] = 0.;
95 fB[0] = fB[1] = fB[2] = 0.;
96 fMatrix =
new TGeoHMatrix();
97 TObject::SetBit(kHelixNeedUpdate, kTRUE);
98 TObject::SetBit(kHelixStraight, kFALSE);
99 TObject::SetBit(kHelixCircle, kFALSE);
105 TGeoHelix::~TGeoHelix()
107 if (fMatrix)
delete fMatrix;
114 Double_t TGeoHelix::ComputeSafeStep(Double_t epsil)
const
116 if (TestBit(kHelixStraight) || TMath::Abs(fC)<TGeoShape::Tolerance())
return 1.E30;
117 Double_t c = GetTotalCurvature();
118 Double_t step = TMath::Sqrt(2.*epsil/c);
125 void TGeoHelix::InitPoint(Double_t x0, Double_t y0, Double_t z0)
130 TObject::SetBit(kHelixNeedUpdate, kTRUE);
136 void TGeoHelix::InitPoint (Double_t *point)
138 InitPoint(point[0], point[1], point[2]);
144 void TGeoHelix::InitDirection(Double_t dirx, Double_t diry, Double_t dirz, Bool_t is_normalized)
149 TObject::SetBit(kHelixNeedUpdate, kTRUE);
150 if (is_normalized)
return;
151 Double_t norm = 1./TMath::Sqrt(dirx*dirx+diry*diry+dirz*dirz);
152 for (Int_t i=0; i<3; i++) fDirInit[i] *= norm;
158 void TGeoHelix::InitDirection(Double_t *dir, Bool_t is_normalized)
160 InitDirection(dir[0], dir[1], dir[2], is_normalized);
166 Double_t TGeoHelix::GetTotalCurvature()
const
168 Double_t k = fC/(1.+fC*fC*fS*fS);
175 void TGeoHelix::SetXYcurvature(Double_t curvature)
178 TObject::SetBit(kHelixNeedUpdate, kTRUE);
180 Error(
"SetXYcurvature",
"Curvature %f not valid. Must be positive.", fC);
183 if (TMath::Abs(fC) < TGeoShape::Tolerance()) {
184 Warning(
"SetXYcurvature",
"Curvature is zero. Helix is a straight line.");
185 TObject::SetBit(kHelixStraight, kTRUE);
192 void TGeoHelix::SetCharge(Int_t charge)
195 Error(
"ctor",
"charge cannot be 0 - define it positive for a left-handed helix, negative otherwise");
198 Int_t q = TMath::Sign(1, charge);
201 TObject::SetBit(kHelixNeedUpdate, kTRUE);
207 void TGeoHelix::SetField(Double_t bx, Double_t by, Double_t bz, Bool_t is_normalized)
212 TObject::SetBit(kHelixNeedUpdate, kTRUE);
213 if (is_normalized)
return;
214 Double_t norm = 1./TMath::Sqrt(bx*bx+by*by+bz*bz);
215 for (Int_t i=0; i<3; i++) fB[i] *= norm;
221 void TGeoHelix::SetHelixStep(Double_t step)
224 Error(
"ctor",
"Z step %f not valid. Must be positive.", step);
227 TObject::SetBit(kHelixNeedUpdate, kTRUE);
228 fS = 0.5*step/TMath::Pi();
229 if (fS < TGeoShape::Tolerance()) TObject::SetBit(kHelixCircle, kTRUE);
235 void TGeoHelix::ResetStep()
238 memcpy(fPoint, fPointInit, 3*
sizeof(Double_t));
239 memcpy(fDir, fDirInit, 3*
sizeof(Double_t));
253 void TGeoHelix::Step(Double_t step)
257 if (TObject::TestBit(kHelixStraight)) {
258 for (i=0; i<3; i++) {
259 fPoint[i] = fPointInit[i]+fStep*fDirInit[i];
260 fDir[i] = fDirInit[i];
264 if (TObject::TestBit(kHelixNeedUpdate)) UpdateHelix();
266 fPhi = fStep/TMath::Sqrt(r*r+fS*fS);
268 vect[0] = r * TMath::Cos(fPhi);
269 vect[1] = -fQ * r * TMath::Sin(fPhi);
271 fMatrix->LocalToMaster(vect, fPoint);
273 Double_t ddb = fDirInit[0]*fB[0]+fDirInit[1]*fB[1]+fDirInit[2]*fB[2];
274 Double_t f = -TMath::Sqrt(1.-ddb*ddb);
275 vect[0] = f*TMath::Sin(fPhi);
276 vect[1] = fQ*f*TMath::Cos(fPhi);
278 TMath::Normalize(vect);
279 fMatrix->LocalToMasterVect(vect, fDir);
285 Double_t TGeoHelix::StepToPlane(Double_t *point, Double_t *norm)
288 Double_t snext = 1.E30;
291 if (TObject::TestBit(kHelixNeedUpdate)) UpdateHelix();
292 dx = point[0] - fPoint[0];
293 dy = point[1] - fPoint[1];
294 dz = point[2] - fPoint[2];
295 pdn = dx*norm[0]+dy*norm[1]+dz*norm[2];
296 ddn = fDir[0]*norm[0]+fDir[1]*norm[1]+fDir[2]*norm[2];
297 if (TObject::TestBit(kHelixStraight)) {
299 if ((pdn*ddn) <= 0)
return snext;
307 Double_t safety = TMath::Abs(pdn);
308 Double_t safestep = ComputeSafeStep();
310 Bool_t approaching = (ddn*pdn>0)?kTRUE:kFALSE;
311 if (approaching) snext = pdn/ddn;
312 else if (safety > 2.*r)
return snext;
313 while (snext > safestep) {
314 dist = TMath::Max(safety, safestep);
317 dx = point[0] - fPoint[0];
318 dy = point[1] - fPoint[1];
319 dz = point[2] - fPoint[2];
320 pdn = dx*norm[0]+dy*norm[1]+dz*norm[2];
321 ddn = fDir[0]*norm[0]+fDir[1]*norm[1]+fDir[2]*norm[2];
322 safety = TMath::Abs(pdn);
323 approaching = (ddn*pdn>0)?kTRUE:kFALSE;
325 if (approaching) snext = pdn/ddn;
326 else if (safety > 2.*r) {
339 void TGeoHelix::UpdateHelix()
341 TObject::SetBit(kHelixNeedUpdate, kFALSE);
343 memcpy(fPoint, fPointInit, 3*
sizeof(Double_t));
344 memcpy(fDir, fDirInit, 3*
sizeof(Double_t));
347 Double_t ddb = fDirInit[0]*fB[0]+fDirInit[1]*fB[1]+fDirInit[2]*fB[2];
348 if ((1.-TMath::Abs(ddb))<TGeoShape::Tolerance() || TMath::Abs(fC)<TGeoShape::Tolerance()) {
350 TObject::SetBit(kHelixStraight, kTRUE);
357 if (ddb < 0) fS = -TMath::Abs(fS);
358 Double_t fy = - fQ*TMath::Sqrt(1.-ddb*ddb);
360 rot[1] = fy*(fDirInit[0]-fB[0]*ddb);
361 rot[4] = fy*(fDirInit[1]-fB[1]*ddb);
362 rot[7] = fy*(fDirInit[2]-fB[2]*ddb);
364 rot[0] = rot[4]*rot[8] - rot[7]*rot[5];
365 rot[3] = rot[7]*rot[2] - rot[1]*rot[8];
366 rot[6] = rot[1]*rot[5] - rot[4]*rot[2];
368 tr[0] = fPointInit[0] - rot[0]/fC;
369 tr[1] = fPointInit[1] - rot[3]/fC;
370 tr[2] = fPointInit[2] - rot[6]/fC;
372 fMatrix->SetTranslation(tr);
373 fMatrix->SetRotation(rot);