#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* )
{
if (SetModelCheckClass(obj, TEveCalo2D::Class())) {
fM = dynamic_cast<TEveCalo2D*>(obj);
return kTRUE;
}
return kFALSE;
}
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();
for(UInt_t phiBin = 0; 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);
}
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(cellData.PhiMin(), cellData.PhiMax(), towerH, off);
off += towerH;
}
if (rnrCtx.SecSelection()) glPopName();
}
}
delete [] sliceVal;
}
void TEveCalo2DGL::DrawRPhiHighlighted(TGLRnrCtx & ) 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;
for(UInt_t phiBin = 1; phiBin <= nPhiBins; ++phiBin)
{
if (fM->fCellListsSelected[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 = *(fM->fCellListsSelected[phiBin]);
for (TEveCaloData::vCellId_i i=cids.begin(); i!=cids.end(); i++) {
data->GetCellData((*i), cellData);
sliceVal[i->fSlice] += cellData.Value(fM->fPlotEt);
}
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);
}
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(cellData.PhiMin(), cellData.PhiMax(), 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 r1 = fM->GetEndCapPos()/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;
UInt_t nEta = data->GetEtaBins()->GetNbins();
for (UInt_t etaBin = 1; etaBin <= nEta; ++etaBin)
{
if (cellLists[etaBin] )
{
assert(fM->fCellLists[etaBin]);
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.Phi() > 0)
sliceValsUp [it->fSlice] += cellData.Value(fM->fPlotEt);
else
sliceValsLow[it->fSlice] += cellData.Value(fM->fPlotEt);
}
isBarrel = TMath::Abs(cellData.EtaMax()) < fM->GetTransitionEta();
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(cellData.ThetaMin(), cellData.ThetaMax(), offUp, isBarrel, kTRUE , towerH);
offUp += towerH;
}
if (sliceValsLow[s])
{
if (rnrCtx.SecSelection()) glLoadName(0);
fM->SetupColorHeight(sliceValsLow[s], s, towerH);
MakeRhoZCell(cellData.ThetaMin(), cellData.ThetaMax(), offLow, isBarrel, kFALSE , towerH);
offLow += towerH;
}
if (rnrCtx.SecSelection()) glPopName();
}
if (rnrCtx.SecSelection()) glPopName();
}
}
delete [] sliceValsUp;
delete [] sliceValsLow;
}
void TEveCalo2DGL::DrawRhoZHighlighted(TGLRnrCtx & ) const
{
static const TEveException eh("TEveCalo2DGL::DrawRhoZHighlighted ");
TEveCaloData* data = fM->GetData();
Int_t nSlices = data->GetNSlices();
UInt_t nEtaBins = data->GetEtaBins()->GetNbins();
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 (fM->fCellListsSelected[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 = *(fM->fCellListsSelected[etaBin]);
for (TEveCaloData::vCellId_i i=cids.begin(); i!=cids.end(); i++) {
data->GetCellData(*i, cellData);
if (cellData.Phi() > 0)
sliceValsUp [i->fSlice] += cellData.Value(fM->fPlotEt);
else
sliceValsLow[i->fSlice] += cellData.Value(fM->fPlotEt);
}
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.Phi() > 0)
sliceValsUpRef [i->fSlice] += cellData.Value(fM->fPlotEt);
else
sliceValsLowRef[i->fSlice] += cellData.Value(fM->fPlotEt);
}
isBarrel = TMath::Abs(cellData.EtaMax()) < fM->GetTransitionEta();
for (Int_t s = 0; s < nSlices; ++s)
{
fM->SetupColorHeight(sliceValsUpRef[s], s, towerHRef);
if (sliceValsUp[s] > 0) {
fM->SetupColorHeight(sliceValsUp[s], s, towerH);
MakeRhoZCell(cellData.ThetaMin(), cellData.ThetaMax(), offUp, isBarrel, kTRUE , towerH);
}
offUp += towerHRef;
fM->SetupColorHeight(sliceValsLowRef[s], s, towerHRef);
if (sliceValsLow[s] > 0) {
fM->SetupColorHeight(sliceValsLow[s], s, towerH);
MakeRhoZCell(cellData.ThetaMin(), cellData.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);
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();
}
void TEveCalo2DGL::DrawHighlight(TGLRnrCtx& rnrCtx, const TGLPhysicalShape* pshp) const
{
static const TEveException eh("TEveCalo2DGL::DrawHighlight ");
if ((pshp->GetSelected() == 2) && fM->fData->GetCellsSelected().size())
{
glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT | GL_LINE_BIT );
glDisable(GL_CULL_FACE);
glDisable(GL_LIGHTING);
glEnable(GL_LINE_SMOOTH);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
TGLUtil::LineWidth(2);
glColor4ubv(rnrCtx.ColorSet().Selection(pshp->GetSelected()).CArr());
TGLUtil::LockColor();
try {
if (IsRPhi())
DrawRPhiHighlighted(rnrCtx);
else
DrawRhoZHighlighted(rnrCtx);
}
catch (TEveException& exc)
{
Warning(eh, exc);
}
TGLUtil::UnlockColor();
glPopAttrib();
}
}
void TEveCalo2DGL::ProcessSelection(TGLRnrCtx & , TGLSelectRecord & rec)
{
Int_t prev = fM->fData->GetCellsSelected().size();
if (!rec.GetMultiple()) fM->fData->GetCellsSelected().clear();
Int_t binID = -1;
if (rec.GetN() > 2)
{
binID = rec.GetItem(1);
Int_t slice = rec.GetItem(2);
TEveCaloData::CellData_t cellData;
for (TEveCaloData::vCellId_i it = fM->fCellLists[binID]->begin();
it!=fM->fCellLists[binID]->end(); it++)
{
if ((*it).fSlice == slice)
{
fM->fData->GetCellData(*it, cellData);
if (!IsRPhi())
{
if ((rec.GetItem(3) && cellData.Phi() > 0) || (rec.GetItem(3) == kFALSE && cellData.Phi() < 0)) {
fM->fData->GetCellsSelected().push_back(*it);
}
}
else {
fM->fData->GetCellsSelected().push_back(*it);
}
}
}
}
if (prev == 0 && binID >= 0)
rec.SetSecSelResult(TGLSelectRecord::kEnteringSelection);
else if (prev && binID < 0)
rec.SetSecSelResult(TGLSelectRecord::kLeavingSelection);
else if (prev && binID >= 0)
rec.SetSecSelResult(TGLSelectRecord::kModifyingInternalSelection);
fM->fData->CellSelectionChanged();
}