// @(#)root/histpainter:$Name: $:$Id: TGraphPainter.cxx,v 1.00
// Author: Olivier Couet
/*************************************************************************
* Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
#include "TROOT.h"
#include "TGraphPainter.h"
#include "TMath.h"
#include "TPolyLine.h"
#include "TPolyMarker.h"
#include "TVirtualPad.h"
#include "TView.h"
#include "THLimitsFinder.h"
#include "TStyle.h"
#include "Hoption.h"
R__EXTERN TH1 *gCurrentHist;
R__EXTERN Hoption_t Hoption;
ClassImp(TGraphPainter)
//______________________________________________________________________________
//
// TGraphPainter paints a TGraphDelaunay
//
//______________________________________________________________________________
TGraphPainter::TGraphPainter()
{
// TGraphPainter default constructor
fDelaunay = 0;
}
//______________________________________________________________________________
TGraphPainter::TGraphPainter(TGraphDelaunay *gd)
{
// TGraphPainter constructor
fDelaunay = gd;
fGraph2D = fDelaunay->GetGraph2D();
fNpoints = fGraph2D->GetN();
fX = fGraph2D->GetX();
fY = fGraph2D->GetY();
fZ = fGraph2D->GetZ();
fNdt = 0;
fXN = 0;
fYN = 0;
fXNmin = 0;
fXNmax = 0;
fYNmin = 0;
fYNmax = 0;
fPTried = 0;
fNTried = 0;
fMTried = 0;
}
//______________________________________________________________________________
TGraphPainter::~TGraphPainter()
{
// TGraphPainter destructor.
}
//______________________________________________________________________________
void TGraphPainter::FindTriangles()
{
// Find triangles in fDelaunay and initialise the TGraphPainter values
// needed to paint triangles or find contours.
fDelaunay->FindAllTriangles();
fNdt = fDelaunay->GetNdt();
fXN = fDelaunay->GetXN();
fYN = fDelaunay->GetYN();
fXNmin = fDelaunay->GetXNmin();
fXNmax = fDelaunay->GetXNmax();
fYNmin = fDelaunay->GetYNmin();
fYNmax = fDelaunay->GetYNmax();
fPTried = fDelaunay->GetPTried();
fNTried = fDelaunay->GetNTried();
fMTried = fDelaunay->GetMTried();
}
//______________________________________________________________________________
TList *TGraphPainter::GetContourList(Double_t contour)
{
// Returns the X and Y graphs building a contour. A contour level may
// consist in several parts not connected to each other. This function
// finds them and returns them in a graphs' list.
// Exit if the contour is outisde the Z range.
Double_t zmin = gCurrentHist->GetMinimum();
Double_t zmax = gCurrentHist->GetMaximum();
if (Hoption.Logz) {
if (zmin > 0) {
zmin = TMath::Log10(zmin);
zmax = TMath::Log10(zmax);
} else {
return 0;
}
}
if(contour<zmin || contour>zmax) {
Error("GetContourList", "Contour level (%g) outside the Z scope [%g,%g]",
contour,zmin,zmax);
return 0;
}
if (!fNdt) FindTriangles();
TGraph *graph = 0; // current graph
Int_t npg = 0; // number of points in the current graph
TList *list = new TList(); // list holding all the graphs
// Find all the segments making the contour
Double_t r21, r20, r10;
Int_t p0, p1, p2;
Double_t x0, y0, z0;
Double_t x1, y1, z1;
Double_t x2, y2, z2;
Int_t t[3],it,i0,i1,i2;
// Allocate space to store the segments. They cannot be more than the
// number of triangles.
Double_t xs0c, ys0c, xs1c, ys1c;
Double_t *xs0 = new Double_t[fNdt];
Double_t *ys0 = new Double_t[fNdt];
Double_t *xs1 = new Double_t[fNdt];
Double_t *ys1 = new Double_t[fNdt];
Int_t nbSeg = 0;
// Loop over all the triangles in order to find all the line segments
// making the contour.
for(it=0; it<fNdt; it++) {
t[0] = fPTried[it];
t[1] = fNTried[it];
t[2] = fMTried[it];
p0 = t[0]-1;
p1 = t[1]-1;
p2 = t[2]-1;
x0 = fX[p0]; x2 = fX[p0];
y0 = fY[p0]; y2 = fY[p0];
z0 = fZ[p0]; z2 = fZ[p0];
// Order along Z axis the points (xi,yi,zi) where "i" belongs to {0,1,2}
// After this z0 < z1 < z2
i0=0, i1=0, i2=0;
if (fZ[p1]<=z0) {z0=fZ[p1]; x0=fX[p1]; y0=fY[p1]; i0=1;}
if (fZ[p1]>z2) {z2=fZ[p1]; x2=fX[p1]; y2=fY[p1]; i2=1;}
if (fZ[p2]<=z0) {z0=fZ[p2]; x0=fX[p2]; y0=fY[p2]; i0=2;}
if (fZ[p2]>z2) {z2=fZ[p2]; x2=fX[p2]; y2=fY[p2]; i2=2;}
i1 = 3-i2-i0;
x1 = fX[t[i1]-1];
y1 = fY[t[i1]-1];
z1 = fZ[t[i1]-1];
if (Hoption.Logz) {
z0 = TMath::Log10(z0);
z1 = TMath::Log10(z1);
z2 = TMath::Log10(z2);
}
if(contour >= z0 && contour <=z2) {
r20 = (contour-z0)/(z2-z0);
xs0c = r20*(x2-x0)+x0;
ys0c = r20*(y2-y0)+y0;
if(contour >= z1 && contour <=z2) {
r21 = (contour-z1)/(z2-z1);
xs1c = r21*(x2-x1)+x1;
ys1c = r21*(y2-y1)+y1;
} else {
r10 = (contour-z0)/(z1-z0);
xs1c = r10*(x1-x0)+x0;
ys1c = r10*(y1-y0)+y0;
}
// do not take the segments equal to a point
if(xs0c != xs1c || ys0c != ys1c) {
nbSeg++;
xs0[nbSeg-1] = xs0c;
ys0[nbSeg-1] = ys0c;
xs1[nbSeg-1] = xs1c;
ys1[nbSeg-1] = ys1c;
}
}
}
Bool_t *segUsed = new Bool_t[fNdt];
for(Int_t i=0; i<fNdt; i++) segUsed[i]=kFALSE;
// Find all the graphs making the contour. There is two kind of graphs,
// either they are "opened" or they are "closed"
// Find the opened graphs
Double_t xc=0, yc=0, xnc=0, ync=0;
Bool_t findNew;
Bool_t s0, s1;
Int_t is, js;
for (is=0; is<nbSeg; is++) {
if (segUsed[is]) continue;
s0 = s1 = kFALSE;
// Find to which segment is is connected. It can be connected
// via 0, 1 or 2 vertices.
for (js=0; js<nbSeg; js++) {
if (is==js) continue;
if (xs0[is]==xs0[js] && ys0[is]==ys0[js]) s0 = kTRUE;
if (xs0[is]==xs1[js] && ys0[is]==ys1[js]) s0 = kTRUE;
if (xs1[is]==xs0[js] && ys1[is]==ys0[js]) s1 = kTRUE;
if (xs1[is]==xs1[js] && ys1[is]==ys1[js]) s1 = kTRUE;
}
// Segment is is alone, not connected. It is stored in the
// list and the next segment is examined.
if (!s0 && !s1) {
graph = new TGraph();
graph->SetPoint(npg,xs0[is],ys0[is]); npg++;
graph->SetPoint(npg,xs1[is],ys1[is]); npg++;
segUsed[is] = kTRUE;
list->Add(graph); npg = 0;
continue;
}
// Segment is is connected via 1 vertex only and can be considered
// as the starting point of an opened contour.
if (!s0 || !s1) {
// Find all the segments connected to segment is
graph = new TGraph();
if (s0) {xc = xs0[is]; yc = ys0[is]; xnc = xs1[is]; ync = ys1[is];}
if (s1) {xc = xs1[is]; yc = ys1[is]; xnc = xs0[is]; ync = ys0[is];}
graph->SetPoint(npg,xnc,ync); npg++;
segUsed[is] = kTRUE;
js = 0;
L01:
findNew = kFALSE;
if (segUsed[js] && js<nbSeg) {
js++;
goto L01;
} else if (xc==xs0[js] && yc==ys0[js]) {
xc = xs1[js];
yc = ys1[js];
findNew = kTRUE;
} else if (xc==xs1[js] && yc==ys1[js]) {
xc = xs0[js];
yc = ys0[js];
findNew = kTRUE;
}
if (findNew) {
segUsed[js] = kTRUE;
graph->SetPoint(npg,xc,yc); npg++;
js = 0;
goto L01;
}
js++;
if (js<nbSeg) goto L01;
list->Add(graph); npg = 0;
}
}
// Find the closed graphs. At this point all the remaining graphs
// are closed. Any segment can be used to start the search.
for (is=0; is<nbSeg; is++) {
if (segUsed[is]) continue;
// Find all the segments connected to segment is
graph = new TGraph();
segUsed[is] = kTRUE;
xc = xs0[is];
yc = ys0[is];
js = 0;
graph->SetPoint(npg,xc,yc); npg++;
L02:
findNew = kFALSE;
if (segUsed[js] && js<nbSeg) {
js++;
goto L02;
} else if (xc==xs0[js] && yc==ys0[js]) {
xc = xs1[js];
yc = ys1[js];
findNew = kTRUE;
} else if (xc==xs1[js] && yc==ys1[js]) {
xc = xs0[js];
yc = ys0[js];
findNew = kTRUE;
}
if (findNew) {
segUsed[js] = kTRUE;
graph->SetPoint(npg,xc,yc); npg++;
js = 0;
goto L02;
}
js++;
if (js<nbSeg) goto L02;
// Close the contour
graph->SetPoint(npg,xs0[is],ys0[is]); npg++;
list->Add(graph); npg = 0;
}
delete [] xs0;
delete [] ys0;
delete [] xs1;
delete [] ys1;
delete [] segUsed;
return list;
}
//______________________________________________________________________________
void TGraphPainter::Paint(Option_t *option)
{
// Paint a TGraphDelaunay according to the value of "option":
//
// "TRI" : The Delaunay triangles are drawn using filled area.
// An hidden surface drawing technique is used. The surface is
// painted with the current fill area color. The edges of each
// triangles are painted with the current line color.
// "TRIW" : The Delaunay triangles are drawn as wire frame
// "TRI1" : The Delaunay triangles are painted with color levels. The edges
// of each triangles are painted with the current line color.
// "TRI2" : the Delaunay triangles are painted with color levels.
// "P" : Draw a marker at each vertex
// "P0" : Draw a circle at each vertex. Each circle background is white.
// "PCOL" : Draw a marker at each vertex. The color of each marker is
// defined according to its Z position.
// "CONT" : Draw contours
// "LINE" : Draw a 3D polyline
TString opt = option;
opt.ToLower();
Bool_t triangles = opt.Contains("tri") ||
opt.Contains("tri1") ||
opt.Contains("tri2");
if (opt.Contains("tri0")) triangles = kFALSE;
Bool_t markers = opt.Contains("p") && !triangles;
Bool_t contour = opt.Contains("cont");
Bool_t line = opt.Contains("line");
fGraph2D->TAttLine::Modify();
fGraph2D->TAttFill::Modify();
fGraph2D->TAttMarker::Modify();
// Compute minimums and maximums
TAxis *xaxis = gCurrentHist->GetXaxis();
Int_t first = xaxis->GetFirst();
fXmin = xaxis->GetBinLowEdge(first);
if (Hoption.Logx && fXmin <= 0) fXmin = xaxis->GetBinUpEdge(xaxis->FindFixBin(0.01*xaxis->GetBinWidth(first)));
fXmax = xaxis->GetBinUpEdge(xaxis->GetLast());
TAxis *yaxis = gCurrentHist->GetYaxis();
first = yaxis->GetFirst();
fYmin = yaxis->GetBinLowEdge(first);
if (Hoption.Logy && fYmin <= 0) fYmin = yaxis->GetBinUpEdge(yaxis->FindFixBin(0.01*yaxis->GetBinWidth(first)));
fYmax = yaxis->GetBinUpEdge(yaxis->GetLast());
fZmax = gCurrentHist->GetMaximum();
fZmin = gCurrentHist->GetMinimum();
if (Hoption.Logz && fZmin <= 0) fZmin = TMath::Min((Double_t)1, (Double_t)0.001*gCurrentHist->GetMaximum());
if (triangles) PaintTriangles(option);
if (markers) PaintPolyMarker(option);
if (contour) PaintContour(option);
if (line) PaintPolyLine(option);
}
//______________________________________________________________________________
void TGraphPainter::PaintContour(Option_t * /*option*/)
{
// Paints the 2D graph as a contour plot. Delaunay triangles are used
// to compute the contours.
// Initialize the levels on the Z axis
Int_t ncolors = gStyle->GetNumberOfColors();
Int_t ndiv = gCurrentHist->GetContour();
if (ndiv == 0 ) {
ndiv = gStyle->GetNumberContours();
gCurrentHist->SetContour(ndiv);
}
Int_t ndivz = TMath::Abs(ndiv);
if (gCurrentHist->TestBit(TH1::kUserContour) == 0) gCurrentHist->SetContour(ndiv);
Int_t theColor;
TList *l;
TGraph *g;
TObject *obj;
Double_t c;
if (!fNdt) FindTriangles();
for (Int_t k=0; k<ndiv; k++) {
c = gCurrentHist->GetContourLevelPad(k);
l = GetContourList(c);
TIter next(l);
while ((obj = next())) {
if(obj->InheritsFrom(TGraph::Class()) ) {
g=(TGraph*)obj;
theColor = Int_t((k+0.99)*Float_t(ncolors)/Float_t(ndivz));
g->SetLineColor(gStyle->GetColorPalette(theColor));
g->Paint("l");
}
}
}
}
//______________________________________________________________________________
void TGraphPainter::PaintLevels(Int_t *t,Double_t *x, Double_t *y,
Int_t nblev, Double_t *glev)
{
// Paints one triangle.
// nblev = 0 : paint the color levels
// nblev != 0 : paint the grid
Int_t i, fillColor, ncolors, theColor0, theColor2;
Int_t p0=t[0]-1;
Int_t p1=t[1]-1;
Int_t p2=t[2]-1;
Double_t xl[2],yl[2];
Double_t zl, r21, r20, r10;
Double_t x0 = x[0] , x2 = x[0];
Double_t y0 = y[0] , y2 = y[0];
Double_t z0 = fZ[p0], z2 = fZ[p0];
// Order along Z axis the points (xi,yi,zi) where "i" belongs to {0,1,2}
// After this z0 < z1 < z2
Int_t i0=0, i1=0, i2=0;
if (fZ[p1]<=z0) {z0=fZ[p1]; x0=x[1]; y0=y[1]; i0=1;}
if (fZ[p1]>z2) {z2=fZ[p1]; x2=x[1]; y2=y[1]; i2=1;}
if (fZ[p2]<=z0) {z0=fZ[p2]; x0=x[2]; y0=y[2]; i0=2;}
if (fZ[p2]>z2) {z2=fZ[p2]; x2=x[2]; y2=y[2]; i2=2;}
i1 = 3-i2-i0;
Double_t x1 = x[i1];
Double_t y1 = y[i1];
Double_t z1 = fZ[t[i1]-1];
// zi = Z values of the stripe number i
// zip = Previous zi
Double_t zi=0, zip=0;
if (nblev <= 0) {
// Paint the colors levels
// Compute the color associated to z0 (theColor0) and z2 (theColor2)
ncolors = gStyle->GetNumberOfColors();
theColor0 = (Int_t)( ((z0-fZmin)/(fZmax-fZmin))*(ncolors-1) );
theColor2 = (Int_t)( ((z2-fZmin)/(fZmax-fZmin))*(ncolors-1) );
// The stripes drawn to fill the triangles may have up to 5 points
Double_t xp[5], yp[5];
// rl = Ratio between z0 and z2 (long)
// rs = Ratio between z0 and z1 or z1 and z2 (short)
Double_t rl,rs;
// ci = Color of the stripe number i
// npf = number of point needed to draw the current stripe
Int_t ci,npf;
fillColor = fGraph2D->GetFillColor();
// If the z0's color and z2's colors are the same, the whole triangle
// can be painted in one go.
if(theColor0 == theColor2) {
fGraph2D->SetFillColor(gStyle->GetColorPalette(theColor0));
fGraph2D->TAttFill::Modify();
gPad->PaintFillArea(3,x,y);
// The triangle must be painted with several colors
} else {
for(ci=theColor0; ci<=theColor2; ci++) {
fGraph2D->SetFillColor(gStyle->GetColorPalette(ci));
fGraph2D->TAttFill::Modify();
if (ci==theColor0) {
zi = (((ci+1)*(fZmax-fZmin))/(ncolors-1))+fZmin;
xp[0] = x0;
yp[0] = y0;
rl = (zi-z0)/(z2-z0);
xp[1] = rl*(x2-x0)+x0;
yp[1] = rl*(y2-y0)+y0;
if (zi>=z1 || z0==z1) {
rs = (zi-z1)/(z2-z1);
xp[2] = rs*(x2-x1)+x1;
yp[2] = rs*(y2-y1)+y1;
xp[3] = x1;
yp[3] = y1;
npf = 4;
} else {
rs = (zi-z0)/(z1-z0);
xp[2] = rs*(x1-x0)+x0;
yp[2] = rs*(y1-y0)+y0;
npf = 3;
}
} else if (ci==theColor2) {
xp[0] = xp[1];
yp[0] = yp[1];
xp[1] = x2;
yp[1] = y2;
if (zi<z1 || z2==z1) {
xp[3] = xp[2];
yp[3] = yp[2];
xp[2] = x1;
yp[2] = y1;
npf = 4;
} else {
npf = 3;
}
} else {
zi = (((ci+1)*(fZmax-fZmin))/(ncolors-1))+fZmin;
xp[0] = xp[1];
yp[0] = yp[1];
rl = (zi-z0)/(z2-z0);
xp[1] = rl*(x2-x0)+x0;
yp[1] = rl*(y2-y0)+y0;
if ( zi>=z1 && zip<=z1) {
xp[3] = x1;
yp[3] = y1;
xp[4] = xp[2];
yp[4] = yp[2];
npf = 5;
} else {
xp[3] = xp[2];
yp[3] = yp[2];
npf = 4;
}
if (zi<z1) {
rs = (zi-z0)/(z1-z0);
xp[2] = rs*(x1-x0)+x0;
yp[2] = rs*(y1-y0)+y0;
} else {
rs = (zi-z1)/(z2-z1);
xp[2] = rs*(x2-x1)+x1;
yp[2] = rs*(y2-y1)+y1;
}
}
zip = zi;
// Paint a stripe
gPad->PaintFillArea(npf,xp,yp);
}
}
fGraph2D->SetFillColor(fillColor);
fGraph2D->TAttFill::Modify();
} else {
// Paint the grid levels
fGraph2D->SetLineStyle(3);
fGraph2D->TAttLine::Modify();
for(i=0; i<nblev; i++){
zl=glev[i];
if(zl >= z0 && zl <=z2) {
r21=(zl-z1)/(z2-z1);
r20=(zl-z0)/(z2-z0);
r10=(zl-z0)/(z1-z0);
xl[0]=r20*(x2-x0)+x0;
yl[0]=r20*(y2-y0)+y0;
if(zl >= z1 && zl <=z2) {
xl[1]=r21*(x2-x1)+x1;
yl[1]=r21*(y2-y1)+y1;
} else {
xl[1]=r10*(x1-x0)+x0;
yl[1]=r10*(y1-y0)+y0;
}
gPad->PaintPolyLine(2,xl,yl);
}
}
fGraph2D->SetLineStyle(1);
fGraph2D->TAttLine::Modify();
}
}
//______________________________________________________________________________
void TGraphPainter::PaintPolyMarker(Option_t *option)
{
// Paints the 2D graph as PaintPolyMarker
Double_t temp1[3],temp2[3];
TView *view = gPad->GetView();
if (!view) {
Error("PaintPolyMarker", "No TView in current pad");
return;
}
TString opt = option;
opt.ToLower();
Bool_t markers0 = opt.Contains("p0");
Bool_t colors = opt.Contains("pcol");
Int_t ncolors = gStyle->GetNumberOfColors();
Int_t it, theColor;
Double_t *xm = new Double_t[fNpoints];
Double_t *ym = new Double_t[fNpoints];
Int_t npd = 0;
for (it=0; it<fNpoints; it++) {
if(fX[it] < fXmin || fX[it] > fXmax) continue;
if(fY[it] < fYmin || fY[it] > fYmax) continue;
npd++;
temp1[0] = fX[it];
temp1[1] = fY[it];
temp1[2] = fZ[it];
temp1[0] = TMath::Max(temp1[0],fXmin);
temp1[1] = TMath::Max(temp1[1],fYmin);
temp1[2] = TMath::Max(temp1[2],fZmin);
temp1[2] = TMath::Min(temp1[2],fZmax);
if (Hoption.Logx) temp1[0] = TMath::Log10(temp1[0]);
if (Hoption.Logy) temp1[1] = TMath::Log10(temp1[1]);
if (Hoption.Logz) temp1[2] = TMath::Log10(temp1[2]);
view->WCtoNDC(temp1, &temp2[0]);
xm[it] = temp2[0];
ym[it] = temp2[1];
}
if (markers0) {
PaintPolyMarker0(npd,xm,ym);
} else if (colors) {
for (it=0; it<fNpoints; it++) {
theColor = (Int_t)( ((fZ[it]-fZmin)/(fZmax-fZmin))*(ncolors-1) );
fGraph2D->SetMarkerColor(gStyle->GetColorPalette(theColor));
fGraph2D->TAttMarker::Modify();
gPad->PaintPolyMarker(1,&xm[it],&ym[it]);
}
} else {
fGraph2D->SetMarkerStyle(fGraph2D->GetMarkerStyle());
fGraph2D->SetMarkerSize(fGraph2D->GetMarkerSize());
fGraph2D->SetMarkerColor(fGraph2D->GetMarkerColor());
fGraph2D->TAttMarker::Modify();
gPad->PaintPolyMarker(npd,xm,ym);
}
delete [] xm;
delete [] ym;
}
//______________________________________________________________________________
void TGraphPainter::PaintPolyLine(Option_t * /* option */)
{
// Paints the 2D graph as PaintPolyLine
Double_t temp1[3],temp2[3];
TView *view = gPad->GetView();
if (!view) {
Error("PaintPolyLine", "No TView in current pad");
return;
}
Int_t it;
Double_t *xm = new Double_t[fNpoints];
Double_t *ym = new Double_t[fNpoints];
Int_t npd = 0;
for (it=0; it<fNpoints; it++) {
if(fX[it] < fXmin || fX[it] > fXmax) continue;
if(fY[it] < fYmin || fY[it] > fYmax) continue;
npd++;
temp1[0] = fX[it];
temp1[1] = fY[it];
temp1[2] = fZ[it];
temp1[0] = TMath::Max(temp1[0],fXmin);
temp1[1] = TMath::Max(temp1[1],fYmin);
temp1[2] = TMath::Max(temp1[2],fZmin);
temp1[2] = TMath::Min(temp1[2],fZmax);
if (Hoption.Logx) temp1[0] = TMath::Log10(temp1[0]);
if (Hoption.Logy) temp1[1] = TMath::Log10(temp1[1]);
if (Hoption.Logz) temp1[2] = TMath::Log10(temp1[2]);
view->WCtoNDC(temp1, &temp2[0]);
xm[it] = temp2[0];
ym[it] = temp2[1];
}
fGraph2D->SetLineStyle(fGraph2D->GetLineStyle());
fGraph2D->SetLineWidth(fGraph2D->GetLineWidth());
fGraph2D->SetLineColor(fGraph2D->GetLineColor());
fGraph2D->TAttLine::Modify();
gPad->PaintPolyLine(npd,xm,ym);
delete [] xm;
delete [] ym;
}
//______________________________________________________________________________
void TGraphPainter::PaintPolyMarker0(Int_t n, Double_t *x, Double_t *y)
{
// Paints a circle at each vertex. Each circle background is white.
fGraph2D->SetMarkerSize(fGraph2D->GetMarkerSize());
Int_t mc = fGraph2D->GetMarkerColor();
for (Int_t i=0; i<n; i++) {
fGraph2D->SetMarkerStyle(20);
fGraph2D->SetMarkerColor(0);
fGraph2D->TAttMarker::Modify();
gPad->PaintPolyMarker(1,&x[i],&y[i]);
fGraph2D->SetMarkerStyle(24);
fGraph2D->SetMarkerColor(mc);
fGraph2D->TAttMarker::Modify();
gPad->PaintPolyMarker(1,&x[i],&y[i]);
}
}
//______________________________________________________________________________
void TGraphPainter::PaintTriangles(Option_t *option)
{
// Paints the 2D graph as triangles
Double_t x[4], y[4], temp1[3],temp2[3];
Int_t it,t[3];
Int_t *order = 0;
Double_t *dist = 0;
TView *view = gPad->GetView();
if (!view) {
Error("PaintTriangles", "No TView in current pad");
return;
}
TString opt = option;
opt.ToLower();
Bool_t tri1 = opt.Contains("tri1");
Bool_t tri2 = opt.Contains("tri2");
Bool_t markers = opt.Contains("p");
Bool_t markers0 = opt.Contains("p0");
Bool_t wire = opt.Contains("w");
// Define the grid levels drawn on the triangles.
// The grid levels are aligned on the Z axis' main tick marks.
Int_t nblev=0;
Double_t *glev=0;
if (!tri1 && !tri2 && !wire) {
Int_t ndivz = gCurrentHist->GetZaxis()->GetNdivisions()%100;
Int_t nbins;
Double_t binLow, binHigh, binWidth;
// Find the main tick marks positions.
Double_t *r0 = view->GetRmin();
Double_t *r1 = view->GetRmax();
if (ndivz > 0) {
THLimitsFinder::Optimize(r0[2], r1[2], ndivz,
binLow, binHigh, nbins, binWidth, " ");
} else {
nbins = TMath::Abs(ndivz);
binLow = r0[2];
binHigh = r1[2];
binWidth = (binHigh-binLow)/nbins;
}
// Define the grid levels
nblev = nbins+1;
glev = new Double_t[nblev];
for (Int_t i = 0; i < nblev; ++i) glev[i] = binLow+i*binWidth;
}
// Initialize the levels on the Z axis
if (tri1 || tri2) {
Int_t ndiv = gCurrentHist->GetContour();
if (ndiv == 0 ) {
ndiv = gStyle->GetNumberContours();
gCurrentHist->SetContour(ndiv);
}
if (gCurrentHist->TestBit(TH1::kUserContour) == 0) gCurrentHist->SetContour(ndiv);
}
// For each triangle, compute the distance between the triangle centre
// and the back planes. Then these distances are sorted in order to draw
// the triangles from back to front.
if (!fNdt) FindTriangles();
Double_t cp = TMath::Cos(view->GetLongitude()*TMath::Pi()/180.);
Double_t sp = TMath::Sin(view->GetLongitude()*TMath::Pi()/180.);
order = new Int_t[fNdt];
dist = new Double_t[fNdt];
Double_t xd,yd;
Int_t p, n, m;
Bool_t o = kFALSE;
for (it=0; it<fNdt; it++) {
p = fPTried[it];
n = fNTried[it];
m = fMTried[it];
xd = (fXN[p]+fXN[n]+fXN[m])/3;
yd = (fYN[p]+fYN[n]+fYN[m])/3;
if ((cp >= 0) && (sp >= 0.)) {
dist[it] = -(fXNmax-xd+fYNmax-yd);
} else if ((cp <= 0) && (sp >= 0.)) {
dist[it] = -(fXNmax-xd+yd-fYNmin);
o = kTRUE;
} else if ((cp <= 0) && (sp <= 0.)) {
dist[it] = -(xd-fXNmin+yd-fYNmin);
} else {
dist[it] = -(xd-fXNmin+fYNmax-yd);
o = kTRUE;
}
}
TMath::Sort(fNdt, dist, order, o);
// Draw the triangles and markers if requested
fGraph2D->SetFillColor(fGraph2D->GetFillColor());
Int_t fs = fGraph2D->GetFillStyle();
fGraph2D->SetFillStyle(1001);
fGraph2D->TAttFill::Modify();
fGraph2D->SetLineColor(fGraph2D->GetLineColor());
fGraph2D->TAttLine::Modify();
Int_t ls = fGraph2D->GetLineStyle();
for (it=0; it<fNdt; it++) {
t[0] = fPTried[order[it]];
t[1] = fNTried[order[it]];
t[2] = fMTried[order[it]];
for (Int_t k=0; k<3; k++) {
if(fX[t[k]-1] < fXmin || fX[t[k]-1] > fXmax) goto endloop;
if(fY[t[k]-1] < fYmin || fY[t[k]-1] > fYmax) goto endloop;
temp1[0] = fX[t[k]-1];
temp1[1] = fY[t[k]-1];
temp1[2] = fZ[t[k]-1];
temp1[0] = TMath::Max(temp1[0],fXmin);
temp1[1] = TMath::Max(temp1[1],fYmin);
temp1[2] = TMath::Max(temp1[2],fZmin);
temp1[2] = TMath::Min(temp1[2],fZmax);
if (Hoption.Logx) temp1[0] = TMath::Log10(temp1[0]);
if (Hoption.Logy) temp1[1] = TMath::Log10(temp1[1]);
if (Hoption.Logz) temp1[2] = TMath::Log10(temp1[2]);
view->WCtoNDC(temp1, &temp2[0]);
x[k] = temp2[0];
y[k] = temp2[1];
}
x[3] = x[0];
y[3] = y[0];
if (tri1 || tri2) PaintLevels(t,x,y);
if (!tri1 && !tri2 && !wire) {
gPad->PaintFillArea(3,x,y);
PaintLevels(t,x,y,nblev,glev);
}
if (!tri2) gPad->PaintPolyLine(4,x,y);
if (markers) {
if (markers0) {
PaintPolyMarker0(3,x,y);
} else {
fGraph2D->SetMarkerStyle(fGraph2D->GetMarkerStyle());
fGraph2D->SetMarkerSize(fGraph2D->GetMarkerSize());
fGraph2D->SetMarkerColor(fGraph2D->GetMarkerColor());
fGraph2D->TAttMarker::Modify();
gPad->PaintPolyMarker(3,x,y);
}
}
endloop:
continue;
}
fGraph2D->SetFillStyle(fs);
fGraph2D->SetLineStyle(ls);
fGraph2D->TAttLine::Modify();
fGraph2D->TAttFill::Modify();
delete [] order;
delete [] dist;
if (glev) delete [] glev;
}
ROOT page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.