TPainter3dAlgorithms.cxx

Go to the documentation of this file.
00001 // @(#)root/histpainter:$Id: TPainter3dAlgorithms.cxx 36057 2010-10-04 13:51:04Z couet $
00002 // Author: Rene Brun, Evgueni Tcherniaev, Olivier Couet   12/12/94
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 
00013 //______________________________________________________________________________
00014 /* Begin_Html
00015 <center><h2>Legos and Surfaces package</h2></center>
00016 This package was originally written by Evgueni Tcherniaev from IHEP/Protvino.
00017 <p>
00018 The original Fortran implementation was adapted to HIGZ/PAW by Olivier Couet
00019 and  Evgueni Tcherniaev.
00020 <p>
00021 This class is a subset of the original system. It has been converted to a C++
00022 class by Rene Brun.
00023 End_Html */
00024 
00025 #include <stdlib.h>
00026 
00027 #include "TROOT.h"
00028 #include "TPainter3dAlgorithms.h"
00029 #include "TVirtualPad.h"
00030 #include "THistPainter.h"
00031 #include "TH1.h"
00032 #include "TF3.h"
00033 #include "TView.h"
00034 #include "TVirtualX.h"
00035 #include "Hoption.h"
00036 #include "Hparam.h"
00037 #include "TMath.h"
00038 #include "TStyle.h"
00039 #include "TObjArray.h"
00040 #include "THLimitsFinder.h"
00041 #include "TColor.h"
00042 
00043 #ifdef R__SUNCCBUG
00044 const Double_t kRad = 1.74532925199432955e-02;
00045 #else
00046 const Double_t kRad = TMath::ATan(1)*Double_t(4)/Double_t(180);
00047 #endif
00048 const Double_t kFdel = 0.;
00049 const Double_t kDel = 0.0001;
00050 const Int_t kNiso = 4;
00051 const Int_t kNmaxp = kNiso*13;
00052 const Int_t kNmaxt = kNiso*12;
00053 const Int_t kLmax = 12;
00054 const Int_t kF3FillColor1 = 201;
00055 const Int_t kF3FillColor2 = 202;
00056 const Int_t kF3LineColor  = 203;
00057 
00058 Int_t    TPainter3dAlgorithms::fgF3Clipping = 0;
00059 Double_t TPainter3dAlgorithms::fgF3XClip = 0.;
00060 Double_t TPainter3dAlgorithms::fgF3YClip = 0.;
00061 Double_t TPainter3dAlgorithms::fgF3ZClip = 0.;
00062 TF3     *TPainter3dAlgorithms::fgCurrentF3 = 0;
00063 
00064 // Static arrays used to paint stacked lego plots.
00065 const Int_t kVSizeMax = 20;
00066 static Double_t gV[kVSizeMax];
00067 static Double_t gTT[4*kVSizeMax];
00068 static Int_t gColorMain[kVSizeMax+1];
00069 static Int_t gColorDark[kVSizeMax+1];
00070 
00071 extern TH1  *gCurrentHist; //these 3 globals should be replaced by class members
00072 extern Hoption_t Hoption;
00073 extern Hparam_t  Hparam;
00074 
00075 ClassImp(TPainter3dAlgorithms)
00076 
00077 
00078 //______________________________________________________________________________
00079 TPainter3dAlgorithms::TPainter3dAlgorithms(): TObject(), TAttLine(1,1,1), TAttFill(1,0)
00080 {
00081    // Lego default constructor
00082 
00083    Int_t i;
00084    fIfrast          = 0;
00085    fMesh            = 1;
00086    fRaster          = 0;
00087    fColorTop        = 1;
00088    fColorBottom     = 1;
00089    fNlevel          = 0;
00090    fSystem          = kCARTESIAN;
00091    fDrawFace        = 0;
00092    fLegoFunction    = 0;
00093    fSurfaceFunction = 0;
00094 
00095 
00096    TList *stack = 0;
00097    if (gCurrentHist) stack = gCurrentHist->GetPainter()->GetStack();
00098    fNStack = 0;
00099    if (stack) fNStack = stack->GetSize();
00100    if (fNStack > kVSizeMax) {
00101       fColorMain  = new Int_t[fNStack+1];
00102       fColorDark  = new Int_t[fNStack+1];
00103    } else {
00104       fColorMain = &gColorMain[0];
00105       fColorDark = &gColorDark[0];
00106    }
00107 
00108    for (i=0;i<fNStack;i++) { fColorMain[i] = 1; fColorDark[i] = 1; }
00109    for (i=0;i<3;i++)       { fRmin[i] = 0, fRmax[i] = 1; }
00110    for (i=0;i<4;i++)       { fYls[i] = 0; }
00111 
00112    for (i=0;i<30;i++)      { fJmask[i] = 0; }
00113    for (i=0;i<200;i++)     { fLevelLine[i] = 0; }
00114    for (i=0;i<465;i++)     { fMask[i] = 0; }
00115    for (i=0;i<258;i++)     { fColorLevel[i] = 0; }
00116    for (i=0;i<1200;i++)    { fPlines[i] = 0.; }
00117    for (i=0;i<200;i++)     { fT[i] = 0.; }
00118    for (i=0;i<2000;i++)    { fU[i] = 0.; fD[i] = 0.; }
00119    for (i=0;i<12;i++)      { fVls[i] = 0.; }
00120    for (i=0;i<257;i++)     { fFunLevel[i] = 0.; }
00121    for (i=0;i<183;i++)     { fAphi[i] = 0.; }
00122    for (i=0;i<8;i++)       { fF8[i] = 0.; }
00123 
00124    fLoff   = 0;
00125    fNT     = 0;
00126    fNcolor = 0;
00127    fNlines = 0;
00128    fNqs    = 0;
00129    fNxrast = 0;
00130    fNyrast = 0;
00131    fIc1    = 0;
00132    fIc2    = 0;
00133    fIc3    = 0;
00134    fQA     = 0.;
00135    fQD     = 0.;
00136    fQS     = 0.;
00137    fX0     = 0.;
00138    fYdl    = 0.;
00139    fXrast  = 0.;
00140    fYrast  = 0.;
00141    fFmin   = 0.;
00142    fFmax   = 0.;
00143    fDXrast = 0.;
00144    fDYrast = 0.;
00145    fDX     = 0.;
00146 }
00147 
00148 
00149 //______________________________________________________________________________
00150 TPainter3dAlgorithms::TPainter3dAlgorithms(Double_t *rmin, Double_t *rmax, Int_t system)
00151       : TObject(), TAttLine(1,1,1), TAttFill(1,0)
00152 {
00153    // Normal default constructor
00154    //
00155    //  rmin[3], rmax[3] are the limits of the lego object depending on
00156    //  the selected coordinate system
00157 
00158    Int_t i;
00159    Double_t psi;
00160 
00161    fIfrast       = 0;
00162    fMesh         = 1;
00163    fRaster       = 0;
00164    fColorTop     = 1;
00165    fColorBottom  = 1;
00166    fNlevel       = 0;
00167    fSystem       = system;
00168    if (system == kCARTESIAN || system == kPOLAR) psi =  0;
00169    else                                          psi = 90;
00170    fDrawFace        = 0;
00171    fLegoFunction    = 0;
00172    fSurfaceFunction = 0;
00173 
00174    TList *stack = gCurrentHist->GetPainter()->GetStack();
00175    fNStack = 0;
00176    if (stack) fNStack = stack->GetSize();
00177    if (fNStack > kVSizeMax) {
00178       fColorMain  = new Int_t[fNStack+1];
00179       fColorDark  = new Int_t[fNStack+1];
00180    } else {
00181       fColorMain = &gColorMain[0];
00182       fColorDark = &gColorDark[0];
00183    }
00184 
00185    for (i=0;i<fNStack;i++) { fColorMain[i] = 1; fColorDark[i] = 1; }
00186    for (i=0;i<3;i++)       { fRmin[i] = rmin[i], fRmax[i] = rmax[i]; }
00187    for (i=0;i<4;i++)       { fYls[i] = 0; }
00188 
00189    for (i=0;i<30;i++)      { fJmask[i] = 0; }
00190    for (i=0;i<200;i++)     { fLevelLine[i] = 0; }
00191    for (i=0;i<465;i++)     { fMask[i] = 0; }
00192    for (i=0;i<258;i++)     { fColorLevel[i] = 0; }
00193    for (i=0;i<1200;i++)    { fPlines[i] = 0.; }
00194    for (i=0;i<200;i++)     { fT[i] = 0.; }
00195    for (i=0;i<2000;i++)    { fU[i] = 0.; fD[i] = 0.; }
00196    for (i=0;i<12;i++)      { fVls[i] = 0.; }
00197    for (i=0;i<257;i++)     { fFunLevel[i] = 0.; }
00198    for (i=0;i<183;i++)     { fAphi[i] = 0.; }
00199    for (i=0;i<8;i++)       { fF8[i] = 0.; }
00200 
00201    fLoff   = 0;
00202    fNT     = 0;
00203    fNcolor = 0;
00204    fNlines = 0;
00205    fNqs    = 0;
00206    fNxrast = 0;
00207    fNyrast = 0;
00208    fIc1    = 0;
00209    fIc2    = 0;
00210    fIc3    = 0;
00211    fQA     = 0.;
00212    fQD     = 0.;
00213    fQS     = 0.;
00214    fX0     = 0.;
00215    fYdl    = 0.;
00216    fXrast  = 0.;
00217    fYrast  = 0.;
00218    fFmin   = 0.;
00219    fFmax   = 0.;
00220    fDXrast = 0.;
00221    fDYrast = 0.;
00222    fDX     = 0.;
00223 
00224    TView *view = 0;
00225    if (gPad) view = gPad->GetView();
00226    if (!view) view = TView::CreateView(fSystem, rmin, rmax);
00227    view->SetView(gPad->GetPhi(), gPad->GetTheta(), psi, i);
00228    view->SetRange(rmin,rmax);
00229 }
00230 
00231 
00232 //______________________________________________________________________________
00233 TPainter3dAlgorithms::~TPainter3dAlgorithms()
00234 {
00235    // Lego default destructor
00236 
00237    if (fRaster) {delete [] fRaster; fRaster = 0;}
00238    if (fNStack > kVSizeMax) {
00239       delete [] fColorMain;
00240       delete [] fColorDark;
00241    }
00242 }
00243 
00244 
00245 //______________________________________________________________________________
00246 void TPainter3dAlgorithms::BackBox(Double_t ang)
00247 {
00248    // Draw back surfaces of surrounding box
00249    //
00250    //    Input  ANG     - angle between X and Y axis
00251    //
00252    //           DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
00253    //             ICODES(*) - set of codes for this face
00254    //             NP        - number of nodes in face
00255    //             IFACE(NP) - face
00256    //             T(NP)     - additional function
00257 
00258    /* Initialized data */
00259    static Int_t iface1[4] = { 1,4,8,5 };
00260    static Int_t iface2[4] = { 4,3,7,8 };
00261    TView *view = 0;
00262 
00263    if (gPad) view = gPad->GetView();
00264    if (!view) {
00265       Error("BackBox", "no TView in current pad");
00266       return;
00267    }
00268 
00269    /* Local variables */
00270    Double_t cosa, sina;
00271    Int_t i;
00272    Double_t r[24]        /* was [3][8] */, av[24]        /* was [3][8] */;
00273    Int_t icodes[3];
00274    Double_t tt[4];
00275    Int_t ix1, ix2, iy1, iy2, iz1, iz2;
00276 
00277    cosa = TMath::Cos(kRad*ang);
00278    sina = TMath::Sin(kRad*ang);
00279    view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
00280    for (i = 1; i <= 8; ++i) {
00281       r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
00282       r[i*3 - 2] = av[i*3 - 2]*sina;
00283       r[i*3 - 1] = av[i*3 - 1];
00284    }
00285 
00286    //          D R A W   F O R W A R D   F A C E S */
00287    icodes[0] = 0;
00288    icodes[1] = 0;
00289    icodes[2] = 0;
00290    tt[0] = r[iface1[0]*3 - 1];
00291    tt[1] = r[iface1[1]*3 - 1];
00292    tt[2] = r[iface1[2]*3 - 1];
00293    tt[3] = r[iface1[3]*3 - 1];
00294    (this->*fDrawFace)(icodes, r, 4, iface1, tt);
00295    tt[0] = r[iface2[0]*3 - 1];
00296    tt[1] = r[iface2[1]*3 - 1];
00297    tt[2] = r[iface2[2]*3 - 1];
00298    tt[3] = r[iface2[3]*3 - 1];
00299    (this->*fDrawFace)(icodes, r, 4, iface2, tt);
00300 }
00301 
00302 
00303 //______________________________________________________________________________
00304 void TPainter3dAlgorithms::ClearRaster()
00305 {
00306    // Clear screen
00307 
00308    Int_t nw = (fNxrast*fNyrast + 29) / 30;
00309    for (Int_t i = 0; i < nw; ++i) fRaster[i] = 0;
00310    fIfrast = 0;
00311 }
00312 
00313 
00314 //______________________________________________________________________________
00315 void TPainter3dAlgorithms::ColorFunction(Int_t nl, Double_t *fl, Int_t *icl, Int_t &irep)
00316 {
00317    // Set correspondance between function and color levels
00318    //
00319    //    Input: NL        - number of levels
00320    //           FL(NL)    - function levels
00321    //           ICL(NL+1) - colors for levels
00322    //
00323    //    Output: IREP     - reply: 0 O.K.
00324    //                             -1 error in parameters:
00325    //                         illegal number of levels
00326    //                         function levels must be in increasing order
00327    //                         negative color index
00328 
00329    static const char *where = "ColorFunction";
00330 
00331    /* Local variables */
00332    Int_t i;
00333 
00334    irep = 0;
00335    if (nl == 0) {fNlevel = 0;        return; }
00336 
00337    //          C H E C K   P A R A M E T E R S
00338    if (nl < 0 || nl > 256) {
00339       Error(where, "illegal number of levels (%d)", nl);
00340       irep = -1;
00341       return;
00342    }
00343    for (i = 1; i < nl; ++i) {
00344       if (fl[i] <= fl[i - 1]) {
00345    //         Error(where, "function levels must be in increasing order");
00346          irep = -1;
00347          return;
00348       }
00349    }
00350    for (i = 0; i < nl; ++i) {
00351       if (icl[i] < 0) {
00352    //         Error(where, "negative color index (%d)", icl[i]);
00353          irep = -1;
00354          return;
00355       }
00356    }
00357 
00358    //          S E T   L E V E L S
00359    fNlevel = nl;
00360    for (i = 0; i < fNlevel; ++i) fFunLevel[i]   = Hparam.factor*fl[i];
00361    for (i = 0; i < fNlevel+1; ++i) fColorLevel[i] = icl[i];
00362 }
00363 
00364 
00365 //______________________________________________________________________________
00366 void TPainter3dAlgorithms::DefineGridLevels(Int_t ndivz)
00367 {
00368    // Define the grid levels drawn in the background of surface and lego plots.
00369    // The grid levels are aligned on the  Z axis' main tick marks.
00370 
00371    Int_t i, nbins=0;
00372    Double_t binLow, binHigh, binWidth;
00373    TView *view = 0;
00374 
00375    if (gPad) view = gPad->GetView();
00376    if (!view) {
00377       Error("GridLevels", "no TView in current pad");
00378       return;
00379    }
00380 
00381    // Find the main tick marks positions.
00382    Double_t *rmin = view->GetRmin();
00383    Double_t *rmax = view->GetRmax();
00384    if (ndivz > 0) {
00385       THLimitsFinder::Optimize(rmin[2], rmax[2], ndivz,
00386                                binLow, binHigh, nbins, binWidth, " ");
00387    } else {
00388       nbins = TMath::Abs(ndivz);
00389       binLow = rmin[2];
00390       binHigh = rmax[2];
00391       binWidth = (binHigh-binLow)/nbins;
00392    }
00393 
00394    // Define the grid levels
00395    fNlevel = nbins+1;
00396    for (i = 0; i < fNlevel; ++i) fFunLevel[i] = binLow+i*binWidth;
00397 }
00398 
00399 
00400 //______________________________________________________________________________
00401 void TPainter3dAlgorithms::DrawFaceMode1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
00402 {
00403    // Draw face - 1st variant
00404    //
00405    //    Function: Draw face - 1st variant
00406    //              (2 colors: 1st for external surface, 2nd for internal)
00407    //
00408    //    References: WCtoNDC
00409    //
00410    //    Input: ICODES(*) - set of codes for the line (not used)
00411    //             ICODES(1) - IX
00412    //             ICODES(2) - IY
00413    //           XYZ(3,*)  - coordinates of nodes
00414    //           NP        - number of nodes
00415    //           IFACE(NP) - face
00416    //           T(NP)     - additional function defined on this face
00417    //                       (not used in this routine)
00418 
00419    /* Local variables */
00420    Int_t i, k,ifneg,i1, i2;
00421    Double_t x[13], y[13];
00422    Double_t z;
00423    Double_t p3[24]        /* was [2][12] */;
00424    TView *view = 0;
00425 
00426    if (gPad) view = gPad->GetView();
00427    if (!view) return;
00428 
00429    //          T R A N S F E R   T O   N O R M A L I S E D   COORDINATES
00430    /* Parameter adjustments */
00431    --t;
00432    --iface;
00433    xyz -= 4;
00434    --icodes;
00435 
00436    ifneg = 0;
00437    for (i = 1; i <= np; ++i) {
00438       k = iface[i];
00439       if (k < 0) ifneg = 1;
00440       if (k < 0) k = -k;
00441       view->WCtoNDC(&xyz[k*3 + 1], &p3[2*i - 2]);
00442       x[i - 1] = p3[2*i - 2];
00443       y[i - 1] = p3[2*i - 1];
00444    }
00445 
00446    //          F I N D   N O R M A L
00447    z = 0;
00448    for (i = 1; i <= np; ++i) {
00449       i1 = i;
00450       i2 = i1 + 1;
00451       if (i2 > np) i2 = 1;
00452       z = z + p3[2*i1 - 1]*p3[2*i2 - 2] - p3[2*i1 - 2] *
00453               p3[2*i2 - 1];
00454    }
00455 
00456    //          D R A W   F A C E
00457    if (z > 0)         SetFillColor(kF3FillColor1);
00458    if (z <= 0) SetFillColor(kF3FillColor2);
00459    SetFillStyle(1001);
00460    TAttFill::Modify();
00461    gPad->PaintFillArea(np, x, y);
00462 
00463    //          D R A W   B O R D E R
00464    if (ifneg == 0) {
00465       SetFillStyle(0);
00466       SetFillColor(kF3LineColor);
00467       TAttFill::Modify();
00468       gPad->PaintFillArea(np, x, y);
00469    } else {
00470       x[np] = x[0];
00471       y[np] = y[0];
00472       SetLineColor(kF3LineColor);
00473       TAttLine::Modify();
00474       for (i = 1; i <= np; ++i) {
00475          if (iface[i] > 0) gPad->PaintPolyLine(2, &x[i-1], &y[i-1]);
00476       }
00477    }
00478 }
00479 
00480 
00481 //______________________________________________________________________________
00482 void TPainter3dAlgorithms::DrawFaceMode2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
00483 {
00484    // Draw face - 2nd option
00485    //
00486    //    Function: Draw face - 2nd option
00487    //              (fill in correspondance with function levels)
00488    //
00489    //    References: WCtoNDC, FillPolygon
00490    //
00491    //    Input: ICODES(*) - set of codes for the line (not used)
00492    //             ICODES(1) - IX
00493    //             ICODES(2) - IY
00494    //           XYZ(3,*)  - coordinates of nodes
00495    //           NP        - number of nodes
00496    //           IFACE(NP) - face
00497    //           T(NP)     - additional function defined on this face
00498 
00499    /* Local variables */
00500    Int_t i, k;
00501    Double_t x[12], y[12];
00502    Double_t p3[36]        /* was [3][12] */;
00503    TView *view = 0;
00504 
00505    if (gPad) view = gPad->GetView();
00506    if (!view) return;
00507 
00508    //          T R A N S F E R   T O   N O R M A L I S E D   COORDINATES
00509    /* Parameter adjustments */
00510    --t;
00511    --iface;
00512    xyz -= 4;
00513    --icodes;
00514 
00515    for (i = 1; i <= np; ++i) {
00516       k = iface[i];
00517       view->WCtoNDC(&xyz[k*3 + 1], &p3[i*3 - 3]);
00518       x[i - 1] = p3[i*3 - 3];
00519       y[i - 1] = p3[i*3 - 2];
00520    }
00521 
00522    //          D R A W   F A C E   &   B O R D E R
00523    FillPolygon(np, p3, &t[1]);
00524    if (fMesh == 1) {
00525       SetFillColor(1);
00526       SetFillStyle(0);
00527       TAttFill::Modify();
00528       gPad->PaintFillArea(np, x, y);
00529    }
00530 }
00531 
00532 
00533 //______________________________________________________________________________
00534 void TPainter3dAlgorithms::DrawFaceMode3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
00535 {
00536    // Draw face - 3rd option
00537    //
00538    //    Function: Draw face - 3rd option
00539    //              (draw face for stacked lego plot)
00540    //
00541    //    References: WCtoNDC
00542    //
00543    //    Input: ICODES(*) - set of codes for the line
00544    //             ICODES(1) - IX coordinate of the line cell
00545    //             ICODES(2) - IY coordinate of the line cell
00546    //             ICODES(3) - lego number
00547    //             ICODES(4) - side: 1-face,2-right,3-back,4-left,
00548    //                               5-bottom, 6-top
00549    //             XYZ(3,*)  - coordinates of nodes
00550    //             NP        - number of nodes
00551    //             IFACE(NP) - face
00552    //             T(*)      - additional function (not used here)
00553 
00554    Int_t i, k;
00555    Int_t icol = 0;
00556    Double_t x[4], y[4], p3[12]        /* was [3][4] */;
00557    TView *view = 0;
00558 
00559    if (gPad) view = gPad->GetView();
00560    if (!view) return;
00561 
00562    /* Parameter adjustments */
00563    --t;
00564    --iface;
00565    xyz -= 4;
00566    --icodes;
00567 
00568    if (icodes[4] == 6) icol = fColorTop;
00569    if (icodes[4] == 5) icol = fColorBottom;
00570    if (icodes[4] == 1) icol = fColorMain[icodes[3] - 1];
00571    if (icodes[4] == 2) icol = fColorDark[icodes[3] - 1];
00572    if (icodes[4] == 3) icol = fColorMain[icodes[3] - 1];
00573    if (icodes[4] == 4) icol = fColorDark[icodes[3] - 1];
00574 
00575    for (i = 1; i <= np; ++i) {
00576       k = iface[i];
00577       view->WCtoNDC(&xyz[k*3 + 1], &p3[i*3 - 3]);
00578       x[i - 1] = p3[i*3 - 3];
00579       y[i - 1] = p3[i*3 - 2];
00580    }
00581 
00582    SetFillStyle(1001);
00583    SetFillColor(icol);
00584    TAttFill::Modify();
00585    gPad->PaintFillArea(np, x, y);
00586    if (fMesh) {
00587       SetFillStyle(0);
00588       SetFillColor(1);
00589       TAttFill::Modify();
00590       gPad->PaintFillArea(np, x, y);
00591    }
00592 }
00593 
00594 
00595 //______________________________________________________________________________
00596 void TPainter3dAlgorithms::DrawFaceMove1(Int_t *icodes, Double_t *xyz, Int_t np,
00597                                          Int_t *iface, Double_t *tt)
00598 {
00599    // Draw face - 1st variant for "MOVING SCREEN" algorithm
00600    //
00601    //    Function: Draw face - 1st variant for "MOVING SCREEN" algorithm
00602    //              (draw face with level lines)
00603    //
00604    //    References: FindLevelLines, WCtoNDC,
00605    //                FindVisibleDraw, ModifyScreen
00606    //
00607    //    Input: ICODES(*) - set of codes for the line (not used)
00608    //             ICODES(1) - IX
00609    //             ICODES(2) - IY
00610    //           XYZ(3,*)  - coordinates of nodes
00611    //           NP        - number of nodes
00612    //           IFACE(NP) - face
00613    //           TT(NP)    - additional function defined on this face
00614    //                       (not used in this routine)
00615 
00616    Double_t xdel, ydel;
00617    Int_t i, k, i1, i2, il, it;
00618    Double_t x[2], y[2];
00619    Double_t p1[3], p2[3], p3[36]        /* was [3][12] */;
00620    TView *view = 0;
00621 
00622    if (gPad) view = gPad->GetView();
00623    if (!view) return;
00624 
00625    //          C O P Y   P O I N T S   T O   A R R A Y
00626    /* Parameter adjustments */
00627    --tt;
00628    --iface;
00629    xyz -= 4;
00630    --icodes;
00631 
00632    for (i = 1; i <= np; ++i) {
00633       k = iface[i];
00634       p3[i*3 - 3] = xyz[k*3 + 1];
00635       p3[i*3 - 2] = xyz[k*3 + 2];
00636       p3[i*3 - 1] = xyz[k*3 + 3];
00637    }
00638 
00639    //          F I N D   L E V E L   L I N E S
00640    FindLevelLines(np, p3, &tt[1]);
00641 
00642    //          D R A W   L E V E L   L I N E S
00643    SetLineStyle(3);
00644    TAttLine::Modify();
00645    for (il = 1; il <= fNlines; ++il) {
00646       FindVisibleDraw(&fPlines[(2*il + 1)*3 - 9], &fPlines[(2*il + 2)*3 - 9]);
00647       view->WCtoNDC(&fPlines[(2*il + 1)*3 - 9], p1);
00648       view->WCtoNDC(&fPlines[(2*il + 2)*3 - 9], p2);
00649       xdel = p2[0] - p1[0];
00650       ydel = p2[1] - p1[1];
00651       for (it = 1; it <= fNT; ++it) {
00652          x[0] = p1[0] + xdel*fT[2*it - 2];
00653          y[0] = p1[1] + ydel*fT[2*it - 2];
00654          x[1] = p1[0] + xdel*fT[2*it - 1];
00655          y[1] = p1[1] + ydel*fT[2*it - 1];
00656          gPad->PaintPolyLine(2, x, y);
00657       }
00658    }
00659 
00660    //          D R A W   F A C E
00661    SetLineStyle(1);
00662    TAttLine::Modify();
00663    for (i = 1; i <= np; ++i) {
00664       i1 = i;
00665       i2 = i + 1;
00666       if (i == np) i2 = 1;
00667       FindVisibleDraw(&p3[i1*3 - 3], &p3[i2*3 - 3]);
00668       view->WCtoNDC(&p3[i1*3 - 3], p1);
00669       view->WCtoNDC(&p3[i2*3 - 3], p2);
00670       xdel = p2[0] - p1[0];
00671       ydel = p2[1] - p1[1];
00672       for (it = 1; it <= fNT; ++it) {
00673          x[0] = p1[0] + xdel*fT[2*it - 2];
00674          y[0] = p1[1] + ydel*fT[2*it - 2];
00675          x[1] = p1[0] + xdel*fT[2*it - 1];
00676          y[1] = p1[1] + ydel*fT[2*it - 1];
00677          gPad->PaintPolyLine(2, x, y);
00678       }
00679    }
00680 
00681    //          M O D I F Y    S C R E E N
00682    for (i = 1; i <= np; ++i) {
00683       i1 = i;
00684       i2 = i + 1;
00685       if (i == np) i2 = 1;
00686       ModifyScreen(&p3[i1*3 - 3], &p3[i2*3 - 3]);
00687    }
00688 }
00689 
00690 
00691 //______________________________________________________________________________
00692 void TPainter3dAlgorithms::DrawFaceMove3(Int_t *icodes, Double_t *xyz, Int_t np,
00693                                          Int_t *iface, Double_t *tt)
00694 {
00695    // Draw face - 3rd variant for "MOVING SCREEN" algorithm
00696    //
00697    //    Function: Draw face - 1st variant for "MOVING SCREEN" algorithm
00698    //              (draw level lines only)
00699    //
00700    //    References: FindLevelLines, WCtoNDC,
00701    //                FindVisibleDraw, ModifyScreen
00702    //
00703    //    Input: ICODES(*) - set of codes for the line (not used)
00704    //             ICODES(1) - IX
00705    //             ICODES(2) - IY
00706    //           XYZ(3,*)  - coordinates of nodes
00707    //           NP        - number of nodes
00708    //           IFACE(NP) - face
00709    //           TT(NP)    - additional function defined on this face
00710    //                       (not used in this routine)
00711 
00712    Double_t xdel, ydel;
00713    Int_t i, k, i1, i2, il, it;
00714    Double_t x[2], y[2];
00715    Double_t p1[3], p2[3], p3[36]        /* was [3][12] */;
00716    TView *view = 0;
00717 
00718    if (gPad) view = gPad->GetView();
00719    if (!view) return;
00720 
00721    // Parameter adjustments (ftoc)
00722    --tt;
00723    --iface;
00724    xyz -= 4;
00725    --icodes;
00726 
00727    // Copy points to array
00728    for (i = 1; i <= np; ++i) {
00729       k = iface[i];
00730       p3[i*3 - 3] = xyz[k*3 + 1];
00731       p3[i*3 - 2] = xyz[k*3 + 2];
00732       p3[i*3 - 1] = xyz[k*3 + 3];
00733    }
00734 
00735    // Find level lines
00736    FindLevelLines(np, p3, &tt[1]);
00737 
00738    // Draw level lines
00739    TAttLine::Modify();
00740    for (il = 1; il <= fNlines; ++il) {
00741       FindVisibleDraw(&fPlines[(2*il + 1)*3 - 9], &fPlines[(2*il + 2)*3 - 9]);
00742       view->WCtoNDC(&fPlines[(2*il + 1)*3 - 9], p1);
00743       view->WCtoNDC(&fPlines[(2*il + 2)*3 - 9], p2);
00744       xdel = p2[0] - p1[0];
00745       ydel = p2[1] - p1[1];
00746       for (it = 1; it <= fNT; ++it) {
00747          x[0] = p1[0] + xdel*fT[2*it - 2];
00748          y[0] = p1[1] + ydel*fT[2*it - 2];
00749          x[1] = p1[0] + xdel*fT[2*it - 1];
00750          y[1] = p1[1] + ydel*fT[2*it - 1];
00751          gPad->PaintPolyLine(2, x, y);
00752       }
00753    }
00754 
00755    // Modify screen
00756    for (i = 1; i <= np; ++i) {
00757       i1 = i;
00758       i2 = i + 1;
00759       if (i == np) i2 = 1;
00760       ModifyScreen(&p3[i1*3 - 3], &p3[i2*3 - 3]);
00761    }
00762 }
00763 
00764 
00765 //______________________________________________________________________________
00766 void TPainter3dAlgorithms::DrawFaceMove2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
00767 {
00768    // Draw face - 2nd variant for "MOVING SCREEN" algorithm
00769    //
00770    //    Function: Draw face - 2nd variant for "MOVING SCREEN" algorithm
00771    //              (draw face for stacked lego plot)
00772    //
00773    //    References: FindLevelLines, WCtoNDC,
00774    //                FindVisibleDraw, ModifyScreen
00775    //
00776    //    Input: ICODES(*) - set of codes for the line (not used)
00777    //             ICODES(1) - IX
00778    //             ICODES(2) - IY
00779    //             ICODES(3) - line code (N of lego)
00780    //           XYZ(3,*)  - coordinates of nodes
00781    //           NP        - number of nodes
00782    //           IFACE(NP) - face
00783    //           TT(NP)    - additional function defined on this face
00784    //                       (not used in this routine)
00785 
00786    Double_t xdel, ydel;
00787    Int_t i, k, icol, i1, i2, it;
00788    Double_t x[2], y[2];
00789    Double_t p1[3], p2[3], p3[36]        /* was [3][12] */;
00790    TView *view = 0;
00791 
00792    if (gPad) view = gPad->GetView();
00793    if (!view) return;
00794 
00795    //          C O P Y   P O I N T S   T O   A R R A Y
00796    /* Parameter adjustments */
00797    --tt;
00798    --iface;
00799    xyz -= 4;
00800    --icodes;
00801 
00802    for (i = 1; i <= np; ++i) {
00803       k = iface[i];
00804       p3[i*3 - 3] = xyz[k*3 + 1];
00805       p3[i*3 - 2] = xyz[k*3 + 2];
00806       p3[i*3 - 1] = xyz[k*3 + 3];
00807    }
00808 
00809    //          D R A W   F A C E
00810    icol = icodes[3];
00811    if (icol) SetLineColor(fColorMain[icol - 1]);
00812    else      SetLineColor(1);
00813    TAttLine::Modify();
00814    for (i = 1; i <= np; ++i) {
00815       i1 = i;
00816       i2 = i + 1;
00817       if (i == np) i2 = 1;
00818       FindVisibleDraw(&p3[i1*3 - 3], &p3[i2*3 - 3]);
00819       view->WCtoNDC(&p3[i1*3 - 3], p1);
00820       view->WCtoNDC(&p3[i2*3 - 3], p2);
00821       xdel = p2[0] - p1[0];
00822       ydel = p2[1] - p1[1];
00823       for (it = 1; it <= fNT; ++it) {
00824          x[0] = p1[0] + xdel*fT[2*it - 2];
00825          y[0] = p1[1] + ydel*fT[2*it - 2];
00826          x[1] = p1[0] + xdel*fT[2*it - 1];
00827          y[1] = p1[1] + ydel*fT[2*it - 1];
00828          gPad->PaintPolyLine(2, x, y);
00829       }
00830    }
00831 
00832    //          M O D I F Y    S C R E E N
00833    for (i = 1; i <= np; ++i) {
00834       i1 = i;
00835       i2 = i + 1;
00836       if (i == np) i2 = 1;
00837       ModifyScreen(&p3[i1*3 - 3], &p3[i2*3 - 3]);
00838    }
00839 }
00840 
00841 
00842 //______________________________________________________________________________
00843 void TPainter3dAlgorithms::DrawFaceRaster1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
00844 {
00845    // Draw face - 1st variant for "RASTER SCREEN" algorithm
00846    //
00847    //    Function: Draw face - 1st variant for "RASTER SCREEN" algorithm
00848    //              (draw face with level lines)
00849    //
00850    //    References: FindLevelLines, WCtoNDC,
00851    //                FindVisibleLine, FillPolygonBorder
00852    //
00853    //    Input: ICODES(*) - set of codes for the line (not used)
00854    //             ICODES(1) - IX
00855    //             ICODES(2) - IY
00856    //           XYZ(3,*)  - coordinates of nodes
00857    //           NP        - number of nodes
00858    //           IFACE(NP) - face
00859    //           TT(NP)    - additional function defined on this face
00860    //                       (not used in this routine)
00861 
00862    Double_t xdel, ydel;
00863    Int_t i, k, i1, i2, il, it;
00864    Double_t x[2], y[2];
00865    Double_t p1[3], p2[3], p3[36]        /* was [3][12] */;
00866    Double_t pp[24]        /* was [2][12] */;
00867    TView *view = 0;
00868 
00869    if (gPad) view = gPad->GetView();
00870    if (!view) return;
00871 
00872    //          C O P Y   P O I N T S   T O   A R R A Y
00873    /* Parameter adjustments */
00874    --tt;
00875    --iface;
00876    xyz -= 4;
00877    --icodes;
00878 
00879    for (i = 1; i <= np; ++i) {
00880       k = iface[i];
00881       if (k < 0) k = -k;
00882       p3[i*3 - 3] = xyz[k*3 + 1];
00883       p3[i*3 - 2] = xyz[k*3 + 2];
00884       p3[i*3 - 1] = xyz[k*3 + 3];
00885       view->WCtoNDC(&p3[i*3 - 3], &pp[2*i - 2]);
00886    }
00887 
00888    //          F I N D   L E V E L   L I N E S
00889    FindLevelLines(np, p3, &tt[1]);
00890 
00891    //          D R A W   L E V E L   L I N E S
00892    SetLineStyle(3);
00893    TAttLine::Modify();
00894    for (il = 1; il <= fNlines; ++il) {
00895       view->WCtoNDC(&fPlines[(2*il + 1)*3 - 9], p1);
00896       view->WCtoNDC(&fPlines[(2*il + 2)*3 - 9], p2);
00897       FindVisibleLine(p1, p2, 100, fNT, fT);
00898       xdel = p2[0] - p1[0];
00899       ydel = p2[1] - p1[1];
00900       for (it = 1; it <= fNT; ++it) {
00901          x[0] = p1[0] + xdel*fT[2*it - 2];
00902          y[0] = p1[1] + ydel*fT[2*it - 2];
00903          x[1] = p1[0] + xdel*fT[2*it - 1];
00904          y[1] = p1[1] + ydel*fT[2*it - 1];
00905          gPad->PaintPolyLine(2, x, y);
00906       }
00907    }
00908 
00909    //          D R A W   F A C E
00910    SetLineStyle(1);
00911    TAttLine::Modify();
00912    for (i = 1; i <= np; ++i) {
00913       if (iface[i] < 0) continue;
00914       i1 = i;
00915       i2 = i + 1;
00916       if (i == np) i2 = 1;
00917       FindVisibleLine(&pp[2*i1 - 2], &pp[2*i2 - 2], 100, fNT, fT);
00918       xdel = pp[2*i2 - 2] - pp[2*i1 - 2];
00919       ydel = pp[2*i2 - 1] - pp[2*i1 - 1];
00920       for (it = 1; it <= fNT; ++it) {
00921          x[0] = pp[2*i1 - 2] + xdel*fT[2*it - 2];
00922          y[0] = pp[2*i1 - 1] + ydel*fT[2*it - 2];
00923          x[1] = pp[2*i1 - 2] + xdel*fT[2*it - 1];
00924          y[1] = pp[2*i1 - 1] + ydel*fT[2*it - 1];
00925          gPad->PaintPolyLine(2, x, y);
00926       }
00927    }
00928 
00929    //          M O D I F Y    S C R E E N
00930    FillPolygonBorder(np, pp);
00931 }
00932 
00933 
00934 //______________________________________________________________________________
00935 void TPainter3dAlgorithms::DrawFaceRaster2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
00936 {
00937    // Draw face - 2nd variant for "RASTER SCREEN" algorithm
00938    //
00939    //    Function: Draw face - 2nd variant for "RASTER SCREEN" algorithm
00940    //              (draw face for stacked lego plot)
00941    //
00942    //    References: WCtoNDC, FindVisibleLine, FillPolygonBorder
00943    //
00944    //    Input: ICODES(*) - set of codes for the line (not used)
00945    //             ICODES(1) - IX
00946    //             ICODES(2) - IY
00947    //             ICODES(3) - line code (N of lego)
00948    //           XYZ(3,*)  - coordinates of nodes
00949    //           NP        - number of nodes
00950    //           IFACE(NP) - face
00951    //           TT(NP)    - additional function defined on this face
00952    //                       (not used in this routine)
00953 
00954    Double_t xdel, ydel;
00955    Int_t i, k, icol, i1, i2, it;
00956    Double_t p[3], x[2], y[2];
00957    Double_t pp[24]        /* was [2][12] */;
00958    TView *view = 0;
00959 
00960    if (gPad) view = gPad->GetView();
00961    if (!view) return;
00962 
00963    //          C O P Y   P O I N T S   T O   A R R A Y
00964    /* Parameter adjustments */
00965    --tt;
00966    --iface;
00967    xyz -= 4;
00968    --icodes;
00969 
00970    for (i = 1; i <= np; ++i) {
00971       k = iface[i];
00972       if (k < 0) k = -k;
00973       view->WCtoNDC(&xyz[k*3 + 1], p);
00974       pp[2*i - 2] = p[0];
00975       pp[2*i - 1] = p[1];
00976    }
00977 
00978    //          D R A W   F A C E
00979    icol = icodes[3];
00980    if (icol) SetLineColor(fColorMain[icol - 1]);
00981    else      SetLineColor(1);
00982    TAttLine::Modify();
00983    for (i = 1; i <= np; ++i) {
00984       if (iface[i] < 0) continue;
00985       i1 = i;
00986       i2 = i + 1;
00987       if (i == np) i2 = 1;
00988       FindVisibleLine(&pp[2*i1 - 2], &pp[2*i2 - 2], 100, fNT, fT);
00989       xdel = pp[2*i2 - 2] - pp[2*i1 - 2];
00990       ydel = pp[2*i2 - 1] - pp[2*i1 - 1];
00991       for (it = 1; it <= fNT; ++it) {
00992          x[0] = pp[2*i1 - 2] + xdel*fT[2*it - 2];
00993          y[0] = pp[2*i1 - 1] + ydel*fT[2*it - 2];
00994          x[1] = pp[2*i1 - 2] + xdel*fT[2*it - 1];
00995          y[1] = pp[2*i1 - 1] + ydel*fT[2*it - 1];
00996          gPad->PaintPolyLine(2, x, y);
00997       }
00998    }
00999 
01000    //          M O D I F Y    R A S T E R   S C R E E N
01001    FillPolygonBorder(np, pp);
01002 }
01003 
01004 
01005 //______________________________________________________________________________
01006 void TPainter3dAlgorithms::FillPolygon(Int_t n, Double_t *p, Double_t *f)
01007 {
01008    // Fill polygon with function values at vertexes
01009    //
01010    //    Input: N      - number of vertexes
01011    //           P(3,*) - polygon
01012    //           F(*)   - function values at nodes
01013    //
01014    //    Errors: - illegal number of vertexes in polygon
01015    //            - illegal call of FillPolygon: no levels
01016 
01017    Int_t ilev, i, k, icol, i1, i2, nl, np;
01018    Double_t fmin, fmax;
01019    Double_t x[12], y[12], f1, f2;
01020    Double_t p3[36]        /* was [3][12] */;
01021    Double_t funmin, funmax;
01022 
01023    /* Parameter adjustments */
01024    --f;
01025    p -= 4;
01026 
01027    if (n < 3) {
01028       Error("FillPolygon", "illegal number of vertices in polygon (%d)", n);
01029       return;
01030    }
01031 
01032    if (fNlevel == 0) {
01033       // Illegal call of FillPolygon: no levels
01034       return;
01035    }
01036    np = n;
01037    nl = fNlevel;
01038    if (nl < 0) nl = -nl;
01039    fmin = f[1];
01040    fmax = f[1];
01041    for (i = 2; i <= np; ++i) {
01042       if (fmin > f[i]) fmin = f[i];
01043       if (fmax < f[i]) fmax = f[i];
01044    }
01045    funmin = fFunLevel[0] - 1;
01046    if (fmin < funmin) funmin = fmin - 1;
01047    funmax = fFunLevel[nl - 1] + 1;
01048    if (fmax > funmax) funmax = fmax + 1;
01049 
01050    //          F I N D   A N D   D R A W   S U B P O L Y G O N S
01051    f2 = funmin;
01052    for (ilev = 1; ilev <= nl+1; ++ilev) {
01053    //         S E T   L E V E L   L I M I T S
01054       f1 = f2;
01055       if (ilev == nl + 1) f2 = funmax;
01056       else                f2 = fFunLevel[ilev - 1];
01057       if (fmax < f1)  return;
01058       if (fmin > f2)  continue;
01059    //         F I N D   S U B P O L Y G O N
01060       k = 0;
01061       for (i = 1; i <= np; ++i) {
01062          i1 = i;
01063          i2 = i + 1;
01064          if (i == np) i2 = 1;
01065          FindPartEdge(&p[i1*3 + 1], &p[i2*3 + 1], f[i1], f[i2], f1, f2, k, p3);
01066       }
01067    //         D R A W   S U B P O L Y G O N
01068       if (k < 3) continue;
01069       for (i = 1; i <= k; ++i) {
01070          x[i - 1] = p3[i*3 - 3];
01071          y[i - 1] = p3[i*3 - 2];
01072       }
01073       if (ilev==1) {
01074          icol=gPad->GetFillColor();
01075       } else {
01076          icol = fColorLevel[ilev - 2];
01077       }
01078       SetFillColor(icol);
01079       SetFillStyle(1001);
01080       TAttFill::Modify();
01081       gPad->PaintFillArea(k, x, y);
01082    }
01083 }
01084 
01085 
01086 //______________________________________________________________________________
01087 void TPainter3dAlgorithms::FillPolygonBorder(Int_t nn, Double_t *xy)
01088 {
01089    // Fill a polygon including border ("RASTER SCREEN")
01090    //
01091    //    Input: NN      - number of polygon nodes
01092    //           XY(2,*) - polygon nodes
01093 
01094    Int_t kbit, nbit, step, ymin, ymax, test[kLmax], xcur[kLmax], xnex[kLmax],
01095       i, j, k, n, ibase, t, x, y, xscan[24]        /* was [2][kLmax] */,
01096       yscan, x1[kLmax+2], y1[kLmax+2], x2[kLmax+2], y2[kLmax+2],
01097       ib, nb, dx, dy, iw, nx, xx, yy, signdx, nstart, xx1, xx2, nxa, nxb;
01098 
01099    //          T R A N S F E R   T O   S C R E E N   C O O R D I N A T E S
01100    /* Parameter adjustments */
01101    xy -= 3;
01102 
01103    if (fIfrast) return;
01104 
01105    n = nn;
01106    x1[0] = 0;
01107    y1[0] = 0;
01108    for (i = 1; i <= n; ++i) {
01109       x1[i - 1] = Int_t(fNxrast*((xy[2*i + 1] - fXrast) /fDXrast) - 0.01);
01110       y1[i - 1] = Int_t(fNyrast*((xy[2*i + 2] - fYrast) /fDYrast) - 0.01);
01111    }
01112    x1[n] = x1[0];
01113    y1[n] = y1[0];
01114 
01115    //          F I N D   Y - M I N   A N D   Y - M A X
01116    //          S E T   R I G H T   E D G E   O R I E N T A T I O N
01117    ymin = y1[0];
01118    ymax = y1[0];
01119    for (i = 1; i <= n; ++i) {
01120       if (ymin > y1[i - 1])   ymin = y1[i - 1];
01121       if (ymax < y1[i - 1])   ymax = y1[i - 1];
01122       if (y1[i - 1] <= y1[i]) {x2[i - 1] = x1[i]; y2[i - 1] = y1[i];}
01123       else {
01124          x2[i - 1] = x1[i - 1];
01125          y2[i - 1] = y1[i - 1];
01126          x1[i - 1] = x1[i];
01127          y1[i - 1] = y1[i];
01128       }
01129    }
01130    if (ymin >= fNyrast) return;
01131    if (ymax < 0)        return;
01132    if (ymax >= fNyrast) ymax = fNyrast - 1;
01133 
01134    //          S O R T   L I N E S
01135    for (i = 1; i < n; ++i) {
01136       if (y1[i] >= y1[i - 1]) continue;
01137       y = y1[i];
01138       k = 1;
01139       for (j = i - 1; j >= 1; --j) {
01140          if (y < y1[j - 1]) continue;
01141          k = j + 1;
01142          break;
01143       }
01144       x = x1[i];
01145       xx = x2[i];
01146       yy = y2[i];
01147       for (j = i; j >= k; --j) {
01148          x1[j] = x1[j - 1];
01149          y1[j] = y1[j - 1];
01150          x2[j] = x2[j - 1];
01151          y2[j] = y2[j - 1];
01152       }
01153       x1[k - 1] = x;
01154       y1[k - 1] = y;
01155       x2[k - 1] = xx;
01156       y2[k - 1] = yy;
01157    }
01158 
01159    //          S E T   I N I T I A L   V A L U E S
01160    for (i = 1; i <= n; ++i) {
01161       xcur[i - 1] = x1[i - 1];
01162       dy = y2[i - 1] - y1[i - 1];
01163       dx = x2[i - 1] - x1[i - 1];
01164       signdx = 1;
01165       if (dx < 0)   signdx = -1;
01166       if (dx < 0)   dx = -dx;
01167       if (dx <= dy) {
01168          t = -(dy + 1) / 2 + dx;
01169          if (t < 0) {
01170             test[i - 1] = t;
01171             xnex[i - 1] = xcur[i - 1];
01172          } else {
01173             test[i - 1] = t - dy;
01174             xnex[i - 1] = xcur[i - 1] + signdx;
01175          }
01176       } else if (dy != 0) {
01177          step = (dx - 1) / (dy + dy) + 1;
01178          test[i - 1] = step*dy - (dx + 1) / 2 - dx;
01179          xnex[i - 1] = xcur[i - 1] + signdx*step;
01180       }
01181    }
01182 
01183    //          L O O P   O N   S C A N   L I N E S
01184    nstart = 1;
01185    for (yscan = ymin; yscan <= ymax; ++yscan) {
01186       nx  = 0;
01187       nxa = 0;
01188       nxb = kLmax + 1;
01189       for (i = nstart; i <= n; ++i) {
01190          if (y1[i - 1] > yscan) goto L500;
01191          if (y2[i - 1] <= yscan) {
01192             if (i == nstart)       ++nstart;
01193             if (y2[i - 1] != yscan)continue;
01194             --nxb;
01195             if (x2[i - 1] >= xcur[i - 1]) {
01196                xscan[2*nxb - 2] = xcur[i - 1];
01197                xscan[2*nxb - 1] = x2[i - 1];
01198             } else {
01199                xscan[2*nxb - 2] = x2[i - 1];
01200                xscan[2*nxb - 1] = xcur[i - 1];
01201             }
01202             continue;
01203          }
01204 
01205    //          S T O R E   C U R R E N T  X
01206    //          P R E P A R E   X   F O R   N E X T   S C A N - L I N E
01207          ++nxa;
01208          dy = y2[i - 1] - y1[i - 1];
01209          dx = x2[i - 1] - x1[i - 1];
01210          if (dx >= 0) {
01211             signdx = 1;
01212             xscan[2*nxa - 2] = xcur[i - 1];
01213             xscan[2*nxa - 1] = xnex[i - 1];
01214             if (xscan[2*nxa - 2] != xscan[2*nxa - 1]) {
01215                --xscan[2*nxa - 1];
01216             }
01217          } else {
01218             dx = -dx;
01219             signdx = -1;
01220             xscan[2*nxa - 2] = xnex[i - 1];
01221             xscan[2*nxa - 1] = xcur[i - 1];
01222             if (xscan[2*nxa - 2] != xscan[2*nxa - 1]) {
01223                ++xscan[2*nxa - 2];
01224             }
01225          }
01226          xcur[i - 1] = xnex[i - 1];
01227          if (dx <= dy) {
01228             test[i - 1] += dx;
01229             if (test[i - 1] < 0) continue;
01230             test[i - 1] -= dy;
01231             xnex[i - 1] += signdx;
01232             continue;
01233          }
01234          step = dx / dy;
01235          t = test[i - 1] + step*dy;
01236          if (t >= 0) {
01237             test[i - 1] = t - dx;
01238             xnex[i - 1] += signdx*step;
01239          } else {
01240             test[i - 1] = t + dy - dx;
01241             xnex[i - 1] += signdx*(step + 1);
01242          }
01243       }
01244 
01245    //          S O R T   P O I N T S   A L O N G   X
01246 L500:
01247       if (yscan < 0) continue;
01248       ibase = yscan*fNxrast;
01249       if (nxa >= 2) {
01250          for (i = 1; i < nxa; ++i) {
01251             for (j = i; j >= 1; --j) {
01252                if (xscan[2*j] >= xscan[2*j - 2]) continue;
01253                x = xscan[2*j];
01254                xscan[2*j] = xscan[2*j - 2];
01255                xscan[2*j - 2] = x;
01256                x = xscan[2*j - 1];
01257                xscan[2*j + 1] = xscan[2*j - 1];
01258                xscan[2*j - 1] = x;
01259             }
01260          }
01261          for (i = 1; i <= nxa; i += 2) {
01262             ++nx;
01263             xscan[2*nx - 2] = xscan[2*i - 2];
01264             x = xscan[2*i + 1];
01265             if (xscan[2*i - 1] > x) x = xscan[2*i - 1];
01266             xscan[2*nx - 1] = x;
01267          }
01268       }
01269       if (nxb <= kLmax) {
01270          for (i = nxb; i <= kLmax; ++i) {
01271             ++nx;
01272             xscan[2*nx - 2] = xscan[2*i - 2];
01273             xscan[2*nx - 1] = xscan[2*i - 1];
01274          }
01275       }
01276    //          C O N C A T E N A T E   A N D   F I L L
01277       while (nx) {
01278          xx1 = xscan[2*nx - 2];
01279          xx2 = xscan[2*nx - 1];
01280          --nx;
01281          k = 1;
01282          while (k <= nx) {
01283             if ((xscan[2*k - 2] <= xx2 + 1) && (xscan[2*k - 1] >= xx1 - 1)) {
01284                if (xscan[2*k - 2] < xx1)     xx1 = xscan[2*k - 2];
01285                if (xscan[2*k - 1] > xx2)     xx2 = xscan[2*k - 1];
01286                xscan[2*k - 2] = xscan[2*nx - 2];
01287                xscan[2*k - 1] = xscan[2*nx - 1];
01288                --nx;
01289             } else  ++k;
01290          }
01291          if (xx1 < 0)        xx1 = 0;
01292          if (xx2 >= fNxrast) xx2 = fNxrast - 1;
01293          nbit = xx2 - xx1 + 1;
01294          kbit = ibase + xx1;
01295          iw = kbit / 30;
01296          ib = kbit - iw*30 + 1;
01297          iw = iw + 1;
01298          nb = 30 - ib + 1;
01299          if (nb > nbit) nb = nbit;
01300          fRaster[iw - 1] = fRaster[iw - 1] | fMask[fJmask[nb - 1] + ib - 1];
01301          nbit -= nb;
01302          if (nbit) {
01303             while(nbit > 30) {
01304                fRaster[iw] = fMask[464];
01305                ++iw;
01306                nbit += -30;
01307             }
01308             fRaster[iw] = fRaster[iw] | fMask[fJmask[nbit - 1]];
01309             ++iw;
01310          }
01311       }
01312    }
01313 }
01314 
01315 
01316 //______________________________________________________________________________
01317 void TPainter3dAlgorithms::FindLevelLines(Int_t np, Double_t *f, Double_t *t)
01318 {
01319    // Find level lines for face
01320    //
01321    //    Input: NP      - number of nodes
01322    //           F(3,NP) - face
01323    //           T(NP)   - additional function
01324    //
01325    //    Error: number of points for line not equal 2
01326 
01327    Int_t i, k, i1, i2, il, nl;
01328    Double_t tmin, tmax, d1, d2;
01329 
01330    /* Parameter adjustments */
01331    --t;
01332    f -= 4;
01333 
01334    /* Function Body */
01335    fNlines = 0;
01336    if (fNlevel == 0) return;
01337    nl = fNlevel;
01338    if (nl < 0) nl = -nl;
01339 
01340    //         F I N D   Tmin   A N D   Tmax
01341    tmin = t[1];
01342    tmax = t[1];
01343    for (i = 2; i <= np; ++i) {
01344       if (t[i] < tmin) tmin = t[i];
01345       if (t[i] > tmax) tmax = t[i];
01346    }
01347    if (tmin >= fFunLevel[nl - 1]) return;
01348    if (tmax <= fFunLevel[0])      return;
01349 
01350    //          F I N D   L E V E L S   L I N E S
01351    for (il = 1; il <= nl; ++il) {
01352       if (tmin >= fFunLevel[il - 1]) continue;
01353       if (tmax <= fFunLevel[il - 1]) return;
01354       if (fNlines >= 200)            return;
01355       ++fNlines;
01356       fLevelLine[fNlines - 1] = il;
01357       k = 0;
01358       for (i = 1; i <= np; ++i) {
01359          i1 = i;
01360          i2 = i + 1;
01361          if (i == np) i2 = 1;
01362          d1 = t[i1] - fFunLevel[il - 1];
01363          d2 = t[i2] - fFunLevel[il - 1];
01364          if (d1) {
01365             if (d1*d2 < 0) goto L320;
01366             continue;
01367          }
01368          ++k;
01369          fPlines[(k + 2*fNlines)*3 - 9] = f[i1*3 + 1];
01370          fPlines[(k + 2*fNlines)*3 - 8] = f[i1*3 + 2];
01371          fPlines[(k + 2*fNlines)*3 - 7] = f[i1*3 + 3];
01372          if (k == 1) continue;
01373          goto L340;
01374 L320:
01375          ++k;
01376          d1 /= t[i2] - t[i1];
01377          d2 /= t[i2] - t[i1];
01378          fPlines[(k + 2*fNlines)*3 - 9] = d2*f[i1*3 + 1] - d1*f[i2*3 + 1];
01379          fPlines[(k + 2*fNlines)*3 - 8] = d2*f[i1*3 + 2] - d1*f[i2*3 + 2];
01380          fPlines[(k + 2*fNlines)*3 - 7] = d2*f[i1*3 + 3] - d1*f[i2*3 + 3];
01381          if (k != 1) goto L340;
01382       }
01383       if (k != 2) {
01384          Error("FindLevelLines", "number of points for line not equal 2");
01385          --fNlines;
01386       }
01387 L340:
01388       if (il < 0) return;
01389    }
01390 }
01391 
01392 
01393 //______________________________________________________________________________
01394 void TPainter3dAlgorithms::FindPartEdge(Double_t *p1, Double_t *p2, Double_t f1,
01395                                         Double_t f2, Double_t fmin,
01396                                         Double_t fmax, Int_t &kpp, Double_t *pp)
01397 {
01398    // Find part of edge
01399    //
01400    //    Function: Find part of edge where function defined on this edge
01401    //              has value from FMIN to FMAX
01402    //
01403    //    Input: P1(3) - 1st point
01404    //           P2(3) - 2nd point
01405    //           F1    - function value at 1st point
01406    //           F2    - function value at 2nd point
01407    //           FMIN  - min value of layer
01408    //           FMAX  - max value of layer
01409    //
01410    //    Output: KPP - current number of point
01411    //            PP(3,*) - coordinates of new face
01412 
01413    Double_t d1, d2;
01414    Int_t k1, k2, kk;
01415 
01416    /* Parameter adjustments */
01417    pp -= 4;
01418    --p2;
01419    --p1;
01420 
01421    k1 = 0;
01422    if (f1 < fmin)  k1 = -2;
01423    if (f1 == fmin) k1 = -1;
01424    if (f1 == fmax) k1 = 1;
01425    if (f1 > fmax)  k1 = 2;
01426    k2 = 0;
01427    if (f2 < fmin)  k2 = -2;
01428    if (f2 == fmin) k2 = -1;
01429    if (f2 == fmax) k2 = 1;
01430    if (f2 > fmax)  k2 = 2;
01431    kk = (k1 + 2)*5 + (k2 + 2) + 1;
01432 
01433    //    K2:    -2  -1   0  +1  +2
01434    //    K1:    -2 -1 0 +1 +2
01435    switch ((int)kk) {
01436       case 1:  return;
01437       case 2:  return;
01438       case 3:  goto L200;
01439       case 4:  goto L200;
01440       case 5:  goto L600;
01441       case 6:  goto L100;
01442       case 7:  goto L100;
01443       case 8:  goto L100;
01444       case 9:  goto L100;
01445       case 10:  goto L500;
01446       case 11:  goto L400;
01447       case 12:  goto L100;
01448       case 13:  goto L100;
01449       case 14:  goto L100;
01450       case 15:  goto L500;
01451       case 16:  goto L400;
01452       case 17:  goto L100;
01453       case 18:  goto L100;
01454       case 19:  goto L100;
01455       case 20:  goto L100;
01456       case 21:  goto L700;
01457       case 22:  goto L300;
01458       case 23:  goto L300;
01459       case 24:  return;
01460       case 25:  return;
01461    }
01462 
01463    //          1 - S T   P O I N T
01464 L100:
01465    ++kpp;
01466    pp[kpp*3 + 1] = p1[1];
01467    pp[kpp*3 + 2] = p1[2];
01468    pp[kpp*3 + 3] = p1[3];
01469    return;
01470 
01471    //           I N T E R S E C T I O N   W I T H   Fmin
01472 L200:
01473    ++kpp;
01474    d1 = (fmin - f1) / (f1 - f2);
01475    d2 = (fmin - f2) / (f1 - f2);
01476    pp[kpp*3 + 1] = d2*p1[1] - d1*p2[1];
01477    pp[kpp*3 + 2] = d2*p1[2] - d1*p2[2];
01478    pp[kpp*3 + 3] = d2*p1[3] - d1*p2[3];
01479    return;
01480 
01481    //           I N T E R S E C T I O N   W I T H   Fmax
01482 L300:
01483    ++kpp;
01484    d1 = (fmax - f1) / (f1 - f2);
01485    d2 = (fmax - f2) / (f1 - f2);
01486    pp[kpp*3 + 1] = d2*p1[1] - d1*p2[1];
01487    pp[kpp*3 + 2] = d2*p1[2] - d1*p2[2];
01488    pp[kpp*3 + 3] = d2*p1[3] - d1*p2[3];
01489    return;
01490 
01491    //          1 - S T   P O I N T,   I N T E R S E C T I O N  WITH  Fmin
01492 L400:
01493    ++kpp;
01494    pp[kpp*3 + 1] = p1[1];
01495    pp[kpp*3 + 2] = p1[2];
01496    pp[kpp*3 + 3] = p1[3];
01497    ++kpp;
01498    d1 = (fmin - f1) / (f1 - f2);
01499    d2 = (fmin - f2) / (f1 - f2);
01500    pp[kpp*3 + 1] = d2*p1[1] - d1*p2[1];
01501    pp[kpp*3 + 2] = d2*p1[2] - d1*p2[2];
01502    pp[kpp*3 + 3] = d2*p1[3] - d1*p2[3];
01503    return;
01504 
01505    //          1 - S T   P O I N T,   I N T E R S E C T I O N  WITH  Fmax
01506 L500:
01507    ++kpp;
01508    pp[kpp*3 + 1] = p1[1];
01509    pp[kpp*3 + 2] = p1[2];
01510    pp[kpp*3 + 3] = p1[3];
01511    ++kpp;
01512    d1 = (fmax - f1) / (f1 - f2);
01513    d2 = (fmax - f2) / (f1 - f2);
01514    pp[kpp*3 + 1] = d2*p1[1] - d1*p2[1];
01515    pp[kpp*3 + 2] = d2*p1[2] - d1*p2[2];
01516    pp[kpp*3 + 3] = d2*p1[3] - d1*p2[3];
01517    return;
01518 
01519    //           I N T E R S E C T I O N   W I T H   Fmin, Fmax
01520 L600:
01521    ++kpp;
01522    d1 = (fmin - f1) / (f1 - f2);
01523    d2 = (fmin - f2) / (f1 - f2);
01524    pp[kpp*3 + 1] = d2*p1[1] - d1*p2[1];
01525    pp[kpp*3 + 2] = d2*p1[2] - d1*p2[2];
01526    pp[kpp*3 + 3] = d2*p1[3] - d1*p2[3];
01527    ++kpp;
01528    d1 = (fmax - f1) / (f1 - f2);
01529    d2 = (fmax - f2) / (f1 - f2);
01530    pp[kpp*3 + 1] = d2*p1[1] - d1*p2[1];
01531    pp[kpp*3 + 2] = d2*p1[2] - d1*p2[2];
01532    pp[kpp*3 + 3] = d2*p1[3] - d1*p2[3];
01533    return;
01534 
01535    //          I N T E R S E C T I O N   W I T H   Fmax, Fmin
01536 L700:
01537    ++kpp;
01538    d1 = (fmax - f1) / (f1 - f2);
01539    d2 = (fmax - f2) / (f1 - f2);
01540    pp[kpp*3 + 1] = d2*p1[1] - d1*p2[1];
01541    pp[kpp*3 + 2] = d2*p1[2] - d1*p2[2];
01542    pp[kpp*3 + 3] = d2*p1[3] - d1*p2[3];
01543    ++kpp;
01544    d1 = (fmin - f1) / (f1 - f2);
01545    d2 = (fmin - f2) / (f1 - f2);
01546    pp[kpp*3 + 1] = d2*p1[1] - d1*p2[1];
01547    pp[kpp*3 + 2] = d2*p1[2] - d1*p2[2];
01548    pp[kpp*3 + 3] = d2*p1[3] - d1*p2[3];
01549 }
01550 
01551 
01552 //______________________________________________________________________________
01553 void TPainter3dAlgorithms::FindVisibleDraw(Double_t *r1, Double_t *r2)
01554 {
01555    // Find visible parts of line (draw line)
01556    //
01557    //    Input: R1(3)  - 1-st point of the line
01558    //           R2(3)  - 2-nd point of the line
01559 
01560    Double_t yy1u, yy2u;
01561    Int_t i, icase, i1, i2, icase1, icase2, iv, ifback;
01562    Double_t x1, x2, y1, y2, z1, z2, dd, di;
01563    Double_t dt, dy;
01564    Double_t tt, uu, ww, yy, yy1, yy2, yy1d, yy2d;
01565    Double_t *tn = 0;
01566    const Double_t kEpsil = 1.e-6;
01567    /* Parameter adjustments */
01568    --r2;
01569    --r1;
01570    TView *view = 0;
01571 
01572    if (gPad) view = gPad->GetView();
01573    if (view) {
01574       tn = view->GetTN();
01575       x1 = tn[0]*r1[1] + tn[1]*r1[2] + tn[2]*r1[3]  + tn[3];
01576       x2 = tn[0]*r2[1] + tn[1]*r2[2] + tn[2]*r2[3]  + tn[3];
01577       y1 = tn[4]*r1[1] + tn[5]*r1[2] + tn[6]*r1[3]  + tn[7];
01578       y2 = tn[4]*r2[1] + tn[5]*r2[2] + tn[6]*r2[3]  + tn[7];
01579       z1 = tn[8]*r1[1] + tn[9]*r1[2] + tn[10]*r1[3] + tn[11];
01580       z2 = tn[8]*r2[1] + tn[9]*r2[2] + tn[10]*r2[3] + tn[11];
01581    } else {
01582       Error("FindVisibleDraw", "no TView in current pad");
01583       return;
01584    }
01585 
01586    ifback = 0;
01587    if (x1 >= x2) {
01588       ifback = 1;
01589       ww = x1;
01590       x1 = x2;
01591       x2 = ww;
01592       ww = y1;
01593       y1 = y2;
01594       y2 = ww;
01595       ww = z1;
01596       z1 = z2;
01597       z2 = ww;
01598    }
01599    fNT = 0;
01600    i1 = Int_t((x1 - fX0) / fDX) + 15;
01601    i2 = Int_t((x2 - fX0) / fDX) + 15;
01602    x1 = fX0 + (i1 - 1)*fDX;
01603    x2 = fX0 + (i2 - 1)*fDX;
01604    if (i1 != i2) {
01605 
01606    //          F I N D   V I S I B L E   P A R T S   O F   T H E   L I N E
01607       di = (Double_t) (i2 - i1);
01608       dy = (y2 - y1) / di;
01609       dt = 1 / di;
01610       iv = -1;
01611       for (i = i1; i <= i2 - 1; ++i) {
01612          yy1 = y1 + dy*(i - i1);
01613          yy2 = yy1 + dy;
01614          yy1u = yy1 - fU[2*i - 2];
01615          yy1d = yy1 - fD[2*i - 2];
01616          yy2u = yy2 - fU[2*i - 1];
01617          yy2d = yy2 - fD[2*i - 1];
01618          tt = dt*(i - i1);
01619    //         A N A L I Z E   L E F T   S I D E
01620          icase1 = 1;
01621          if (yy1u >  kEpsil) icase1 = 0;
01622          if (yy1d < -kEpsil) icase1 = 2;
01623          if ((icase1 == 0 || icase1 == 2) && iv <= 0) {
01624             iv = 1;
01625             ++fNT;
01626             fT[2*fNT - 2] = tt;
01627          }
01628          if (icase1 == 1 && iv >= 0) {
01629             iv = -1;
01630             fT[2*fNT - 1] = tt;
01631          }
01632    //         A N A L I Z E   R I G H T   S I D E
01633          icase2 = 1;
01634          if (yy2u >  kEpsil) icase2 = 0;
01635          if (yy2d < -kEpsil) icase2 = 2;
01636          icase = icase1*3 + icase2;
01637          if (icase == 1) {
01638             iv = -1;
01639             fT[2*fNT - 1] = tt + dt*(yy1u / (yy1u - yy2u));
01640          }
01641          if (icase == 2) {
01642             fT[2*fNT - 1] = tt + dt*(yy1u / (yy1u - yy2u));
01643             ++fNT;
01644             fT[2*fNT - 2] = tt + dt*(yy1d / (yy1d - yy2d));
01645          }
01646          if (icase == 3) {
01647             iv = 1;
01648             ++fNT;
01649             fT[2*fNT - 2] = tt + dt*(yy1u / (yy1u - yy2u));
01650          }
01651          if (icase == 5) {
01652             iv = 1;
01653             ++fNT;
01654             fT[2*fNT - 2] = tt + dt*(yy1d / (yy1d - yy2d));
01655          }
01656          if (icase == 6) {
01657             fT[2*fNT - 1] = tt + dt*(yy1d / (yy1d - yy2d));
01658             ++fNT;
01659             fT[2*fNT - 2] = tt + dt*(yy1u / (yy1u - yy2u));
01660          }
01661          if (icase == 7) {
01662             iv = -1;
01663             fT[2*fNT - 1] = tt + dt*(yy1d / (yy1d - yy2d));
01664          }
01665          if (fNT + 1 >= 100) break;
01666       }
01667       if (iv > 0) fT[2*fNT - 1] = 1;
01668    } else {
01669 
01670    //          V E R T I C A L   L I N E
01671       fNT = 1;
01672       fT[0] = 0;
01673       fT[1] = 1;
01674       if (y2 <= y1) {
01675          if (y2 == y1) { fNT = 0; return;}
01676          ifback = 1 - ifback;
01677          yy = y1;
01678          y1 = y2;
01679          y2 = yy;
01680       }
01681       uu = fU[2*i1 - 2];
01682       dd = fD[2*i1 - 2];
01683       if (i1 != 1) {
01684          if (uu < fU[2*i1 - 3]) uu = fU[2*i1 - 3];
01685          if (dd > fD[2*i1 - 3]) dd = fD[2*i1 - 3];
01686       }
01687    //         F I N D   V I S I B L E   P A R T   O F   L I N E
01688       if (y1 <  uu && y2 >  dd) {
01689          if (y1 >= dd && y2 <= uu) {fNT = 0; return;}
01690          fNT = 0;
01691          if (dd > y1) {
01692             ++fNT;
01693             fT[2*fNT - 2] = 0;
01694             fT[2*fNT - 1] = (dd - y1) / (y2 - y1);
01695          }
01696          if (uu < y2) {
01697             ++fNT;
01698             fT[2*fNT - 2] = (uu - y1) / (y2 - y1);
01699             fT[2*fNT - 1] = 1;
01700          }
01701       }
01702    }
01703 
01704    if (ifback == 0) return;
01705    if (fNT == 0)    return;
01706    for (i = 1; i <= fNT; ++i) {
01707       fT[2*i - 2] = 1 - fT[2*i - 2];
01708       fT[2*i - 1] = 1 - fT[2*i - 1];
01709    }
01710 }
01711 
01712 
01713 //______________________________________________________________________________
01714 void TPainter3dAlgorithms::FindVisibleLine(Double_t *p1, Double_t *p2, Int_t ntmax, Int_t &nt, Double_t *t)
01715 {
01716    // Find visible part of a line ("RASTER SCREEN")
01717    //
01718    //    Input: P1(2) - 1st point of the line
01719    //           P2(2) - 2nd point of the line
01720    //           NTMAX - max allowed number of visible segments
01721    //
01722    //    Output: NT     - number of visible segments of the line
01723    //            T(2,*) - visible segments
01724 
01725    Double_t ddtt;
01726    Double_t tcur;
01727    Int_t i, incrx, ivis, x1, y1, x2, y2, ib, kb, dx, dy, iw, ix, iy, ifinve, dx2, dy2;
01728    Double_t t1, t2;
01729    Double_t dt;
01730    Double_t tt;
01731    /* Parameter adjustments */
01732    t -= 3;
01733    --p2;
01734    --p1;
01735 
01736    if (fIfrast) {
01737       nt = 1;
01738       t[3] = 0;
01739       t[4] = 1;
01740       return;
01741    }
01742    x1 = Int_t(fNxrast*((p1[1] - fXrast) / fDXrast) - 0.01);
01743    y1 = Int_t(fNyrast*((p1[2] - fYrast) / fDYrast) - 0.01);
01744    x2 = Int_t(fNxrast*((p2[1] - fXrast) / fDXrast) - 0.01);
01745    y2 = Int_t(fNyrast*((p2[2] - fYrast) / fDYrast) - 0.01);
01746    ifinve = 0;
01747    if (y1 > y2) {
01748       ifinve = 1;
01749       iw = x1;
01750       x1 = x2;
01751       x2 = iw;
01752       iw = y1;
01753       y1 = y2;
01754       y2 = iw;
01755    }
01756    nt   = 0;
01757    ivis = 0;
01758    if (y1 >= fNyrast) return;
01759    if (y2 < 0)        return;
01760    if (x1 >= fNxrast && x2 >= fNxrast) return;
01761    if (x1 < 0 && x2 < 0)               return;
01762 
01763    //          S E T   I N I T I A L   V A L U E S
01764    incrx = 1;
01765    dx = x2 - x1;
01766    if (dx < 0) {
01767       dx = -dx;
01768       incrx = -1;
01769    }
01770    dy  = y2 - y1;
01771    dx2 = dx + dx;
01772    dy2 = dy + dy;
01773    if (dy > dx) goto L200;
01774 
01775    //          D X   . G T .   D Y
01776    dt = 1./ (Double_t)(dx + 1.);
01777    ddtt = dt*(float).5;
01778    tcur = -(Double_t)dt;
01779    tt = (Double_t) (-(dx + dy2));
01780    iy = y1;
01781    kb = iy*fNxrast + x1 - incrx;
01782    for (ix = x1; incrx < 0 ? ix >= x2 : ix <= x2; ix += incrx) {
01783       kb += incrx;
01784       tcur += dt;
01785       tt += dy2;
01786       if (tt >= 0) {
01787          ++iy;
01788          tt -= dx2;
01789          kb += fNxrast;
01790       }
01791       if (iy < 0)        goto L110;
01792       if (iy >= fNyrast) goto L110;
01793       if (ix < 0)        goto L110;
01794       if (ix >= fNxrast) goto L110;
01795       iw = kb / 30;
01796       ib = kb - iw*30 + 1;
01797       if (fRaster[iw] & fMask[ib - 1]) goto L110;
01798       if (ivis > 0)      continue;
01799       ivis = 1;
01800       ++nt;
01801       t[2*nt + 1] = tcur;
01802       continue;
01803 L110:
01804       if (ivis == 0) continue;
01805       ivis = 0;
01806       t[2*nt + 2] = tcur;
01807       if (nt == ntmax)  goto L300;
01808    }
01809    if (ivis > 0) t[2*nt + 2] = tcur + dt + ddtt;
01810    goto L300;
01811 
01812    //          D Y   . G T .   D X
01813 L200:
01814    dt = 1. / (Double_t)(dy + 1.);
01815    ddtt = dt*(float).5;
01816    tcur = -(Double_t)dt;
01817    tt = (Double_t) (-(dy + dx2));
01818    ix = x1;
01819    if (y2 >= fNyrast) y2 = fNyrast - 1;
01820    kb = (y1 - 1)*fNxrast + ix;
01821    for (iy = y1; iy <= y2; ++iy) {
01822       kb += fNxrast;
01823       tcur += dt;
01824       tt += dx2;
01825       if (tt >= 0) {
01826          ix += incrx;
01827          tt -= dy2;
01828          kb += incrx;
01829       }
01830       if (iy < 0)        goto L210;
01831       if (ix < 0)        goto L210;
01832       if (ix >= fNxrast) goto L210;
01833       iw = kb / 30;
01834       ib = kb - iw*30 + 1;
01835       if (fRaster[iw] & fMask[ib - 1]) goto L210;
01836       if (ivis > 0) continue;
01837       ivis = 1;
01838       ++nt;
01839       t[2*nt + 1] = tcur;
01840       continue;
01841 L210:
01842       if (ivis == 0) continue;
01843       ivis = 0;
01844       t[2*nt + 2] = tcur;
01845       if (nt == ntmax) goto L300;
01846    }
01847    if (ivis > 0) t[2*nt + 2] = tcur + dt;
01848 
01849    //          C H E C K   D I R E C T I O N   O F   P A R A M E T E R
01850 L300:
01851    if (nt == 0) return;
01852    dt *= 1.1;
01853    if (t[3] <= dt) t[3] = 0;
01854    if (t[2*nt + 2] >= 1 - dt) t[2*nt + 2] = 1;
01855    if (ifinve == 0) return;
01856    for (i = 1; i <= nt; ++i) {
01857       t1 = t[2*i + 1];
01858       t2 = t[2*i + 2];
01859       t[2*i + 1] = 1 - t2;
01860       t[2*i + 2] = 1 - t1;
01861    }
01862 }
01863 
01864 
01865 //______________________________________________________________________________
01866 void TPainter3dAlgorithms::FrontBox(Double_t ang)
01867 {
01868    // Draw forward faces of surrounding box & axes
01869    //
01870    //    Function: Draw forward faces of surrounding box & axes
01871    //
01872    //    References: AxisVertex, Gaxis
01873    //
01874    //    Input  ANG     - angle between X and Y axis
01875    //
01876    //           DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
01877    //             ICODES(*) - set of codes for this face
01878    //             NP        - number of nodes in face
01879    //             IFACE(NP) - face
01880    //             T(NP)     - additional function
01881 
01882    /* Initialized data */
01883    static Int_t iface1[4] = { 1,2,6,5 };
01884    static Int_t iface2[4] = { 2,3,7,6 };
01885 
01886    Double_t cosa, sina;
01887    Double_t r[24]        /* was [3][8] */, av[24]        /* was [3][8] */;
01888    Int_t icodes[3];
01889    Double_t fdummy[1];
01890    Int_t i, ix1, ix2, iy1, iy2, iz1, iz2;
01891    TView *view = 0;
01892 
01893    if (gPad) view = gPad->GetView();
01894    if (!view) {
01895       Error("FrontBox", "no TView in current pad");
01896       return;
01897    }
01898 
01899    cosa = TMath::Cos(kRad*ang);
01900    sina = TMath::Sin(kRad*ang);
01901    view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
01902    for (i = 1; i <= 8; ++i) {
01903       r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2] * cosa;
01904       r[i*3 - 2] = av[i*3 - 2] * sina;
01905       r[i*3 - 1] = av[i*3 - 1];
01906    }
01907 
01908    //          D R A W   F O R W A R D   F A C E S
01909    icodes[0] = 0;
01910    icodes[1] = 0;
01911    icodes[2] = 0;
01912    (this->*fDrawFace)(icodes, r, 4, iface1, fdummy);
01913    (this->*fDrawFace)(icodes, r, 4, iface2, fdummy);
01914 }
01915 
01916 
01917 //______________________________________________________________________________
01918 void TPainter3dAlgorithms::GouraudFunction(Int_t ia, Int_t ib, Double_t *face, Double_t *t)
01919 {
01920    // Find part of surface with luminosity in the corners
01921    //
01922    //              This routine is used for Gouraud shading
01923 
01924    Int_t iphi;
01925    static Double_t f[108];        /* was [3][4][3][3] */
01926    Int_t i, j, k;
01927    Double_t r, s, x[36];        /* was [4][3][3] */
01928    Double_t y[36];        /* was [4][3][3] */
01929    Double_t z[36];        /* was [4][3][3] */
01930    Int_t incrx[3], incry[3];
01931 
01932    Double_t x1, x2, y1, y2, z1, z2, th, an[27];        /* was [3][3][3] */
01933    Double_t bn[12];    /* was [3][2][2] */
01934 
01935    Double_t rad;
01936    Double_t phi;
01937    Int_t ixt, iyt;
01938 
01939     /* Parameter adjustments */
01940    --t;
01941    face -= 4;
01942 
01943    iphi = 1;
01944    rad = TMath::ATan(1) * (float)4 / (float)180;
01945 
01946    //        Find real cell indexes
01947    ixt = ia + Hparam.xfirst - 1;
01948    iyt = ib + Hparam.yfirst - 1;
01949 
01950    //        Find increments of neighboring cells
01951    incrx[0] = -1;
01952    incrx[1] = 0;
01953    incrx[2] = 1;
01954    if (ixt == 1) incrx[0] = 0;
01955    if (ixt == Hparam.xlast - 1) incrx[2] = 0;
01956    incry[0] = -1;
01957    incry[1] = 0;
01958    incry[2] = 1;
01959    if (iyt == 1) incry[0] = 0;
01960    if (iyt == Hparam.ylast - 1) incry[2] = 0;
01961 
01962    //        Find neighboring faces
01963    Int_t i1, i2;
01964    for (j = 1; j <= 3; ++j) {
01965       for (i = 1; i <= 3; ++i) {
01966          i1 = ia + incrx[i - 1];
01967          i2 = ib + incry[j - 1];
01968          SurfaceFunction(i1, i2, &f[(((i + j*3) << 2) + 1)*3 - 51], &t[1]);
01969       }
01970    }
01971 
01972    //       Set face
01973    for (k = 1; k <= 4; ++k) {
01974       for (i = 1; i <= 3; ++i) {
01975          face[i + k*3] = f[i + (k + 32)*3 - 52];
01976       }
01977    }
01978 
01979    //       Find coordinates and normales
01980    for (j = 1; j <= 3; ++j) {
01981       for (i = 1; i <= 3; ++i) {
01982          for (k = 1; k <= 4; ++k) {
01983             if (Hoption.System == kPOLAR) {
01984                phi = f[iphi + (k + ((i + j*3) << 2))*3 - 52]*rad;
01985                r = f[3 - iphi + (k + ((i + j*3) << 2))*3 - 52];
01986                x[k + ((i + j*3) << 2) - 17] = r * TMath::Cos(phi);
01987                y[k + ((i + j*3) << 2) - 17] = r * TMath::Sin(phi);
01988                z[k + ((i + j*3) << 2) - 17] = f[(k + ((i + j*3) << 2))*3 - 49];
01989             } else if (Hoption.System == kCYLINDRICAL) {
01990                phi = f[iphi + (k + ((i + j*3) << 2))*3 - 52]*rad;
01991                r = f[(k + ((i + j*3) << 2))*3 - 49];
01992                x[k + ((i + j*3) << 2) - 17] = r*TMath::Cos(phi);
01993                y[k + ((i + j*3) << 2) - 17] = r*TMath::Sin(phi);
01994                z[k + ((i + j*3) << 2) - 17] = f[3 - iphi + (k + ((i + j*3) << 2))*3 - 52];
01995             } else if (Hoption.System == kSPHERICAL) {
01996                phi = f[iphi + (k + ((i + j*3) << 2))*3 - 52]*rad;
01997                th = f[3 - iphi + (k + ((i + j*3) << 2))*3 - 52]*rad;
01998                r = f[(k + ((i + j*3) << 2))*3 - 49];
01999                x[k + ((i + j*3) << 2) - 17] = r*TMath::Sin(th)*TMath::Cos(phi);
02000                y[k + ((i + j*3) << 2) - 17] = r*TMath::Sin(th)*TMath::Sin(phi);
02001                z[k + ((i + j*3) << 2) - 17] = r*TMath::Cos(th);
02002             } else if (Hoption.System == kRAPIDITY) {
02003                phi = f[iphi + (k + ((i + j*3) << 2))*3 - 52]*rad;
02004                th = f[3 - iphi + (k + ((i + j*3) << 2))*3 - 52]*rad;
02005                r = f[(k + ((i + j*3) << 2))*3 - 49];
02006                x[k + ((i + j*3) << 2) - 17] = r*TMath::Cos(phi);
02007                y[k + ((i + j*3) << 2) - 17] = r*TMath::Sin(phi);
02008                z[k + ((i + j*3) << 2) - 17] = r*TMath::Cos(th) / TMath::Sin(th);
02009             } else {
02010                x[k + ((i + j*3) << 2) - 17] = f[(k + ((i + j*3) << 2))*3 - 51];
02011                y[k + ((i + j*3) << 2) - 17] = f[(k + ((i + j*3) << 2))*3 - 50];
02012                z[k + ((i + j*3) << 2) - 17] = f[(k + ((i + j*3) << 2))*3 - 49];
02013             }
02014          }
02015          x1 = x[((i + j*3) << 2) - 14] - x[((i + j*3) << 2) - 16];
02016          x2 = x[((i + j*3) << 2) - 13] - x[((i + j*3) << 2) - 15];
02017          y1 = y[((i + j*3) << 2) - 14] - y[((i + j*3) << 2) - 16];
02018          y2 = y[((i + j*3) << 2) - 13] - y[((i + j*3) << 2) - 15];
02019          z1 = z[((i + j*3) << 2) - 14] - z[((i + j*3) << 2) - 16];
02020          z2 = z[((i + j*3) << 2) - 13] - z[((i + j*3) << 2) - 15];
02021          an[(i + j*3)*3 - 12] = y1*z2 - y2*z1;
02022          an[(i + j*3)*3 - 11] = z1*x2 - z2*x1;
02023          an[(i + j*3)*3 - 10] = x1*y2 - x2*y1;
02024          s = TMath::Sqrt(an[(i + j*3)*3 - 12]*an[(i + j*3)*3 - 12] + an[
02025                         (i + j*3)*3 - 11]*an[(i + j*3)*3 - 11] + an[(i
02026                         + j*3)*3 - 10]*an[(i + j*3)*3 - 10]);
02027 
02028          an[(i + j*3)*3 - 12] /= s;
02029          an[(i + j*3)*3 - 11] /= s;
02030          an[(i + j*3)*3 - 10] /= s;
02031       }
02032    }
02033 
02034    //         Find average normals
02035    for (j = 1; j <= 2; ++j) {
02036       for (i = 1; i <= 2; ++i) {
02037          for (k = 1; k <= 3; ++k) {
02038             bn[k + (i + 2*j)*3 - 10] = an[k + (i + j*3)*3 - 13]
02039               + an[k + (i + 1 + j*3)*3 - 13] + an[k + (i + 1 +
02040                           (j + 1)*3)*3 - 13] + an[k + (i + (j + 1)*3)*3 - 13];
02041          }
02042       }
02043    }
02044 
02045    //        Set luminosity
02046    Luminosity(bn,     t[1]);
02047    Luminosity(&bn[3], t[2]);
02048    Luminosity(&bn[9], t[3]);
02049    Luminosity(&bn[6], t[4]);
02050 }
02051 
02052 
02053 //______________________________________________________________________________
02054 void TPainter3dAlgorithms::InitMoveScreen(Double_t xmin, Double_t xmax)
02055 {
02056    // Initialize "MOVING SCREEN" method
02057    //
02058    //    Input: XMIN - left boundary
02059    //           XMAX - right boundary
02060 
02061    fX0 = xmin;
02062    fDX = (xmax - xmin) / 1000;
02063    for (Int_t i = 1; i <= 1000; ++i) {
02064       fU[2*i - 2] = (float)-999;
02065       fU[2*i - 1] = (float)-999;
02066       fD[2*i - 2] = (float)999;
02067       fD[2*i - 1] = (float)999;
02068    }
02069 }
02070 
02071 
02072 //______________________________________________________________________________
02073 void TPainter3dAlgorithms::InitRaster(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Int_t nx, Int_t ny  )
02074 {
02075    // Initialize hidden lines removal algorithm (RASTER SCREEN)
02076    //
02077    //    Input: XMIN - Xmin in the normalized coordinate system
02078    //           YMIN - Ymin in the normalized coordinate system
02079    //           XMAX - Xmax in the normalized coordinate system
02080    //           YMAX - Ymax in the normalized coordinate system
02081    //           NX   - number of pixels along X
02082    //           NY   - number of pixels along Y
02083 
02084    Int_t i, j, k, ib, nb;
02085 
02086    fNxrast = nx;
02087    fNyrast = ny;
02088    fXrast  = xmin;
02089    fDXrast = xmax - xmin;
02090    fYrast  = ymin;
02091    fDYrast = ymax - ymin;
02092 
02093    //  Create buffer for raster
02094    Int_t buffersize = nx*ny/30 + 1;
02095    fRaster = new Int_t[buffersize];
02096 
02097    //          S E T   M A S K S
02098    k = 0;
02099    Int_t pow2 = 1;
02100    for (i = 1; i <= 30; ++i) {
02101       fJmask[i - 1] = k;
02102       k = k + 30 - i + 1;
02103       fMask[i - 1] = pow2;
02104       pow2 *= 2;
02105    }
02106    j = 30;
02107    for (nb = 2; nb <= 30; ++nb) {
02108       for (ib = 1; ib <= 30 - nb + 1; ++ib) {
02109          k = 0;
02110          for (i = ib; i <= ib + nb - 1; ++i) k = k | fMask[i - 1];
02111          ++j;
02112          fMask[j - 1] = k;
02113       }
02114    }
02115 
02116    //          C L E A R   R A S T E R   S C R E E N
02117    ClearRaster();
02118 }
02119 
02120 
02121 //______________________________________________________________________________
02122 void TPainter3dAlgorithms::LegoFunction(Int_t ia, Int_t ib, Int_t &nv, Double_t *ab, Double_t *vv, Double_t *t)
02123 {
02124    // Service function for Legos
02125 
02126    Int_t i, j, ixt, iyt;
02127    Double_t xval1l, xval2l, yval1l,  yval2l;
02128    Double_t xlab1l, xlab2l, ylab1l, ylab2l;
02129    Double_t rinrad = gStyle->GetLegoInnerR();
02130    Double_t dangle = 10; //Delta angle for Rapidity option
02131 
02132    /* Parameter adjustments */
02133    t -= 5;
02134    --vv;
02135    ab -= 3;
02136 
02137    ixt = ia + Hparam.xfirst - 1;
02138    iyt = ib + Hparam.yfirst - 1;
02139 
02140    //             Compute the cell position in cartesian coordinates
02141    //             and compute the LOG if necessary
02142    Double_t xwid = gCurrentHist->GetXaxis()->GetBinWidth(ixt);
02143    Double_t ywid = gCurrentHist->GetYaxis()->GetBinWidth(iyt);
02144    ab[3] = gCurrentHist->GetXaxis()->GetBinLowEdge(ixt) + xwid*Hparam.baroffset;
02145    ab[4] = gCurrentHist->GetYaxis()->GetBinLowEdge(iyt) + ywid*Hparam.baroffset;
02146    ab[5] = ab[3] + xwid*Hparam.barwidth;
02147    ab[8] = ab[4] + ywid*Hparam.barwidth;
02148 
02149    if (Hoption.Logx) {
02150       if (ab[3] > 0) ab[3]  = TMath::Log10(ab[3]);
02151       else           ab[3]  = Hparam.xmin;
02152       if (ab[5] > 0) ab[5]  = TMath::Log10(ab[5]);
02153       else           ab[5]  = Hparam.xmin;
02154    }
02155    xval1l = Hparam.xmin;
02156    xval2l = Hparam.xmax;
02157    if (Hoption.Logy) {
02158       if (ab[4] > 0) ab[4]  = TMath::Log10(ab[4]);
02159       else           ab[4]  = Hparam.ymin;
02160       if (ab[8] > 0) ab[8]  = TMath::Log10(ab[8]);
02161       else           ab[8]  = Hparam.ymin;
02162    }
02163    yval1l = Hparam.ymin;
02164    yval2l = Hparam.ymax;
02165 
02166    if (ab[3] < Hparam.xmin) ab[3] = Hparam.xmin;
02167    if (ab[4] < Hparam.ymin) ab[4] = Hparam.ymin;
02168    if (ab[5] > Hparam.xmax) ab[5] = Hparam.xmax;
02169    if (ab[8] > Hparam.ymax) ab[8] = Hparam.ymax;
02170    if (ab[5] < Hparam.xmin) ab[5] = Hparam.xmin;
02171    if (ab[8] < Hparam.ymin) ab[8] = Hparam.ymin;
02172 
02173    xlab1l = gCurrentHist->GetXaxis()->GetXmin();
02174    xlab2l = gCurrentHist->GetXaxis()->GetXmax();
02175    if (Hoption.Logx) {
02176       if (xlab2l>0) {
02177          if (xlab1l>0) xlab1l = TMath::Log10(xlab1l);
02178          else          xlab1l = TMath::Log10(0.001*xlab2l);
02179          xlab2l = TMath::Log10(xlab2l);
02180       }
02181    }
02182    ylab1l = gCurrentHist->GetYaxis()->GetXmin();
02183    ylab2l = gCurrentHist->GetYaxis()->GetXmax();
02184    if (Hoption.Logy) {
02185       if (ylab2l>0) {
02186          if (ylab1l>0) ylab1l = TMath::Log10(ylab1l);
02187          else          ylab1l = TMath::Log10(0.001*ylab2l);
02188          ylab2l = TMath::Log10(ylab2l);
02189       }
02190    }
02191 
02192    //       Transform the cell position in the required coordinate system
02193    if (Hoption.System == kPOLAR) {
02194       ab[3] = 360*(ab[3] - xlab1l) / (xlab2l - xlab1l);
02195       ab[5] = 360*(ab[5] - xlab1l) / (xlab2l - xlab1l);
02196       ab[4] = (ab[4] - yval1l) / (yval2l - yval1l);
02197       ab[8] = (ab[8] - yval1l) / (yval2l - yval1l);
02198    } else if (Hoption.System == kCYLINDRICAL) {
02199       ab[3] = 360*(ab[3] - xlab1l) / (xlab2l - xlab1l);
02200       ab[5] = 360*(ab[5] - xlab1l) / (xlab2l - xlab1l);
02201    } else if (Hoption.System == kSPHERICAL) {
02202       ab[3] = 360*(ab[3] - xlab1l) / (xlab2l - xlab1l);
02203       ab[5] = 360*(ab[5] - xlab1l) / (xlab2l - xlab1l);
02204       ab[4] = 180*(ab[4] - ylab1l) / (ylab2l - ylab1l);
02205       ab[8] = 180*(ab[8] - ylab1l) / (ylab2l - ylab1l);
02206    } else if (Hoption.System == kRAPIDITY) {
02207       ab[3] = 360*(ab[3] - xlab1l) / (xlab2l - xlab1l);
02208       ab[5] = 360*(ab[5] - xlab1l) / (xlab2l - xlab1l);
02209       ab[4] = (180 - dangle*2)*(ab[4] - ylab1l) / (ylab2l - ylab1l) + dangle;
02210       ab[8] = (180 - dangle*2)*(ab[8] - ylab1l) / (ylab2l - ylab1l) + dangle;
02211    }
02212 
02213    //             Complete the cell coordinates
02214    ab[6]  = ab[4];
02215    ab[7]  = ab[5];
02216    ab[9]  = ab[3];
02217    ab[10] = ab[8];
02218 
02219    //              Get the content of the table, and loop on the
02220    //              stack if necessary.
02221    vv[1] = Hparam.zmin;
02222    vv[2] = Hparam.factor*gCurrentHist->GetCellContent(ixt, iyt);
02223 
02224    // In linear scale, 3D boxes all start from 0.
02225    if (Hparam.zmin<0 && !Hoption.Logz && gStyle->GetHistMinimumZero()) {
02226       if (vv[2]<0) {
02227          vv[1] = vv[2];
02228          vv[2] = 0;
02229       } else {
02230          vv[1]=0;
02231       }
02232    }
02233 
02234    TList *stack = gCurrentHist->GetPainter()->GetStack();
02235    Int_t nids = 0; //not yet implemented
02236    if (stack) nids = stack->GetSize();
02237    if (nids) {
02238       for (i = 2; i <= nids + 1; ++i) {
02239          TH1 *hid = (TH1*)stack->At(i-2);
02240          vv[i + 1] = Hparam.factor*hid->GetCellContent(ixt, iyt) + vv[i];
02241          vv[i + 1] = TMath::Max(Hparam.zmin, vv[i + 1]);
02242          //vv[i + 1] = TMath::Min(Hparam.zmax, vv[i + 1]);
02243       }
02244    }
02245 
02246    nv = nids + 2;
02247    for (i = 2; i <= nv; ++i) {
02248       if (Hoption.Logz) {
02249          if (vv[i] > 0)
02250             vv[i] = TMath::Max(Hparam.zmin, (Double_t)TMath::Log10(vv[i]));
02251          else
02252             vv[i] = Hparam.zmin;
02253          vv[i] = TMath::Min(vv[i], Hparam.zmax);
02254       } else {
02255             vv[i] = TMath::Max(Hparam.zmin, vv[i]);
02256             vv[i] = TMath::Min(Hparam.zmax, vv[i]);
02257       }
02258    }
02259 
02260    if (!Hoption.Logz) {
02261       i = 3;
02262       while (i <= nv) {
02263          if (vv[i] < vv[i - 1]) {
02264             vv[i - 1] = vv[i];
02265             i = 3;
02266             continue;
02267          }
02268          ++i;
02269       }
02270    }
02271 
02272    //          For cylindrical, spherical and pseudo-rapidity, the content
02273    //          is mapped onto the radius
02274    if (Hoption.System == kCYLINDRICAL || Hoption.System == kSPHERICAL || Hoption.System == kRAPIDITY) {
02275       for (i = 1; i <= nv; ++i) {
02276          vv[i] = (1 - rinrad)*((vv[i] - Hparam.zmin) /
02277                  (Hparam.zmax - Hparam.zmin)) + rinrad;
02278       }
02279    }
02280 
02281    for (i = 1; i <= nv; ++i) {
02282       for (j = 1; j <= 4; ++j) t[j + (i << 2)] = vv[i];
02283    }
02284 }
02285 
02286 
02287 //______________________________________________________________________________
02288 void TPainter3dAlgorithms::LegoCartesian(Double_t ang, Int_t nx, Int_t ny, const char *chopt)
02289 {
02290    // Draw stack of lego-plots in cartesian coordinates
02291    //
02292    //    Input: ANG      - angle between X ang Y
02293    //           NX       - number of cells along X
02294    //           NY       - number of cells along Y
02295    //
02296    //           FUN(IX,IY,NV,XY,V,T) - external routine
02297    //             IX     - X number of the cell
02298    //             IY     - Y number of the cell
02299    //             NV     - number of values for given cell
02300    //             XY(2,4)- coordinates of the cell corners
02301    //             V(NV)  - cell values
02302    //             T(4,NV)- additional function (for example: temperature)
02303    //
02304    //           DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
02305    //             ICODES(*) - set of codes for this line
02306    //               ICODES(1) - IX
02307    //               ICODES(2) - IY
02308    //               ICODES(3) - IV
02309    //               ICODES(4) - side: 1-face,2-right,3-back,4-left,
02310    //                                 5-bottom, 6-top
02311    //               XYZ(3,*)  - coordinates of nodes
02312    //               NP        - number of nodes
02313    //               IFACE(NP) - face
02314    //                T(4)   - additional function (here Z-coordinate)
02315    //
02316    //           CHOPT - options: 'BF' - from BACK to FRONT
02317    //                            'FB' - from FRONT to BACK
02318    //
02319    //Begin_Html
02320    /*
02321    <img src="gif/Lego1Cartesian.gif">
02322    */
02323    //End_Html
02324 
02325    // Local variables
02326    Double_t cosa, sina;
02327    Int_t ivis[4], iface[4];
02328    Double_t tface[4];
02329    Int_t incrx, incry, i1, k1, k2, ix1, iy1, ix2, iy2, i, iv, ix, iy, nv;
02330    Int_t icodes[4];
02331    Double_t zn, xy[8]; // was [2][4]
02332    Double_t xyz[24];   // was [3][8]
02333    Double_t *tn = 0;
02334    TView *view = 0;
02335 
02336    sina = TMath::Sin(ang*kRad);
02337    cosa = TMath::Cos(ang*kRad);
02338 
02339    //          F I N D   T H E   M O S T   L E F T   P O I N T
02340    if (gPad) view = gPad->GetView();
02341    if (!view) {
02342       Error("LegoCartesian", "no TView in current pad");
02343       return;
02344    }
02345    tn = view->GetTN();
02346 
02347    i1 = 1;
02348    if (tn[0] < 0) i1 = 2;
02349    if (tn[0]*cosa + tn[1]*sina < 0) i1 = 5 - i1;
02350 
02351    // Allocate v and tt arrays
02352    Double_t *v, *tt;
02353    Int_t vSize = fNStack+2;
02354    if (vSize > kVSizeMax) {
02355       v  = new Double_t[vSize];
02356       tt = new Double_t[4*vSize];
02357    } else {
02358       vSize = kVSizeMax;
02359       v  = &gV[0];
02360       tt = &gTT[0];
02361    }
02362 
02363    //          D E F I N E   O R D E R   O F   D R A W I N G
02364    if (*chopt == 'B' || *chopt == 'b') {
02365       incrx = -1;
02366       incry = -1;
02367    } else {
02368       incrx = 1;
02369       incry = 1;
02370    }
02371    if (i1 == 1 || i1 == 2) incrx = -incrx;
02372    if (i1 == 2 || i1 == 3) incry = -incry;
02373    ix1 = 1;
02374    iy1 = 1;
02375    if (incrx < 0) ix1 = nx;
02376    if (incry < 0) iy1 = ny;
02377    ix2 = nx - ix1 + 1;
02378    iy2 = ny - iy1 + 1;
02379 
02380    //          F I N D   V I S I B I L I T Y   O F   S I D E S
02381    ivis[0] = 0;
02382    ivis[1] = 0;
02383    ivis[2] = 0;
02384    ivis[3] = 0;
02385    nv      = 0;
02386    view->FindNormal(0, 1, 0, zn);
02387    if (zn < 0) ivis[0] = 1;
02388    if (zn > 0) ivis[2] = 1;
02389    view->FindNormal(sina, cosa, 0, zn);
02390    if (zn > 0) ivis[1] = 1;
02391    if (zn < 0) ivis[3] = 1;
02392 
02393    //          D R A W   S T A C K   O F   L E G O - P L O T S
02394    THistPainter *painter = (THistPainter*)gCurrentHist->GetPainter();
02395    for (iy = iy1; incry < 0 ? iy >= iy2 : iy <= iy2; iy += incry) {
02396       for (ix = ix1; incrx < 0 ? ix >= ix2 : ix <= ix2; ix += incrx) {
02397          if (!painter->IsInside(ix,iy)) continue;
02398          (this->*fLegoFunction)(ix, iy, nv, xy, v, tt);
02399          if (nv < 2 || nv > vSize) continue;
02400          if (Hoption.Zero) {
02401             Double_t total_content=0;
02402             for (iv = 1; iv < nv; ++iv) total_content += v[iv];
02403             if (total_content==0) continue;
02404          }
02405          icodes[0] = ix;
02406          icodes[1] = iy;
02407          for (i = 1; i <= 4; ++i) {
02408             xyz[i*3 - 3] = xy[2*i - 2] + xy[2*i - 1]*cosa;
02409             xyz[i*3 - 2] = xy[2*i - 1]*sina;
02410             xyz[(i + 4)*3 - 3] = xyz[i*3 - 3];
02411             xyz[(i + 4)*3 - 2] = xyz[i*3 - 2];
02412          }
02413    //         D R A W   S T A C K
02414          for (iv = 1; iv < nv; ++iv) {
02415             for (i = 1; i <= 4; ++i) {
02416                xyz[i*3 - 1] = v[iv - 1];
02417                xyz[(i + 4)*3 - 1] = v[iv];
02418             }
02419             if (v[iv - 1] == v[iv]) continue;
02420             icodes[2] = iv;
02421             for (i = 1; i <= 4; ++i) {
02422                if (ivis[i - 1] == 0) continue;
02423                k1 = i;
02424                k2 = i + 1;
02425                if (i == 4) k2 = 1;
02426                icodes[3] = k1;
02427                iface[0] = k1;
02428                iface[1] = k2;
02429                iface[2] = k2 + 4;
02430                iface[3] = k1 + 4;
02431                tface[0] = tt[k1 + (iv << 2) - 5];
02432                tface[1] = tt[k2 + (iv << 2) - 5];
02433                tface[2] = tt[k2 + ((iv + 1) << 2) - 5];
02434                tface[3] = tt[k1 + ((iv + 1) << 2) - 5];
02435                (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
02436             }
02437          }
02438    //         D R A W   B O T T O M   F A C E
02439          view->FindNormal(0, 0, 1, zn);
02440          if (zn < 0) {
02441             icodes[2] = 1;
02442             icodes[3] = 5;
02443             for (i = 1; i <= 4; ++i) {
02444                xyz[i*3 - 1] = v[0];
02445                iface[i - 1] = 5 - i;
02446                tface[i - 1] = tt[5 - i - 1];
02447             }
02448             (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
02449          }
02450    //         D R A W   T O P   F A C E
02451          if (zn > 0) {
02452             icodes[2] = nv - 1;
02453             icodes[3] = 6;
02454             for (i = 1; i <= 4; ++i) {
02455                iface[i - 1] = i + 4;
02456                tface[i - 1] = tt[i + (nv << 2) - 5];
02457             }
02458             Int_t cs = fColorTop;
02459             if ( nv > 2 && (v[nv-1] == v[nv-2])) {
02460                for (iv = nv-1; iv>2; iv--) {
02461                   if (v[nv-1] == v[iv-1]) fColorTop = fColorMain[iv-2];
02462                }
02463             }
02464             (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
02465             fColorTop = cs;
02466          }
02467       }
02468    }
02469    if (vSize > kVSizeMax) {
02470       delete [] v;
02471       delete [] tt;
02472    }
02473 }
02474 
02475 
02476 //______________________________________________________________________________
02477 void TPainter3dAlgorithms::LegoPolar(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
02478 {
02479    // Draw stack of lego-plots in polar coordinates
02480    //
02481    //    Input: IORDR - order of variables (0 - R,PHI; 1 - PHI,R)
02482    //           NA    - number of steps along 1st variable
02483    //           NB    - number of steps along 2nd variable
02484    //
02485    //           FUN(IA,IB,NV,AB,V,TT) - external routine
02486    //             IA      - cell number for 1st variable
02487    //             IB      - cell number for 2nd variable
02488    //             NV      - number of values for given cell
02489    //             AB(2,4) - coordinates of the cell corners
02490    //             V(NV)   - cell values
02491    //             TT(4,*) - additional function
02492    //
02493    //           DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
02494    //             ICODES(*) - set of codes for this face
02495    //               ICODES(1) - IA
02496    //               ICODES(2) - IB
02497    //               ICODES(3) - IV
02498    //               ICODES(4) - side: 1-internal,2-right,3-external,4-left
02499    //                                 5-bottom, 6-top
02500    //             XYZ(3,*)  - coordinates of nodes
02501    //             NP        - number of nodes in face
02502    //             IFACE(NP) - face
02503    //             T(NP)     - additional function
02504    //
02505    //            CHOPT       - options: 'BF' - from BACK to FRONT
02506    //                                   'FB' - from FRONT to BACK
02507    //
02508    //Begin_Html
02509    /*
02510    <img src="gif/Lego1Polar.gif">
02511    */
02512    //End_Html
02513 
02514    Int_t iphi, jphi, kphi, incr, nphi, ivis[6], iopt, iphi1, iphi2, iface[4], i, j;
02515    Double_t tface[4];
02516    Int_t incrr, k1, k2, ia, ib, ir1, ir2;
02517    Double_t ab[8];       // was [2][4]
02518    Int_t ir, jr, iv, nr, nv, icodes[4];
02519    Double_t xyz[24];     // was [3][8]
02520    ia = ib = 0;
02521    TView *view = 0;
02522 
02523    if (gPad) view = gPad->GetView();
02524    if (!view) {
02525       Error("LegoPolar", "no TView in current pad");
02526       return;
02527    }
02528 
02529    if (iordr == 0) {
02530       jr   = 1;
02531       jphi = 2;
02532       nr   = na;
02533       nphi = nb;
02534    } else {
02535       jr   = 2;
02536       jphi = 1;
02537       nr   = nb;
02538       nphi = na;
02539    }
02540    if (nphi > 180) {
02541       Error("LegoPolar", "too many PHI sectors (%d)", nphi);
02542       return;
02543    }
02544    iopt = 2;
02545    if (*chopt == 'B' || *chopt == 'b') iopt = 1;
02546 
02547     // Allocate v and tt arrays
02548    Double_t *v, *tt;
02549    Int_t vSize = fNStack+2;
02550    if (vSize > kVSizeMax) {
02551       v  = new Double_t[vSize];
02552       tt = new Double_t[4*vSize];
02553    } else {
02554       vSize = kVSizeMax;
02555       v  = &gV[0];
02556       tt = &gTT[0];
02557    }
02558 
02559    //     P R E P A R E   P H I   A R R A Y
02560    //     F I N D    C R I T I C A L   S E C T O R S
02561    nv   = 0;
02562    kphi = nphi;
02563    if (iordr == 0) ia = nr;
02564    if (iordr != 0) ib = nr;
02565    for (i = 1; i <= nphi; ++i) {
02566       if (iordr == 0) ib = i;
02567       if (iordr != 0) ia = i;
02568       (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
02569       if (i == 1) fAphi[0] = ab[jphi - 1];
02570       fAphi[i - 1] = (fAphi[i - 1] + ab[jphi - 1]) / (float)2.;
02571       fAphi[i] = ab[jphi + 3];
02572    }
02573    view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
02574 
02575    //      E N C O D E   V I S I B I L I T Y   O F   S I D E S
02576    //      A N D   O R D E R   A L O N G   R
02577    for (i = 1; i <= nphi; ++i) {
02578       if (!iordr) ib = i;
02579       if (iordr)  ia = i;
02580       (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
02581       SideVisibilityEncode(iopt, ab[jphi - 1]*kRad, ab[jphi + 3]*kRad, fAphi[i - 1]);
02582    }
02583 
02584    //       D R A W   S T A C K   O F   L E G O - P L O T S
02585    incr = 1;
02586    iphi = iphi1;
02587 L100:
02588    if (iphi > nphi) goto L300;
02589 
02590    //     D E C O D E   V I S I B I L I T Y   O F   S I D E S
02591    SideVisibilityDecode(fAphi[iphi - 1], ivis[0], ivis[1], ivis[2], ivis[3], ivis[4], ivis[5], incrr);
02592    ir1 = 1;
02593    if (incrr < 0) ir1 = nr;
02594    ir2 = nr - ir1 + 1;
02595    //      D R A W   L E G O S   F O R   S E C T O R
02596    for (ir = ir1; incrr < 0 ? ir >= ir2 : ir <= ir2; ir += incrr) {
02597       if (iordr == 0) { ia = ir;   ib = iphi; }
02598       else            { ia = iphi; ib = ir; }
02599       (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
02600       if (nv < 2 || nv > vSize) continue;
02601       if (Hoption.Zero) {
02602          Double_t total_content=0;
02603          for (iv = 1; iv < nv; ++iv) total_content += v[iv];
02604          if (total_content==0) continue;
02605       }
02606       icodes[0] = ia;
02607       icodes[1] = ib;
02608       for (i = 1; i <= 4; ++i) {
02609          j = i;
02610          if (iordr != 0 && i == 2) j = 4;
02611          if (iordr != 0 && i == 4) j = 2;
02612          xyz[j*3 - 3] = ab[jr + 2*i - 3]*TMath::Cos(ab[jphi + 2*i - 3]*kRad);
02613          xyz[j*3 - 2] = ab[jr + 2*i - 3]*TMath::Sin(ab[jphi + 2*i - 3]*kRad);
02614          xyz[(j + 4)*3 - 3] = xyz[j*3 - 3];
02615          xyz[(j + 4)*3 - 2] = xyz[j*3 - 2];
02616       }
02617    //      D R A W   S T A C K
02618       for (iv = 1; iv < nv; ++iv) {
02619          for (i = 1; i <= 4; ++i) {
02620             xyz[i*3 - 1] = v[iv - 1];
02621             xyz[(i + 4)*3 - 1] = v[iv];
02622          }
02623          if (v[iv - 1] >= v[iv]) continue;
02624          icodes[2] = iv;
02625          for (i = 1; i <= 4; ++i) {
02626             if (ivis[i - 1] == 0) continue;
02627             k1 = i - 1;
02628             if (i == 1) k1 = 4;
02629             k2 = i;
02630             if (xyz[k1*3 - 3] == xyz[k2*3 - 3] && xyz[k1*3 - 2] ==
02631                 xyz[k2*3 - 2]) continue;
02632             iface[0] = k1;
02633             iface[1] = k2;
02634             iface[2] = k2 + 4;
02635             iface[3] = k1 + 4;
02636             tface[0] = tt[k1 + (iv << 2) - 5];
02637             tface[1] = tt[k2 + (iv << 2) - 5];
02638             tface[2] = tt[k2 + ((iv + 1) << 2) - 5];
02639             tface[3] = tt[k1 + ((iv + 1) << 2) - 5];
02640             icodes[3] = i;
02641             (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
02642          }
02643       }
02644    //         D R A W   B O T T O M   F A C E
02645       if (ivis[4] != 0) {
02646          icodes[2] = 1;
02647          icodes[3] = 5;
02648          for (i = 1; i <= 4; ++i) {
02649             xyz[i*3 - 1] = v[0];
02650             iface[i - 1] = 5 - i;
02651             tface[i - 1] = tt[5 - i - 1];
02652          }
02653          (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
02654       }
02655    //         D R A W   T O P   F A C E
02656       if (ivis[5] != 0) {
02657          icodes[2] = nv - 1;
02658          icodes[3] = 6;
02659          for (i = 1; i <= 4; ++i) {
02660             iface[i - 1] = i + 4;
02661             tface[i - 1] = tt[i + (nv << 2) - 5];
02662          }
02663          Int_t cs = fColorTop;
02664          if ( nv > 2 && (v[nv-1] == v[nv-2])) {
02665             for (iv = nv-1; iv>2; iv--) {
02666                if (v[nv-1] == v[iv-1]) fColorTop = fColorMain[iv-2];
02667             }
02668          }
02669          (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
02670          fColorTop = cs;
02671       }
02672    }
02673    //      N E X T   P H I
02674 L300:
02675    iphi += incr;
02676    if (iphi == 0)      iphi = kphi;
02677    if (iphi > kphi)    iphi = 1;
02678    if (iphi != iphi2)  goto L100;
02679    if (incr == 0) {
02680       if (vSize > kVSizeMax) {
02681          delete [] v;
02682          delete [] tt;
02683       }
02684       return;
02685    }
02686    if (incr < 0) {
02687       incr = 0;
02688       goto L100;
02689    }
02690    incr = -1;
02691    iphi = iphi1;
02692    goto L300;
02693 }
02694 
02695 
02696 //______________________________________________________________________________
02697 void TPainter3dAlgorithms::LegoCylindrical(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
02698 {
02699    // Draw stack of lego-plots in cylindrical coordinates
02700    //
02701    //    Input: IORDR - order of variables (0 - Z,PHI; 1 - PHI,Z)
02702    //           NA    - number of steps along 1st variable
02703    //           NPHI  - number of steps along 2nd variable
02704    //
02705    //           FUN(IA,IB,NV,AB,V,TT) - external routine
02706    //             IA      - cell number for 1st variable
02707    //             IB      - cell number for 2nd variable
02708    //             NV      - number of values for given cell
02709    //             AB(2,4) - coordinates of the cell corners
02710    //             V(NV)   - cell values
02711    //             TT(4,*) - additional function
02712    //
02713    //           DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
02714    //             ICODES(*) - set of codes for this face
02715    //               ICODES(1) - IA
02716    //               ICODES(2) - IB
02717    //               ICODES(3) - IV
02718    //               ICODES(4) - side: 1,2,3,4 - ordinary sides
02719    //                                 5-bottom,6-top
02720    //             XYZ(3,*)  - coordinates of nodes
02721    //             NP        - number of nodes in face
02722    //             IFACE(NP) - face
02723    //             T(NP)     - additional function
02724    //
02725    //           CHOPT       - options: 'BF' - from BACK to FRONT
02726    //                                  'FB' - from FRONT to BACK
02727    //
02728    //Begin_Html
02729    /*
02730    <img src="gif/Lego1Cylindrical.gif">
02731    */
02732    //End_Html
02733 
02734    Int_t iphi, jphi, kphi, incr, nphi, ivis[6], iopt, iphi1, iphi2, iface[4], i, j;
02735    Double_t tface[4], z;
02736    Double_t ab[8];       // was [2][4]
02737    Int_t ia, ib, idummy, iz1, iz2, nz, incrz, k1, k2, nv;
02738    Int_t iv, iz, jz, icodes[4];
02739    Double_t cosphi[4];
02740    Double_t sinphi[4];
02741    Double_t xyz[24];     // was [3][8]
02742    ia = ib = 0;
02743    TView *view = 0;
02744 
02745    if (gPad) view = gPad->GetView();
02746    if (!view) {
02747       Error("LegoCylindrical", "no TView in current pad");
02748       return;
02749    }
02750 
02751    if (iordr == 0) {
02752       jz   = 1;
02753       jphi = 2;
02754       nz   = na;
02755       nphi = nb;
02756    } else {
02757       jz   = 2;
02758       jphi = 1;
02759       nz   = nb;
02760       nphi = na;
02761    }
02762    if (nphi > 180) {
02763       Error("LegoCylindrical", "too many PHI sectors (%d)", nphi);
02764       return;
02765    }
02766    iopt = 2;
02767    if (*chopt == 'B' || *chopt == 'b') iopt = 1;
02768 
02769     // Allocate v and tt arrays
02770    Double_t *v, *tt;
02771    Int_t vSize = fNStack+2;
02772    if (vSize > kVSizeMax) {
02773       v  = new Double_t[vSize];
02774       tt = new Double_t[4*vSize];
02775    } else {
02776       vSize = kVSizeMax;
02777       v  = &gV[0];
02778       tt = &gTT[0];
02779    }
02780 
02781    //       P R E P A R E   P H I   A R R A Y
02782    //       F I N D    C R I T I C A L   S E C T O R S
02783    nv   = 0;
02784    kphi = nphi;
02785    if (iordr == 0) ia = nz;
02786    if (iordr != 0) ib = nz;
02787    for (i = 1; i <= nphi; ++i) {
02788       if (iordr == 0) ib = i;
02789       if (iordr != 0) ia = i;
02790       (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
02791       if (i == 1)  fAphi[0] = ab[jphi - 1];
02792       fAphi[i - 1] = (fAphi[i - 1] + ab[jphi - 1]) / (float)2.;
02793       fAphi[i] = ab[jphi + 3];
02794    }
02795    view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
02796 
02797    //      E N C O D E   V I S I B I L I T Y   O F   S I D E S
02798    //      A N D   O R D E R   A L O N G   R
02799    for (i = 1; i <= nphi; ++i) {
02800       if (iordr == 0) ib = i;
02801       if (iordr != 0) ia = i;
02802       (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
02803       SideVisibilityEncode(iopt, ab[jphi - 1]*kRad, ab[jphi + 3]*kRad, fAphi[i - 1]);
02804    }
02805 
02806    //       F I N D   O R D E R   A L O N G   Z
02807    incrz = 1;
02808    iz1 = 1;
02809    view->FindNormal(0, 0, 1, z);
02810    if ((z <= 0 && iopt == 1) || (z > 0 && iopt == 2)) {
02811       incrz = -1;
02812       iz1 = nz;
02813    }
02814    iz2 = nz - iz1 + 1;
02815 
02816    //       D R A W   S T A C K   O F   L E G O - P L O T S
02817    incr = 1;
02818    iphi = iphi1;
02819 L100:
02820    if (iphi > nphi) goto L400;
02821    //     D E C O D E   V I S I B I L I T Y   O F   S I D E S
02822    idummy = 0;
02823    SideVisibilityDecode(fAphi[iphi - 1], ivis[4], ivis[1], ivis[5], ivis[3], ivis[0], ivis[2], idummy);
02824    for (iz = iz1; incrz < 0 ? iz >= iz2 : iz <= iz2; iz += incrz) {
02825       if (iordr == 0) {ia = iz;   ib = iphi;}
02826       else            {ia = iphi; ib = iz;}
02827       (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
02828       if (nv < 2 || nv > vSize) continue;
02829       icodes[0] = ia;
02830       icodes[1] = ib;
02831       for (i = 1; i <= 4; ++i) {
02832          j = i;
02833          if (iordr != 0 && i == 2) j = 4;
02834          if (iordr != 0 && i == 4) j = 2;
02835          cosphi[j - 1] = TMath::Cos(ab[jphi + 2*i - 3]*kRad);
02836          sinphi[j - 1] = TMath::Sin(ab[jphi + 2*i - 3]*kRad);
02837          xyz[j*3 - 1] = ab[jz + 2*i - 3];
02838          xyz[(j + 4)*3 - 1] = ab[jz + 2*i - 3];
02839       }
02840    //      D R A W   S T A C K
02841       for (iv = 1; iv < nv; ++iv) {
02842          for (i = 1; i <= 4; ++i) {
02843             xyz[i*3 - 3] = v[iv - 1]*cosphi[i - 1];
02844             xyz[i*3 - 2] = v[iv - 1]*sinphi[i - 1];
02845             xyz[(i + 4)*3 - 3] = v[iv]*cosphi[i - 1];
02846             xyz[(i + 4)*3 - 2] = v[iv]*sinphi[i - 1];
02847          }
02848          if (v[iv - 1] >= v[iv]) continue;
02849          icodes[2] = iv;
02850          for (i = 1; i <= 4; ++i) {
02851             if (ivis[i - 1] == 0) continue;
02852             k1 = i;
02853             k2 = i - 1;
02854             if (i == 1) k2 = 4;
02855             iface[0] = k1;
02856             iface[1] = k2;
02857             iface[2] = k2 + 4;
02858             iface[3] = k1 + 4;
02859             tface[0] = tt[k1 + (iv << 2) - 5];
02860             tface[1] = tt[k2 + (iv << 2) - 5];
02861             tface[2] = tt[k2 + ((iv + 1) << 2) - 5];
02862             tface[3] = tt[k1 + ((iv + 1) << 2) - 5];
02863             icodes[3] = i;
02864             (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
02865          }
02866       }
02867    //       D R A W   B O T T O M   F A C E
02868       if (ivis[4] != 0 && v[0] > 0) {
02869          icodes[2] = 1;
02870          icodes[3] = 5;
02871          for (i = 1; i <= 4; ++i) {
02872             xyz[i*3 - 3] = v[0]*cosphi[i - 1];
02873             xyz[i*3 - 2] = v[0]*sinphi[i - 1];
02874             iface[i - 1] = i;
02875             tface[i - 1] = tt[i - 1];
02876          }
02877          (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
02878       }
02879    //      D R A W   T O P   F A C E
02880       if (ivis[5] != 0 && v[nv - 1] > 0) {
02881          icodes[2] = nv - 1;
02882          icodes[3] = 6;
02883          for (i = 1; i <= 4; ++i) {
02884             iface[i - 1] = 5 - i + 4;
02885             tface[i - 1] = tt[5 - i + (nv << 2) - 5];
02886          }
02887          Int_t cs = fColorTop;
02888          if ( nv > 2 && (v[nv-1] == v[nv-2])) {
02889             for (iv = nv-1; iv>2; iv--) {
02890                if (v[nv-1] == v[iv-1]) fColorTop = fColorMain[iv-2];
02891             }
02892          }
02893          (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
02894          fColorTop = cs;
02895       }
02896    }
02897    //      N E X T   P H I
02898 L400:
02899    iphi += incr;
02900    if (iphi == 0)     iphi = kphi;
02901    if (iphi > kphi)   iphi = 1;
02902    if (iphi != iphi2) goto L100;
02903    if (incr == 0) {
02904       if (vSize > kVSizeMax) {
02905          delete [] v;
02906          delete [] tt;
02907       }
02908       return;
02909    }
02910    if (incr < 0) {
02911       incr = 0;
02912       goto L100;
02913    }
02914    incr = -1;
02915    iphi = iphi1;
02916    goto L400;
02917 }
02918 
02919 
02920 //______________________________________________________________________________
02921 void TPainter3dAlgorithms::LegoSpherical(Int_t ipsdr, Int_t iordr, Int_t na, Int_t nb, const char *chopt)
02922 {
02923    // Draw stack of lego-plots spheric coordinates
02924    //
02925    //    Input: IPSDR - pseudo-rapidity flag
02926    //           IORDR - order of variables (0 - THETA,PHI; 1 - PHI,THETA)
02927    //           NA    - number of steps along 1st variable
02928    //           NB    - number of steps along 2nd variable
02929    //
02930    //           FUN(IA,IB,NV,AB,V,TT) - external routine
02931    //             IA      - cell number for 1st variable
02932    //             IB      - cell number for 2nd variable
02933    //             NV      - number of values for given cell
02934    //             AB(2,4) - coordinates of the cell corners
02935    //             V(NV)   - cell values
02936    //             TT(4,*) - additional function
02937    //
02938    //           DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
02939    //             ICODES(*) - set of codes for this face
02940    //               ICODES(1) - IA
02941    //               ICODES(2) - IB
02942    //               ICODES(3) - IV
02943    //               ICODES(4) - side: 1,2,3,4 - ordinary sides
02944    //                                 5-bottom,6-top
02945    //             XYZ(3,*)  - coordinates of nodes
02946    //             NP        - number of nodes in face
02947    //             IFACE(NP) - face
02948    //             T(NP)     - additional function
02949    //
02950    //           CHOPT       - options: 'BF' - from BACK to FRONT
02951    //                                  'FB' - from FRONT to BACK
02952 
02953    Int_t iphi, jphi, kphi, incr, nphi, ivis[6], iopt, iphi1, iphi2, iface[4], i, j;
02954    Double_t tface[4], costh[4];
02955    Double_t sinth[4];
02956    Int_t k1, k2, ia, ib, incrth, ith, jth, kth, nth, mth, ith1, ith2, nv;
02957    Double_t ab[8];       // was [2][4]
02958    Double_t th;
02959    Int_t iv, icodes[4];
02960    Double_t zn, cosphi[4];
02961    Double_t sinphi[4], th1, th2, phi;
02962    Double_t xyz[24];     // was [3][8]
02963    Double_t phi1, phi2;
02964    ia = ib = 0;
02965    TView *view = 0;
02966 
02967    if (gPad) view = gPad->GetView();
02968    if (!view) {
02969       Error("LegoSpherical", "no TView in current pad");
02970       return;
02971    }
02972 
02973    if (iordr == 0) {
02974       jth  = 1;
02975       jphi = 2;
02976       nth  = na;
02977       nphi = nb;
02978    } else {
02979       jth  = 2;
02980       jphi = 1;
02981       nth  = nb;
02982       nphi = na;
02983    }
02984    if (nth > 180) {
02985       Error("LegoSpherical", "too many THETA sectors (%d)", nth);
02986       return;
02987    }
02988    if (nphi > 180) {
02989       Error("LegoSpherical", "too many PHI sectors (%d)", nphi);
02990       return;
02991    }
02992    iopt = 2;
02993    if (*chopt == 'B' || *chopt == 'b') iopt = 1;
02994 
02995    // Allocate v and tt arrays
02996    Double_t *v, *tt;
02997    Int_t vSize = fNStack+2;
02998    if (vSize > kVSizeMax) {
02999       v  = new Double_t[vSize];
03000       tt = new Double_t[4*vSize];
03001    } else {
03002       vSize = kVSizeMax;
03003       v  = &gV[0];
03004       tt = &gTT[0];
03005    }
03006 
03007    //       P R E P A R E   P H I   A R R A Y
03008    //       F I N D    C R I T I C A L   P H I   S E C T O R S
03009    nv  = 0;
03010    kphi = nphi;
03011    mth = nth / 2;
03012    if (mth == 0)    mth = 1;
03013    if (iordr == 0) ia = mth;
03014    if (iordr != 0) ib = mth;
03015    for (i = 1; i <= nphi; ++i) {
03016       if (iordr == 0) ib = i;
03017       if (iordr != 0) ia = i;
03018       (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
03019       if (i == 1)  fAphi[0] = ab[jphi - 1];
03020       fAphi[i - 1] = (fAphi[i - 1] + ab[jphi - 1]) / (float)2.;
03021       fAphi[i] = ab[jphi + 3];
03022    }
03023    view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
03024 
03025    //       P R E P A R E   T H E T A   A R R A Y
03026    if (iordr == 0) ib = 1;
03027    if (iordr != 0) ia = 1;
03028    for (i = 1; i <= nth; ++i) {
03029       if (iordr == 0) ia = i;
03030       if (iordr != 0) ib = i;
03031       (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
03032       if (i == 1) fAphi[0] = ab[jth - 1];
03033       fAphi[i - 1] = (fAphi[i - 1] + ab[jth - 1]) / (float)2.;
03034       fAphi[i] = ab[jth + 3];
03035    }
03036 
03037    //       D R A W   S T A C K   O F   L E G O - P L O T S
03038    kth = nth;
03039 
03040    incr = 1;
03041    iphi = iphi1;
03042 L100:
03043    if (iphi > nphi) goto L500;
03044 
03045    //      F I N D    C R I T I C A L   T H E T A   S E C T O R S
03046    if (!iordr) {ia = mth;        ib = iphi; }
03047    else        {ia = iphi;ib = mth;  }
03048    (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
03049    phi = (ab[jphi - 1] + ab[jphi + 3]) / (float)2.;
03050    view->FindThetaSectors(iopt, phi, kth, fAphi, ith1, ith2);
03051    incrth = 1;
03052    ith = ith1;
03053 L200:
03054    if (ith > nth)   goto L400;
03055    if (iordr == 0) ia = ith;
03056    if (iordr != 0) ib = ith;
03057    (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
03058    if (nv < 2 || nv > vSize) goto L400;
03059 
03060    //      D E F I N E   V I S I B I L I T Y   O F   S I D E S
03061    for (i = 1; i <= 6; ++i) ivis[i - 1] = 0;
03062 
03063    phi1 = kRad*ab[jphi - 1];
03064    phi2 = kRad*ab[jphi + 3];
03065    th1  = kRad*ab[jth - 1];
03066    th2  = kRad*ab[jth + 3];
03067    view->FindNormal(TMath::Sin(phi1), -TMath::Cos(phi1), 0, zn);
03068    if (zn > 0) ivis[1] = 1;
03069    view->FindNormal(-TMath::Sin(phi2), TMath::Cos(phi2), 0, zn);
03070    if (zn > 0) ivis[3] = 1;
03071    phi = (phi1 + phi2) / (float)2.;
03072    view->FindNormal(-TMath::Cos(phi)*TMath::Cos(th1), -TMath::Sin(phi)*TMath::Cos(th1), TMath::Sin(th1), zn);
03073    if (zn > 0) ivis[0] = 1;
03074    view->FindNormal(TMath::Cos(phi)*TMath::Cos(th2), TMath::Sin(phi)*TMath::Cos(th2), -TMath::Sin(th2), zn);
03075    if (zn > 0) ivis[2] = 1;
03076    th = (th1 + th2) / (float)2.;
03077    if (ipsdr == 1) th = kRad*90;
03078    view->FindNormal(TMath::Cos(phi)*TMath::Sin(th), TMath::Sin(phi)*TMath::Sin(th), TMath::Cos(th), zn);
03079    if (zn < 0) ivis[4] = 1;
03080    if (zn > 0) ivis[5] = 1;
03081 
03082    //      D R A W   S T A C K
03083    icodes[0] = ia;
03084    icodes[1] = ib;
03085    for (i = 1; i <= 4; ++i) {
03086       j = i;
03087       if (iordr != 0 && i == 2) j = 4;
03088       if (iordr != 0 && i == 4) j = 2;
03089       costh[j - 1]  = TMath::Cos(kRad*ab[jth + 2*i - 3]);
03090       sinth[j - 1]  = TMath::Sin(kRad*ab[jth + 2*i - 3]);
03091       cosphi[j - 1] = TMath::Cos(kRad*ab[jphi + 2*i - 3]);
03092       sinphi[j - 1] = TMath::Sin(kRad*ab[jphi + 2*i - 3]);
03093    }
03094    for (iv = 1; iv < nv; ++iv) {
03095       if (ipsdr == 1) {
03096          for (i = 1; i <= 4; ++i) {
03097             xyz[i*3 - 3] = v[iv - 1]*cosphi[i - 1];
03098             xyz[i*3 - 2] = v[iv - 1]*sinphi[i - 1];
03099             xyz[i*3 - 1] = v[iv - 1]*costh[i - 1] / sinth[i - 1];
03100             xyz[(i + 4)*3 - 3] = v[iv]*cosphi[i - 1];
03101             xyz[(i + 4)*3 - 2] = v[iv]*sinphi[i - 1];
03102             xyz[(i + 4)*3 - 1] = v[iv]*costh[i - 1] / sinth[i - 1];
03103          }
03104       } else {
03105          for (i = 1; i <= 4; ++i) {
03106             xyz[i*3 - 3] = v[iv - 1]*sinth[i - 1]*cosphi[i - 1];
03107             xyz[i*3 - 2] = v[iv - 1]*sinth[i - 1]*sinphi[i - 1];
03108             xyz[i*3 - 1] = v[iv - 1]*costh[i - 1];
03109             xyz[(i + 4)*3 - 3] = v[iv]*sinth[i - 1]*cosphi[i - 1];
03110             xyz[(i + 4)*3 - 2] = v[iv]*sinth[i - 1]*sinphi[i - 1];
03111             xyz[(i + 4)*3 - 1] = v[iv]*costh[i - 1];
03112          }
03113       }
03114       if (v[iv - 1] >= v[iv]) continue;
03115       icodes[2] = iv;
03116       for (i = 1; i <= 4; ++i) {
03117          if (ivis[i - 1] == 0) continue;
03118          k1 = i - 1;
03119          if (i == 1) k1 = 4;
03120          k2 = i;
03121          iface[0] = k1;
03122          iface[1] = k2;
03123          iface[2] = k2 + 4;
03124          iface[3] = k1 + 4;
03125          tface[0] = tt[k1 + (iv << 2) - 5];
03126          tface[1] = tt[k2 + (iv << 2) - 5];
03127          tface[2] = tt[k2 + ((iv + 1) << 2) - 5];
03128          tface[3] = tt[k1 + ((iv + 1) << 2) - 5];
03129          icodes[3] = i;
03130          (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
03131       }
03132    }
03133    //      D R A W   B O T T O M   F A C E
03134    if (ivis[4] != 0 && v[0] > 0) {
03135       icodes[2] = 1;
03136       icodes[3] = 5;
03137       for (i = 1; i <= 4; ++i) {
03138          if (ipsdr == 1) {
03139             xyz[i*3 - 3] = v[0]*cosphi[i - 1];
03140             xyz[i*3 - 2] = v[0]*sinphi[i - 1];
03141             xyz[i*3 - 1] = v[0]*costh[i - 1] / sinth[i - 1];
03142          } else {
03143             xyz[i*3 - 3] = v[0]*sinth[i - 1]*cosphi[i - 1];
03144             xyz[i*3 - 2] = v[0]*sinth[i - 1]*sinphi[i - 1];
03145             xyz[i*3 - 1] = v[0]*costh[i - 1];
03146          }
03147          iface[i - 1] = 5 - i;
03148          tface[i - 1] = tt[5 - i - 1];
03149       }
03150       (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
03151    }
03152    //      D R A W   T O P   F A C E
03153    if (ivis[5] != 0 && v[nv - 1] > 0) {
03154       icodes[2] = nv - 1;
03155       icodes[3] = 6;
03156       for (i = 1; i <= 4; ++i) {
03157          iface[i - 1] = i + 4;
03158          tface[i - 1] = tt[i + 4 + 2*nv - 5];
03159       }
03160       Int_t cs = fColorTop;
03161       if ( nv > 2 && (v[nv-1] == v[nv-2])) {
03162          for (iv = nv-1; iv>2; iv--) {
03163             if (v[nv-1] == v[iv-1]) fColorTop = fColorMain[iv-2];
03164          }
03165       }
03166       (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
03167       fColorTop = cs;
03168    }
03169    //      N E X T   T H E T A
03170 L400:
03171    ith += incrth;
03172    if (ith == 0)    ith = kth;
03173    if (ith > kth)   ith = 1;
03174    if (ith != ith2) goto L200;
03175    if (incrth == 0) goto L500;
03176    if (incrth < 0) {
03177       incrth = 0;
03178       goto L200;
03179    }
03180    incrth = -1;
03181    ith = ith1;
03182    goto L400;
03183    //      N E X T   P H I
03184 L500:
03185    iphi += incr;
03186    if (iphi == 0)     iphi = kphi;
03187    if (iphi > kphi)   iphi = 1;
03188    if (iphi != iphi2) goto L100;
03189    if (incr == 0) {
03190       if (vSize > kVSizeMax) {
03191          delete [] v;
03192          delete [] tt;
03193       }
03194       return;
03195    }
03196    if (incr < 0) {
03197       incr = 0;
03198       goto L100;
03199    }
03200    incr = -1;
03201    iphi = iphi1;
03202    goto L500;
03203 }
03204 
03205 
03206 //______________________________________________________________________________
03207 void TPainter3dAlgorithms::LightSource(Int_t nl, Double_t yl, Double_t xscr,
03208                                        Double_t yscr, Double_t zscr, Int_t &irep)
03209 {
03210    // Set light source
03211    //
03212    //    Input: NL   - source number: -1 off all light sources
03213    //                                  0 set diffused light
03214    //           YL   - intensity of the light source
03215    //           XSCR |
03216    //           YSCR  > direction of the light (in respect of the screen)
03217    //           ZSCR |
03218    //
03219    //    Output: IREP   - reply : 0 - O.K.
03220    //                            -1 - error in light sources definition:
03221    //                                 negative intensity
03222    //                                 source number greater than max
03223    //                                 light source is placed at origin
03224 
03225    /* Local variables */
03226    Int_t i;
03227    Double_t s;
03228 
03229    irep = 0;
03230    if (nl < 0)       goto L100;
03231    else if (nl == 0) goto L200;
03232    else              goto L300;
03233 
03234    //          S W I T C H   O F F   L I G H T S
03235 L100:
03236    fLoff = 1;
03237    fYdl = 0;
03238    for (i = 1; i <= 4; ++i) {
03239       fYls[i - 1] = 0;
03240    }
03241    return;
03242    //          S E T   D I F F U S E D   L I G H T
03243 L200:
03244    if (yl < 0) {
03245       Error("LightSource", "negative light intensity");
03246       irep = -1;
03247       return;
03248    }
03249    fYdl = yl;
03250    goto L400;
03251    //          S E T   L I G H T   S O U R C E
03252 L300:
03253    if (nl > 4 || yl < 0) {
03254       Error("LightSource", "illegal light source number (nl=%d, yl=%f)", nl, yl);
03255       irep = -1;
03256       return;
03257    }
03258    s = TMath::Sqrt(xscr*xscr + yscr*yscr + zscr*zscr);
03259    if (s == 0) {
03260       Error("LightSource", "light source is placed at origin");
03261       irep = -1;
03262       return;
03263    }
03264    fYls[nl - 1] = yl;
03265    fVls[nl*3 - 3] = xscr / s;
03266    fVls[nl*3 - 2] = yscr / s;
03267    fVls[nl*3 - 1] = zscr / s;
03268    //         C H E C K   L I G H T S
03269 L400:
03270    fLoff = 0;
03271    if (fYdl != 0) return;
03272    for (i = 1; i <= 4; ++i) {
03273       if (fYls[i - 1] != 0) return;
03274    }
03275    fLoff = 1;
03276 }
03277 
03278 
03279 //______________________________________________________________________________
03280 void TPainter3dAlgorithms::Luminosity(Double_t *anorm, Double_t &flum)
03281 {
03282    // Find surface luminosity at given point
03283    //                                         --
03284    //    Lightness model formula: Y = YD*QA + > YLi*(QD*cosNi+QS*cosRi)
03285    //                                         --
03286    //
03287    //            B1     = VN(3)*VL(2) - VN(2)*VL(3)
03288    //            B2     = VN(1)*VL(3) - VN(3)*VL(1)
03289    //            B3     = VN(2)*VL(1) - VN(1)*VL(2)
03290    //            B4     = VN(1)*VL(1) + VN(2)*VL(2) + VN(3)*VL(3)
03291    //            VR(1)  = VN(3)*B2 - VN(2)*B3 + VN(1)*B4
03292    //            VR(2)  =-VN(3)*B1 + VN(1)*B3 + VN(2)*B4
03293    //            VR(3)  = VN(2)*B1 - VN(1)*B2 + VN(3)*B4
03294    //            S      = SQRT(VR(1)*VR(1)+VR(2)*VR(2)+VR(3)*VR(3))
03295    //            VR(1)  = VR(1)/S
03296    //            VR(2)  = VR(2)/S
03297    //            VR(3)  = VR(3)/S
03298    //            COSR   = VR(1)*0. + VR(2)*0. + VR(3)*1.
03299    //
03300    //    References: WCtoNDC
03301    //
03302    //    Input: ANORM(3) - surface normal at given point
03303    //
03304    //    Output: FLUM - luminosity
03305 
03306    /* Local variables */
03307    Double_t cosn, cosr;
03308    Int_t i;
03309    Double_t s, vl[3], vn[3];
03310    TView *view = 0;
03311 
03312    if (gPad) view = gPad->GetView();
03313    if (!view) return;
03314 
03315    /* Parameter adjustments */
03316    --anorm;
03317 
03318    flum = 0;
03319    if (fLoff != 0) return;
03320 
03321    //          T R A N S F E R   N O R M A L  T O   SCREEN COORDINATES
03322    view->NormalWCtoNDC(&anorm[1], vn);
03323    s = TMath::Sqrt(vn[0]*vn[0] + vn[1]*vn[1] + vn[2]*vn[2]);
03324    if (vn[2] < 0) s = -(Double_t)s;
03325    vn[0] /= s;
03326    vn[1] /= s;
03327    vn[2] /= s;
03328 
03329    //          F I N D   L U M I N O S I T Y
03330    flum = fYdl*fQA;
03331    for (i = 1; i <= 4; ++i) {
03332       if (fYls[i - 1] <= 0) continue;
03333       vl[0] = fVls[i*3 - 3];
03334       vl[1] = fVls[i*3 - 2];
03335       vl[2] = fVls[i*3 - 1];
03336       cosn = vl[0]*vn[0] + vl[1]*vn[1] + vl[2]*vn[2];
03337       if (cosn < 0) continue;
03338       cosr = vn[1]*(vn[2]*vl[1] - vn[1]*vl[2]) - vn[0]*(vn[0]*vl[2]
03339              - vn[2]*vl[0]) + vn[2]*cosn;
03340       if (cosr <= 0) cosr = 0;
03341       flum += fYls[i - 1]*(fQD*cosn + fQS*TMath::Power(cosr, fNqs));
03342    }
03343 }
03344 
03345 
03346 //______________________________________________________________________________
03347 void TPainter3dAlgorithms::ModifyScreen(Double_t *r1, Double_t *r2)
03348 {
03349    // Modify SCREEN
03350    //
03351    //    Input: R1(3) - 1-st point of the line
03352    //           R2(3) - 2-nd point of the line
03353 
03354    /* Local variables */
03355    Int_t i, i1, i2;
03356    Double_t x1, x2, y1, y2, dy, ww, yy1, yy2, *tn;
03357 
03358    /* Parameter adjustments */
03359    --r2;
03360    --r1;
03361 
03362    TView *view = 0;
03363    if (gPad) view = gPad->GetView();
03364 
03365    if (view) {
03366       tn = view->GetTN();
03367       x1 = tn[0]*r1[1] + tn[1]*r1[2] + tn[2]*r1[3] + tn[3];
03368       x2 = tn[0]*r2[1] + tn[1]*r2[2] + tn[2]*r2[3] + tn[3];
03369       y1 = tn[4]*r1[1] + tn[5]*r1[2] + tn[6]*r1[3] + tn[7];
03370       y2 = tn[4]*r2[1] + tn[5]*r2[2] + tn[6]*r2[3] + tn[7];
03371    } else {
03372       Error("ModifyScreen", "no TView in current pad");
03373       return;
03374    }
03375 
03376    if (x1 >= x2) {
03377       ww = x1;
03378       x1 = x2;
03379       x2 = ww;
03380       ww = y1;
03381       y1 = y2;
03382       y2 = ww;
03383    }
03384    i1 = Int_t((x1 - fX0) / fDX) + 15;
03385    i2 = Int_t((x2 - fX0) / fDX) + 15;
03386    if (i1 == i2) return;
03387 
03388    //          M O D I F Y   B O U N D A R I E S   OF THE SCREEN
03389    dy = (y2 - y1) / (i2 - i1);
03390    for (i = i1; i <= i2 - 1; ++i) {
03391       yy1 = y1 + dy*(i - i1);
03392       yy2 = yy1 + dy;
03393       if (fD[2*i - 2] > yy1) fD[2*i - 2] = yy1;
03394       if (fD[2*i - 1] > yy2) fD[2*i - 1] = yy2;
03395       if (fU[2*i - 2] < yy1) fU[2*i - 2] = yy1;
03396       if (fU[2*i - 1] < yy2) fU[2*i - 1] = yy2;
03397    }
03398 }
03399 
03400 
03401 //______________________________________________________________________________
03402 void TPainter3dAlgorithms::SetDrawFace(DrawFaceFunc_t drface)
03403 {
03404    // Store pointer to current algorithm to draw faces
03405 
03406    fDrawFace = drface;
03407 }
03408 
03409 
03410 //______________________________________________________________________________
03411 void TPainter3dAlgorithms::SetLegoFunction(LegoFunc_t fun)
03412 {
03413    // Store pointer to current lego function
03414 
03415    fLegoFunction = fun;
03416 }
03417 
03418 
03419 //______________________________________________________________________________
03420 void TPainter3dAlgorithms::SetSurfaceFunction(SurfaceFunc_t fun)
03421 {
03422    // Store pointer to current surface function
03423 
03424    fSurfaceFunction = fun;
03425 }
03426 
03427 
03428 //______________________________________________________________________________
03429 void TPainter3dAlgorithms::SetF3(TF3 *f3)
03430 {
03431    // Static function
03432    // Store pointer to current implicit function
03433 
03434    fgCurrentF3 = f3;
03435 }
03436 
03437 
03438 //______________________________________________________________________________
03439 void TPainter3dAlgorithms::SetF3ClippingBoxOff()
03440 {
03441    // static function
03442    // Set the implicit function clipping box "off".
03443 
03444    fgF3Clipping = 0;
03445 }
03446 
03447 
03448 //______________________________________________________________________________
03449 void TPainter3dAlgorithms::SetF3ClippingBoxOn(Double_t xclip,
03450                                               Double_t yclip, Double_t zclip)
03451 {
03452    // static function
03453    // Set the implicit function clipping box "on" and define the clipping box.
03454    // xclip, yclip and zclip is a point within the function range. All the
03455    // function value having x<=xclip and y<=yclip and z>=zclip are clipped.
03456 
03457    fgF3Clipping = 1;
03458    fgF3XClip = xclip;
03459    fgF3YClip = yclip;
03460    fgF3ZClip = zclip;
03461 }
03462 
03463 
03464 //______________________________________________________________________________
03465 void TPainter3dAlgorithms::SetColorDark(Color_t color, Int_t n)
03466 {
03467    // Store dark color for stack number n
03468 
03469    if (n < 0 ) {fColorBottom = color; return;}
03470    if (n > fNStack ) {fColorTop  = color; return;}
03471    fColorDark[n] = color;
03472 }
03473 
03474 
03475 //______________________________________________________________________________
03476 void TPainter3dAlgorithms::SetColorMain(Color_t color, Int_t n)
03477 {
03478    // Store color for stack number n
03479 
03480    if (n < 0 ) {fColorBottom = color; return;}
03481    if (n > fNStack ) {fColorTop = color; return;}
03482    fColorMain[n] = color;
03483 }
03484 
03485 
03486 //______________________________________________________________________________
03487 void TPainter3dAlgorithms::SideVisibilityDecode(Double_t val, Int_t &iv1, Int_t &iv2, Int_t &iv3, Int_t &iv4, Int_t &iv5, Int_t &iv6, Int_t &ir)
03488 {
03489    // Decode side visibilities and order along R for sector
03490    //
03491    //    Input: VAL - encoded value
03492    //
03493    //    Output: IV1 ... IV6  - visibility of the sides
03494    //            IR           - increment along R
03495 
03496    Int_t ivis[6], i, k, num;
03497 
03498    k = Int_t(val);
03499    num = 128;
03500    for (i = 1; i <= 6; ++i) {
03501       ivis[i - 1] = 0;
03502       num /= 2;
03503       if (k < num) continue;
03504       k -= num;
03505       ivis[i - 1] = 1;
03506    }
03507    ir = 1;
03508    if (k == 1) ir = -1;
03509    iv1 = ivis[5];
03510    iv2 = ivis[4];
03511    iv3 = ivis[3];
03512    iv4 = ivis[2];
03513    iv5 = ivis[1];
03514    iv6 = ivis[0];
03515 }
03516 
03517 
03518 //______________________________________________________________________________
03519 void TPainter3dAlgorithms::SideVisibilityEncode(Int_t iopt, Double_t phi1, Double_t phi2, Double_t &val)
03520 {
03521    // Encode side visibilities and order along R for sector
03522    //
03523    //    Input: IOPT - options: 1 - from BACK to FRONT 'BF'
03524    //                           2 - from FRONT to BACK 'FB'
03525    //           PHI1 - 1st phi of sector
03526    //           PHI2 - 2nd phi of sector
03527    //
03528    //    Output: VAL - encoded value
03529 
03530    /* Local variables */
03531    Double_t zn, phi;
03532    Int_t k = 0;
03533    TView *view = 0;
03534 
03535    if (gPad) view = gPad->GetView();
03536    if (!view) {
03537       Error("SideVisibilityEncode", "no TView in current pad");
03538       return;
03539    }
03540 
03541    view->FindNormal(0, 0, 1, zn);
03542    if (zn > 0) k += 64;
03543    if (zn < 0) k += 32;
03544    view->FindNormal(-TMath::Sin(phi2), TMath::Cos(phi2), 0, zn);
03545    if (zn > 0) k += 16;
03546    view->FindNormal(TMath::Sin(phi1), -TMath::Cos(phi1), 0, zn);
03547    if (zn > 0) k += 4;
03548    phi = (phi1 + phi2) / (float)2.;
03549    view->FindNormal(TMath::Cos(phi), TMath::Sin(phi), 0, zn);
03550    if (zn > 0) k += 8;
03551    if (zn < 0) k += 2;
03552    if ((zn <= 0 && iopt == 1) || (zn > 0 && iopt == 2)) ++k;
03553    val = Double_t(k);
03554 }
03555 
03556 
03557 //______________________________________________________________________________
03558 void TPainter3dAlgorithms::Spectrum(Int_t nl, Double_t fmin, Double_t fmax, Int_t ic, Int_t idc, Int_t &irep)
03559 {
03560    // Set Spectrum
03561    //
03562    //    Input: NL   - number of levels
03563    //           FMIN - MIN function value
03564    //           FMAX - MAX function value
03565    //           IC   - initial color index (for 1st level)
03566    //           IDC  - color index increment
03567    //
03568    //    Output: IREP - reply: 0 O.K.
03569    //                         -1 error in parameters
03570    //                            F_max less than F_min
03571    //                            illegal number of levels
03572    //                            initial color index is negative
03573    //                            color index increment must be positive
03574 
03575    static const char *where = "Spectrum";
03576 
03577    /* Local variables */
03578    Double_t delf;
03579    Int_t i;
03580 
03581    irep = 0;
03582    if (nl == 0) {fNlevel = 0; return; }
03583 
03584    //          C H E C K   P A R A M E T E R S
03585    if (fmax <= fmin) {
03586       Error(where, "fmax (%f) less than fmin (%f)", fmax, fmin);
03587       irep = -1;
03588       return;
03589    }
03590    if (nl < 0 || nl > 256) {
03591       Error(where, "illegal number of levels (%d)", nl);
03592       irep = -1;
03593       return;
03594    }
03595    if (ic < 0) {
03596       Error(where, "initial color index is negative");
03597       irep = -1;
03598       return;
03599    }
03600    if (idc < 0) {
03601       Error(where, "color index increment must be positive");
03602       irep = -1;
03603    }
03604 
03605    //          S E T  S P E C T R
03606    const Int_t kMAXCOL = 50;
03607    delf    = (fmax - fmin) / nl;
03608    fNlevel = -(nl + 1);
03609    for (i = 1; i <= nl+1; ++i) {
03610       fFunLevel[i - 1] = fmin + (i - 1)*delf;
03611       fColorLevel[i] = ic + (i - 1)*idc;
03612       if (ic <= kMAXCOL && fColorLevel[i] > kMAXCOL) fColorLevel[i] -= kMAXCOL;
03613    }
03614    fColorLevel[0] = fColorLevel[1];
03615    fColorLevel[nl + 1] = fColorLevel[nl];
03616 }
03617 
03618 
03619 //______________________________________________________________________________
03620 void TPainter3dAlgorithms::SurfaceCartesian(Double_t ang, Int_t nx, Int_t ny, const char *chopt)
03621 {
03622    // Draw surface in cartesian coordinate system
03623    //
03624    //    Input: ANG      - angle between X ang Y
03625    //           NX       - number of steps along X
03626    //           NY       - number of steps along Y
03627    //
03628    //           FUN(IX,IY,F,T) - external routine
03629    //             IX     - X number of the cell
03630    //             IY     - Y number of the cell
03631    //             F(3,4) - face which corresponds to the cell
03632    //             T(4)   - additional function (for example: temperature)
03633    //
03634    //           DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
03635    //             ICODES(*) - set of codes for this face
03636    //               ICODES(1) - IX
03637    //               ICODES(2) - IY
03638    //             NP        - number of nodes in face
03639    //             IFACE(NP) - face
03640    //             T(NP)     - additional function
03641    //
03642    //           CHOPT - options: 'BF' - from BACK to FRONT
03643    //                            'FB' - from FRONT to BACK
03644 
03645    /* Initialized data */
03646 
03647    Int_t iface[4] = { 1,2,3,4 };
03648 
03649    /* Local variables */
03650    Double_t cosa, sina, f[12]        /* was [3][4] */;
03651    Int_t i, incrx, incry, i1, ix, iy;
03652    Double_t tt[4];
03653    Int_t icodes[2], ix1, iy1, ix2, iy2;
03654    Double_t xyz[12]        /* was [3][4] */;
03655    Double_t *tn;
03656 
03657    sina = TMath::Sin(ang*kRad);
03658    cosa = TMath::Cos(ang*kRad);
03659 
03660    //          F I N D   T H E   M O S T   L E F T   P O I N T
03661    TView *view = 0;
03662 
03663    if (gPad) view = gPad->GetView();
03664    if (!view) {
03665       Error("SurfaceCartesian", "no TView in current pad");
03666       return;
03667    }
03668    tn = view->GetTN();
03669 
03670    i1 = 1;
03671    if (tn[0] < 0) i1 = 2;
03672    if (tn[0]*cosa + tn[1]*sina < 0) i1 = 5 - i1;
03673 
03674    //          D E F I N E   O R D E R   O F   D R A W I N G
03675    if (*chopt == 'B' || *chopt == 'b') {incrx = -1; incry = -1;}
03676    else                                {incrx = 1;  incry = 1;}
03677    if (i1 == 1 || i1 == 2) incrx = -incrx;
03678    if (i1 == 2 || i1 == 3) incry = -incry;
03679    ix1 = 1;
03680    iy1 = 1;
03681    if (incrx < 0) ix1 = nx;
03682    if (incry < 0) iy1 = ny;
03683    ix2 = nx - ix1 + 1;
03684    iy2 = ny - iy1 + 1;
03685 
03686    //          D R A W   S U R F A C E
03687    THistPainter *painter = (THistPainter*)gCurrentHist->GetPainter();
03688    for (iy = iy1; incry < 0 ? iy >= iy2 : iy <= iy2; iy += incry) {
03689       for (ix = ix1; incrx < 0 ? ix >= ix2 : ix <= ix2; ix += incrx) {
03690          if (!painter->IsInside(ix,iy)) continue;
03691          (this->*fSurfaceFunction)(ix, iy, f, tt);
03692          for (i = 1; i <= 4; ++i) {
03693             xyz[i*3 - 3] = f[i*3 - 3] + f[i*3 - 2]*cosa;
03694             xyz[i*3 - 2] = f[i*3 - 2]*sina;
03695             xyz[i*3 - 1] = f[i*3 - 1];
03696             // added EJB -->
03697             Double_t al, ab;
03698             if (Hoption.Proj == 1 ) {
03699                THistPainter::ProjectAitoff2xy(xyz[i*3 - 3], xyz[i*3 - 2], al, ab);
03700                xyz[i*3 - 3] = al;
03701                xyz[i*3 - 2] = ab;
03702             } else if (Hoption.Proj == 2 ) {
03703                THistPainter::ProjectMercator2xy(xyz[i*3 - 3], xyz[i*3 - 2], al, ab);
03704                xyz[i*3 - 3] = al;
03705                xyz[i*3 - 2] = ab;
03706             } else if (Hoption.Proj == 3) {
03707                THistPainter::ProjectSinusoidal2xy(xyz[i*3 - 3], xyz[i*3 - 2], al, ab);
03708                xyz[i*3 - 3] = al;
03709                xyz[i*3 - 2] = ab;
03710             } else if (Hoption.Proj == 4) {
03711                THistPainter::ProjectParabolic2xy(xyz[i*3 - 3], xyz[i*3 - 2], al, ab);
03712                xyz[i*3 - 3] = al;
03713                xyz[i*3 - 2] = ab;
03714             }
03715          }
03716          icodes[0] = ix;
03717          icodes[1] = iy;
03718          (this->*fDrawFace)(icodes, xyz, 4, iface, tt);
03719       }
03720    }
03721 }
03722 
03723 
03724 //______________________________________________________________________________
03725 void TPainter3dAlgorithms::SurfaceFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
03726 {
03727    // Service function for Surfaces
03728    static Int_t ixadd[4] = { 0,1,1,0 };
03729    static Int_t iyadd[4] = { 0,0,1,1 };
03730 
03731    Double_t rinrad = gStyle->GetLegoInnerR();
03732    Double_t dangle = 10; //Delta angle for Rapidity option
03733    Double_t xval1l, xval2l, yval1l, yval2l;
03734    Double_t xlab1l, xlab2l, ylab1l, ylab2l;
03735    Int_t i, ixa, iya, icx, ixt, iyt;
03736 
03737     /* Parameter adjustments */
03738    --t;
03739    f -= 4;
03740 
03741    ixt = ia + Hparam.xfirst - 1;
03742    iyt = ib + Hparam.yfirst - 1;
03743 
03744    xval1l = Hparam.xmin;
03745    xval2l = Hparam.xmax;
03746    yval1l = Hparam.ymin;
03747    yval2l = Hparam.ymax;
03748 
03749    xlab1l = gCurrentHist->GetXaxis()->GetXmin();
03750    xlab2l = gCurrentHist->GetXaxis()->GetXmax();
03751    if (Hoption.Logx) {
03752       if (xlab2l>0) {
03753          if (xlab1l>0) xlab1l = TMath::Log10(xlab1l);
03754          else          xlab1l = TMath::Log10(0.001*xlab2l);
03755          xlab2l = TMath::Log10(xlab2l);
03756       }
03757    }
03758    ylab1l = gCurrentHist->GetYaxis()->GetXmin();
03759    ylab2l = gCurrentHist->GetYaxis()->GetXmax();
03760    if (Hoption.Logy) {
03761       if (ylab2l>0) {
03762          if (ylab1l>0) ylab1l = TMath::Log10(ylab1l);
03763          else          ylab1l = TMath::Log10(0.001*ylab2l);
03764          ylab2l = TMath::Log10(ylab2l);
03765       }
03766    }
03767 
03768    for (i = 1; i <= 4; ++i) {
03769       ixa = ixadd[i - 1];
03770       iya = iyadd[i - 1];
03771       Double_t xwid = gCurrentHist->GetXaxis()->GetBinWidth(ixt+ixa);
03772       Double_t ywid = gCurrentHist->GetYaxis()->GetBinWidth(iyt+iya);
03773 
03774    //          Compute the cell position in cartesian coordinates
03775    //          and compute the LOG if necessary
03776       f[i*3 + 1] = gCurrentHist->GetXaxis()->GetBinLowEdge(ixt+ixa) + 0.5*xwid;
03777       f[i*3 + 2] = gCurrentHist->GetYaxis()->GetBinLowEdge(iyt+iya) + 0.5*ywid;
03778       if (Hoption.Logx) {
03779          if (f[i*3 + 1] > 0) f[i*3 + 1] = TMath::Log10(f[i*3 + 1]);
03780          else                f[i*3 + 1] = Hparam.xmin;
03781       }
03782       if (Hoption.Logy) {
03783          if (f[i*3 + 2] > 0) f[i*3 + 2] = TMath::Log10(f[i*3 + 2]);
03784          else                f[i*3 + 2] = Hparam.ymin;
03785       }
03786 
03787    //     Transform the cell position in the required coordinate system
03788       if (Hoption.System == kPOLAR) {
03789          f[i*3 + 1] = 360*(f[i*3 + 1] - xlab1l) / (xlab2l - xlab1l);
03790          f[i*3 + 2] = (f[i*3 + 2] - yval1l) / (yval2l - yval1l);
03791       } else if (Hoption.System == kCYLINDRICAL) {
03792          f[i*3 + 1] = 360*(f[i*3 + 1] - xlab1l) / (xlab2l - xlab1l);
03793       } else if (Hoption.System == kSPHERICAL) {
03794          f[i*3 + 1] = 360*(f[i*3 + 1] - xlab1l) / (xlab2l - xlab1l);
03795          f[i*3 + 2] = 360*(f[i*3 + 2] - ylab1l) / (ylab2l - ylab1l);
03796       } else if (Hoption.System == kRAPIDITY) {
03797          f[i*3 + 1] = 360*(f[i*3 + 1] - xlab1l) / (xlab2l - xlab1l);
03798          f[i*3 + 2] = (180 - dangle*2)*(f[i*3 + 2] - ylab1l) / (ylab2l - ylab1l) + dangle;
03799       }
03800 
03801    //          Get the content of the table. If the X index (ICX) is
03802    //          greater than the X size of the table (NCX), that's mean
03803    //          IGTABL tried to close the surface and in this case the
03804    //          first channel should be used. */
03805       icx = ixt + ixa;
03806       if (icx > Hparam.xlast) icx = 1;
03807       f[i*3+3] = Hparam.factor*gCurrentHist->GetCellContent(icx, iyt + iya);
03808       if (Hoption.Logz) {
03809          if (f[i*3+3] > 0) f[i*3+3] = TMath::Log10(f[i*3+3]);
03810          else              f[i*3+3] = Hparam.zmin;
03811          if (f[i*3+3] < Hparam.zmin) f[i*3+3] = Hparam.zmin;
03812          if (f[i*3+3] > Hparam.zmax) f[i*3+3] = Hparam.zmax;
03813       } else {
03814          f[i*3+3] = TMath::Max(Hparam.zmin, f[i*3+3]);
03815          f[i*3+3] = TMath::Min(Hparam.zmax, f[i*3+3]);
03816       }
03817 
03818    // The colors on the surface can represent the content or the errors.
03819    // if (fSumw2.fN) t[i] = gCurrentHist->GetCellError(icx, iyt + iya);
03820    // else           t[i] = f[i * 3 + 3];
03821       t[i] = f[i * 3 + 3];
03822    }
03823 
03824    //          Define the position of the colored contours for SURF3
03825    if (Hoption.Surf == 23) {
03826       for (i = 1; i <= 4; ++i) f[i * 3 + 3] = fRmax[2];
03827    }
03828 
03829    if (Hoption.System == kCYLINDRICAL || Hoption.System == kSPHERICAL || Hoption.System == kRAPIDITY) {
03830       for (i = 1; i <= 4; ++i) {
03831          f[i*3 + 3] = (1 - rinrad)*((f[i*3 + 3] - Hparam.zmin) /
03832          (Hparam.zmax - Hparam.zmin)) + rinrad;
03833       }
03834    }
03835 }
03836 
03837 
03838 //______________________________________________________________________________
03839 void TPainter3dAlgorithms::SurfacePolar(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
03840 {
03841    // Draw surface in polar coordinates
03842    //
03843    //    Input: IORDR - order of variables (0 - R,PHI, 1 - PHI,R)
03844    //           NA    - number of steps along 1st variable
03845    //           NB    - number of steps along 2nd variable
03846    //
03847    //           FUN(IA,IB,F,T) - external routine
03848    //             IA     - cell number for 1st variable
03849    //             IB     - cell number for 2nd variable
03850    //             F(3,4) - face which corresponds to the cell
03851    //               F(1,*) - A
03852    //               F(2,*) - B
03853    //               F(3,*) - Z
03854    //             T(4)   - additional function (for example: temperature)
03855    //
03856    //           DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
03857    //             ICODES(*) - set of codes for this face
03858    //               ICODES(1) - IA
03859    //               ICODES(2) - IB
03860    //             XYZ(3,*)  - coordinates of nodes
03861    //             NP        - number of nodes in face
03862    //             IFACE(NP) - face
03863    //             T(NP)     - additional function
03864    //
03865    //           CHOPT       - options: 'BF' - from BACK to FRONT
03866    //                                  'FB' - from FRONT to BACK
03867 
03868    /* Initialized data */
03869    static Int_t iface[4] = { 1,2,3,4 };
03870    TView *view = 0;
03871 
03872    if (gPad) view = gPad->GetView();
03873    if (!view) {
03874       Error("SurfacePolar", "no TView in current pad");
03875       return;
03876    }
03877 
03878    Int_t iphi, jphi, kphi, incr, nphi, iopt, iphi1, iphi2;
03879    Double_t f[12]        /* was [3][4] */;
03880    Int_t i, j, incrr, ir1, ir2;
03881    Double_t z;
03882    Int_t ia, ib, ir, jr, nr, icodes[2];
03883    Double_t tt[4];
03884    Double_t phi, ttt[4], xyz[12]        /* was [3][4] */;
03885    ia = ib = 0;
03886 
03887    if (iordr == 0) {
03888       jr   = 1;
03889       jphi = 2;
03890       nr   = na;
03891       nphi = nb;
03892    } else {
03893       jr   = 2;
03894       jphi = 1;
03895       nr   = nb;
03896       nphi = na;
03897    }
03898    if (nphi > 180) {
03899       Error("SurfacePolar", "too many PHI sectors (%d)", nphi);
03900       return;
03901    }
03902    iopt = 2;
03903    if (*chopt == 'B' || *chopt == 'b') iopt = 1;
03904 
03905    //       P R E P A R E   P H I   A R R A Y
03906    //      F I N D    C R I T I C A L   S E C T O R S
03907    kphi = nphi;
03908    if (iordr == 0) ia = nr;
03909    if (iordr != 0) ib = nr;
03910    for (i = 1; i <= nphi; ++i) {
03911       if (iordr == 0) ib = i;
03912       if (iordr != 0) ia = i;
03913       (this->*fSurfaceFunction)(ia, ib, f, tt);
03914       if (i == 1) fAphi[0] = f[jphi - 1];
03915       fAphi[i - 1] = (fAphi[i - 1] + f[jphi - 1]) / (float)2.;
03916       fAphi[i] = f[jphi + 5];
03917    }
03918    view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
03919 
03920    //       D R A W   S U R F A C E
03921    incr = 1;
03922    iphi = iphi1;
03923 L100:
03924    if (iphi > nphi) goto L300;
03925 
03926    //      F I N D   O R D E R   A L O N G   R
03927    if (iordr == 0) {ia = nr;         ib = iphi;}
03928    else            {ia = iphi;ib = nr;}
03929 
03930    (this->*fSurfaceFunction)(ia, ib, f, tt);
03931    phi = kRad*((f[jphi - 1] + f[jphi + 5]) / 2);
03932    view->FindNormal(TMath::Cos(phi), TMath::Sin(phi), 0, z);
03933    incrr = 1;
03934    ir1 = 1;
03935    if ((z <= 0 && iopt == 1) || (z > 0 && iopt == 2)) {
03936       incrr = -1;
03937       ir1 = nr;
03938    }
03939    ir2 = nr - ir1 + 1;
03940    //      D R A W   S U R F A C E   F O R   S E C T O R
03941    for (ir = ir1; incrr < 0 ? ir >= ir2 : ir <= ir2; ir += incrr) {
03942       if (iordr == 0) ia = ir;
03943       if (iordr != 0) ib = ir;
03944 
03945       (this->*fSurfaceFunction)(ia, ib, f, tt);
03946       for (i = 1; i <= 4; ++i) {
03947          j = i;
03948          if (iordr != 0 && i == 2) j = 4;
03949          if (iordr != 0 && i == 4) j = 2;
03950          xyz[j*3 - 3] = f[jr + i*3 - 4]*TMath::Cos(f[jphi + i*3 - 4]*kRad);
03951          xyz[j*3 - 2] = f[jr + i*3 - 4]*TMath::Sin(f[jphi + i*3 - 4]*kRad);
03952          xyz[j*3 - 1] = f[i*3 - 1];
03953          ttt[j - 1] = tt[i - 1];
03954       }
03955       icodes[0] = ia;
03956       icodes[1] = ib;
03957       (this->*fDrawFace)(icodes, xyz, 4, iface, ttt);
03958    }
03959    //      N E X T   P H I
03960 L300:
03961    iphi += incr;
03962    if (iphi == 0)     iphi = kphi;
03963    if (iphi > kphi)   iphi = 1;
03964    if (iphi != iphi2) goto L100;
03965    if (incr == 0) return;
03966    if (incr < 0) {
03967       incr = 0;
03968       goto L100;
03969    }
03970    incr = -1;
03971    iphi = iphi1;
03972    goto L300;
03973 }
03974 
03975 
03976 //______________________________________________________________________________
03977 void TPainter3dAlgorithms::SurfaceCylindrical(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
03978 {
03979    // Draw surface in cylindrical coordinates
03980    //
03981    //    Input: IORDR - order of variables (0 - Z,PHI, 1 - PHI,Z)
03982    //           NA    - number of steps along 1st variable
03983    //           NB    - number of steps along 2nd variable
03984    //
03985    //           FUN(IA,IB,F,T) - external routine
03986    //             IA     - cell number for 1st variable
03987    //             IB     - cell number for 2nd variable
03988    //             F(3,4) - face which corresponds to the cell
03989    //               F(1,*) - A
03990    //               F(2,*) - B
03991    //               F(3,*) - R
03992    //             T(4)   - additional function (for example: temperature)
03993    //
03994    //           DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
03995    //             ICODES(*) - set of codes for this face
03996    //               ICODES(1) - IA
03997    //               ICODES(2) - IB
03998    //             XYZ(3,*)  - coordinates of nodes
03999    //             NP        - number of nodes in face
04000    //             IFACE(NP) - face
04001    //             T(NP)     - additional function
04002    //
04003    //           CHOPT       - options: 'BF' - from BACK to FRONT
04004    //                                  'FB' - from FRONT to BACK
04005    //
04006    //Begin_Html
04007    /*
04008    <img src="gif/Surface1Cylindrical.gif">
04009    */
04010    //End_Html
04011 
04012    /* Initialized data */
04013    static Int_t iface[4] = { 1,2,3,4 };
04014 
04015    Int_t iphi, jphi, kphi, incr, nphi, iopt, iphi1, iphi2;
04016    Int_t i, j, incrz, nz, iz1, iz2;
04017    Int_t ia, ib, iz, jz, icodes[2];
04018    Double_t f[12]        /* was [3][4] */;
04019    Double_t z;
04020    Double_t tt[4];
04021    Double_t ttt[4], xyz[12]        /* was [3][4] */;
04022    ia = ib = 0;
04023    TView *view = 0;
04024 
04025    if (gPad) view = gPad->GetView();
04026    if (!view) {
04027       Error("SurfaceCylindrical", "no TView in current pad");
04028       return;
04029    }
04030 
04031    if (iordr == 0) {
04032       jz   = 1;
04033       jphi = 2;
04034       nz   = na;
04035       nphi = nb;
04036    } else {
04037       jz   = 2;
04038       jphi = 1;
04039       nz   = nb;
04040       nphi = na;
04041    }
04042    if (nphi > 180) {
04043       Error("SurfaceCylindrical", "too many PHI sectors (%d)", nphi);
04044       return;
04045    }
04046    iopt = 2;
04047    if (*chopt == 'B' || *chopt == 'b') iopt = 1;
04048 
04049    //       P R E P A R E   P H I   A R R A Y
04050    //       F I N D    C R I T I C A L   S E C T O R S
04051    kphi = nphi;
04052    if (iordr == 0) ia = nz;
04053    if (iordr != 0) ib = nz;
04054    for (i = 1; i <= nphi; ++i) {
04055       if (iordr == 0) ib = i;
04056       if (iordr != 0) ia = i;
04057       (this->*fSurfaceFunction)(ia, ib, f, tt);
04058       if (i == 1) fAphi[0] = f[jphi - 1];
04059       fAphi[i - 1] = (fAphi[i - 1] + f[jphi - 1]) / (float)2.;
04060       fAphi[i] = f[jphi + 5];
04061    }
04062    view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
04063 
04064    //       F I N D   O R D E R   A L O N G   Z
04065    incrz = 1;
04066    iz1 = 1;
04067    view->FindNormal(0, 0, 1, z);
04068    if ((z <= 0 && iopt == 1) || (z > 0 && iopt == 2)) {
04069       incrz = -1;
04070       iz1 = nz;
04071    }
04072    iz2 = nz - iz1 + 1;
04073 
04074    //       D R A W   S U R F A C E
04075    incr = 1;
04076    iphi = iphi1;
04077 L100:
04078    if (iphi > nphi) goto L400;
04079    for (iz = iz1; incrz < 0 ? iz >= iz2 : iz <= iz2; iz += incrz) {
04080       if (iordr == 0) {ia = iz;   ib = iphi;}
04081       else             {ia = iphi; ib = iz;}
04082       (this->*fSurfaceFunction)(ia, ib, f, tt);
04083       for (i = 1; i <= 4; ++i) {
04084          j = i;
04085          if (iordr == 0 && i == 2) j = 4;
04086          if (iordr == 0 && i == 4) j = 2;
04087          xyz[j*3 - 3] = f[i*3 - 1]*TMath::Cos(f[jphi + i*3 - 4]*kRad);
04088          xyz[j*3 - 2] = f[i*3 - 1]*TMath::Sin(f[jphi + i*3 - 4]*kRad);
04089          xyz[j*3 - 1] = f[jz + i*3 - 4];
04090          ttt[j - 1] = tt[i - 1];
04091       }
04092       icodes[0] = ia;
04093       icodes[1] = ib;
04094       (this->*fDrawFace)(icodes, xyz, 4, iface, ttt);
04095    }
04096    //      N E X T   P H I
04097 L400:
04098    iphi += incr;
04099    if (iphi == 0)     iphi = kphi;
04100    if (iphi > kphi)   iphi = 1;
04101    if (iphi != iphi2) goto L100;
04102    if (incr ==  0) return;
04103    if (incr < 0) {
04104       incr = 0;
04105       goto L100;
04106    }
04107    incr = -1;
04108    iphi = iphi1;
04109    goto L400;
04110 }
04111 
04112 
04113 //______________________________________________________________________________
04114 void TPainter3dAlgorithms::SurfaceSpherical(Int_t ipsdr, Int_t iordr, Int_t na, Int_t nb, const char *chopt)
04115 {
04116    // Draw surface in spheric coordinates
04117    //
04118    //    Input: IPSDR - pseudo-rapidity flag
04119    //           IORDR - order of variables (0 - THETA,PHI; 1 - PHI,THETA)
04120    //           NA    - number of steps along 1st variable
04121    //           NB    - number of steps along 2nd variable
04122    //
04123    //           FUN(IA,IB,F,T) - external routine
04124    //             IA     - cell number for 1st variable
04125    //             IB     - cell number for 2nd variable
04126    //             F(3,4) - face which corresponds to the cell
04127    //               F(1,*) - A
04128    //               F(2,*) - B
04129    //               F(3,*) - R
04130    //             T(4)   - additional function (for example: temperature)
04131    //
04132    //           DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
04133    //             ICODES(*) - set of codes for this face
04134    //               ICODES(1) - IA
04135    //               ICODES(2) - IB
04136    //             XYZ(3,*)  - coordinates of nodes
04137    //             NP        - number of nodes in face
04138    //             IFACE(NP) - face
04139    //             T(NP)     - additional function
04140    //
04141    //           CHOPT       - options: 'BF' - from BACK to FRONT
04142    //                                  'FB' - from FRONT to BACK
04143 
04144    /* Initialized data */
04145    static Int_t iface[4] = { 1,2,3,4 };
04146 
04147    Int_t iphi, jphi, kphi, incr, nphi, iopt, iphi1, iphi2;
04148    Int_t i, j, incrth, ith, jth, kth, nth, mth, ith1, ith2;
04149    Int_t ia, ib, icodes[2];
04150    Double_t f[12]        /* was [3][4] */;
04151    Double_t tt[4];
04152    Double_t phi;
04153    Double_t ttt[4], xyz[12]        /* was [3][4] */;
04154    ia = ib = 0;
04155    TView *view = 0;
04156 
04157    if (gPad) view = gPad->GetView();
04158    if (!view) {
04159       Error("SurfaceSpherical", "no TView in current pad");
04160       return;
04161    }
04162 
04163    if (iordr == 0) {
04164       jth  = 1;
04165       jphi = 2;
04166       nth  = na;
04167       nphi = nb;
04168    } else {
04169       jth  = 2;
04170       jphi = 1;
04171       nth  = nb;
04172       nphi = na;
04173    }
04174    if (nth > 180)  {
04175       Error("SurfaceSpherical", "too many THETA sectors (%d)", nth);
04176       return;
04177    }
04178    if (nphi > 180) {
04179       Error("SurfaceSpherical", "too many PHI sectors (%d)", nphi);
04180       return;
04181    }
04182    iopt = 2;
04183    if (*chopt == 'B' || *chopt == 'b') iopt = 1;
04184 
04185    //       P R E P A R E   P H I   A R R A Y
04186    //       F I N D    C R I T I C A L   P H I   S E C T O R S
04187    kphi = nphi;
04188    mth = nth / 2;
04189    if (mth == 0)    mth = 1;
04190    if (iordr == 0) ia = mth;
04191    if (iordr != 0) ib = mth;
04192    for (i = 1; i <= nphi; ++i) {
04193       if (iordr == 0) ib = i;
04194       if (iordr != 0) ia = i;
04195       (this->*fSurfaceFunction)(ia, ib, f, tt);
04196       if (i == 1) fAphi[0] = f[jphi - 1];
04197       fAphi[i - 1] = (fAphi[i - 1] + f[jphi - 1]) / (float)2.;
04198       fAphi[i] = f[jphi + 5];
04199    }
04200    view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
04201 
04202    //       P R E P A R E   T H E T A   A R R A Y
04203    if (iordr == 0) ib = 1;
04204    if (iordr != 0) ia = 1;
04205    for (i = 1; i <= nth; ++i) {
04206       if (iordr == 0) ia = i;
04207       if (iordr != 0) ib = i;
04208 
04209       (this->*fSurfaceFunction)(ia, ib, f, tt);
04210       if (i == 1) fAphi[0] = f[jth - 1];
04211       fAphi[i - 1] = (fAphi[i - 1] + f[jth - 1]) / (float)2.;
04212       fAphi[i] = f[jth + 5];
04213    }
04214 
04215    //       D R A W   S U R F A C E
04216    kth  = nth;
04217    incr = 1;
04218    iphi = iphi1;
04219 L100:
04220    if (iphi > nphi) goto L500;
04221 
04222    //      F I N D    C R I T I C A L   T H E T A   S E C T O R S
04223    if (iordr == 0) {ia = mth; ib = iphi;}
04224    else             {ia = iphi;ib = mth;}
04225 
04226    (this->*fSurfaceFunction)(ia, ib, f, tt);
04227    phi = (f[jphi - 1] + f[jphi + 5]) / (float)2.;
04228    view->FindThetaSectors(iopt, phi, kth, fAphi, ith1, ith2);
04229    incrth = 1;
04230    ith = ith1;
04231 L200:
04232    if (ith > nth)   goto L400;
04233    if (iordr == 0) ia = ith;
04234    if (iordr != 0) ib = ith;
04235 
04236    (this->*fSurfaceFunction)(ia, ib, f, tt);
04237    if (ipsdr == 1) {
04238       for (i = 1; i <= 4; ++i) {
04239          j = i;
04240          if (iordr != 0 && i == 2) j = 4;
04241          if (iordr != 0 && i == 4) j = 2;
04242          xyz[j * 3 - 3] = f[i*3 - 1]*TMath::Cos(f[jphi + i*3 - 4]*kRad);
04243          xyz[j * 3 - 2] = f[i*3 - 1]*TMath::Sin(f[jphi + i*3 - 4]*kRad);
04244          xyz[j * 3 - 1] = f[i*3 - 1]*TMath::Cos(f[jth  + i*3 - 4]*kRad) /
04245                           TMath::Sin(f[jth + i*3 - 4]*kRad);
04246          ttt[j - 1] = tt[i - 1];
04247       }
04248    } else {
04249       for (i = 1; i <= 4; ++i) {
04250          j = i;
04251          if (iordr != 0 && i == 2) j = 4;
04252          if (iordr != 0 && i == 4) j = 2;
04253          xyz[j*3 - 3] = f[i*3 - 1]*TMath::Sin(f[jth + i*3 - 4]*kRad)*TMath::Cos(f[jphi + i*3 - 4]*kRad);
04254          xyz[j*3 - 2] = f[i*3 - 1]*TMath::Sin(f[jth + i*3 - 4]*kRad)*TMath::Sin(f[jphi + i*3 - 4]*kRad);
04255          xyz[j*3 - 1] = f[i*3 - 1]*TMath::Cos(f[jth + i*3 - 4]*kRad);
04256          ttt[j - 1] = tt[i - 1];
04257       }
04258    }
04259    icodes[0] = ia;
04260    icodes[1] = ib;
04261    (this->*fDrawFace)(icodes, xyz, 4, iface, ttt);
04262    //      N E X T   T H E T A
04263 L400:
04264    ith += incrth;
04265    if (ith == 0)    ith = kth;
04266    if (ith > kth)   ith = 1;
04267    if (ith != ith2) goto L200;
04268    if (incrth == 0)  goto L500;
04269    if (incrth < 0) {
04270       incrth = 0;
04271       goto L200;
04272    }
04273    incrth = -1;
04274    ith = ith1;
04275    goto L400;
04276    //      N E X T   P H I
04277 L500:
04278    iphi += incr;
04279    if (iphi == 0)     iphi = kphi;
04280    if (iphi > kphi)   iphi = 1;
04281    if (iphi != iphi2) goto L100;
04282    if (incr == 0) return;
04283    if (incr < 0) {
04284       incr = 0;
04285       goto L100;
04286    }
04287    incr = -1;
04288    iphi = iphi1;
04289    goto L500;
04290 }
04291 
04292 
04293 //______________________________________________________________________________
04294 void TPainter3dAlgorithms::SurfaceProperty(Double_t qqa, Double_t qqd, Double_t qqs, Int_t nnqs, Int_t &irep)
04295 {
04296    // Set surface property coefficients
04297    //
04298    //    Input: QQA  - diffusion coefficient for diffused light  [0.,1.]
04299    //           QQD  - diffusion coefficient for direct light    [0.,1.]
04300    //           QQS  - diffusion coefficient for reflected light [0.,1.]
04301    //           NNCS - power coefficient for reflected light     (.GE.1)
04302    //
04303    //                                         --
04304    //    Lightness model formula: Y = YD*QA + > YLi*(QD*cosNi+QS*cosRi)
04305    //                                         --
04306    //
04307    //    Output: IREP   - reply : 0 - O.K.
04308    //                            -1 - error in cooefficients
04309 
04310    irep = 0;
04311    if (qqa < 0 || qqa > 1 || qqd < 0 || qqd > 1 || qqs < 0 || qqs > 1 || nnqs < 1) {
04312       Error("SurfaceProperty", "error in coefficients");
04313       irep = -1;
04314       return;
04315    }
04316    fQA  = qqa;
04317    fQD  = qqd;
04318    fQS  = qqs;
04319    fNqs = nnqs;
04320 }
04321 
04322 
04323 //______________________________________________________________________________
04324 void TPainter3dAlgorithms::ImplicitFunction(Double_t *rmin, Double_t *rmax,
04325                              Int_t nx, Int_t ny, Int_t nz, const char *chopt)
04326 {
04327    // Draw implicit function FUN(X,Y,Z) = 0 in cartesian coordinates using
04328    // hidden surface removal algorithm "Painter".
04329    //
04330    //     Input: FUN      - external routine FUN(X,Y,Z)
04331    //            RMIN(3)  - min scope coordinates
04332    //            RMAX(3)  - max scope coordinates
04333    //            NX       - number of steps along X
04334    //            NY       - number of steps along Y
04335    //            NZ       - number of steps along Z
04336    //
04337    //            DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
04338    //              ICODES(*) - set of codes for this face
04339    //                ICODES(1) - 1
04340    //                ICODES(2) - 1
04341    //                ICODES(3) - 1
04342    //              NP        - number of nodes in face
04343    //              IFACE(NP) - face
04344    //              T(NP)     - additional function (lightness)
04345    //
04346    //            CHOPT - options: 'BF' - from BACK to FRONT
04347    //                             'FB' - from FRONT to BACK
04348 
04349    Int_t ix,    iy,    iz;
04350    Int_t ix1,   iy1,   iz1;
04351    Int_t ix2,   iy2,   iz2;
04352    Int_t incr,  incrx, incry, incrz;
04353    Int_t icodes[3], i, i1, i2, k, nnod, ntria;
04354    Double_t x1=0, x2=0, y1, y2, z1, z2;
04355    Double_t dx, dy, dz;
04356    Double_t p[8][3], pf[8], pn[8][3], t[3], fsurf, w;
04357 
04358    Double_t xyz[kNmaxp][3], xyzn[kNmaxp][3], grad[kNmaxp][3];
04359    Double_t dtria[kNmaxt][6], abcd[kNmaxt][4];
04360    Int_t    itria[kNmaxt][3], iorder[kNmaxt];
04361    TView *view = 0;
04362 
04363    if (gPad) view = gPad->GetView();
04364    if (!view) {
04365       Error("ImplicitFunction", "no TView in current pad");
04366       return;
04367    }
04368    Double_t *tnorm = view->GetTnorm();
04369 
04370    //       D E F I N E   O R D E R   O F   D R A W I N G
04371    if (*chopt == 'B' || *chopt == 'b') {
04372       incrx = +1;
04373       incry = +1;
04374       incrz = +1;
04375    } else {
04376       incrx = -1;
04377       incry = -1;
04378       incrz = -1;
04379    }
04380    if (tnorm[8]  < 0.) incrx =-incrx;
04381    if (tnorm[9]  < 0.) incry =-incry;
04382    if (tnorm[10] < 0.) incrz =-incrz;
04383    ix1 = 1;
04384    iy1 = 1;
04385    iz1 = 1;
04386    if (incrx == -1) ix1 = nx;
04387    if (incry == -1) iy1 = ny;
04388    if (incrz == -1) iz1 = nz;
04389    ix2 = nx - ix1 + 1;
04390    iy2 = ny - iy1 + 1;
04391    iz2 = nz - iz1 + 1;
04392    dx  = (rmax[0]-rmin[0]) / nx;
04393    dy  = (rmax[1]-rmin[1]) / ny;
04394    dz  = (rmax[2]-rmin[2]) / nz;
04395 
04396    // Define the colors used to draw the function
04397    Float_t r, g, b, hue, light, satur, light2;
04398    TColor *colref = gROOT->GetColor(fgCurrentF3->GetFillColor());
04399    colref->GetRGB(r, g, b);
04400    TColor::RGBtoHLS(r, g, b, hue, light, satur);
04401    TColor *acol;
04402    acol = gROOT->GetColor(kF3FillColor1);
04403    acol->SetRGB(r, g, b);
04404    if (light >= 0.5) {
04405       light2 = .5*light;
04406    } else {
04407       light2 = 1-.5*light;
04408    }
04409    TColor::HLStoRGB(hue, light2, satur, r, g, b);
04410    acol = gROOT->GetColor(kF3FillColor2);
04411    acol->SetRGB(r, g, b);
04412    colref = gROOT->GetColor(fgCurrentF3->GetLineColor());
04413    colref->GetRGB(r, g, b);
04414    acol = gROOT->GetColor(kF3LineColor);
04415    acol->SetRGB(r, g, b);
04416 
04417    //       D R A W   F U N C T I O N
04418    for (iz = iz1; incrz < 0 ? iz >= iz2 : iz <= iz2; iz += incrz) {
04419       z1     = (iz-1)*dz + rmin[2];
04420       z2     = z1 + dz;
04421       p[0][2] = z1;
04422       p[1][2] = z1;
04423       p[2][2] = z1;
04424       p[3][2] = z1;
04425       p[4][2] = z2;
04426       p[5][2] = z2;
04427       p[6][2] = z2;
04428       p[7][2] = z2;
04429       for (iy = iy1; incry < 0 ? iy >= iy2 : iy <= iy2; iy += incry) {
04430          y1      = (iy-1)*dy + rmin[1];
04431          y2      = y1 + dy;
04432          p[0][1] = y1;
04433          p[1][1] = y1;
04434          p[2][1] = y2;
04435          p[3][1] = y2;
04436          p[4][1] = y1;
04437          p[5][1] = y1;
04438          p[6][1] = y2;
04439          p[7][1] = y2;
04440          if (incrx == +1) {
04441             x2    = rmin[0];
04442             pf[1] = fgCurrentF3->Eval(x2,y1,z1);
04443             pf[2] = fgCurrentF3->Eval(x2,y2,z1);
04444             pf[5] = fgCurrentF3->Eval(x2,y1,z2);
04445             pf[6] = fgCurrentF3->Eval(x2,y2,z2);
04446          } else {
04447             x1    = rmax[0];
04448             pf[0] = fgCurrentF3->Eval(x1,y1,z1);
04449             pf[3] = fgCurrentF3->Eval(x1,y2,z1);
04450             pf[4] = fgCurrentF3->Eval(x1,y1,z2);
04451             pf[7] = fgCurrentF3->Eval(x1,y2,z2);
04452          }
04453          for (ix = ix1; incrx < 0 ? ix >= ix2 : ix <= ix2; ix += incrx) {
04454             icodes[0] = ix;
04455             icodes[1] = iy;
04456             icodes[2] = iz;
04457             if (incrx == +1) {
04458                x1     = x2;
04459                x2     = x2 + dx;
04460                pf[0]  = pf[1];
04461                pf[3]  = pf[2];
04462                pf[4]  = pf[5];
04463                pf[7]  = pf[6];
04464                pf[1]  = fgCurrentF3->Eval(x2,y1,z1);
04465                pf[2]  = fgCurrentF3->Eval(x2,y2,z1);
04466                pf[5]  = fgCurrentF3->Eval(x2,y1,z2);
04467                pf[6]  = fgCurrentF3->Eval(x2,y2,z2);
04468             } else {
04469                x2     = x1;
04470                x1     = x1 - dx;
04471                pf[1]  = pf[0];
04472                pf[2]  = pf[3];
04473                pf[5]  = pf[4];
04474                pf[6]  = pf[7];
04475                pf[0]  = fgCurrentF3->Eval(x1,y1,z1);
04476                pf[3]  = fgCurrentF3->Eval(x1,y2,z1);
04477                pf[4]  = fgCurrentF3->Eval(x1,y1,z2);
04478                pf[7]  = fgCurrentF3->Eval(x1,y2,z2);
04479             }
04480             if (pf[0] >= -kFdel) goto L110;
04481             if (pf[1] >= -kFdel) goto L120;
04482             if (pf[2] >= -kFdel) goto L120;
04483             if (pf[3] >= -kFdel) goto L120;
04484             if (pf[4] >= -kFdel) goto L120;
04485             if (pf[5] >= -kFdel) goto L120;
04486             if (pf[6] >= -kFdel) goto L120;
04487             if (pf[7] >= -kFdel) goto L120;
04488             goto L510;
04489 L110:
04490             if (pf[1] < -kFdel) goto L120;
04491             if (pf[2] < -kFdel) goto L120;
04492             if (pf[3] < -kFdel) goto L120;
04493             if (pf[4] < -kFdel) goto L120;
04494             if (pf[5] < -kFdel) goto L120;
04495             if (pf[6] < -kFdel) goto L120;
04496             if (pf[7] < -kFdel) goto L120;
04497             goto L510;
04498 L120:
04499             p[0][0] = x1;
04500             p[1][0] = x2;
04501             p[2][0] = x2;
04502             p[3][0] = x1;
04503             p[4][0] = x1;
04504             p[5][0] = x2;
04505             p[6][0] = x2;
04506             p[7][0] = x1;
04507 
04508             //       F I N D   G R A D I E N T S
04509             // Find X-gradient
04510             if (ix == 1) {
04511                pn[0][0] = (pf[1] - pf[0]) / dx;
04512                pn[3][0] = (pf[2] - pf[3]) / dx;
04513                pn[4][0] = (pf[5] - pf[4]) / dx;
04514                pn[7][0] = (pf[6] - pf[7]) / dx;
04515             } else {
04516                pn[0][0] = (pf[1] - fgCurrentF3->Eval(x1-dx,y1,z1)) / (dx + dx);
04517                pn[3][0] = (pf[2] - fgCurrentF3->Eval(x1-dx,y2,z1)) / (dx + dx);
04518                pn[4][0] = (pf[5] - fgCurrentF3->Eval(x1-dx,y1,z2)) / (dx + dx);
04519                pn[7][0] = (pf[6] - fgCurrentF3->Eval(x1-dx,y2,z2)) / (dx + dx);
04520             }
04521             if (ix == nx) {
04522                pn[1][0] = (pf[1] - pf[0]) / dx;
04523                pn[2][0] = (pf[2] - pf[3]) / dx;
04524                pn[5][0] = (pf[5] - pf[4]) / dx;
04525                pn[6][0] = (pf[6] - pf[7]) / dx;
04526             } else {
04527                pn[1][0] = (fgCurrentF3->Eval(x2+dx,y1,z1) - pf[0]) / (dx + dx);
04528                pn[2][0] = (fgCurrentF3->Eval(x2+dx,y2,z1) - pf[3]) / (dx + dx);
04529                pn[5][0] = (fgCurrentF3->Eval(x2+dx,y1,z2) - pf[4]) / (dx + dx);
04530                pn[6][0] = (fgCurrentF3->Eval(x2+dx,y2,z2) - pf[7]) / (dx + dx);
04531             }
04532             // Find Y-gradient
04533             if (iy == 1) {
04534                pn[0][1] = (pf[3] - pf[0]) / dy;
04535                pn[1][1] = (pf[2] - pf[1]) / dy;
04536                pn[4][1] = (pf[7] - pf[4]) / dy;
04537                pn[5][1] = (pf[6] - pf[5]) / dy;
04538             } else {
04539                pn[0][1] = (pf[3] - fgCurrentF3->Eval(x1,y1-dy,z1)) / (dy + dy);
04540                pn[1][1] = (pf[2] - fgCurrentF3->Eval(x2,y1-dy,z1)) / (dy + dy);
04541                pn[4][1] = (pf[7] - fgCurrentF3->Eval(x1,y1-dy,z2)) / (dy + dy);
04542                pn[5][1] = (pf[6] - fgCurrentF3->Eval(x2,y1-dy,z2)) / (dy + dy);
04543             }
04544             if (iy == ny) {
04545                pn[2][1] = (pf[2] - pf[1]) / dy;
04546                pn[3][1] = (pf[3] - pf[0]) / dy;
04547                pn[6][1] = (pf[6] - pf[5]) / dy;
04548                pn[7][1] = (pf[7] - pf[4]) / dy;
04549             } else {
04550                pn[2][1] = (fgCurrentF3->Eval(x2,y2+dy,z1) - pf[1]) / (dy + dy);
04551                pn[3][1] = (fgCurrentF3->Eval(x1,y2+dy,z1) - pf[0]) / (dy + dy);
04552                pn[6][1] = (fgCurrentF3->Eval(x2,y2+dy,z2) - pf[5]) / (dy + dy);
04553                pn[7][1] = (fgCurrentF3->Eval(x1,y2+dy,z2) - pf[4]) / (dy + dy);
04554             }
04555             // Find Z-gradient
04556             if (iz == 1) {
04557                pn[0][2] = (pf[4] - pf[0]) / dz;
04558                pn[1][2] = (pf[5] - pf[1]) / dz;
04559                pn[2][2] = (pf[6] - pf[2]) / dz;
04560                pn[3][2] = (pf[7] - pf[3]) / dz;
04561             } else {
04562                pn[0][2] = (pf[4] - fgCurrentF3->Eval(x1,y1,z1-dz)) / (dz + dz);
04563                pn[1][2] = (pf[5] - fgCurrentF3->Eval(x2,y1,z1-dz)) / (dz + dz);
04564                pn[2][2] = (pf[6] - fgCurrentF3->Eval(x2,y2,z1-dz)) / (dz + dz);
04565                pn[3][2] = (pf[7] - fgCurrentF3->Eval(x1,y2,z1-dz)) / (dz + dz);
04566             }
04567             if (iz == nz) {
04568                pn[4][2] = (pf[4] - pf[0]) / dz;
04569                pn[5][2] = (pf[5] - pf[1]) / dz;
04570                pn[6][2] = (pf[6] - pf[2]) / dz;
04571                pn[7][2] = (pf[7] - pf[3]) / dz;
04572             } else {
04573                pn[4][2] = (fgCurrentF3->Eval(x1,y1,z2+dz) - pf[0]) / (dz + dz);
04574                pn[5][2] = (fgCurrentF3->Eval(x2,y1,z2+dz) - pf[1]) / (dz + dz);
04575                pn[6][2] = (fgCurrentF3->Eval(x2,y2,z2+dz) - pf[2]) / (dz + dz);
04576                pn[7][2] = (fgCurrentF3->Eval(x1,y2,z2+dz) - pf[3]) / (dz + dz);
04577             }
04578             fsurf = 0.;
04579             MarchingCube(fsurf, p, pf, pn, nnod, ntria, xyz, grad, itria);
04580             if (ntria == 0)   goto L510;
04581 
04582             for ( i=1 ; i<=nnod ; i++ ) {
04583                view->WCtoNDC(&xyz[i-1][0], &xyzn[i-1][0]);
04584                Luminosity(&grad[i-1][0], w);
04585                grad[i-1][0] = w;
04586             }
04587             ZDepth(xyzn, ntria, itria, dtria, abcd, (Int_t*)iorder);
04588             if (ntria == 0)   goto L510;
04589             incr = 1;
04590             if (*chopt == 'B' || *chopt == 'b') incr =-1;
04591             i1 = 1;
04592             if (incr == -1) i1 = ntria;
04593             i2 = ntria - i1 + 1;
04594             // If clipping box is on do not draw the triangles
04595             if (fgF3Clipping) {
04596                if(x2<=fgF3XClip && y2 <=fgF3YClip && z2>=fgF3ZClip) goto L510;
04597             }
04598             // Draw triangles
04599             for (i=i1; incr < 0 ? i >= i2 : i <= i2; i += incr) {
04600                k      = iorder[i-1];
04601                t[0]   = grad[TMath::Abs(itria[k-1][0])-1][0];
04602                t[1]   = grad[TMath::Abs(itria[k-1][1])-1][0];
04603                t[2]   = grad[TMath::Abs(itria[k-1][2])-1][0];
04604                (this->*fDrawFace)(icodes, (Double_t*)xyz, 3, &itria[k-1][0], t);
04605             }
04606 L510:
04607             continue;
04608          }
04609       }
04610    }
04611 }
04612 
04613 
04614 //______________________________________________________________________________
04615 void TPainter3dAlgorithms::MarchingCube(Double_t fiso, Double_t p[8][3],
04616                                         Double_t f[8], Double_t g[8][3],
04617                                         Int_t &nnod, Int_t &ntria,
04618                                         Double_t xyz[][3],
04619                                         Double_t grad[][3],
04620                                         Int_t itria[][3])
04621 {
04622    // Topological decider for "Marching Cubes" algorithm Find set of triangles
04623    // aproximating the isosurface F(x,y,z)=Fiso inside the cube
04624    // (improved version)
04625    //
04626    // Input: FISO   - function value for isosurface
04627    //        P(3,8) - cube vertexes
04628    //        F(8)   - function values at the vertexes
04629    //        G(3,8) - function gradients at the vertexes
04630    //
04631    // Output: NNOD       - number of nodes     (maximum 13)
04632    //         NTRIA      - number of triangles (maximum 12)
04633    //         XYZ(3,*)   - nodes
04634    //         GRAD(3,*)  - node normales       (not normalized)
04635    //         ITRIA(3,*) - triangles
04636    //
04637 
04638    static Int_t irota[24][8] = { { 1,2,3,4,5,6,7,8 }, { 2,3,4,1,6,7,8,5 },
04639                                  { 3,4,1,2,7,8,5,6 }, { 4,1,2,3,8,5,6,7 },
04640                                  { 6,5,8,7,2,1,4,3 }, { 5,8,7,6,1,4,3,2 },
04641                                  { 8,7,6,5,4,3,2,1 }, { 7,6,5,8,3,2,1,4 },
04642                                  { 2,6,7,3,1,5,8,4 }, { 6,7,3,2,5,8,4,1 },
04643                                  { 7,3,2,6,8,4,1,5 }, { 3,2,6,7,4,1,5,8 },
04644                                  { 5,1,4,8,6,2,3,7 }, { 1,4,8,5,2,3,7,6 },
04645                                  { 4,8,5,1,3,7,6,2 }, { 8,5,1,4,7,6,2,3 },
04646                                  { 5,6,2,1,8,7,3,4 }, { 6,2,1,5,7,3,4,8 },
04647                                  { 2,1,5,6,3,4,8,7 }, { 1,5,6,2,4,8,7,3 },
04648                                  { 4,3,7,8,1,2,6,5 }, { 3,7,8,4,2,6,5,1 },
04649                                  { 7,8,4,3,6,5,1,2 }, { 8,4,3,7,5,1,2,6 } };
04650 
04651    static Int_t iwhat[21] = { 1,3,5,65,50,67,74,51,177,105,113,58,165,178,
04652                               254,252,250,190,205,188,181 };
04653 
04654    Int_t j, i, i1, i2, i3, ir, irt=0, k, k1, k2, incr, icase=0, n;
04655    Int_t itr[3];
04656 
04657    nnod  = 0;
04658    ntria = 0;
04659 
04660    // F I N D   C O N F I G U R A T I O N   T Y P E
04661    for ( i=1; i<=8 ; i++) {
04662       fF8[i-1] = f[i-1] - fiso;
04663    }
04664    for ( ir=1 ; ir<=24 ; ir++ ) {
04665       k    = 0;
04666       incr = 1;
04667       for ( i=1 ; i<=8 ; i++ ) {
04668          if (fF8[irota[ir-1][i-1]-1] >= 0.) k = k + incr;
04669          incr = incr + incr;
04670       }
04671       if (k==0 || k==255) return;
04672       for ( i=1 ; i<=21 ; i++ ) {
04673          if (k != iwhat[i-1]) continue;
04674             icase = i;
04675             irt   = ir;
04676             goto L200;
04677       }
04678    }
04679 
04680    // R O T A T E   C U B E
04681 L200:
04682    for ( i=1 ; i<=8 ; i++ ) {
04683       k        = irota[irt-1][i-1];
04684       fF8[i-1] = f[k-1] - fiso;
04685       fP8[i-1][0] = p[k-1][0];
04686       fP8[i-1][1] = p[k-1][1];
04687       fP8[i-1][2] = p[k-1][2];
04688       fG8[i-1][0] = g[k-1][0];
04689       fG8[i-1][1] = g[k-1][1];
04690       fG8[i-1][2] = g[k-1][2];
04691    }
04692 
04693    // V A R I O U S   C O N F I G U R A T I O N S
04694    n = 0;
04695    switch ((int)icase) {
04696       case 1:
04697       case 15:
04698          MarchingCubeCase00(1, 4, 9, 0, 0, 0, nnod, ntria, xyz, grad, itria);
04699          goto L400;
04700       case 2:
04701       case 16:
04702          MarchingCubeCase00(2, 4, 9, 10, 0, 0, nnod, ntria, xyz, grad, itria);
04703          goto L400;
04704       case 3:
04705       case 17:
04706          MarchingCubeCase03(nnod, ntria, xyz, grad, itria);
04707          goto L400;
04708       case 4:
04709       case 18:
04710          MarchingCubeCase04(nnod, ntria, xyz, grad, itria);
04711          goto L400;
04712       case 5:
04713       case 19:
04714          MarchingCubeCase00(6, 2, 1, 9, 8, 0, nnod, ntria, xyz, grad, itria);
04715          goto L400;
04716       case 6:
04717       case 20:
04718          MarchingCubeCase06(nnod, ntria, xyz, grad, itria);
04719          goto L400;
04720       case 7:
04721       case 21:
04722          MarchingCubeCase07(nnod, ntria, xyz, grad, itria);
04723          goto L400;
04724       case 8:
04725          MarchingCubeCase00(2, 4, 8, 6, 0, 0, nnod, ntria, xyz, grad, itria);
04726          goto L500;
04727       case 9:
04728          MarchingCubeCase00(1, 4, 12, 7, 6, 10, nnod, ntria, xyz, grad, itria);
04729          goto L500;
04730       case 0:
04731          MarchingCubeCase10(nnod, ntria, xyz, grad, itria);
04732          goto L500;
04733       case 11:
04734          MarchingCubeCase00(1, 4, 8, 7, 11, 10, nnod, ntria, xyz, grad, itria);
04735          goto L500;
04736       case 12:
04737          MarchingCubeCase12(nnod, ntria, xyz, grad, itria);
04738          goto L500;
04739       case 13:
04740          MarchingCubeCase13(nnod, ntria, xyz, grad, itria);
04741          goto L500;
04742       case 14:
04743          MarchingCubeCase00(1, 9, 12, 7, 6, 2, nnod, ntria, xyz, grad, itria);
04744          goto L500;
04745    }
04746 
04747    // I F   N E E D E D ,   I N V E R T   T R I A N G L E S
04748 L400:
04749    if (ntria == 0) return;
04750    if (icase <= 14) goto L500;
04751    for ( i=1; i<=ntria ; i++ ) {
04752       i1 = TMath::Abs(itria[i-1][0]);
04753       i2 = TMath::Abs(itria[i-1][1]);
04754       i3 = TMath::Abs(itria[i-1][2]);
04755       if (itria[i-1][2] < 0) i1 =-i1;
04756       if (itria[i-1][1] < 0) i3 =-i3;
04757       if (itria[i-1][0] < 0) i2 =-i2;
04758       itria[i-1][0] = i1;
04759       itria[i-1][1] = i3;
04760       itria[i-1][2] = i2;
04761    }
04762 
04763    // R E M O V E   V E R Y   S M A L L   T R I A N G L E S
04764 L500:
04765    n = n + 1;
04766 L510:
04767    if (n > ntria) return;
04768    for ( i=1 ; i<=3 ; i++ ) {
04769       i1 = i;
04770       i2 = i + 1;
04771       if (i == 3) i2 = 1;
04772       k1 = TMath::Abs(itria[n-1][i1-1]);
04773       k2 = TMath::Abs(itria[n-1][i2-1]);
04774       if (TMath::Abs(xyz[k1-1][0]-xyz[k2-1][0]) > kDel) continue;
04775       if (TMath::Abs(xyz[k1-1][1]-xyz[k2-1][1]) > kDel) continue;
04776       if (TMath::Abs(xyz[k1-1][2]-xyz[k2-1][2]) > kDel) continue;
04777       i3 = i - 1;
04778       if (i == 1) i3 = 3;
04779       goto L530;
04780    }
04781    goto L500;
04782 
04783    // R E M O V E   T R I A N G L E
04784 L530:
04785    for ( i=1 ; i<=3 ; i++ ) {
04786       itr[i-1] = itria[n-1][i-1];
04787       itria[n-1][i-1] = itria[ntria-1][i-1];
04788    }
04789    ntria = ntria - 1;
04790    if (ntria == 0) return;
04791    if (itr[i2-1]*itr[i3-1] > 0) goto L510;
04792 
04793    // C O R R E C T   O T H E R   T R I A N G L E S
04794    if (itr[i2-1] < 0) {
04795       k1 =-itr[i2-1];
04796       k2 =-TMath::Abs(itr[i3-1]);
04797    }
04798    if (itr[i3-1] < 0) {
04799       k1 =-itr[i3-1];
04800       k2 =-TMath::Abs(itr[i1-1]);
04801    }
04802    for ( j=1 ; j<=ntria ; j++ ) {
04803       for ( i=1 ; i<=3 ; i++ ) {
04804          if (itria[j-1][i-1] != k2) continue;
04805          i2 = TMath::Abs(itria[j-1][0]);
04806          if (i != 3) i2 = TMath::Abs(itria[j-1][i]);
04807          if (i2 == k1) itria[j-1][i-1] =-itria[j-1][i-1];
04808          goto L560;
04809       }
04810 L560:
04811       continue;
04812    }
04813    goto L510;
04814 }
04815 
04816 
04817 //______________________________________________________________________________
04818 void TPainter3dAlgorithms::MarchingCubeCase00(Int_t k1, Int_t k2, Int_t k3,
04819                                               Int_t k4, Int_t k5, Int_t k6,
04820                                               Int_t &nnod, Int_t &ntria,
04821                                               Double_t xyz[52][3],
04822                                               Double_t grad[52][3],
04823                                               Int_t itria[48][3])
04824 {
04825    // Consideration of trivial cases: 1,2,5,8,9,11,14
04826    //
04827    // Input: K1,...,K6 - edges intersected with isosurface
04828    //
04829    // Output: the same as for IHMCUB
04830 
04831    static Int_t it[4][4][3] = { { { 1,2, 3 }, { 0,0, 0 }, { 0,0, 0 }, { 0,0, 0 } },
04832                                 { { 1,2,-3 }, {-1,3, 4 }, { 0,0, 0 }, { 0,0, 0 } },
04833                                 { { 1,2,-3 }, {-1,3,-4 }, {-1,4, 5 }, { 0,0, 0 } },
04834                                 { { 1,2,-3 }, {-1,3,-4 }, {-4,6,-1 }, { 4,5,-6 } }
04835                               };
04836    Int_t it2[4][3], i, j;
04837 
04838    Int_t ie[6];
04839 
04840    // S E T   N O D E S   &   N O R M A L E S
04841    ie[0] = k1;
04842    ie[1] = k2;
04843    ie[2] = k3;
04844    ie[3] = k4;
04845    ie[4] = k5;
04846    ie[5] = k6;
04847    nnod  = 6;
04848    if (ie[5] == 0) nnod = 5;
04849    if (ie[4] == 0) nnod = 4;
04850    if (ie[3] == 0) nnod = 3;
04851    MarchingCubeFindNodes(nnod, ie, xyz, grad);
04852 
04853    // S E T   T R I A N G L E S
04854    ntria = nnod - 2;
04855    // Copy "it" into a 2D matrix to be passed to MarchingCubeSetTriangles
04856    for ( i=0; i<3 ; i++) {
04857       for ( j=0; j<4 ; j++) {
04858          it2[j][i] = it[ntria-1][j][i];
04859       }
04860    }
04861    MarchingCubeSetTriangles(ntria, it2, itria);
04862 }
04863 
04864 
04865 //______________________________________________________________________________
04866 void TPainter3dAlgorithms::MarchingCubeCase03(Int_t &nnod, Int_t &ntria,
04867                                Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
04868 {
04869    // Consider case No 3
04870    //
04871    // Input: see common HCMCUB
04872    //
04873    // Output: the same as for IHMCUB
04874 
04875    Double_t f0;
04876    static Int_t ie[6]     = { 4,9,1, 2,11,3 };
04877    static Int_t it1[2][3] = { { 1,2,3 }, { 4,5,6 } };
04878    static Int_t it2[4][3] = { { 1,2,-5 }, { -1,5,6 }, { 5,-2,4 }, { -4,2,3 } };
04879 
04880    //  S E T   N O D E S   &   N O R M A L E S
04881    nnod = 6;
04882    MarchingCubeFindNodes(nnod, ie, xyz, grad);
04883 
04884    //  F I N D   C O N F I G U R A T I O N
04885    f0 = (fF8[0]*fF8[2]-fF8[1]*fF8[3]) / (fF8[0]+fF8[2]-fF8[1]-fF8[3]);
04886    if (f0>=0. && fF8[0]>=0.) goto L100;
04887    if (f0<0. && fF8[0]<0.) goto L100;
04888    ntria = 2;
04889    MarchingCubeSetTriangles(ntria, it1, itria);
04890    return;
04891 
04892    //  N O T   S E P A R A T E D   F R O N T   F A C E
04893 L100:
04894    ntria = 4;
04895    MarchingCubeSetTriangles(ntria, it2, itria);
04896 }
04897 
04898 
04899 //______________________________________________________________________________
04900 void TPainter3dAlgorithms::MarchingCubeCase04(Int_t &nnod, Int_t &ntria,
04901                                Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
04902 {
04903    // Consider case No 4
04904    //
04905    // Input: see common HCMCUB
04906    //
04907    // Output: the same as for IHMCUB
04908 
04909    Int_t irep;
04910    static Int_t ie[6]     = { 4,9,1, 7,11,6 };
04911    static Int_t it1[2][3] = { { 1,2,3 }, { 4,5,6 } };
04912    static Int_t it2[6][3] = { { 1,2,4 }, { 2,3,6 }, { 3,1,5 },
04913                               { 4,5,1 }, { 5,6,3 }, { 6,4,2 } };
04914 
04915    //  S E T   N O D E S   &   N O R M A L E S
04916    nnod = 6;
04917    MarchingCubeFindNodes(nnod, ie, xyz, grad);
04918 
04919    //  I S   T H E R E   S U R F A C E   P E N E T R A T I O N ?
04920    MarchingCubeSurfacePenetration(fF8[0], fF8[1], fF8[2], fF8[3],
04921                                   fF8[4], fF8[5], fF8[6], fF8[7], irep);
04922    if (irep == 0) {
04923       ntria = 2;
04924       MarchingCubeSetTriangles(ntria, it1, itria);
04925    } else {
04926       ntria = 6;
04927       MarchingCubeSetTriangles(ntria, it2, itria);
04928    }
04929 }
04930 
04931 
04932 //______________________________________________________________________________
04933 void TPainter3dAlgorithms::MarchingCubeCase06(Int_t &nnod, Int_t &ntria,
04934                                Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
04935 {
04936    // Consider case No 6
04937    //
04938    // Input: see common HCMCUB
04939    //
04940    // Output: the same as for IHMCUB
04941 
04942    Double_t f0;
04943    Int_t irep;
04944 
04945    static Int_t ie[7]     = { 2,4,9,10, 6,7,11 };
04946    static Int_t it1[5][3] = { { 6,7,-1 }, { -6,1,2 }, { 6,2,3 }, { 6,3,-4 }, { -6,4,5 } };
04947    static Int_t it2[3][3] = { { 1,2,-3 }, { -1,3,4 }, { 5,6,7 } };
04948    static Int_t it3[7][3] = { { 6,7,-1 }, { -6,1,2 }, { 6,2,3 }, { 6,3,-4 }, { -6,4,5 },
04949                               { 1,7,-5 }, { -1,5,4 } };
04950 
04951    //  S E T   N O D E S   &   N O R M A L E S
04952    nnod = 7;
04953    MarchingCubeFindNodes(nnod, ie, xyz, grad);
04954 
04955    //  F I N D   C O N F I G U R A T I O N
04956    f0 = (fF8[1]*fF8[6]-fF8[5]*fF8[2]) / (fF8[1]+fF8[6]-fF8[5]-fF8[2]);
04957    if (f0>=0. && fF8[1]>=0.) goto L100;
04958    if (f0<0. && fF8[1]<0.) goto L100;
04959 
04960    //  I S   T H E R E   S U R F A C E   P E N E T R A T I O N ?
04961    MarchingCubeSurfacePenetration(fF8[2], fF8[1], fF8[5], fF8[6],
04962                                   fF8[3], fF8[0], fF8[4], fF8[7], irep);
04963    if (irep == 1) {
04964       ntria = 7;
04965       MarchingCubeSetTriangles(ntria, it3, itria);
04966    } else {
04967       ntria = 3;
04968       MarchingCubeSetTriangles(ntria, it2, itria);
04969    }
04970    return;
04971 
04972    //  N O T   S E P A R A T E D   R I G H T   F A C E
04973 L100:
04974    ntria = 5;
04975    MarchingCubeSetTriangles(ntria, it1, itria);
04976 }
04977 
04978 
04979 //______________________________________________________________________________
04980 void TPainter3dAlgorithms::MarchingCubeCase07(Int_t &nnod, Int_t &ntria,
04981                                Double_t xyz[52][3], Double_t grad[52][3],
04982                                Int_t itria[48][3])
04983 {
04984    // Consider case No 7
04985    //
04986    // Input: see common HCMCUB
04987    //
04988    // Output: the same as for IHMCUB
04989 
04990    Double_t f1, f2, f3;
04991    Int_t icase, irep;
04992    static Int_t ie[9] = { 3,12,4, 1,10,2, 11,6,7 };
04993    static Int_t it[9][9][3] = {
04994    {{  1,2,3}, {  4,5,6}, {  7,8,9}, {  0,0,0}, {  0,0,0}, {  0,0,0}, {  0,0,0}, {  0,0,0}, {  0,0,0}},
04995    {{  1,2,3}, { 4,9,-7}, { -4,7,6}, { 9,4,-5}, { -9,5,8}, {  0,0,0}, {  0,0,0}, {  0,0,0}, {  0,0,0}},
04996    {{  4,5,6}, { 8,3,-1}, { -8,1,7}, { 3,8,-9}, { -3,9,2}, {  0,0,0}, {  0,0,0}, {  0,0,0}, {  0,0,0}},
04997    {{-10,2,3}, {10,3,-1}, {-10,1,7}, {10,7,-6}, {-10,6,4}, {10,4,-5}, {-10,5,8}, { 10,8,9}, {10,9,-2}},
04998    {{  7,8,9}, { 2,5,-6}, { -2,6,1}, { 5,2,-3}, { -5,3,4}, {  0,0,0}, {  0,0,0}, {  0,0,0}, {  0,0,0}},
04999    {{-10,1,2}, {10,2,-3}, {-10,3,4}, { 10,4,5}, {10,5,-8}, {-10,8,9}, {10,9,-7}, {-10,7,6}, {10,6,-1}},
05000    {{ 10,2,3}, {10,3,-4}, {-10,4,5}, {10,5,-6}, {-10,6,1}, {10,1,-7}, {-10,7,8}, {10,8,-9}, {-10,9,2}},
05001    {{  1,7,6}, { -4,2,3}, {-4,9,-2}, {-9,4,-5}, { -9,5,8}, {  0,0,0}, {  0,0,0}, {  0,0,0}, {  0,0,0}},
05002    {{ -1,9,2}, {  1,2,3}, { 1,3,-4}, { 6,-1,4}, {  6,4,5}, { 6,-5,7}, { -7,5,8}, {  7,8,9}, { 7,-9,1}}
05003    };
05004 
05005    Int_t it2[9][3], i, j;
05006 
05007    //  S E T   N O D E S   &   N O R M A L E S
05008    nnod = 9;
05009    MarchingCubeFindNodes(nnod, ie, xyz, grad);
05010 
05011    //  F I N D   C O N F I G U R A T I O N
05012    f1 = (fF8[2]*fF8[5]-fF8[1]*fF8[6]) / (fF8[2]+fF8[5]-fF8[1]-fF8[6]);
05013    f2 = (fF8[2]*fF8[7]-fF8[3]*fF8[6]) / (fF8[2]+fF8[7]-fF8[3]-fF8[6]);
05014    f3 = (fF8[2]*fF8[0]-fF8[1]*fF8[3]) / (fF8[2]+fF8[0]-fF8[1]-fF8[3]);
05015    icase = 1;
05016    if (f1>=0. && fF8[2] <0.) icase = icase + 1;
05017    if (f1 <0. && fF8[2]>=0.) icase = icase + 1;
05018    if (f2>=0. && fF8[2] <0.) icase = icase + 2;
05019    if (f2 <0. && fF8[2]>=0.) icase = icase + 2;
05020    if (f3>=0. && fF8[2] <0.) icase = icase + 4;
05021    if (f3 <0. && fF8[2]>=0.) icase = icase + 4;
05022    ntria = 5;
05023 
05024    switch ((int)icase) {
05025       case 1:  goto L100;
05026       case 2:  goto L400;
05027       case 3:  goto L400;
05028       case 4:  goto L200;
05029       case 5:  goto L400;
05030       case 6:  goto L200;
05031       case 7:  goto L200;
05032       case 8:  goto L300;
05033    }
05034 
05035 L100:
05036    ntria = 3;
05037    goto L400;
05038 
05039    //  F I N D   A D D I T I O N A L   P O I N T
05040 L200:
05041    nnod  = 10;
05042    ntria = 9;
05043 
05044    // Copy "it" into a 2D matrix to be passed to MarchingCubeMiddlePoint
05045    for ( i=0; i<3 ; i++) {
05046       for ( j=0; j<9 ; j++) {
05047          it2[j][i] = it[icase-1][j][i];
05048       }
05049    }
05050    MarchingCubeMiddlePoint(9, xyz, grad, it2, &xyz[nnod-1][0], &grad[nnod-1][0]);
05051    goto L400;
05052 
05053    //  I S   T H E R E   S U R F A C E   P E N E T R A T I O N ?
05054 L300:
05055    MarchingCubeSurfacePenetration(fF8[3], fF8[2], fF8[6], fF8[7],
05056                                   fF8[0], fF8[1], fF8[5], fF8[4], irep);
05057    if (irep != 2) goto L400;
05058 ///   IHMCTT(NTRIA,IT8,ITRIA)
05059    ntria = 9;
05060    icase = 9;
05061 
05062    //  S E T   T R I A N G L E S
05063 L400:
05064    // Copy "it" into a 2D matrix to be passed to MarchingCubeSetTriangles
05065    for ( i=0; i<3 ; i++) {
05066       for ( j=0; j<9 ; j++) {
05067          it2[j][i] = it[icase-1][j][i];
05068       }
05069    }
05070    MarchingCubeSetTriangles(ntria, it2, itria);
05071 }
05072 
05073 
05074 //______________________________________________________________________________
05075 void TPainter3dAlgorithms::MarchingCubeCase10(Int_t &nnod, Int_t &ntria,
05076                                Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
05077 {
05078    // Consider case No 10
05079    //
05080    // Input: see common HCMCUB
05081    //
05082    // Output: the same as for IHMCUB
05083 
05084    Double_t f1, f2;
05085    Int_t icase, irep;
05086    static Int_t ie[8] = { 1,3,12,9, 5,7,11,10 };
05087    static Int_t it[6][8][3] = {
05088    {{1,2,-3}, {-1,3,4}, {5,6,-7}, {-5,7,8}, { 0,0,0}, { 0,0,0}, { 0,0,0}, { 0,0,0}},
05089    {{ 9,1,2}, { 9,2,3}, { 9,3,4}, { 9,4,5}, { 9,5,6}, { 9,6,7}, { 9,7,8}, { 9,8,1}},
05090    {{ 9,1,2}, { 9,4,1}, { 9,3,4}, { 9,6,3}, { 9,5,6}, { 9,8,5}, { 9,7,8}, { 9,2,7}},
05091    {{1,2,-7}, {-1,7,8}, {5,6,-3}, {-5,3,4}, { 0,0,0}, { 0,0,0}, { 0,0,0}, { 0,0,0}},
05092    {{1,2,-7}, {-1,7,8}, {2,3,-6}, {-2,6,7}, {3,4,-5}, {-3,5,6}, {4,1,-8}, {-4,8,5}},
05093    {{1,2,-3}, {-1,3,4}, {2,7,-6}, {-2,6,3}, {7,8,-5}, {-7,5,6}, {8,1,-4}, {-8,4,5}}
05094    };
05095    Int_t it2[8][3], i, j;
05096 
05097    //  S E T   N O D E S   &   N O R M A L E S
05098    nnod = 8;
05099    MarchingCubeFindNodes(nnod, ie, xyz, grad);
05100 
05101    //  F I N D   C O N F I G U R A T I O N
05102    f1 = (fF8[0]*fF8[5]-fF8[1]*fF8[4]) / (fF8[0]+fF8[5]-fF8[1]-fF8[4]);
05103    f2 = (fF8[3]*fF8[6]-fF8[2]*fF8[7]) / (fF8[3]+fF8[6]-fF8[2]-fF8[5]);
05104    icase = 1;
05105    if (f1 >= 0.) icase = icase + 1;
05106    if (f2 >= 0.) icase = icase + 2;
05107    if (icase==1 || icase==4) goto L100;
05108 
05109    // D I F F E R E N T    T O P   A N D   B O T T O M
05110    nnod  = 9;
05111    ntria = 8;
05112    // Copy "it" into a 2D matrix to be passed to MarchingCubeMiddlePoint
05113    for ( i=0; i<3 ; i++) {
05114       for ( j=0; j<8 ; j++) {
05115          it2[j][i] = it[icase-1][j][i];
05116       }
05117    }
05118    MarchingCubeMiddlePoint(8, xyz, grad, it2, &xyz[nnod-1][0], &grad[nnod-1][0]);
05119    goto L200;
05120 
05121    //  I S   T H E R E   S U R F A C E   P E N E T R A T I O N ?
05122 L100:
05123    MarchingCubeSurfacePenetration(fF8[0], fF8[1], fF8[5], fF8[4],
05124                                   fF8[3], fF8[2], fF8[6], fF8[7], irep);
05125    ntria = 4;
05126    if (irep == 0) goto L200;
05127    //  "B O T T L E   N E C K"
05128    ntria = 8;
05129    if (icase == 1) icase = 5;
05130    if (icase == 4) icase = 6;
05131 
05132    //  S E T   T R I A N G L E S
05133 L200:
05134    // Copy "it" into a 2D matrix to be passed to MarchingCubeSetTriangles
05135    for ( i=0; i<3 ; i++) {
05136       for ( j=0; j<8 ; j++) {
05137          it2[j][i] = it[icase-1][j][i];
05138       }
05139    }
05140    MarchingCubeSetTriangles(ntria, it2, itria);
05141 }
05142 
05143 
05144 //______________________________________________________________________________
05145 void TPainter3dAlgorithms::MarchingCubeCase12(Int_t &nnod, Int_t &ntria,
05146                                Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
05147 {
05148    // Consider case No 12
05149    //
05150    // Input: see common HCMCUB
05151    //
05152    // Output: the same as for IHMCUB
05153 
05154    Double_t f1, f2;
05155    Int_t icase, irep;
05156    static Int_t ie[8] = { 3,12,4, 1,9,8,6,2 };
05157    static Int_t it[6][8][3] = {
05158    {{ 1,2,3},  {4,5,-6}, {-4,6,8}, { 6,7,8}, { 0,0,0}, { 0,0,0}, { 0,0,0}, { 0,0,0}},
05159    {{-9,1,2},  {9,2,-3}, {-9,3,4}, {9,4,-5}, {-9,5,6}, {9,6,-7}, {-9,7,8}, {9,8,-1}},
05160    {{9,1,-2},  {-9,2,6}, {9,6,-7}, {-9,7,8}, {9,8,-4}, {-9,4,5}, {9,5,-3}, {-9,3,1}},
05161    {{ 3,4,5},  {1,2,-6}, {-1,6,8}, { 6,7,8}, { 0,0,0}, { 0,0,0}, { 0,0,0}, { 0,0,0}},
05162    {{ 7,8,6},  {6,8,-1}, {-6,1,2}, {3,1,-8}, {-3,8,4}, { 3,4,5}, {3,5,-6}, {-3,6,2}},
05163    {{ 7,8,6},  {6,8,-4}, {-6,4,5}, {3,4,-8}, {-3,8,1}, { 3,1,2}, {3,2,-6}, {-3,6,5}}
05164    };
05165    Int_t it2[8][3], i, j;
05166 
05167    //  S E T   N O D E S   &   N O R M A L E S
05168    nnod = 8;
05169    MarchingCubeFindNodes(nnod, ie, xyz, grad);
05170 
05171    //  F I N D   C O N F I G U R A T I O N
05172    f1 = (fF8[0]*fF8[2]-fF8[1]*fF8[3]) / (fF8[0]+fF8[2]-fF8[1]-fF8[3]);
05173    f2 = (fF8[0]*fF8[7]-fF8[3]*fF8[4]) / (fF8[0]+fF8[7]-fF8[3]-fF8[4]);
05174    icase = 1;
05175    if (f1 >= 0.) icase = icase + 1;
05176    if (f2 >= 0.) icase = icase + 2;
05177    if (icase==1 || icase==4) goto L100;
05178 
05179    //  F I N D   A D D I T I O N A L   P O I N T
05180    nnod  = 9;
05181    ntria = 8;
05182    // Copy "it" into a 2D matrix to be passed to MarchingCubeMiddlePoint
05183    for ( i=0; i<3 ; i++) {
05184       for ( j=0; j<8 ; j++) {
05185          it2[j][i] = it[icase-1][j][i];
05186       }
05187    }
05188    MarchingCubeMiddlePoint(8, xyz, grad, it2, &xyz[nnod-1][0], &grad[nnod-1][0]);
05189    goto L200;
05190 
05191    //  I S   T H E R E   S U R F A C E   P E N E T R A T I O N ?
05192 L100:
05193    MarchingCubeSurfacePenetration(fF8[0], fF8[1], fF8[2], fF8[3],
05194                                   fF8[4], fF8[5], fF8[6], fF8[7], irep);
05195    ntria = 4;
05196    if (irep != 1) goto L200;
05197    //  "B O T T L E   N E C K"
05198    ntria = 8;
05199    if (icase == 1) icase = 5;
05200    if (icase == 4) icase = 6;
05201 
05202    //  S E T   T R I A N G L E S
05203 L200:
05204    // Copy "it" into a 2D matrix to be passed to MarchingCubeSetTriangles
05205    for ( i=0; i<3 ; i++) {
05206       for ( j=0; j<8 ; j++) {
05207          it2[j][i] = it[icase-1][j][i];
05208       }
05209    }
05210    MarchingCubeSetTriangles(ntria, it2, itria);
05211 }
05212 
05213 
05214 //______________________________________________________________________________
05215 void TPainter3dAlgorithms::MarchingCubeCase13(Int_t &nnod, Int_t &ntria,
05216                                Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
05217 {
05218    // Consider case No 13
05219    //
05220    // Input: see common HCMCUB
05221    //
05222    // Output: the same as for IHMCUB
05223 
05224    Double_t ff[8];
05225    Double_t f1, f2, f3, f4;
05226    Int_t nr, nf, i, k, incr, n, kr, icase, irep;
05227    static Int_t irota[12][8] = {
05228          {1,2,3,4,5,6,7,8}, {1,5,6,2,4,8,7,3}, {1,4,8,5,2,3,7,6},
05229          {3,7,8,4,2,6,5,1}, {3,2,6,7,4,1,5,8}, {3,4,1,2,7,8,5,6},
05230          {6,7,3,2,5,8,4,1}, {6,5,8,7,2,1,4,3}, {6,2,1,5,7,3,4,8},
05231          {8,4,3,7,5,1,2,6}, {8,5,1,4,7,6,2,3}, {8,7,6,5,4,3,2,1} };
05232    static Int_t iwhat[8] = { 63,62,54,26,50,9,1,0 };
05233    static Int_t ie[12] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
05234    static Int_t iface[6][4] = {
05235          {1,2,3,4}, {5,6,7,8}, {1,2,6,5}, {2,6,7,3}, {4,3,7,8}, {1,5,8,4} };
05236    static Int_t it1[4][3] = { {1,2,10}, {9,5,8}, {6,11,7}, {3,4,12} };
05237    static Int_t it2[4][3] = { {5,6,10}, {1,4,9}, {2,11,3}, {7,8,12} };
05238    static Int_t it3[6][3] = { {10,12,-3}, {-10,3,2}, {12,10,-1}, {-12,1,4},
05239          {9,5,8}, {6,11,7} };
05240    static Int_t it4[6][3] = { {11,9,-1}, {-11,1,2}, {9,11,-3}, {-9,3,4},
05241          {5,6,10}, {7,8,12} };
05242    static Int_t it5[10][3] = { {13,2,-11}, {-13,11,7}, {13,7,-6}, {-13,6,10},
05243          {13,10,1}, {13,1,-4}, {-13,4,12}, {13,12,-3}, {-13,3,2}, {5,8,9} };
05244    static Int_t it6[10][3] = { {13,2,-10}, {-13,10,5}, {13,5,-6}, {-13,6,11},
05245          {13,11,3}, {13,3,-4}, {-13,4,9}, {13,9,-1}, {-13,1,2}, {12,7,8} };
05246    static Int_t it7[12][3] = { {13,2,-11}, {-13,11,7}, {13,7,-6}, {-13,6,10},
05247          {13,10,-5}, {-13,5,8}, {13,8,-9}, {-13,9,1},
05248          {13,1,-4}, {-13,4,12}, {13,12,-3}, {-13,3,2} };
05249    static Int_t it8[6][3] = { {3,8,12}, {3,-2,-8}, {-2,5,-8}, {2,10,-5},
05250          {7,6,11}, {1,4,9} };
05251    static Int_t it9[10][3] = { {7,12,-3}, {-7,3,11}, {11,3,2}, {6,11,-2}, {-6,2,10},
05252          {6,10,5}, {7,6,-5}, {-7,5,8}, {7,8,12}, {1,4,9} };
05253    static Int_t it10[10][3] = { {9,1,-10}, {-9,10,5}, {9,5,8}, {4,9,-8}, {-4,8,12},
05254          {4,12,3}, {1,4,-3}, {-1,3,2}, {1,2,10}, {7,6,11} };
05255 
05256       nnod = 0;
05257       ntria = 0;
05258 
05259    // F I N D   C O N F I G U R A T I O N   T Y P E
05260    for ( nr=1 ; nr<=12 ; nr++ ) {
05261       k = 0;
05262       incr = 1;
05263       for ( nf=1 ; nf<=6 ; nf++ ) {
05264          f1 = fF8[irota[nr-1][iface[nf-1][0]-1]-1];
05265          f2 = fF8[irota[nr-1][iface[nf-1][1]-1]-1];
05266          f3 = fF8[irota[nr-1][iface[nf-1][2]-1]-1];
05267          f4 = fF8[irota[nr-1][iface[nf-1][3]-1]-1];
05268          if ((f1*f3-f2*f4)/(f1+f3-f2-f4) >= 0.) k = k + incr;
05269          incr = incr + incr;
05270       }
05271       for ( i=1 ; i<=8 ; i++ ) {
05272          if (k != iwhat[i-1]) continue;
05273          icase = i;
05274          kr = nr;
05275          goto L200;
05276       }
05277    }
05278    Error("MarchingCubeCase13", "configuration is not found");
05279    return;
05280 
05281    //  R O T A T E   C U B E
05282 L200:
05283    if (icase==1 || icase==8) goto L300;
05284    for ( n=1 ; n<=8 ; n++) {
05285       k = irota[kr-1][n-1];
05286       ff[n-1] = fF8[k-1];
05287       for ( i=1 ; i<=3 ; i++ ) {
05288          xyz[n-1][i-1] = fP8[k-1][i-1];
05289          grad[n-1][i-1] = fG8[k-1][i-1];
05290       }
05291    }
05292    for ( n=1 ; n<=8 ; n++ ) {
05293       fF8[n-1] = ff[n-1];
05294       for ( i=1 ; i<=3 ; i++ ) {
05295          fP8[n-1][i-1] = xyz[n-1][i-1];
05296          fG8[n-1][i-1] = grad[n-1][i-1];
05297       }
05298    }
05299 
05300    //  S E T   N O D E S   &   N O R M A L E S
05301 L300:
05302    nnod = 12;
05303    MarchingCubeFindNodes(nnod, ie, xyz, grad);
05304 
05305    //  V A R I O U S   C O N F I G U R A T I O N S
05306    switch ((int)icase) {
05307       case 1:
05308          ntria = 4;
05309          MarchingCubeSetTriangles(ntria, it1, itria);
05310          return;
05311       case 8:
05312          ntria = 4;
05313          MarchingCubeSetTriangles(ntria, it2, itria);
05314          return;
05315       case 2:
05316          ntria = 6;
05317          MarchingCubeSetTriangles(ntria, it3, itria);
05318          return;
05319       case 7:
05320          ntria = 6;
05321          MarchingCubeSetTriangles(ntria, it4, itria);
05322          return;
05323       case 3:
05324          nnod = 13;
05325          ntria = 10;
05326          MarchingCubeMiddlePoint(9, xyz, grad, it5,
05327                                  &xyz[nnod-1][0], &grad[nnod-1][0]);
05328          MarchingCubeSetTriangles(ntria, it5, itria);
05329          return;
05330       case 6:
05331          nnod = 13;
05332          ntria = 10;
05333          MarchingCubeMiddlePoint(9, xyz, grad, it6,
05334                                  &xyz[nnod-1][0], &grad[nnod-1][0]);
05335          MarchingCubeSetTriangles(ntria, it6, itria);
05336          return;
05337       case 5:
05338          nnod = 13;
05339          ntria = 12;
05340          MarchingCubeMiddlePoint(12, xyz, grad, it7,
05341                                  &xyz[nnod-1][0], &grad[nnod-1][0]);
05342          MarchingCubeSetTriangles(ntria, it7, itria);
05343          return;
05344       //  I S   T H E R E   S U R F A C E   P E N E T R A T I O N ?
05345       case 4:
05346          MarchingCubeSurfacePenetration(fF8[2], fF8[3], fF8[0], fF8[1],
05347                                         fF8[6], fF8[7], fF8[4], fF8[5], irep);
05348          switch ((int)(irep+1)) {
05349             case 1:
05350                ntria = 6;
05351                MarchingCubeSetTriangles(ntria, it8, itria);
05352                return;
05353             case 2:
05354                ntria = 10;
05355                MarchingCubeSetTriangles(ntria, it9, itria);
05356                return;
05357             case 3:
05358                ntria = 10;
05359                MarchingCubeSetTriangles(ntria, it10, itria);
05360          }
05361    }
05362 }
05363 
05364 
05365 //______________________________________________________________________________
05366 void TPainter3dAlgorithms::MarchingCubeSetTriangles(Int_t ntria, Int_t it[][3],
05367                                                     Int_t itria[48][3])
05368 {
05369    // Set triangles (if parameter IALL=1, all edges will be visible)
05370    //
05371    // Input: NTRIA   - number of triangles
05372    //        IT(3,*) - triangles
05373    //
05374    // Output: ITRIA(3,*) - triangles
05375 
05376    Int_t n, i, k;
05377 
05378    for ( n=1 ; n<=ntria ; n++ ) {
05379       for ( i=1 ; i<=3 ; i++ ) {
05380          k = it[n-1][i-1];
05381          itria[n-1][i-1] = k;
05382       }
05383    }
05384 }
05385 
05386 
05387 //______________________________________________________________________________
05388 void TPainter3dAlgorithms::MarchingCubeMiddlePoint(Int_t nnod, Double_t xyz[52][3],
05389                                     Double_t grad[52][3],
05390                                     Int_t it[][3], Double_t *pxyz,
05391                                     Double_t *pgrad)
05392 {
05393    // Find middle point of a polygon
05394    //
05395    // Input: NNOD      - number of nodes in the polygon
05396    //        XYZ(3,*)  - node coordinates
05397    //        GRAD(3,*) - node normales
05398    //        IT(3,*)   - division of the polygons into triangles
05399    //
05400    // Output: PXYZ(3)  - middle point coordinates
05401    //         PGRAD(3) - middle point normale
05402 
05403    Double_t p[3], g[3];
05404    Int_t i, n, k;
05405 
05406    for ( i=1 ; i<=3 ; i++ ) {
05407       p[i-1] = 0.;
05408       g[i-1] = 0.;
05409    }
05410    for ( n=1 ; n<=nnod ; n++ ) {
05411       k = it[n-1][2];
05412       if (k < 0) k =-k;
05413       for ( i=1 ; i<=3 ; i++ ) {
05414          p[i-1] = p[i-1] + xyz[k-1][i-1];
05415          g[i-1] = g[i-1] + grad[k-1][i-1];
05416       }
05417    }
05418    for ( i=1 ; i<=3 ; i++ ) {
05419       pxyz[i-1] = p[i-1] / nnod;
05420       pgrad[i-1] = g[i-1] / nnod;
05421    }
05422 }
05423 
05424 
05425 //______________________________________________________________________________
05426 void TPainter3dAlgorithms::MarchingCubeSurfacePenetration(Double_t a00, Double_t a10,
05427                                            Double_t a11, Double_t a01,
05428                                            Double_t b00, Double_t b10,
05429                                            Double_t b11, Double_t b01,
05430                                            Int_t &irep)
05431 {
05432    // Check for surface penetration ("bottle neck")
05433    //
05434    // Input: A00,A10,A11,A01 - vertex values for 1st face
05435    //        B00,B10,B11,B01 - vertex values for opposite face
05436    //
05437    // Output: IREP - 1,2 - there is surface penetration
05438    //                0   - there is not surface penetration
05439 
05440    Double_t a, b, c, d, s0, s1, s2;
05441    Int_t iposa, iposb;
05442 
05443    irep = 0;
05444    a = (a11-a01)*(b00-b10) - (a00-a10)*(b11-b01);
05445    if (a == 0.) return;
05446    b = a01*(b00-b10)-(a11-a01)*b00-(a00-a10)*b01+a00*(b11-b01);
05447    c = a00*b01 - a01*b00;
05448    d = b*b-4*a*c;
05449    if (d <= 0.) return;
05450    d = TMath::Sqrt(d);
05451    if (TMath::Abs(-b+d) > TMath::Abs(2*a)) return;
05452    s1 = (-b+d) / (2*a);
05453    if (s1<0. || s1>1.) return;
05454    if (TMath::Abs(-b-d) > TMath::Abs(2*a)) return;
05455    s2 = (-b-d) / (2*a);
05456    if (s2<0. || s2>1.) return;
05457 
05458    //  C A S E   N O   4 ?
05459    iposa = 0;
05460    if (a00 >= 0) iposa = iposa + 1;
05461    if (a01 >= 0) iposa = iposa + 2;
05462    if (a10 >= 0) iposa = iposa + 4;
05463    if (a11 >= 0) iposa = iposa + 8;
05464    if (iposa==6 || iposa==9) goto L100;
05465    irep = 1;
05466    return;
05467 
05468    //  N O T   C A S E   N O   4
05469 L100:
05470    s0 = (a00-a01) / (a00+a11-a10-a01);
05471    if (s1>=s0 && s2<s0) return;
05472    if (s1<s0 && s2>=s0) return;
05473    irep = 1;
05474    if (s1 >= s0) irep = 2;
05475 
05476    //  C A S E S   N O   10, 13 ?
05477    iposb = 0;
05478    if (b00 >= 0) iposb = iposb + 1;
05479    if (b01 >= 0) iposb = iposb + 2;
05480    if (b10 >= 0) iposb = iposb + 4;
05481    if (b11 >= 0) iposb = iposb + 8;
05482    if (iposb!=6 && iposb!=9)  return;
05483    s0 = (b00-b01) / (b00+b11-b10-b01);
05484    if (iposa != iposb) goto L200;
05485    //  C A S E   N O   10
05486    if (irep==1 && s1>s0) return;
05487    if (irep==2 && s1<s0) return;
05488    irep = 0;
05489    return;
05490    //  C A S E   N O   13
05491 L200:
05492    if (irep==1 && s1<s0) return;
05493    if (irep==2 && s1>s0) return;
05494    irep = 0;
05495 }
05496 
05497 
05498 //______________________________________________________________________________
05499 void TPainter3dAlgorithms::MarchingCubeFindNodes(Int_t nnod,
05500                                   Int_t *ie, Double_t xyz[52][3],
05501                                   Double_t grad[52][3])
05502 {
05503    // Find nodes and normales
05504    //
05505    // Input: NNOD  - number of nodes
05506    //        IE(*) - edges which have section node
05507    //
05508    // Output: XYZ(3,*)  - nodes
05509    //         GRAD(3,*) - node normales (not normalized)
05510 
05511    Int_t n, k, i, n1, n2;
05512    Double_t t;
05513    static Int_t iedge[12][2] = {
05514          {1,2}, {2,3}, {3,4}, {4,1}, {5,6}, {6,7}, {7,8}, {8,5}, {1,5}, {2,6}, {3,7}, {4,8} };
05515 
05516    for ( n=1 ; n<=nnod ; n++ ) {
05517       k = ie[n-1];
05518       if (k < 0) k =-k;
05519       n1 = iedge[k-1][0];
05520       n2 = iedge[k-1][1];
05521       t = fF8[n1-1] / (fF8[n1-1]-fF8[n2-1]);
05522       for ( i=1 ; i<=3 ; i++ ) {
05523          xyz[n-1][i-1] = (fP8[n2-1][i-1]-fP8[n1-1][i-1])*t + fP8[n1-1][i-1];
05524          grad[n-1][i-1] = (fG8[n2-1][i-1]-fG8[n1-1][i-1])*t + fG8[n1-1][i-1];
05525       }
05526    }
05527 }
05528 
05529 
05530 //______________________________________________________________________________
05531 void TPainter3dAlgorithms::ZDepth(Double_t xyz[52][3], Int_t &nface,
05532                                   Int_t iface[48][3], Double_t dface[48][6],
05533                                   Double_t abcd[48][4], Int_t *iorder)
05534 {
05535    // Z-depth algorithm for set of triangles
05536    //
05537    // Input: XYZ(3,*)   - nodes
05538    //        NFACE      - number of triangular faces
05539    //        IFACE(3,*) - faces (triangles)
05540    //
05541    // Arrays: DFACE(6,*) - array for min-max scopes
05542    //         ABCD(4,*)  - array for face plane equations
05543    //
05544    // Output: IORDER(*) - face order
05545 
05546    Int_t n, nf, i1, i2, i3, i, icur, k, itst, kface, kf, irep;
05547    Int_t nn[3], kk[3];
05548    Double_t wmin, wmax, a, b, c, q, zcur;
05549    Double_t v[2][3], abcdn[4], abcdk[4];
05550 
05551    //  S E T   I N I T I A L   O R D E R
05552    //  I G N O R E   V E R Y   S M A L L   F A C E S
05553    //  S E T   M I N - M A X   S C O P E S
05554    //  S E T   F A C E   P L A N E   E Q U A T I O N S
05555    nf = 0;
05556    for ( n=1 ; n<=nface ; n++ ) {
05557       i1 = TMath::Abs(iface[n-1][0]);
05558       i2 = TMath::Abs(iface[n-1][1]);
05559       i3 = TMath::Abs(iface[n-1][2]);
05560    //       A R E A   T E S T
05561       if (TMath::Abs(xyz[i2-1][0]-xyz[i1-1][0])<=kDel &&
05562           TMath::Abs(xyz[i2-1][1]-xyz[i1-1][1])<=kDel &&
05563           TMath::Abs(xyz[i2-1][2]-xyz[i1-1][2])<=kDel) continue;
05564       if (TMath::Abs(xyz[i3-1][0]-xyz[i2-1][0])<=kDel &&
05565           TMath::Abs(xyz[i3-1][1]-xyz[i2-1][1])<=kDel &&
05566           TMath::Abs(xyz[i3-1][2]-xyz[i2-1][2])<=kDel) continue;
05567       if (TMath::Abs(xyz[i1-1][0]-xyz[i3-1][0])<=kDel &&
05568           TMath::Abs(xyz[i1-1][1]-xyz[i3-1][1])<=kDel &&
05569           TMath::Abs(xyz[i1-1][2]-xyz[i3-1][2])<=kDel) continue;
05570    //       P R O J E C T I O N   T E S T
05571       if (TMath::Abs(xyz[i2-1][0]-xyz[i1-1][0])<=kDel &&
05572           TMath::Abs(xyz[i2-1][1]-xyz[i1-1][1])<=kDel &&
05573           TMath::Abs(xyz[i3-1][0]-xyz[i2-1][0])<=kDel &&
05574           TMath::Abs(xyz[i3-1][1]-xyz[i2-1][1])<=kDel &&
05575           TMath::Abs(xyz[i1-1][0]-xyz[i3-1][0])<=kDel &&
05576           TMath::Abs(xyz[i1-1][1]-xyz[i3-1][1])<=kDel) continue;
05577       nf = nf + 1;
05578       iorder[nf-1] = n;
05579    //       F I N D   M I N - M A X
05580       for ( i=1 ; i<=3 ; i++ ) {
05581          wmin = xyz[i1-1][i-1];
05582          wmax = xyz[i1-1][i-1];
05583          if (wmin > xyz[i2-1][i-1]) wmin = xyz[i2-1][i-1];
05584          if (wmax < xyz[i2-1][i-1]) wmax = xyz[i2-1][i-1];
05585          if (wmin > xyz[i3-1][i-1]) wmin = xyz[i3-1][i-1];
05586          if (wmax < xyz[i3-1][i-1]) wmax = xyz[i3-1][i-1];
05587          dface[n-1][i-1] = wmin;
05588          dface[n-1][i+2] = wmax;
05589       }
05590    //      F I N D   F A C E   E Q U A T I O N
05591       for ( i=1 ; i<=3 ; i++ ) {
05592          v[0][i-1] = xyz[i2-1][i-1] - xyz[i1-1][i-1];
05593          v[1][i-1] = xyz[i3-1][i-1] - xyz[i2-1][i-1];
05594       }
05595       a = (v[0][1]*v[1][2] - v[0][2]*v[1][1]);
05596       b = (v[0][2]*v[1][0] - v[0][0]*v[1][2]);
05597       c = (v[0][0]*v[1][1] - v[0][1]*v[1][0]);
05598       q = TMath::Sqrt(a*a+b*b+c*c);
05599       if (c < 0.) q =-q;
05600       a = a / q;
05601       b = b / q;
05602       c = c / q;
05603       abcd[n-1][0] = a;
05604       abcd[n-1][1] = b;
05605       abcd[n-1][2] = c;
05606       abcd[n-1][3] =-(a*xyz[i1-1][0] + b*xyz[i1-1][1] + c*xyz[i1-1][2]);
05607    }
05608    nface = nf;
05609    if (nf <= 1) return;
05610 
05611    //  S O R T   T R I A N G L E S   A L O N G   Z - M I N
05612    for ( icur=2 ; icur<=nface ; icur++ ) {
05613       k = iorder[icur-1];
05614       zcur = dface[k-1][2];
05615       for ( itst=icur-1 ; itst>=1 ; itst-- ) {
05616          k = iorder[itst-1];
05617          if (zcur < dface[k-1][2]) break;
05618          k = iorder[itst-1];
05619          iorder[itst-1] = iorder[itst];
05620          iorder[itst] = k;
05621       }
05622    }
05623 
05624    //  Z - D E P T H   A L G O R I T H M
05625    kface  = nface;
05626 L300:
05627    if (kface == 1) goto L900;
05628    nf = iorder[kface-1];
05629    if (nf < 0) nf =-nf;
05630    abcdn[0] = abcd[nf-1][0];
05631    abcdn[1] = abcd[nf-1][1];
05632    abcdn[2] = abcd[nf-1][2];
05633    abcdn[3] = abcd[nf-1][3];
05634    nn[0] = TMath::Abs(iface[nf-1][0]);
05635    nn[1] = TMath::Abs(iface[nf-1][1]);
05636    nn[2] = TMath::Abs(iface[nf-1][2]);
05637 
05638    //  I N T E R N A L   L O O P
05639    for ( k=kface-1 ; k>=1 ; k-- ) {
05640       kf = iorder[k-1];
05641       if (kf < 0) kf =-kf;
05642       if (dface[nf-1][5] > dface[kf-1][2]+kDel) goto L400;
05643       if (iorder[k-1] > 0) goto L900;
05644       goto L800;
05645 
05646    //  M I N - M A X   T E S T
05647 L400:
05648       if (dface[kf-1][0] >= dface[nf-1][3]-kDel) goto L800;
05649       if (dface[kf-1][3] <= dface[nf-1][0]+kDel) goto L800;
05650       if (dface[kf-1][1] >= dface[nf-1][4]-kDel) goto L800;
05651       if (dface[kf-1][4] <= dface[nf-1][1]+kDel) goto L800;
05652 
05653    //  K F   B E F O R E   N F ?
05654       kk[0] = TMath::Abs(iface[kf-1][0]);
05655       kk[1] = TMath::Abs(iface[kf-1][1]);
05656       kk[2] = TMath::Abs(iface[kf-1][2]);
05657       if (abcdn[0]*xyz[kk[0]-1][0]+abcdn[1]*xyz[kk[0]-1][1]+
05658           abcdn[2]*xyz[kk[0]-1][2]+abcdn[3] < -kDel) goto L500;
05659       if (abcdn[0]*xyz[kk[1]-1][0]+abcdn[1]*xyz[kk[1]-1][1]+
05660           abcdn[2]*xyz[kk[1]-1][2]+abcdn[3] < -kDel) goto L500;
05661       if (abcdn[0]*xyz[kk[2]-1][0]+abcdn[1]*xyz[kk[2]-1][1]+
05662           abcdn[2]*xyz[kk[2]-1][2]+abcdn[3] < -kDel) goto L500;
05663       goto L800;
05664 
05665    //  N F    A F T E R    K F ?
05666 L500:
05667       abcdk[0] = abcd[kf-1][0];
05668       abcdk[1] = abcd[kf-1][1];
05669       abcdk[2] = abcd[kf-1][2];
05670       abcdk[3] = abcd[kf-1][3];
05671       if (abcdk[0]*xyz[nn[0]-1][0]+abcdk[1]*xyz[nn[0]-1][1]+
05672           abcdk[2]*xyz[nn[0]-1][2]+abcdk[3] > kDel) goto L600;
05673       if (abcdk[0]*xyz[nn[1]-1][0]+abcdk[1]*xyz[nn[1]-1][1]+
05674           abcdk[2]*xyz[nn[1]-1][2]+abcdk[3] > kDel) goto L600;
05675       if (abcdk[0]*xyz[nn[2]-1][0]+abcdk[1]*xyz[nn[2]-1][1]+
05676           abcdk[2]*xyz[nn[2]-1][2]+abcdk[3] > kDel) goto L600;
05677       goto L800;
05678 
05679    //  E D G E   B Y   E D G E   T E S T
05680    //  K F - E D G E S   A G A I N S T   N F
05681 L600:
05682       for ( i=1 ; i<=3 ; i++ ) {
05683          i1 = kk[i-1];
05684          i2 = kk[0];
05685          if (i != 3) i2 = kk[i];
05686          TestEdge(kDel, xyz, i1, i2, nn, abcdn, irep);
05687          if ( irep<0 ) goto L700;
05688          if ( irep==0 ) continue;
05689          if ( irep>0 ) goto L800;
05690       }
05691    //  N F - E D G E S   A G A I N S T   K F
05692       for ( i=1 ; i<=3 ; i++ ) {
05693          i1 = nn[i-1];
05694          i2 = nn[0];
05695          if (i != 3) i2 = nn[i];
05696          TestEdge(kDel, xyz, i1, i2, kk, abcdk, irep);
05697          if ( irep<0 ) goto L800;
05698          if ( irep==0 ) continue;
05699          if ( irep>0 ) goto L700;
05700       }
05701       goto L800;
05702 
05703    //  C H A N G E   F A C E   O R D E R
05704 L700:
05705       kf = iorder[k-1];
05706       for ( i=k+1 ; i<=kface ; i++ ) {
05707          iorder[i-2] = iorder[i-1];
05708       }
05709       iorder[kface-1] =-kf;
05710       if (kf > 0) goto L300;
05711       goto L900;
05712 L800:
05713       continue;
05714    }
05715 
05716    //  N E X T   F A C E
05717 L900:
05718    if (iorder[kface-1] < 0) iorder[kface-1] =-iorder[kface-1];
05719    kface = kface - 1;
05720    if (kface > 0) goto L300;
05721 }
05722 
05723 
05724 //______________________________________________________________________________
05725 void TPainter3dAlgorithms::TestEdge(Double_t del, Double_t xyz[52][3], Int_t i1, Int_t i2,
05726                      Int_t iface[3], Double_t abcd[4], Int_t &irep)
05727 {
05728    // Test edge against face (triangle)
05729    //
05730    // Input: DEL      - precision
05731    //        XYZ(3,*) - nodes
05732    //        I1       - 1-st node of edge
05733    //        I2       - 2-nd node of edge
05734    //        IFACE(3) - triangular face
05735    //        ABCD(4)  - face plane
05736    //
05737    // Output: IREP:-1 - edge under face
05738    //               0 - no decision
05739    //              +1 - edge before face
05740 
05741    Int_t k, k1, k2, ixy, i;
05742    Double_t a, b, c, d1, d2, dd, xy, tmin, tmax, tmid, x, y, z;
05743    Double_t d[3], delta[3], t[2];
05744 
05745    irep  = 0;
05746 
05747    //  F I N D   I N T E R S E C T I O N   P O I N T S
05748    delta[0] = xyz[i2-1][0] - xyz[i1-1][0];
05749    delta[1] = xyz[i2-1][1] - xyz[i1-1][1];
05750    delta[2] = xyz[i2-1][2] - xyz[i1-1][2];
05751    if (TMath::Abs(delta[0])<=del && TMath::Abs(delta[1])<=del) return;
05752    ixy = 1;
05753    if (TMath::Abs(delta[1]) > TMath::Abs(delta[0])) ixy = 2;
05754    a = delta[1];
05755    b =-delta[0];
05756    c =-(a*xyz[i1-1][0] + b*xyz[i1-1][1]);
05757    d[0] = a*xyz[iface[0]-1][0] + b*xyz[iface[0]-1][1] + c;
05758    d[1] = a*xyz[iface[1]-1][0] + b*xyz[iface[1]-1][1] + c;
05759    d[2] = a*xyz[iface[2]-1][0] + b*xyz[iface[2]-1][1] + c;
05760    k = 0;
05761    for ( i=1 ; i<=3 ; i++ ) {
05762       k1 = i;
05763       k2 = i + 1;
05764       if (i == 3) k2 = 1;
05765       if (d[k1-1]>=0. && d[k2-1]>=0.) continue;
05766       if (d[k1-1] <0. && d[k2-1] <0.) continue;
05767       d1 = d[k1-1] / (d[k1-1] - d[k2-1]);
05768       d2 = d[k2-1] / (d[k1-1] - d[k2-1]);
05769       xy = d1*xyz[iface[k2-1]-1][ixy-1] - d2*xyz[iface[k1-1]-1][ixy-1];
05770       k = k + 1;
05771       t[k-1] = (xy-xyz[i1-1][ixy-1]) / delta[ixy-1];
05772       if (k == 2) goto L200;
05773    }
05774    return;
05775 
05776    //  C O M P A R E   Z - D E P T H
05777 L200:
05778    tmin = TMath::Min(t[0],t[1]);
05779    tmax = TMath::Max(t[0],t[1]);
05780    if (tmin>1. || tmax<0) return;
05781    if (tmin < 0.) tmin = 0.;
05782    if (tmax > 1.) tmax = 1.;
05783    tmid = (tmin + tmax) / 2.;
05784    x = delta[0]*tmid + xyz[i1-1][0];
05785    y = delta[1]*tmid + xyz[i1-1][1];
05786    z = delta[2]*tmid + xyz[i1-1][2];
05787    dd = abcd[0]*x + abcd[1]*y + abcd[2]*z + abcd[3];
05788    if (dd > del) goto L997;
05789    if (dd <-del) goto L998;
05790    return;
05791 
05792 L997:
05793    irep =+1;
05794    return;
05795 L998:
05796    irep =-1;
05797 }
05798 
05799 
05800 //______________________________________________________________________________
05801 void TPainter3dAlgorithms::IsoSurface (Int_t ns, Double_t *s, Int_t nx,
05802                                        Int_t ny, Int_t nz,
05803                                        Double_t *x, Double_t *y, Double_t *z,
05804                                        const char *chopt)
05805 {
05806    // Draw set of isosurfaces for a scalar function defined on a grid.
05807    //
05808    //     Input: NS          - number of isosurfaces
05809    //            S(*)        - isosurface values
05810    //            NX          - number of slices along X
05811    //            NY          - number of slices along Y
05812    //            NZ          - number of slices along Z
05813    //            X(*)        - slices along X
05814    //            Y(*)        - slices along Y
05815    //            Z(*)        - slices along Z
05816    //            F(NX,NY,NZ) - function values <- Not used, current histo used instead
05817    //
05818    //            DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
05819    //              ICODES(1) - isosurface number
05820    //              ICODES(2) - isosurface number
05821    //              ICODES(3) - isosurface number
05822    //              NP        - number of nodes in face
05823    //              IFACE(NP) - face
05824    //              T(NP)     - additional function (lightness)
05825    //
05826    //            CHOPT - options: 'BF' - from BACK to FRONT
05827    //                             'FB' - from FRONT to BACK
05828 
05829    Double_t p[8][3], pf[8], pn[8][3];
05830    Double_t p0[3], p1[3], p2[3], p3[3], t[3];
05831    Double_t fsurf, w, d1, d2, df1, df2;
05832    Int_t icodes[3];
05833    Int_t i, i1, i2, j, ibase, nnod, knod, ntria, ktria, iopt, iready;
05834    Int_t ixcrit, iycrit, izcrit, incrx, incry, incrz, incr;
05835    Int_t ix, ix1=0, ix2=0, iy, iy1=0, iy2=0, iz, iz1=0, iz2=0, k, kx, ky, kz, isurf, nsurf;
05836 
05837    Double_t xyz[kNmaxp][3], xyzn[kNmaxp][3], grad[kNmaxp][3];
05838    Double_t dtria[kNmaxt][6], abcd[kNmaxt][4];
05839    Int_t    itria[kNmaxt][3], iorder[kNmaxt], iattr[kNmaxt];
05840 
05841    static Int_t ind[8][3] = { { 0,0,0 }, { 1,0,0 }, { 1,0,1 }, { 0,0,1 },
05842                               { 0,1,0 }, { 1,1,0 }, { 1,1,1 }, { 0,1,1 } };
05843    for (i=0;i<kNmaxp;i++) {
05844       xyzn[i][0] = 0.;
05845       xyzn[i][1] = 0.;
05846       xyzn[i][2] = 0.;
05847    }
05848 
05849    TView *view = 0;
05850 
05851    if (gPad) view = gPad->GetView();
05852    if (!view) {
05853       Error("ImplicitFunction", "no TView in current pad");
05854       return;
05855    }
05856 
05857    nsurf = ns;
05858    if (nsurf > kNiso) {
05859       Warning("IsoSurface","Number of isosurfaces too large. Increase kNiso");
05860    }
05861    iopt = 2;
05862    if (*chopt == 'B' || *chopt == 'b') iopt = 1;
05863 
05864    //       F I N D   X - , Y - , Z - C R I T I C A L
05865    //       This logic works for parallel projection only.
05866    //       For central projection another logic should be implemented.
05867    p0[0] = x[0];
05868    p0[1] = y[0];
05869    p0[2] = z[0];
05870    view->WCtoNDC(p0, p0);
05871    p1[0] = x[nx-1];
05872    p1[1] = y[0];
05873    p1[2] = z[0];
05874    view->WCtoNDC(p1, p1);
05875    p2[0] = x[0];
05876    p2[1] = y[ny-1];
05877    p2[2] = z[0];
05878    view->WCtoNDC(p2, p2);
05879    p3[0] = x[0];
05880    p3[1] = y[0];
05881    p3[2] = z[nz-1];
05882    view->WCtoNDC(p3, p3);
05883    ixcrit = nx;
05884    iycrit = ny;
05885    izcrit = nz;
05886    if (p1[2] < p0[2]) ixcrit = 1;
05887    if (p2[2] < p0[2]) iycrit = 1;
05888    if (p3[2] < p0[2]) izcrit = 1;
05889 
05890    //       L O O P   A L O N G   G R I D
05891    //       This logic works for both (parallel & central) projections.
05892    incrx = 1;
05893    incry = 1;
05894    incrz = 1;
05895 L110:
05896    if (incrz >= 0) {
05897       if (iopt == 1) iz1 = 1;
05898       if (iopt == 1) iz2 = izcrit-1;
05899       if (iopt == 2) iz1 = izcrit;
05900       if (iopt == 2) iz2 = nz - 1;
05901    } else {
05902       if (iopt == 1) iz1 = nz - 1;
05903       if (iopt == 1) iz2 = izcrit;
05904       if (iopt == 2) iz1 = izcrit-1;
05905       if (iopt == 2) iz2 = 1;
05906    }
05907    for (iz = iz1; incrz < 0 ? iz >= iz2 : iz <= iz2; iz += incrz) {
05908 L120:
05909       if (incry >= 0) {
05910          if (iopt == 1) iy1 = 1;
05911          if (iopt == 1) iy2 = iycrit-1;
05912          if (iopt == 2) iy1 = iycrit;
05913          if (iopt == 2) iy2 = ny - 1;
05914       } else {
05915          if (iopt == 1) iy1 = ny - 1;
05916          if (iopt == 1) iy2 = iycrit;
05917          if (iopt == 2) iy1 = iycrit-1;
05918          if (iopt == 2) iy2 = 1;
05919       }
05920       for (iy = iy1; incry < 0 ? iy >= iy2 : iy <= iy2; iy += incry) {
05921 L130:
05922          if (incrx >= 0) {
05923             if (iopt == 1) ix1 = 1;
05924             if (iopt == 1) ix2 = ixcrit-1;
05925             if (iopt == 2) ix1 = ixcrit;
05926             if (iopt == 2) ix2 = nx - 1;
05927          } else {
05928             if (iopt == 1) ix1 = nx - 1;
05929             if (iopt == 1) ix2 = ixcrit;
05930             if (iopt == 2) ix1 = ixcrit-1;
05931             if (iopt == 2) ix2 = 1;
05932          }
05933          for (ix = ix1; incrx < 0 ? ix >= ix2 : ix <= ix2; ix += incrx) {
05934             nnod = 0;
05935             ntria = 0;
05936             iready = 0;
05937             for ( isurf=1 ; isurf<=nsurf ; isurf++ ) {
05938                fsurf = s[isurf-1];
05939                if (gCurrentHist->GetBinContent(ix,  iy,  iz)   >= fsurf)
05940                   goto L210;
05941                if (gCurrentHist->GetBinContent(ix+1,iy,  iz)   >= fsurf)
05942                   goto L220;
05943                if (gCurrentHist->GetBinContent(ix,  iy+1,iz)   >= fsurf)
05944                   goto L220;
05945                if (gCurrentHist->GetBinContent(ix+1,iy+1,iz)   >= fsurf)
05946                   goto L220;
05947                if (gCurrentHist->GetBinContent(ix,  iy,  iz+1) >= fsurf)
05948                   goto L220;
05949                if (gCurrentHist->GetBinContent(ix+1,iy,  iz+1) >= fsurf)
05950                   goto L220;
05951                if (gCurrentHist->GetBinContent(ix,  iy+1,iz+1) >= fsurf)
05952                   goto L220;
05953                if (gCurrentHist->GetBinContent(ix+1,iy+1,iz+1) >= fsurf)
05954                   goto L220;
05955                continue;
05956 L210:
05957                if (gCurrentHist->GetBinContent(ix+1,iy,  iz)   < fsurf)
05958                   goto L220;
05959                if (gCurrentHist->GetBinContent(ix,  iy+1,iz)   < fsurf)
05960                   goto L220;
05961                if (gCurrentHist->GetBinContent(ix+1,iy+1,iz)   < fsurf)
05962                   goto L220;
05963                if (gCurrentHist->GetBinContent(ix,  iy,  iz+1) < fsurf)
05964                   goto L220;
05965                if (gCurrentHist->GetBinContent(ix+1,iy,  iz+1) < fsurf)
05966                   goto L220;
05967                if (gCurrentHist->GetBinContent(ix,  iy+1,iz+1) < fsurf)
05968                   goto L220;
05969                if (gCurrentHist->GetBinContent(ix+1,iy+1,iz+1) < fsurf)
05970                   goto L220;
05971                continue;
05972 
05973    //       P R E P A R E   C U B E   ( P A R A L L E P I P E D )
05974 L220:
05975                if (iready !=0) goto L310;
05976                iready = 1;
05977                for ( i=1 ; i<=8 ; i++ ) {
05978                   kx = ix + ind[i-1][0];
05979                   ky = iy + ind[i-1][1];
05980                   kz = iz + ind[i-1][2];
05981                   p[i-1][0] = x[kx-1];
05982                   p[i-1][1] = y[ky-1];
05983                   p[i-1][2] = z[kz-1];
05984                   pf[i-1] = gCurrentHist->GetBinContent(kx,ky,kz);
05985    //       F I N D   X - G R A D I E N T
05986                   if (kx == 1) {
05987                      pn[i-1][0] = (gCurrentHist->GetBinContent(2,ky,kz) -
05988                                    gCurrentHist->GetBinContent(1,ky,kz)) /
05989                                    (x[1]-x[0]);
05990                   } else if (kx == nx) {
05991                      pn[i-1][0] = (gCurrentHist->GetBinContent(kx,ky,kz) -
05992                                    gCurrentHist->GetBinContent(kx-1,ky,kz)) /
05993                                    (x[kx-1]-x[kx-2]);
05994                   } else {
05995                      d1 = x[kx-1] - x[kx-2];
05996                      d2 = x[kx] - x[kx-1];
05997                      if (d1 == d2) {
05998                         pn[i-1][0] = (gCurrentHist->GetBinContent(kx+1,ky,kz) -
05999                                       gCurrentHist->GetBinContent(kx-1,ky,kz)) /
06000                                       (d1+d1);
06001                      } else {
06002                         df1 = gCurrentHist->GetBinContent(kx,ky,kz) -
06003                               gCurrentHist->GetBinContent(kx-1,ky,kz);
06004                         df2 = gCurrentHist->GetBinContent(kx+1,ky,kz) -
06005                               gCurrentHist->GetBinContent(kx,ky,kz);
06006                         pn[i-1][0] = (df1*d2*d2+df2*d1*d1)/(d1*d2*d2+d2*d1*d1);
06007                      }
06008                   }
06009    //       F I N D   Y - G R A D I E N T
06010                   if (ky == 1) {
06011                      pn[i-1][1] = (gCurrentHist->GetBinContent(kx,2,kz) -
06012                                    gCurrentHist->GetBinContent(kx,1,kz)) /
06013                                    (y[1]-y[0]);
06014                   } else if (ky == ny) {
06015                      pn[i-1][1] = (gCurrentHist->GetBinContent(kx,ky,kz) -
06016                                    gCurrentHist->GetBinContent(kx,ky-1,kz)) /
06017                                    (y[ky-1]-y[ky-2]);
06018                   } else {
06019                      d1 = y[ky-1] - y[ky-2];
06020                      d2 = y[ky] - y[ky-1];
06021                      if (d1 == d2) {
06022                         pn[i-1][1] = (gCurrentHist->GetBinContent(kx,ky+1,kz) -
06023                                       gCurrentHist->GetBinContent(kx,ky-1,kz)) /
06024                                       (d1+d1);
06025                      } else {
06026                         df1 = gCurrentHist->GetBinContent(kx,ky,kz) -
06027                               gCurrentHist->GetBinContent(kx,ky-1,kz);
06028                         df2 = gCurrentHist->GetBinContent(kx,ky+1,kz) -
06029                               gCurrentHist->GetBinContent(kx,ky,kz);
06030                         pn[i-1][1] = (df1*d2*d2+df2*d1*d1)/(d1*d2*d2+d2*d1*d1);
06031                      }
06032                   }
06033    //       F I N D   Z - G R A D I E N T
06034                   if (kz == 1) {
06035                      pn[i-1][2] = (gCurrentHist->GetBinContent(kx,ky,2) -
06036                                    gCurrentHist->GetBinContent(kx,ky,1)) /
06037                                    (z[1]-z[0]);
06038                   } else if (kz == nz) {
06039                      pn[i-1][2] = (gCurrentHist->GetBinContent(kx,ky,kz) -
06040                                    gCurrentHist->GetBinContent(kx,ky,kz-1)) /
06041                                    (z[kz-1]-z[kz-2]);
06042                   } else {
06043                      d1 = z[kz-1] - z[kz-2];
06044                      d2 = z[kz] - z[kz-1];
06045                      if (d1 == d2) {
06046                         pn[i-1][2] = (gCurrentHist->GetBinContent(kx,ky,kz+1) -
06047                                       gCurrentHist->GetBinContent(kx,ky,kz-1)) /
06048                                       (d1+d1);
06049                      } else {
06050                         df1 = gCurrentHist->GetBinContent(kx,ky,kz) -
06051                               gCurrentHist->GetBinContent(kx,ky,kz-1);
06052                         df2 = gCurrentHist->GetBinContent(kx,ky,kz+1) -
06053                               gCurrentHist->GetBinContent(kx,ky,kz);
06054                         pn[i-1][2] = (df1*d2*d2+df2*d1*d1)/(d1*d2*d2+d2*d1*d1);
06055                      }
06056                   }
06057                }
06058 
06059    //       F I N D   S E T   O F   T R I A N G L E S
06060 L310:
06061                Double_t xyz_tmp[kNmaxp][3], grad_tmp[kNmaxp][3];
06062                Int_t itria_tmp[kNmaxt][3], l;
06063 
06064                MarchingCube(s[isurf-1], p, pf, pn, knod, ktria,
06065                             xyz_tmp, grad_tmp, itria_tmp);
06066 
06067                for( l=0 ; l<knod ; l++) {
06068                   xyz[nnod+l][0] = xyz_tmp[l][0];
06069                   xyz[nnod+l][1] = xyz_tmp[l][1];
06070                   xyz[nnod+l][2] = xyz_tmp[l][2];
06071                   grad[nnod+l][0] = grad_tmp[l][0];
06072                   grad[nnod+l][1] = grad_tmp[l][1];
06073                   grad[nnod+l][2] = grad_tmp[l][2];
06074                }
06075                for( l=0 ; l<ktria ; l++) {
06076                   itria[ntria+l][0] = itria_tmp[l][0];
06077                   itria[ntria+l][1] = itria_tmp[l][1];
06078                   itria[ntria+l][2] = itria_tmp[l][2];
06079                }
06080 
06081                for ( i=ntria+1 ; i<=ntria+ktria ; i++ ) {
06082                  for ( j=1 ; j<=3 ; j++ ){
06083                      ibase = nnod;
06084                      if (itria[i-1][j-1] < 0) ibase =-nnod;
06085                      itria[i-1][j-1] = itria[i-1][j-1] + ibase;
06086                   }
06087                   iattr[i-1] = isurf;
06088                }
06089                nnod = nnod + knod;
06090                ntria = ntria + ktria;
06091             }
06092 
06093    //       D E P T H   S O R T,   D R A W I N G
06094             if (ntria == 0) continue;
06095             for ( i=1 ; i<=nnod ; i++ ) {
06096                view->WCtoNDC(&xyz[i-1][0], &xyzn[i-1][0]);
06097                Luminosity(&grad[i-1][0], w);
06098                grad[i-1][0] = w;
06099             }
06100             ZDepth(xyzn, ntria, itria, dtria, abcd, (Int_t*)iorder);
06101             if (ntria == 0) continue;
06102             incr = 1;
06103             if (iopt == 1) incr = -1;
06104             i1 = 1;
06105             if (incr == -1) i1 = ntria;
06106             i2 = ntria - i1 + 1;
06107             for (i = i1; incr < 0 ? i >= i2 : i <= i2; i += incr) {
06108                k = iorder[i-1];
06109                t[0] = grad[TMath::Abs(itria[k-1][0])-1][0];
06110                t[1] = grad[TMath::Abs(itria[k-1][1])-1][0];
06111                t[2] = grad[TMath::Abs(itria[k-1][2])-1][0];
06112                icodes[0] = iattr[k-1];
06113                icodes[1] = iattr[k-1];
06114                icodes[2] = iattr[k-1];
06115                DrawFaceGouraudShaded(icodes, xyz, 3, &itria[k-1][0], t);
06116             }
06117          }
06118          incrx = -incrx;
06119          if (incrx < 0) goto L130;
06120       }
06121       incry = -incry;
06122       if (incry < 0) goto L120;
06123    }
06124    incrz = -incrz;
06125    if (incrz < 0) goto L110;
06126 }
06127 
06128 //______________________________________________________________________________
06129 void TPainter3dAlgorithms::DrawFaceGouraudShaded(Int_t *icodes,
06130                                                  Double_t xyz[][3],
06131                                                  Int_t np, Int_t *iface,
06132                                                  Double_t *t)
06133 {
06134    // Draw the faces for the Gouraud Shaded Iso surfaces
06135 
06136    Int_t i, k, irep;
06137    Double_t p3[12][3];
06138    TView *view = 0;
06139 
06140    if (gPad) view = gPad->GetView();
06141    if (!view) {
06142       Error("ImplicitFunction", "no TView in current pad");
06143       return;
06144    }
06145 
06146    if (icodes[0]==1) Spectrum(fNcolor, fFmin, fFmax, fIc1, 1, irep);
06147    if (icodes[0]==2) Spectrum(fNcolor, fFmin, fFmax, fIc2, 1, irep);
06148    if (icodes[0]==3) Spectrum(fNcolor, fFmin, fFmax, fIc3, 1, irep);
06149    for ( i=1 ; i<=np ; i++) {
06150       k = iface[i-1];
06151       if (k<0) k = -k;
06152       view->WCtoNDC(&xyz[k-1][0], &p3[i-1][0]);
06153    }
06154 
06155    FillPolygon(np, (Double_t *)p3, (Double_t *)t);
06156 }

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