TPie.cxx

Go to the documentation of this file.
00001 // @(#)root/graf:$Id: TPie.cxx 31025 2009-11-08 16:42:42Z brun $
00002 // Author: Guido Volpi, Olivier Couet 03/11/2006
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 "TPie.h"
00013 #include "TPieSlice.h"
00014 
00015 #include <Riostream.h>
00016 #include <TROOT.h>
00017 #include <TVirtualPad.h>
00018 #include <TArc.h>
00019 #include <TLegend.h>
00020 #include <TMath.h>
00021 #include <TStyle.h>
00022 #include <TLatex.h>
00023 #include <TPaveText.h>
00024 #include <TH1.h>
00025 #include <TColor.h>
00026 
00027 ClassImp(TPie)
00028 
00029 
00030 //______________________________________________________________________________
00031 //
00032 // Draw a Pie Chart
00033 //
00034 // The macro $ROOTSYS/tutorials/graphics/piechart.C produces the following
00035 // picture:
00036 //Begin_Html
00037 /*
00038 <img src="gif/piechart.gif">
00039 */
00040 //End_Html
00041 //
00042 
00043 Double_t gX             = 0; // Temporary pie X position.
00044 Double_t gY             = 0; // Temporary pie Y position.
00045 Double_t gRadius        = 0; // Temporary pie Radius of the TPie.
00046 Double_t gRadiusOffset  = 0; // Temporary slice's radial offset.
00047 Double_t gAngularOffset = 0; // Temporary slice's angular offset.
00048 Bool_t   gIsUptSlice    = kFALSE; // True if a slice in the TPie should
00049                                   // be updated.
00050 Int_t    gCurrent_slice = -1;// Current slice under mouse.
00051 Double_t gCurrent_phi1  = 0; // Phimin of the current slice.
00052 Double_t gCurrent_phi2  = 0; // Phimax of the current slice.
00053 Double_t gCurrent_rad   = 0; // Current distance from the vertex of the
00054                              // current slice.
00055 Double_t gCurrent_x     = 0; // Current x in the pad metric.
00056 Double_t gCurrent_y     = 0; // Current y in the pad metric.
00057 Double_t gCurrent_ang   = 0; // Current angular, within current_phi1
00058                                     // and current_phi2.
00059 
00060 //______________________________________________________________________________
00061 TPie::TPie() : TNamed()
00062 {
00063    // Default constructor.
00064 
00065    Init(1, 0, 0.5, 0.5, 0.4);
00066 }
00067 
00068 
00069 //______________________________________________________________________________
00070 TPie::TPie(const char *name, const char *title, Int_t npoints) :
00071            TNamed(name,title)
00072 {
00073    // This constructor creates a pie chart when only the number of
00074    // the slices is known. The number of slices is fixed.
00075 
00076    Init(npoints, 0, 0.5, 0.5, 0.4);
00077 }
00078 
00079 
00080 //______________________________________________________________________________
00081 TPie::TPie(const char *name, const char *title,
00082            Int_t npoints, Double_t *vals,
00083            Int_t *colors, const char *lbls[]) : TNamed(name,title)
00084 {
00085    // Normal constructor. The 1st and 2nd parameters are the name of the object
00086    // and its title.
00087    //
00088    // The number of points passed at this point is used to allocate the memory.
00089    //
00090    // Slices values are given as Double_t.
00091    //
00092    // The 4th elements is an array containing, in double precision format,
00093    // the value of each slice. It is also possible to specify the filled color
00094    // of each slice. If the color array is not specfied the slices are colored
00095    // using a color sequence in the standard palette.
00096 
00097    Init(npoints, 0, 0.5, 0.5, 0.4);
00098    for (Int_t i=0; i<fNvals; ++i) fPieSlices[i]->SetValue(vals[i]);
00099 
00100    SetFillColors(colors);
00101    SetLabels(lbls);
00102 }
00103 
00104 
00105 //______________________________________________________________________________
00106 TPie::TPie(const char *name,
00107            const char *title,
00108            Int_t npoints, Float_t *vals,
00109            Int_t *colors, const char *lbls[]) : TNamed(name,title)
00110 {
00111    // Normal constructor (Float_t).
00112 
00113    Init(npoints, 0, 0.5, 0.5, 0.4);
00114    for (Int_t i=0; i<fNvals; ++i) fPieSlices[i]->SetValue(vals[i]);
00115 
00116    SetFillColors(colors);
00117    SetLabels(lbls);
00118 }
00119 
00120 
00121 //______________________________________________________________________________
00122 TPie::TPie(const TH1 *h) : TNamed(h->GetName(),h->GetTitle())
00123 {
00124    // Constructor from a TH1
00125 
00126    Int_t i;
00127 
00128    TAxis *axis = h->GetXaxis();
00129    Int_t first = axis->GetFirst();
00130    Int_t last  = axis->GetLast();
00131    Int_t np    = last-first+1;
00132    Init(np, 0, 0.5, 0.5, 0.4);
00133 
00134    for (i=first; i<=last; ++i) fPieSlices[i-first]->SetValue(h->GetBinContent(i));
00135    if (axis->GetLabels()) {
00136       for (i=first; i<=last; ++i) fPieSlices[i-first]->SetTitle(axis->GetBinLabel(i));
00137    } else {
00138       SetLabelFormat("%val");
00139    }
00140    SetTextSize(axis->GetLabelSize());
00141    SetTextColor(axis->GetLabelColor());
00142    SetTextFont(axis->GetLabelFont());
00143 }
00144 
00145 
00146 //______________________________________________________________________________
00147 TPie::TPie(const TPie &cpy) : TNamed(cpy), TAttText(cpy)
00148 {
00149    // Copy constructor.
00150 
00151    Init(cpy.fNvals, cpy.fAngularOffset, cpy.fX, cpy.fY, cpy.fRadius);
00152 
00153    for (Int_t i=0;i<fNvals;++i) {
00154       fPieSlices[i] = cpy.fPieSlices[i];
00155    }
00156 }
00157 
00158 
00159 //______________________________________________________________________________
00160 TPie::~TPie()
00161 {
00162    // Destructor.
00163 
00164    if (fNvals>0) {
00165       delete [] fPieSlices;
00166    }
00167 
00168    if (fSlices) delete [] fSlices;
00169    if (fLegend) delete fLegend;
00170 }
00171 
00172 
00173 //______________________________________________________________________________
00174 Int_t TPie::DistancetoPrimitive(Int_t px, Int_t py)
00175 {
00176    // Evaluate the distance to the chart in gPad.
00177 
00178    Int_t dist = 9999;
00179 
00180    gCurrent_slice = DistancetoSlice(px,py);
00181    if ( gCurrent_slice>=0 ) {
00182       if (gCurrent_rad<=fRadius) {
00183          dist = 0;
00184       }
00185    }
00186 
00187    return dist;
00188 }
00189 
00190 
00191 //______________________________________________________________________________
00192 Int_t TPie::DistancetoSlice(Int_t px, Int_t py)
00193 {
00194    // Returns the slice number at the pixel position (px,py).
00195    // Returns -1 if no slice is picked.
00196    //
00197    // Used by DistancetoPrimitive.
00198 
00199    MakeSlices();
00200 
00201    Int_t result(-1);
00202 
00203    // coordinates
00204    Double_t xx = gPad->AbsPixeltoX(px); //gPad->PadtoX(gPad->AbsPixeltoX(px));
00205    Double_t yy = gPad->AbsPixeltoY(py); //gPad->PadtoY(gPad->AbsPixeltoY(py));
00206 
00207    // XY metric
00208    Double_t radX  = fRadius;
00209    Double_t radY  = fRadius;
00210    Double_t radXY = 1.;
00211    if (fIs3D==kTRUE) {
00212       radXY = TMath::Sin(fAngle3D/180.*TMath::Pi());
00213       radY  = radXY*radX;
00214    }
00215 
00216    Double_t phimin;
00217    Double_t cphi;
00218    Double_t phimax;
00219 
00220    Float_t dPxl = (gPad->PixeltoY(0)-gPad->PixeltoY(1))/radY;
00221    for (Int_t i=0;i<fNvals;++i) {
00222       fPieSlices[i]->SetIsActive(kFALSE);
00223 
00224       if (gIsUptSlice && gCurrent_slice!=i) continue;
00225 
00226       // Angles' values for this slice
00227       phimin = fSlices[2*i  ]*TMath::Pi()/180.;
00228       cphi   = fSlices[2*i+1]*TMath::Pi()/180.;
00229       phimax = fSlices[2*i+2]*TMath::Pi()/180.;
00230 
00231       Double_t radOffset = fPieSlices[i]->GetRadiusOffset();
00232 
00233       Double_t dx  = (xx-fX-radOffset*TMath::Cos(cphi))/radX;
00234       Double_t dy  = (yy-fY-radOffset*TMath::Sin(cphi)*radXY)/radY;
00235 
00236       if (TMath::Abs(dy)<dPxl) dy = dPxl;
00237 
00238       Double_t ang = TMath::ATan2(dy,dx);
00239       if (ang<0) ang += TMath::TwoPi();
00240 
00241       Double_t dist = TMath::Sqrt(dx*dx+dy*dy);
00242 
00243       if ( ((ang>=phimin && ang <= phimax) || (phimax>TMath::TwoPi() &&
00244             ang+TMath::TwoPi()>=phimin && ang+TMath::TwoPi()<phimax)) &&
00245             dist<=1.) { // if true the pointer is in the slice region
00246 
00247          gCurrent_x    = dx;
00248          gCurrent_y    = dy;
00249          gCurrent_ang  = ang;
00250          gCurrent_phi1 = phimin;
00251          gCurrent_phi2 = phimax;
00252          gCurrent_rad  = dist*fRadius;
00253 
00254          if (dist<.95 && dist>.65) {
00255             Double_t range = phimax-phimin;
00256             Double_t lang = ang-phimin;
00257             Double_t rang = phimax-ang;
00258             if (lang<0) lang += TMath::TwoPi();
00259             else if (lang>=TMath::TwoPi()) lang -= TMath::TwoPi();
00260             if (rang<0) rang += TMath::TwoPi();
00261             else if (rang>=TMath::TwoPi()) rang -= TMath::TwoPi();
00262 
00263             if (lang/range<.25 || rang/range<.25) {
00264                fPieSlices[i]->SetIsActive(kTRUE);
00265                result = -1;
00266             }
00267             else result  = i;
00268          } else {
00269             result = i;
00270          }
00271 
00272          break;
00273       }
00274    }
00275    return result;
00276 }
00277 
00278 
00279 //______________________________________________________________________________
00280 void TPie::Draw(Option_t *option)
00281 {
00282    // Draw the pie chart.
00283    //
00284    // The possible options are listed in the TPie::Paint() method.
00285 
00286    TString soption(option);
00287    soption.ToLower();
00288 
00289    if (soption.Length()==0) soption = "l";
00290 
00291    if (gPad) {
00292       if (!gPad->IsEditable()) gROOT->MakeDefCanvas();
00293       if (!soption.Contains("same")) {
00294          gPad->Clear();
00295          gPad->Range(0.,0.,1.,1.);
00296       }
00297    }
00298 
00299    for (Int_t i=0;i<fNvals;++i) fPieSlices[i]->AppendPad();
00300    AppendPad(soption.Data());
00301 }
00302 
00303 
00304 //______________________________________________________________________________
00305 void TPie::DrawGhost()
00306 {
00307    // This method is for internal use. It is used by Execute event to draw the
00308    // outline of "this" TPie. Used when the opaque movements are not permitted.
00309 
00310    MakeSlices();
00311 
00312    // XY metric
00313    Double_t radX  = fRadius;
00314    Double_t radY  = fRadius;
00315    Double_t radXY = 1.;
00316    if (fIs3D) {
00317       radXY = TMath::Sin(fAngle3D/180.*TMath::Pi());
00318       radY  = radXY*radX;
00319    }
00320 
00321    for (Int_t i=0;i<fNvals&&fIs3D==kTRUE;++i) {
00322       Float_t minphi = (fSlices[i*2]+gAngularOffset+.5)*TMath::Pi()/180.;
00323       Float_t avgphi = (fSlices[i*2+1]+gAngularOffset)*TMath::Pi()/180.;
00324       Float_t maxphi = (fSlices[i*2+2]+gAngularOffset-.5)*TMath::Pi()/180.;
00325 
00326       Double_t radOffset = (i == gCurrent_slice ? gRadiusOffset : fPieSlices[i]->GetRadiusOffset());
00327       Double_t x0 = gX+radOffset*TMath::Cos(avgphi);
00328       Double_t y0 = gY+radOffset*TMath::Sin(avgphi)*radXY-fHeight;
00329 
00330       gVirtualX->DrawLine( gPad->XtoAbsPixel(x0), gPad->YtoAbsPixel(y0),
00331                            gPad->XtoAbsPixel(x0+gRadius*TMath::Cos(minphi)),
00332                            gPad->YtoAbsPixel(y0+gRadius*TMath::Sin(minphi)*radXY) );
00333 
00334       Int_t ndiv = 10;
00335       Double_t dphi = (maxphi-minphi)/ndiv;
00336 
00337       if (dphi>.15) ndiv = (Int_t) ((maxphi-minphi)/.15);
00338       dphi = (maxphi-minphi)/ndiv;
00339 
00340       // Loop to draw the arc
00341       for (Int_t j=0;j<ndiv;++j) {
00342          Double_t phi = minphi+dphi*j;
00343          gVirtualX->DrawLine( gPad->XtoAbsPixel(x0+gRadius*TMath::Cos(phi)),
00344                               gPad->YtoAbsPixel(y0+gRadius*TMath::Sin(phi)*radXY),
00345                               gPad->XtoAbsPixel(x0+gRadius*TMath::Cos(phi+dphi)),
00346                               gPad->YtoAbsPixel(y0+gRadius*TMath::Sin(phi+dphi)*radXY));
00347       }
00348 
00349       gVirtualX->DrawLine( gPad->XtoAbsPixel(x0+gRadius*TMath::Cos(maxphi)),
00350                            gPad->YtoAbsPixel(y0+gRadius*TMath::Sin(maxphi)*radXY),
00351                            gPad->XtoAbsPixel(x0), gPad->YtoAbsPixel(y0) );
00352 
00353       gVirtualX->DrawLine(gPad->XtoAbsPixel(x0),
00354                           gPad->YtoAbsPixel(y0),
00355                           gPad->XtoAbsPixel(x0),
00356                           gPad->YtoAbsPixel(y0+fHeight));
00357       gVirtualX->DrawLine(gPad->XtoAbsPixel(x0+gRadius*TMath::Cos(minphi)),
00358                           gPad->YtoAbsPixel(y0+gRadius*TMath::Sin(minphi)*radXY),
00359                           gPad->XtoAbsPixel(x0+gRadius*TMath::Cos(minphi)),
00360                           gPad->YtoAbsPixel(y0+gRadius*TMath::Sin(minphi)*radXY+fHeight));
00361       gVirtualX->DrawLine(gPad->XtoAbsPixel(x0+gRadius*TMath::Cos(maxphi)),
00362                           gPad->YtoAbsPixel(y0+gRadius*TMath::Sin(maxphi)*radXY),
00363                           gPad->XtoAbsPixel(x0+gRadius*TMath::Cos(maxphi)),
00364                           gPad->YtoAbsPixel(y0+gRadius*TMath::Sin(maxphi)*radXY+fHeight));
00365    }
00366 
00367 
00368    // Loop over slices
00369    for (Int_t i=0;i<fNvals;++i) {
00370       Float_t minphi = (fSlices[i*2]+gAngularOffset+.5)*TMath::Pi()/180.;
00371       Float_t avgphi = (fSlices[i*2+1]+gAngularOffset)*TMath::Pi()/180.;
00372       Float_t maxphi = (fSlices[i*2+2]+gAngularOffset-.5)*TMath::Pi()/180.;
00373 
00374       Double_t radOffset = (i == gCurrent_slice ? gRadiusOffset : fPieSlices[i]->GetRadiusOffset());
00375       Double_t x0 = gX+radOffset*TMath::Cos(avgphi);
00376       Double_t y0 = gY+radOffset*TMath::Sin(avgphi)*radXY;
00377 
00378       gVirtualX->DrawLine( gPad->XtoAbsPixel(x0), gPad->YtoAbsPixel(y0),
00379                            gPad->XtoAbsPixel(x0+gRadius*TMath::Cos(minphi)),
00380                            gPad->YtoAbsPixel(y0+gRadius*TMath::Sin(minphi)*radXY) );
00381 
00382 
00383       Int_t ndiv = 10;
00384       Double_t dphi = (maxphi-minphi)/ndiv;
00385 
00386       if (dphi>.15) ndiv = (Int_t) ((maxphi-minphi)/.15);
00387       dphi = (maxphi-minphi)/ndiv;
00388 
00389       // Loop to draw the arc
00390       for (Int_t j=0;j<ndiv;++j) {
00391          Double_t phi = minphi+dphi*j;
00392          gVirtualX->DrawLine( gPad->XtoAbsPixel(x0+gRadius*TMath::Cos(phi)),
00393                               gPad->YtoAbsPixel(y0+gRadius*TMath::Sin(phi)*radXY),
00394                               gPad->XtoAbsPixel(x0+gRadius*TMath::Cos(phi+dphi)),
00395                               gPad->YtoAbsPixel(y0+gRadius*TMath::Sin(phi+dphi)*radXY));
00396       }
00397 
00398       gVirtualX->DrawLine( gPad->XtoAbsPixel(x0+gRadius*TMath::Cos(maxphi)),
00399                            gPad->YtoAbsPixel(y0+gRadius*TMath::Sin(maxphi)*radXY),
00400                            gPad->XtoAbsPixel(x0), gPad->YtoAbsPixel(y0) );
00401    }
00402 }
00403 
00404 
00405 //______________________________________________________________________________
00406 void TPie::ExecuteEvent(Int_t event, Int_t px, Int_t py)
00407 {
00408    // Execute the mouse events.
00409 
00410    if (!gPad) return;
00411    if (!gPad->IsEditable() && event != kMouseEnter) return;
00412 
00413    if (gCurrent_slice<=-10) {
00414       gPad->SetCursor(kCross);
00415       return;
00416    }
00417 
00418    MakeSlices();
00419 
00420    static bool isMovingPie(kFALSE);
00421    static bool isMovingSlice(kFALSE);
00422    static bool isResizing(kFALSE);
00423    static bool isRotating(kFALSE);
00424    static bool onBorder(kFALSE);
00425    bool isRedrawing(kFALSE);
00426    static Int_t prev_event(-1);
00427    static Int_t oldpx, oldpy;
00428 
00429    // Portion of pie considered as "border"
00430    const Double_t dr     = gPad->PixeltoX(3);
00431    const Double_t minRad = gPad->PixeltoX(10);
00432 
00433    // Angular divisions in radial direction
00434    const Double_t angstep1 = 0.5*TMath::PiOver4();
00435    const Double_t angstep2 = 1.5*TMath::PiOver4();
00436    const Double_t angstep3 = 2.5*TMath::PiOver4();
00437    const Double_t angstep4 = 3.5*TMath::PiOver4();
00438    const Double_t angstep5 = 4.5*TMath::PiOver4();
00439    const Double_t angstep6 = 5.5*TMath::PiOver4();
00440    const Double_t angstep7 = 6.5*TMath::PiOver4();
00441    const Double_t angstep8 = 7.5*TMath::PiOver4();
00442 
00443    // XY metric
00444    Double_t radX  = fRadius;
00445    Double_t radY  = fRadius;
00446    Double_t radXY = 1.;
00447    if (fIs3D==kTRUE) {
00448       radXY = TMath::Sin(fAngle3D/180.*TMath::Pi());
00449       radY  = radXY*radX;
00450    }
00451 
00452    Int_t dx, dy;
00453    Double_t mdx, mdy;
00454 
00455    switch(event) {
00456       case kButton1Down:
00457          // Change cursor to show pie's movement.
00458          gVirtualX->SetLineColor(1);
00459          gVirtualX->SetLineWidth(2);
00460 
00461          // Current center and radius.
00462          gX             = fX;
00463          gY             = fY;
00464          gRadius        = fRadius;
00465          gRadiusOffset  = fPieSlices[gCurrent_slice]->GetRadiusOffset();
00466          gAngularOffset = 0;
00467          gIsUptSlice    = kTRUE;
00468 
00469          prev_event = kButton1Down;
00470 
00471       case kMouseMotion:
00472          if (gCurrent_rad>=fRadius-2.*dr && gCurrent_rad<=fRadius+dr
00473                && !isMovingPie && !isMovingSlice && !isResizing) {
00474             if (gCurrent_ang>=angstep8 || gCurrent_ang<angstep1)
00475                gPad->SetCursor(kRightSide);
00476             else if (gCurrent_ang>=angstep1 && gCurrent_ang<angstep2)
00477                gPad->SetCursor(kTopRight);
00478             else if (gCurrent_ang>=angstep2 && gCurrent_ang<angstep3)
00479                gPad->SetCursor(kTopSide);
00480             else if (gCurrent_ang>=angstep3 && gCurrent_ang<angstep4)
00481                gPad->SetCursor(kTopLeft);
00482             else if (gCurrent_ang>=angstep4 && gCurrent_ang<=angstep5)
00483                gPad->SetCursor(kLeftSide);
00484             else if (gCurrent_ang>=angstep5 && gCurrent_ang<angstep6)
00485                gPad->SetCursor(kBottomLeft);
00486             else if (gCurrent_ang>=angstep6 && gCurrent_ang<angstep7)
00487                gPad->SetCursor(kBottomSide);
00488             else if (gCurrent_ang>=angstep7 && gCurrent_ang<angstep8)
00489                gPad->SetCursor(kBottomRight);
00490             onBorder = kTRUE;
00491          } else {
00492             onBorder = kFALSE;
00493             if (gCurrent_rad>fRadius*.6) {
00494                gPad->SetCursor(kPointer);
00495             } else if (gCurrent_rad<=fRadius*.3) {
00496                gPad->SetCursor(kHand);
00497             } else if (gCurrent_rad<=fRadius*.6 && gCurrent_rad>=fRadius*.3) {
00498                gPad->SetCursor(kRotate);
00499             }
00500          }
00501          oldpx = px;
00502          oldpy = py;
00503          if (isMovingPie || isMovingSlice) gPad->SetCursor(kMove);
00504          break;
00505 
00506       case kButton1Motion:
00507          if (!isMovingSlice || !isMovingPie || !isResizing || !isRotating) {
00508             if (prev_event==kButton1Down) {
00509                if (onBorder) {
00510                   isResizing = kTRUE;
00511                } else if (gCurrent_rad>=fRadius*.6 && gCurrent_slice>=0) {
00512                   isMovingSlice = kTRUE;
00513                } else if (gCurrent_rad<=fRadius*.3) {
00514                   isMovingPie = kTRUE;
00515                } else if (gCurrent_rad<fRadius*.6 && gCurrent_rad>fRadius*.3) {
00516                   isRotating = kTRUE;
00517                }
00518             }
00519          }
00520 
00521          dx = px-oldpx;
00522          dy = py-oldpy;
00523 
00524          mdx = gPad->PixeltoX(dx);
00525          mdy = gPad->PixeltoY(dy);
00526 
00527          if (isMovingPie || isMovingSlice) {
00528             gPad->SetCursor(kMove);
00529             if (isMovingSlice) {
00530                Float_t avgphi = fSlices[gCurrent_slice*2+1]*TMath::Pi()/180.;
00531 
00532                if (!gPad->OpaqueMoving()) DrawGhost();
00533 
00534                gRadiusOffset += TMath::Cos(avgphi)*mdx +TMath::Sin(avgphi)*mdy/radXY;
00535                if (gRadiusOffset<0) gRadiusOffset = .0;
00536                gIsUptSlice         = kTRUE;
00537 
00538                if (!gPad->OpaqueMoving()) DrawGhost();
00539             } else {
00540                if (!gPad->OpaqueMoving()) DrawGhost();
00541 
00542                gX += mdx;
00543                gY += mdy;
00544 
00545                if (!gPad->OpaqueMoving()) DrawGhost();
00546             }
00547          } else if (isResizing) {
00548             if (!gPad->OpaqueResizing()) DrawGhost();
00549 
00550             Float_t dr1 = mdx*TMath::Cos(gCurrent_ang)+mdy*TMath::Sin(gCurrent_ang)/radXY;
00551             if (gRadius+dr1>=minRad) {
00552                gRadius += dr1;
00553             } else {
00554                gRadius = minRad;
00555             }
00556 
00557             if (!gPad->OpaqueResizing()) DrawGhost();
00558          } else if (isRotating) {
00559             if (!gPad->OpaqueMoving()) DrawGhost();
00560 
00561             Double_t xx = gPad->AbsPixeltoX(px);
00562             Double_t yy = gPad->AbsPixeltoY(py);
00563 
00564             Double_t dx1  = xx-gX;
00565             Double_t dy1  = yy-gY;
00566 
00567             Double_t ang = TMath::ATan2(dy1,dx1);
00568             if (ang<0) ang += TMath::TwoPi();
00569 
00570             gAngularOffset = (ang-gCurrent_ang)*180/TMath::Pi();
00571 
00572             if (!gPad->OpaqueMoving()) DrawGhost();
00573          }
00574 
00575          oldpx = px;
00576          oldpy = py;
00577 
00578          if ( ((isMovingPie || isMovingSlice || isRotating) && gPad->OpaqueMoving()) ||
00579                (isResizing && gPad->OpaqueResizing()) ) {
00580             isRedrawing = kTRUE;
00581             event = kButton1Up;
00582          }
00583          else break;
00584 
00585       case kButton1Up:
00586          if (!isRedrawing) {
00587             prev_event = kButton1Up;
00588             gIsUptSlice = kFALSE;
00589          }
00590 
00591          if (gROOT->IsEscaped()) {
00592             gROOT->SetEscape(kFALSE);
00593             gIsUptSlice = kFALSE;
00594             isRedrawing = kFALSE;
00595             break;
00596          }
00597 
00598          fX      = gX;
00599          fY      = gY;
00600          fRadius = gRadius;
00601          fPieSlices[gCurrent_slice]->SetRadiusOffset(gRadiusOffset);
00602          SetAngularOffset(fAngularOffset+gAngularOffset);
00603 
00604          if (isRedrawing && (isMovingPie || isMovingSlice)) gPad->SetCursor(kMove);
00605 
00606          if (isMovingPie)   isMovingPie   = kFALSE;
00607          if (isMovingSlice) isMovingSlice = kFALSE;
00608          if (isResizing)    isResizing    = kFALSE;
00609          if (isRotating)    {
00610             isRotating = kFALSE;
00611             // this is important mainly when OpaqueMoving==kTRUE
00612             gCurrent_ang += gAngularOffset/180.*TMath::Pi();
00613          }
00614 
00615          gPad->Modified(kTRUE);
00616 
00617 
00618          isRedrawing = kFALSE;
00619          gIsUptSlice = kFALSE;
00620 
00621          gVirtualX->SetLineColor(-1);
00622          gVirtualX->SetLineWidth(-1);
00623 
00624          break;
00625       case kButton1Locate:
00626 
00627          ExecuteEvent(kButton1Down, px, py);
00628 
00629          while (1) {
00630             px = py = 0;
00631             event = gVirtualX->RequestLocator(1, 1, px, py);
00632 
00633             ExecuteEvent(kButton1Motion, px, py);
00634 
00635             if (event != -1) {                     // button is released
00636                ExecuteEvent(kButton1Up, px, py);
00637                return;
00638             }
00639          }
00640          break;
00641 
00642       case kMouseEnter:
00643          break;
00644 
00645       default:
00646          // unknown event
00647          break;
00648    }
00649 }
00650 
00651 
00652 //______________________________________________________________________________
00653 const char* TPie::GetEntryLabel(Int_t i)
00654 {
00655    // Returns the label of the entry number "i".
00656 
00657    return GetSlice(i)->GetTitle();
00658 }
00659 
00660 
00661 //______________________________________________________________________________
00662 Int_t TPie::GetEntryFillColor(Int_t i)
00663 {
00664    // Return the color of the slice number "i".
00665 
00666    return GetSlice(i)->GetFillColor();
00667 }
00668 
00669 
00670 //______________________________________________________________________________
00671 Int_t TPie::GetEntryFillStyle(Int_t i)
00672 {
00673    // Return the style use to fill the slice number "i".
00674 
00675    return GetSlice(i)->GetFillStyle();
00676 }
00677 
00678 
00679 //______________________________________________________________________________
00680 Int_t TPie::GetEntryLineColor(Int_t i)
00681 {
00682    // Return the line color used to outline thi "i" slice
00683 
00684    return GetSlice(i)->GetLineColor();
00685 }
00686 
00687 
00688 //______________________________________________________________________________
00689 Int_t TPie::GetEntryLineStyle(Int_t i)
00690 {
00691    // Return the style used to outline thi "i" slice
00692 
00693    return GetSlice(i)->GetLineStyle();
00694 }
00695 
00696 
00697 //______________________________________________________________________________
00698 Int_t TPie::GetEntryLineWidth(Int_t i)
00699 {
00700    // Return the line width used to outline thi "i" slice
00701 
00702    return GetSlice(i)->GetLineWidth();
00703 }
00704 
00705 
00706 //______________________________________________________________________________
00707 Double_t TPie::GetEntryRadiusOffset(Int_t i)
00708 {
00709    // Return the radial offset's value for the slice number "i".
00710 
00711    return GetSlice(i)->GetRadiusOffset();
00712 }
00713 
00714 
00715 //______________________________________________________________________________
00716 Double_t TPie::GetEntryVal(Int_t i)
00717 {
00718    // Return the value associated with the slice number "i".
00719 
00720    return GetSlice(i)->GetValue();
00721 }
00722 
00723 
00724 //______________________________________________________________________________
00725 TLegend* TPie::GetLegend()
00726 {
00727    // If created before by Paint option or by MakeLegend method return
00728    // the pointer to the legend, otherwise return 0;
00729 
00730    return fLegend;
00731 }
00732 
00733 
00734 //______________________________________________________________________________
00735 TPieSlice* TPie::GetSlice(Int_t id)
00736 {
00737    // Return the reference to the slice of index 'id'. There are no controls
00738    // of memory corruption, be carefull.
00739 
00740    return fPieSlices[id];
00741 }
00742 
00743 
00744 //______________________________________________________________________________
00745 void TPie::Init(Int_t np, Double_t ao, Double_t x, Double_t y, Double_t r)
00746 {
00747    // Common initialization for all constructors.
00748    // This is a private function called to allocate the memory.
00749 
00750    gIsUptSlice = kFALSE;
00751 
00752    fAngularOffset = ao;
00753    fX             = x;
00754    fY             = y;
00755    fRadius        = r;
00756    fNvals         = np;
00757    fSum           = 0.;
00758    fSlices        = 0;
00759    fLegend        = 0;
00760    fHeight        = 0.08;
00761    fAngle3D       = 30;
00762 
00763    fLabelsOffset = gStyle->GetLabelOffset();
00764 
00765    fPieSlices = new TPieSlice*[fNvals];
00766 
00767    for (Int_t i=0;i<fNvals;++i) {
00768       TString tmplbl = "Slice";
00769       tmplbl += i;
00770       fPieSlices[i] = new TPieSlice(tmplbl.Data(), tmplbl.Data(), this);
00771       fPieSlices[i]->SetRadiusOffset(0.);
00772       fPieSlices[i]->SetLineColor(1);
00773       fPieSlices[i]->SetLineStyle(1);
00774       fPieSlices[i]->SetLineWidth(1);
00775       fPieSlices[i]->SetFillColor(gStyle->GetColorPalette(i));
00776       fPieSlices[i]->SetFillStyle(1001);
00777    }
00778 
00779    fLabelFormat    = "%txt";
00780    fFractionFormat = "%3.2f";
00781    fValueFormat    = "%4.2f";
00782    fPercentFormat  = "%3.1f";
00783 }
00784 
00785 
00786 //______________________________________________________________________________
00787 TLegend* TPie::MakeLegend(Double_t x1, Double_t y1, Double_t x2, Double_t y2, const char *leg_header)
00788 {
00789    // This method create a legend that explains the contents
00790    // of the slice for this pie-chart.
00791    //
00792    // The parameter passed reppresents the option passed to shown the slices,
00793    // see TLegend::AddEntry() for futher details.
00794    //
00795    // The pointer of the TLegend is returned.
00796 
00797    if (!fLegend) fLegend = new TLegend(x1,y1,x2,y2,leg_header);
00798    else fLegend->Clear();
00799 
00800    for (Int_t i=0;i<fNvals;++i) {
00801       fLegend->AddEntry(*(fPieSlices+i),fPieSlices[i]->GetTitle(),"f");
00802    }
00803 
00804    if (gPad) fLegend->Draw();
00805 
00806    return fLegend;
00807 }
00808 
00809 
00810 //______________________________________________________________________________
00811 void TPie::Paint(Option_t *option)
00812 {
00813    // Paint a Pie chart in a canvas.
00814    // The possible option are:
00815    //
00816    // "R"   Print the labels along the central "R"adius of slices.
00817    // "T"   Print the label in a direction "T"angent to circle that describes
00818    //       the TPie.
00819    // "3D"  Draw the pie-chart with a pseudo 3D effect.
00820    // "NOL" No OutLine: Don't draw the slices' outlines, any property over the
00821    //       slices' line is ignored.
00822    // ">"   Sort the slices in increasing order.
00823    // "<"   Sort the slices in decreasing order.
00824    //
00825    // After the use of > or < options the internal order of the TPieSlices
00826    // is changed.
00827    //
00828    // Other options changing the labels' format are described in
00829    // TPie::SetLabelFormat().
00830 
00831    MakeSlices();
00832 
00833    TString soption(option);
00834 
00835    bool optionSame(kFALSE);
00836 
00837    // if true the lines around the slices are drawn, if false not
00838    Bool_t optionLine(kTRUE);
00839 
00840    // For the label orientation there are 3 possibilities:
00841    //   0: horizontal
00842    //   1: radial
00843    //   2: tangent
00844    Int_t lblor(0);
00845 
00846    // Parse the options
00847    Int_t idx;
00848    // Paint the TPie in an existing canvas
00849    if ( (idx=soption.Index("same"))>=0 ) {
00850       optionSame = kTRUE;
00851       soption.Remove(idx,4);
00852    }
00853 
00854    if ( (idx=soption.Index("nol"))>=0 ) {
00855       optionLine = kFALSE;
00856       soption.Remove(idx,3);
00857    }
00858 
00859    // check if is active the pseudo-3d
00860    if ( (idx=soption.Index("3d"))>=0 ) {
00861       fIs3D = kTRUE;
00862       soption.Remove(idx,2);
00863    } else {
00864       fIs3D = kFALSE;
00865    }
00866 
00867    // seek if have to draw the labels around the pie chart
00868    if ( (idx=soption.Index("t"))>=0 ) {
00869       lblor = 2;
00870       soption.Remove(idx,1);
00871    }
00872 
00873    // Seek if have to paint the labels along the radii
00874    if ( (idx=soption.Index("r"))>=0 ) {
00875       lblor = 1;
00876       soption.Remove(idx,1);
00877    }
00878    
00879    // Seeks if has to paint sort the slices in increasing mode
00880    if ( (idx=soption.Index(">"))>=0 ) {
00881       SortSlices(kTRUE);
00882       soption.Remove(idx,1);
00883    }
00884 
00885    // Seeks if has to paint sort the slices in decreasing mode
00886    if ( (idx=soption.Index("<"))>=0 ) {
00887       SortSlices(kFALSE);
00888       soption.Remove(idx,1);
00889    }
00890 
00891    if (fNvals<=0) {
00892       Warning("Paint","No vals");
00893       return;
00894    }
00895 
00896    if (!fPieSlices) {
00897       Warning("Paint","No valid arrays of values");
00898       return;
00899    }
00900 
00901    // Check if gPad exists and define the drawing range.
00902    if (!gPad) return;
00903 
00904    // Objects useful to draw labels and slices
00905    TLatex *textlabel = new TLatex();
00906    TArc *arc = new TArc();
00907    TLine *line = new TLine();
00908 
00909    // XY metric
00910    Double_t radX  = fRadius;
00911    Double_t radY  = fRadius;
00912    Double_t radXY = 1.;
00913 
00914    if (fIs3D) {
00915       radXY = TMath::Sin(fAngle3D/180.*TMath::Pi());
00916       radY = fRadius*radXY;
00917    }
00918 
00919    // Draw the slices.
00920    Int_t pixelHeight = gPad->YtoPixel(0)-gPad->YtoPixel(fHeight);
00921    for (Int_t pi=0;pi<pixelHeight&&fIs3D==kTRUE; ++pi) { // loop for pseudo-3d effect
00922       for (Int_t i=0;i<fNvals;++i) {
00923          // draw the arc
00924          // set the color of the next slice
00925          if (pi>0) {
00926             arc->SetFillStyle(0);
00927             arc->SetLineColor(TColor::GetColorDark((fPieSlices[i]->GetFillColor())));
00928          } else {
00929             arc->SetFillStyle(0);
00930             if (optionLine==kTRUE) {
00931                arc->SetLineColor(fPieSlices[i]->GetLineColor());
00932                arc->SetLineStyle(fPieSlices[i]->GetLineStyle());
00933                arc->SetLineWidth(fPieSlices[i]->GetLineWidth());
00934             } else {
00935                arc->SetLineWidth(0);
00936                arc->SetLineColor(TColor::GetColorDark((fPieSlices[i]->GetFillColor())));
00937             }
00938          }
00939          // Paint the slice
00940          Float_t aphi = fSlices[2*i+1]*TMath::Pi()/180.;
00941 
00942          Double_t ax = fX+TMath::Cos(aphi)*fPieSlices[i]->GetRadiusOffset();
00943          Double_t ay = fY+TMath::Sin(aphi)*fPieSlices[i]->GetRadiusOffset()*radXY+gPad->PixeltoY(pixelHeight-pi);
00944 
00945          arc->PaintEllipse(ax, ay, radX, radY, fSlices[2*i],
00946                                                fSlices[2*i+2], 0.);
00947 
00948          if (optionLine==kTRUE) {
00949             line->SetLineColor(fPieSlices[i]->GetLineColor());
00950             line->SetLineStyle(fPieSlices[i]->GetLineStyle());
00951             line->SetLineWidth(fPieSlices[i]->GetLineWidth());
00952             line->PaintLine(ax,ay,ax,ay);
00953 
00954             Double_t x0, y0;
00955             x0 = ax+radX*TMath::Cos(fSlices[2*i]/180.*TMath::Pi());
00956             y0 = ay+radY*TMath::Sin(fSlices[2*i]/180.*TMath::Pi());
00957             line->PaintLine(x0,y0,x0,y0);
00958 
00959             x0 = ax+radX*TMath::Cos(fSlices[2*i+2]/180.*TMath::Pi());
00960             y0 = ay+radY*TMath::Sin(fSlices[2*i+2]/180.*TMath::Pi());
00961             line->PaintLine(x0,y0,x0,y0);
00962          }
00963       }
00964    } // end loop for pseudo-3d effect
00965 
00966    for (Int_t i=0;i<fNvals;++i) { // loop for the piechart
00967       // Set the color of the next slice
00968       arc->SetFillColor(fPieSlices[i]->GetFillColor());
00969       arc->SetFillStyle(fPieSlices[i]->GetFillStyle());
00970       if (optionLine==kTRUE) {
00971          arc->SetLineColor(fPieSlices[i]->GetLineColor());
00972          arc->SetLineStyle(fPieSlices[i]->GetLineStyle());
00973          arc->SetLineWidth(fPieSlices[i]->GetLineWidth());
00974       } else {
00975          arc->SetLineWidth(0);
00976          arc->SetLineColor(fPieSlices[i]->GetFillColor());
00977       }
00978 
00979       // Paint the slice
00980       Float_t aphi = fSlices[2*i+1]*TMath::Pi()/180.;
00981 
00982       Double_t ax = fX+TMath::Cos(aphi)*fPieSlices[i]->GetRadiusOffset();
00983       Double_t ay = fY+TMath::Sin(aphi)*fPieSlices[i]->GetRadiusOffset()*radXY;
00984       arc->PaintEllipse(ax, ay, radX, radY, fSlices[2*i],
00985                                             fSlices[2*i+2], 0.);
00986 
00987    } // end loop to draw the slices
00988 
00989 
00990    // Set the font
00991    textlabel->SetTextFont(GetTextFont());
00992    textlabel->SetTextSize(GetTextSize());
00993    textlabel->SetTextColor(GetTextColor());
00994 
00995    // Loop to place the labels.
00996    for (Int_t i=0;i<fNvals;++i) {
00997       Float_t aphi = fSlices[2*i+1]*TMath::Pi()/180.;
00998       //aphi = TMath::ATan2(TMath::Sin(aphi)*radXY,TMath::Cos(aphi));
00999 
01000       Float_t label_off = fLabelsOffset;
01001 
01002 
01003       // Paint the text in the pad
01004       TString tmptxt  = fLabelFormat;
01005 
01006       tmptxt.ReplaceAll("%txt",fPieSlices[i]->GetTitle());
01007       tmptxt.ReplaceAll("%val",Form(fValueFormat.Data(),fPieSlices[i]->GetValue()));
01008       tmptxt.ReplaceAll("%frac",Form(fFractionFormat.Data(),fPieSlices[i]->GetValue()/fSum));
01009       tmptxt.ReplaceAll("%perc",Form("%3.1f %s",(fPieSlices[i]->GetValue()/fSum)*100,"%"));
01010 
01011       textlabel->SetTitle(tmptxt.Data());
01012       Double_t h = textlabel->GetYsize();
01013       Double_t w = textlabel->GetXsize();
01014 
01015       Float_t lx = fX+(fRadius+fPieSlices[i]->GetRadiusOffset()+label_off)*TMath::Cos(aphi);
01016       Float_t ly = fY+(fRadius+fPieSlices[i]->GetRadiusOffset()+label_off)*TMath::Sin(aphi)*radXY;
01017 
01018       Double_t lblang = 0;
01019 
01020       if (lblor==1) { // radial direction for the label
01021          aphi = TMath::ATan2(TMath::Sin(aphi)*radXY,TMath::Cos(aphi));
01022          lblang += aphi;
01023          if (lblang<=0) lblang += TMath::TwoPi();
01024          if (lblang>TMath::TwoPi()) lblang-= TMath::TwoPi();
01025 
01026          lx += h/2.*TMath::Sin(lblang);
01027          ly -= h/2.*TMath::Cos(lblang);
01028 
01029          // This control prevent text up-side
01030          if (lblang>TMath::PiOver2() && lblang<=3.*TMath::PiOver2()) {
01031             lx     += w*TMath::Cos(lblang)-h*TMath::Sin(lblang);
01032             ly     += w*TMath::Sin(lblang)+h*TMath::Cos(lblang);
01033             lblang -= TMath::Pi();
01034          }
01035       } else if (lblor==2) { // tangential direction of the labels
01036          aphi -=TMath::PiOver2();
01037          aphi = TMath::ATan2(TMath::Sin(aphi)*radXY,TMath::Cos(aphi));
01038          lblang += aphi;//-TMath::PiOver2();
01039          if (lblang<0) lblang+=TMath::TwoPi();
01040 
01041          lx -= w/2.*TMath::Cos(lblang);
01042          ly -= w/2.*TMath::Sin(lblang);
01043 
01044          if (lblang>TMath::PiOver2() && lblang<3.*TMath::PiOver2()) {
01045             lx     += w*TMath::Cos(lblang)-h*TMath::Sin(lblang);
01046             ly     += w*TMath::Sin(lblang)+h*TMath::Cos(lblang);
01047             lblang -= TMath::Pi();
01048          }
01049       } else { // horizontal labels (default direction)
01050          aphi = TMath::ATan2(TMath::Sin(aphi)*radXY,TMath::Cos(aphi));
01051          if (aphi>TMath::PiOver2() || aphi<=-TMath::PiOver2()) lx -= w;
01052          if (aphi<0)                                           ly -= h;
01053       }
01054 
01055       Float_t rphi = TMath::ATan2((ly-fY)*radXY,lx-fX);
01056       if (rphi < 0 && fIs3D && label_off>=0.)
01057          ly -= fHeight;
01058 
01059       textlabel->PaintLatex(lx,ly,
01060                             lblang*180/TMath::Pi()+GetTextAngle(),
01061                             GetTextSize(), tmptxt.Data());
01062    }
01063 
01064    delete arc;
01065    delete line;
01066    delete textlabel;
01067 
01068    if (optionSame) return;
01069 
01070    // Draw title
01071    TPaveText *title = 0;
01072    TObject *obj;
01073    if ((obj = gPad->GetListOfPrimitives()->FindObject("title"))) {
01074       title = dynamic_cast<TPaveText*>(obj);
01075    }
01076 
01077    // Check the OptTitle option
01078    if (strlen(GetTitle()) == 0 || gStyle->GetOptTitle() <= 0) {
01079       if (title) delete title;
01080       return;
01081    }
01082 
01083    // Height and width of the title
01084    Double_t ht = gStyle->GetTitleH();
01085    Double_t wt = gStyle->GetTitleW();
01086    if (ht<=0) ht = 1.1*gStyle->GetTitleFontSize();
01087    if (ht<=0) ht = 0.05; // minum height
01088    if (wt<=0) { // eval the width of the title
01089       TLatex l;
01090       l.SetTextSize(ht);
01091       l.SetTitle(GetTitle());
01092       // adjustment in case the title has several lines (#splitline)
01093       ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
01094       Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
01095       wt = TMath::Min(0.7, 0.02+wndc);
01096    }
01097 
01098    if (title) {
01099       TText *t0 = (TText*)title->GetLine(0);
01100       if (t0) {
01101          if (!strcmp(t0->GetTitle(),GetTitle())) return;
01102          t0->SetTitle(GetTitle());
01103          if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
01104       }
01105       return;
01106    }
01107 
01108    Int_t talh = gStyle->GetTitleAlign()/10;
01109    if (talh < 1) talh = 1; if (talh > 3) talh = 3;
01110    Int_t talv = gStyle->GetTitleAlign()%10;
01111    if (talv < 1) talv = 1; if (talv > 3) talv = 3;
01112    Double_t xpos, ypos;
01113    xpos = gStyle->GetTitleX();
01114    ypos = gStyle->GetTitleY();
01115    if (talh == 2) xpos = xpos-wt/2.;
01116    if (talh == 3) xpos = xpos-wt;
01117    if (talv == 2) ypos = ypos+ht/2.;
01118    if (talv == 1) ypos = ypos+ht;
01119 
01120    title = new TPaveText(xpos,ypos-ht,xpos+wt,ypos,"blNDC");
01121    title->SetFillColor(gStyle->GetTitleFillColor());
01122    title->SetFillStyle(gStyle->GetTitleStyle());
01123    title->SetName("title");
01124 
01125    title->SetBorderSize(gStyle->GetTitleBorderSize());
01126    title->SetTextColor(gStyle->GetTitleTextColor());
01127    title->SetTextFont(gStyle->GetTitleFont(""));
01128    if (gStyle->GetTitleFont("")%10 > 2)
01129       title->SetTextSize(gStyle->GetTitleFontSize());
01130    title->AddText(GetTitle());
01131 
01132    title->SetBit(kCanDelete);
01133 
01134    title->Draw();
01135    title->Paint();
01136 }
01137 
01138 
01139 //______________________________________________________________________________
01140 void TPie::SavePrimitive(ostream &out, Option_t *option)
01141 {
01142    // Save primitive as a C++ statement(s) on output stream out
01143 
01144    out << "   " << endl;
01145    if (gROOT->ClassSaved(TPie::Class())) {
01146       out << "   ";
01147    } else {
01148       out << "   TPie *";
01149    }
01150    out << GetName() << " = new TPie(\"" << GetName() << "\", \"" << GetTitle()
01151        << "\", " << fNvals << ");" << endl;
01152    out << "   " << GetName() << "->SetCircle(" << fX << ", " << fY << ", "
01153        << fRadius << ");" << endl;
01154    out << "   " << GetName() << "->SetValueFormat(\"" << GetValueFormat()
01155        << "\");" << endl;
01156    out << "   " << GetName() << "->SetLabelFormat(\"" << GetLabelFormat()
01157        << "\");" << endl;
01158    out << "   " << GetName() << "->SetPercentFormat(\"" << GetPercentFormat()
01159        << "\");" << endl;
01160    out << "   " << GetName() << "->SetLabelsOffset(" << GetLabelsOffset()
01161        << ");" << endl;
01162    out << "   " << GetName() << "->SetAngularOffset(" << GetAngularOffset()
01163        << ");" << endl;
01164    out << "   " << GetName() << "->SetTextAngle(" << GetTextAngle() << ");" << endl;
01165    out << "   " << GetName() << "->SetTextColor(" << GetTextColor() << ");" << endl;
01166    out << "   " << GetName() << "->SetTextFont(" << GetTextFont() << ");" << endl;
01167    out << "   " << GetName() << "->SetTextSize(" << GetTextSize() << ");" << endl;
01168 
01169 
01170    // Save the values for the slices
01171    for (Int_t i=0;i<fNvals;++i) {
01172       out << "   " << GetName() << "->GetSlice(" << i << ")->SetTitle(\""
01173           << fPieSlices[i]->GetTitle() << "\");" << endl;
01174       out << "   " << GetName() << "->GetSlice(" << i << ")->SetValue("
01175           << fPieSlices[i]->GetValue() << ");" << endl;
01176       out << "   " << GetName() << "->GetSlice(" << i << ")->SetRadiusOffset("
01177           << fPieSlices[i]->GetRadiusOffset() << ");" << endl;
01178       out << "   " << GetName() << "->GetSlice(" << i << ")->SetFillColor("
01179           << fPieSlices[i]->GetFillColor() << ");" << endl;
01180       out << "   " << GetName() << "->GetSlice(" << i << ")->SetFillStyle("
01181           << fPieSlices[i]->GetFillStyle() << ");" << endl;
01182       out << "   " << GetName() << "->GetSlice(" << i << ")->SetLineColor("
01183           << fPieSlices[i]->GetLineColor() << ");" << endl;
01184       out << "   " << GetName() << "->GetSlice(" << i << ")->SetLineStyle("
01185           << fPieSlices[i]->GetLineStyle() << ");" << endl;
01186       out << "   " << GetName() << "->GetSlice(" << i << ")->SetLineWidth("
01187           << fPieSlices[i]->GetLineWidth() << ");" << endl;
01188    }
01189 
01190    out << "   " << GetName() << "->Draw(\"" << option << "\");" << endl;
01191 }
01192 
01193 
01194 
01195 //______________________________________________________________________________
01196 void TPie::SetAngle3D(Float_t val) {
01197    // Set the value of for the pseudo 3D view angle, in degree.
01198    // The range of the permitted values is: [0,90]
01199 
01200    // check if val is in the permitted range
01201    while (val>360.) val -= 360.;
01202    while (val<0)    val += 360.;
01203    if      (val>=90 && val<180)   val = 180-val;
01204    else if (val>=180 && val<=360) val = 360-val;
01205 
01206    fAngle3D = val;
01207 }
01208 
01209 
01210 //______________________________________________________________________________
01211 void TPie::SetAngularOffset(Double_t offset)
01212 {
01213    // Set the global angular offset for slices in degree [0,360]
01214 
01215    fAngularOffset = offset;
01216 
01217    while (fAngularOffset>=360.) fAngularOffset -= 360.;
01218    while (fAngularOffset<0.)    fAngularOffset += 360.;
01219 
01220    MakeSlices(kTRUE);
01221 }
01222 
01223 
01224 //______________________________________________________________________________
01225 void TPie::SetCircle(Double_t x, Double_t y, Double_t rad)
01226 {
01227    // Set the coordinates of the circle that describe the pie:
01228    // - the 1st and the 2nd arguments are the x and y center's coordinates.
01229    // - the 3rd value is the pie-chart's radius.
01230    //
01231    // All the coordinates are in NDC space.
01232 
01233    fX      = x;
01234    fY      = y;
01235    fRadius = rad;
01236 }
01237 
01238 
01239 //______________________________________________________________________________
01240 void TPie::SetEntryLabel(Int_t i, const char *text)
01241 {
01242    // Set slice number "i" label. The first parameter is the index of the slice,
01243    // the other is the label text.
01244 
01245    // Set the Label of a single slice
01246    if (i>=0 && i<fNvals) fPieSlices[i]->SetTitle(text);
01247 }
01248 
01249 
01250 //______________________________________________________________________________
01251 void TPie::SetEntryLineColor(Int_t i, Int_t color)
01252 {
01253    // Set the color for the slice's outline. "i" is the slice number.
01254 
01255    if (i>=0 && i<fNvals) fPieSlices[i]->SetLineColor(color);
01256 }
01257 
01258 
01259 //______________________________________________________________________________
01260 void TPie::SetEntryLineStyle(Int_t i, Int_t style)
01261 {
01262    // Set the style for the slice's outline. "i" is the slice number.
01263 
01264    if (i>=0 && i<fNvals) fPieSlices[i]->SetLineStyle(style);
01265 }
01266 
01267 
01268 //______________________________________________________________________________
01269 void TPie::SetEntryLineWidth(Int_t i, Int_t width)
01270 {
01271    // Set the width of the slice's outline. "i" is the slice number.
01272 
01273    if (i>=0 && i<fNvals) fPieSlices[i]->SetLineWidth(width);
01274 }
01275 
01276 
01277 //______________________________________________________________________________
01278 void TPie::SetEntryFillColor(Int_t i, Int_t color)
01279 {
01280    // Set the color for the slice "i".
01281 
01282    if (i>=0 && i<fNvals) fPieSlices[i]->SetFillColor(color);
01283 }
01284 
01285 
01286 //______________________________________________________________________________
01287 void TPie::SetEntryFillStyle(Int_t i, Int_t style)
01288 {
01289    // Set the fill style for the "i" slice
01290 
01291    if (i>=0 && i<fNvals) fPieSlices[i]->SetFillStyle(style);
01292 }
01293 
01294 
01295 //______________________________________________________________________________
01296 void TPie::SetEntryRadiusOffset(Int_t i, Double_t shift)
01297 {
01298    // Set the distance, in the direction of the radius of the slice.
01299 
01300    if (i>=0 && i<fNvals) fPieSlices[i]->SetRadiusOffset(shift);
01301 }
01302 
01303 
01304 //______________________________________________________________________________
01305 void TPie::SetEntryVal(Int_t i, Double_t val)
01306 {
01307    // Set the value of a slice
01308 
01309    if (i>=0 && i<fNvals) fPieSlices[i]->SetValue(val);
01310 
01311    MakeSlices(kTRUE);
01312 }
01313 
01314 
01315 //______________________________________________________________________________
01316 void TPie::SetFillColors(Int_t *colors)
01317 {
01318    // Set the fill colors for all the TPie's slices.
01319 
01320    if (!colors) return;
01321    for (Int_t i=0;i<fNvals;++i) fPieSlices[i]->SetFillColor(colors[i]);
01322 }
01323 
01324 
01325 //______________________________________________________________________________
01326 void TPie::SetHeight(Double_t val/*=20*/)
01327 {
01328    // Set the height, in pixel, for the piechart if is drawn using
01329    // the pseudo-3d mode.
01330    //
01331    // The default value is 20 pixel.
01332 
01333    fHeight = val;
01334 }
01335 
01336 
01337 //______________________________________________________________________________
01338 void TPie::SetLabelFormat(const char *fmt)
01339 {
01340    // This method is used to customize the label format. The format string
01341    // must contain one of these modifiers:
01342    //
01343    // - %txt  : to print the text label associated with the slice
01344    // - %val  : to print the numeric value of the slice
01345    // - %frac : to print the relative fraction of this slice
01346    // - %perc : to print the % of this slice
01347    //
01348    // ex. : mypie->SetLabelFormat("%txt (%frac)");
01349 
01350    fLabelFormat = fmt;
01351 }
01352 
01353 
01354 //______________________________________________________________________________
01355 void TPie::SetFractionFormat(const char *fmt)
01356 {
01357    // Set numeric format in the label, is used if the label format
01358    // there is the modifier %frac, in this case the value is printed
01359    // using this format.
01360    //
01361    // The numeric format use the standard C modifier used in stdio library:
01362    // %f, %2.1$, %e... for further documentation you can use the printf
01363    // mapage ("man 3 printf" on linux)
01364    //
01365    // ex. : mypie->SetLabelFormat("%txt (%frac)");
01366    //       mypie->SetFractionFormat("2.1f");
01367 
01368    fFractionFormat = fmt;
01369 }
01370 
01371 
01372 //______________________________________________________________________________
01373 void TPie::SetLabels(const char *lbls[])
01374 {
01375    // Set the labels for all the slices.
01376 
01377    if (!lbls) return;
01378    for (Int_t i=0;i<fNvals;++i) fPieSlices[i]->SetTitle(lbls[i]);
01379 }
01380 
01381 
01382 //______________________________________________________________________________
01383 void TPie::SetLabelsOffset(Float_t labelsoffset)
01384 {
01385    // Set the distance between the label end the external line of the TPie.
01386 
01387    fLabelsOffset = labelsoffset;
01388 }
01389 
01390 
01391 //______________________________________________________________________________
01392 void TPie::SetPercentFormat(const char *fmt)
01393 {
01394    // Set the numeric format for the percent value of a slice, default: %3.1f
01395 
01396    fPercentFormat = fmt;
01397 }
01398 
01399 
01400 //______________________________________________________________________________
01401 void TPie::SetRadius(Double_t rad)
01402 {
01403    // Set the pie chart's radius' value.
01404 
01405    if (rad>0) {
01406       fRadius = rad;
01407    } else {
01408       Warning("SetRadius",
01409               "It's not possible set the radius to a negative value");
01410    }
01411 }
01412 
01413 
01414 //______________________________________________________________________________
01415 void TPie::SetValueFormat(const char *fmt)
01416 {
01417    // Set the numeric format the slices' values.
01418    // Used by %val (see SetLabelFormat()).
01419 
01420    fValueFormat = fmt;
01421 }
01422 
01423 
01424 //______________________________________________________________________________
01425 void TPie::SetX(Double_t x)
01426 {
01427    // Set X value.
01428 
01429    fX = x;
01430 }
01431 
01432 
01433 //______________________________________________________________________________
01434 void TPie::SetY(Double_t y)
01435 {
01436    // Set Y value.
01437 
01438    fY = y;
01439 }
01440 
01441 
01442 //______________________________________________________________________________
01443 void TPie::MakeSlices(Bool_t force)
01444 {
01445    // Make the slices.
01446    // If they already exist it does nothing unless force=kTRUE.
01447 
01448    if (fSlices && !force) return;
01449 
01450    fSum = .0;
01451 
01452    for (Int_t i=0;i<fNvals;++i) {
01453       if (fPieSlices[i]->GetValue()<0) {
01454          Warning("MakeSlices",
01455                  "Negative values in TPie, absolute value will be used");
01456          fPieSlices[i]->SetValue(-1.*fPieSlices[i]->GetValue());
01457       }
01458       fSum += fPieSlices[i]->GetValue();
01459    }
01460 
01461    if (fSum<=.0) return;
01462 
01463    if (!fSlices) fSlices = new Float_t[2*fNvals+1];
01464 
01465    // Compute the slices size and position (2 angles for each slice)
01466    fSlices[0] = fAngularOffset;
01467    for (Int_t i=0;i<fNvals;++i) {
01468       Float_t dphi   = fPieSlices[i]->GetValue()/fSum*360.;
01469       fSlices[2*i+1] = fSlices[2*i]+dphi/2.;
01470       fSlices[2*i+2] = fSlices[2*i]+dphi;
01471    }
01472 }
01473 
01474 
01475 //______________________________________________________________________________
01476 void TPie::SortSlices(Bool_t amode, Float_t merge_threshold)
01477 {
01478    // This method, mainly intended for internal use, ordered the  slices accoording their values.
01479    // The default (amode=kTRUE) is inscreasing order, but is also possible in decreasing order (amode=kFALSE).
01480    //
01481    // If the merge_thresold>0 the slice that contains a quantity smaller than merge_thresold are merged
01482    // togheter
01483    
01484    
01485    // main loop to order, bubble sort, the array
01486    Bool_t isDone = kFALSE;
01487 
01488    while (isDone==kFALSE) {
01489       isDone = kTRUE;
01490 
01491       for (Int_t i=0;i<fNvals-1;++i) { // loop over the values
01492          if ( (amode && (fPieSlices[i]->GetValue()>fPieSlices[i+1]->GetValue())) ||
01493               (!amode && (fPieSlices[i]->GetValue()<fPieSlices[i+1]->GetValue()))
01494             )
01495          {
01496             // exchange the order
01497             TPieSlice *tmpcpy = fPieSlices[i];
01498             fPieSlices[i] = fPieSlices[i+1];
01499             fPieSlices[i+1] = tmpcpy;
01500 
01501             isDone = kFALSE;
01502          }
01503       }  // end loop the values
01504    } // end main ordering loop
01505 
01506    if (merge_threshold>0) {
01507       // merge smallest slices
01508       TPieSlice *merged_slice = new TPieSlice("merged","other",this);
01509       merged_slice->SetRadiusOffset(0.);
01510       merged_slice->SetLineColor(1);
01511       merged_slice->SetLineStyle(1);
01512       merged_slice->SetLineWidth(1);
01513       merged_slice->SetFillColor(gStyle->GetColorPalette( (amode ? 0 : fNvals-1) ));
01514       merged_slice->SetFillStyle(1001);
01515 
01516       if (amode) {         
01517          // search slices under the threshold
01518          Int_t iMerged = 0;
01519          for (;iMerged<fNvals&&fPieSlices[iMerged]->GetValue()<merge_threshold;++iMerged) {
01520             merged_slice->SetValue( merged_slice->GetValue()+fPieSlices[iMerged]->GetValue() );
01521          }
01522          
01523          // evaluate number of valid slices
01524          if (iMerged<=1) { // no slices to merge
01525             delete merged_slice; 
01526          }
01527          else { // write a new array with the right dimension
01528             Int_t old_fNvals = fNvals;
01529             fNvals = fNvals-iMerged+1;
01530             TPieSlice **new_array = new TPieSlice*[fNvals];
01531             new_array[0] = merged_slice;
01532             for (Int_t i=0;i<old_fNvals;++i) {
01533                if (i<iMerged) delete fPieSlices[i];
01534                else new_array[i-iMerged+1] = fPieSlices[i];
01535             }
01536             delete [] fPieSlices;
01537             fPieSlices = new_array;
01538          }
01539       }
01540       else {
01541          Int_t iMerged = fNvals-1;
01542          for (;iMerged>=0&&fPieSlices[iMerged]->GetValue()<merge_threshold;--iMerged) {
01543             merged_slice->SetValue( merged_slice->GetValue()+fPieSlices[iMerged]->GetValue() );
01544          }
01545 
01546          // evaluate number of valid slices
01547          Int_t nMerged = fNvals-1-iMerged;
01548          if (nMerged<=1) { // no slices to merge
01549             delete merged_slice; 
01550          }
01551          else { // write a new array with the right dimension
01552             Int_t old_fNvals = fNvals;
01553             fNvals = fNvals-nMerged+1;
01554             TPieSlice **new_array = new TPieSlice*[fNvals];
01555             new_array[fNvals-1] = merged_slice;
01556             for (Int_t i=old_fNvals-1;i>=0;--i) {
01557                if (i>iMerged) delete fPieSlices[i];
01558                else new_array[i-nMerged-1] = fPieSlices[i];
01559             }
01560             delete [] fPieSlices;
01561             fPieSlices = new_array;
01562          }
01563 
01564       }
01565    }
01566    
01567    MakeSlices(kTRUE);
01568 }
01569 

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