Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGeoTrack.cxx
Go to the documentation of this file.
1 // @(#)root/geom:$Id$
2 // Author: Andrei Gheata 2003/04/10
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "TBrowser.h"
13 #include "TPolyLine3D.h"
14 #include "TPoint.h"
15 #include "TVirtualPad.h"
16 #include "TView.h"
17 
18 #include "TGeoManager.h"
19 #include "TVirtualGeoPainter.h"
20 #include "TGeoTrack.h"
21 
22 /** \class TGeoTrack
23 \ingroup Geometry_classes
24 
25 Class for user-defined tracks attached to a geometry.
26 Tracks are 3D objects made of points and they store a
27 pointer to a TParticle. The geometry manager holds a list
28 of all tracks that will be deleted on destruction of
29 gGeoManager.
30 */
31 
32 ClassImp(TGeoTrack);
33 
34 ////////////////////////////////////////////////////////////////////////////////
35 /// Default constructor.
36 
37 TGeoTrack::TGeoTrack()
38 {
39  fPointsSize = 0;
40  fNpoints = 0;
41  fPoints = 0;
42 }
43 
44 ////////////////////////////////////////////////////////////////////////////////
45 /// Constructor.
46 
47 TGeoTrack::TGeoTrack(Int_t id, Int_t pdgcode, TVirtualGeoTrack *parent, TObject *particle)
48  :TVirtualGeoTrack(id,pdgcode,parent,particle)
49 {
50  fPointsSize = 0;
51  fNpoints = 0;
52  fPoints = 0;
53  if (fParent==0) {
54  SetMarkerColor(2);
55  SetMarkerStyle(8);
56  SetMarkerSize(0.6);
57  SetLineColor(2);
58  SetLineWidth(2);
59  } else {
60  SetMarkerColor(4);
61  SetMarkerStyle(8);
62  SetMarkerSize(0.6);
63  SetLineColor(4);
64  SetLineWidth(2);
65  }
66 }
67 
68 ////////////////////////////////////////////////////////////////////////////////
69 /// Copy ctor. NOT TO BE CALLED.
70 
71 TGeoTrack::TGeoTrack(const TGeoTrack& other)
72  :TVirtualGeoTrack(other),
73  fPointsSize(other.fPointsSize),
74  fNpoints(other.fNpoints),
75  fPoints(other.fPoints)
76 {
77 }
78 
79 ////////////////////////////////////////////////////////////////////////////////
80 /// Assignment operator. NOT TO BE CALLED.
81 
82 TGeoTrack& TGeoTrack::operator=(const TGeoTrack& gv)
83 {
84  if(this!=&gv) {
85  TVirtualGeoTrack::operator=(gv);
86  fPointsSize=gv.fPointsSize;
87  fNpoints=gv.fNpoints;
88  fPoints=gv.fPoints;
89  }
90  return *this;
91 }
92 
93 ////////////////////////////////////////////////////////////////////////////////
94 /// Destructor.
95 
96 TGeoTrack::~TGeoTrack()
97 {
98  if (fPoints) delete [] fPoints;
99 // if (gPad) gPad->GetListOfPrimitives()->Remove(this);
100 }
101 
102 ////////////////////////////////////////////////////////////////////////////////
103 /// Add a daughter track to this.
104 
105 TVirtualGeoTrack *TGeoTrack::AddDaughter(Int_t id, Int_t pdgcode, TObject *particle)
106 {
107  if (!fTracks) fTracks = new TObjArray(1);
108  Int_t index = fTracks->GetEntriesFast();
109  TGeoTrack *daughter = new TGeoTrack(id,pdgcode,this,particle);
110  fTracks->AddAtAndExpand(daughter,index);
111  return daughter;
112 }
113 
114 ////////////////////////////////////////////////////////////////////////////////
115 /// Add a daughter and return its index.
116 
117 Int_t TGeoTrack::AddDaughter(TVirtualGeoTrack *other)
118 {
119  if (!fTracks) fTracks = new TObjArray(1);
120  Int_t index = fTracks->GetEntriesFast();
121  fTracks->AddAtAndExpand(other,index);
122  other->SetParent(this);
123  return index;
124 }
125 
126 ////////////////////////////////////////////////////////////////////////////////
127 /// Draw animation of this track
128 
129 void TGeoTrack::AnimateTrack(Double_t tmin, Double_t tmax, Double_t nframes, Option_t *option)
130 {
131  if (tmin<0 || tmin>=tmax || nframes<1) return;
132  gGeoManager->SetAnimateTracks();
133  gGeoManager->SetVisLevel(1);
134  if (!gPad) {
135  gGeoManager->GetMasterVolume()->Draw();
136  }
137  TList *list = gPad->GetListOfPrimitives();
138  TIter next(list);
139  TObject *obj;
140  while ((obj = next())) {
141  if (!strcmp(obj->ClassName(), "TGeoTrack")) list->Remove(obj);
142  }
143  Double_t dt = (tmax-tmin)/Double_t(nframes);
144  Double_t delt = 2E-9;
145  Double_t t = tmin;
146  Bool_t geomanim = kFALSE;
147  Bool_t issave = kFALSE;
148  TString fname;
149 
150  TString opt(option);
151  if (opt.Contains("/G")) geomanim = kTRUE;
152  if (opt.Contains("/S")) issave = kTRUE;
153 
154  TVirtualGeoPainter *p = gGeoManager->GetGeomPainter();
155  Double_t *box = p->GetViewBox();
156  box[0] = box[1] = box[2] = 0;
157  box[3] = box[4] = box[5] = 100;
158  gGeoManager->SetTminTmax(0,0);
159  Draw(opt.Data());
160  Double_t start[6], end[6];
161  Int_t i, j;
162  Double_t dlat=0, dlong=0, dpsi=0;
163  Double_t dd[6] = {0,0,0,0,0,0};
164  if (geomanim) {
165  p->EstimateCameraMove(tmin+5*dt, tmin+15*dt, start, end);
166  for (i=0; i<3; i++) {
167  start[i+3] = 20 + 1.3*start[i+3];
168  end[i+3] = 20 + 0.9*end[i+3];
169  }
170  for (i=0; i<6; i++) {
171  dd[i] = (end[i]-start[i])/10.;
172  }
173  memcpy(box, start, 6*sizeof(Double_t));
174  p->GetViewAngles(dlong,dlat,dpsi);
175  dlong = (-206-dlong)/Double_t(nframes);
176  dlat = (126-dlat)/Double_t(nframes);
177  dpsi = (75-dpsi)/Double_t(nframes);
178  p->GrabFocus();
179  }
180 
181  for (i=0; i<nframes; i++) {
182  if (t-delt<0) gGeoManager->SetTminTmax(0,t);
183  else gGeoManager->SetTminTmax(t-delt,t);
184  if (geomanim) {
185  for (j=0; j<6; j++) box[j]+=dd[j];
186  p->GrabFocus(1,dlong,dlat,dpsi);
187  } else {
188  gPad->Modified();
189  gPad->Update();
190  }
191  if (issave) {
192  fname = TString::Format("anim%04d.gif", i);
193  gPad->Print(fname);
194  }
195  t += dt;
196  }
197  gGeoManager->SetAnimateTracks(kFALSE);
198 }
199 
200 ////////////////////////////////////////////////////////////////////////////////
201 /// Add a point on the track.
202 
203 void TGeoTrack::AddPoint(Double_t x, Double_t y, Double_t z, Double_t t)
204 {
205  if (!fPoints) {
206  fPointsSize = 16;
207  fPoints = new Double_t[fPointsSize];
208  } else {
209  if (fNpoints>=fPointsSize) {
210  Double_t *temp = new Double_t[2*fPointsSize];
211  memcpy(temp, fPoints, fNpoints*sizeof(Double_t));
212  fPointsSize *= 2;
213  delete [] fPoints;
214  fPoints = temp;
215  }
216  }
217  fPoints[fNpoints++] = x;
218  fPoints[fNpoints++] = y;
219  fPoints[fNpoints++] = z;
220  fPoints[fNpoints++] = t;
221 }
222 
223 ////////////////////////////////////////////////////////////////////////////////
224 /// How-to-browse for a track.
225 
226 void TGeoTrack::Browse(TBrowser *b)
227 {
228  if (!b) return;
229  Int_t nd = GetNdaughters();
230  if (!nd) {
231  b->Add(this);
232  return;
233  }
234  for (Int_t i=0; i<nd; i++)
235  b->Add(GetDaughter(i));
236 
237 }
238 
239 ////////////////////////////////////////////////////////////////////////////////
240 /// Returns distance to track primitive for picking.
241 
242 Int_t TGeoTrack::DistancetoPrimitive(Int_t px, Int_t py)
243 {
244  const Int_t inaxis = 7;
245  const Int_t maxdist = 5;
246  Int_t dist = 9999;
247 
248 
249  Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
250  Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
251  Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
252  Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
253 
254  // return if point is not in the user area
255  if (px < puxmin - inaxis) return dist;
256  if (py > puymin + inaxis) return dist;
257  if (px > puxmax + inaxis) return dist;
258  if (py < puymax - inaxis) return dist;
259 
260  TView *view = gPad->GetView();
261  if (!view) return dist;
262  Int_t imin, imax;
263  if (TObject::TestBit(kGeoPDrawn) && Size(imin,imax)>=2) {
264  Int_t i, dsegment;
265  Double_t x1,y1,x2,y2;
266  Double_t xndc[3];
267  Int_t np = fNpoints>>2;
268  if (imin<0) imin=0;
269  if (imax>np-1) imax=np-1;
270  for (i=imin;i<imax;i++) {
271  view->WCtoNDC(&fPoints[i<<2], xndc);
272  x1 = xndc[0];
273  y1 = xndc[1];
274  view->WCtoNDC(&fPoints[(i+1)<<2], xndc);
275  x2 = xndc[0];
276  y2 = xndc[1];
277  dsegment = DistancetoLine(px,py,x1,y1,x2,y2);
278 // printf("%i: dseg=%i\n", i, dsegment);
279  if (dsegment < dist) {
280  dist = dsegment;
281  if (dist<maxdist) {
282  gPad->SetSelected(this);
283  return 0;
284  }
285  }
286  }
287  }
288  // check now daughters
289  Int_t nd = GetNdaughters();
290  if (!nd) return dist;
291  TGeoTrack *track;
292  for (Int_t id=0; id<nd; id++) {
293  track = (TGeoTrack*)GetDaughter(id);
294  dist = track->DistancetoPrimitive(px,py);
295  if (dist<maxdist) return 0;
296  }
297  return dist;
298 }
299 
300 ////////////////////////////////////////////////////////////////////////////////
301 /// Draw this track over-imposed on a geometry, according to option.
302 /// Options (case sensitive):
303 /// - default : track without daughters
304 /// - /D : track and first level descendents only
305 /// - /* : track and all descendents
306 /// - /Ntype : descendents of this track with particle name matching input type.
307 ///
308 /// Options can appear only once but can be combined : e.g. Draw("/D /Npion-")
309 ///
310 /// Time range for visible track segments can be set via TGeoManager::SetTminTmax()
311 
312 void TGeoTrack::Draw(Option_t *option)
313 {
314  if (!gPad) gGeoManager->GetMasterVolume()->Draw();
315  char *opt1 = Compress(option); // we will have to delete this ?
316  TString opt(opt1);
317  Bool_t is_default = kTRUE;
318  Bool_t is_onelevel = kFALSE;
319  Bool_t is_all = kFALSE;
320  Bool_t is_type = kFALSE;
321  if (opt.Contains("/D")) {
322  is_onelevel = kTRUE;
323  is_default = kFALSE;
324  }
325  if (opt.Contains("/*")) {
326  is_all = kTRUE;
327  is_default = kFALSE;
328  }
329  if (opt.Contains("/N")) {
330  is_type = kTRUE;
331  Int_t ist = opt.Index("/N")+2;
332  Int_t ilast = opt.Index("/",ist);
333  if (ilast<0) ilast=opt.Length();
334  TString type = opt(ist, ilast-ist);
335  gGeoManager->SetParticleName(type.Data());
336  }
337  SetBits(is_default, is_onelevel, is_all, is_type);
338  AppendPad("SAME");
339  if (!gGeoManager->IsAnimatingTracks()) {
340  gPad->Modified();
341  gPad->Update();
342  }
343  delete [] opt1;
344  return;
345 }
346 
347  ///////////////////////////////////////////////////////////////////////////////
348  /// Event treatment.
349 
350 void TGeoTrack::ExecuteEvent(Int_t /*event*/, Int_t /*px*/, Int_t /*py*/)
351 {
352  if (!gPad) return;
353  gPad->SetCursor(kHand);
354 }
355 
356 ////////////////////////////////////////////////////////////////////////////////
357 /// Get some info about the track.
358 
359 char *TGeoTrack::GetObjectInfo(Int_t /*px*/, Int_t /*py*/) const
360 {
361  static TString info;
362  Double_t x=0,y=0,z=0,t=0;
363  GetPoint(0,x,y,z,t);
364  info = TString::Format("%s (%g, %g, %g) tof=%g", GetName(),x,y,z,t);
365  return (char*)info.Data();
366 }
367 
368 ////////////////////////////////////////////////////////////////////////////////
369 /// Get coordinates for point I on the track.
370 
371 Int_t TGeoTrack::GetPoint(Int_t i, Double_t &x, Double_t &y, Double_t &z, Double_t &t) const
372 {
373  Int_t np = fNpoints>>2;
374  if (i<0 || i>=np) {
375  Error("GetPoint", "no point %i, indmax=%d", i, np-1);
376  return -1;
377  }
378  Int_t icrt = 4*i;
379  x = fPoints[icrt];
380  y = fPoints[icrt+1];
381  z = fPoints[icrt+2];
382  t = fPoints[icrt+3];
383  return i;
384 }
385 
386 ////////////////////////////////////////////////////////////////////////////////
387 /// Return the pointer to the array of points starting with index I.
388 
389 const Double_t *TGeoTrack::GetPoint(Int_t i) const
390 {
391  if (!fNpoints) return 0;
392  return (&fPoints[i<<2]);
393 }
394 
395 ////////////////////////////////////////////////////////////////////////////////
396 /// Return the index of point on track having closest TOF smaller than
397 /// the input value. Output POINT is filled with the interpolated value.
398 
399 Int_t TGeoTrack::GetPoint(Double_t tof, Double_t *point, Int_t istart) const
400 {
401  Int_t np = fNpoints>>2;
402  if (istart>(np-2)) return (np-1);
403  Int_t ip = SearchPoint(tof, istart);
404  if (ip<0 || ip>(np-2)) return ip;
405  // point in segment (ip, ip+1) where 0<=ip<fNpoints-1
406  Int_t i;
407  Int_t j = ip<<2;
408  Int_t k = (ip+1)<<2;
409  Double_t dt = tof-fPoints[j+3];
410  Double_t ddt = fPoints[k+3]-fPoints[j+3];
411  for (i=0; i<3; i++) point[i] = fPoints[j+i] +(fPoints[k+i]-fPoints[j+i])*dt/ddt;
412  return ip;
413 }
414 
415 ////////////////////////////////////////////////////////////////////////////////
416 /// Paint this track (and descendents) with current attributes.
417 
418 void TGeoTrack::Paint(Option_t *option)
419 {
420  Bool_t is_default = TObject::TestBit(kGeoPDefault);
421  Bool_t is_onelevel = TObject::TestBit(kGeoPOnelevel);
422  Bool_t is_all = TObject::TestBit(kGeoPAllDaughters);
423  Bool_t is_type = TObject::TestBit(kGeoPType);
424  Bool_t match_type = kTRUE;
425  TObject::SetBit(kGeoPDrawn, kFALSE);
426  if (is_type) {
427  const char *type = gGeoManager->GetParticleName();
428  if (strlen(type) && strcmp(type, GetName())) match_type=kFALSE;
429  }
430  if (match_type) {
431  if (is_default || is_onelevel || is_all) PaintTrack(option);
432  }
433  // paint now daughters
434  Int_t nd = GetNdaughters();
435  if (!nd || is_default) return;
436  TGeoTrack *track;
437  for (Int_t i=0; i<nd; i++) {
438  track = (TGeoTrack*)GetDaughter(i);
439  if (track->IsInTimeRange()) {
440  track->SetBits(is_default,kFALSE,is_all,is_type);
441  track->Paint(option);
442  }
443  }
444 }
445 
446 ////////////////////////////////////////////////////////////////////////////////
447 /// Paint track and daughters.
448 
449 void TGeoTrack::PaintCollect(Double_t time, Double_t *box)
450 {
451  Bool_t is_default = TObject::TestBit(kGeoPDefault);
452  Bool_t is_onelevel = TObject::TestBit(kGeoPOnelevel);
453  Bool_t is_all = TObject::TestBit(kGeoPAllDaughters);
454  Bool_t is_type = TObject::TestBit(kGeoPType);
455  Bool_t match_type = kTRUE;
456  if (is_type) {
457  const char *type = gGeoManager->GetParticleName();
458  if (strlen(type) && strcmp(type, GetName())) match_type=kFALSE;
459  }
460  if (match_type) {
461  if (is_default || is_onelevel || is_all) PaintCollectTrack(time, box);
462  }
463  // loop now daughters
464  Int_t nd = GetNdaughters();
465  if (!nd || is_default) return;
466  TGeoTrack *track;
467  for (Int_t i=0; i<nd; i++) {
468  track = (TGeoTrack*)GetDaughter(i);
469  if (track) track->PaintCollect(time, box);
470  }
471 }
472 
473 ////////////////////////////////////////////////////////////////////////////////
474 /// Paint just this track.
475 
476 void TGeoTrack::PaintCollectTrack(Double_t time, Double_t *box)
477 {
478  TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
479  if (!painter) return;
480  Int_t np = fNpoints>>2;
481  Double_t point[3], local[3];
482  Bool_t convert = (gGeoManager->GetTopVolume() == gGeoManager->GetMasterVolume())?kFALSE:kTRUE;
483  Int_t ip = GetPoint(time, point);
484  if (ip>=0 && ip<np-1) {
485  if (convert) gGeoManager->MasterToTop(point, local);
486  else memcpy(local, point, 3*sizeof(Double_t));
487  painter->AddTrackPoint(local, box);
488  }
489 }
490 
491 ////////////////////////////////////////////////////////////////////////////////
492 /// Paint current point of the track as marker.
493 
494 void TGeoTrack::PaintMarker(Double_t *point, Option_t *)
495 {
496  TPoint p;
497  Double_t xndc[3];
498  TView *view = gPad->GetView();
499  if (!view) return;
500  view->WCtoNDC(point, xndc);
501  if (xndc[0] < gPad->GetX1() || xndc[0] > gPad->GetX2()) return;
502  if (xndc[1] < gPad->GetY1() || xndc[1] > gPad->GetY2()) return;
503  p.fX = gPad->XtoPixel(xndc[0]);
504  p.fY = gPad->YtoPixel(xndc[1]);
505  TAttMarker::Modify();
506  gVirtualX->DrawPolyMarker(1, &p);
507 }
508 
509 ////////////////////////////////////////////////////////////////////////////////
510 /// Paint this track with its current attributes.
511 
512 void TGeoTrack::PaintTrack(Option_t *option)
513 {
514  // Check whether there is some 3D view class for this TPad
515 // TPadView3D *view3D = (TPadView3D*)gPad->GetView3D();
516 // if (view3D) view3D->PaintGeoTrack(this,option); // to be implemented
517 
518  // Check if option is 'x3d'. NOTE: This is a simple checking
519  // but since there is no other
520  // options yet, this works fine.
521  TString opt(option);
522  opt.ToLower();
523  TObject::SetBit(kGeoPDrawn, kFALSE);
524  if (opt.Contains("x")) return;
525  Int_t np = fNpoints>>2;
526  Int_t imin=0;
527  Int_t imax=np-1;
528  Int_t ip;
529  Double_t start[3] = {0.,0.,0.};
530  Double_t end[3] = {0.,0.,0.};
531  Double_t seg[6] = {0.,0.,0.,0.,0.,0.};
532  Bool_t convert = (gGeoManager->GetTopVolume() == gGeoManager->GetMasterVolume())?kFALSE:kTRUE;
533  Double_t tmin=0.,tmax=0.;
534  Bool_t is_time = gGeoManager->GetTminTmax(tmin,tmax);
535  if (is_time) {
536  imin = GetPoint(tmin, start);
537  if (imin>=0 && imin<np-1) {
538  // we have a starting point -> find ending point
539  imax = GetPoint(tmax, end, imin);
540  if (imax<np-1) {
541  // we also have an ending point -> check if on the same segment with imin
542  if (imax==imin) {
543  // paint the virtual segment between the 2 points
544  TAttLine::Modify();
545  if (convert) {
546  gGeoManager->MasterToTop(start, &seg[0]);
547  gGeoManager->MasterToTop(end, &seg[3]);
548  gPad->PaintLine3D(&seg[0], &seg[3]);
549  } else {
550  gPad->PaintLine3D(start, end);
551  }
552  } else {
553  // paint the starting, ending and connecting segments
554  TAttLine::Modify();
555  if (convert) {
556  gGeoManager->MasterToTop(start, &seg[0]);
557  gGeoManager->MasterToTop(&fPoints[(imin+1)<<2], &seg[3]);
558  gPad->PaintLine3D(&seg[0], &seg[3]);
559  gGeoManager->MasterToTop(&fPoints[imax<<2], &seg[0]);
560  gGeoManager->MasterToTop(end, &seg[3]);
561  gPad->PaintLine3D(&seg[0], &seg[3]);
562  for (ip=imin+1; ip<imax; ip++) {
563  gGeoManager->MasterToTop(&fPoints[ip<<2], &seg[0]);
564  gGeoManager->MasterToTop(&fPoints[(ip+1)<<2], &seg[3]);
565  gPad->PaintLine3D(&seg[0], &seg[3]);
566  }
567  } else {
568  gPad->PaintLine3D(start, &fPoints[(imin+1)<<2]);
569  gPad->PaintLine3D(&fPoints[imax<<2], end);
570  for (ip=imin+1; ip<imax; ip++) {
571  gPad->PaintLine3D(&fPoints[ip<<2], &fPoints[(ip+1)<<2]);
572  }
573  }
574  }
575  if (convert) {
576  gGeoManager->MasterToTop(end, &seg[0]);
577  PaintMarker(&seg[0]);
578  } else {
579  PaintMarker(end);
580  }
581  } else {
582  TAttLine::Modify();
583  if (convert) {
584  gGeoManager->MasterToTop(start, &seg[0]);
585  gGeoManager->MasterToTop(&fPoints[(imin+1)<<2], &seg[3]);
586  gPad->PaintLine3D(&seg[0], &seg[3]);
587  for (ip=imin+1; ip<np-2; ip++) {
588  gGeoManager->MasterToTop(&fPoints[ip<<2], &seg[0]);
589  gGeoManager->MasterToTop(&fPoints[(ip+1)<<2], &seg[3]);
590  gPad->PaintLine3D(&seg[0], &seg[3]);
591  }
592  } else {
593  gPad->PaintLine3D(start, &fPoints[(imin+1)<<2]);
594  for (ip=imin+1; ip<np-2; ip++) {
595  gPad->PaintLine3D(&fPoints[ip<<2], &fPoints[(ip+1)<<2]);
596  }
597  }
598  }
599  } else {
600  imax = GetPoint(tmax, end);
601  if (imax<0 || imax>=(np-1)) return;
602  // we have to draw just the end of the track
603  TAttLine::Modify();
604  if (convert) {
605  for (ip=0; ip<imax-1; ip++) {
606  gGeoManager->MasterToTop(&fPoints[ip<<2], &seg[0]);
607  gGeoManager->MasterToTop(&fPoints[(ip+1)<<2], &seg[3]);
608  gPad->PaintLine3D(&seg[0], &seg[3]);
609  }
610  } else {
611  for (ip=0; ip<imax-1; ip++) {
612  gPad->PaintLine3D(&fPoints[ip<<2], &fPoints[(ip+1)<<2]);
613  }
614  }
615  if (convert) {
616  gGeoManager->MasterToTop(&fPoints[imax<<2], &seg[0]);
617  gGeoManager->MasterToTop(end, &seg[3]);
618  gPad->PaintLine3D(&seg[0], &seg[3]);
619  PaintMarker(&seg[3]);
620  } else {
621  gPad->PaintLine3D(&fPoints[imax<<2], end);
622  PaintMarker(end);
623  }
624  }
625  TObject::SetBit(kGeoPDrawn);
626  return;
627  }
628 
629  // paint all segments from track
630  TObject::SetBit(kGeoPDrawn);
631  TAttLine::Modify(); // change attributes if necessary
632  for (ip=imin; ip<imax; ip++) {
633  gPad->PaintLine3D(&fPoints[ip<<2], &fPoints[(ip+1)<<2]);
634  }
635 }
636 
637 ////////////////////////////////////////////////////////////////////////////////
638 /// Print some info about the track.
639 
640 void TGeoTrack::Print(Option_t * /*option*/) const
641 {
642  Int_t np = fNpoints>>2;
643  printf(" TGeoTrack%6i : %s ===============================\n", fId,GetName());
644  printf(" parent =%6i nd =%3i\n", (fParent)?fParent->GetId():-1, GetNdaughters());
645  Double_t x=0,y=0,z=0,t=0;
646  GetPoint(0,x,y,z,t);
647  printf(" production vertex : (%g, %g, %g) at tof=%g\n", x,y,z,t);
648  GetPoint(np-1,x,y,z,t);
649  printf(" Npoints =%6i, last : (%g, %g, %g) at tof=%g\n\n", np,x,y,z,t);
650 }
651 
652 ////////////////////////////////////////////////////////////////////////////////
653 /// Return the number of points within the time interval specified by
654 /// TGeoManager class and the corresponding indices.
655 
656 Int_t TGeoTrack::Size(Int_t &imin, Int_t &imax)
657 {
658  Double_t tmin, tmax;
659  Int_t np = fNpoints>>2;
660  imin = 0;
661  imax = np-1;
662  Int_t size = np;
663  if (!gGeoManager->GetTminTmax(tmin, tmax)) return size;
664  imin = SearchPoint(tmin);
665  imax = SearchPoint(tmax, imin);
666  return (imax-imin+1);
667 }
668 
669 ////////////////////////////////////////////////////////////////////////////////
670 /// Search index of track point having the closest time tag smaller than
671 /// TIME. Optional start index can be provided.
672 
673 Int_t TGeoTrack::SearchPoint(Double_t time, Int_t istart) const
674 {
675  Int_t nabove, nbelow, middle, midloc;
676  Int_t np = fNpoints>>2;
677  nabove = np+1;
678  nbelow = istart;
679  while (nabove-nbelow > 1) {
680  middle = (nabove+nbelow)/2;
681  midloc = ((middle-1)<<2)+3;
682  if (time == fPoints[midloc]) return middle-1;
683  if (time < fPoints[midloc]) nabove = middle;
684  else nbelow = middle;
685  }
686  return (nbelow-1);
687 }
688 
689 ////////////////////////////////////////////////////////////////////////////////
690 /// Set drawing bits for this track
691 
692 void TGeoTrack::SetBits(Bool_t is_default, Bool_t is_onelevel,
693  Bool_t is_all, Bool_t is_type)
694 {
695  TObject::SetBit(kGeoPDefault, is_default);
696  TObject::SetBit(kGeoPOnelevel, is_onelevel);
697  TObject::SetBit(kGeoPAllDaughters, is_all);
698  TObject::SetBit(kGeoPType, is_type);
699 }
700 
701 ////////////////////////////////////////////////////////////////////////////////
702 /// Returns 3D size for the track.
703 
704 void TGeoTrack::Sizeof3D() const
705 {
706 }
707 
708 ////////////////////////////////////////////////////////////////////////////////
709 /// Reset data for this track.
710 
711 void TGeoTrack::ResetTrack()
712 {
713  fNpoints = 0;
714  fPointsSize = 0;
715  if (fTracks) {fTracks->Delete(); delete fTracks;}
716  fTracks = 0;
717  if (fPoints) delete [] fPoints;
718  fPoints = 0;
719 }
720