Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TEveCalo2DGL.cxx
Go to the documentation of this file.
1 // @(#)root/eve:$Id$
2 // Author: Matevz Tadel 2007
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2007, 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 "TEveCalo2DGL.h"
13 #include "TEveCalo.h"
14 #include "TEveProjections.h"
15 #include "TEveProjectionManager.h"
16 #include "TEveRGBAPalette.h"
17 
18 #include "TGLRnrCtx.h"
19 #include "TGLPhysicalShape.h"
20 #include "TGLSelectRecord.h"
21 #include "TGLIncludes.h"
22 #include "TGLUtil.h"
23 #include "TAxis.h"
24 
25 /** \class TEveCalo2DGL
26 \ingroup TEve
27 OpenGL renderer class for TEveCalo2D.
28 */
29 
30 ClassImp(TEveCalo2DGL);
31 
32 ////////////////////////////////////////////////////////////////////////////////
33 /// Constructor.
34 
35 TEveCalo2DGL::TEveCalo2DGL() :
36  TGLObject(),
37  fM(0)
38 {
39  // fDLCache = kFALSE; // Disable display list.
40  fMultiColor = kTRUE;
41 }
42 
43 ////////////////////////////////////////////////////////////////////////////////
44 /// Set model object.
45 
46 Bool_t TEveCalo2DGL::SetModel(TObject* obj, const Option_t* /*opt*/)
47 {
48  fM = SetModelDynCast<TEveCalo2D>(obj);
49  return kTRUE;
50 }
51 
52 ////////////////////////////////////////////////////////////////////////////////
53 /// Set bounding box.
54 
55 void TEveCalo2DGL::SetBBox()
56 {
57  SetAxisAlignedBBox(((TEveCalo2D*)fExternalObj)->AssertBBox());
58 }
59 
60 ////////////////////////////////////////////////////////////////////////////////
61 /// Is current projection type RPhi
62 
63 Bool_t TEveCalo2DGL::IsRPhi() const
64 {
65  return fM->fManager->GetProjection()->GetType() == TEveProjection::kPT_RPhi;
66 }
67 
68 ////////////////////////////////////////////////////////////////////////////////
69 /// Calculate vertices for the calorimeter cell in RPhi projection.
70 /// Returns outside radius of the tower.
71 
72 void TEveCalo2DGL::MakeRPhiCell(Float_t phiMin, Float_t phiMax,
73  Float_t towerH, Float_t offset) const
74 {
75  using namespace TMath;
76 
77  Float_t r1 = fM->fBarrelRadius + offset;
78  Float_t r2 = r1 + towerH;
79 
80  Float_t pnts[8];
81 
82  pnts[0] = r1*Cos(phiMin); pnts[1] = r1*Sin(phiMin);
83  pnts[2] = r2*Cos(phiMin); pnts[3] = r2*Sin(phiMin);
84  pnts[4] = r2*Cos(phiMax); pnts[5] = r2*Sin(phiMax);
85  pnts[6] = r1*Cos(phiMax); pnts[7] = r1*Sin(phiMax);
86 
87  Float_t x, y, z;
88  glBegin(GL_QUADS);
89  for (Int_t i = 0; i < 4; ++i)
90  {
91  x = pnts[2*i];
92  y = pnts[2*i+1];
93  z = 0.f;
94  fM->fManager->GetProjection()->ProjectPoint(x, y, z, fM->fDepth);
95  glVertex3f(x, y, z);
96  }
97  glEnd();
98 }
99 
100 ////////////////////////////////////////////////////////////////////////////////
101 /// Draw calorimeter cells in RPhi projection.
102 
103 void TEveCalo2DGL::DrawRPhi(TGLRnrCtx & rnrCtx, TEveCalo2D::vBinCells_t& cellLists) const
104 {
105  TEveCaloData* data = fM->GetData();
106  Int_t nSlices = data->GetNSlices();
107  Float_t *sliceVal = new Float_t[nSlices];
108  TEveCaloData::CellData_t cellData;
109  Float_t towerH;
110 
111  UInt_t nPhi = data->GetPhiBins()->GetNbins();
112  TAxis* axis = data->GetPhiBins();
113  for(UInt_t phiBin = 1; phiBin <= nPhi; ++phiBin)
114  {
115  if (cellLists[phiBin] )
116  {
117  // reset values
118  Float_t off = 0;
119  for (Int_t s=0; s<nSlices; ++s)
120  sliceVal[s] = 0;
121 
122  // sum eta cells
123  TEveCaloData::vCellId_t* cids = cellLists[phiBin];
124  for (TEveCaloData::vCellId_i it = cids->begin(); it != cids->end(); it++)
125  {
126  data->GetCellData(*it, cellData);
127  sliceVal[(*it).fSlice] += cellData.Value(fM->fPlotEt)*(*it).fFraction;
128  }
129 
130  if (rnrCtx.SecSelection()) {
131  glLoadName(phiBin); // set name-stack phi bin
132  glPushName(0);
133  }
134  for (Int_t s = 0; s < nSlices; ++s)
135  {
136  if (rnrCtx.SecSelection()) glLoadName(s); // set name-stack slice
137  fM->SetupColorHeight(sliceVal[s], s, towerH);
138  MakeRPhiCell(axis->GetBinLowEdge(phiBin), axis->GetBinUpEdge(phiBin), towerH, off);
139  off += towerH;
140  }
141  if (rnrCtx.SecSelection()) glPopName(); // slice
142  }
143  }
144 
145  delete [] sliceVal;
146 }
147 
148 ////////////////////////////////////////////////////////////////////////////////
149 /// Draw selected calorimeter cells in RPhi projection.
150 
151 void TEveCalo2DGL::DrawRPhiHighlighted(std::vector<TEveCaloData::vCellId_t*>& cellLists) const
152 {
153  static const TEveException eh("TEveCalo2DGL::DrawRPhiHighlighted ");
154 
155  TEveCaloData* data = fM->fData;
156  TEveCaloData::CellData_t cellData;
157  Int_t nSlices = data->GetNSlices();
158  UInt_t nPhiBins = data->GetPhiBins()->GetNbins();
159  Float_t *sliceVal = new Float_t[nSlices];
160  Float_t *sliceValRef = new Float_t[nSlices];
161  Float_t towerH, towerHRef;
162 
163  TAxis* axis = data->GetPhiBins();
164  for(UInt_t phiBin = 1; phiBin <= nPhiBins; ++phiBin)
165  {
166  if (cellLists[phiBin])
167  {
168  if (!fM->fCellLists[phiBin]) {
169  delete[] sliceVal;
170  delete[] sliceValRef;
171  throw eh + "selected cell not in cell list cache.";
172  }
173 
174  Float_t off = 0;
175  // selected eta sum
176  for (Int_t s=0; s<nSlices; ++s) sliceVal[s] = 0;
177  TEveCaloData::vCellId_t& cids = *(cellLists[phiBin]);
178  for (TEveCaloData::vCellId_i i=cids.begin(); i!=cids.end(); i++) {
179  data->GetCellData((*i), cellData);
180  sliceVal[i->fSlice] += cellData.Value(fM->fPlotEt)*(*i).fFraction;
181  }
182  // referenced eta sum
183  for (Int_t s=0; s<nSlices; ++s) sliceValRef[s] = 0;
184  TEveCaloData::vCellId_t& cidsRef = *(fM->fCellLists[phiBin]);
185  for (TEveCaloData::vCellId_i i=cidsRef.begin(); i!=cidsRef.end(); i++) {
186  data->GetCellData(*i, cellData);
187  sliceValRef[i->fSlice] += cellData.Value(fM->fPlotEt)*(*i).fFraction;
188  }
189  // draw
190  for (Int_t s = 0; s < nSlices; ++s) {
191  fM->SetupColorHeight(sliceValRef[s], s, towerHRef);
192  if (sliceVal[s] > 0)
193  {
194  fM->SetupColorHeight(sliceVal[s], s, towerH);
195  MakeRPhiCell(axis->GetBinLowEdge(phiBin), axis->GetBinUpEdge(phiBin), towerH, off);
196  }
197  off += towerHRef;
198  }
199  }
200  }
201 
202  delete [] sliceVal;
203  delete [] sliceValRef;
204 }
205 
206 ////////////////////////////////////////////////////////////////////////////////
207 /// Draw cell in RhoZ projection.
208 
209 void TEveCalo2DGL::MakeRhoZCell(Float_t thetaMin, Float_t thetaMax,
210  Float_t& offset, Bool_t isBarrel, Bool_t phiPlus, Float_t towerH) const
211 {
212  using namespace TMath;
213 
214  Float_t pnts[8];
215 
216  Float_t sin1 = Sin(thetaMin);
217  Float_t cos1 = Cos(thetaMin);
218  Float_t sin2 = Sin(thetaMax);
219  Float_t cos2 = Cos(thetaMax);
220 
221  if (isBarrel)
222  {
223  Float_t r1 = fM->fBarrelRadius/Abs(Sin(0.5f*(thetaMin+thetaMax))) + offset;
224  Float_t r2 = r1 + towerH;
225 
226  pnts[0] = r1*sin1; pnts[1] = r1*cos1;
227  pnts[2] = r2*sin1; pnts[3] = r2*cos1;
228  pnts[4] = r2*sin2; pnts[5] = r2*cos2;
229  pnts[6] = r1*sin2; pnts[7] = r1*cos2;
230  }
231  else
232  {
233  // endcap
234  Float_t zE = fM->GetForwardEndCapPos();
235  // uses a different theta definition than GetTransitionThetaBackward(), so we need a conversion
236  Float_t transThetaB = TEveCaloData::EtaToTheta(fM->GetTransitionEtaBackward());
237  if (thetaMax >= transThetaB)
238  zE = Abs(fM->GetBackwardEndCapPos());
239  Float_t r1 = zE/Abs(Cos(0.5f*(thetaMin+thetaMax))) + offset;
240  Float_t r2 = r1 + towerH;
241 
242  pnts[0] = r1*sin1; pnts[1] = r1*cos1;
243  pnts[2] = r2*sin1; pnts[3] = r2*cos1;
244  pnts[4] = r2*sin2; pnts[5] = r2*cos2;
245  pnts[6] = r1*sin2; pnts[7] = r1*cos2;
246  }
247 
248  glBegin(GL_QUADS);
249  Float_t x, y, z;
250  for (Int_t i = 0; i < 4; ++i)
251  {
252  x = 0.f;
253  y = phiPlus ? Abs(pnts[2*i]) : -Abs(pnts[2*i]);
254  z = pnts[2*i+1];
255  fM->fManager->GetProjection()->ProjectPoint(x, y, z, fM->fDepth);
256  glVertex3f(x, y, z);
257  }
258  glEnd();
259 }
260 
261 ////////////////////////////////////////////////////////////////////////////////
262 /// Draw calorimeter in RhoZ projection.
263 
264 void TEveCalo2DGL::DrawRhoZ(TGLRnrCtx & rnrCtx, TEveCalo2D::vBinCells_t& cellLists) const
265 {
266  TEveCaloData* data = fM->GetData();
267  Int_t nSlices = data->GetNSlices();
268 
269  TEveCaloData::CellData_t cellData;
270  Float_t *sliceValsUp = new Float_t[nSlices];
271  Float_t *sliceValsLow = new Float_t[nSlices];
272  Bool_t isBarrel;
273  Float_t towerH;
274  Float_t transEtaF = fM->GetTransitionEtaForward();
275  Float_t transEtaB = fM->GetTransitionEtaBackward();
276 
277  TAxis* axis = data->GetEtaBins();
278  UInt_t nEta = axis->GetNbins();
279  for (UInt_t etaBin = 1; etaBin <= nEta; ++etaBin)
280  {
281  if (cellLists[etaBin] )
282  {
283  assert(fM->fCellLists[etaBin]);
284  Float_t etaMin = axis->GetBinLowEdge(etaBin);
285  Float_t etaMax = axis->GetBinUpEdge(etaBin);
286  Float_t thetaMin = TEveCaloData::EtaToTheta(etaMax);
287  Float_t thetaMax = TEveCaloData::EtaToTheta(etaMin);
288 
289  // clear
290  Float_t offUp = 0;
291  Float_t offLow = 0;
292  for (Int_t s = 0; s < nSlices; ++s) {
293  sliceValsUp [s] = 0;
294  sliceValsLow[s] = 0;
295  }
296  // values
297  TEveCaloData::vCellId_t* cids = cellLists[etaBin];
298  for (TEveCaloData::vCellId_i it = cids->begin(); it != cids->end(); ++it)
299  {
300  data->GetCellData(*it, cellData);
301  if (cellData.IsUpperRho())
302  sliceValsUp [it->fSlice] += cellData.Value(fM->fPlotEt)*(*it).fFraction;
303  else
304  sliceValsLow[it->fSlice] += cellData.Value(fM->fPlotEt)*(*it).fFraction;
305  }
306 
307  isBarrel = !(etaMax > 0 && etaMax > transEtaF) && !(etaMin < 0 && etaMin < transEtaB);
308 
309  // draw
310  if (rnrCtx.SecSelection()) glLoadName(etaBin); // name-stack eta bin
311  if (rnrCtx.SecSelection()) glPushName(0);
312 
313  for (Int_t s = 0; s < nSlices; ++s)
314  {
315  if (rnrCtx.SecSelection()) glLoadName(s); // name-stack slice
316  if (rnrCtx.SecSelection()) glPushName(0);
317  // phi +
318  if (sliceValsUp[s])
319  {
320  if (rnrCtx.SecSelection()) glLoadName(1); // name-stack phi sign
321  fM->SetupColorHeight(sliceValsUp[s], s, towerH);
322  MakeRhoZCell(thetaMin, thetaMax, offUp, isBarrel, kTRUE , towerH);
323  offUp += towerH;
324  }
325  // phi -
326  if (sliceValsLow[s])
327  {
328  if (rnrCtx.SecSelection()) glLoadName(0); // name-stack phi sign
329  fM->SetupColorHeight(sliceValsLow[s], s, towerH);
330  MakeRhoZCell(thetaMin, thetaMax, offLow, isBarrel, kFALSE , towerH);
331  offLow += towerH;
332  }
333  if (rnrCtx.SecSelection()) glPopName(); // phi sign is pos
334  }
335  //
336  if (rnrCtx.SecSelection()) glPopName(); // slice
337  }
338  }
339 
340  delete [] sliceValsUp;
341  delete [] sliceValsLow;
342 }
343 
344 ////////////////////////////////////////////////////////////////////////////////
345 /// Draw selected calorimeter cells in RhoZ projection.
346 
347 void TEveCalo2DGL::DrawRhoZHighlighted(std::vector<TEveCaloData::vCellId_t*>& cellLists) const
348 {
349  static const TEveException eh("TEveCalo2DGL::DrawRhoZHighlighted ");
350 
351  TEveCaloData* data = fM->GetData();
352  TAxis* axis = data->GetEtaBins();
353  UInt_t nEtaBins = axis->GetNbins();
354  Int_t nSlices = data->GetNSlices();
355  Float_t transEtaF = fM->GetTransitionEtaForward();
356  Float_t transEtaB = fM->GetTransitionEtaBackward();
357 
358  Float_t *sliceValsUp = new Float_t[nSlices];
359  Float_t *sliceValsLow = new Float_t[nSlices];
360  Float_t *sliceValsUpRef = new Float_t[nSlices];
361  Float_t *sliceValsLowRef = new Float_t[nSlices];
362 
363  Bool_t isBarrel;
364  Float_t towerH, towerHRef, offUp, offLow;
365  TEveCaloData::CellData_t cellData;
366 
367  for (UInt_t etaBin = 1; etaBin <= nEtaBins; ++etaBin)
368  {
369  if (cellLists[etaBin])
370  {
371  if (!fM->fCellLists[etaBin]) {
372  delete[] sliceValsUp;
373  delete[] sliceValsLow;
374  delete[] sliceValsUpRef;
375  delete[] sliceValsLowRef;
376  throw(eh + "selected cell not in cell list cache.");
377  }
378 
379  offUp = 0; offLow =0;
380  // selected phi sum
381  for (Int_t s = 0; s < nSlices; ++s) {
382  sliceValsUp[s] = 0; sliceValsLow[s] = 0;
383  }
384  TEveCaloData::vCellId_t& cids = *(cellLists[etaBin]);
385  for (TEveCaloData::vCellId_i i=cids.begin(); i!=cids.end(); i++) {
386  data->GetCellData(*i, cellData);
387  if (cellData.IsUpperRho())
388  sliceValsUp [i->fSlice] += cellData.Value(fM->fPlotEt)*(*i).fFraction;
389  else
390  sliceValsLow[i->fSlice] += cellData.Value(fM->fPlotEt)*(*i).fFraction;
391  }
392 
393  // reference phi sum
394  for (Int_t s = 0; s < nSlices; ++s)
395  {
396  sliceValsUpRef[s] = 0; sliceValsLowRef[s] = 0;
397  }
398  TEveCaloData::vCellId_t& cidsRef = *(fM->fCellLists[etaBin]);
399  for (TEveCaloData::vCellId_i i=cidsRef.begin(); i!=cidsRef.end(); i++)
400  {
401  data->GetCellData(*i, cellData);
402  if (cellData.IsUpperRho())
403  sliceValsUpRef [i->fSlice] += cellData.Value(fM->fPlotEt)*(*i).fFraction;
404  else
405  sliceValsLowRef[i->fSlice] += cellData.Value(fM->fPlotEt)*(*i).fFraction;
406  }
407 
408  Float_t bincenterEta = axis->GetBinCenter(etaBin);
409  isBarrel = !(bincenterEta > 0 && bincenterEta > transEtaF) && !(bincenterEta < 0 && bincenterEta < transEtaB);
410 
411  for (Int_t s = 0; s < nSlices; ++s)
412  {
413  Float_t thetaMin = TEveCaloData::EtaToTheta(axis->GetBinUpEdge(etaBin));
414  Float_t thetaMax = TEveCaloData::EtaToTheta(axis->GetBinLowEdge(etaBin));
415  // phi +
416  fM->SetupColorHeight(sliceValsUpRef[s], s, towerHRef);
417  if (sliceValsUp[s] > 0) {
418  fM->SetupColorHeight(sliceValsUp[s], s, towerH);
419  MakeRhoZCell(thetaMin, thetaMax, offUp, isBarrel, kTRUE , towerH);
420  }
421  offUp += towerHRef;
422 
423  // phi -
424  fM->SetupColorHeight(sliceValsLowRef[s], s, towerHRef);
425  if (sliceValsLow[s] > 0) {
426  fM->SetupColorHeight(sliceValsLow[s], s, towerH);
427  MakeRhoZCell(thetaMin, thetaMax, offLow, isBarrel, kFALSE , towerH);
428  }
429  offLow += towerHRef;
430  } // slices
431  } // if eta bin
432  } //eta bin
433 
434  delete [] sliceValsUp;
435  delete [] sliceValsLow;
436  delete [] sliceValsUpRef;
437  delete [] sliceValsLowRef;
438 }
439 
440 ////////////////////////////////////////////////////////////////////////////////
441 /// Render with OpenGL.
442 
443 void TEveCalo2DGL::DirectDraw(TGLRnrCtx & rnrCtx) const
444 {
445  TGLCapabilitySwitch light_off(GL_LIGHTING, kFALSE);
446  TGLCapabilitySwitch cull_off (GL_CULL_FACE, kFALSE);
447 
448  glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT);
449  glEnable(GL_BLEND);
450  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
451 
452  if (fM->fCellIdCacheOK == kFALSE)
453  fM->BuildCellIdCache();
454 
455  fM->AssertPalette();
456 
457  if (rnrCtx.SecSelection()) glPushName(0);
458  if (IsRPhi())
459  DrawRPhi(rnrCtx, fM->fCellLists);
460  else
461  DrawRhoZ(rnrCtx, fM->fCellLists);
462  if (rnrCtx.SecSelection()) glPopName();
463  glPopAttrib();
464 }
465 
466 ////////////////////////////////////////////////////////////////////////////////
467 /// Draw towers in highlight mode.
468 
469 void TEveCalo2DGL::DrawHighlight(TGLRnrCtx& rnrCtx, const TGLPhysicalShape* /*pshp*/, Int_t /*lvl*/) const
470 {
471  static const TEveException eh("TEveCalo2DGL::DrawHighlight ");
472 
473  if (fM->fData->GetCellsSelected().empty() && fM->fData->GetCellsHighlighted().empty())
474  {
475  return;
476  }
477 
478  TGLCapabilitySwitch cull_off (GL_CULL_FACE, kFALSE);
479 
480  TGLUtil::LockColor();
481  try
482  {
483  if (!fM->fData->GetCellsHighlighted().empty())
484  {
485  glColor4ubv(rnrCtx.ColorSet().Selection(3).CArr());
486 
487  if (IsRPhi())
488  DrawRPhiHighlighted(fM->fCellListsHighlighted);
489  else
490  DrawRhoZHighlighted(fM->fCellListsHighlighted);
491  }
492  if (!fM->fData->GetCellsSelected().empty())
493  {
494  glColor4ubv(rnrCtx.ColorSet().Selection(1).CArr());
495  if (IsRPhi())
496  DrawRPhiHighlighted(fM->fCellListsSelected);
497  else
498  DrawRhoZHighlighted(fM->fCellListsSelected);
499 
500  }
501  }
502  catch (TEveException& exc)
503  {
504  Warning(eh, "%s", exc.what());
505  }
506  TGLUtil::UnlockColor();
507 }
508 
509 ////////////////////////////////////////////////////////////////////////////////
510 /// Processes tower selection in eta bin or phi bin.
511 /// Virtual function from TGLogicalShape. Called from TGLViewer.
512 
513 void TEveCalo2DGL::ProcessSelection(TGLRnrCtx & /*rnrCtx*/, TGLSelectRecord & rec)
514 {
515  TEveCaloData::vCellId_t sel;
516  if (rec.GetN() > 2)
517  {
518  Int_t bin = rec.GetItem(1);
519  Int_t slice = rec.GetItem(2);
520  for (TEveCaloData::vCellId_i it = fM->fCellLists[bin]->begin();
521  it != fM->fCellLists[bin]->end(); ++it)
522  {
523  if ((*it).fSlice == slice)
524  {
525  if (IsRPhi())
526  {
527  sel.push_back(*it);
528  }
529  else
530  {
531  assert(rec.GetN() > 3);
532  Bool_t is_upper = (rec.GetItem(3) == 1);
533  TEveCaloData::CellData_t cd;
534  fM->fData->GetCellData(*it, cd);
535  if ((is_upper && cd.IsUpperRho()) || (!is_upper && !cd.IsUpperRho()))
536  sel.push_back(*it);
537  }
538  }
539  }
540  }
541  fM->fData->ProcessSelection(sel, rec);
542 }