TGraphPainter.cxx

Go to the documentation of this file.
00001 // @(#)root/histpainter:$Id: TGraphPainter.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 "TGraphPainter.h"
00014 #include "TMath.h"
00015 #include "TGraph.h"
00016 #include "TPolyLine.h"
00017 #include "TPolyMarker.h"
00018 #include "TVirtualPad.h"
00019 #include "TView.h"
00020 #include "TStyle.h"
00021 #include "TH1.h"
00022 #include "TF1.h"
00023 #include "TPaveStats.h"
00024 #include "TGaxis.h"
00025 #include "TGraphAsymmErrors.h"
00026 #include "TGraphBentErrors.h"
00027 #include "TGraphPolargram.h"
00028 #include "TGraphPolar.h"
00029 #include "TGraphQQ.h"
00030 #include "TLatex.h"
00031 #include "TArrow.h"
00032 #include "TFrame.h"
00033 #include "TVirtualPadEditor.h"
00034 
00035 Double_t *gxwork, *gywork, *gxworkl, *gyworkl;
00036 
00037 ClassImp(TGraphPainter);
00038 
00039 //______________________________________________________________________________
00040 /* Begin_Html
00041 <center><h2>The graph painter class</h2></center>
00042 
00043 <ul>
00044 <li><a href="#GP00">Introduction</li></a>
00045 <li><a href="#GP01">Graphs' plotting options</li></a>
00046 <li><a href="#GP02">Exclusion graphs</li></a>
00047 <li><a href="#GP03">Graphs with error bars</li></a>
00048 <ul>
00049 <li><a href="#GP03a">TGraphErrors</li></a>
00050 <li><a href="#GP03b">TGraphAsymmErrors</li></a>
00051 <li><a href="#GP03c">TGraphBentErrors</li></a>
00052 </ul>
00053 <li><a href="#GP04">TGraphPolar options</li></a>
00054 </ul>
00055 
00056 <a name="GP00"></a><h3>Introduction</h3>
00057 
00058 Graphs are drawn via the painter <tt>TGraphPainter</tt> class. This class
00059 implement all the various techniques need to display the various kind of
00060 graphs ie: <tt>TGraph</tt>, <tt>TGraphAsymmErrors</tt>,
00061 <tt>TGraphBentErrors</tt> and <tt>TGraphErrors</tt>.
00062 
00063 <p>
00064 To draw a graph "<tt>g</tt>" is enough to do:
00065 <pre>
00066    g->Draw("AL");
00067 </pre>
00068 
00069 
00070 The option <tt>"AL"</tt> in the <tt>Draw()</tt> method means that the axis
00071 syetem should be define (option <tt>"A"</tt>) and that the graph should
00072 be drawn as a simple line (option <tt>"L"</tt>). By default a graph is drawn
00073 in the current pad in the current coordinates system. To define a suitable
00074 coordinates system and drawn the axis the option <tt>"A"</tt> must be
00075 specified.
00076 <p>
00077 <tt>TGraphPainter</tt> offers many options to paint the various kind of graphs.
00078 <p>
00079 The <tt>TGraphPainter</tt> class specializes in the drawing of graphs. It is
00080 separated from the graph so that one can have graphs without the
00081 graphics overhead, for example in a batch program.
00082 <p>
00083 When a displayed graph is modified, there is not need to call the
00084 <tt>Draw()</tt> method again; the image will be refreshed the next time the
00085 pad will be updated.
00086 <p>A pad is updated after one of these three actions:
00087 <ol>
00088 <li>  a carriage control on the ROOT command line,
00089 <li>  a click inside the pad,
00090 <li>  a call to <tt>TPad::Update</tt>.
00091 </ol>
00092 
00093 <a name="GP01"></a><h3>Graphs' plotting options</h3>
00094 Graphs can be drawn with the following options:
00095 <p>
00096 <table border=0>
00097 
00098 <tr><th valign=top>"A"</th><td>
00099 Axis are drawn around the graph
00100 </td></tr>
00101 
00102 <tr><th valign=top>"L"</th><td>
00103 A simple polyline between every points is drawn
00104 </td></tr>
00105 
00106 <tr><th valign=top>"F"</th><td>
00107 A fill area is drawn ('CF' draw a smooth fill area)
00108 </td></tr>
00109 
00110 <tr><th valign=top>"C"</th><td>
00111 A smooth Curve is drawn
00112 </td></tr>
00113 
00114 <tr><th valign=top>"*"</th><td>
00115 A Star is plotted at each point
00116 </td></tr>
00117 
00118 <tr><th valign=top>"P"</th><td>
00119 Idem with the current marker
00120 </td></tr>
00121 
00122 <tr><th valign=top>"B"</th><td>
00123 A Bar chart is drawn at each point
00124 </td></tr>
00125 
00126 <tr><th valign=top>"1"</th><td>
00127 ylow=rwymin
00128 </td></tr>
00129 
00130 <tr><th valign=top>"X+"</th><td>
00131 The X-axis is drawn on the top side of the plot.
00132 </td></tr>
00133 
00134 <tr><th valign=top>"Y+"</th><td>
00135 The Y-axis is drawn on the right side of the plot.
00136 </td></tr>
00137 
00138 </table>
00139 <p>
00140 
00141 Several drawing options can be combined. In the following example the graph
00142 is drawn as a smooth curve (option "C") and with markers (option "P"). The
00143 option "A" request the definition of the axis.
00144 
00145 End_Html
00146 Begin_Macro(source)
00147 {
00148    TCanvas *c1 = new TCanvas("c1","c1",200,10,600,400);
00149 
00150    c1->SetFillColor(42);
00151    c1->SetGrid();
00152 
00153    const Int_t n = 20;
00154    Double_t x[n], y[n];
00155    for (Int_t i=0;i<n;i++) {
00156       x[i] = i*0.1;
00157       y[i] = 10*sin(x[i]+0.2);
00158    }
00159    gr = new TGraph(n,x,y);
00160    gr->SetLineColor(2);
00161    gr->SetLineWidth(4);
00162    gr->SetMarkerColor(4);
00163    gr->SetMarkerSize(1.5);
00164    gr->SetMarkerStyle(21);
00165    gr->SetTitle("Option ACP example");
00166    gr->GetXaxis()->SetTitle("X title");
00167    gr->GetYaxis()->SetTitle("Y title");
00168    gr->Draw("ACP");
00169 
00170    // TCanvas::Update() draws the frame, after which one can change it
00171    c1->Update();
00172    c1->GetFrame()->SetFillColor(21);
00173    c1->GetFrame()->SetBorderSize(12);
00174    c1->Modified();
00175    return c1;
00176 }
00177 End_Macro
00178 Begin_Html
00179 
00180 
00181 <a name="GP02"></a><h3>Exclusion graphs</h3>
00182 
00183 When a graph is painted with the option <tt>"C"</tt> or <tt>"L"</tt> it is
00184 possible to draw a filled area on one side of the line. This is useful to show
00185 exclusion zones.
00186 
00187 <p>This drawing mode is activated when the absolute value of the graph line
00188 width (set thanks to <tt>SetLineWidth()</tt>) is greater than 99. In that
00189 case the line width number is interpreted as:
00190 <pre>
00191       100*ff+ll = ffll
00192 </pre>
00193 <ul>
00194 <li> The two digits number <tt>"ll"</tt> represent the normal line width
00195 <li> The two digits number  <tt>"ff"</tt> is the filled area width.
00196 <li> The sign of "ffll" allows to flip the filled area from one side of the line to
00197      the other.
00198 </ul>
00199 The current fill area attributes are used to draw the hatched zone.
00200 
00201 End_Html
00202 Begin_Macro(source)
00203 ../../../tutorials/graphs/exclusiongraph.C
00204 End_Macro
00205 Begin_Html
00206 
00207 <a name="GP03"></a><h3>Graphs with error bars</h3>
00208 Three classes are available to handle graphs with error bars:
00209 <tt>TGraphErrors</tt>, <tt>TGraphAsymmErrors</tt> and <tt>TGraphBentErrors</tt>.
00210 In addition to the drawing options previously described, the graphs with error
00211 bars can be drawn with the following extra options:
00212 <p>
00213 <table border=0>
00214 
00215 <tr><th valign=top>"Z"</th><td>
00216 By default horizonthal and vertical small lines are drawn at
00217 the end of the error bars. If option "z" or "Z" is specified,
00218 these lines are not drawn.
00219 </td></tr>
00220 
00221 <tr><th valign=top>">"</th><td>
00222 An arrow is drawn at the end of the error bars.
00223 The size of the arrow is set to 2/3 of the marker size.
00224 </td></tr>
00225 
00226 <tr><th valign=top>"|>"</th><td>
00227 A filled arrow is drawn at the end of the error bars.
00228 The size of the arrow is set to 2/3 of the marker size.
00229 </td></tr>
00230 
00231 <tr><th valign=top>"X"</th><td>
00232 By default the error bars are drawn. If option "X" is specified,
00233 the errors are not drawn. The graph with errors in drawn like a normal graph.
00234 </td></tr>
00235 
00236 <tr><th valign=top>"||"</th><td>
00237 Only the end vertical/horizonthal lines
00238 of the error bars are drawn. This option is interesting to superimpose
00239 systematic errors on top of a graph with statistical errors.
00240 </td></tr>
00241 
00242 <tr><th valign=top>"[]"</th><td>
00243 Does the same as option "||" except that it draws additionnal tick marks at the
00244 end of the vertical/horizonthal lines. This makes less ambiguous plots
00245 in case several graphs are drawn on the same picture.
00246 </td></tr>
00247 
00248 <tr><th valign=top>"2"</th><td>
00249 Error rectangles are drawn.
00250 </td></tr>
00251 
00252 <tr><th valign=top>"3"</th><td>
00253 A filled area is drawn through the end points of the vertical error bars.
00254 </td></tr>
00255 
00256 <tr><th valign=top>"4"</th><td>
00257 A smoothed filled area is drawn through the end points of the vertical error
00258 bars.
00259 </td></tr>
00260 </table>
00261 <p>
00262 <tt>gStyle->SetErrorX(dx)</tt> controls the size of the error along x.
00263 <tt>dx = 0</tt> removes the error along x.
00264 <p>
00265 <tt>gStyle->SetEndErrorSize(np)</tt> controls the size of the lines
00266 at the end of the error bars (when option 1 is used).
00267 By default <tt>np=1</tt>. (np represents the number of pixels).
00268 
00269 <a name="GP03a"></a><h4><u>TGraphErrors</u></h4>
00270 A <tt>TGraphErrors</tt> is a <tt>TGraph</tt> with error bars. The errors are
00271 defined along X and Y and are symmetric: The left and right errors are the same
00272 along X and the bottom and up errors are the same along Y.
00273 
00274 End_Html
00275 Begin_Macro(source)
00276 {
00277    TCanvas *c4 = new TCanvas("c4","c4",200,10,600,400);
00278    double x[] = {0, 1, 2, 3, 4};
00279    double y[] = {0, 2, 4, 1, 3};
00280    double ex[] = {0.1, 0.2, 0.3, 0.4, 0.5};
00281    double ey[] = {1, 0.5, 1, 0.5, 1};
00282    TGraphErrors* ge = new TGraphErrors(5, x, y, ex, ey);
00283    ge->Draw("ap");
00284    return c4;
00285 }
00286 End_Macro
00287 Begin_Html
00288 The option "3" allows to shows the error as band.
00289 
00290 End_Html
00291 Begin_Macro(source)
00292 {
00293    TCanvas *c41 = new TCanvas("c41","c41",200,10,600,400);
00294    double x[] = {0, 1, 2, 3, 4};
00295    double y[] = {0, 2, 4, 1, 3};
00296    double ex[] = {0.1, 0.2, 0.3, 0.4, 0.5};
00297    double ey[] = {1, 0.5, 1, 0.5, 1};
00298    TGraphErrors* ge = new TGraphErrors(5, x, y, ex, ey);
00299    ge->SetFillColor(4);
00300    ge->SetFillStyle(3010);
00301    ge->Draw("a3");
00302    return c41;
00303 }
00304 End_Macro
00305 Begin_Html
00306 
00307 The option "4" is similar to the option "3" except that the band is smoothed.
00308 As the following picture shows, this option should be used carefuly because
00309 the smoothing algorithm may show some (huge) "bouncing" effects. In some case
00310 looks nicer than the option "3" (because it is smooth) but it can be
00311 misleading.
00312 
00313 End_Html
00314 Begin_Macro(source)
00315 {
00316    TCanvas *c42 = new TCanvas("c42","c42",200,10,600,400);
00317    double x[] = {0, 1, 2, 3, 4};
00318    double y[] = {0, 2, 4, 1, 3};
00319    double ex[] = {0.1, 0.2, 0.3, 0.4, 0.5};
00320    double ey[] = {1, 0.5, 1, 0.5, 1};
00321    TGraphErrors* ge = new TGraphErrors(5, x, y, ex, ey);
00322    ge->SetFillColor(6);
00323    ge->SetFillStyle(3005);
00324    ge->Draw("a4");
00325    return c42;
00326 }
00327 End_Macro
00328 Begin_Html
00329 
00330 The following example shows how the option "[]" can be used to superimpose
00331 systematic errors on top of a graph with statistical errors.
00332 
00333 End_Html
00334 Begin_Macro(source)
00335 {
00336    TCanvas *c43 = new TCanvas("c43","c43",200,10,600,400);
00337    c43->DrawFrame(0., -0.5, 6., 2);
00338 
00339    double x[5]    = {1, 2, 3, 4, 5};
00340    double zero[5] = {0, 0, 0, 0, 0};
00341 
00342    // data set (1) with stat and sys errors
00343    double y1[5]       = {1.2, 1.15, 1.19, 0.9, 1.4};
00344    double ey_stat1[5] = {0.2, 0.18, 0.17, 0.2, 0.4};
00345    double ey_sys1[5]  = {0.5, 0.71, 0.76, 0.5, 0.45};
00346 
00347    // data set (2) with stat and sys errors
00348    double y2[5]       = {0.25, 0.18, 0.29, 0.2, 0.21};
00349    double ey_stat2[5] = {0.2, 0.18, 0.17, 0.2, 0.4};
00350    double ey_sys2[5]  = {0.63, 0.19, 0.7, 0.2, 0.7};
00351 
00352    // Now draw data set (1)
00353 
00354    // We first have to draw it only with the stat errors
00355    TGraphErrors *graph1 = new TGraphErrors(5, x, y1, zero, ey_stat1);
00356    graph1->SetMarkerStyle(20);
00357    graph1->Draw("P");
00358 
00359    // Now we have to somehow depict the sys errors
00360 
00361    TGraphErrors *graph1_sys = new TGraphErrors(5, x, y1, zero, ey_sys1);
00362    graph1_sys->Draw("[]");
00363 
00364    // Now draw data set (2)
00365 
00366    // We first have to draw it only with the stat errors
00367    TGraphErrors *graph2 = new TGraphErrors(5, x, y2, zero, ey_stat2);
00368    graph2->SetMarkerStyle(24);
00369    graph2->Draw("P");
00370 
00371    // Now we have to somehow depict the sys errors
00372 
00373    TGraphErrors *graph2_sys = new TGraphErrors(5, x, y2, zero, ey_sys2);
00374    graph2_sys->Draw("[]");
00375    return c43;
00376 }
00377 End_Macro
00378 Begin_Html
00379 
00380 <a name="GP03b"></a><h4><u>TGraphAsymmErrors</u></h4>
00381 A <tt>TGraphAsymmErrors</tt> is like a <tt>TGraphErrors</tt> but the errors
00382 defined along X and Y are not symmetric: The left and right errors are
00383 different along X and the bottom and up errors are different along Y.
00384 
00385 End_Html
00386 Begin_Macro(source)
00387 {
00388    TCanvas *c2 = new TCanvas("c2","c2",200,10,600,400);
00389    double ax[] = {0, 1, 2, 3, 4};
00390    double ay[] = {0, 2, 4, 1, 3};
00391    double aexl[] = {0.1, 0.2, 0.3, 0.4, 0.5};
00392    double aexh[] = {0.5, 0.4, 0.3, 0.2, 0.1};
00393    double aeyl[] = {1, 0.5, 1, 0.5, 1};
00394    double aeyh[] = {0.5, 1, 0.5, 1, 0.5};
00395    TGraphAsymmErrors* gae = new TGraphAsymmErrors(5, ax, ay, aexl, aexh, aeyl, aeyh);
00396    gae->SetFillColor(2);
00397    gae->SetFillStyle(3001);
00398    gae->Draw("a2");
00399    gae->Draw("p");
00400    return c2;
00401 }
00402 End_Macro
00403 Begin_Html
00404 
00405 
00406 <a name="GP03c"></a><h4><u>TGraphBentErrors</u></h4>
00407 A <tt>TGraphBentErrors</tt> is like a <tt>TGraphAsymmErrors</tt>.
00408 An extra parameter allows to bent the error bars to better see them
00409 when several graphs are drawn on the same plot.
00410 
00411 End_Html
00412 Begin_Macro(source)
00413 {
00414    TCanvas *c3 = new TCanvas("c3","c3",200,10,600,400);
00415    const Int_t n = 10;
00416    Double_t x[n]  = {-0.22, 0.05, 0.25, 0.35, 0.5, 0.61,0.7,0.85,0.89,0.95};
00417    Double_t y[n]  = {1,2.9,5.6,7.4,9,9.6,8.7,6.3,4.5,1};
00418    Double_t exl[n] = {.05,.1,.07,.07,.04,.05,.06,.07,.08,.05};
00419    Double_t eyl[n] = {.8,.7,.6,.5,.4,.4,.5,.6,.7,.8};
00420    Double_t exh[n] = {.02,.08,.05,.05,.03,.03,.04,.05,.06,.03};
00421    Double_t eyh[n] = {.6,.5,.4,.3,.2,.2,.3,.4,.5,.6};
00422    Double_t exld[n] = {.0,.0,.0,.0,.0,.0,.0,.0,.0,.0};
00423    Double_t eyld[n] = {.0,.0,.05,.0,.0,.0,.0,.0,.0,.0};
00424    Double_t exhd[n] = {.0,.0,.0,.0,.0,.0,.0,.0,.0,.0};
00425    Double_t eyhd[n] = {.0,.0,.0,.0,.0,.0,.0,.0,.05,.0};
00426    TGraphBentErrors *gr = new TGraphBentErrors(n,x,y,exl,exh,eyl,eyh,exld,exhd,eyld,eyhd);
00427    gr->SetTitle("TGraphBentErrors Example");
00428    gr->SetMarkerColor(4);
00429    gr->SetMarkerStyle(21);
00430    gr->Draw("ALP");
00431    return c3;
00432 }
00433 End_Macro
00434 Begin_Html
00435 
00436 
00437 <a name="GP04"></a><h3>TGraphPolar options</h3>
00438 
00439 The drawing options for the polar graphs are the following values:
00440 
00441 <table border=0>
00442 
00443 <tr><th valign=top>"O"</th><td>
00444 Polar labels are paint orthogonally to the polargram radius.
00445 </td></tr>
00446 
00447 <tr><th valign=top>"P"</th><td>
00448 Polymarker are paint at each point position.
00449 </td></tr>
00450 
00451 <tr><th valign=top>"E"</th><td>
00452 Paint error bars.
00453 </td></tr>
00454 
00455 <tr><th valign=top>"F"</th><td>
00456 Paint fill area (closed polygon).
00457 </td></tr>
00458 
00459 <tr><th valign=top>"A"</th><td>
00460 Force axis redrawing even if a polargram already exists.
00461 </td></tr>
00462 
00463 <tr><th valign=top>"N"</th><td>
00464 Disable the display of the polar labels.
00465 </td></tr>
00466 
00467 </table>
00468 
00469 End_Html
00470 Begin_Macro(source)
00471 {
00472    TCanvas *c1 = new TCanvas("c1","c1",500,500);
00473    TGraphPolar * grP1 = new TGraphPolar();
00474    grP1->SetTitle("TGraphPolar example");
00475 
00476    grP1->SetPoint(0, (1*TMath::Pi())/4., 0.05);
00477    grP1->SetPoint(1, (2*TMath::Pi())/4., 0.10);
00478    grP1->SetPoint(2, (3*TMath::Pi())/4., 0.15);
00479    grP1->SetPoint(3, (4*TMath::Pi())/4., 0.20);
00480    grP1->SetPoint(4, (5*TMath::Pi())/4., 0.25);
00481    grP1->SetPoint(5, (6*TMath::Pi())/4., 0.30);
00482    grP1->SetPoint(6, (7*TMath::Pi())/4., 0.35);
00483    grP1->SetPoint(7, (8*TMath::Pi())/4., 0.40);
00484 
00485    grP1->SetMarkerStyle(20);
00486    grP1->SetMarkerSize(1.);
00487    grP1->SetMarkerColor(4);
00488    grP1->SetLineColor(4);
00489    grP1->Draw("ALP");
00490 
00491    // Update, otherwise GetPolargram returns 0
00492    c1->Update();
00493    grP1->GetPolargram()->SetToRadian();
00494 
00495    return c1;
00496 }
00497 End_Macro
00498 Begin_Html
00499 
00500 End_Html */
00501 
00502 
00503 //______________________________________________________________________________
00504 TGraphPainter::TGraphPainter()
00505 {
00506    /* Begin_Html
00507    Default constructor
00508    End_Html */
00509 }
00510 
00511 
00512 //______________________________________________________________________________
00513 TGraphPainter::~TGraphPainter()
00514 {
00515    /* Begin_Html
00516    Destructor.
00517    End_Html */
00518 }
00519 
00520 
00521 //______________________________________________________________________________
00522 void TGraphPainter::ComputeLogs(Int_t npoints, Int_t opt)
00523 {
00524    /* Begin_Html
00525    Compute the lorarithm of global variables <tt>gxwork</tt> and <tt>gywork</tt>
00526    according to the value of Options and put the results in the global
00527    variables <tt>gxworkl</tt> and <tt>gyworkl</tt>.
00528    <p>
00529    npoints : Number of points in gxwork and in gywork.
00530    <ul>
00531    <li> opt = 1 CompulteLogs is called from PaintGrapHist
00532    <li> opt = 0 CompulteLogs is called from PaintGraph
00533    </ul>
00534    End_Html */
00535 
00536    Int_t i;
00537    memcpy(gxworkl,gxwork,npoints*8);
00538    memcpy(gyworkl,gywork,npoints*8);
00539    if (gPad->GetLogx()) {
00540       for (i=0;i<npoints;i++) {
00541          if (gxworkl[i] > 0) gxworkl[i] = TMath::Log10(gxworkl[i]);
00542          else                gxworkl[i] = gPad->GetX1();
00543       }
00544    }
00545    if (!opt && gPad->GetLogy()) {
00546       for (i=0;i<npoints;i++) {
00547          if (gyworkl[i] > 0) gyworkl[i] = TMath::Log10(gyworkl[i]);
00548          else                gyworkl[i] = gPad->GetY1();
00549       }
00550    }
00551 }
00552 
00553 
00554 //______________________________________________________________________________
00555 Int_t TGraphPainter::DistancetoPrimitiveHelper(TGraph *theGraph, Int_t px, Int_t py)
00556 {
00557    /* Begin_Html
00558    Compute distance from point px,py to a graph.
00559    <p>
00560    Compute the closest distance of approach from point px,py to this line.
00561    The distance is computed in pixels units.
00562    End_Html */
00563 
00564    // Are we on the axis?
00565    Int_t distance;
00566    if (theGraph->GetHistogram()) {
00567       distance = theGraph->GetHistogram()->DistancetoPrimitive(px,py);
00568       if (distance <= 5) return distance;
00569    }
00570 
00571    // Somewhere on the graph points?
00572    const Int_t big = 9999;
00573    const Int_t kMaxDiff = 10;
00574    Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
00575    Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
00576    Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
00577    Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
00578 
00579    // return if point is not in the graph area
00580    if (px <= puxmin) return big;
00581    if (py >= puymin) return big;
00582    if (px >= puxmax) return big;
00583    if (py <= puymax) return big;
00584 
00585    // check if point is near one of the graph points
00586    Int_t i, pxp, pyp, d;
00587    distance = big;
00588 
00589    Int_t theNpoints = theGraph->GetN();
00590    Double_t *theX, *theY;
00591    if (theGraph->InheritsFrom(TGraphPolar::Class())) {
00592       TGraphPolar *theGraphPolar = (TGraphPolar*) theGraph;
00593       theX   = theGraphPolar->GetXpol();
00594       theY   = theGraphPolar->GetYpol();
00595    } else {
00596       theX   = theGraph->GetX();
00597       theY   = theGraph->GetY();
00598    }
00599 
00600    for (i=0;i<theNpoints;i++) {
00601       pxp = gPad->XtoAbsPixel(gPad->XtoPad(theX[i]));
00602       pyp = gPad->YtoAbsPixel(gPad->YtoPad(theY[i]));
00603       d   = TMath::Abs(pxp-px) + TMath::Abs(pyp-py);
00604       if (d < distance) distance = d;
00605    }
00606    if (distance < kMaxDiff) return distance;
00607 
00608    for (i=0;i<theNpoints-1;i++) {
00609       TAttLine l;
00610       d = l.DistancetoLine(px, py, gPad->XtoPad(theX[i]), gPad->YtoPad(theY[i]), gPad->XtoPad(theX[i+1]), gPad->YtoPad(theY[i+1]));
00611       if (d < distance) distance = d;
00612    }
00613 
00614    // If graph has been drawn with the fill area option, check if we are inside
00615    TString drawOption = theGraph->GetDrawOption();
00616    drawOption.ToLower();
00617    if (drawOption.Contains("f")) {
00618       Double_t xp = gPad->AbsPixeltoX(px); xp = gPad->PadtoX(xp);
00619       Double_t yp = gPad->AbsPixeltoY(py); yp = gPad->PadtoY(yp);
00620       if (TMath::IsInside(xp,yp,theNpoints,theX,theY) != 0) distance = 1;
00621    }
00622 
00623    // Loop on the list of associated functions and user objects
00624    TObject *f;
00625    TList *functions = theGraph->GetListOfFunctions();
00626    TIter   next(functions);
00627    while ((f = (TObject*) next())) {
00628       Int_t dist;
00629       if (f->InheritsFrom(TF1::Class())) dist = f->DistancetoPrimitive(-px,py);
00630       else                               dist = f->DistancetoPrimitive(px,py);
00631       if (dist < kMaxDiff) {
00632          gPad->SetSelected(f);
00633          return 0; //must be o and not dist in case of TMultiGraph
00634       }
00635    }
00636 
00637    return distance;
00638 }
00639 
00640 
00641 //______________________________________________________________________________
00642 void TGraphPainter::DrawPanelHelper(TGraph *theGraph)
00643 {
00644    /* Begin_html
00645    Display a panel with all histogram drawing options.
00646    End_html */
00647 
00648    if (!gPad) {
00649       Error("DrawPanel", "need to draw graph first");
00650       return;
00651    }
00652    TVirtualPadEditor *editor = TVirtualPadEditor::GetPadEditor();
00653    editor->Show();
00654    gROOT->ProcessLine(Form("((TCanvas*)0x%lx)->Selected((TVirtualPad*)0x%lx,(TObject*)0x%lx,1)",
00655                            (ULong_t)gPad->GetCanvas(), (ULong_t)gPad, (ULong_t)theGraph));
00656 }
00657 
00658 
00659 //______________________________________________________________________________
00660 void TGraphPainter::ExecuteEventHelper(TGraph *theGraph, Int_t event, Int_t px, Int_t py)
00661 {
00662    /* Begin_Html
00663    Execute action corresponding to one event.
00664    <p>
00665    This member function is called when a graph is clicked with the locator.
00666    <p>
00667    If the left mouse button is clicked on one of the line end points, this point
00668    follows the cursor until button is released.
00669    <p>
00670    If the middle mouse button clicked, the line is moved parallel to itself
00671    until the button is released.
00672    End_Html */
00673 
00674    Int_t i, d;
00675    Double_t xmin, xmax, ymin, ymax, dx, dy, dxr, dyr;
00676    const Int_t kMaxDiff =  3;
00677    static Bool_t middle, badcase;
00678    static Int_t ipoint, pxp, pyp;
00679    static Int_t px1,px2,py1,py2;
00680    static Int_t pxold, pyold, px1old, py1old, px2old, py2old;
00681    static Int_t dpx, dpy;
00682    static Int_t *x=0, *y=0;
00683 
00684    if (!theGraph->IsEditable() || theGraph->InheritsFrom(TGraphPolar::Class())) {
00685       gPad->SetCursor(kHand);
00686       return;
00687    }
00688    if (!gPad->IsEditable()) return;
00689    Int_t theNpoints = theGraph->GetN();
00690    Double_t *theX  = theGraph->GetX();
00691    Double_t *theY  = theGraph->GetY();
00692 
00693    switch (event) {
00694 
00695    case kButton1Down:
00696       badcase = kFALSE;
00697       gVirtualX->SetLineColor(-1);
00698       theGraph->TAttLine::Modify();  //Change line attributes only if necessary
00699       px1 = gPad->XtoAbsPixel(gPad->GetX1());
00700       py1 = gPad->YtoAbsPixel(gPad->GetY1());
00701       px2 = gPad->XtoAbsPixel(gPad->GetX2());
00702       py2 = gPad->YtoAbsPixel(gPad->GetY2());
00703       ipoint = -1;
00704 
00705 
00706       if (x || y) break;
00707       x = new Int_t[theNpoints+1];
00708       y = new Int_t[theNpoints+1];
00709       for (i=0;i<theNpoints;i++) {
00710          pxp = gPad->XtoAbsPixel(gPad->XtoPad(theX[i]));
00711          pyp = gPad->YtoAbsPixel(gPad->YtoPad(theY[i]));
00712          if (pxp < -kMaxPixel || pxp >= kMaxPixel ||
00713              pyp < -kMaxPixel || pyp >= kMaxPixel) {
00714             badcase = kTRUE;
00715             continue;
00716          }
00717          gVirtualX->DrawLine(pxp-4, pyp-4, pxp+4,  pyp-4);
00718          gVirtualX->DrawLine(pxp+4, pyp-4, pxp+4,  pyp+4);
00719          gVirtualX->DrawLine(pxp+4, pyp+4, pxp-4,  pyp+4);
00720          gVirtualX->DrawLine(pxp-4, pyp+4, pxp-4,  pyp-4);
00721          x[i] = pxp;
00722          y[i] = pyp;
00723          d   = TMath::Abs(pxp-px) + TMath::Abs(pyp-py);
00724          if (d < kMaxDiff) ipoint =i;
00725       }
00726       dpx = 0;
00727       dpy = 0;
00728       pxold = px;
00729       pyold = py;
00730       if (ipoint < 0) return;
00731       if (ipoint == 0) {
00732          px1old = 0;
00733          py1old = 0;
00734          px2old = gPad->XtoAbsPixel(theX[1]);
00735          py2old = gPad->YtoAbsPixel(theY[1]);
00736       } else if (ipoint == theNpoints-1) {
00737          px1old = gPad->XtoAbsPixel(gPad->XtoPad(theX[theNpoints-2]));
00738          py1old = gPad->YtoAbsPixel(gPad->YtoPad(theY[theNpoints-2]));
00739          px2old = 0;
00740          py2old = 0;
00741       } else {
00742          px1old = gPad->XtoAbsPixel(gPad->XtoPad(theX[ipoint-1]));
00743          py1old = gPad->YtoAbsPixel(gPad->YtoPad(theY[ipoint-1]));
00744          px2old = gPad->XtoAbsPixel(gPad->XtoPad(theX[ipoint+1]));
00745          py2old = gPad->YtoAbsPixel(gPad->YtoPad(theY[ipoint+1]));
00746       }
00747       pxold = gPad->XtoAbsPixel(gPad->XtoPad(theX[ipoint]));
00748       pyold = gPad->YtoAbsPixel(gPad->YtoPad(theY[ipoint]));
00749 
00750       break;
00751 
00752 
00753    case kMouseMotion:
00754 
00755       middle = kTRUE;
00756       for (i=0;i<theNpoints;i++) {
00757          pxp = gPad->XtoAbsPixel(gPad->XtoPad(theX[i]));
00758          pyp = gPad->YtoAbsPixel(gPad->YtoPad(theY[i]));
00759          d   = TMath::Abs(pxp-px) + TMath::Abs(pyp-py);
00760          if (d < kMaxDiff) middle = kFALSE;
00761       }
00762 
00763 
00764    // check if point is close to an axis
00765       if (middle) gPad->SetCursor(kMove);
00766       else gPad->SetCursor(kHand);
00767       break;
00768 
00769    case kButton1Motion:
00770       if (middle) {
00771          for(i=0;i<theNpoints-1;i++) {
00772             gVirtualX->DrawLine(x[i]+dpx, y[i]+dpy, x[i+1]+dpx, y[i+1]+dpy);
00773             pxp = x[i]+dpx;
00774             pyp = y[i]+dpy;
00775             if (pxp < -kMaxPixel || pxp >= kMaxPixel ||
00776                 pyp < -kMaxPixel || pyp >= kMaxPixel) continue;
00777             gVirtualX->DrawLine(pxp-4, pyp-4, pxp+4,  pyp-4);
00778             gVirtualX->DrawLine(pxp+4, pyp-4, pxp+4,  pyp+4);
00779             gVirtualX->DrawLine(pxp+4, pyp+4, pxp-4,  pyp+4);
00780             gVirtualX->DrawLine(pxp-4, pyp+4, pxp-4,  pyp-4);
00781          }
00782          pxp = x[theNpoints-1]+dpx;
00783          pyp = y[theNpoints-1]+dpy;
00784          gVirtualX->DrawLine(pxp-4, pyp-4, pxp+4,  pyp-4);
00785          gVirtualX->DrawLine(pxp+4, pyp-4, pxp+4,  pyp+4);
00786          gVirtualX->DrawLine(pxp+4, pyp+4, pxp-4,  pyp+4);
00787          gVirtualX->DrawLine(pxp-4, pyp+4, pxp-4,  pyp-4);
00788          dpx += px - pxold;
00789          dpy += py - pyold;
00790          pxold = px;
00791          pyold = py;
00792          for(i=0;i<theNpoints-1;i++) {
00793             gVirtualX->DrawLine(x[i]+dpx, y[i]+dpy, x[i+1]+dpx, y[i+1]+dpy);
00794             pxp = x[i]+dpx;
00795             pyp = y[i]+dpy;
00796             if (pxp < -kMaxPixel || pxp >= kMaxPixel ||
00797                 pyp < -kMaxPixel || pyp >= kMaxPixel) continue;
00798             gVirtualX->DrawLine(pxp-4, pyp-4, pxp+4,  pyp-4);
00799             gVirtualX->DrawLine(pxp+4, pyp-4, pxp+4,  pyp+4);
00800             gVirtualX->DrawLine(pxp+4, pyp+4, pxp-4,  pyp+4);
00801             gVirtualX->DrawLine(pxp-4, pyp+4, pxp-4,  pyp-4);
00802          }
00803          pxp = x[theNpoints-1]+dpx;
00804          pyp = y[theNpoints-1]+dpy;
00805          gVirtualX->DrawLine(pxp-4, pyp-4, pxp+4,  pyp-4);
00806          gVirtualX->DrawLine(pxp+4, pyp-4, pxp+4,  pyp+4);
00807          gVirtualX->DrawLine(pxp+4, pyp+4, pxp-4,  pyp+4);
00808          gVirtualX->DrawLine(pxp-4, pyp+4, pxp-4,  pyp-4);
00809       } else {
00810          if (px1old) gVirtualX->DrawLine(px1old, py1old, pxold,  pyold);
00811          if (px2old) gVirtualX->DrawLine(pxold,  pyold,  px2old, py2old);
00812          gVirtualX->DrawLine(pxold-4, pyold-4, pxold+4,  pyold-4);
00813          gVirtualX->DrawLine(pxold+4, pyold-4, pxold+4,  pyold+4);
00814          gVirtualX->DrawLine(pxold+4, pyold+4, pxold-4,  pyold+4);
00815          gVirtualX->DrawLine(pxold-4, pyold+4, pxold-4,  pyold-4);
00816          pxold = px;
00817          pxold = TMath::Max(pxold, px1);
00818          pxold = TMath::Min(pxold, px2);
00819          pyold = py;
00820          pyold = TMath::Max(pyold, py2);
00821          pyold = TMath::Min(pyold, py1);
00822          if (px1old) gVirtualX->DrawLine(px1old, py1old, pxold,  pyold);
00823          if (px2old) gVirtualX->DrawLine(pxold,  pyold,  px2old, py2old);
00824          gVirtualX->DrawLine(pxold-4, pyold-4, pxold+4,  pyold-4);
00825          gVirtualX->DrawLine(pxold+4, pyold-4, pxold+4,  pyold+4);
00826          gVirtualX->DrawLine(pxold+4, pyold+4, pxold-4,  pyold+4);
00827          gVirtualX->DrawLine(pxold-4, pyold+4, pxold-4,  pyold-4);
00828       }
00829       break;
00830 
00831    case kButton1Up:
00832 
00833       if (gROOT->IsEscaped()) {
00834          gROOT->SetEscape(kFALSE);
00835          delete [] x; x = 0;
00836          delete [] y; y = 0;
00837          break;
00838       }
00839 
00840    // Compute x,y range
00841       xmin = gPad->GetUxmin();
00842       xmax = gPad->GetUxmax();
00843       ymin = gPad->GetUymin();
00844       ymax = gPad->GetUymax();
00845       dx   = xmax-xmin;
00846       dy   = ymax-ymin;
00847       dxr  = dx/(1 - gPad->GetLeftMargin() - gPad->GetRightMargin());
00848       dyr  = dy/(1 - gPad->GetBottomMargin() - gPad->GetTopMargin());
00849 
00850       if (theGraph->GetHistogram()) {
00851          // Range() could change the size of the pad pixmap and therefore should
00852          // be called before the other paint routines
00853          gPad->Range(xmin - dxr*gPad->GetLeftMargin(),
00854                       ymin - dyr*gPad->GetBottomMargin(),
00855                       xmax + dxr*gPad->GetRightMargin(),
00856                       ymax + dyr*gPad->GetTopMargin());
00857          gPad->RangeAxis(xmin, ymin, xmax, ymax);
00858       }
00859       if (middle) {
00860          for(i=0;i<theNpoints;i++) {
00861             if (badcase) continue;  //do not update if big zoom and points moved
00862             if (x) theX[i] = gPad->PadtoX(gPad->AbsPixeltoX(x[i]+dpx));
00863             if (y) theY[i] = gPad->PadtoY(gPad->AbsPixeltoY(y[i]+dpy));
00864          }
00865       } else {
00866          theX[ipoint] = gPad->PadtoX(gPad->AbsPixeltoX(pxold));
00867          theY[ipoint] = gPad->PadtoY(gPad->AbsPixeltoY(pyold));
00868          if (theGraph->InheritsFrom("TCutG")) {
00869             //make sure first and last point are the same
00870             if (ipoint == 0) {
00871                theX[theNpoints-1] = theX[0];
00872                theY[theNpoints-1] = theY[0];
00873             }
00874             if (ipoint == theNpoints-1) {
00875                theX[0] = theX[theNpoints-1];
00876                theY[0] = theY[theNpoints-1];
00877             }
00878          }
00879       }
00880       badcase = kFALSE;
00881       delete [] x; x = 0;
00882       delete [] y; y = 0;
00883       gPad->Modified(kTRUE);
00884       gVirtualX->SetLineColor(-1);
00885    }
00886 }
00887 
00888 
00889 //______________________________________________________________________________
00890 char *TGraphPainter::GetObjectInfoHelper(TGraph * /*theGraph*/, Int_t /*px*/, Int_t /*py*/) const
00891 {
00892    return (char*)"";
00893 }
00894 
00895 
00896 //______________________________________________________________________________
00897 void TGraphPainter::PaintHelper(TGraph *theGraph, Option_t *option)
00898 {
00899    /* Begin_Html
00900    Paint a any kind of TGraph
00901    End_Html */
00902 
00903    if (theGraph) {
00904       SetBit(TGraph::kClipFrame, theGraph->TestBit(TGraph::kClipFrame));
00905       if (theGraph->InheritsFrom(TGraphBentErrors::Class())) {
00906          PaintGraphBentErrors(theGraph,option);
00907       } else if (theGraph->InheritsFrom(TGraphQQ::Class())) {
00908          PaintGraphQQ(theGraph,option);
00909       } else if (theGraph->InheritsFrom(TGraphAsymmErrors::Class())) {
00910          PaintGraphAsymmErrors(theGraph,option);
00911       } else if (theGraph->InheritsFrom(TGraphErrors::Class())) {
00912          if (theGraph->InheritsFrom(TGraphPolar::Class())) {
00913             PaintGraphPolar(theGraph,option);
00914          } else {
00915             PaintGraphErrors(theGraph,option);
00916          }
00917       } else {
00918          PaintGraphSimple(theGraph,option);
00919       }
00920    }
00921 }
00922 
00923 
00924 //______________________________________________________________________________
00925 void TGraphPainter::PaintGraph(TGraph *theGraph, Int_t npoints, const Double_t *x, const Double_t *y, Option_t *chopt)
00926 {
00927    /* Begin_Html
00928    <a href="#GP01">Control function to draw a graph.</a>
00929    End_Html */
00930 
00931    Int_t optionLine , optionAxis , optionCurve, optionStar , optionMark;
00932    Int_t optionBar  , optionR    , optionOne  , optionE;
00933    Int_t optionFill , optionZ    , optionCurveFill;
00934    Int_t i, npt, nloop;
00935    Int_t drawtype=0;
00936    Double_t xlow, xhigh, ylow, yhigh;
00937    Double_t barxmin, barxmax, barymin, barymax;
00938    Double_t uxmin, uxmax;
00939    Double_t x1, xn, y1, yn;
00940    Double_t dbar, bdelta;
00941    Int_t theNpoints = theGraph->GetN();
00942 
00943    if (npoints <= 0) {
00944       Error("PaintGraph", "illegal number of points (%d)", npoints);
00945       return;
00946    }
00947    TString opt = chopt;
00948    opt.ToUpper();
00949    opt.ReplaceAll("SAME","");
00950 
00951    if(opt.Contains("L")) optionLine = 1;  else optionLine = 0;
00952    if(opt.Contains("A")) optionAxis = 1;  else optionAxis = 0;
00953    if(opt.Contains("C")) optionCurve= 1;  else optionCurve= 0;
00954    if(opt.Contains("*")) optionStar = 1;  else optionStar = 0;
00955    if(opt.Contains("P")) optionMark = 1;  else optionMark = 0;
00956    if(opt.Contains("B")) optionBar  = 1;  else optionBar  = 0;
00957    if(opt.Contains("R")) optionR    = 1;  else optionR    = 0;
00958    if(opt.Contains("1")) optionOne  = 1;  else optionOne  = 0;
00959    if(opt.Contains("F")) optionFill = 1;  else optionFill = 0;
00960    if(opt.Contains("2") || opt.Contains("3") ||
00961       opt.Contains("4")) optionE = 1;  else optionE = 0;
00962    optionZ    = 0;
00963 
00964    // If no "drawing" option is selected and if chopt<>' ' nothing is done.
00965    if (optionLine+optionFill+optionCurve+optionStar+optionMark+optionBar+optionE == 0) {
00966       if (strlen(chopt) == 0)  optionLine=1;
00967       else   return;
00968    }
00969 
00970    if (optionStar) theGraph->SetMarkerStyle(3);
00971 
00972    optionCurveFill = 0;
00973    if (optionCurve && optionFill) {
00974       optionCurveFill = 1;
00975       optionFill      = 0;
00976    }
00977 
00978    // Draw the Axis.
00979    Double_t rwxmin,rwxmax, rwymin, rwymax, maximum, minimum, dx, dy;
00980    if (optionAxis) {
00981       if (theGraph->GetHistogram()) {
00982          rwxmin    = gPad->GetUxmin();
00983          rwxmax    = gPad->GetUxmax();
00984          rwymin    = gPad->GetUymin();
00985          rwymax    = gPad->GetUymax();
00986          minimum   = theGraph->GetHistogram()->GetMinimumStored();
00987          maximum   = theGraph->GetHistogram()->GetMaximumStored();
00988          if (minimum == -1111) { //this can happen after unzooming
00989             minimum = theGraph->GetHistogram()->GetYaxis()->GetXmin();
00990             theGraph->GetHistogram()->SetMinimum(minimum);
00991          }
00992          if (maximum == -1111) {
00993             maximum = theGraph->GetHistogram()->GetYaxis()->GetXmax();
00994             theGraph->GetHistogram()->SetMaximum(maximum);
00995          }
00996          uxmin     = gPad->PadtoX(rwxmin);
00997          uxmax     = gPad->PadtoX(rwxmax);
00998       } else {
00999 
01000          theGraph->ComputeRange(rwxmin, rwymin, rwxmax, rwymax);  //this is redefined in TGraphErrors
01001 
01002          if (rwxmin == rwxmax) rwxmax += 1.;
01003          if (rwymin == rwymax) rwymax += 1.;
01004          dx = 0.1*(rwxmax-rwxmin);
01005          dy = 0.1*(rwymax-rwymin);
01006          uxmin    = rwxmin - dx;
01007          uxmax    = rwxmax + dx;
01008          minimum  = rwymin - dy;
01009          maximum  = rwymax + dy;
01010       }
01011       if (theGraph->GetMinimum() != -1111) rwymin = minimum = theGraph->GetMinimum();
01012       if (theGraph->GetMaximum() != -1111) rwymax = maximum = theGraph->GetMaximum();
01013       if (uxmin < 0 && rwxmin >= 0) uxmin = 0.9*rwxmin;
01014       if (uxmax > 0 && rwxmax <= 0) {
01015          if (gPad->GetLogx()) uxmax = 1.1*rwxmax;
01016          else                 uxmax = 0;
01017       }
01018       if (minimum < 0 && rwymin >= 0) minimum = 0.9*rwymin;
01019       if (maximum > 0 && rwymax <= 0) {
01020          //if(gPad->GetLogy()) maximum = 1.1*rwymax;
01021          //else                maximum = 0;
01022       }
01023       if (minimum <= 0 && gPad->GetLogy()) minimum = 0.001*maximum;
01024       if (uxmin <= 0 && gPad->GetLogx()) {
01025          if (uxmax > 1000) uxmin = 1;
01026          else              uxmin = 0.001*uxmax;
01027       }
01028       rwymin = minimum;
01029       rwymax = maximum;
01030 
01031       // Create a temporary histogram and fill each channel with the
01032       // function value.
01033       char chopth[8] = " ";
01034       if (strstr(chopt,"x+")) strncat(chopth, "x+",2);
01035       if (strstr(chopt,"y+")) strncat(chopth, "y+",2);
01036       if (!theGraph->GetHistogram()) {
01037          // the graph is created with at least as many channels as there are
01038          // points to permit zooming on the full range.
01039          rwxmin = uxmin;
01040          rwxmax = uxmax;
01041          npt = 100;
01042          if (theNpoints > npt) npt = theNpoints;
01043          TH1 *h = new TH1F(Form("%s_h",GetName()),GetTitle(),npt,rwxmin,rwxmax);
01044          theGraph->SetHistogram(h);
01045          if (!theGraph->GetHistogram()) return;
01046          theGraph->GetHistogram()->SetMinimum(rwymin);
01047          theGraph->GetHistogram()->SetMaximum(rwymax);
01048          theGraph->GetHistogram()->GetYaxis()->SetLimits(rwymin,rwymax);
01049          theGraph->GetHistogram()->SetBit(TH1::kNoStats);
01050          theGraph->GetHistogram()->SetDirectory(0);
01051          theGraph->GetHistogram()->Paint(chopth); // Draw histogram axis, title and grid
01052       } else {
01053          if (gPad->GetLogy()) {
01054             theGraph->GetHistogram()->SetMinimum(rwymin);
01055             theGraph->GetHistogram()->SetMaximum(rwymax);
01056             theGraph->GetHistogram()->GetYaxis()->SetLimits(rwymin,rwymax);
01057          }
01058          theGraph->GetHistogram()->Paint(chopth); // Draw histogram axis, title and grid
01059       }
01060    }
01061 
01062    // Set Clipping option
01063    gPad->SetBit(TGraph::kClipFrame, theGraph->TestBit(TGraph::kClipFrame));
01064 
01065    TF1 *fit = 0;
01066    TList *functions = theGraph->GetListOfFunctions();
01067    TObject *f;
01068    if (functions) {
01069       f = (TF1*)functions->First();
01070       if (f) {
01071          if (f->InheritsFrom(TF1::Class())) fit = (TF1*)f;
01072       }
01073       TIter   next(functions);
01074       while ((f = (TObject*) next())) {
01075          if (f->InheritsFrom(TF1::Class())) {
01076             fit = (TF1*)f;
01077             break;
01078          }
01079       }
01080    }
01081    if (fit) PaintStats(theGraph, fit);
01082 
01083    rwxmin   = gPad->GetUxmin();
01084    rwxmax   = gPad->GetUxmax();
01085    rwymin   = gPad->GetUymin();
01086    rwymax   = gPad->GetUymax();
01087    uxmin    = gPad->PadtoX(rwxmin);
01088    uxmax    = gPad->PadtoX(rwxmax);
01089    if (theGraph->GetHistogram() && !theGraph->InheritsFrom("TGraphPolar")) {
01090       maximum = theGraph->GetHistogram()->GetMaximum();
01091       minimum = theGraph->GetHistogram()->GetMinimum();
01092    } else {
01093       maximum = gPad->PadtoY(rwymax);
01094       minimum = gPad->PadtoY(rwymin);
01095    }
01096 
01097    // Set attributes
01098    theGraph->TAttLine::Modify();
01099    theGraph->TAttFill::Modify();
01100    theGraph->TAttMarker::Modify();
01101 
01102    // Draw the graph with a polyline or a fill area
01103    gxwork  = new Double_t[2*npoints+10];
01104    gywork  = new Double_t[2*npoints+10];
01105    gxworkl = new Double_t[2*npoints+10];
01106    gyworkl = new Double_t[2*npoints+10];
01107 
01108    if (optionLine || optionFill) {
01109       x1    = x[0];
01110       xn    = x[npoints-1];
01111       y1    = y[0];
01112       yn    = y[npoints-1];
01113       nloop = npoints;
01114       if (optionFill && (xn != x1 || yn != y1)) nloop++;
01115       npt = 0;
01116       for (i=1;i<=nloop;i++) {
01117          if (i > npoints) {
01118             gxwork[npt] = gxwork[0];  gywork[npt] = gywork[0];
01119          } else {
01120             gxwork[npt] = x[i-1];      gywork[npt] = y[i-1];
01121             npt++;
01122          }
01123          if (i == nloop) {
01124             ComputeLogs(npt, optionZ);
01125             Int_t bord = gStyle->GetDrawBorder();
01126             if (optionR) {
01127                if (optionFill) {
01128                   gPad->PaintFillArea(npt,gyworkl,gxworkl);
01129                   if (bord) gPad->PaintPolyLine(npt,gyworkl,gxworkl);
01130                } else {
01131                   if (TMath::Abs(theGraph->GetLineWidth())>99) PaintPolyLineHatches(theGraph, npt, gyworkl, gxworkl);
01132                   gPad->PaintPolyLine(npt,gyworkl,gxworkl);
01133                }
01134             }
01135             else {
01136                if (optionFill) {
01137                   gPad->PaintFillArea(npt,gxworkl,gyworkl);
01138                   if (bord) gPad->PaintPolyLine(npt,gxworkl,gyworkl);
01139                } else {
01140                   if (TMath::Abs(theGraph->GetLineWidth())>99) PaintPolyLineHatches(theGraph, npt, gxworkl, gyworkl);
01141                   gPad->PaintPolyLine(npt,gxworkl,gyworkl);
01142                }
01143             }
01144             gxwork[0] = gxwork[npt-1];  gywork[0] = gywork[npt-1];
01145             npt      = 1;
01146          }
01147       }
01148    }
01149 
01150    // Draw the graph with a smooth Curve. Smoothing via Smooth
01151    if (optionCurve) {
01152       x1 = x[0];
01153       xn = x[npoints-1];
01154       y1 = y[0];
01155       yn = y[npoints-1];
01156       drawtype = 1;
01157       nloop = npoints;
01158       if (optionCurveFill) {
01159          drawtype += 1000;
01160          if (xn != x1 || yn != y1) nloop++;
01161       }
01162       if (!optionR) {
01163          npt = 0;
01164          for (i=1;i<=nloop;i++) {
01165             if (i > npoints) {
01166                gxwork[npt] = gxwork[0];  gywork[npt] = gywork[0];
01167             } else {
01168                gxwork[npt] = x[i-1];      gywork[npt] = y[i-1];
01169                npt++;
01170             }
01171             ComputeLogs(npt, optionZ);
01172             if (gyworkl[npt-1] < rwymin || gyworkl[npt-1] > rwymax) {
01173                if (npt > 2) {
01174                   ComputeLogs(npt, optionZ);
01175                   Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
01176                }
01177                gxwork[0] = gxwork[npt-1]; gywork[0] = gywork[npt-1];
01178                npt=1;
01179                continue;
01180             }
01181          }
01182          if (npt > 1) {
01183             ComputeLogs(npt, optionZ);
01184             Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
01185          }
01186       }
01187       else {
01188          drawtype += 10;
01189          npt    = 0;
01190          for (i=1;i<=nloop;i++) {
01191             if (i > npoints) {
01192                gxwork[npt] = gxwork[0];  gywork[npt] = gywork[0];
01193             } else {
01194                if (y[i-1] < minimum || y[i-1] > maximum) continue;
01195                if (x[i-1] < uxmin    || x[i-1] > uxmax)  continue;
01196                gxwork[npt] = x[i-1];      gywork[npt] = y[i-1];
01197                npt++;
01198             }
01199             ComputeLogs(npt, optionZ);
01200             if (gxworkl[npt-1] < rwxmin || gxworkl[npt-1] > rwxmax) {
01201                if (npt > 2) {
01202                   ComputeLogs(npt, optionZ);
01203                   Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
01204                }
01205                gxwork[0] = gxwork[npt-1]; gywork[0] = gywork[npt-1];
01206                npt=1;
01207                continue;
01208             }
01209          }
01210          if (npt > 1) {
01211             ComputeLogs(npt, optionZ);
01212             Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
01213          }
01214       }
01215    }
01216 
01217    // Draw the graph with a '*' on every points
01218    if (optionStar) {
01219       theGraph->SetMarkerStyle(3);
01220       npt = 0;
01221       for (i=1;i<=npoints;i++) {
01222          gxwork[npt] = x[i-1];      gywork[npt] = y[i-1];
01223          npt++;
01224          if (i == npoints) {
01225             ComputeLogs(npt, optionZ);
01226             if (optionR)  gPad->PaintPolyMarker(npt,gyworkl,gxworkl);
01227             else          gPad->PaintPolyMarker(npt,gxworkl,gyworkl);
01228             npt = 0;
01229          }
01230       }
01231    }
01232 
01233    // Draw the graph with the current polymarker on every points
01234    if (optionMark) {
01235       npt = 0;
01236       for (i=1;i<=npoints;i++) {
01237          gxwork[npt] = x[i-1];      gywork[npt] = y[i-1];
01238          npt++;
01239          if (i == npoints) {
01240             ComputeLogs(npt, optionZ);
01241             if (optionR) gPad->PaintPolyMarker(npt,gyworkl,gxworkl);
01242             else         gPad->PaintPolyMarker(npt,gxworkl,gyworkl);
01243             npt = 0;
01244          }
01245       }
01246    }
01247 
01248    // Draw the graph as a bar chart
01249    if (optionBar) {
01250       if (!optionR) {
01251          barxmin = x[0];
01252          barxmax = x[0];
01253          for (i=1;i<npoints;i++) {
01254             if (x[i] < barxmin) barxmin = x[i];
01255             if (x[i] > barxmax) barxmax = x[i];
01256          }
01257          bdelta = (barxmax-barxmin)/Double_t(npoints);
01258       }
01259       else {
01260          barymin = y[0];
01261          barymax = y[0];
01262          for (i=1;i<npoints;i++) {
01263             if (y[i] < barymin) barymin = y[i];
01264             if (y[i] > barymax) barymax = y[i];
01265          }
01266          bdelta = (barymax-barymin)/Double_t(npoints);
01267       }
01268       dbar  = 0.5*bdelta*gStyle->GetBarWidth();
01269       if (!optionR) {
01270          for (i=1;i<=npoints;i++) {
01271             xlow  = x[i-1] - dbar;
01272             xhigh = x[i-1] + dbar;
01273             yhigh = y[i-1];
01274             if (xlow  < uxmin) xlow = uxmin;
01275             if (xhigh > uxmax) xhigh = uxmax;
01276             if (!optionOne) ylow = TMath::Max((Double_t)0,gPad->GetUymin());
01277             else            ylow = gPad->GetUymin();
01278             gxwork[0] = xlow;
01279             gywork[0] = ylow;
01280             gxwork[1] = xhigh;
01281             gywork[1] = yhigh;
01282             ComputeLogs(2, optionZ);
01283             if (gyworkl[0] < gPad->GetUymin()) gyworkl[0] = gPad->GetUymin();
01284             if (gyworkl[1] < gPad->GetUymin()) continue;
01285             if (gyworkl[1] > gPad->GetUymax()) gyworkl[1] = gPad->GetUymax();
01286             if (gyworkl[0] > gPad->GetUymax()) continue;
01287 
01288             gPad->PaintBox(gxworkl[0],gyworkl[0],gxworkl[1],gyworkl[1]);
01289          }
01290       }
01291       else {
01292          for (i=1;i<=npoints;i++) {
01293             xhigh = x[i-1];
01294             ylow  = y[i-1] - dbar;
01295             yhigh = y[i-1] + dbar;
01296             xlow     = TMath::Max((Double_t)0, gPad->GetUxmin());
01297             gxwork[0] = xlow;
01298             gywork[0] = ylow;
01299             gxwork[1] = xhigh;
01300             gywork[1] = yhigh;
01301             ComputeLogs(2, optionZ);
01302             gPad->PaintBox(gxworkl[0],gyworkl[0],gxworkl[1],gyworkl[1]);
01303          }
01304       }
01305    }
01306    gPad->ResetBit(TGraph::kClipFrame);
01307 
01308    delete [] gxwork;
01309    delete [] gywork;
01310    delete [] gxworkl;
01311    delete [] gyworkl;
01312 }
01313 
01314 
01315 //______________________________________________________________________________
01316 void TGraphPainter::PaintGrapHist(TGraph *theGraph, Int_t npoints, const Double_t *x,
01317                                   const Double_t *y, Option_t *chopt)
01318 {
01319    /* Begin_Html
01320    This method is used by
01321    <a href="http://root.cern.ch/root/html/THistPainter.html"><tt>THistPainter</tt></a>
01322    to paint 1D histograms.
01323    <p>
01324    Input parameters:
01325    <ul>
01326    <li> npoints : Number of points in X or in Y.
01327    <li> x[npoints] or x[0] : x coordinates or (xmin,xmax).
01328    <li> y[npoints] or y[0] : y coordinates or (ymin,ymax).
01329    <li> chopt : Option.
01330    </ul>
01331    <p>
01332    The aspect of the graph is done according to the value of the chopt.
01333    <p>
01334    <table border=0>
01335    <tr><th valign=top>"R"</th><td>
01336    Graph is drawn horizontaly, parallel to X axis. (default is vertically,
01337    parallel to Y axis)
01338    <br>
01339    If option R is selected the user must give:
01340    <ul>
01341    <li> 2 values for Y (y[0]=YMIN and y[1]=YMAX)
01342    <li> N values for X, one for each channel.
01343    </ul>
01344    Otherwise the user must give:
01345    <ul>
01346    <li> N values for Y, one for each channel.
01347    <li> 2 values for X (x[0]=XMIN and x[1]=XMAX)
01348    </ul>
01349    </td></tr>
01350 
01351    <tr><th valign=top>"L"</th><td>
01352    A simple polyline beetwen every points is drawn
01353    </td></tr>
01354 
01355    <tr><th valign=top>"H"</th><td>
01356    An Histogram with equidistant bins is drawn
01357    as a polyline.
01358    </td></tr>
01359 
01360    <tr><th valign=top>"F"</th><td>
01361    An histogram with equidistant bins is drawn
01362    as a fill area. Contour is not drawn unless
01363    chopt='H' is also selected..
01364    </td></tr>
01365 
01366    <tr><th valign=top>"N"</th><td>
01367    Non equidistant bins (default is equidistant)
01368    If N is the number of channels array X and Y
01369    must be dimensionned as follow:
01370    If option R is not selected (default) then
01371    the user must give:
01372      (N+1) values for X (limits of channels).
01373       N values for Y, one for each channel.
01374    Otherwise the user must give:
01375      (N+1) values for Y (limits of channels).
01376       N values for X, one for each channel.
01377    </td></tr>
01378 
01379    <tr><th valign=top>"F1"</th><td>
01380    Idem as 'F' except that fill area is no more
01381    reparted arround axis X=0 or Y=0 .
01382    </td></tr>
01383 
01384    <tr><th valign=top>"F2"</th><td>
01385    Draw a Fill area polyline connecting the center of bins
01386    </td></tr>
01387 
01388    <tr><th valign=top>"C"</th><td>
01389    A smooth Curve is drawn.
01390    </td></tr>
01391 
01392    <tr><th valign=top>"*"</th><td>
01393    A Star is plotted at the center of each bin.
01394    </td></tr>
01395 
01396    <tr><th valign=top>"P"</th><td>
01397    Idem with the current marker
01398    </td></tr>
01399 
01400    <tr><th valign=top>"P0"</th><td>
01401    Idem with the current marker. Empty bins also drawn
01402    </td></tr>
01403 
01404    <tr><th valign=top>"B"</th><td>
01405    A Bar chart with equidistant bins is drawn as fill
01406    areas (Contours are drawn).
01407    </td></tr>
01408 
01409    <tr><th valign=top>"9"</th><td>
01410    Force graph to be drawn in high resolution mode.
01411    By default, the graph is drawn in low resolution
01412    in case the number of points is greater than the number of
01413    pixels in the current pad.
01414    </td></tr>
01415 
01416    <tr><th valign=top>"]["</th><td>
01417    "Cutoff" style. When this option is selected together with
01418    H option, the first and last vertical lines of the histogram
01419    are not drawn.
01420    </td></tr>
01421 
01422    </table>
01423    End_Html */
01424 
01425    const char *where = "PaintGraphHist";
01426 
01427    Int_t optionLine , optionAxis , optionCurve, optionStar, optionMark;
01428    Int_t optionBar  , optionRot  , optionOne  , optionOff ;
01429    Int_t optionFill , optionZ;
01430    Int_t optionHist , optionBins , optionMarker;
01431    Int_t i, j, npt;
01432    Int_t drawtype=0, drawborder, drawbordersav;
01433    Double_t xlow, xhigh, ylow, yhigh;
01434    Double_t wmin, wmax;
01435    Double_t dbar, offset, wminstep;
01436    Double_t delta = 0;
01437    Double_t ylast = 0;
01438    Double_t xi, xi1, xj, xj1, yi1, yi, yj, yj1, xwmin, ywmin;
01439    Int_t first, last, nbins;
01440    Int_t fillarea;
01441 
01442    char choptaxis[10] = " ";
01443 
01444    if (npoints <= 0) {
01445       Error(where, "illegal number of points (%d)", npoints);
01446       return;
01447    }
01448    TString opt = chopt;
01449    opt.ToUpper();
01450    if(opt.Contains("H"))  optionHist = 1;  else optionHist = 0;
01451    if(opt.Contains("F"))  optionFill = 1;  else optionFill = 0;
01452    if(opt.Contains("C"))  optionCurve= 1;  else optionCurve= 0;
01453    if(opt.Contains("*"))  optionStar = 1;  else optionStar = 0;
01454    if(opt.Contains("R"))  optionRot  = 1;  else optionRot  = 0;
01455    if(opt.Contains("1"))  optionOne  = 1;  else optionOne  = 0;
01456    if(opt.Contains("B"))  optionBar  = 1;  else optionBar  = 0;
01457    if(opt.Contains("N"))  optionBins = 1;  else optionBins = 0;
01458    if(opt.Contains("L"))  optionLine = 1;  else optionLine = 0;
01459    if(opt.Contains("P"))  optionMark = 1;  else optionMark = 0;
01460    if(opt.Contains("A"))  optionAxis = 1;  else optionAxis = 0;
01461    if(opt.Contains("][")) optionOff  = 1;  else optionOff  = 0;
01462    if(opt.Contains("P0")) optionMark = 10;
01463 
01464    Int_t optionFill2 = 0;
01465    if(opt.Contains("F") && opt.Contains("2")) {
01466       optionFill = 0; optionFill2 = 1;
01467    }
01468 
01469    // Set Clipping option
01470    Option_t *noClip;
01471    if (theGraph->TestBit(TGraph::kClipFrame)) noClip = "";
01472    else noClip = "C";
01473    gPad->SetBit(TGraph::kClipFrame, theGraph->TestBit(TGraph::kClipFrame));
01474 
01475    optionZ = 1;
01476 
01477    if (optionStar) theGraph->SetMarkerStyle(3);
01478 
01479    first = 1;
01480    last  = npoints;
01481    nbins = last - first + 1;
01482 
01483    //           Draw the Axis with a fixed number of division: 510
01484 
01485    Double_t baroffset = gStyle->GetBarOffset();
01486    Double_t barwidth  = gStyle->GetBarWidth();
01487    Double_t rwxmin    = gPad->GetUxmin();
01488    Double_t rwxmax    = gPad->GetUxmax();
01489    Double_t rwymin    = gPad->GetUymin();
01490    Double_t rwymax    = gPad->GetUymax();
01491    Double_t uxmin     = gPad->PadtoX(rwxmin);
01492    Double_t uxmax     = gPad->PadtoX(rwxmax);
01493    Double_t rounding  = (uxmax-uxmin)*1.e-5;
01494    drawborder         = gStyle->GetDrawBorder();
01495    if (optionAxis) {
01496       Int_t nx1, nx2, ndivx, ndivy, ndiv;
01497       choptaxis[0]  = 0;
01498       Double_t rwmin  = rwxmin;
01499       Double_t rwmax  = rwxmax;
01500       ndivx = gStyle->GetNdivisions("X");
01501       ndivy = gStyle->GetNdivisions("Y");
01502       if (ndivx > 1000) {
01503          nx2   = ndivx/100;
01504          nx1   = TMath::Max(1, ndivx%100);
01505          ndivx = 100*nx2 + Int_t(Double_t(nx1)*gPad->GetAbsWNDC());
01506       }
01507       ndiv  =TMath::Abs(ndivx);
01508       // coverity [Calling risky function]
01509       if (ndivx < 0) strlcat(choptaxis, "N",10);
01510       if (gPad->GetGridx()) {
01511          // coverity [Calling risky function]
01512          strlcat(choptaxis, "W",10);
01513       }
01514       if (gPad->GetLogx()) {
01515          rwmin = TMath::Power(10,rwxmin);
01516          rwmax = TMath::Power(10,rwxmax);
01517          // coverity [Calling risky function]
01518          strlcat(choptaxis, "G",10);
01519       }
01520       TGaxis *axis = new TGaxis();
01521       axis->SetLineColor(gStyle->GetAxisColor("X"));
01522       axis->SetTextColor(gStyle->GetLabelColor("X"));
01523       axis->SetTextFont(gStyle->GetLabelFont("X"));
01524       axis->SetLabelSize(gStyle->GetLabelSize("X"));
01525       axis->SetLabelOffset(gStyle->GetLabelOffset("X"));
01526       axis->SetTickSize(gStyle->GetTickLength("X"));
01527 
01528       axis->PaintAxis(rwxmin,rwymin,rwxmax,rwymin,rwmin,rwmax,ndiv,choptaxis);
01529 
01530       choptaxis[0]  = 0;
01531       rwmin  = rwymin;
01532       rwmax  = rwymax;
01533       if (ndivy < 0) {
01534          nx2   = ndivy/100;
01535          nx1   = TMath::Max(1, ndivy%100);
01536          ndivy = 100*nx2 + Int_t(Double_t(nx1)*gPad->GetAbsHNDC());
01537          // coverity [Calling risky function]
01538          strlcat(choptaxis, "N",10);
01539       }
01540       ndiv  =TMath::Abs(ndivy);
01541       if (gPad->GetGridy()) {
01542          // coverity [Calling risky function]
01543          strlcat(choptaxis, "W",10);
01544       }
01545       if (gPad->GetLogy()) {
01546          rwmin = TMath::Power(10,rwymin);
01547          rwmax = TMath::Power(10,rwymax);
01548          // coverity [Calling risky function]
01549          strlcat(choptaxis,"G",10);
01550       }
01551       axis->SetLineColor(gStyle->GetAxisColor("Y"));
01552       axis->SetTextColor(gStyle->GetLabelColor("Y"));
01553       axis->SetTextFont(gStyle->GetLabelFont("Y"));
01554       axis->SetLabelSize(gStyle->GetLabelSize("Y"));
01555       axis->SetLabelOffset(gStyle->GetLabelOffset("Y"));
01556       axis->SetTickSize(gStyle->GetTickLength("Y"));
01557 
01558       axis->PaintAxis(rwxmin,rwymin,rwxmin,rwymax,rwmin,rwmax,ndiv,choptaxis);
01559       delete axis;
01560    }
01561 
01562 
01563    //           Set attributes
01564    theGraph->TAttLine::Modify();
01565    theGraph->TAttFill::Modify();
01566    theGraph->TAttMarker::Modify();
01567 
01568    //       Min-Max scope
01569 
01570    if (!optionRot) {wmin = x[0];   wmax = x[1];}
01571    else            {wmin = y[0];   wmax = y[1];}
01572 
01573    if (!optionBins) delta = (wmax - wmin)/ Double_t(nbins);
01574 
01575    Int_t fwidth = gPad->GetFrameLineWidth();
01576    TFrame *frame = gPad->GetFrame();
01577    if (frame) fwidth = frame->GetLineWidth();
01578    if (optionOff) fwidth = 1;
01579    Double_t dxframe = gPad->AbsPixeltoX(fwidth/2) - gPad->AbsPixeltoX(0);
01580    Double_t vxmin = gPad->PadtoX(gPad->GetUxmin() + dxframe);
01581    Double_t vxmax = gPad->PadtoX(gPad->GetUxmax() - dxframe);
01582    Double_t dyframe = -gPad->AbsPixeltoY(fwidth/2) + gPad->AbsPixeltoY(0);
01583    Double_t vymin = gPad->GetUymin() + dyframe; //y already in log scale
01584    vxmin = TMath::Max(vxmin,wmin);
01585    vxmax = TMath::Min(vxmax,wmax);
01586 
01587    //           Draw the histogram with a fill area
01588 
01589    gxwork  = new Double_t[2*npoints+10];
01590    gywork  = new Double_t[2*npoints+10];
01591    gxworkl = new Double_t[2*npoints+10];
01592    gyworkl = new Double_t[2*npoints+10];
01593 
01594    if (optionFill && !optionCurve) {
01595       fillarea = kTRUE;
01596       if (!optionRot) {
01597          gxwork[0] = vxmin;
01598          if (!optionOne) gywork[0] = TMath::Min(TMath::Max((Double_t)0,gPad->GetUymin())
01599                                                ,gPad->GetUymax());
01600          else            gywork[0] = gPad->GetUymin();
01601          npt = 2;
01602          for (j=first; j<=last;j++) {
01603             if (!optionBins) {
01604                gxwork[npt-1]   = gxwork[npt-2];
01605                gxwork[npt]     = wmin+((j-first+1)*delta);
01606                if (gxwork[npt] < gxwork[0]) gxwork[npt] = gxwork[0];
01607 
01608             }
01609             else {
01610                xj1 = x[j];      xj  = x[j-1];
01611                if (xj1 < xj) {
01612                   if (j != last) Error(where, "X must be in increasing order");
01613                   else           Error(where, "X must have N+1 values with option N");
01614                   return;
01615                }
01616                gxwork[npt-1] = x[j-1];       gxwork[npt] = x[j];
01617             }
01618             gywork[npt-1] = y[j-1];
01619             gywork[npt]   = y[j-1];
01620             if (gywork[npt] < vymin) {gywork[npt] = vymin; gywork[npt-1] = vymin;}
01621             if (gxwork[npt-1] >= uxmin-rounding && gxwork[npt] <= uxmax+rounding) npt += 2;
01622             else gxwork[npt-2] = TMath::Min(gxwork[npt], uxmax);
01623             if (j == last) {
01624                gxwork[npt-1] = gxwork[npt-2];
01625                gywork[npt-1] = gywork[0];
01626                //make sure that the fill area does not overwrite the frame
01627                //take into account the frame linewidth
01628                if (gxwork[0    ] < vxmin) {gxwork[0    ] = vxmin; gxwork[1    ] = vxmin;}
01629                if (gywork[0] < vymin) {gywork[0] = vymin; gywork[npt-1] = vymin;}
01630 
01631                //transform to log ?
01632                ComputeLogs(npt, optionZ);
01633                gPad->PaintFillArea(npt,gxworkl,gyworkl);
01634                if (drawborder) {
01635                   if (!fillarea) gyworkl[0] = ylast;
01636                   gPad->PaintPolyLine(npt-1,gxworkl,gyworkl,noClip);
01637                }
01638                continue;
01639             }
01640          }  //endfor (j=first; j<=last;j++) {
01641       }
01642       else {
01643          gywork[0] = wmin;
01644          if (!optionOne) gxwork[0] = TMath::Max((Double_t)0,gPad->GetUxmin());
01645          else            gxwork[0] = gPad->GetUxmin();
01646          npt = 2;
01647          for (j=first; j<=last;j++) {
01648             if (!optionBins) {
01649                gywork[npt-1] = gywork[npt-2];
01650                gywork[npt]   = wmin+((j-first+1)*delta);
01651             }
01652             else {
01653                yj1 = y[j];      yj  = y[j-1];
01654                if (yj1 < yj) {
01655                   if (j != last) Error(where, "Y must be in increasing order");
01656                   else           Error(where, "Y must have N+1 values with option N");
01657                   return;
01658                }
01659                gywork[npt-1] = y[j-1];       gywork[npt] = y[j];
01660             }
01661             gxwork[npt-1] = x[j-1];      gxwork[npt] = x[j-1];
01662             if (gxwork[npt-1] >= uxmin-rounding && gxwork[npt] <= uxmax+rounding) npt += 2;
01663             if (j == last) {
01664                gywork[npt-1] = gywork[npt-2];
01665                gxwork[npt-1] = gxwork[0];
01666                ComputeLogs(npt, optionZ);
01667                gPad->PaintFillArea(npt,gxworkl,gyworkl);
01668                if (drawborder) {
01669                   if (!fillarea) gyworkl[0] = ylast;
01670                   gPad->PaintPolyLine(npt-1,gxworkl,gyworkl,noClip);
01671                }
01672                continue;
01673             }
01674          }  //endfor (j=first; j<=last;j++)
01675       }
01676       theGraph->TAttLine::Modify();
01677       theGraph->TAttFill::Modify();
01678    }
01679 
01680    //      Draw a standard Histogram (default)
01681 
01682    if ((optionHist) || strlen(chopt) == 0) {
01683       if (!optionRot) {
01684          gxwork[0] = wmin;
01685          gywork[0] = gPad->GetUymin();
01686          ywmin    = gywork[0];
01687          npt      = 2;
01688          for (i=first; i<=last;i++) {
01689             if (!optionBins) {
01690                gxwork[npt-1] = gxwork[npt-2];
01691                gxwork[npt]   = wmin+((i-first+1)*delta);
01692             }
01693             else {
01694                xi1 = x[i];      xi  = x[i-1];
01695                if (xi1 < xi) {
01696                   if (i != last) Error(where, "X must be in increasing order");
01697                   else           Error(where, "X must have N+1 values with option N");
01698                   return;
01699                }
01700                gxwork[npt-1] = x[i-1];      gxwork[npt] = x[i];
01701             }
01702             gywork[npt-1] = y[i-1];
01703             gywork[npt]   = y[i-1];
01704             if (gywork[npt] < vymin) {gywork[npt] = vymin; gywork[npt-1] = vymin;}
01705             if (gxwork[npt-1] >= uxmin-rounding && gxwork[npt] <= uxmax+rounding) npt += 2;
01706             else gxwork[npt-2] = TMath::Min(gxwork[npt], uxmax);
01707             if (i == last) {
01708                gxwork[npt-1] = gxwork[npt-2];
01709                gywork[npt-1] = gywork[0];
01710                //make sure that the fill area does not overwrite the frame
01711                //take into account the frame linewidth
01712                if (gxwork[0] < vxmin) {gxwork[0] = vxmin; gxwork[1    ] = vxmin;}
01713                if (gywork[0] < vymin) {gywork[0] = vymin; gywork[npt-1] = vymin;}
01714 
01715                ComputeLogs(npt, optionZ);
01716 
01717                // do not draw the two vertical lines on the edges
01718                Int_t nbpoints = npt-2;
01719                Int_t point1  = 1;
01720 
01721                if (optionOff) {
01722                   // remove points before the low cutoff
01723                   Int_t ip;
01724                   for (ip=point1; ip<=nbpoints; ip++) {
01725                      if (gyworkl[ip] != ywmin) {
01726                         point1 = ip;
01727                         break;
01728                      }
01729                   }
01730                   // remove points after the high cutoff
01731                   Int_t point2 = nbpoints;
01732                   for (ip=point2; ip>=point1; ip--) {
01733                      if (gyworkl[ip] != ywmin) {
01734                         point2 = ip;
01735                         break;
01736                      }
01737                   }
01738                   nbpoints = point2-point1+1;
01739                } else {
01740                   // if the 1st or last bin are not on the pad limits the
01741                   // the two vertical lines on the edges are added.
01742                   if (gxwork[0] > gPad->GetUxmin()) { nbpoints++; point1 = 0; }
01743                   if (gxwork[nbpoints] < gPad->GetUxmax()) nbpoints++;
01744                }
01745 
01746                gPad->PaintPolyLine(nbpoints,&gxworkl[point1],&gyworkl[point1],noClip);
01747                continue;
01748             }
01749          }  //endfor (i=first; i<=last;i++)
01750       }
01751       else {
01752          gywork[0] = wmin;
01753          gxwork[0] = TMath::Max((Double_t)0,gPad->GetUxmin());
01754          xwmin    = gxwork[0];
01755          npt      = 2;
01756          for (i=first; i<=last;i++) {
01757             if (!optionBins) {
01758                gywork[npt-1]   = gywork[npt-2];
01759                gywork[npt] = wmin+((i-first+1)*delta);
01760             }
01761             else {
01762                yi1 = y[i];      yi  = y[i-1];
01763                if (yi1 < yi) {
01764                   if (i != last) Error(where, "Y must be in increasing order");
01765                   else           Error(where, "Y must have N+1 values with option N");
01766                   return;
01767                }
01768                gywork[npt-1] = y[i-1];      gywork[npt] = y[i];
01769             }
01770             gxwork[npt-1] = x[i-1];      gxwork[npt] = x[i-1];
01771             if (gxwork[npt-1] >= uxmin-rounding && gxwork[npt] <= uxmax+rounding) npt += 2;
01772             if (i == last) {
01773                gywork[npt-1] = gywork[npt-2];
01774                gxwork[npt-1] = xwmin;
01775                ComputeLogs(npt, optionZ);
01776                gPad->PaintPolyLine(npt,gxworkl,gyworkl,noClip);
01777                continue;
01778             }
01779          }  //endfor (i=first; i<=last;i++)
01780       }
01781    }
01782 
01783    //              Draw the histogram with a smooth Curve. The computing
01784    //              of the smoothing is done by the routine IGRAp1
01785 
01786    if (optionCurve) {
01787       if (!optionFill) drawtype = 1;
01788       else {
01789          if (!optionOne) drawtype = 2;
01790          else            drawtype = 3;
01791       }
01792       if (!optionRot) {
01793          npt = 0;
01794          for (i=first; i<=last;i++) {
01795             npt++;
01796             if (!optionBins) gxwork[npt-1] = wmin+(i-first)*delta+0.5*delta;
01797             else {
01798                xi1 = x[i];      xi  = x[i-1];
01799                if (xi1 < xi) {
01800                   if (i != last) Error(where, "X must be in increasing order");
01801                   else           Error(where, "X must have N+1 values with option N");
01802                   return;
01803                }
01804                gxwork[npt-1] = x[i-1] + 0.5*(x[i]-x[i-1]);
01805             }
01806             if (gxwork[npt-1] < uxmin || gxwork[npt-1] > uxmax) {
01807                npt--;
01808                continue;
01809             }
01810             gywork[npt-1] = y[i-1];
01811             ComputeLogs(npt, optionZ);
01812             if ((gyworkl[npt-1] < rwymin) || (gyworkl[npt-1] > rwymax)) {
01813                if (npt > 2) {
01814                   ComputeLogs(npt, optionZ);
01815                   Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
01816                }
01817                gxwork[0] = gxwork[npt-1];
01818                gywork[0] = gywork[npt-1];
01819                npt      = 1;
01820                continue;
01821             }
01822             if (npt >= 50) {
01823                ComputeLogs(50, optionZ);
01824                Smooth(theGraph, 50,gxworkl,gyworkl,drawtype);
01825                gxwork[0] = gxwork[npt-1];
01826                gywork[0] = gywork[npt-1];
01827                npt      = 1;
01828             }
01829          }  //endfor (i=first; i<=last;i++)
01830          if (npt > 1) {
01831             ComputeLogs(npt, optionZ);
01832             Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
01833          }
01834       }
01835       else {
01836          drawtype = drawtype+10;
01837          npt   = 0;
01838          for (i=first; i<=last;i++) {
01839             npt++;
01840             if (!optionBins) gywork[npt-1] = wmin+(i-first)*delta+0.5*delta;
01841             else {
01842                yi1 = y[i];      yi = y[i-1];
01843                if (yi1 < yi) {
01844                   if (i != last) Error(where, "Y must be in increasing order");
01845                   else           Error(where, "Y must have N+1 values with option N");
01846                   return;
01847                }
01848                gywork[npt-1] = y[i-1] + 0.5*(y[i]-y[i-1]);
01849             }
01850             gxwork[npt-1] = x[i-1];
01851             ComputeLogs(npt, optionZ);
01852             if ((gxworkl[npt] < uxmin) || (gxworkl[npt] > uxmax)) {
01853                if (npt > 2) {
01854                   ComputeLogs(npt, optionZ);
01855                   Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
01856                }
01857                gxwork[0] = gxwork[npt-1];
01858                gywork[0] = gywork[npt-1];
01859                npt      = 1;
01860                continue;
01861             }
01862             if (npt >= 50) {
01863                ComputeLogs(50, optionZ);
01864                Smooth(theGraph, 50,gxworkl,gyworkl,drawtype);
01865                gxwork[0] = gxwork[npt-1];
01866                gywork[0] = gywork[npt-1];
01867                npt      = 1;
01868             }
01869          }  //endfor (i=first; i<=last;i++)
01870          if (npt > 1) {
01871             ComputeLogs(npt, optionZ);
01872             Smooth(theGraph, npt,gxworkl,gyworkl,drawtype);
01873          }
01874       }
01875    }
01876 
01877    //    Draw the histogram with a simple line or/and a marker
01878 
01879    optionMarker = 0;
01880    if ((optionStar) || (optionMark))optionMarker=1;
01881    if ((optionMarker) || (optionLine)) {
01882       wminstep = wmin + 0.5*delta;
01883       Axis_t ax1,ax2,ay1,ay2;
01884       gPad->GetRangeAxis(ax1,ay1,ax2,ay2);
01885 
01886       Int_t ax1Pix = gPad->XtoAbsPixel(ax1);
01887       Int_t ax2Pix = gPad->XtoAbsPixel(ax2);
01888       Int_t ay1Pix = gPad->YtoAbsPixel(ay1);
01889       Int_t ay2Pix = gPad->YtoAbsPixel(ay2);
01890 
01891       Int_t nrPix;
01892       if (!optionRot)
01893          nrPix = ax2Pix-ax1Pix+1;
01894       else
01895          nrPix = ay2Pix-ay1Pix+1;
01896 
01897       // Make here decision whether it should be painted in high or low resolution
01898       Int_t ip, ipix, lowRes = 0;
01899       if (3*nrPix < last-first+1) {
01900          lowRes = 1;
01901       }
01902       if (optionFill2)       lowRes = 0;
01903       if (opt.Contains("9")) lowRes = 0;
01904       if (lowRes) {
01905          Double_t *minPix   = new Double_t[nrPix];
01906          Double_t *maxPix   = new Double_t[nrPix];
01907          Double_t *centrPix = new Double_t[nrPix];
01908          Int_t *nrEntries   = new Int_t[nrPix];
01909 
01910          for (ip = 0; ip < nrPix; ip++) {
01911             minPix[ip]    =  1e100;
01912             maxPix[ip]    = -1e100;
01913             nrEntries[ip] = 0;
01914          }
01915 
01916          for (ip = first; ip < last; ip++) {
01917             Double_t xw;
01918             if (!optionBins) xw = wmin + (ip-first)*delta+0.5*delta;
01919             else             xw = x[ip-1] + 0.5*(x[ip]-x[ip-1]);;
01920 
01921             if (!optionRot) {
01922                Int_t ix = gPad->XtoAbsPixel(gPad->XtoPad(xw))-ax1Pix;
01923                if (ix < 0) ix = 0;
01924                if (ix >= nrPix) ix = nrPix-1;
01925                Int_t yPixel = gPad->YtoAbsPixel(y[ip-1]);
01926                if (yPixel >= ay1Pix) continue;
01927                if (minPix[ix] > yPixel) minPix[ix] = yPixel;
01928                if (maxPix[ix] < yPixel) maxPix[ix] = yPixel;
01929                (nrEntries[ix])++;
01930             } else {
01931                Int_t iy = gPad->YtoAbsPixel(gPad->YtoPad(y[ip-1]))-ay1Pix;
01932                if (iy < 0) iy = 0;
01933                if (iy >= nrPix) iy = nrPix-1;;
01934                Int_t xPixel = gPad->XtoAbsPixel(gPad->XtoPad(xw));
01935                if (minPix[iy] > xPixel) minPix[iy] = xPixel;
01936                if (maxPix[iy] < xPixel) maxPix[iy] = xPixel;
01937                (nrEntries[iy])++;
01938             }
01939          }
01940 
01941          for (ipix = 0; ipix < nrPix; ipix++) {
01942             if (nrEntries[ipix] > 0)
01943                centrPix[ipix] = (minPix[ipix]+maxPix[ipix])/2.0;
01944             else
01945                centrPix[ipix] = 2*TMath::Max(TMath::Abs(minPix[ipix]),
01946                                              TMath::Abs(maxPix[ipix]));
01947          }
01948 
01949          Double_t *xc = new Double_t[nrPix];
01950          Double_t *yc = new Double_t[nrPix];
01951 
01952          Double_t xcadjust = 0.3*(gPad->AbsPixeltoX(ax1Pix+1) - gPad->AbsPixeltoX(ax1Pix));
01953          Double_t ycadjust = 0.3*(gPad->AbsPixeltoY(ay1Pix)   - gPad->AbsPixeltoY(ay1Pix+1));
01954          Int_t nrLine = 0;
01955          for (ipix = 0; ipix < nrPix; ipix++) {
01956             if (minPix[ipix] <= maxPix[ipix]) {
01957                Double_t xl[2]; Double_t yl[2];
01958                if (!optionRot) {
01959                   xc[nrLine] = gPad->AbsPixeltoX(ax1Pix+ipix) + xcadjust;
01960                   yc[nrLine] = gPad->AbsPixeltoY((Int_t)centrPix[ipix]);
01961 
01962                   xl[0]      = xc[nrLine];
01963                   yl[0]      = gPad->AbsPixeltoY((Int_t)minPix[ipix]);
01964                   xl[1]      = xc[nrLine];
01965                   yl[1]      = gPad->AbsPixeltoY((Int_t)maxPix[ipix]);
01966                } else {
01967                   yc[nrLine] = gPad->AbsPixeltoY(ay1Pix+ipix) + ycadjust;
01968                   xc[nrLine] = gPad->AbsPixeltoX((Int_t)centrPix[ipix]);
01969 
01970                   xl[0]      = gPad->AbsPixeltoX((Int_t)minPix[ipix]);
01971                   yl[0]      = yc[nrLine];
01972                   xl[1]      = gPad->AbsPixeltoX((Int_t)maxPix[ipix]);
01973                   yl[1]      = yc[nrLine];
01974                }
01975                if (!optionZ && gPad->GetLogx()) {
01976                   if (xc[nrLine] > 0) xc[nrLine] = TMath::Log10(xc[nrLine]);
01977                   else                xc[nrLine] = gPad->GetX1();
01978                   for (Int_t il = 0; il < 2; il++) {
01979                      if (xl[il] > 0) xl[il] = TMath::Log10(xl[il]);
01980                      else            xl[il] = gPad->GetX1();
01981                   }
01982                }
01983                if (!optionZ && gPad->GetLogy()) {
01984                   if (yc[nrLine] > 0) yc[nrLine] = TMath::Log10(yc[nrLine]);
01985                   else                yc[nrLine] = gPad->GetY1();
01986                   for (Int_t il = 0; il < 2; il++) {
01987                      if (yl[il] > 0) yl[il] = TMath::Log10(yl[il]);
01988                      else            yl[il] = gPad->GetY1();
01989                   }
01990                }
01991 
01992                gPad->PaintPolyLine(2,xl,yl,noClip);
01993                nrLine++;
01994             }
01995          }
01996 
01997          gPad->PaintPolyLine(nrLine,xc,yc,noClip);
01998 
01999          delete [] xc;
02000          delete [] yc;
02001 
02002          delete [] minPix;
02003          delete [] maxPix;
02004          delete [] centrPix;
02005          delete [] nrEntries;
02006       } else {
02007          if (!optionRot) {
02008             npt = 0;
02009             for (i=first; i<=last;i++) {
02010                npt++;
02011                if (!optionBins) gxwork[npt-1] = wmin+(i-first)*delta+0.5*delta;
02012                else {
02013                   xi1 = x[i];      xi = x[i-1];
02014                   if (xi1 < xi) {
02015                      if (i != last) Error(where, "X must be in increasing order");
02016                      else           Error(where, "X must have N+1 values with option N");
02017                      return;
02018                   }
02019                   gxwork[npt-1] = x[i-1] + 0.5*(x[i]-x[i-1]);
02020                }
02021                if (gxwork[npt-1] < uxmin || gxwork[npt-1] > uxmax) { npt--; continue;}
02022                if ((optionMark != 10) && (optionLine == 0)) {
02023                   if (y[i-1] <= rwymin)  {npt--; continue;}
02024                }
02025                gywork[npt-1] = y[i-1];
02026                gywork[npt]   = y[i-1]; //new
02027                if ((gywork[npt-1] < rwymin) || ((gywork[npt-1] > rwymax) && !optionFill2)) {
02028                   if ((gywork[npt-1] < rwymin)) gywork[npt-1] = rwymin;
02029                   if ((gywork[npt-1] > rwymax)) gywork[npt-1] = rwymax;
02030                   if (npt > 2) {
02031                      if (optionMarker) {
02032                         ComputeLogs(npt, optionZ);
02033                         gPad->PaintPolyMarker(npt,gxworkl,gyworkl);
02034                      }
02035                      if (optionLine) {
02036                         if (!optionMarker) ComputeLogs(npt, optionZ);
02037                         gPad->PaintPolyLine(npt,gxworkl,gyworkl,noClip);
02038                      }
02039                   }
02040                   gxwork[0] = gxwork[npt-1];
02041                   gywork[0] = gywork[npt-1];
02042                   npt       = 1;
02043                   continue;
02044                }
02045 
02046                if (npt >= 50) {
02047                   if (optionMarker) {
02048                      ComputeLogs(50, optionZ);
02049                      gPad->PaintPolyMarker(50,gxworkl,gyworkl);
02050                   }
02051                   if (optionLine) {
02052                      if (!optionMarker) ComputeLogs(50, optionZ);
02053                      if (optionFill2) {
02054                         gxworkl[npt]   = gxworkl[npt-1]; gyworkl[npt]   = rwymin;
02055                         gxworkl[npt+1] = gxworkl[0];     gyworkl[npt+1] = rwymin;
02056                         gPad->PaintFillArea(52,gxworkl,gyworkl);
02057                      }
02058                      gPad->PaintPolyLine(50,gxworkl,gyworkl);
02059                   }
02060                   gxwork[0] = gxwork[npt-1];
02061                   gywork[0] = gywork[npt-1];
02062                   npt      = 1;
02063                }
02064             }  //endfor (i=first; i<=last;i++)
02065             if (optionMarker && npt > 0) {
02066                ComputeLogs(npt, optionZ);
02067                gPad->PaintPolyMarker(npt,gxworkl,gyworkl);
02068             }
02069             if (optionLine && npt > 1) {
02070                if (!optionMarker) ComputeLogs(npt, optionZ);
02071                if (optionFill2) {
02072                   gxworkl[npt]   = gxworkl[npt-1]; gyworkl[npt]   = rwymin;
02073                   gxworkl[npt+1] = gxworkl[0];     gyworkl[npt+1] = rwymin;
02074                   gPad->PaintFillArea(npt+2,gxworkl,gyworkl);
02075                }
02076                gPad->PaintPolyLine(npt,gxworkl,gyworkl);
02077             }
02078          }
02079          else {
02080             npt = 0;
02081             for (i=first; i<=last;i++) {
02082                npt++;
02083                if (!optionBins) gywork[npt-1] = wminstep+(i-first)*delta+0.5*delta;
02084                else {
02085                   yi1 = y[i];      yi = y[i-1];
02086                   if (yi1 < yi) {
02087                      if (i != last) Error(where, "Y must be in increasing order");
02088                      else           Error(where, "Y must have N+1 values with option N");
02089                      return;
02090                   }
02091                   gywork[npt-1] = y[i-1] + 0.5*(y[i]-y[i-1]);
02092                }
02093                gxwork[npt-1] = x[i-1];
02094                if ((gxwork[npt-1] < uxmin) || (gxwork[npt-1] > uxmax)) {
02095                   if (npt > 2) {
02096                      if (optionMarker) {
02097                         ComputeLogs(npt, optionZ);
02098                         gPad->PaintPolyMarker(npt,gxworkl,gyworkl);
02099                      }
02100                      if (optionLine) {
02101                         if (!optionMarker) ComputeLogs(npt, optionZ);
02102                         gPad->PaintPolyLine(npt,gxworkl,gyworkl,noClip);
02103                      }
02104                   }
02105                   gxwork[0] = gxwork[npt-1];
02106                   gywork[0] = gywork[npt-1];
02107                   npt      = 1;
02108                   continue;
02109                }
02110                if (npt >= 50) {
02111                   if (optionMarker) {
02112                      ComputeLogs(50, optionZ);
02113                      gPad->PaintPolyMarker(50,gxworkl,gyworkl);
02114                   }
02115                   if (optionLine) {
02116                      if (!optionMarker) ComputeLogs(50, optionZ);
02117                      gPad->PaintPolyLine(50,gxworkl,gyworkl);
02118                   }
02119                   gxwork[0] = gxwork[npt-1];
02120                   gywork[0] = gywork[npt-1];
02121                   npt      = 1;
02122                }
02123             }  //endfor (i=first; i<=last;i++)
02124             if (optionMarker && npt > 0) {
02125                ComputeLogs(npt, optionZ);
02126                gPad->PaintPolyMarker(npt,gxworkl,gyworkl);
02127             }
02128             if (optionLine != 0 && npt > 1) {
02129                if (!optionMarker) ComputeLogs(npt, optionZ);
02130                gPad->PaintPolyLine(npt,gxworkl,gyworkl,noClip);
02131             }
02132          }
02133       }
02134    }
02135 
02136    //              Draw the histogram as a bar chart
02137 
02138    if (optionBar) {
02139       if (!optionBins) { offset = delta*baroffset; dbar = delta*barwidth; }
02140       else {
02141          if (!optionRot) {
02142             offset = (x[1]-x[0])*baroffset;
02143             dbar   = (x[1]-x[0])*barwidth;
02144          } else {
02145             offset = (y[1]-y[0])*baroffset;
02146             dbar   = (y[1]-y[0])*barwidth;
02147          }
02148       }
02149       drawbordersav = drawborder;
02150       gStyle->SetDrawBorder(1);
02151       if (!optionRot) {
02152          xlow  = wmin+offset;
02153          xhigh = wmin+offset+dbar;
02154          if (!optionOne) ylow = TMath::Min(TMath::Max((Double_t)0,gPad->GetUymin())
02155                                 ,gPad->GetUymax());
02156          else            ylow = gPad->GetUymin();
02157 
02158          for (i=first; i<=last;i++) {
02159             yhigh    = y[i-1];
02160             gxwork[0] = xlow;
02161             gywork[0] = ylow;
02162             gxwork[1] = xhigh;
02163             gywork[1] = yhigh;
02164             ComputeLogs(2, optionZ);
02165             gPad->PaintBox(gxworkl[0],gyworkl[0],gxworkl[1],gyworkl[1]);
02166             if (!optionBins) {
02167                xlow  = xlow+delta;
02168                xhigh = xhigh+delta;
02169             }
02170             else {
02171                if (i < last) {
02172                   xi1 = x[i];      xi = x[i-1];
02173                   if (xi1 < xi) {
02174                      Error(where, "X must be in increasing order");
02175                      return;
02176                   }
02177                   offset  = (x[i+1]-x[i])*baroffset;
02178                   dbar    = (x[i+1]-x[i])*barwidth;
02179                   xlow    = x[i] + offset;
02180                   xhigh   = x[i] + offset + dbar;
02181                }
02182             }
02183          }  //endfor (i=first; i<=last;i++)
02184       }
02185       else {
02186          ylow  = wmin + offset;
02187          yhigh = wmin + offset + dbar;
02188          if (!optionOne) xlow = TMath::Max((Double_t)0,gPad->GetUxmin());
02189          else            xlow = gPad->GetUxmin();
02190 
02191          for (i=first; i<=last;i++) {
02192             xhigh    = x[i-1];
02193             gxwork[0] = xlow;
02194             gywork[0] = ylow;
02195             gxwork[1] = xhigh;
02196             gywork[1] = yhigh;
02197             ComputeLogs(2, optionZ);
02198             gPad->PaintBox(gxworkl[0],gyworkl[0],gxworkl[1],gyworkl[1]);
02199             gPad->PaintBox(xlow,ylow,xhigh,yhigh);
02200             if (!optionBins) {
02201                ylow  = ylow  + delta;
02202                yhigh = yhigh + delta;
02203             }
02204             else {
02205                if (i < last) {
02206                   yi1 = y[i];      yi = y[i-1];
02207                   if (yi1 < yi) {
02208                      Error(where, "Y must be in increasing order");
02209                      return;
02210                   }
02211                   offset  = (y[i+1]-y[i])*baroffset;
02212                   dbar    = (y[i+1]-y[i])*barwidth;
02213                   ylow    = y[i] + offset;
02214                   yhigh   = y[i] + offset + dbar;
02215                }
02216             }
02217          }  //endfor (i=first; i<=last;i++)
02218       }
02219       gStyle->SetDrawBorder(drawbordersav);
02220    }
02221    gPad->ResetBit(TGraph::kClipFrame);
02222 
02223    delete [] gxwork;
02224    delete [] gywork;
02225    delete [] gxworkl;
02226    delete [] gyworkl;
02227 }
02228 
02229 
02230 //______________________________________________________________________________
02231 void TGraphPainter::PaintGraphAsymmErrors(TGraph *theGraph, Option_t *option)
02232 {
02233    /* Begin_Html
02234    <a href="#GP03">Paint this TGraphAsymmErrors with its current attributes.</a>
02235    End_Html */
02236 
02237    Double_t *xline = 0;
02238    Double_t *yline = 0;
02239    Int_t if1 = 0;
02240    Int_t if2 = 0;
02241 
02242    const Int_t kBASEMARKER=8;
02243    Double_t s2x, s2y, symbolsize, sbase;
02244    Double_t x, y, xl1, xl2, xr1, xr2, yup1, yup2, ylow1, ylow2, tx, ty;
02245    static Float_t cxx[15] = {1,1,0.6,0.6,1,1,0.6,0.5,1,0.6,0.6,1,0.6,1,1};
02246    static Float_t cyy[15] = {1,1,1,1,1,1,1,1,1,0.5,0.6,1,1,1,1};
02247    Int_t theNpoints = theGraph->GetN();
02248    Double_t *theX  = theGraph->GetX();
02249    Double_t *theY  = theGraph->GetY();
02250    Double_t *theEXlow  = theGraph->GetEXlow();
02251    Double_t *theEYlow  = theGraph->GetEYlow();
02252    Double_t *theEXhigh = theGraph->GetEXhigh();
02253    Double_t *theEYhigh = theGraph->GetEYhigh();
02254 
02255    if (strchr(option,'X') || strchr(option,'x')) {PaintGraphSimple(theGraph, option); return;}
02256    Bool_t brackets = kFALSE;
02257    Bool_t braticks = kFALSE;
02258    if (strstr(option,"||") || strstr(option,"[]")) {
02259       brackets = kTRUE;
02260       if (strstr(option,"[]")) braticks = kTRUE;
02261    }
02262    Bool_t endLines = kTRUE;
02263    if (strchr(option,'z')) endLines = kFALSE;
02264    if (strchr(option,'Z')) endLines = kFALSE;
02265    const char *arrowOpt = 0;
02266    if (strchr(option,'>'))  arrowOpt = ">";
02267    if (strstr(option,"|>")) arrowOpt = "|>";
02268 
02269    Bool_t axis = kFALSE;
02270    if (strchr(option,'a')) axis = kTRUE;
02271    if (strchr(option,'A')) axis = kTRUE;
02272    if (axis) PaintGraphSimple(theGraph, option);
02273 
02274    Bool_t option2 = kFALSE;
02275    Bool_t option3 = kFALSE;
02276    Bool_t option4 = kFALSE;
02277    if (strchr(option,'2')) option2 = kTRUE;
02278    if (strchr(option,'3')) option3 = kTRUE;
02279    if (strchr(option,'4')) {option3 = kTRUE; option4 = kTRUE;}
02280 
02281    if (option3) {
02282       xline = new Double_t[2*theNpoints];
02283       yline = new Double_t[2*theNpoints];
02284       if (!xline || !yline) {
02285          Error("Paint", "too many points, out of memory");
02286          return;
02287       }
02288       if1 = 1;
02289       if2 = 2*theNpoints;
02290    }
02291 
02292    theGraph->TAttLine::Modify();
02293 
02294    TArrow arrow;
02295    arrow.SetLineWidth(theGraph->GetLineWidth());
02296    arrow.SetLineColor(theGraph->GetLineColor());
02297    arrow.SetFillColor(theGraph->GetFillColor());
02298 
02299    TBox box;
02300    Double_t x1b,y1b,x2b,y2b;
02301    box.SetLineWidth(theGraph->GetLineWidth());
02302    box.SetLineColor(theGraph->GetLineColor());
02303    box.SetFillColor(theGraph->GetFillColor());
02304    box.SetFillStyle(theGraph->GetFillStyle());
02305 
02306    symbolsize  = theGraph->GetMarkerSize();
02307    sbase       = symbolsize*kBASEMARKER;
02308    Int_t mark  = theGraph->GetMarkerStyle();
02309    Double_t cx  = 0;
02310    Double_t cy  = 0;
02311    if (mark >= 20 && mark <= 34) {
02312       cx = cxx[mark-20];
02313       cy = cyy[mark-20];
02314    }
02315 
02316    // Define the offset of the error bars due to the symbol size
02317    s2x  = gPad->PixeltoX(Int_t(0.5*sbase)) - gPad->PixeltoX(0);
02318    s2y  =-gPad->PixeltoY(Int_t(0.5*sbase)) + gPad->PixeltoY(0);
02319    Int_t dxend = Int_t(gStyle->GetEndErrorSize());
02320    tx    = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
02321    ty    =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
02322    Float_t asize = 0.6*symbolsize*kBASEMARKER/gPad->GetWh();
02323 
02324    gPad->SetBit(TGraph::kClipFrame, theGraph->TestBit(TGraph::kClipFrame));
02325    for (Int_t i=0;i<theNpoints;i++) {
02326       x  = gPad->XtoPad(theX[i]);
02327       y  = gPad->YtoPad(theY[i]);
02328       if (option3) {
02329          if (x < gPad->GetUxmin()) x = gPad->GetUxmin();
02330          if (x > gPad->GetUxmax()) x = gPad->GetUxmax();
02331          if (y < gPad->GetUymin()) y = gPad->GetUymin();
02332          if (y > gPad->GetUymax()) y = gPad->GetUymax();
02333       } else {
02334          if (x < gPad->GetUxmin()) continue;
02335          if (x > gPad->GetUxmax()) continue;
02336          if (y < gPad->GetUymin()) continue;
02337          if (y > gPad->GetUymax()) continue;
02338       }
02339       xl1 = x - s2x*cx;
02340       xl2 = gPad->XtoPad(theX[i] - theEXlow[i]);
02341 
02342       //  draw the error rectangles
02343       if (option2) {
02344          x1b = gPad->XtoPad(theX[i] - theEXlow[i]);
02345          y1b = gPad->YtoPad(theY[i] - theEYlow[i]);
02346          x2b = gPad->XtoPad(theX[i] + theEXhigh[i]);
02347          y2b = gPad->YtoPad(theY[i] + theEYhigh[i]);
02348          if (x1b < gPad->GetUxmin()) x1b = gPad->GetUxmin();
02349          if (x1b > gPad->GetUxmax()) x1b = gPad->GetUxmax();
02350          if (y1b < gPad->GetUymin()) y1b = gPad->GetUymin();
02351          if (y1b > gPad->GetUymax()) y1b = gPad->GetUymax();
02352          if (x2b < gPad->GetUxmin()) x2b = gPad->GetUxmin();
02353          if (x2b > gPad->GetUxmax()) x2b = gPad->GetUxmax();
02354          if (y2b < gPad->GetUymin()) y2b = gPad->GetUymin();
02355          if (y2b > gPad->GetUymax()) y2b = gPad->GetUymax();
02356          box.PaintBox(x1b, y1b, x2b, y2b);
02357          continue;
02358       }
02359 
02360       //  keep points for fill area drawing
02361       if (option3) {
02362          xline[if1-1] = x;
02363          xline[if2-1] = x;
02364          yline[if1-1] = gPad->YtoPad(theY[i] + theEYhigh[i]);
02365          yline[if2-1] = gPad->YtoPad(theY[i] - theEYlow[i]);
02366          if1++;
02367          if2--;
02368          continue;
02369       }
02370 
02371       if (xl1 > xl2) {
02372          if (arrowOpt) {
02373             arrow.PaintArrow(xl1,y,xl2,y,asize,arrowOpt);
02374          } else {
02375             if (!brackets) gPad->PaintLine(xl1,y,xl2,y);
02376             if (endLines) {
02377                gPad->PaintLine(xl2,y-ty,xl2,y+ty);
02378                if (braticks) {
02379                   gPad->PaintLine(xl2,y-ty,xl2+tx,y-ty);
02380                   gPad->PaintLine(xl2,y+ty,xl2+tx,y+ty);
02381                }
02382             }
02383          }
02384       }
02385       xr1 = x + s2x*cx;
02386       xr2 = gPad->XtoPad(theX[i] + theEXhigh[i]);
02387       if (xr1 < xr2) {
02388          if (arrowOpt) {
02389             arrow.PaintArrow(xr1,y,xr2,y,asize,arrowOpt);
02390          } else {
02391             if (!brackets) gPad->PaintLine(xr1,y,xr2,y);
02392             if (endLines) {
02393                gPad->PaintLine(xr2,y-ty,xr2,y+ty);
02394                if (braticks) {
02395                   gPad->PaintLine(xr2,y-ty,xr2-tx,y-ty);
02396                   gPad->PaintLine(xr2,y+ty,xr2-tx,y+ty);
02397                }
02398             }
02399          }
02400       }
02401       yup1 = y + s2y*cy;
02402       yup2 = gPad->YtoPad(theY[i] + theEYhigh[i]);
02403       if (yup2 > gPad->GetUymax()) yup2 =  gPad->GetUymax();
02404       if (yup2 > yup1) {
02405          if (arrowOpt) {
02406             arrow.PaintArrow(x,yup1,x,yup2,asize,arrowOpt);
02407          } else {
02408             if (!brackets) gPad->PaintLine(x,yup1,x,yup2);
02409             if (endLines) {
02410                gPad->PaintLine(x-tx,yup2,x+tx,yup2);
02411                if (braticks) {
02412                   gPad->PaintLine(x-tx,yup2,x-tx,yup2-ty);
02413                   gPad->PaintLine(x+tx,yup2,x+tx,yup2-ty);
02414                }
02415             }
02416          }
02417       }
02418       ylow1 = y - s2y*cy;
02419       ylow2 = gPad->YtoPad(theY[i] - theEYlow[i]);
02420       if (ylow2 < gPad->GetUymin()) ylow2 =  gPad->GetUymin();
02421       if (ylow2 < ylow1) {
02422          if (arrowOpt) {
02423             arrow.PaintArrow(x,ylow1,x,ylow2,asize,arrowOpt);
02424          } else {
02425             if (!brackets) gPad->PaintLine(x,ylow1,x,ylow2);
02426             if (endLines) {
02427                gPad->PaintLine(x-tx,ylow2,x+tx,ylow2);
02428                if (braticks) {
02429                   gPad->PaintLine(x-tx,ylow2,x-tx,ylow2+ty);
02430                   gPad->PaintLine(x+tx,ylow2,x+tx,ylow2+ty);
02431                }
02432             }
02433          }
02434       }
02435    }
02436    if (!brackets && !axis) PaintGraphSimple(theGraph, option);
02437    gPad->ResetBit(TGraph::kClipFrame);
02438 
02439    if (option3) {
02440       Int_t logx = gPad->GetLogx();
02441       Int_t logy = gPad->GetLogy();
02442       gPad->SetLogx(0);
02443       gPad->SetLogy(0);
02444       if (option4) PaintGraph(theGraph, 2*theNpoints, xline, yline,"FC");
02445       else         PaintGraph(theGraph, 2*theNpoints, xline, yline,"F");
02446       gPad->SetLogx(logx);
02447       gPad->SetLogy(logy);
02448       delete [] xline;
02449       delete [] yline;
02450    }
02451 }
02452 
02453 
02454 //_____________________________________________________________________________
02455 void TGraphPainter::PaintGraphBentErrors(TGraph *theGraph, Option_t *option)
02456 {
02457    /* Begin_Html
02458    <a href="#GP03">Paint this TGraphBentErrors with its current attributes.</a>
02459    End_Html */
02460 
02461    Double_t *xline = 0;
02462    Double_t *yline = 0;
02463    Int_t if1 = 0;
02464    Int_t if2 = 0;
02465 
02466    const Int_t kBASEMARKER=8;
02467    Double_t s2x, s2y, symbolsize, sbase;
02468    Double_t x, y, xl1, xl2, xr1, xr2, yup1, yup2, ylow1, ylow2, tx, ty;
02469    Double_t bxl, bxh, byl, byh;
02470    static Float_t cxx[15] = {1,1,0.6,0.6,1,1,0.6,0.5,1,0.6,0.6,1,0.6,1,1};
02471    static Float_t cyy[15] = {1,1,1,1,1,1,1,1,1,0.5,0.6,1,1,1,1};
02472    Int_t theNpoints = theGraph->GetN();
02473    Double_t *theX  = theGraph->GetX();
02474    Double_t *theY  = theGraph->GetY();
02475    Double_t *theEXlow  = theGraph->GetEXlow();
02476    Double_t *theEYlow  = theGraph->GetEYlow();
02477    Double_t *theEXhigh = theGraph->GetEXhigh();
02478    Double_t *theEYhigh = theGraph->GetEYhigh();
02479    Double_t *theEXlowd  = theGraph->GetEXlowd();
02480    Double_t *theEXhighd = theGraph->GetEXhighd();
02481    Double_t *theEYlowd  = theGraph->GetEYlowd();
02482    Double_t *theEYhighd = theGraph->GetEYhighd();
02483 
02484    if (strchr(option,'X') || strchr(option,'x')) {PaintGraphSimple(theGraph, option); return;}
02485    Bool_t brackets = kFALSE;
02486    Bool_t braticks = kFALSE;
02487    if (strstr(option,"||") || strstr(option,"[]")) {
02488       brackets = kTRUE;
02489       if (strstr(option,"[]")) braticks = kTRUE;
02490    }
02491    Bool_t endLines = kTRUE;
02492    if (strchr(option,'z')) endLines = kFALSE;
02493    if (strchr(option,'Z')) endLines = kFALSE;
02494    const char *arrowOpt = 0;
02495    if (strchr(option,'>'))  arrowOpt = ">";
02496    if (strstr(option,"|>")) arrowOpt = "|>";
02497 
02498    Bool_t axis = kFALSE;
02499    if (strchr(option,'a')) axis = kTRUE;
02500    if (strchr(option,'A')) axis = kTRUE;
02501    if (axis) PaintGraphSimple(theGraph,option);
02502 
02503    Bool_t option2 = kFALSE;
02504    Bool_t option3 = kFALSE;
02505    Bool_t option4 = kFALSE;
02506    if (strchr(option,'2')) option2 = kTRUE;
02507    if (strchr(option,'3')) option3 = kTRUE;
02508    if (strchr(option,'4')) {option3 = kTRUE; option4 = kTRUE;}
02509 
02510    if (option3) {
02511       xline = new Double_t[2*theNpoints];
02512       yline = new Double_t[2*theNpoints];
02513       if (!xline || !yline) {
02514          Error("Paint", "too many points, out of memory");
02515          return;
02516       }
02517       if1 = 1;
02518       if2 = 2*theNpoints;
02519    }
02520 
02521    theGraph->TAttLine::Modify();
02522 
02523    TArrow arrow;
02524    arrow.SetLineWidth(theGraph->GetLineWidth());
02525    arrow.SetLineColor(theGraph->GetLineColor());
02526    arrow.SetFillColor(theGraph->GetFillColor());
02527 
02528    TBox box;
02529    Double_t x1b,y1b,x2b,y2b;
02530    box.SetLineWidth(theGraph->GetLineWidth());
02531    box.SetLineColor(theGraph->GetLineColor());
02532    box.SetFillColor(theGraph->GetFillColor());
02533    box.SetFillStyle(theGraph->GetFillStyle());
02534 
02535    symbolsize  = theGraph->GetMarkerSize();
02536    sbase       = symbolsize*kBASEMARKER;
02537    Int_t mark  = theGraph->GetMarkerStyle();
02538    Double_t cx  = 0;
02539    Double_t cy  = 0;
02540    if (mark >= 20 && mark <= 34) {
02541       cx = cxx[mark-20];
02542       cy = cyy[mark-20];
02543    }
02544 
02545    // define the offset of the error bars due to the symbol size
02546    s2x  = gPad->PixeltoX(Int_t(0.5*sbase)) - gPad->PixeltoX(0);
02547    s2y  =-gPad->PixeltoY(Int_t(0.5*sbase)) + gPad->PixeltoY(0);
02548    Int_t dxend = Int_t(gStyle->GetEndErrorSize());
02549    tx   = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
02550    ty   =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
02551    Float_t asize = 0.6*symbolsize*kBASEMARKER/gPad->GetWh();
02552 
02553    gPad->SetBit(TGraph::kClipFrame, theGraph->TestBit(TGraph::kClipFrame));
02554    for (Int_t i=0;i<theNpoints;i++) {
02555       x  = gPad->XtoPad(theX[i]);
02556       y  = gPad->YtoPad(theY[i]);
02557       bxl = gPad->YtoPad(theY[i]+theEXlowd[i]);
02558       bxh = gPad->YtoPad(theY[i]+theEXhighd[i]);
02559       byl = gPad->XtoPad(theX[i]+theEYlowd[i]);
02560       byh = gPad->XtoPad(theX[i]+theEYhighd[i]);
02561       if (option3) {
02562          if (x < gPad->GetUxmin()) x = gPad->GetUxmin();
02563          if (x > gPad->GetUxmax()) x = gPad->GetUxmax();
02564          if (y < gPad->GetUymin()) y = gPad->GetUymin();
02565          if (y > gPad->GetUymax()) y = gPad->GetUymax();
02566       } else {
02567          if (x < gPad->GetUxmin()) continue;
02568          if (x > gPad->GetUxmax()) continue;
02569          if (y < gPad->GetUymin()) continue;
02570          if (y > gPad->GetUymax()) continue;
02571       }
02572 
02573       //  draw the error rectangles
02574       if (option2) {
02575          x1b = gPad->XtoPad(theX[i] - theEXlow[i]);
02576          y1b = gPad->YtoPad(theY[i] - theEYlow[i]);
02577          x2b = gPad->XtoPad(theX[i] + theEXhigh[i]);
02578          y2b = gPad->YtoPad(theY[i] + theEYhigh[i]);
02579          if (x1b < gPad->GetUxmin()) x1b = gPad->GetUxmin();
02580          if (x1b > gPad->GetUxmax()) x1b = gPad->GetUxmax();
02581          if (y1b < gPad->GetUymin()) y1b = gPad->GetUymin();
02582          if (y1b > gPad->GetUymax()) y1b = gPad->GetUymax();
02583          if (x2b < gPad->GetUxmin()) x2b = gPad->GetUxmin();
02584          if (x2b > gPad->GetUxmax()) x2b = gPad->GetUxmax();
02585          if (y2b < gPad->GetUymin()) y2b = gPad->GetUymin();
02586          if (y2b > gPad->GetUymax()) y2b = gPad->GetUymax();
02587          box.PaintBox(x1b, y1b, x2b, y2b);
02588          continue;
02589       }
02590 
02591       //  keep points for fill area drawing
02592       if (option3) {
02593          xline[if1-1] = byh;
02594          xline[if2-1] = byl;
02595          yline[if1-1] = gPad->YtoPad(theY[i] + theEYhigh[i]);
02596          yline[if2-1] = gPad->YtoPad(theY[i] - theEYlow[i]);
02597          if1++;
02598          if2--;
02599          continue;
02600       }
02601 
02602       xl1 = x - s2x*cx;
02603       xl2 = gPad->XtoPad(theX[i] - theEXlow[i]);
02604       if (xl1 > xl2) {
02605          if (arrowOpt) {
02606             arrow.PaintArrow(xl1,y,xl2,bxl,asize,arrowOpt);
02607          } else {
02608             if (!brackets) gPad->PaintLine(xl1,y,xl2,bxl);
02609             if (endLines) {
02610                gPad->PaintLine(xl2,bxl-ty,xl2,bxl+ty);
02611                if (braticks) {
02612                   gPad->PaintLine(xl2,bxl-ty,xl2+tx,bxl-ty);
02613                   gPad->PaintLine(xl2,bxl+ty,xl2+tx,bxl+ty);
02614                }
02615             }
02616          }
02617       }
02618       xr1 = x + s2x*cx;
02619       xr2 = gPad->XtoPad(theX[i] + theEXhigh[i]);
02620       if (xr1 < xr2) {
02621          if (arrowOpt) {
02622             arrow.PaintArrow(xr1,y,xr2,bxh,asize,arrowOpt);
02623          } else {
02624             if (!brackets) gPad->PaintLine(xr1,y,xr2,bxh);
02625             if (endLines) {
02626                gPad->PaintLine(xr2,bxh-ty,xr2,bxh+ty);
02627                if (braticks) {
02628                   gPad->PaintLine(xr2,bxh-ty,xr2-tx,bxh-ty);
02629                   gPad->PaintLine(xr2,bxh+ty,xr2-tx,bxh+ty);
02630                }
02631             }
02632          }
02633       }
02634       yup1 = y + s2y*cy;
02635       yup2 = gPad->YtoPad(theY[i] + theEYhigh[i]);
02636       if (yup2 > gPad->GetUymax()) yup2 =  gPad->GetUymax();
02637       if (yup2 > yup1) {
02638          if (arrowOpt) {
02639             arrow.PaintArrow(x,yup1,byh,yup2,asize,arrowOpt);
02640          } else {
02641             if (!brackets) gPad->PaintLine(x,yup1,byh,yup2);
02642             if (endLines) {
02643                gPad->PaintLine(byh-tx,yup2,byh+tx,yup2);
02644                if (braticks) {
02645                   gPad->PaintLine(byh-tx,yup2,byh-tx,yup2-ty);
02646                   gPad->PaintLine(byh+tx,yup2,byh+tx,yup2-ty);
02647                }
02648             }
02649          }
02650       }
02651       ylow1 = y - s2y*cy;
02652       ylow2 = gPad->YtoPad(theY[i] - theEYlow[i]);
02653       if (ylow2 < gPad->GetUymin()) ylow2 =  gPad->GetUymin();
02654       if (ylow2 < ylow1) {
02655          if (arrowOpt) {
02656             arrow.PaintArrow(x,ylow1,byl,ylow2,asize,arrowOpt);
02657          } else {
02658             if (!brackets) gPad->PaintLine(x,ylow1,byl,ylow2);
02659             if (endLines) {
02660                gPad->PaintLine(byl-tx,ylow2,byl+tx,ylow2);
02661                if (braticks) {
02662                   gPad->PaintLine(byl-tx,ylow2,byl-tx,ylow2+ty);
02663                   gPad->PaintLine(byl+tx,ylow2,byl+tx,ylow2+ty);
02664                }
02665             }
02666          }
02667       }
02668    }
02669    if (!brackets && !axis) PaintGraphSimple(theGraph, option);
02670    gPad->ResetBit(TGraph::kClipFrame);
02671 
02672    if (option3) {
02673       Int_t logx = gPad->GetLogx();
02674       Int_t logy = gPad->GetLogy();
02675       gPad->SetLogx(0);
02676       gPad->SetLogy(0);
02677       if (option4) PaintGraph(theGraph, 2*theNpoints, xline, yline,"FC");
02678       else         PaintGraph(theGraph, 2*theNpoints, xline, yline,"F");
02679       gPad->SetLogx(logx);
02680       gPad->SetLogy(logy);
02681       delete [] xline;
02682       delete [] yline;
02683    }
02684 }
02685 
02686 
02687 //______________________________________________________________________________
02688 void TGraphPainter::PaintGraphErrors(TGraph *theGraph, Option_t *option)
02689 {
02690    /* Begin_Html
02691    <a href="#GP03">Paint this TGraphErrors with its current attributes.</a>
02692    End_Html */
02693 
02694    Double_t *xline = 0;
02695    Double_t *yline = 0;
02696    Int_t if1 = 0;
02697    Int_t if2 = 0;
02698 
02699    const Int_t kBASEMARKER=8;
02700    Double_t s2x, s2y, symbolsize, sbase;
02701    Double_t x, y, ex, ey, xl1, xl2, xr1, xr2, yup1, yup2, ylow1, ylow2, tx, ty;
02702    static Float_t cxx[15] = {1,1,0.6,0.6,1,1,0.6,0.5,1,0.6,0.6,1,0.6,1,1};
02703    static Float_t cyy[15] = {1,1,1,1,1,1,1,1,1,0.5,0.6,1,1,1,1};
02704    Int_t theNpoints = theGraph->GetN();
02705    Double_t *theX  = theGraph->GetX();
02706    Double_t *theY  = theGraph->GetY();
02707    Double_t *theEX = theGraph->GetEX();
02708    Double_t *theEY = theGraph->GetEY();
02709 
02710    if (strchr(option,'X') || strchr(option,'x')) {PaintGraphSimple(theGraph, option); return;}
02711    Bool_t brackets = kFALSE;
02712    Bool_t braticks = kFALSE;
02713    if (strstr(option,"||") || strstr(option,"[]")) {
02714       brackets = kTRUE;
02715       if (strstr(option,"[]")) braticks = kTRUE;
02716    }
02717    Bool_t endLines = kTRUE;
02718    if (strchr(option,'z')) endLines = kFALSE;
02719    if (strchr(option,'Z')) endLines = kFALSE;
02720    const char *arrowOpt = 0;
02721    if (strchr(option,'>'))  arrowOpt = ">";
02722    if (strstr(option,"|>")) arrowOpt = "|>";
02723 
02724    Bool_t axis = kFALSE;
02725    if (strchr(option,'a')) axis = kTRUE;
02726    if (strchr(option,'A')) axis = kTRUE;
02727    if (axis) PaintGraphSimple(theGraph, option);
02728 
02729    Bool_t option2 = kFALSE;
02730    Bool_t option3 = kFALSE;
02731    Bool_t option4 = kFALSE;
02732    if (strchr(option,'2')) option2 = kTRUE;
02733    if (strchr(option,'3')) option3 = kTRUE;
02734    if (strchr(option,'4')) {option3 = kTRUE; option4 = kTRUE;}
02735 
02736    if (option3) {
02737       xline = new Double_t[2*theNpoints];
02738       yline = new Double_t[2*theNpoints];
02739       if (!xline || !yline) {
02740          Error("Paint", "too many points, out of memory");
02741          return;
02742       }
02743       if1 = 1;
02744       if2 = 2*theNpoints;
02745    }
02746 
02747    theGraph->TAttLine::Modify();
02748 
02749    TArrow arrow;
02750    arrow.SetLineWidth(theGraph->GetLineWidth());
02751    arrow.SetLineColor(theGraph->GetLineColor());
02752    arrow.SetFillColor(theGraph->GetFillColor());
02753 
02754    TBox box;
02755    Double_t x1b,y1b,x2b,y2b;
02756    box.SetLineWidth(theGraph->GetLineWidth());
02757    box.SetLineColor(theGraph->GetLineColor());
02758    box.SetFillColor(theGraph->GetFillColor());
02759    box.SetFillStyle(theGraph->GetFillStyle());
02760 
02761    symbolsize  = theGraph->GetMarkerSize();
02762    sbase       = symbolsize*kBASEMARKER;
02763    Int_t mark  = theGraph->GetMarkerStyle();
02764    Double_t cx  = 0;
02765    Double_t cy  = 0;
02766    if (mark >= 20 && mark <= 34) {
02767       cx = cxx[mark-20];
02768       cy = cyy[mark-20];
02769    }
02770 
02771    //      define the offset of the error bars due to the symbol size
02772    s2x  = gPad->PixeltoX(Int_t(0.5*sbase)) - gPad->PixeltoX(0);
02773    s2y  =-gPad->PixeltoY(Int_t(0.5*sbase)) + gPad->PixeltoY(0);
02774    Int_t dxend = Int_t(gStyle->GetEndErrorSize());
02775    tx    = gPad->PixeltoX(dxend) - gPad->PixeltoX(0);
02776    ty    =-gPad->PixeltoY(dxend) + gPad->PixeltoY(0);
02777    Float_t asize = 0.6*symbolsize*kBASEMARKER/gPad->GetWh();
02778 
02779    gPad->SetBit(TGraph::kClipFrame, theGraph->TestBit(TGraph::kClipFrame));
02780    for (Int_t i=0;i<theNpoints;i++) {
02781       x  = gPad->XtoPad(theX[i]);
02782       y  = gPad->YtoPad(theY[i]);
02783       if (option3) {
02784          if (x < gPad->GetUxmin()) x = gPad->GetUxmin();
02785          if (x > gPad->GetUxmax()) x = gPad->GetUxmax();
02786          if (y < gPad->GetUymin()) y = gPad->GetUymin();
02787          if (y > gPad->GetUymax()) y = gPad->GetUymax();
02788       } else {
02789          if (x < gPad->GetUxmin()) continue;
02790          if (x > gPad->GetUxmax()) continue;
02791          if (y < gPad->GetUymin()) continue;
02792          if (y > gPad->GetUymax()) continue;
02793       }
02794       ex = theEX[i];
02795       ey = theEY[i];
02796 
02797       //  draw the error rectangles
02798       if (option2) {
02799          x1b = gPad->XtoPad(theX[i] - ex);
02800          y1b = gPad->YtoPad(theY[i] - ey);
02801          x2b = gPad->XtoPad(theX[i] + ex);
02802          y2b = gPad->YtoPad(theY[i] + ey);
02803          if (x1b < gPad->GetUxmin()) x1b = gPad->GetUxmin();
02804          if (x1b > gPad->GetUxmax()) x1b = gPad->GetUxmax();
02805          if (y1b < gPad->GetUymin()) y1b = gPad->GetUymin();
02806          if (y1b > gPad->GetUymax()) y1b = gPad->GetUymax();
02807          if (x2b < gPad->GetUxmin()) x2b = gPad->GetUxmin();
02808          if (x2b > gPad->GetUxmax()) x2b = gPad->GetUxmax();
02809          if (y2b < gPad->GetUymin()) y2b = gPad->GetUymin();
02810          if (y2b > gPad->GetUymax()) y2b = gPad->GetUymax();
02811          box.PaintBox(x1b, y1b, x2b, y2b);
02812          continue;
02813       }
02814 
02815       //  keep points for fill area drawing
02816       if (option3) {
02817          xline[if1-1] = x;
02818          xline[if2-1] = x;
02819          yline[if1-1] = gPad->YtoPad(theY[i] + ey);
02820          yline[if2-1] = gPad->YtoPad(theY[i] - ey);
02821          if1++;
02822          if2--;
02823          continue;
02824       }
02825 
02826       xl1 = x - s2x*cx;
02827       xl2 = gPad->XtoPad(theX[i] - ex);
02828       if (xl1 > xl2) {
02829          if (arrowOpt) {
02830             arrow.PaintArrow(xl1,y,xl2,y,asize,arrowOpt);
02831          } else {
02832             if (!brackets) gPad->PaintLine(xl1,y,xl2,y);
02833             if (endLines) {
02834                gPad->PaintLine(xl2,y-ty,xl2,y+ty);
02835                if (braticks) {
02836                   gPad->PaintLine(xl2,y-ty,xl2+tx,y-ty);
02837                   gPad->PaintLine(xl2,y+ty,xl2+tx,y+ty);
02838                }
02839             }
02840          }
02841       }
02842       xr1 = x + s2x*cx;
02843       xr2 = gPad->XtoPad(theX[i] + ex);
02844       if (xr1 < xr2) {
02845          if (arrowOpt) {
02846             arrow.PaintArrow(xr1,y,xr2,y,asize,arrowOpt);
02847          } else {
02848             if (!brackets) gPad->PaintLine(xr1,y,xr2,y);
02849             if (endLines) {
02850                gPad->PaintLine(xr2,y-ty,xr2,y+ty);
02851                if (braticks) {
02852                   gPad->PaintLine(xr2,y-ty,xr2-tx,y-ty);
02853                   gPad->PaintLine(xr2,y+ty,xr2-tx,y+ty);
02854                }
02855             }
02856          }
02857       }
02858       yup1 = y + s2y*cy;
02859       yup2 = gPad->YtoPad(theY[i] + ey);
02860       if (yup2 > gPad->GetUymax()) yup2 =  gPad->GetUymax();
02861       if (yup2 > yup1) {
02862          if (arrowOpt) {
02863             arrow.PaintArrow(x,yup1,x,yup2,asize,arrowOpt);
02864          } else {
02865             if (!brackets) gPad->PaintLine(x,yup1,x,yup2);
02866             if (endLines) {
02867                gPad->PaintLine(x-tx,yup2,x+tx,yup2);
02868                if (braticks) {
02869                   gPad->PaintLine(x-tx,yup2,x-tx,yup2-ty);
02870                   gPad->PaintLine(x+tx,yup2,x+tx,yup2-ty);
02871                }
02872             }
02873          }
02874       }
02875       ylow1 = y - s2y*cy;
02876       ylow2 = gPad->YtoPad(theY[i] - ey);
02877       if (ylow2 < gPad->GetUymin()) ylow2 =  gPad->GetUymin();
02878       if (ylow2 < ylow1) {
02879          if (arrowOpt) {
02880             arrow.PaintArrow(x,ylow1,x,ylow2,asize,arrowOpt);
02881          } else {
02882             if (!brackets) gPad->PaintLine(x,ylow1,x,ylow2);
02883             if (endLines) {
02884                gPad->PaintLine(x-tx,ylow2,x+tx,ylow2);
02885                if (braticks) {
02886                   gPad->PaintLine(x-tx,ylow2,x-tx,ylow2+ty);
02887                   gPad->PaintLine(x+tx,ylow2,x+tx,ylow2+ty);
02888                }
02889             }
02890          }
02891       }
02892    }
02893    if (!brackets && !axis) PaintGraphSimple(theGraph, option);
02894    gPad->ResetBit(TGraph::kClipFrame);
02895 
02896    if (option3) {
02897       Int_t logx = gPad->GetLogx();
02898       Int_t logy = gPad->GetLogy();
02899       gPad->SetLogx(0);
02900       gPad->SetLogy(0);
02901          if (option4) PaintGraph(theGraph, 2*theNpoints, xline, yline,"FC");
02902          else         PaintGraph(theGraph, 2*theNpoints, xline, yline,"F");
02903       gPad->SetLogx(logx);
02904       gPad->SetLogy(logy);
02905       delete [] xline;
02906       delete [] yline;
02907    }
02908 }
02909 
02910 
02911 //______________________________________________________________________________
02912 void TGraphPainter::PaintGraphPolar(TGraph *theGraph, Option_t* options)
02913 {
02914    /* Begin_Html
02915    <a href="#GP04">Paint this TGraphPolar with its current attributes.</a>
02916    End_Html */
02917 
02918    Int_t ipt, i;
02919    Double_t rwrmin, rwrmax, rwtmin, rwtmax;
02920 
02921    TGraphPolar *theGraphPolar = (TGraphPolar*) theGraph;
02922 
02923    Int_t theNpoints  = theGraphPolar->GetN();
02924    Double_t *theX    = theGraphPolar->GetX();
02925    Double_t *theY    = theGraphPolar->GetY();
02926    Double_t *theEX   = theGraphPolar->GetEX();
02927    Double_t *theEY   = theGraphPolar->GetEY();
02928 
02929    if (theNpoints<1) return;
02930    TString opt = options;
02931    opt.ToUpper();
02932 
02933    Bool_t nolabel = kFALSE;
02934    if(opt.Contains("N")){
02935       nolabel = kTRUE;
02936       opt.ReplaceAll("N","");
02937    }
02938 
02939    TGraphPolargram *thePolargram = theGraphPolar->GetPolargram();
02940 
02941    // Check for existing TGraphPolargram in the Pad
02942    if (gPad) {
02943       // Existing polargram
02944       if (thePolargram) if (!gPad->FindObject(thePolargram->GetName())) thePolargram=0;
02945       if (!thePolargram) {
02946          // Find any other Polargram in the Pad
02947          TListIter padObjIter(gPad->GetListOfPrimitives());
02948          while (TObject* AnyObj = padObjIter.Next()) {
02949             if (TString(AnyObj->ClassName()).CompareTo("TGraphPolargram",
02950                                                       TString::kExact)==0)
02951             thePolargram = (TGraphPolargram*)AnyObj;
02952             theGraphPolar->SetPolargram(thePolargram);
02953          }
02954       }
02955    }
02956 
02957    // Get new polargram range if necessary.
02958    if (!thePolargram) {
02959       // Get range, initialize with first/last value
02960       rwrmin = theY[0]; rwrmax = theY[theNpoints-1];
02961       rwtmin = theX[0]; rwtmax = theX[theNpoints-1];
02962 
02963       for (ipt = 0; ipt < theNpoints; ipt++) {
02964          // Check for errors if available
02965          if (theEX) {
02966             if (theX[ipt] -theEX[ipt] < rwtmin) rwtmin = theX[ipt]-theEX[ipt];
02967             if (theX[ipt] +theEX[ipt] > rwtmax) rwtmax = theX[ipt]+theEX[ipt];
02968          } else {
02969             if (theX[ipt] < rwtmin) rwtmin=theX[ipt];
02970             if (theX[ipt] > rwtmax) rwtmax=theX[ipt];
02971          }
02972          if (theEY) {
02973             if (theY[ipt] -theEY[ipt] < rwrmin) rwrmin = theY[ipt]-theEY[ipt];
02974             if (theY[ipt] +theEY[ipt] > rwrmax) rwrmax = theY[ipt]+theEY[ipt];
02975          } else {
02976             if (theY[ipt] < rwrmin) rwrmin=theY[ipt];
02977             if (theY[ipt] > rwrmax) rwrmax=theY[ipt];
02978          }
02979       }
02980       // Add radial and Polar margins.
02981       if (rwrmin == rwrmax) rwrmax += 1.;
02982       if (rwtmin == rwtmax) rwtmax += 1.;
02983       Double_t dr = (rwrmax-rwrmin);
02984       Double_t dt = (rwtmax-rwtmin);
02985       rwrmax += 0.1*dr;
02986       rwrmin -= 0.1*dr;
02987 
02988       // Assume equaly spaced points for full 2*Pi.
02989       rwtmax += dt/theNpoints;
02990    } else {
02991       rwrmin = thePolargram->GetRMin();
02992       rwrmax = thePolargram->GetRMax();
02993       rwtmin = thePolargram->GetTMin();
02994       rwtmax = thePolargram->GetTMax();
02995    }
02996 
02997    if ((!thePolargram) || theGraphPolar->GetOptionAxis()) {
02998       // Draw Polar coord system
02999       thePolargram = new TGraphPolargram("Polargram",rwrmin,rwrmax,rwtmin,rwtmax);
03000       theGraphPolar->SetPolargram(thePolargram);
03001       if (opt.Contains("O")) thePolargram->SetBit(TGraphPolargram::kLabelOrtho);
03002       else thePolargram->ResetBit(TGraphPolargram::kLabelOrtho);
03003       if (nolabel) thePolargram->Draw("N");
03004       else         thePolargram->Draw("");
03005       theGraphPolar->SetOptionAxis(kFALSE);   //Prevent redrawing
03006    }
03007 
03008    // Convert points to polar.
03009    Double_t *theXpol = theGraphPolar->GetXpol();
03010    Double_t *theYpol = theGraphPolar->GetYpol();
03011 
03012    // Project theta in [0,2*Pi] and radius in [0,1].
03013    Double_t radiusNDC = rwrmax-rwrmin;
03014    Double_t thetaNDC  = (rwtmax-rwtmin)/(2*TMath::Pi());
03015 
03016    // Draw the error bars.
03017    // Y errors are lines, but X errors are pieces of circles.
03018    if (opt.Contains("E")) {
03019       if (theEY) {
03020          for (i=0; i<theNpoints; i++) {
03021             Double_t eymin, eymax, exmin,exmax;
03022             exmin = (theY[i]-theEY[i]-rwrmin)/radiusNDC*
03023                      TMath::Cos((theX[i]-rwtmin)/thetaNDC);
03024             eymin = (theY[i]-theEY[i]-rwrmin)/radiusNDC*
03025                      TMath::Sin((theX[i]-rwtmin)/thetaNDC);
03026             exmax = (theY[i]+theEY[i]-rwrmin)/radiusNDC*
03027                      TMath::Cos((theX[i]-rwtmin)/thetaNDC);
03028             eymax = (theY[i]+theEY[i]-rwrmin)/radiusNDC*
03029                      TMath::Sin((theX[i]-rwtmin)/thetaNDC);
03030             theGraphPolar->TAttLine::Modify();
03031             if (exmin != exmax || eymin != eymax) gPad->PaintLine(exmin,eymin,exmax,eymax);
03032          }
03033       }
03034       if (theEX) {
03035          for (i=0; i<theNpoints; i++) {
03036             Double_t rad = (theY[i]-rwrmin)/radiusNDC;
03037             Double_t phimin = (theX[i]-theEX[i]-rwtmin)/thetaNDC*180/TMath::Pi();
03038             Double_t phimax = (theX[i]+theEX[i]-rwtmin)/thetaNDC*180/TMath::Pi();
03039             theGraphPolar->TAttLine::Modify();
03040             if (phimin != phimax) thePolargram->PaintCircle(0,0,rad,phimin,phimax,0);
03041          }
03042       }
03043    }
03044 
03045    // Draw the graph itself.
03046    if (!(gPad->GetLogx()) && !(gPad->GetLogy())) {
03047       Double_t a, b, c=1, x1, x2, y1, y2, discr, norm1, norm2, xts, yts;
03048       Bool_t previouspointin = kFALSE;
03049       Double_t norm = 0;
03050       Double_t xt   = 0;
03051       Double_t yt   = 0 ;
03052       Int_t j       = -1;
03053       for (i=0; i<theNpoints; i++) {
03054          if (thePolargram->IsRadian()) {c=1;}
03055          if (thePolargram->IsDegree()) {c=180/TMath::Pi();}
03056          if (thePolargram->IsGrad())   {c=100/TMath::Pi();}
03057          xts  = xt;
03058          yts  = yt;
03059          xt   = (theY[i]-rwrmin)/radiusNDC*TMath::Cos(c*(theX[i]-rwtmin)/thetaNDC);
03060          yt   = (theY[i]-rwrmin)/radiusNDC*TMath::Sin(c*(theX[i]-rwtmin)/thetaNDC);
03061          norm = sqrt(xt*xt+yt*yt);
03062          // Check if points are in the main circle.
03063          if ( norm <= 1) {
03064             // We check that the previous point was in the circle too.
03065             // We record new point position.
03066             if (!previouspointin) {
03067                j++;
03068                theXpol[j] = xt;
03069                theYpol[j] = yt;
03070             } else {
03071                a = (yt-yts)/(xt-xts);
03072                b = yts-a*xts;
03073                discr = 4*(a*a-b*b+1);
03074                x1 = (-2*a*b+sqrt(discr))/(2*(a*a+1));
03075                x2 = (-2*a*b-sqrt(discr))/(2*(a*a+1));
03076                y1 = a*x1+b;
03077                y2 = a*x2+b;
03078                norm1 = sqrt((x1-xt)*(x1-xt)+(y1-yt)*(y1-yt));
03079                norm2 = sqrt((x2-xt)*(x2-xt)+(y2-yt)*(y2-yt));
03080                previouspointin = kFALSE;
03081                j = 0;
03082                if (norm1 < norm2) {
03083                   theXpol[j] = x1;
03084                   theYpol[j] = y1;
03085                } else {
03086                   theXpol[j] = x2;
03087                   theYpol[j] = y2;
03088                }
03089                j++;
03090                theXpol[j] = xt;
03091                theYpol[j] = yt;
03092                PaintGraph(theGraphPolar, j+1, theXpol, theYpol, opt);
03093             }
03094          } else {
03095             // We check that the previous point was in the circle.
03096             // We record new point position
03097             if (j>=1 && !previouspointin) {
03098                a = (yt-theYpol[j])/(xt-theXpol[j]);
03099                b = theYpol[j]-a*theXpol[j];
03100                previouspointin = kTRUE;
03101                discr = 4*(a*a-b*b+1);
03102                x1 = (-2*a*b+sqrt(discr))/(2*(a*a+1));
03103                x2 = (-2*a*b-sqrt(discr))/(2*(a*a+1));
03104                y1 = a*x1+b;
03105                y2 = a*x2+b;
03106                norm1 = sqrt((x1-xt)*(x1-xt)+(y1-yt)*(y1-yt));
03107                norm2 = sqrt((x2-xt)*(x2-xt)+(y2-yt)*(y2-yt));
03108                j++;
03109                if (norm1 < norm2) {
03110                   theXpol[j] = x1;
03111                   theYpol[j] = y1;
03112                } else {
03113                   theXpol[j] = x2;
03114                   theYpol[j] = y2;
03115                }
03116                PaintGraph(theGraphPolar, j+1, theXpol, theYpol, opt);
03117             }
03118             j=-1;
03119          }
03120       }
03121       if (j>=1) {
03122          // If the last point is in the circle, we draw the last serie of point.
03123          PaintGraph(theGraphPolar, j+1, theXpol, theYpol, opt);
03124       }
03125    } else {
03126       for (i=0; i<theNpoints; i++) {
03127          theXpol[i] = TMath::Abs((theY[i]-rwrmin)/radiusNDC*TMath::Cos((theX[i]-rwtmin)/thetaNDC)+1);
03128          theYpol[i] = TMath::Abs((theY[i]-rwrmin)/radiusNDC*TMath::Sin((theX[i]-rwtmin)/thetaNDC)+1);
03129       }
03130       PaintGraph(theGraphPolar, theNpoints, theXpol, theYpol,opt);
03131    }
03132 
03133    // Paint the title.
03134 
03135    if (TestBit(TH1::kNoTitle)) return;
03136    Int_t nt = strlen(theGraph->GetTitle());
03137    TPaveText *title = 0;
03138    TObject *obj;
03139    TIter next(gPad->GetListOfPrimitives());
03140    while ((obj = next())) {
03141       if (!obj->InheritsFrom(TPaveText::Class())) continue;
03142       title = (TPaveText*)obj;
03143       if (strcmp(title->GetName(),"title")) {title = 0; continue;}
03144       break;
03145    }
03146    if (nt == 0 || gStyle->GetOptTitle() <= 0) {
03147       if (title) delete title;
03148       return;
03149    }
03150    Double_t ht = gStyle->GetTitleH();
03151    Double_t wt = gStyle->GetTitleW();
03152    if (ht <= 0) ht = 1.1*gStyle->GetTitleFontSize();
03153    if (ht <= 0) ht = 0.05;
03154    if (wt <= 0) {
03155       TLatex l;
03156       l.SetTextSize(ht);
03157       l.SetTitle(theGraph->GetTitle());
03158       // Adjustment in case the title has several lines (#splitline)
03159       ht = TMath::Max(ht, 1.2*l.GetYsize()/(gPad->GetY2() - gPad->GetY1()));
03160       Double_t wndc = l.GetXsize()/(gPad->GetX2() - gPad->GetX1());
03161       wt = TMath::Min(0.7, 0.02+wndc);
03162    }
03163    if (title) {
03164       TText *t0 = (TText*)title->GetLine(0);
03165       if (t0) {
03166          if (!strcmp(t0->GetTitle(),theGraph->GetTitle())) return;
03167          t0->SetTitle(theGraph->GetTitle());
03168          if (wt > 0) title->SetX2NDC(title->GetX1NDC()+wt);
03169       }
03170       return;
03171    }
03172 
03173    Int_t talh = gStyle->GetTitleAlign()/10;
03174    if (talh < 1) talh = 1; if (talh > 3) talh = 3;
03175    Int_t talv = gStyle->GetTitleAlign()%10;
03176    if (talv < 1) talv = 1; if (talv > 3) talv = 3;
03177 
03178    Double_t xpos, ypos;
03179    xpos = gStyle->GetTitleX();
03180    ypos = gStyle->GetTitleY();
03181 
03182    if (talh == 2) xpos = xpos-wt/2.;
03183    if (talh == 3) xpos = xpos-wt;
03184    if (talv == 2) ypos = ypos+ht/2.;
03185    if (talv == 1) ypos = ypos+ht;
03186 
03187    TPaveText *ptitle = new TPaveText(xpos, ypos-ht, xpos+wt, ypos,"blNDC");
03188 
03189    // Box with the histogram title.
03190    ptitle->SetFillColor(gStyle->GetTitleFillColor());
03191    ptitle->SetFillStyle(gStyle->GetTitleStyle());
03192    ptitle->SetName("title");
03193    ptitle->SetBorderSize(gStyle->GetTitleBorderSize());
03194    ptitle->SetTextColor(gStyle->GetTitleTextColor());
03195    ptitle->SetTextFont(gStyle->GetTitleFont(""));
03196    if (gStyle->GetTitleFont("")%10 > 2)
03197    ptitle->SetTextSize(gStyle->GetTitleFontSize());
03198    ptitle->AddText(theGraph->GetTitle());
03199    ptitle->SetBit(kCanDelete);
03200    ptitle->Draw();
03201    ptitle->Paint();
03202 }
03203 
03204 
03205 //______________________________________________________________________________
03206 void TGraphPainter::PaintGraphQQ(TGraph *theGraph, Option_t *option)
03207 {
03208    /* Begin_Html
03209    Paint this graphQQ. No options for the time being.
03210    End_Html */
03211 
03212    TGraphQQ *theGraphQQ = (TGraphQQ*) theGraph;
03213 
03214    Double_t *theX    = theGraphQQ->GetX();
03215    Double_t  theXq1  = theGraphQQ->GetXq1();
03216    Double_t  theXq2  = theGraphQQ->GetXq2();
03217    Double_t  theYq1  = theGraphQQ->GetYq1();
03218    Double_t  theYq2  = theGraphQQ->GetYq2();
03219    TF1      *theF    = theGraphQQ->GetF();
03220 
03221    if (!theX){
03222       Error("TGraphQQ::Paint", "2nd dataset or theoretical function not specified");
03223       return;
03224    }
03225 
03226    if (theF){
03227       theGraphQQ->GetXaxis()->SetTitle("theoretical quantiles");
03228       theGraphQQ->GetYaxis()->SetTitle("data quantiles");
03229    }
03230 
03231    PaintGraphSimple(theGraph,option);
03232 
03233    Double_t xmin = gPad->GetUxmin();
03234    Double_t xmax = gPad->GetUxmax();
03235    Double_t ymin = gPad->GetUymin();
03236    Double_t ymax = gPad->GetUymax();
03237    Double_t yxmin, xymin, yxmax, xymax;
03238    Double_t xqmin = TMath::Max(xmin, theXq1);
03239    Double_t xqmax = TMath::Min(xmax, theXq2);
03240    Double_t yqmin = TMath::Max(ymin, theYq1);
03241    Double_t yqmax = TMath::Min(ymax, theYq2);
03242 
03243    TLine line1, line2, line3;
03244    line1.SetLineStyle(2);
03245    line3.SetLineStyle(2);
03246    yxmin = (theYq2-theYq1)*(xmin-theXq1)/(theXq2-theXq1) + theYq1;
03247    if (yxmin < ymin){
03248       xymin = (theXq2-theXq1)*(ymin-theYq1)/(theYq2-theYq1) + theXq1;
03249       line1.PaintLine(xymin, ymin, xqmin, yqmin);
03250    }
03251    else
03252       line1.PaintLine(xmin, yxmin, xqmin, yqmin);
03253 
03254    line2.PaintLine(xqmin, yqmin, xqmax, yqmax);
03255 
03256    yxmax = (theYq2-theYq1)*(xmax-theXq1)/(theXq2-theXq1) + theYq1;
03257    if (yxmax > ymax){
03258       xymax = (theXq2-theXq1)*(ymax-theYq1)/(theYq2-theYq1) + theXq1;
03259       line3.PaintLine(xqmax, yqmax, xymax, ymax);
03260    }
03261    else
03262       line3.PaintLine(xqmax, yqmax, xmax, yxmax);
03263 }
03264 
03265 
03266 //______________________________________________________________________________
03267 void TGraphPainter::PaintGraphSimple(TGraph *theGraph, Option_t *option)
03268 {
03269    /* Begin_Html
03270    Paint a simple graph, without errors bars.
03271    End_Html */
03272 
03273    if (strstr(option,"H") || strstr(option,"h")) {
03274       PaintGrapHist(theGraph, theGraph->GetN(), theGraph->GetX(), theGraph->GetY(), option);
03275    } else {
03276       PaintGraph(theGraph, theGraph->GetN(), theGraph->GetX(), theGraph->GetY(), option);
03277    }
03278 
03279    // Paint associated objects in the list of functions (for instance
03280    // the fit function).
03281    TList *functions = theGraph->GetListOfFunctions();
03282    if (!functions) return;
03283    TObjOptLink *lnk = (TObjOptLink*)functions->FirstLink();
03284    TObject *obj;
03285 
03286    while (lnk) {
03287       obj = lnk->GetObject();
03288       TVirtualPad *padsave = gPad;
03289       if (obj->InheritsFrom(TF1::Class())) {
03290          if (obj->TestBit(TF1::kNotDraw) == 0) obj->Paint("lsame");
03291       } else  {
03292          obj->Paint(lnk->GetOption());
03293       }
03294       lnk = (TObjOptLink*)lnk->Next();
03295       padsave->cd();
03296    }
03297    return;
03298 }
03299 
03300 
03301 //______________________________________________________________________________
03302 void TGraphPainter::PaintPolyLineHatches(TGraph *theGraph, Int_t n, const Double_t *x, const Double_t *y)
03303 {
03304    /* Begin_Html
03305    Paint a polyline with hatches on one side showing an exclusion zone. x and y
03306    are the the vectors holding the polyline and n the number of points in the
03307    polyline and <tt>w</tt> the width of the hatches. <tt>w</tt> can be negative.
03308    This method is not meant to be used directly. It is called automatically
03309    according to the line style convention.
03310    End_Html */
03311 
03312    Int_t i,j,nf;
03313    Double_t w = (theGraph->GetLineWidth()/100)*0.005;
03314 
03315    Double_t *xf = new Double_t[2*n];
03316    Double_t *yf = new Double_t[2*n];
03317    Double_t *xt = new Double_t[n];
03318    Double_t *yt = new Double_t[n];
03319    Double_t x1, x2, y1, y2, x3, y3, xm, ym, a, a1, a2, a3;
03320 
03321    // Compute the gPad coordinates in TRUE normalized space (NDC)
03322    Int_t ix1,iy1,ix2,iy2;
03323    Int_t iw = gPad->GetWw();
03324    Int_t ih = gPad->GetWh();
03325    Double_t x1p,y1p,x2p,y2p;
03326    gPad->GetPadPar(x1p,y1p,x2p,y2p);
03327    ix1 = (Int_t)(iw*x1p);
03328    iy1 = (Int_t)(ih*y1p);
03329    ix2 = (Int_t)(iw*x2p);
03330    iy2 = (Int_t)(ih*y2p);
03331    Double_t wndc  = TMath::Min(1.,(Double_t)iw/(Double_t)ih);
03332    Double_t hndc  = TMath::Min(1.,(Double_t)ih/(Double_t)iw);
03333    Double_t rh    = hndc/(Double_t)ih;
03334    Double_t rw    = wndc/(Double_t)iw;
03335    Double_t x1ndc = (Double_t)ix1*rw;
03336    Double_t y1ndc = (Double_t)iy1*rh;
03337    Double_t x2ndc = (Double_t)ix2*rw;
03338    Double_t y2ndc = (Double_t)iy2*rh;
03339 
03340    // Ratios to convert user space in TRUE normalized space (NDC)
03341    Double_t rx1,ry1,rx2,ry2;
03342    gPad->GetRange(rx1,ry1,rx2,ry2);
03343    Double_t rx = (x2ndc-x1ndc)/(rx2-rx1);
03344    Double_t ry = (y2ndc-y1ndc)/(ry2-ry1);
03345 
03346    // The first part of the filled area is made of the graph points.
03347    // Make sure that two adjacent points are different.
03348    xf[0] = rx*(x[0]-rx1)+x1ndc;
03349    yf[0] = ry*(y[0]-ry1)+y1ndc;
03350    nf = 0;
03351    for (i=1; i<n; i++) {
03352       if (x[i]==x[i-1] && y[i]==y[i-1]) continue;
03353       nf++;
03354       xf[nf] = rx*(x[i]-rx1)+x1ndc;
03355       yf[nf] = ry*(y[i]-ry1)+y1ndc;
03356    }
03357 
03358    // For each graph points a shifted points is computed to build up
03359    // the second part of the filled area. First and last points are
03360    // treated as special cases, outside of the loop.
03361    if (xf[1]==xf[0]) {
03362       a = TMath::PiOver2();
03363    } else {
03364       a = TMath::ATan((yf[1]-yf[0])/(xf[1]-xf[0]));
03365    }
03366    if (xf[0]<=xf[1]) {
03367       xt[0] = xf[0]-w*TMath::Sin(a);
03368       yt[0] = yf[0]+w*TMath::Cos(a);
03369    } else {
03370       xt[0] = xf[0]+w*TMath::Sin(a);
03371       yt[0] = yf[0]-w*TMath::Cos(a);
03372    }
03373 
03374    if (xf[nf]==xf[nf-1]) {
03375       a = TMath::PiOver2();
03376    } else {
03377       a = TMath::ATan((yf[nf]-yf[nf-1])/(xf[nf]-xf[nf-1]));
03378    }
03379    if (xf[nf]>=xf[nf-1]) {
03380       xt[nf] = xf[nf]-w*TMath::Sin(a);
03381       yt[nf] = yf[nf]+w*TMath::Cos(a);
03382    } else {
03383       xt[nf] = xf[nf]+w*TMath::Sin(a);
03384       yt[nf] = yf[nf]-w*TMath::Cos(a);
03385    }
03386 
03387    Double_t xi0,yi0,xi1,yi1,xi2,yi2;
03388    for (i=1; i<nf; i++) {
03389       xi0 = xf[i];
03390       yi0 = yf[i];
03391       xi1 = xf[i+1];
03392       yi1 = yf[i+1];
03393       xi2 = xf[i-1];
03394       yi2 = yf[i-1];
03395       if (xi1==xi0) {
03396          a1 = TMath::PiOver2();
03397       } else {
03398          a1  = TMath::ATan((yi1-yi0)/(xi1-xi0));
03399       }
03400       if (xi1<xi0) a1 = a1+3.14159;
03401       if (xi2==xi0) {
03402          a2 = TMath::PiOver2();
03403       } else {
03404          a2  = TMath::ATan((yi0-yi2)/(xi0-xi2));
03405       }
03406       if (xi0<xi2) a2 = a2+3.14159;
03407       x1 = xi0-w*TMath::Sin(a1);
03408       y1 = yi0+w*TMath::Cos(a1);
03409       x2 = xi0-w*TMath::Sin(a2);
03410       y2 = yi0+w*TMath::Cos(a2);
03411       xm = (x1+x2)*0.5;
03412       ym = (y1+y2)*0.5;
03413       if (xm==xi0) {
03414          a3 = TMath::PiOver2();
03415       } else {
03416          a3 = TMath::ATan((ym-yi0)/(xm-xi0));
03417       }
03418       x3 = xi0-w*TMath::Sin(a3+1.57079);
03419       y3 = yi0+w*TMath::Cos(a3+1.57079);
03420       // Rotate (x3,y3) by PI around (xi0,yi0) if it is not on the (xm,ym) side.
03421       if ((xm-xi0)*(x3-xi0)<0 && (ym-yi0)*(y3-yi0)<0) {
03422          x3 = 2*xi0-x3;
03423          y3 = 2*yi0-y3;
03424       }
03425       if ((xm==x1) && (ym==y1)) {
03426          x3 = xm;
03427          y3 = ym;
03428       }
03429       xt[i] = x3;
03430       yt[i] = y3;
03431    }
03432 
03433    // Close the polygon if the first and last points are the same
03434    if (xf[nf]==xf[0] && yf[nf]==yf[0]) {
03435       xm = (xt[nf]+xt[0])*0.5;
03436       ym = (yt[nf]+yt[0])*0.5;
03437       if (xm==xf[0]) {
03438          a3 = TMath::PiOver2();
03439       } else {
03440          a3 = TMath::ATan((ym-yf[0])/(xm-xf[0]));
03441       }
03442       x3 = xf[0]+w*TMath::Sin(a3+1.57079);
03443       y3 = yf[0]-w*TMath::Cos(a3+1.57079);
03444       if ((xm-xf[0])*(x3-xf[0])<0 && (ym-yf[0])*(y3-yf[0])<0) {
03445          x3 = 2*xf[0]-x3;
03446          y3 = 2*yf[0]-y3;
03447       }
03448       xt[nf] = x3;
03449       xt[0]  = x3;
03450       yt[nf] = y3;
03451       yt[0]  = y3;
03452    }
03453 
03454    // Find the crossing segments and remove the useless ones
03455    Double_t xc, yc, c1, b1, c2, b2;
03456    Bool_t cross = kFALSE;
03457    Int_t nf2 = nf;
03458    for (i=nf2; i>0; i--) {
03459       for (j=i-1; j>0; j--) {
03460          if(xt[i-1]==xt[i] || xt[j-1]==xt[j]) continue;
03461          c1  = (yt[i-1]-yt[i])/(xt[i-1]-xt[i]);
03462          b1  = yt[i]-c1*xt[i];
03463          c2  = (yt[j-1]-yt[j])/(xt[j-1]-xt[j]);
03464          b2  = yt[j]-c2*xt[j];
03465          if (c1 != c2) {
03466             xc = (b2-b1)/(c1-c2);
03467             yc = c1*xc+b1;
03468             if (xc>TMath::Min(xt[i],xt[i-1]) && xc<TMath::Max(xt[i],xt[i-1]) &&
03469                 xc>TMath::Min(xt[j],xt[j-1]) && xc<TMath::Max(xt[j],xt[j-1]) &&
03470                 yc>TMath::Min(yt[i],yt[i-1]) && yc<TMath::Max(yt[i],yt[i-1]) &&
03471                 yc>TMath::Min(yt[j],yt[j-1]) && yc<TMath::Max(yt[j],yt[j-1])) {
03472                nf++; xf[nf] = xt[i]; yf[nf] = yt[i];
03473                nf++; xf[nf] = xc   ; yf[nf] = yc;
03474                i = j;
03475                cross = kTRUE;
03476                break;
03477             } else {
03478                continue;
03479             }
03480          } else {
03481             continue;
03482          }
03483       }
03484       if (!cross) {
03485          nf++;
03486          xf[nf] = xt[i];
03487          yf[nf] = yt[i];
03488       }
03489       cross = kFALSE;
03490    }
03491    nf++; xf[nf] = xt[0]; yf[nf] = yt[0];
03492 
03493    // NDC to user coordinates
03494    for (i=0; i<nf+1; i++) {
03495       xf[i] = (1/rx)*(xf[i]-x1ndc)+rx1;
03496       yf[i] = (1/ry)*(yf[i]-y1ndc)+ry1;
03497    }
03498 
03499    // Draw filled area
03500    gPad->PaintFillArea(nf+1,xf,yf);
03501    theGraph->TAttLine::Modify(); // In case of PaintFillAreaHatches
03502 
03503    delete [] xf;
03504    delete [] yf;
03505    delete [] xt;
03506    delete [] yt;
03507 }
03508 
03509 
03510 //______________________________________________________________________________
03511 void TGraphPainter::PaintStats(TGraph *theGraph, TF1 *fit)
03512 {
03513    /* Begin_Html
03514    Paint the statistics box with the fit info.
03515    End_Html */
03516 
03517    Int_t dofit;
03518    TPaveStats *stats  = 0;
03519    TList *functions = theGraph->GetListOfFunctions();
03520    TIter next(functions);
03521    TObject *obj;
03522    while ((obj = next())) {
03523       if (obj->InheritsFrom(TPaveStats::Class())) {
03524          stats = (TPaveStats*)obj;
03525          break;
03526       }
03527    }
03528 
03529    if (stats) dofit  = stats->GetOptFit();
03530    else       dofit  = gStyle->GetOptFit();
03531 
03532    if (!dofit) fit = 0;
03533    if (!fit) return;
03534    if (dofit  == 1) dofit  =  111;
03535    Int_t nlines = 0;
03536    Int_t print_fval    = dofit%10;
03537    Int_t print_ferrors = (dofit/10)%10;
03538    Int_t print_fchi2   = (dofit/100)%10;
03539    Int_t print_fprob   = (dofit/1000)%10;
03540    Int_t nlinesf = print_fval + print_fchi2 + print_fprob;
03541    if (fit) nlinesf += fit->GetNpar();
03542    Bool_t done = kFALSE;
03543    Double_t  statw  = 1.8*gStyle->GetStatW();
03544    Double_t  stath  = 0.25*(nlines+nlinesf)*gStyle->GetStatH();
03545    if (stats) {
03546       stats->Clear();
03547       done = kTRUE;
03548    } else {
03549       stats  = new TPaveStats(
03550                gStyle->GetStatX()-statw,
03551                gStyle->GetStatY()-stath,
03552                gStyle->GetStatX(),
03553                gStyle->GetStatY(),"brNDC");
03554 
03555       stats->SetParent(functions);
03556       stats->SetOptFit(dofit);
03557       stats->SetOptStat(0);
03558       stats->SetFillColor(gStyle->GetStatColor());
03559       stats->SetFillStyle(gStyle->GetStatStyle());
03560       stats->SetBorderSize(gStyle->GetStatBorderSize());
03561       stats->SetTextFont(gStyle->GetStatFont());
03562       if (gStyle->GetStatFont()%10 > 2)
03563          stats->SetTextSize(gStyle->GetStatFontSize());
03564       stats->SetFitFormat(gStyle->GetFitFormat());
03565       stats->SetStatFormat(gStyle->GetStatFormat());
03566       stats->SetName("stats");
03567 
03568       stats->SetTextColor(gStyle->GetStatTextColor());
03569       stats->SetTextAlign(12);
03570       stats->SetBit(kCanDelete);
03571       stats->SetBit(kMustCleanup);
03572    }
03573 
03574    char t[64];
03575    char textstats[50];
03576    Int_t ndf = fit->GetNDF();
03577    snprintf(textstats,50,"#chi^{2} / ndf = %s%s / %d","%",stats->GetFitFormat(),ndf);
03578    snprintf(t,64,textstats,(Float_t)fit->GetChisquare());
03579    if (print_fchi2) stats->AddText(t);
03580    if (print_fprob) {
03581       snprintf(textstats,50,"Prob  = %s%s","%",stats->GetFitFormat());
03582       snprintf(t,64,textstats,(Float_t)TMath::Prob(fit->GetChisquare(),ndf));
03583       stats->AddText(t);
03584    }
03585    if (print_fval || print_ferrors) {
03586       for (Int_t ipar=0;ipar<fit->GetNpar();ipar++) {
03587          if (print_ferrors) {
03588             snprintf(textstats,50,"%-8s = %s%s #pm %s%s ",fit->GetParName(ipar),"%",stats->GetFitFormat(),"%",stats->GetFitFormat());
03589             snprintf(t,64,textstats,(Float_t)fit->GetParameter(ipar)
03590                             ,(Float_t)fit->GetParError(ipar));
03591          } else {
03592             snprintf(textstats,50,"%-8s = %s%s ",fit->GetParName(ipar),"%",stats->GetFitFormat());
03593             snprintf(t,64,textstats,(Float_t)fit->GetParameter(ipar));
03594          }
03595          t[63] = 0;
03596          stats->AddText(t);
03597       }
03598    }
03599 
03600    if (!done) functions->Add(stats);
03601    stats->Paint();
03602 }
03603 
03604 //______________________________________________________________________________
03605 void TGraphPainter::Smooth(TGraph *theGraph, Int_t npoints, Double_t *x, Double_t *y, Int_t drawtype)
03606 {
03607    /* Begin_Html
03608    Smooth a curve given by N points.
03609    <p>
03610    The original code come from an underlaying routine for Draw based on the
03611    CERN GD3 routine TVIPTE:
03612    <pre>
03613         Author - Marlow etc.   Modified by - P. Ward     Date -  3.10.1973
03614    </pre>
03615    This method draws a smooth tangentially continuous curve through
03616    the sequence of data points P(I) I=1,N where P(I)=(X(I),Y(I))
03617    the curve is approximated by a polygonal arc of short vectors .
03618    the data points can represent open curves, P(1) != P(N) or closed
03619    curves P(2) == P(N) . If a tangential discontinuity at P(I) is
03620    required , then set P(I)=P(I+1) . loops are also allowed .
03621    <p>
03622    Reference Marlow and Powell,Harwell report No.R.7092.1972
03623    MCCONALOGUE,Computer Journal VOL.13,NO4,NOV1970Pp392 6
03624    <p>
03625    <ul>
03626    <li>  npoints   : Number of data points.
03627    <li>  x         : Abscissa
03628    <li>  y         : Ordinate
03629    </ul>
03630    End_Html */
03631 
03632    Int_t i, k, kp, km, npointsMax, banksize, n2, npt;
03633    Int_t maxiterations, finished;
03634    Int_t jtype, ktype, closed;
03635    Double_t sxmin, sxmax, symin, symax;
03636    Double_t delta;
03637    Double_t xorg, yorg;
03638    Double_t ratio_signs, xratio, yratio;
03639    Int_t flgic, flgis;
03640    Int_t iw, loptx;
03641    Double_t p1, p2, p3, p4, p5, p6;
03642    Double_t w1, w2, w3;
03643    Double_t a, b, c, r, s, t, z;
03644    Double_t co, so, ct, st, ctu, stu, xnt;
03645    Double_t dx1, dy1, dx2, dy2, dk1, dk2;
03646    Double_t xo, yo, dx, dy, xt, yt;
03647    Double_t xa, xb, ya, yb;
03648    Double_t u1, u2, u3, tj;
03649    Double_t cc, err;
03650    Double_t sb, sth;
03651    Double_t wsign, tsquare, tcube;
03652    c = t = co = so = ct = st = ctu = stu = dx1 = dy1 = dx2 = dy2 = 0;
03653    xt = yt = xa = xb = ya = yb = u1 = u2 = u3 = tj = sb = 0;
03654 
03655    npointsMax  = npoints*10;
03656    n2          = npointsMax-2;
03657    banksize    = n2;
03658 
03659    Double_t *qlx = new Double_t[npointsMax];
03660    Double_t *qly = new Double_t[npointsMax];
03661    if (!qlx || !qly) {
03662       Error("Smooth", "not enough space in memory");
03663       return;
03664    }
03665 
03666    //  Decode the type of curve according to
03667    //  chopt of IGHIST.
03668    //  ('S', 'SA', 'SA1' ,'XS', 'XSA', or 'XSA1')
03669 
03670    loptx = kFALSE;
03671    jtype  = (drawtype%1000)-10;
03672    if (jtype > 0) { ktype = jtype; loptx = kTRUE; }
03673    else             ktype = drawtype%1000;
03674 
03675    Double_t ruxmin = gPad->GetUxmin();
03676    Double_t ruymin = gPad->GetUymin();
03677    if (ktype == 3) {
03678       xorg = ruxmin;
03679       yorg = ruymin;
03680    } else {
03681       xorg = TMath::Max((Double_t)0,ruxmin);
03682       yorg = TMath::Min(TMath::Max((Double_t)0,ruymin),gPad->GetUymax());
03683    }
03684 
03685    // delta is the accuracy required in constructing the curve.
03686    // If it is zero then the routine calculates a value otherwise
03687    // it uses this value. (default is 0.0)
03688 
03689    delta         = 0.00055;
03690    maxiterations = 20;
03691 
03692    //       Scale data to the range 0-ratio_signs in X, 0-1 in Y
03693    //       where ratio_signs is the ratio between the number of changes
03694    //       of sign in Y divided by the number of changes of sign in X
03695 
03696    sxmin = x[0];
03697    sxmax = x[0];
03698    symin = y[0];
03699    symax = y[0];
03700    Double_t six   = 1;
03701    Double_t siy   = 1;
03702    for (i=1;i<npoints;i++) {
03703       if (i > 1) {
03704          if ((x[i]-x[i-1])*(x[i-1]-x[i-2]) < 0) six++;
03705          if ((y[i]-y[i-1])*(y[i-1]-y[i-2]) < 0) siy++;
03706       }
03707       if (x[i] < sxmin) sxmin = x[i];
03708       if (x[i] > sxmax) sxmax = x[i];
03709       if (y[i] < symin) symin = y[i];
03710       if (y[i] > symax) symax = y[i];
03711    }
03712    closed = 0;
03713    Double_t dx1n   = TMath::Abs(x[npoints-1]-x[0]);
03714    Double_t dy1n   = TMath::Abs(y[npoints-1]-y[0]);
03715    if (dx1n < 0.01*(sxmax-sxmin) && dy1n < 0.01*(symax-symin))  closed = 1;
03716    if (sxmin == sxmax) xratio = 1;
03717    else {
03718       if (six > 1) ratio_signs = siy/six;
03719       else         ratio_signs = 20;
03720       xratio = ratio_signs/(sxmax-sxmin);
03721    }
03722    if (symin == symax) yratio = 1;
03723    else                yratio = 1/(symax-symin);
03724 
03725    qlx[0] = x[0];
03726    qly[0] = y[0];
03727    for (i=0;i<npoints;i++) {
03728       x[i] = (x[i]-sxmin)*xratio;
03729       y[i] = (y[i]-symin)*yratio;
03730    }
03731 
03732    //           finished is minus one if we must draw a straight line from P(k-1)
03733    //           to P(k). finished is one if the last call to IPL has  <  N2
03734    //           points. finished is zero otherwise. npt counts the X and Y
03735    //           coordinates in work . When npt=N2 a call to IPL is made.
03736 
03737    finished = 0;
03738    npt      = 1;
03739    k        = 1;
03740 
03741    //           Convert coordinates back to original system
03742 
03743    //           Separate the set of data points into arcs P(k-1),P(k).
03744    //           Calculate the direction cosines. first consider whether
03745    //           there is a continuous tangent at the endpoints.
03746 
03747    if (!closed) {
03748       if (x[0] != x[npoints-1] || y[0] != y[npoints-1]) goto L40;
03749       if (x[npoints-2] == x[npoints-1] && y[npoints-2] == y[npoints-1]) goto L40;
03750       if (x[0] == x[1] && y[0] == y[1]) goto L40;
03751    }
03752    flgic = kFALSE;
03753    flgis = kTRUE;
03754 
03755    //           flgic is true if the curve is open and false if it is closed.
03756    //           flgis is true in the main loop, but is false if there is
03757    //           a deviation from the main loop.
03758 
03759    km = npoints - 1;
03760 
03761    //           Calculate direction cosines at P(1) using P(N-1),P(1),P(2).
03762 
03763    goto L100;
03764 L40:
03765    flgic = kTRUE;
03766    flgis = kFALSE;
03767 
03768    //           Skip excessive consecutive equal points.
03769 
03770 L50:
03771    if (k >= npoints) {
03772       finished = 1;  //*-*-  Prepare to clear out remaining short vectors before returning
03773       if (npt > 1) goto L310;
03774       goto L390;
03775    }
03776    k++;
03777    if (x[k-1] == x[k-2] && y[k-1] == y[k-2])  goto L50;
03778 L60:
03779    km = k-1;
03780    if (k > npoints) {
03781       finished = 1;  //*-*-  Prepare to clear out remaining short vectors before returning
03782       if (npt > 1) goto L310;
03783       goto L390;
03784    }
03785    if (k < npoints) goto L90;
03786    if (!flgic) { kp = 2; goto L130;}
03787 
03788 L80:
03789    if (flgis) goto L150;
03790 
03791    //           Draw a straight line from P(k-1) to P(k).
03792 
03793    finished = -1;
03794    goto L170;
03795 
03796    //           Test whether P(k) is a cusp.
03797 
03798 L90:
03799    if (x[k-1] == x[k] && y[k-1] == y[k]) goto L80;
03800 L100:
03801    kp = k+1;
03802    goto L130;
03803 
03804    //           Branch if the next section of the curve begins at a cusp.
03805 
03806 L110:
03807    if (!flgis) goto L50;
03808 
03809 //*-*-           Carry forward the direction cosines from the previous arc.
03810 
03811 L120:
03812    co = ct;
03813    so = st;
03814    k++;
03815    goto L60;
03816 
03817    //           Calculate the direction cosines at P(k).  If k=1 then
03818    //           N-1 is used for k-1. If k=N then 2 is used for k+1.
03819    //           direction cosines at P(k) obtained from P(k-1),P(k),P(k+1).
03820 
03821 L130:
03822    dx1 = x[k-1]  - x[km-1];
03823    dy1 = y[k-1]  - y[km-1];
03824    dk1 = dx1*dx1 + dy1*dy1;
03825    dx2 = x[kp-1] - x[k-1];
03826    dy2 = y[kp-1] - y[k-1];
03827    dk2 = dx2*dx2 + dy2*dy2;
03828    ctu = dx1*dk2 + dx2*dk1;
03829    stu = dy1*dk2 + dy2*dk1;
03830    xnt = ctu*ctu + stu*stu;
03831 
03832    //           If both ctu and stu are zero,then default.This can
03833    //           occur when P(k)=P(k+1). I.E. A loop.
03834 
03835    if (xnt < 1.E-25) {
03836       ctu = dy1;
03837       stu =-dx1;
03838       xnt = dk1;
03839    }
03840    //           Normalise direction cosines.
03841 
03842    ct = ctu/TMath::Sqrt(xnt);
03843    st = stu/TMath::Sqrt(xnt);
03844    if (flgis) goto L160;
03845 
03846    //           Direction cosines at P(k-1) obtained from P(k-1),P(k),P(k+1).
03847 
03848    w3    = 2*(dx1*dy2-dx2*dy1);
03849    co    = ctu+w3*dy1;
03850    so    = stu-w3*dx1;
03851    xnt   = 1/TMath::Sqrt(co*co+so*so);
03852    co    = co*xnt;
03853    so    = so*xnt;
03854    flgis = kTRUE;
03855    goto L170;
03856 
03857    //           Direction cosines at P(k) obtained from P(k-2),P(k-1),P(k).
03858 
03859 L150:
03860    w3    = 2*(dx1*dy2-dx2*dy1);
03861    ct    = ctu-w3*dy2;
03862    st    = stu+w3*dx2;
03863    xnt   = 1/TMath::Sqrt(ct*ct+st*st);
03864    ct    = ct*xnt;
03865    st    = st*xnt;
03866    flgis = kFALSE;
03867    goto L170;
03868 L160:
03869    if (k <= 1) goto L120;
03870 
03871    //           For the arc between P(k-1) and P(k) with direction cosines co,
03872    //           so and ct,st respectively, calculate the coefficients of the
03873    //           parametric cubic represented by X(t) and Y(t) where
03874    //           X(t)=xa*t**3 + xb*t**2 + co*t + xo
03875    //           Y(t)=ya*t**3 + yb*t**2 + so*t + yo
03876 
03877 L170:
03878    xo = x[k-2];
03879    yo = y[k-2];
03880    dx = x[k-1] - xo;
03881    dy = y[k-1] - yo;
03882 
03883    //           Initialise the values of X(TI),Y(TI) in xt and yt respectively.
03884 
03885    xt = xo;
03886    yt = yo;
03887    if (finished < 0) {  //*-*- Draw a straight line between (xo,yo) and (xt,yt)
03888       xt += dx;
03889       yt += dy;
03890       goto L300;
03891    }
03892    c  = dx*dx+dy*dy;
03893    a  = co+ct;
03894    b  = so+st;
03895    r  = dx*a+dy*b;
03896    t  = c*6/(TMath::Sqrt(r*r+2*(7-co*ct-so*st)*c)+r);
03897    tsquare = t*t;
03898    tcube   = t*tsquare;
03899    xa = (a*t-2*dx)/tcube;
03900    xb = (3*dx-(co+a)*t)/tsquare;
03901    ya = (b*t-2*dy)/tcube;
03902    yb = (3*dy-(so+b)*t)/tsquare;
03903 
03904    //           If the curve is close to a straight line then use a straight
03905    //           line between (xo,yo) and (xt,yt).
03906 
03907    if (.75*TMath::Max(TMath::Abs(dx*so-dy*co),TMath::Abs(dx*st-dy*ct)) <= delta) {
03908       finished = -1;
03909       xt += dx;
03910       yt += dy;
03911       goto L300;
03912    }
03913 
03914    //           Calculate a set of values 0 == t(0).LTCT(1) <  ...  < t(M)=TC
03915    //           such that polygonal arc joining X(t(J)),Y(t(J)) (J=0,1,..M)
03916    //           is within the required accuracy of the curve
03917 
03918    tj = 0;
03919    u1 = ya*xb-yb*xa;
03920    u2 = yb*co-xb*so;
03921    u3 = so*xa-ya*co;
03922 
03923    //           Given t(J), calculate t(J+1). The values of X(t(J)),
03924    //           Y(t(J)) t(J) are contained in xt,yt and tj respectively.
03925 
03926 L180:
03927    s  = t - tj;
03928    iw = -2;
03929 
03930    //           Define iw here later.
03931 
03932    p1 = (2*u1)*tj-u3;
03933    p2 = (u1*tj-u3)*3*tj+u2;
03934    p3 = 3*tj*ya+yb;
03935    p4 = (p3+yb)*tj+so;
03936    p5 = 3*tj*xa+xb;
03937    p6 = (p5+xb)*tj+co;
03938 
03939    //           Test D(tj,THETA). A is set to (Y(tj+s)-Y(tj))/s.b is
03940    //           set to (X(tj+s)-X(tj))/s.
03941 
03942    cc  = 0.8209285;
03943    err = 0.1209835;
03944 L190:
03945    iw -= 2;
03946 L200:
03947    a   = (s*ya+p3)*s+p4;
03948    b   = (s*xa+p5)*s+p6;
03949 
03950    //           Set z to PSI(D/delta)-cc.
03951 
03952    w1 = -s*(s*u1+p1);
03953    w2 = s*s*u1-p2;
03954    w3 = 1.5*w1+w2;
03955 
03956    //           Set the estimate of (THETA-tj)/s.Then set the numerator
03957    //           of the expression (EQUATION 4.4)/s. Then set the square
03958    //           of D(tj,tj+s)/delta. Then replace z by PSI(D/delta)-cc.
03959 
03960    if (w3 > 0) wsign = TMath::Abs(w1);
03961    else        wsign = -TMath::Abs(w1);
03962    sth = 0.5+wsign/(3.4*TMath::Abs(w1)+5.2*TMath::Abs(w3));
03963    z   = s*sth*(s-s*sth)*(w1*sth+w1+w2);
03964    z   = z*z/((a*a+b*b)*(delta*delta));
03965    z   = (z+2.642937)*z/((.3715652*z+3.063444)*z+.2441889)-cc;
03966 
03967    //           Branch if z has been calculated
03968 
03969    if (iw > 0) goto L250;
03970    if (z > err) goto L240;
03971    goto L220;
03972 L210:
03973    iw -= 2;
03974 L220:
03975    if (iw+2 == 0) goto L190;
03976    if (iw+2 >  0) goto L290;
03977 
03978    //           Last part of arc.
03979 
03980 L230:
03981    xt = x[k-1];
03982    yt = y[k-1];
03983    s  = 0;
03984    goto L300;
03985 
03986    //           z(s). find a value of s where 0 <= s <= sb such that
03987    //           TMath::Abs(z(s)) < err
03988 
03989 L240:
03990    kp = 0;
03991    c  = z;
03992    sb = s;
03993 L250:
03994    theGraph->Zero(kp,0,sb,err,s,z,maxiterations);
03995    if (kp == 2) goto L210;
03996    if (kp > 2) {
03997       Error("Smooth", "Attempt to plot outside plot limits");
03998       goto L230;
03999    }
04000    if (iw > 0) goto L200;
04001 
04002    //           Set z=z(s) for s=0.
04003 
04004    if (iw < 0) {
04005       z  = -cc;
04006       iw = 0;
04007       goto L250;
04008    }
04009 
04010    //           Set z=z(s) for s=sb.
04011 
04012    z  = c;
04013    iw = 1;
04014    goto L250;
04015 
04016    //           Update tj,xt and yt.
04017 
04018 L290:
04019    xt = xt + s*b;
04020    yt = yt + s*a;
04021    tj = s  + tj;
04022 
04023    //           Convert coordinates to original system
04024 
04025 L300:
04026    qlx[npt] = sxmin + xt/xratio;
04027    qly[npt] = symin + yt/yratio;
04028    npt++;
04029 
04030    //           If a fill area must be drawn and if the banks LX and
04031    //           LY are too small they are enlarged in order to draw
04032    //           the filled area in one go.
04033 
04034    if (npt < banksize)  goto L320;
04035    if (drawtype >= 1000 || ktype > 1) {
04036       Int_t newsize = banksize + n2;
04037       Double_t *qtemp = new Double_t[banksize];
04038       for (i=0;i<banksize;i++) qtemp[i] = qlx[i];
04039       delete [] qlx;
04040       qlx = new Double_t[newsize];
04041       for (i=0;i<banksize;i++) qlx[i]   = qtemp[i];
04042       for (i=0;i<banksize;i++) qtemp[i] = qly[i];
04043       delete [] qly;
04044       qly = new Double_t[newsize];
04045       for (i=0;i<banksize;i++) qly[i] = qtemp[i];
04046       delete [] qtemp;
04047       banksize = newsize;
04048       goto L320;
04049    }
04050 
04051    //           Draw the graph
04052 
04053 L310:
04054    if (drawtype >= 1000) {
04055       gPad->PaintFillArea(npt,qlx,qly, "B");
04056    }
04057    else {
04058       if (ktype > 1) {
04059          if (!loptx) {
04060             qlx[npt]   = qlx[npt-1];
04061             qlx[npt+1] = qlx[0];
04062             qly[npt]   = yorg;
04063             qly[npt+1] = yorg;
04064          }
04065          else {
04066             qlx[npt]   = xorg;
04067             qlx[npt+1] = xorg;
04068             qly[npt]   = qly[npt-1];
04069             qly[npt+1] = qly[0];
04070          }
04071          gPad->PaintFillArea(npt+2,qlx,qly);
04072       }
04073       if (TMath::Abs(theGraph->GetLineWidth())>99) PaintPolyLineHatches(theGraph, npt, qlx, qly);
04074       gPad->PaintPolyLine(npt,qlx,qly);
04075    }
04076    npt = 1;
04077    qlx[0] = sxmin + xt/xratio;
04078    qly[0] = symin + yt/yratio;
04079 L320:
04080    if (finished > 0) goto L390;
04081    if (finished < 0) { finished = 0; goto L110;}
04082    if (s > 0) goto L180;
04083    goto L110;
04084 
04085    //           Convert coordinates back to original system
04086 
04087 L390:
04088    for (i=0;i<npoints;i++) {
04089       x[i] = sxmin + x[i]/xratio;
04090       y[i] = symin + y[i]/yratio;
04091    }
04092 
04093    delete [] qlx;
04094    delete [] qly;
04095 }

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