#include "TEveCalo2DGL.h"
#include "TEveCalo.h"
#include "TEveProjections.h"
#include "TEveProjectionManager.h"
#include "TEveRGBAPalette.h"
#include "TGLRnrCtx.h"
#include "TGLPhysicalShape.h"
#include "TGLSelectRecord.h"
#include "TGLIncludes.h"
#include "TGLUtil.h"
#include "TAxis.h"
ClassImp(TEveCalo2DGL);
TEveCalo2DGL::TEveCalo2DGL() :
TGLObject(),
fM(0)
{
fMultiColor = kTRUE;
}
Bool_t TEveCalo2DGL::SetModel(TObject* obj, const Option_t* )
{
fM = SetModelDynCast<TEveCalo2D>(obj);
return kTRUE;
}
void TEveCalo2DGL::SetBBox()
{
SetAxisAlignedBBox(((TEveCalo2D*)fExternalObj)->AssertBBox());
}
Bool_t TEveCalo2DGL::IsRPhi() const
{
return fM->fManager->GetProjection()->GetType() == TEveProjection::kPT_RPhi;
}
void TEveCalo2DGL::MakeRPhiCell(Float_t phiMin, Float_t phiMax,
Float_t towerH, Float_t offset) const
{
using namespace TMath;
Float_t r1 = fM->fBarrelRadius + offset;
Float_t r2 = r1 + towerH;
Float_t pnts[8];
pnts[0] = r1*Cos(phiMin); pnts[1] = r1*Sin(phiMin);
pnts[2] = r2*Cos(phiMin); pnts[3] = r2*Sin(phiMin);
pnts[4] = r2*Cos(phiMax); pnts[5] = r2*Sin(phiMax);
pnts[6] = r1*Cos(phiMax); pnts[7] = r1*Sin(phiMax);
Float_t x, y, z;
glBegin(GL_QUADS);
for (Int_t i = 0; i < 4; ++i)
{
x = pnts[2*i];
y = pnts[2*i+1];
z = 0.f;
fM->fManager->GetProjection()->ProjectPoint(x, y, z, fM->fDepth);
glVertex3f(x, y, z);
}
glEnd();
}
void TEveCalo2DGL::DrawRPhi(TGLRnrCtx & rnrCtx, TEveCalo2D::vBinCells_t& cellLists) const
{
TEveCaloData* data = fM->GetData();
Int_t nSlices = data->GetNSlices();
Float_t *sliceVal = new Float_t[nSlices];
TEveCaloData::CellData_t cellData;
Float_t towerH;
UInt_t nPhi = data->GetPhiBins()->GetNbins();
TAxis* axis = data->GetPhiBins();
for(UInt_t phiBin = 1; phiBin <= nPhi; ++phiBin)
{
if (cellLists[phiBin] )
{
Float_t off = 0;
for (Int_t s=0; s<nSlices; ++s)
sliceVal[s] = 0;
TEveCaloData::vCellId_t* cids = cellLists[phiBin];
for (TEveCaloData::vCellId_i it = cids->begin(); it != cids->end(); it++)
{
data->GetCellData(*it, cellData);
sliceVal[(*it).fSlice] += cellData.Value(fM->fPlotEt)*(*it).fFraction;
}
if (rnrCtx.SecSelection()) {
glLoadName(phiBin);
glPushName(0);
}
for (Int_t s = 0; s < nSlices; ++s)
{
if (rnrCtx.SecSelection()) glLoadName(s);
fM->SetupColorHeight(sliceVal[s], s, towerH);
MakeRPhiCell(axis->GetBinLowEdge(phiBin), axis->GetBinUpEdge(phiBin), towerH, off);
off += towerH;
}
if (rnrCtx.SecSelection()) glPopName();
}
}
delete [] sliceVal;
}
void TEveCalo2DGL::DrawRPhiHighlighted(std::vector<TEveCaloData::vCellId_t*>& cellLists) const
{
static const TEveException eh("TEveCalo2DGL::DrawRPhiHighlighted ");
TEveCaloData* data = fM->fData;
TEveCaloData::CellData_t cellData;
Int_t nSlices = data->GetNSlices();
UInt_t nPhiBins = data->GetPhiBins()->GetNbins();
Float_t *sliceVal = new Float_t[nSlices];
Float_t *sliceValRef = new Float_t[nSlices];
Float_t towerH, towerHRef;
TAxis* axis = data->GetPhiBins();
for(UInt_t phiBin = 1; phiBin <= nPhiBins; ++phiBin)
{
if (cellLists[phiBin])
{
if (!fM->fCellLists[phiBin])
throw eh + "selected cell not in cell list cache.";
Float_t off = 0;
for (Int_t s=0; s<nSlices; ++s) sliceVal[s] = 0;
TEveCaloData::vCellId_t& cids = *(cellLists[phiBin]);
for (TEveCaloData::vCellId_i i=cids.begin(); i!=cids.end(); i++) {
data->GetCellData((*i), cellData);
sliceVal[i->fSlice] += cellData.Value(fM->fPlotEt)*(*i).fFraction;
}
for (Int_t s=0; s<nSlices; ++s) sliceValRef[s] = 0;
TEveCaloData::vCellId_t& cidsRef = *(fM->fCellLists[phiBin]);
for (TEveCaloData::vCellId_i i=cidsRef.begin(); i!=cidsRef.end(); i++) {
data->GetCellData(*i, cellData);
sliceValRef[i->fSlice] += cellData.Value(fM->fPlotEt)*(*i).fFraction;
}
for (Int_t s = 0; s < nSlices; ++s) {
fM->SetupColorHeight(sliceValRef[s], s, towerHRef);
if (sliceVal[s] > 0)
{
fM->SetupColorHeight(sliceVal[s], s, towerH);
MakeRPhiCell(axis->GetBinLowEdge(phiBin), axis->GetBinUpEdge(phiBin), towerH, off);
}
off += towerHRef;
}
}
}
delete [] sliceVal;
delete [] sliceValRef;
}
void TEveCalo2DGL::MakeRhoZCell(Float_t thetaMin, Float_t thetaMax,
Float_t& offset, Bool_t isBarrel, Bool_t phiPlus, Float_t towerH) const
{
using namespace TMath;
Float_t pnts[8];
Float_t sin1 = Sin(thetaMin);
Float_t cos1 = Cos(thetaMin);
Float_t sin2 = Sin(thetaMax);
Float_t cos2 = Cos(thetaMax);
if (isBarrel)
{
Float_t r1 = fM->fBarrelRadius/Abs(Sin(0.5f*(thetaMin+thetaMax))) + offset;
Float_t r2 = r1 + towerH;
pnts[0] = r1*sin1; pnts[1] = r1*cos1;
pnts[2] = r2*sin1; pnts[3] = r2*cos1;
pnts[4] = r2*sin2; pnts[5] = r2*cos2;
pnts[6] = r1*sin2; pnts[7] = r1*cos2;
}
else
{
Float_t zE = fM->GetForwardEndCapPos();
Float_t transThetaB = TEveCaloData::EtaToTheta(fM->GetTransitionEtaBackward());
if (thetaMax >= transThetaB)
zE = Abs(fM->GetBackwardEndCapPos());
Float_t r1 = zE/Abs(Cos(0.5f*(thetaMin+thetaMax))) + offset;
Float_t r2 = r1 + towerH;
pnts[0] = r1*sin1; pnts[1] = r1*cos1;
pnts[2] = r2*sin1; pnts[3] = r2*cos1;
pnts[4] = r2*sin2; pnts[5] = r2*cos2;
pnts[6] = r1*sin2; pnts[7] = r1*cos2;
}
glBegin(GL_QUADS);
Float_t x, y, z;
for (Int_t i = 0; i < 4; ++i)
{
x = 0.f;
y = phiPlus ? Abs(pnts[2*i]) : -Abs(pnts[2*i]);
z = pnts[2*i+1];
fM->fManager->GetProjection()->ProjectPoint(x, y, z, fM->fDepth);
glVertex3f(x, y, z);
}
glEnd();
}
void TEveCalo2DGL::DrawRhoZ(TGLRnrCtx & rnrCtx, TEveCalo2D::vBinCells_t& cellLists) const
{
TEveCaloData* data = fM->GetData();
Int_t nSlices = data->GetNSlices();
TEveCaloData::CellData_t cellData;
Float_t *sliceValsUp = new Float_t[nSlices];
Float_t *sliceValsLow = new Float_t[nSlices];
Bool_t isBarrel;
Float_t towerH;
Float_t transEtaF = fM->GetTransitionEtaForward();
Float_t transEtaB = fM->GetTransitionEtaBackward();
TAxis* axis = data->GetEtaBins();
UInt_t nEta = axis->GetNbins();
for (UInt_t etaBin = 1; etaBin <= nEta; ++etaBin)
{
if (cellLists[etaBin] )
{
assert(fM->fCellLists[etaBin]);
Float_t etaMin = axis->GetBinLowEdge(etaBin);
Float_t etaMax = axis->GetBinUpEdge(etaBin);
Float_t thetaMin = TEveCaloData::EtaToTheta(etaMax);
Float_t thetaMax = TEveCaloData::EtaToTheta(etaMin);
Float_t offUp = 0;
Float_t offLow = 0;
for (Int_t s = 0; s < nSlices; ++s) {
sliceValsUp [s] = 0;
sliceValsLow[s] = 0;
}
TEveCaloData::vCellId_t* cids = cellLists[etaBin];
for (TEveCaloData::vCellId_i it = cids->begin(); it != cids->end(); ++it)
{
data->GetCellData(*it, cellData);
if (cellData.IsUpperRho())
sliceValsUp [it->fSlice] += cellData.Value(fM->fPlotEt)*(*it).fFraction;
else
sliceValsLow[it->fSlice] += cellData.Value(fM->fPlotEt)*(*it).fFraction;
}
isBarrel = !(etaMax > 0 && etaMax > transEtaF) && !(etaMin < 0 && etaMin < transEtaB);
if (rnrCtx.SecSelection()) glLoadName(etaBin);
if (rnrCtx.SecSelection()) glPushName(0);
for (Int_t s = 0; s < nSlices; ++s)
{
if (rnrCtx.SecSelection()) glLoadName(s);
if (rnrCtx.SecSelection()) glPushName(0);
if (sliceValsUp[s])
{
if (rnrCtx.SecSelection()) glLoadName(1);
fM->SetupColorHeight(sliceValsUp[s], s, towerH);
MakeRhoZCell(thetaMin, thetaMax, offUp, isBarrel, kTRUE , towerH);
offUp += towerH;
}
if (sliceValsLow[s])
{
if (rnrCtx.SecSelection()) glLoadName(0);
fM->SetupColorHeight(sliceValsLow[s], s, towerH);
MakeRhoZCell(thetaMin, thetaMax, offLow, isBarrel, kFALSE , towerH);
offLow += towerH;
}
if (rnrCtx.SecSelection()) glPopName();
}
if (rnrCtx.SecSelection()) glPopName();
}
}
delete [] sliceValsUp;
delete [] sliceValsLow;
}
void TEveCalo2DGL::DrawRhoZHighlighted(std::vector<TEveCaloData::vCellId_t*>& cellLists) const
{
static const TEveException eh("TEveCalo2DGL::DrawRhoZHighlighted ");
TEveCaloData* data = fM->GetData();
TAxis* axis = data->GetEtaBins();
UInt_t nEtaBins = axis->GetNbins();
Int_t nSlices = data->GetNSlices();
Float_t transEtaF = fM->GetTransitionEtaForward();
Float_t transEtaB = fM->GetTransitionEtaBackward();
Float_t *sliceValsUp = new Float_t[nSlices];
Float_t *sliceValsLow = new Float_t[nSlices];
Float_t *sliceValsUpRef = new Float_t[nSlices];
Float_t *sliceValsLowRef = new Float_t[nSlices];
Bool_t isBarrel;
Float_t towerH, towerHRef, offUp, offLow;
TEveCaloData::CellData_t cellData;
for (UInt_t etaBin = 1; etaBin <= nEtaBins; ++etaBin)
{
if (cellLists[etaBin])
{
if (!fM->fCellLists[etaBin])
throw(eh + "selected cell not in cell list cache.");
offUp = 0; offLow =0;
for (Int_t s = 0; s < nSlices; ++s) {
sliceValsUp[s] = 0; sliceValsLow[s] = 0;
}
TEveCaloData::vCellId_t& cids = *(cellLists[etaBin]);
for (TEveCaloData::vCellId_i i=cids.begin(); i!=cids.end(); i++) {
data->GetCellData(*i, cellData);
if (cellData.IsUpperRho())
sliceValsUp [i->fSlice] += cellData.Value(fM->fPlotEt)*(*i).fFraction;
else
sliceValsLow[i->fSlice] += cellData.Value(fM->fPlotEt)*(*i).fFraction;
}
for (Int_t s = 0; s < nSlices; ++s)
{
sliceValsUpRef[s] = 0; sliceValsLowRef[s] = 0;
}
TEveCaloData::vCellId_t& cidsRef = *(fM->fCellLists[etaBin]);
for (TEveCaloData::vCellId_i i=cidsRef.begin(); i!=cidsRef.end(); i++)
{
data->GetCellData(*i, cellData);
if (cellData.IsUpperRho())
sliceValsUpRef [i->fSlice] += cellData.Value(fM->fPlotEt)*(*i).fFraction;
else
sliceValsLowRef[i->fSlice] += cellData.Value(fM->fPlotEt)*(*i).fFraction;
}
Float_t bincenterEta = axis->GetBinCenter(etaBin);
isBarrel = !(bincenterEta > 0 && bincenterEta > transEtaF) && !(bincenterEta < 0 && bincenterEta < transEtaB);
for (Int_t s = 0; s < nSlices; ++s)
{
Float_t thetaMin = TEveCaloData::EtaToTheta(axis->GetBinUpEdge(etaBin));
Float_t thetaMax = TEveCaloData::EtaToTheta(axis->GetBinLowEdge(etaBin));
fM->SetupColorHeight(sliceValsUpRef[s], s, towerHRef);
if (sliceValsUp[s] > 0) {
fM->SetupColorHeight(sliceValsUp[s], s, towerH);
MakeRhoZCell(thetaMin, thetaMax, offUp, isBarrel, kTRUE , towerH);
}
offUp += towerHRef;
fM->SetupColorHeight(sliceValsLowRef[s], s, towerHRef);
if (sliceValsLow[s] > 0) {
fM->SetupColorHeight(sliceValsLow[s], s, towerH);
MakeRhoZCell(thetaMin, thetaMax, offLow, isBarrel, kFALSE , towerH);
}
offLow += towerHRef;
}
}
}
delete [] sliceValsUp;
delete [] sliceValsLow;
delete [] sliceValsUpRef;
delete [] sliceValsLowRef;
}
void TEveCalo2DGL::DirectDraw(TGLRnrCtx & rnrCtx) const
{
TGLCapabilitySwitch light_off(GL_LIGHTING, kFALSE);
TGLCapabilitySwitch cull_off (GL_CULL_FACE, kFALSE);
glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if (fM->fCellIdCacheOK == kFALSE)
fM->BuildCellIdCache();
fM->AssertPalette();
if (rnrCtx.SecSelection()) glPushName(0);
if (IsRPhi())
DrawRPhi(rnrCtx, fM->fCellLists);
else
DrawRhoZ(rnrCtx, fM->fCellLists);
if (rnrCtx.SecSelection()) glPopName();
glPopAttrib();
}
void TEveCalo2DGL::DrawHighlight(TGLRnrCtx& rnrCtx, const TGLPhysicalShape* , Int_t ) const
{
static const TEveException eh("TEveCalo2DGL::DrawHighlight ");
if (fM->fData->GetCellsSelected().empty() && fM->fData->GetCellsHighlighted().empty())
{
return;
}
TGLCapabilitySwitch cull_off (GL_CULL_FACE, kFALSE);
TGLUtil::LockColor();
try
{
if (!fM->fData->GetCellsHighlighted().empty())
{
glColor4ubv(rnrCtx.ColorSet().Selection(3).CArr());
if (IsRPhi())
DrawRPhiHighlighted(fM->fCellListsHighlighted);
else
DrawRhoZHighlighted(fM->fCellListsHighlighted);
}
if (!fM->fData->GetCellsSelected().empty())
{
glColor4ubv(rnrCtx.ColorSet().Selection(1).CArr());
if (IsRPhi())
DrawRPhiHighlighted(fM->fCellListsSelected);
else
DrawRhoZHighlighted(fM->fCellListsSelected);
}
}
catch (TEveException& exc)
{
Warning(eh, "%s", exc.what());
}
TGLUtil::UnlockColor();
}
void TEveCalo2DGL::ProcessSelection(TGLRnrCtx & , TGLSelectRecord & rec)
{
TEveCaloData::vCellId_t sel;
if (rec.GetN() > 2)
{
Int_t bin = rec.GetItem(1);
Int_t slice = rec.GetItem(2);
for (TEveCaloData::vCellId_i it = fM->fCellLists[bin]->begin();
it != fM->fCellLists[bin]->end(); ++it)
{
if ((*it).fSlice == slice)
{
if (IsRPhi())
{
sel.push_back(*it);
}
else
{
assert(rec.GetN() > 3);
Bool_t is_upper = (rec.GetItem(3) == 1);
TEveCaloData::CellData_t cd;
fM->fData->GetCellData(*it, cd);
if ((is_upper && cd.IsUpperRho()) || (!is_upper && !cd.IsUpperRho()))
sel.push_back(*it);
}
}
}
}
fM->fData->ProcessSelection(sel, rec);
}