TGraph2DPainter.cxx

Go to the documentation of this file.
00001 // @(#)root/histpainter:$Id: TGraph2DPainter.cxx,v 1.00
00002 // Author: Olivier Couet
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "TROOT.h"
00013 #include "TGraph2DPainter.h"
00014 #include "TMath.h"
00015 #include "TList.h"
00016 #include "TGraph.h"
00017 #include "TGraph2D.h"
00018 #include "TGraphDelaunay.h"
00019 #include "TPolyLine.h"
00020 #include "TPolyMarker.h"
00021 #include "TVirtualPad.h"
00022 #include "TView.h"
00023 #include "THLimitsFinder.h"
00024 #include "TStyle.h"
00025 #include "Hoption.h"
00026 #include "TH1.h"
00027 
00028 R__EXTERN TH1  *gCurrentHist;
00029 R__EXTERN Hoption_t Hoption;
00030 
00031 ClassImp(TGraph2DPainter)
00032 
00033 
00034 //______________________________________________________________________________
00035 //
00036 // TGraph2DPainter paints a TGraphDelaunay
00037 //
00038 
00039 
00040 //______________________________________________________________________________
00041 TGraph2DPainter::TGraph2DPainter()
00042 {
00043    // TGraph2DPainter default constructor
00044 
00045    fX        = 0;
00046    fY        = 0;
00047    fZ        = 0;
00048    fEX       = 0;
00049    fEY       = 0;
00050    fEZ       = 0;
00051    fXN       = 0;
00052    fYN       = 0;
00053    fPTried   = 0;
00054    fNTried   = 0;
00055    fMTried   = 0;
00056    fGraph2D  = 0;
00057    fDelaunay = 0;
00058    fXmin     = 0.;
00059    fXmax     = 0.;
00060    fYmin     = 0.;
00061    fYmax     = 0.;
00062    fZmin     = 0.;
00063    fZmax     = 0.;
00064    fXNmin    = 0;
00065    fXNmax    = 0;
00066    fYNmin    = 0;
00067    fYNmax    = 0;
00068    fNdt      = 0;
00069    fNpoints  = 0;
00070 }
00071 
00072 
00073 //______________________________________________________________________________
00074 TGraph2DPainter::TGraph2DPainter(TGraphDelaunay *gd)
00075 {
00076    // TGraph2DPainter constructor
00077 
00078    fDelaunay = gd;
00079    fGraph2D  = fDelaunay->GetGraph2D();
00080    fNpoints  = fGraph2D->GetN();
00081    fX        = fGraph2D->GetX();
00082    fY        = fGraph2D->GetY();
00083    fZ        = fGraph2D->GetZ();
00084    fEX       = fGraph2D->GetEX();
00085    fEY       = fGraph2D->GetEY();
00086    fEZ       = fGraph2D->GetEZ();
00087    fNdt      = 0;
00088    fXN       = 0;
00089    fYN       = 0;
00090    fXNmin    = 0;
00091    fXNmax    = 0;
00092    fYNmin    = 0;
00093    fYNmax    = 0;
00094    fPTried   = 0;
00095    fNTried   = 0;
00096    fMTried   = 0;
00097    fXmin     = 0.;
00098    fXmax     = 0.;
00099    fYmin     = 0.;
00100    fYmax     = 0.;
00101    fZmin     = 0.;
00102    fZmax     = 0.;
00103 }
00104 
00105 
00106 //______________________________________________________________________________
00107 TGraph2DPainter::~TGraph2DPainter()
00108 {
00109    // TGraph2DPainter destructor.
00110 }
00111 
00112 
00113 //______________________________________________________________________________
00114 void TGraph2DPainter::FindTriangles()
00115 {
00116    // Find triangles in fDelaunay and initialise the TGraph2DPainter values
00117    // needed to paint triangles or find contours.
00118 
00119    fDelaunay->FindAllTriangles();
00120    fNdt    = fDelaunay->GetNdt();
00121    fXN     = fDelaunay->GetXN();
00122    fYN     = fDelaunay->GetYN();
00123    fXNmin  = fDelaunay->GetXNmin();
00124    fXNmax  = fDelaunay->GetXNmax();
00125    fYNmin  = fDelaunay->GetYNmin();
00126    fYNmax  = fDelaunay->GetYNmax();
00127    fPTried = fDelaunay->GetPTried();
00128    fNTried = fDelaunay->GetNTried();
00129    fMTried = fDelaunay->GetMTried();
00130 }
00131 
00132 
00133 //______________________________________________________________________________
00134 TList *TGraph2DPainter::GetContourList(Double_t contour)
00135 {
00136    // Returns the X and Y graphs building a contour. A contour level may
00137    // consist in several parts not connected to each other. This function
00138    // finds them and returns them in a graphs' list.
00139 
00140    // Exit if the contour is outisde the Z range.
00141    Double_t zmin = gCurrentHist->GetMinimum();
00142    Double_t zmax = gCurrentHist->GetMaximum();
00143    if (Hoption.Logz) {
00144       if (zmin > 0) {
00145          zmin = TMath::Log10(zmin);
00146          zmax = TMath::Log10(zmax);
00147       } else {
00148          return 0;
00149       }
00150    }
00151    if(contour<zmin || contour>zmax) {
00152       Error("GetContourList", "Contour level (%g) outside the Z scope [%g,%g]",
00153       contour,zmin,zmax);
00154       return 0;
00155    }
00156 
00157    if (!fNdt) FindTriangles();
00158 
00159    TGraph *graph = 0;           // current graph
00160    Int_t npg     = 0;           // number of points in the current graph
00161    TList *list   = new TList(); // list holding all the graphs
00162 
00163    // Find all the segments making the contour
00164 
00165    Double_t r21, r20, r10;
00166    Int_t p0, p1, p2;
00167    Double_t x0, y0, z0;
00168    Double_t x1, y1, z1;
00169    Double_t x2, y2, z2;
00170    Int_t t[3],i,it,i0,i1,i2;
00171 
00172    // Allocate space to store the segments. They cannot be more than the
00173    // number of triangles.
00174    Double_t xs0c, ys0c, xs1c, ys1c;
00175    Double_t *xs0 = new Double_t[fNdt];
00176    Double_t *ys0 = new Double_t[fNdt];
00177    Double_t *xs1 = new Double_t[fNdt];
00178    Double_t *ys1 = new Double_t[fNdt];
00179    for (i=0;i<fNdt;i++) {
00180       xs0[i] = 0.;
00181       ys0[i] = 0.;
00182       xs1[i] = 0.;
00183       ys1[i] = 0.;
00184    }
00185    Int_t nbSeg   = 0;
00186 
00187    // Loop over all the triangles in order to find all the line segments
00188    // making the contour.
00189    for(it=0; it<fNdt; it++) {
00190       t[0] = fPTried[it];
00191       t[1] = fNTried[it];
00192       t[2] = fMTried[it];
00193       p0   = t[0]-1;
00194       p1   = t[1]-1;
00195       p2   = t[2]-1;
00196       x0   = fX[p0]; x2 = fX[p0];
00197       y0   = fY[p0]; y2 = fY[p0];
00198       z0   = fZ[p0]; z2 = fZ[p0];
00199 
00200       // Order along Z axis the points (xi,yi,zi) where "i" belongs to {0,1,2}
00201       // After this z0 < z1 < z2
00202       i0=0, i1=0, i2=0;
00203       if (fZ[p1]<=z0) {z0=fZ[p1]; x0=fX[p1]; y0=fY[p1]; i0=1;}
00204       if (fZ[p1]>z2)  {z2=fZ[p1]; x2=fX[p1]; y2=fY[p1]; i2=1;}
00205       if (fZ[p2]<=z0) {z0=fZ[p2]; x0=fX[p2]; y0=fY[p2]; i0=2;}
00206       if (fZ[p2]>z2)  {z2=fZ[p2]; x2=fX[p2]; y2=fY[p2]; i2=2;}
00207       if (i0==0 && i2==0) {
00208          Error("GetContourList", "wrong vertices ordering");
00209          delete [] xs0;
00210          delete [] ys0;
00211          delete [] xs1;
00212          delete [] ys1;
00213          return 0;
00214       } else {
00215          i1 = 3-i2-i0;
00216       }
00217       x1 = fX[t[i1]-1];
00218       y1 = fY[t[i1]-1];
00219       z1 = fZ[t[i1]-1];
00220 
00221       if (Hoption.Logz) {
00222          z0 = TMath::Log10(z0);
00223          z1 = TMath::Log10(z1);
00224          z2 = TMath::Log10(z2);
00225       }
00226 
00227       if(contour >= z0 && contour <=z2) {
00228          r20 = (contour-z0)/(z2-z0);
00229          xs0c = r20*(x2-x0)+x0;
00230          ys0c = r20*(y2-y0)+y0;
00231          if(contour >= z1 && contour <=z2) {
00232             r21 = (contour-z1)/(z2-z1);
00233             xs1c = r21*(x2-x1)+x1;
00234             ys1c = r21*(y2-y1)+y1;
00235          } else {
00236             r10 = (contour-z0)/(z1-z0);
00237             xs1c = r10*(x1-x0)+x0;
00238             ys1c = r10*(y1-y0)+y0;
00239          }
00240          // do not take the segments equal to a point
00241          if(xs0c != xs1c || ys0c != ys1c) {
00242             nbSeg++;
00243             xs0[nbSeg-1] = xs0c;
00244             ys0[nbSeg-1] = ys0c;
00245             xs1[nbSeg-1] = xs1c;
00246             ys1[nbSeg-1] = ys1c;
00247          }
00248       }
00249    }
00250 
00251    Bool_t *segUsed = new Bool_t[fNdt];
00252    for(i=0; i<fNdt; i++) segUsed[i]=kFALSE;
00253 
00254    // Find all the graphs making the contour. There is two kind of graphs,
00255    // either they are "opened" or they are "closed"
00256 
00257    // Find the opened graphs
00258    Double_t xc=0, yc=0, xnc=0, ync=0;
00259    Bool_t findNew;
00260    Bool_t s0, s1;
00261    Int_t is, js;
00262    for (is=0; is<nbSeg; is++) {
00263       if (segUsed[is]) continue;
00264       s0 = s1 = kFALSE;
00265 
00266       // Find to which segment is is connected. It can be connected
00267       // via 0, 1 or 2 vertices.
00268       for (js=0; js<nbSeg; js++) {
00269          if (is==js) continue;
00270          if (xs0[is]==xs0[js] && ys0[is]==ys0[js]) s0 = kTRUE;
00271          if (xs0[is]==xs1[js] && ys0[is]==ys1[js]) s0 = kTRUE;
00272          if (xs1[is]==xs0[js] && ys1[is]==ys0[js]) s1 = kTRUE;
00273          if (xs1[is]==xs1[js] && ys1[is]==ys1[js]) s1 = kTRUE;
00274       }
00275 
00276       // Segment is is alone, not connected. It is stored in the
00277       // list and the next segment is examined.
00278       if (!s0 && !s1) {
00279          graph = new TGraph();
00280          graph->SetPoint(npg,xs0[is],ys0[is]); npg++;
00281          graph->SetPoint(npg,xs1[is],ys1[is]); npg++;
00282          segUsed[is] = kTRUE;
00283          list->Add(graph); npg = 0;
00284          continue;
00285       }
00286 
00287       // Segment is is connected via 1 vertex only and can be considered
00288       // as the starting point of an opened contour.
00289       if (!s0 || !s1) {
00290          // Find all the segments connected to segment is
00291          graph = new TGraph();
00292          if (s0) {xc = xs0[is]; yc = ys0[is]; xnc = xs1[is]; ync = ys1[is];}
00293          if (s1) {xc = xs1[is]; yc = ys1[is]; xnc = xs0[is]; ync = ys0[is];}
00294          graph->SetPoint(npg,xnc,ync); npg++;
00295          segUsed[is] = kTRUE;
00296          js = 0;
00297 L01:
00298          findNew = kFALSE;
00299          if (segUsed[js] && js<nbSeg) {
00300             js++;
00301             goto L01;
00302          } else if (xc==xs0[js] && yc==ys0[js]) {
00303             xc      = xs1[js];
00304             yc      = ys1[js];
00305             findNew = kTRUE;
00306          } else if (xc==xs1[js] && yc==ys1[js]) {
00307             xc      = xs0[js];
00308             yc      = ys0[js];
00309             findNew = kTRUE;
00310          }
00311          if (findNew) {
00312             segUsed[js] = kTRUE;
00313             graph->SetPoint(npg,xc,yc); npg++;
00314             js = 0;
00315             goto L01;
00316          }
00317          js++;
00318          if (js<nbSeg) goto L01;
00319          list->Add(graph); npg = 0;
00320       }
00321    }
00322 
00323    // Find the closed graphs. At this point all the remaining graphs
00324    // are closed. Any segment can be used to start the search.
00325    for (is=0; is<nbSeg; is++) {
00326       if (segUsed[is]) continue;
00327 
00328       // Find all the segments connected to segment is
00329       graph = new TGraph();
00330       segUsed[is] = kTRUE;
00331       xc = xs0[is];
00332       yc = ys0[is];
00333       js = 0;
00334       graph->SetPoint(npg,xc,yc); npg++;
00335 L02:
00336       findNew = kFALSE;
00337       if (segUsed[js] && js<nbSeg) {
00338          js++;
00339          goto L02;
00340       } else if (xc==xs0[js] && yc==ys0[js]) {
00341          xc      = xs1[js];
00342          yc      = ys1[js];
00343          findNew = kTRUE;
00344       } else if (xc==xs1[js] && yc==ys1[js]) {
00345          xc      = xs0[js];
00346          yc      = ys0[js];
00347          findNew = kTRUE;
00348       }
00349       if (findNew) {
00350          segUsed[js] = kTRUE;
00351          graph->SetPoint(npg,xc,yc); npg++;
00352          js = 0;
00353          goto L02;
00354       }
00355       js++;
00356       if (js<nbSeg) goto L02;
00357       // Close the contour
00358       graph->SetPoint(npg,xs0[is],ys0[is]); npg++;
00359       list->Add(graph); npg = 0;
00360    }
00361 
00362    delete [] xs0;
00363    delete [] ys0;
00364    delete [] xs1;
00365    delete [] ys1;
00366    delete [] segUsed;
00367    return list;
00368 }
00369 
00370 
00371 //______________________________________________________________________________
00372 void TGraph2DPainter::Paint(Option_t *option)
00373 {
00374    // Paint a TGraphDelaunay according to the value of "option":
00375    //
00376    //   "TRI"  : The Delaunay triangles are drawn using filled area.
00377    //            An hidden surface drawing technique is used. The surface is
00378    //            painted with the current fill area color. The edges of each
00379    //            triangles are painted with the current line color.
00380    //   "TRIW" : The Delaunay triangles are drawn as wire frame
00381    //   "TRI1" : The Delaunay triangles are painted with color levels. The edges
00382    //            of each triangles are painted with the current line color.
00383    //   "TRI2" : the Delaunay triangles are painted with color levels.
00384    //   "P"    : Draw a marker at each vertex
00385    //   "P0"   : Draw a circle at each vertex. Each circle background is white.
00386    //   "PCOL" : Draw a marker at each vertex. The color of each marker is
00387    //            defined according to its Z position.
00388    //   "CONT" : Draw contours
00389    //   "LINE" : Draw a 3D polyline
00390 
00391    TString opt = option;
00392    opt.ToLower();
00393    Bool_t triangles = opt.Contains("tri")  ||
00394                       opt.Contains("tri1") ||
00395                       opt.Contains("tri2");
00396    if (opt.Contains("tri0")) triangles = kFALSE;
00397 
00398    Bool_t markers   = opt.Contains("p") && !triangles;
00399    Bool_t contour   = opt.Contains("cont");
00400    Bool_t line      = opt.Contains("line");
00401    Bool_t err       = opt.Contains("err");
00402 
00403    fGraph2D->TAttLine::Modify();
00404    fGraph2D->TAttFill::Modify();
00405    fGraph2D->TAttMarker::Modify();
00406 
00407    // Compute minimums and maximums
00408    TAxis *xaxis = gCurrentHist->GetXaxis();
00409    Int_t first = xaxis->GetFirst();
00410    fXmin = xaxis->GetBinLowEdge(first);
00411    if (Hoption.Logx && fXmin <= 0) fXmin = xaxis->GetBinUpEdge(xaxis->FindFixBin(0.01*xaxis->GetBinWidth(first)));
00412    fXmax = xaxis->GetBinUpEdge(xaxis->GetLast());
00413    TAxis *yaxis = gCurrentHist->GetYaxis();
00414    first = yaxis->GetFirst();
00415    fYmin = yaxis->GetBinLowEdge(first);
00416    if (Hoption.Logy && fYmin <= 0) fYmin = yaxis->GetBinUpEdge(yaxis->FindFixBin(0.01*yaxis->GetBinWidth(first)));
00417    fYmax = yaxis->GetBinUpEdge(yaxis->GetLast());
00418    fZmax = fGraph2D->GetZmax();
00419    fZmin = fGraph2D->GetZmin();
00420    if (Hoption.Logz && fZmin <= 0) fZmin = TMath::Min((Double_t)1, (Double_t)0.001*fGraph2D->GetZmax());
00421 
00422    if (triangles) PaintTriangles(option);
00423    if (contour)   PaintContour(option);
00424    if (line)      PaintPolyLine(option);
00425    if (err)       PaintErrors(option);
00426    if (markers)   PaintPolyMarker(option);
00427 }
00428 
00429 
00430 //______________________________________________________________________________
00431 void TGraph2DPainter::PaintContour(Option_t * /*option*/)
00432 {
00433    // Paints the 2D graph as a contour plot. Delaunay triangles are used
00434    // to compute the contours.
00435 
00436    // Initialize the levels on the Z axis
00437    Int_t ncolors  = gStyle->GetNumberOfColors();
00438    Int_t ndiv   = gCurrentHist->GetContour();
00439    if (ndiv == 0 ) {
00440       ndiv = gStyle->GetNumberContours();
00441       gCurrentHist->SetContour(ndiv);
00442    }
00443    Int_t ndivz  = TMath::Abs(ndiv);
00444    if (gCurrentHist->TestBit(TH1::kUserContour) == 0) gCurrentHist->SetContour(ndiv);
00445 
00446    Int_t theColor;
00447    TList *l;
00448    TGraph *g;
00449    TObject *obj;
00450    Double_t c;
00451 
00452    if (!fNdt) FindTriangles();
00453 
00454    for (Int_t k=0; k<ndiv; k++) {
00455       c = gCurrentHist->GetContourLevelPad(k);
00456       l = GetContourList(c);
00457       TIter next(l);
00458       while ((obj = next())) {
00459          if(obj->InheritsFrom(TGraph::Class()) ) {
00460             g=(TGraph*)obj;
00461             theColor = Int_t((k+0.99)*Float_t(ncolors)/Float_t(ndivz));
00462             g->SetLineColor(gStyle->GetColorPalette(theColor));
00463             g->Paint("l");
00464          }
00465       }
00466    }
00467 }
00468 
00469 
00470 //______________________________________________________________________________
00471 void TGraph2DPainter::PaintErrors(Option_t * /* option */)
00472 {
00473    // Paints the 2D graph as error bars
00474 
00475    Double_t temp1[3],temp2[3];
00476 
00477    TView *view = gPad->GetView();
00478    if (!view) {
00479       Error("PaintErrors", "No TView in current pad");
00480       return;
00481    }
00482 
00483    Int_t  it;
00484 
00485    Double_t *xm = new Double_t[2];
00486    Double_t *ym = new Double_t[2];
00487 
00488    fGraph2D->SetLineStyle(fGraph2D->GetLineStyle());
00489    fGraph2D->SetLineWidth(fGraph2D->GetLineWidth());
00490    fGraph2D->SetLineColor(fGraph2D->GetLineColor());
00491    fGraph2D->TAttLine::Modify();
00492 
00493    for (it=0; it<fNpoints; it++) {
00494       if(fX[it] < fXmin || fX[it] > fXmax) continue;
00495       if(fY[it] < fYmin || fY[it] > fYmax) continue;
00496       if (fEX) {
00497          temp1[0] = fX[it]-fEX[it];
00498          temp1[1] = fY[it];
00499          temp1[2] = fZ[it];
00500          temp1[0] = TMath::Max(temp1[0],fXmin);
00501          temp1[1] = TMath::Max(temp1[1],fYmin);
00502          temp1[2] = TMath::Max(temp1[2],fZmin);
00503          temp1[2] = TMath::Min(temp1[2],fZmax);
00504          if (Hoption.Logx) temp1[0] = TMath::Log10(temp1[0]);
00505          if (Hoption.Logy) temp1[1] = TMath::Log10(temp1[1]);
00506          if (Hoption.Logz) temp1[2] = TMath::Log10(temp1[2]);
00507          view->WCtoNDC(temp1, &temp2[0]);
00508          xm[0] = temp2[0];
00509          ym[0] = temp2[1];
00510 
00511          temp1[0] = fX[it]+fEX[it];
00512          temp1[0] = TMath::Max(temp1[0],fXmin);
00513          if (Hoption.Logx) temp1[0] = TMath::Log10(temp1[0]);
00514          view->WCtoNDC(temp1, &temp2[0]);
00515          xm[1] = temp2[0];
00516          ym[1] = temp2[1];
00517          gPad->PaintPolyLine(2,xm,ym);
00518       }
00519       if (fEY) {
00520          temp1[0] = fX[it];
00521          temp1[1] = fY[it]-fEY[it];
00522          temp1[2] = fZ[it];
00523          temp1[0] = TMath::Max(temp1[0],fXmin);
00524          temp1[1] = TMath::Max(temp1[1],fYmin);
00525          temp1[2] = TMath::Max(temp1[2],fZmin);
00526          temp1[2] = TMath::Min(temp1[2],fZmax);
00527          if (Hoption.Logx) temp1[0] = TMath::Log10(temp1[0]);
00528          if (Hoption.Logy) temp1[1] = TMath::Log10(temp1[1]);
00529          if (Hoption.Logz) temp1[2] = TMath::Log10(temp1[2]);
00530          view->WCtoNDC(temp1, &temp2[0]);
00531          xm[0] = temp2[0];
00532          ym[0] = temp2[1];
00533 
00534          temp1[1] = fY[it]+fEY[it];
00535          temp1[1] = TMath::Max(temp1[1],fYmin);
00536          if (Hoption.Logy) temp1[1] = TMath::Log10(temp1[1]);
00537          view->WCtoNDC(temp1, &temp2[0]);
00538          xm[1] = temp2[0];
00539          ym[1] = temp2[1];
00540          gPad->PaintPolyLine(2,xm,ym);
00541       }
00542       if (fEZ) {
00543          temp1[0] = fX[it];
00544          temp1[1] = fY[it];
00545          temp1[2] = fZ[it]-fEZ[it];
00546          temp1[0] = TMath::Max(temp1[0],fXmin);
00547          temp1[1] = TMath::Max(temp1[1],fYmin);
00548          temp1[2] = TMath::Max(temp1[2],fZmin);
00549          temp1[2] = TMath::Min(temp1[2],fZmax);
00550          if (Hoption.Logx) temp1[0] = TMath::Log10(temp1[0]);
00551          if (Hoption.Logy) temp1[1] = TMath::Log10(temp1[1]);
00552          if (Hoption.Logz) temp1[2] = TMath::Log10(temp1[2]);
00553          view->WCtoNDC(temp1, &temp2[0]);
00554          xm[0] = temp2[0];
00555          ym[0] = temp2[1];
00556 
00557          temp1[2] = fZ[it]+fEZ[it];
00558          temp1[2] = TMath::Max(temp1[2],fZmin);
00559          temp1[2] = TMath::Min(temp1[2],fZmax);
00560          if (Hoption.Logz) temp1[2] = TMath::Log10(temp1[2]);
00561          view->WCtoNDC(temp1, &temp2[0]);
00562          xm[1] = temp2[0];
00563          ym[1] = temp2[1];
00564          gPad->PaintPolyLine(2,xm,ym);
00565       }
00566    }
00567    delete [] xm;
00568    delete [] ym;
00569 }
00570 
00571 
00572 //______________________________________________________________________________
00573 void TGraph2DPainter::PaintLevels(Int_t *t,Double_t *x, Double_t *y,
00574                            Int_t nblev, Double_t *glev)
00575 {
00576    // Paints one triangle.
00577    // nblev  = 0 : paint the color levels
00578    // nblev != 0 : paint the grid
00579 
00580    Int_t i, fillColor, ncolors, theColor0, theColor2;
00581 
00582    Int_t p0=t[0]-1;
00583    Int_t p1=t[1]-1;
00584    Int_t p2=t[2]-1;
00585    Double_t xl[2],yl[2];
00586    Double_t zl, r21, r20, r10;
00587    Double_t x0 = x[0]  , x2 = x[0];
00588    Double_t y0 = y[0]  , y2 = y[0];
00589    Double_t z0 = fZ[p0], z2 = fZ[p0];
00590    Double_t zmin = fZmin;
00591    Double_t zmax = fZmax;
00592 
00593    // Order along Z axis the points (xi,yi,zi) where "i" belongs to {0,1,2}
00594    // After this z0 < z1 < z2
00595    Int_t i0=0, i1=0, i2=0;
00596    if (fZ[p1]<=z0) {z0=fZ[p1]; x0=x[1]; y0=y[1]; i0=1;}
00597    if (fZ[p1]>z2)  {z2=fZ[p1]; x2=x[1]; y2=y[1]; i2=1;}
00598    if (fZ[p2]<=z0) {z0=fZ[p2]; x0=x[2]; y0=y[2]; i0=2;}
00599    if (fZ[p2]>z2)  {z2=fZ[p2]; x2=x[2]; y2=y[2]; i2=2;}
00600    i1 = 3-i2-i0;
00601    Double_t x1 = x[i1];
00602    Double_t y1 = y[i1];
00603    Double_t z1 = fZ[t[i1]-1];
00604 
00605    if (z0>zmax) z0 = zmax;
00606    if (z2>zmax) z2 = zmax;
00607    if (z0<zmin) z0 = zmin;
00608    if (z2<zmin) z2 = zmin;
00609    if (z1>zmax) z1 = zmax;
00610    if (z1<zmin) z1 = zmin;
00611 
00612    if (Hoption.Logz) {
00613       z0   = TMath::Log10(z0);
00614       z1   = TMath::Log10(z1);
00615       z2   = TMath::Log10(z2);
00616       zmin = TMath::Log10(zmin);
00617       zmax = TMath::Log10(zmax);
00618    }
00619 
00620    // zi  = Z values of the stripe number i
00621    // zip = Previous zi
00622    Double_t zi=0, zip=0;
00623 
00624    if (nblev <= 0) {
00625       // Paint the colors levels
00626 
00627       // Compute the color associated to z0 (theColor0) and z2 (theColor2)
00628       ncolors   = gStyle->GetNumberOfColors();
00629       theColor0 = (Int_t)( ((z0-zmin)/(zmax-zmin))*(ncolors-1) );
00630       theColor2 = (Int_t)( ((z2-zmin)/(zmax-zmin))*(ncolors-1) );
00631 
00632       // The stripes drawn to fill the triangles may have up to 5 points
00633       Double_t xp[5], yp[5];
00634 
00635       // rl = Ratio between z0 and z2 (long)
00636       // rs = Ratio between z0 and z1 or z1 and z2 (short)
00637       Double_t rl,rs;
00638 
00639       // ci = Color of the stripe number i
00640       // npf = number of point needed to draw the current stripe
00641       Int_t ci,npf;
00642 
00643       fillColor = fGraph2D->GetFillColor();
00644 
00645       // If the z0's color and z2's colors are the same, the whole triangle
00646       // can be painted in one go.
00647       if(theColor0 == theColor2) {
00648          fGraph2D->SetFillColor(gStyle->GetColorPalette(theColor0));
00649          fGraph2D->TAttFill::Modify();
00650          gPad->PaintFillArea(3,x,y);
00651 
00652       // The triangle must be painted with several colors
00653       } else {
00654          for(ci=theColor0; ci<=theColor2; ci++) {
00655             fGraph2D->SetFillColor(gStyle->GetColorPalette(ci));
00656             fGraph2D->TAttFill::Modify();
00657             if (ci==theColor0) {
00658                zi    = (((ci+1)*(zmax-zmin))/(ncolors-1))+zmin;
00659                xp[0] = x0;
00660                yp[0] = y0;
00661                rl    = (zi-z0)/(z2-z0);
00662                xp[1] = rl*(x2-x0)+x0;
00663                yp[1] = rl*(y2-y0)+y0;
00664                if (zi>=z1 || z0==z1) {
00665                   rs    = (zi-z1)/(z2-z1);
00666                   xp[2] = rs*(x2-x1)+x1;
00667                   yp[2] = rs*(y2-y1)+y1;
00668                   xp[3] = x1;
00669                   yp[3] = y1;
00670                   npf   = 4;
00671                } else {
00672                   rs    = (zi-z0)/(z1-z0);
00673                   xp[2] = rs*(x1-x0)+x0;
00674                   yp[2] = rs*(y1-y0)+y0;
00675                   npf   = 3;
00676                }
00677             } else if (ci==theColor2) {
00678                xp[0] = xp[1];
00679                yp[0] = yp[1];
00680                xp[1] = x2;
00681                yp[1] = y2;
00682                if (zi<z1 || z2==z1) {
00683                   xp[3] = xp[2];
00684                   yp[3] = yp[2];
00685                   xp[2] = x1;
00686                   yp[2] = y1;
00687                   npf   = 4;
00688                } else {
00689                   npf   = 3;
00690                }
00691             } else {
00692                zi    = (((ci+1)*(zmax-zmin))/(ncolors-1))+zmin;
00693                xp[0] = xp[1];
00694                yp[0] = yp[1];
00695                rl    = (zi-z0)/(z2-z0);
00696                xp[1] = rl*(x2-x0)+x0;
00697                yp[1] = rl*(y2-y0)+y0;
00698                if ( zi>=z1 && zip<=z1) {
00699                   xp[3] = x1;
00700                   yp[3] = y1;
00701                   xp[4] = xp[2];
00702                   yp[4] = yp[2];
00703                   npf   = 5;
00704                } else {
00705                   xp[3] = xp[2];
00706                   yp[3] = yp[2];
00707                   npf   = 4;
00708                }
00709                if (zi<z1) {
00710                   rs    = (zi-z0)/(z1-z0);
00711                   xp[2] = rs*(x1-x0)+x0;
00712                   yp[2] = rs*(y1-y0)+y0;
00713                } else {
00714                   rs    = (zi-z1)/(z2-z1);
00715                   xp[2] = rs*(x2-x1)+x1;
00716                   yp[2] = rs*(y2-y1)+y1;
00717                }
00718             }
00719             zip = zi;
00720             // Paint a stripe
00721             gPad->PaintFillArea(npf,xp,yp);
00722          }
00723       }
00724       fGraph2D->SetFillColor(fillColor);
00725       fGraph2D->TAttFill::Modify();
00726 
00727    } else {
00728       // Paint the grid levels
00729       fGraph2D->SetLineStyle(3);
00730       fGraph2D->TAttLine::Modify();
00731       for(i=0; i<nblev; i++){
00732          zl=glev[i];
00733          if(zl >= z0 && zl <=z2) {
00734             r21=(zl-z1)/(z2-z1);
00735             r20=(zl-z0)/(z2-z0);
00736             r10=(zl-z0)/(z1-z0);
00737             xl[0]=r20*(x2-x0)+x0;
00738             yl[0]=r20*(y2-y0)+y0;
00739             if(zl >= z1 && zl <=z2) {
00740                xl[1]=r21*(x2-x1)+x1;
00741                yl[1]=r21*(y2-y1)+y1;
00742             } else {
00743                xl[1]=r10*(x1-x0)+x0;
00744                yl[1]=r10*(y1-y0)+y0;
00745             }
00746             gPad->PaintPolyLine(2,xl,yl);
00747          }
00748       }
00749       fGraph2D->SetLineStyle(1);
00750       fGraph2D->TAttLine::Modify();
00751    }
00752 }
00753 
00754 
00755 //______________________________________________________________________________
00756 void TGraph2DPainter::PaintPolyMarker(Option_t *option)
00757 {
00758    // Paints the 2D graph as PaintPolyMarker
00759 
00760    Double_t temp1[3],temp2[3];
00761 
00762    TView *view = gPad->GetView();
00763    if (!view) {
00764       Error("PaintPolyMarker", "No TView in current pad");
00765       return;
00766    }
00767 
00768    TString opt = option;
00769    opt.ToLower();
00770    Bool_t markers0 = opt.Contains("p0");
00771    Bool_t colors   = opt.Contains("pcol");
00772    Int_t  ncolors  = gStyle->GetNumberOfColors();
00773    Int_t  it, theColor;
00774 
00775    Double_t *xm = new Double_t[fNpoints];
00776    Double_t *ym = new Double_t[fNpoints];
00777    Int_t    npd = 0;
00778    for (it=0; it<fNpoints; it++) {
00779       xm[it] = 0;
00780       ym[it] = 0;
00781       if(fX[it] < fXmin || fX[it] > fXmax) continue;
00782       if(fY[it] < fYmin || fY[it] > fYmax) continue;
00783       npd++;
00784       temp1[0] = fX[it];
00785       temp1[1] = fY[it];
00786       temp1[2] = fZ[it];
00787       temp1[0] = TMath::Max(temp1[0],fXmin);
00788       temp1[1] = TMath::Max(temp1[1],fYmin);
00789       temp1[2] = TMath::Max(temp1[2],fZmin);
00790       temp1[2] = TMath::Min(temp1[2],fZmax);
00791       if (Hoption.Logx) temp1[0] = TMath::Log10(temp1[0]);
00792       if (Hoption.Logy) temp1[1] = TMath::Log10(temp1[1]);
00793       if (Hoption.Logz) temp1[2] = TMath::Log10(temp1[2]);
00794       view->WCtoNDC(temp1, &temp2[0]);
00795       xm[it] = temp2[0];
00796       ym[it] = temp2[1];
00797    }
00798    if (markers0) {
00799       PaintPolyMarker0(npd,xm,ym);
00800    } else if (colors) {
00801       for (it=0; it<fNpoints; it++) {
00802          theColor = (Int_t)( ((fZ[it]-fZmin)/(fZmax-fZmin))*(ncolors-1) );
00803          fGraph2D->SetMarkerColor(gStyle->GetColorPalette(theColor));
00804          fGraph2D->TAttMarker::Modify();
00805          gPad->PaintPolyMarker(1,&xm[it],&ym[it]);
00806       }
00807    } else {
00808       fGraph2D->SetMarkerStyle(fGraph2D->GetMarkerStyle());
00809       fGraph2D->SetMarkerSize(fGraph2D->GetMarkerSize());
00810       fGraph2D->SetMarkerColor(fGraph2D->GetMarkerColor());
00811       fGraph2D->TAttMarker::Modify();
00812       gPad->PaintPolyMarker(npd,xm,ym);
00813    }
00814    delete [] xm;
00815    delete [] ym;
00816 }
00817 
00818 
00819 //______________________________________________________________________________
00820 void TGraph2DPainter::PaintPolyLine(Option_t * /* option */)
00821 {
00822    // Paints the 2D graph as PaintPolyLine
00823 
00824    Double_t temp1[3],temp2[3];
00825 
00826    TView *view = gPad->GetView();
00827    if (!view) {
00828       Error("PaintPolyLine", "No TView in current pad");
00829       return;
00830    }
00831 
00832    Int_t  it;
00833 
00834    Double_t *xm = new Double_t[fNpoints];
00835    Double_t *ym = new Double_t[fNpoints];
00836    Int_t    npd = 0;
00837    for (it=0; it<fNpoints; it++) {
00838       if(fX[it] < fXmin || fX[it] > fXmax) continue;
00839       if(fY[it] < fYmin || fY[it] > fYmax) continue;
00840       npd++;
00841       temp1[0] = fX[it];
00842       temp1[1] = fY[it];
00843       temp1[2] = fZ[it];
00844       temp1[0] = TMath::Max(temp1[0],fXmin);
00845       temp1[1] = TMath::Max(temp1[1],fYmin);
00846       temp1[2] = TMath::Max(temp1[2],fZmin);
00847       temp1[2] = TMath::Min(temp1[2],fZmax);
00848       if (Hoption.Logx) temp1[0] = TMath::Log10(temp1[0]);
00849       if (Hoption.Logy) temp1[1] = TMath::Log10(temp1[1]);
00850       if (Hoption.Logz) temp1[2] = TMath::Log10(temp1[2]);
00851       view->WCtoNDC(temp1, &temp2[0]);
00852       xm[it] = temp2[0];
00853       ym[it] = temp2[1];
00854    }
00855    fGraph2D->SetLineStyle(fGraph2D->GetLineStyle());
00856    fGraph2D->SetLineWidth(fGraph2D->GetLineWidth());
00857    fGraph2D->SetLineColor(fGraph2D->GetLineColor());
00858    fGraph2D->TAttLine::Modify();
00859    gPad->PaintPolyLine(npd,xm,ym);
00860    delete [] xm;
00861    delete [] ym;
00862 }
00863 
00864 
00865 //______________________________________________________________________________
00866 void TGraph2DPainter::PaintPolyMarker0(Int_t n, Double_t *x, Double_t *y)
00867 {
00868    // Paints a circle at each vertex. Each circle background is white.
00869 
00870    fGraph2D->SetMarkerSize(fGraph2D->GetMarkerSize());
00871    Int_t mc = fGraph2D->GetMarkerColor();
00872    for (Int_t i=0; i<n; i++) {
00873       fGraph2D->SetMarkerStyle(20);
00874       fGraph2D->SetMarkerColor(0);
00875       fGraph2D->TAttMarker::Modify();
00876       gPad->PaintPolyMarker(1,&x[i],&y[i]);
00877       fGraph2D->SetMarkerStyle(24);
00878       fGraph2D->SetMarkerColor(mc);
00879       fGraph2D->TAttMarker::Modify();
00880       gPad->PaintPolyMarker(1,&x[i],&y[i]);
00881    }
00882 }
00883 
00884 
00885 //______________________________________________________________________________
00886 void TGraph2DPainter::PaintTriangles(Option_t *option)
00887 {
00888    // Paints the 2D graph as triangles
00889 
00890    Double_t x[4], y[4], temp1[3],temp2[3];
00891    Int_t it,t[3];
00892    Int_t *order = 0;
00893    Double_t *dist = 0;
00894 
00895    TView *view = gPad->GetView();
00896    if (!view) {
00897       Error("PaintTriangles", "No TView in current pad");
00898       return;
00899    }
00900 
00901    TString opt = option;
00902    opt.ToLower();
00903    Bool_t tri1      = opt.Contains("tri1");
00904    Bool_t tri2      = opt.Contains("tri2");
00905    Bool_t markers   = opt.Contains("p");
00906    Bool_t markers0  = opt.Contains("p0");
00907    Bool_t wire      = opt.Contains("w");
00908 
00909    // Define the grid levels drawn on the triangles.
00910    // The grid levels are aligned on the Z axis' main tick marks.
00911    Int_t nblev=0;
00912    Double_t *glev=0;
00913    if (!tri1 && !tri2 && !wire) {
00914       Int_t ndivz = gCurrentHist->GetZaxis()->GetNdivisions()%100;
00915       Int_t nbins;
00916       Double_t binLow, binHigh, binWidth;
00917 
00918       // Find the main tick marks positions.
00919       Double_t *r0 = view->GetRmin();
00920       Double_t *r1 = view->GetRmax();
00921 
00922       if (ndivz > 0) {
00923          THLimitsFinder::Optimize(r0[2], r1[2], ndivz,
00924                                   binLow, binHigh, nbins, binWidth, " ");
00925       } else {
00926          nbins = TMath::Abs(ndivz);
00927          binLow = r0[2];
00928          binHigh = r1[2];
00929          binWidth = (binHigh-binLow)/nbins;
00930       }
00931       // Define the grid levels
00932       nblev = nbins+1;
00933       glev = new Double_t[nblev];
00934       for (Int_t i = 0; i < nblev; ++i) glev[i] = binLow+i*binWidth;
00935    }
00936 
00937    // Initialize the levels on the Z axis
00938    if (tri1 || tri2) {
00939       Int_t ndiv   = gCurrentHist->GetContour();
00940       if (ndiv == 0 ) {
00941          ndiv = gStyle->GetNumberContours();
00942          gCurrentHist->SetContour(ndiv);
00943       }
00944       if (gCurrentHist->TestBit(TH1::kUserContour) == 0) gCurrentHist->SetContour(ndiv);
00945    }
00946 
00947    // For each triangle, compute the distance between the triangle centre
00948    // and the back planes. Then these distances are sorted in order to draw
00949    // the triangles from back to front.
00950    if (!fNdt) FindTriangles();
00951    Double_t cp = TMath::Cos(view->GetLongitude()*TMath::Pi()/180.);
00952    Double_t sp = TMath::Sin(view->GetLongitude()*TMath::Pi()/180.);
00953    order = new Int_t[fNdt];
00954    dist  = new Double_t[fNdt];
00955    Double_t xd,yd;
00956    Int_t p, n, m;
00957    Bool_t o = kFALSE;
00958    for (it=0; it<fNdt; it++) {
00959       p = fPTried[it];
00960       n = fNTried[it];
00961       m = fMTried[it];
00962       xd = (fXN[p]+fXN[n]+fXN[m])/3;
00963       yd = (fYN[p]+fYN[n]+fYN[m])/3;
00964       if ((cp >= 0) && (sp >= 0.)) {
00965          dist[it] = -(fXNmax-xd+fYNmax-yd);
00966       } else if ((cp <= 0) && (sp >= 0.)) {
00967          dist[it] = -(fXNmax-xd+yd-fYNmin);
00968          o = kTRUE;
00969       } else if ((cp <= 0) && (sp <= 0.)) {
00970          dist[it] = -(xd-fXNmin+yd-fYNmin);
00971       } else {
00972          dist[it] = -(xd-fXNmin+fYNmax-yd);
00973          o = kTRUE;
00974       }
00975    }
00976    TMath::Sort(fNdt, dist, order, o);
00977 
00978    // Draw the triangles and markers if requested
00979    fGraph2D->SetFillColor(fGraph2D->GetFillColor());
00980    Int_t fs = fGraph2D->GetFillStyle();
00981    fGraph2D->SetFillStyle(1001);
00982    fGraph2D->TAttFill::Modify();
00983    fGraph2D->SetLineColor(fGraph2D->GetLineColor());
00984    fGraph2D->TAttLine::Modify();
00985    int lst = fGraph2D->GetLineStyle();
00986    for (it=0; it<fNdt; it++) {
00987       t[0] = fPTried[order[it]];
00988       t[1] = fNTried[order[it]];
00989       t[2] = fMTried[order[it]];
00990       for (Int_t k=0; k<3; k++) {
00991          if(fX[t[k]-1] < fXmin || fX[t[k]-1] > fXmax) goto endloop;
00992          if(fY[t[k]-1] < fYmin || fY[t[k]-1] > fYmax) goto endloop;
00993          temp1[0] = fX[t[k]-1];
00994          temp1[1] = fY[t[k]-1];
00995          temp1[2] = fZ[t[k]-1];
00996          temp1[0] = TMath::Max(temp1[0],fXmin);
00997          temp1[1] = TMath::Max(temp1[1],fYmin);
00998          temp1[2] = TMath::Max(temp1[2],fZmin);
00999          temp1[2] = TMath::Min(temp1[2],fZmax);
01000          if (Hoption.Logx) temp1[0] = TMath::Log10(temp1[0]);
01001          if (Hoption.Logy) temp1[1] = TMath::Log10(temp1[1]);
01002          if (Hoption.Logz) temp1[2] = TMath::Log10(temp1[2]);
01003          view->WCtoNDC(temp1, &temp2[0]);
01004          x[k] = temp2[0];
01005          y[k] = temp2[1];
01006       }
01007       x[3] = x[0];
01008       y[3] = y[0];
01009       if (tri1 || tri2) PaintLevels(t,x,y);
01010       if (!tri1 && !tri2 && !wire) {
01011          gPad->PaintFillArea(3,x,y);
01012          PaintLevels(t,x,y,nblev,glev);
01013       }
01014       if (!tri2) gPad->PaintPolyLine(4,x,y);
01015       if (markers) {
01016          if (markers0) {
01017             PaintPolyMarker0(3,x,y);
01018          } else {
01019             fGraph2D->SetMarkerStyle(fGraph2D->GetMarkerStyle());
01020             fGraph2D->SetMarkerSize(fGraph2D->GetMarkerSize());
01021             fGraph2D->SetMarkerColor(fGraph2D->GetMarkerColor());
01022             fGraph2D->TAttMarker::Modify();
01023             gPad->PaintPolyMarker(3,x,y);
01024          }
01025       }
01026 endloop:
01027       continue;
01028    }
01029    fGraph2D->SetFillStyle(fs);
01030    fGraph2D->SetLineStyle(lst);
01031    fGraph2D->TAttLine::Modify();
01032    fGraph2D->TAttFill::Modify();
01033    delete [] order;
01034    delete [] dist;
01035    if (glev) delete [] glev;
01036 }

Generated on Tue Jul 5 14:24:29 2011 for ROOT_528-00b_version by  doxygen 1.5.1