ROOT  6.06/09
Reference Guide
TPainter3dAlgorithms.cxx
Go to the documentation of this file.
1 // @(#)root/histpainter:$Id$
2 // Author: Rene Brun, Evgueni Tcherniaev, Olivier Couet 12/12/94
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 
13 ////////////////////////////////////////////////////////////////////////////////
14 
15 /*! \class TPainter3dAlgorithms
16 \ingroup Hist
17 \brief The Legos and Surfaces painter class.
18 
19 
20 
21 This package was originally written by Evgueni Tcherniaev from IHEP/Protvino.
22 
23 The original Fortran implementation was adapted to HIGZ/PAW by Olivier Couet
24 and Evgueni Tcherniaev.
25 
26 This class is a subset of the original system. It has been converted to a C++
27 class by Rene Brun.
28 */
29 
30 #include <stdlib.h>
31 
32 #include "TROOT.h"
33 #include "TPainter3dAlgorithms.h"
34 #include "TVirtualPad.h"
35 #include "THistPainter.h"
36 #include "TH1.h"
37 #include "TF3.h"
38 #include "TView.h"
39 #include "TVirtualX.h"
40 #include "Hoption.h"
41 #include "Hparam.h"
42 #include "TMath.h"
43 #include "TStyle.h"
44 #include "TObjArray.h"
45 #include "THLimitsFinder.h"
46 #include "TColor.h"
47 
49 const Double_t kFdel = 0.;
50 const Double_t kDel = 0.0001;
51 const Int_t kNiso = 4;
52 const Int_t kNmaxp = kNiso*13;
53 const Int_t kNmaxt = kNiso*12;
54 const Int_t kLmax = 12;
55 const Int_t kF3FillColor1 = 201;
56 const Int_t kF3FillColor2 = 202;
57 const Int_t kF3LineColor = 203;
58 
63 TF3 *TPainter3dAlgorithms::fgCurrentF3 = 0;
64 
65 // Static arrays used to paint stacked lego plots.
66 const Int_t kVSizeMax = 20;
74 
75 extern TH1 *gCurrentHist; //these 3 globals should be replaced by class members
76 extern Hoption_t Hoption;
77 extern Hparam_t Hparam;
78 
80 
81 
82 ////////////////////////////////////////////////////////////////////////////////
83 /// Lego default constructor
84 
86 {
87  Int_t i;
88  fIfrast = 0;
89  fMesh = 1;
90  fRaster = 0;
91  fColorTop = 1;
92  fColorBottom = 1;
93  fEdgeIdx = -1;
94  fNlevel = 0;
95  fSystem = kCARTESIAN;
96  fDrawFace = 0;
97  fLegoFunction = 0;
98  fSurfaceFunction = 0;
99 
100  TList *stack = 0;
101  if (gCurrentHist) stack = gCurrentHist->GetPainter()->GetStack();
102  fNStack = 0;
103  if (stack) fNStack = stack->GetSize();
104  if (fNStack > kVSizeMax) {
105  fColorMain = new Int_t[fNStack+1];
106  fColorDark = new Int_t[fNStack+1];
107  fEdgeColor = new Int_t[fNStack+1];
108  fEdgeStyle = new Int_t[fNStack+1];
109  fEdgeWidth = new Int_t[fNStack+1];
110  } else {
111  fColorMain = &gColorMain[0];
112  fColorDark = &gColorDark[0];
113  fEdgeColor = &gEdgeColor[0];
114  fEdgeStyle = &gEdgeStyle[0];
115  fEdgeWidth = &gEdgeWidth[0];
116  }
117 
118  for (i=0;i<fNStack;i++) { fColorMain[i] = 1; fColorDark[i] = 1; fEdgeColor[i] = 1; fEdgeStyle[i] = 1; fEdgeWidth[i] = 1; }
119  for (i=0;i<3;i++) { fRmin[i] = 0; fRmax[i] = 1; }
120  for (i=0;i<4;i++) { fYls[i] = 0; }
121 
122  for (i=0;i<30;i++) { fJmask[i] = 0; }
123  for (i=0;i<200;i++) { fLevelLine[i] = 0; }
124  for (i=0;i<465;i++) { fMask[i] = 0; }
125  for (i=0;i<258;i++) { fColorLevel[i] = 0; }
126  for (i=0;i<1200;i++) { fPlines[i] = 0.; }
127  for (i=0;i<200;i++) { fT[i] = 0.; }
128  for (i=0;i<2000;i++) { fU[i] = 0.; fD[i] = 0.; }
129  for (i=0;i<12;i++) { fVls[i] = 0.; }
130  for (i=0;i<257;i++) { fFunLevel[i] = 0.; }
131  for (i=0;i<183;i++) { fAphi[i] = 0.; }
132  for (i=0;i<8;i++) { fF8[i] = 0.; }
133 
134  fLoff = 0;
135  fNT = 0;
136  fNcolor = 0;
137  fNlines = 0;
138  fNqs = 0;
139  fNxrast = 0;
140  fNyrast = 0;
141  fIc1 = 0;
142  fIc2 = 0;
143  fIc3 = 0;
144  fQA = 0.;
145  fQD = 0.;
146  fQS = 0.;
147  fX0 = 0.;
148  fYdl = 0.;
149  fXrast = 0.;
150  fYrast = 0.;
151  fFmin = 0.;
152  fFmax = 0.;
153  fDXrast = 0.;
154  fDYrast = 0.;
155  fDX = 0.;
156 }
157 
158 
159 ////////////////////////////////////////////////////////////////////////////////
160 /// Normal default constructor
161 ///
162 /// rmin[3], rmax[3] are the limits of the lego object depending on
163 /// the selected coordinate system
164 
166  : TObject(), TAttLine(1,1,1), TAttFill(1,0)
167 {
168  Int_t i;
169  Double_t psi;
170 
171  fIfrast = 0;
172  fMesh = 1;
173  fRaster = 0;
174  fColorTop = 1;
175  fColorBottom = 1;
176  fEdgeIdx = -1;
177  fNlevel = 0;
178  fSystem = system;
179  if (system == kCARTESIAN || system == kPOLAR) psi = 0;
180  else psi = 90;
181  fDrawFace = 0;
182  fLegoFunction = 0;
183  fSurfaceFunction = 0;
184 
185  TList *stack = gCurrentHist->GetPainter()->GetStack();
186  fNStack = 0;
187  if (stack) fNStack = stack->GetSize();
188  if (fNStack > kVSizeMax) {
189  fColorMain = new Int_t[fNStack+1];
190  fColorDark = new Int_t[fNStack+1];
191  fEdgeColor = new Int_t[fNStack+1];
192  fEdgeStyle = new Int_t[fNStack+1];
193  fEdgeWidth = new Int_t[fNStack+1];
194  } else {
195  fColorMain = &gColorMain[0];
196  fColorDark = &gColorDark[0];
197  fEdgeColor = &gEdgeColor[0];
198  fEdgeStyle = &gEdgeStyle[0];
199  fEdgeWidth = &gEdgeWidth[0];
200  }
201 
202  for (i=0;i<fNStack;i++) { fColorMain[i] = 1; fColorDark[i] = 1; fEdgeColor[i] = 1; fEdgeStyle[i] = 1; fEdgeWidth[i] = 1; }
203  for (i=0;i<3;i++) { fRmin[i] = rmin[i]; fRmax[i] = rmax[i]; }
204  for (i=0;i<4;i++) { fYls[i] = 0; }
205 
206  for (i=0;i<30;i++) { fJmask[i] = 0; }
207  for (i=0;i<200;i++) { fLevelLine[i] = 0; }
208  for (i=0;i<465;i++) { fMask[i] = 0; }
209  for (i=0;i<258;i++) { fColorLevel[i] = 0; }
210  for (i=0;i<1200;i++) { fPlines[i] = 0.; }
211  for (i=0;i<200;i++) { fT[i] = 0.; }
212  for (i=0;i<2000;i++) { fU[i] = 0.; fD[i] = 0.; }
213  for (i=0;i<12;i++) { fVls[i] = 0.; }
214  for (i=0;i<257;i++) { fFunLevel[i] = 0.; }
215  for (i=0;i<183;i++) { fAphi[i] = 0.; }
216  for (i=0;i<8;i++) { fF8[i] = 0.; }
217 
218  fLoff = 0;
219  fNT = 0;
220  fNcolor = 0;
221  fNlines = 0;
222  fNqs = 0;
223  fNxrast = 0;
224  fNyrast = 0;
225  fIc1 = 0;
226  fIc2 = 0;
227  fIc3 = 0;
228  fQA = 0.;
229  fQD = 0.;
230  fQS = 0.;
231  fX0 = 0.;
232  fYdl = 0.;
233  fXrast = 0.;
234  fYrast = 0.;
235  fFmin = 0.;
236  fFmax = 0.;
237  fDXrast = 0.;
238  fDYrast = 0.;
239  fDX = 0.;
240 
241  TView *view = 0;
242  if (gPad) view = gPad->GetView();
243  if (!view) view = TView::CreateView(fSystem, rmin, rmax);
244  if (view) {
245  view->SetView(gPad->GetPhi(), gPad->GetTheta(), psi, i);
246  view->SetRange(rmin,rmax);
247  }
248 }
249 
250 
251 ////////////////////////////////////////////////////////////////////////////////
252 /// Lego default destructor
253 
255 {
256  if (fRaster) {delete [] fRaster; fRaster = 0;}
257  if (fNStack > kVSizeMax) {
258  delete [] fColorMain;
259  delete [] fColorDark;
260  delete [] fEdgeColor;
261  delete [] fEdgeStyle;
262  delete [] fEdgeWidth;
263  }
264 }
265 
266 
267 ////////////////////////////////////////////////////////////////////////////////
268 /// Draw back surfaces of surrounding box
269 ///
270 /// \param[in] ang is the angle between X and Y axis
271 
272 
274 {
275 
276  /* Initialized data */
277  static Int_t iface1[4] = { 1,4,8,5 };
278  static Int_t iface2[4] = { 4,3,7,8 };
279  TView *view = 0;
280 
281  if (gPad) view = gPad->GetView();
282  if (!view) {
283  Error("BackBox", "no TView in current pad");
284  return;
285  }
286 
287  /* Local variables */
288  Double_t cosa, sina;
289  Int_t i;
290  Double_t r[24] /* was [3][8] */, av[24] /* was [3][8] */;
291  Int_t icodes[3];
292  Double_t tt[4];
293  Int_t ix1, ix2, iy1, iy2, iz1, iz2;
294 
295  cosa = TMath::Cos(kRad*ang);
296  sina = TMath::Sin(kRad*ang);
297  view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
298  for (i = 1; i <= 8; ++i) {
299  r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2]*cosa;
300  r[i*3 - 2] = av[i*3 - 2]*sina;
301  r[i*3 - 1] = av[i*3 - 1];
302  }
303 
304  // D R A W F O R W A R D F A C E S */
305  icodes[0] = 0;
306  icodes[1] = 0;
307  icodes[2] = 0;
308  tt[0] = r[iface1[0]*3 - 1];
309  tt[1] = r[iface1[1]*3 - 1];
310  tt[2] = r[iface1[2]*3 - 1];
311  tt[3] = r[iface1[3]*3 - 1];
312  (this->*fDrawFace)(icodes, r, 4, iface1, tt);
313  tt[0] = r[iface2[0]*3 - 1];
314  tt[1] = r[iface2[1]*3 - 1];
315  tt[2] = r[iface2[2]*3 - 1];
316  tt[3] = r[iface2[3]*3 - 1];
317  (this->*fDrawFace)(icodes, r, 4, iface2, tt);
318 }
319 
320 
321 ////////////////////////////////////////////////////////////////////////////////
322 /// Clear screen
323 
325 {
326  Int_t nw = (fNxrast*fNyrast + 29) / 30;
327  for (Int_t i = 0; i < nw; ++i) fRaster[i] = 0;
328  fIfrast = 0;
329 }
330 
331 
332 ////////////////////////////////////////////////////////////////////////////////
333 /// Set correspondance between function and color levels
334 ///
335 /// \param[in] nl number of levels
336 /// \param[in] fl function levels
337 /// \param[in] icl colors for levels
338 ///
339 /// \param[out] irep return code.(0 OK, -1 error).
340 
342 {
343  static const char *where = "ColorFunction";
344 
345  /* Local variables */
346  Int_t i;
347 
348  irep = 0;
349  if (nl == 0) {fNlevel = 0; return; }
350 
351  // C H E C K P A R A M E T E R S
352  if (nl < 0 || nl > 256) {
353  Error(where, "illegal number of levels (%d)", nl);
354  irep = -1;
355  return;
356  }
357  for (i = 1; i < nl; ++i) {
358  if (fl[i] <= fl[i - 1]) {
359  // Error(where, "function levels must be in increasing order");
360  irep = -1;
361  return;
362  }
363  }
364  for (i = 0; i < nl; ++i) {
365  if (icl[i] < 0) {
366  // Error(where, "negative color index (%d)", icl[i]);
367  irep = -1;
368  return;
369  }
370  }
371 
372  // S E T L E V E L S
373  fNlevel = nl;
374  for (i = 0; i < fNlevel; ++i) fFunLevel[i] = Hparam.factor*fl[i];
375  for (i = 0; i < fNlevel+1; ++i) fColorLevel[i] = icl[i];
376 }
377 
378 
379 ////////////////////////////////////////////////////////////////////////////////
380 /// Define the grid levels drawn in the background of surface and lego plots.
381 /// The grid levels are aligned on the Z axis' main tick marks.
382 
384 {
385  Int_t i, nbins=0;
386  Double_t binLow = 0, binHigh = 0, binWidth = 0;
387  TView *view = 0;
388 
389  if (gPad) view = gPad->GetView();
390  if (!view) {
391  Error("GridLevels", "no TView in current pad");
392  return;
393  }
394 
395  // Find the main tick marks positions.
396  Double_t *rmin = view->GetRmin();
397  Double_t *rmax = view->GetRmax();
398  if (!rmin || !rmax) return;
399  if (ndivz > 0) {
400  THLimitsFinder::Optimize(rmin[2], rmax[2], ndivz,
401  binLow, binHigh, nbins, binWidth, " ");
402  } else {
403  nbins = TMath::Abs(ndivz);
404  binLow = rmin[2];
405  binHigh = rmax[2];
406  binWidth = (binHigh-binLow)/nbins;
407  }
408 
409  // Define the grid levels
410  fNlevel = nbins+1;
411  for (i = 0; i < fNlevel; ++i) fFunLevel[i] = binLow+i*binWidth;
412 }
413 
414 
415 ////////////////////////////////////////////////////////////////////////////////
416 /// Draw face - 1st variant (2 colors: 1st for external surface, 2nd for internal)
417 ///
418 /// \param[in] icodes set of codes for the line (not used in this method)
419 /// \param[in] xyz coordinates of nodes
420 /// \param[in] np number of nodes
421 /// \param[in] iface face
422 /// \param[in] t additional function defined on this face (not used in this method)
423 
425 {
426 
427  /* Local variables */
428  Int_t i, k,ifneg,i1, i2;
429  Double_t x[13], y[13];
430  Double_t z;
431  Double_t p3[24] /* was [2][12] */;
432  TView *view = 0;
433 
434  if (gPad) view = gPad->GetView();
435  if (!view) return;
436 
437  // T R A N S F E R T O N O R M A L I S E D COORDINATES
438  /* Parameter adjustments */
439  --t;
440  --iface;
441  xyz -= 4;
442  --icodes;
443 
444  ifneg = 0;
445  for (i = 1; i <= np; ++i) {
446  k = iface[i];
447  if (k < 0) ifneg = 1;
448  if (k < 0) k = -k;
449  view->WCtoNDC(&xyz[k*3 + 1], &p3[2*i - 2]);
450  x[i - 1] = p3[2*i - 2];
451  y[i - 1] = p3[2*i - 1];
452  }
453 
454  // F I N D N O R M A L
455  z = 0;
456  for (i = 1; i <= np; ++i) {
457  i1 = i;
458  i2 = i1 + 1;
459  if (i2 > np) i2 = 1;
460  z = z + p3[2*i1 - 1]*p3[2*i2 - 2] - p3[2*i1 - 2] *
461  p3[2*i2 - 1];
462  }
463 
464  // D R A W F A C E
465  if (z > 0) SetFillColor(kF3FillColor1);
466  if (z <= 0) SetFillColor(kF3FillColor2);
467  SetFillStyle(1001);
469  gPad->PaintFillArea(np, x, y);
470 
471  // D R A W B O R D E R
472  if (ifneg == 0) {
473  SetFillStyle(0);
476  gPad->PaintFillArea(np, x, y);
477  } else {
478  x[np] = x[0];
479  y[np] = y[0];
482  for (i = 1; i <= np; ++i) {
483  if (iface[i] > 0) gPad->PaintPolyLine(2, &x[i-1], &y[i-1]);
484  }
485  }
486 }
487 
488 
489 ////////////////////////////////////////////////////////////////////////////////
490 /// Draw face - 2nd option (fill in correspondance with function levels)
491 ///
492 /// \param[in] icodes set of codes for the line (not used in this method)
493 /// \param[in] xyz coordinates of nodes
494 /// \param[in] np number of nodes
495 /// \param[in] iface face
496 /// \param[in] t additional function defined on this face
497 
499 {
500  /* Local variables */
501  Int_t i, k;
502  Double_t x[12], y[12];
503  Double_t p3[36] /* was [3][12] */;
504  TView *view = 0;
505 
506  if (gPad) view = gPad->GetView();
507  if (!view) return;
508 
509  // T R A N S F E R T O N O R M A L I S E D COORDINATES
510  /* Parameter adjustments */
511  --t;
512  --iface;
513  xyz -= 4;
514  --icodes;
515 
516  for (i = 1; i <= np; ++i) {
517  k = iface[i];
518  view->WCtoNDC(&xyz[k*3 + 1], &p3[i*3 - 3]);
519  x[i - 1] = p3[i*3 - 3];
520  y[i - 1] = p3[i*3 - 2];
521  }
522 
523  // D R A W F A C E & B O R D E R
524  FillPolygon(np, p3, &t[1]);
525  if (fMesh == 1) {
526  if (Hoption.Lego!=0 && Hoption.Surf==0) { // i.e. PaintFillArea for lego, not for surf
528  SetFillStyle(0);
530  gPad->PaintFillArea(np, x, y);
531  }
533  SetLineStyle(fEdgeStyle[fEdgeIdx]);
534  SetLineWidth(fEdgeWidth[fEdgeIdx]);
536  gPad->PaintPolyLine(np, x, y);
537  }
538 }
539 
540 
541 ////////////////////////////////////////////////////////////////////////////////
542 /// Draw face - 3rd option (draw face for stacked lego plot)
543 ///
544 /// \param[in] icodes set of codes for the line
545 /// \param[in] xyz coordinates of nodes
546 /// \param[in] np number of nodes
547 /// \param[in] iface face
548 /// \param[in] t additional function defined on this face (not used in this method)
549 
551 {
552  Int_t i, k;
553  Int_t icol = 0;
554  Double_t x[4], y[4], p3[12] /* was [3][4] */;
555  TView *view = 0;
556 
557  if (gPad) view = gPad->GetView();
558  if (!view) return;
559 
560  /* Parameter adjustments */
561  --t;
562  --iface;
563  xyz -= 4;
564  --icodes;
565 
566  if (icodes[4] == 6) icol = fColorTop;
567  if (icodes[4] == 5) icol = fColorBottom;
568  if (icodes[4] == 1) icol = fColorMain[icodes[3] - 1];
569  if (icodes[4] == 2) icol = fColorDark[icodes[3] - 1];
570  if (icodes[4] == 3) icol = fColorMain[icodes[3] - 1];
571  if (icodes[4] == 4) icol = fColorDark[icodes[3] - 1];
572 
573  for (i = 1; i <= np; ++i) {
574  k = iface[i];
575  view->WCtoNDC(&xyz[k*3 + 1], &p3[i*3 - 3]);
576  x[i - 1] = p3[i*3 - 3];
577  y[i - 1] = p3[i*3 - 2];
578  }
579 
580  SetFillStyle(1001);
581  SetFillColor(icol);
583  gPad->PaintFillArea(np, x, y);
584  if (fMesh) {
585  SetFillStyle(0);
588  gPad->PaintFillArea(np, x, y);
589  SetLineColor(fEdgeColor[fEdgeIdx]);
590  SetLineStyle(fEdgeStyle[fEdgeIdx]);
591  SetLineWidth(fEdgeWidth[fEdgeIdx]);
593  gPad->PaintPolyLine(np, x, y);
594  }
595 }
596 
597 
598 ////////////////////////////////////////////////////////////////////////////////
599 /// Draw face - 1st variant for "MOVING SCREEN" algorithm (draw face with level lines)
600 ///
601 /// \param[in] icodes set of codes for the line (not used in this method)
602 /// \param[in] xyz coordinates of nodes
603 /// \param[in] np number of nodes
604 /// \param[in] iface face
605 /// \param[in] t additional function defined on this face (not used in this method)
606 
608  Int_t *iface, Double_t *tt)
609 {
610  Double_t xdel, ydel;
611  Int_t i, k, i1, i2, il, it;
612  Double_t x[2], y[2];
613  Double_t p1[3], p2[3], p3[36] /* was [3][12] */;
614  TView *view = 0;
615 
616  if (gPad) view = gPad->GetView();
617  if (!view) return;
618 
619  // C O P Y P O I N T S T O A R R A Y
620  /* Parameter adjustments */
621  --tt;
622  --iface;
623  xyz -= 4;
624  --icodes;
625 
626  for (i = 1; i <= np; ++i) {
627  k = iface[i];
628  p3[i*3 - 3] = xyz[k*3 + 1];
629  p3[i*3 - 2] = xyz[k*3 + 2];
630  p3[i*3 - 1] = xyz[k*3 + 3];
631  }
632 
633  // F I N D L E V E L L I N E S
634  FindLevelLines(np, p3, &tt[1]);
635 
636  // D R A W L E V E L L I N E S
637  SetLineStyle(3);
638  if (icodes[3]==0) { // front & back boxes
639  SetLineColor(1);
640  SetLineWidth(1);
641  } else {
643  SetLineWidth(fEdgeWidth[fEdgeIdx]);
644  }
646  for (il = 1; il <= fNlines; ++il) {
647  FindVisibleDraw(&fPlines[(2*il + 1)*3 - 9], &fPlines[(2*il + 2)*3 - 9]);
648  view->WCtoNDC(&fPlines[(2*il + 1)*3 - 9], p1);
649  view->WCtoNDC(&fPlines[(2*il + 2)*3 - 9], p2);
650  xdel = p2[0] - p1[0];
651  ydel = p2[1] - p1[1];
652  for (it = 1; it <= fNT; ++it) {
653  x[0] = p1[0] + xdel*fT[2*it - 2];
654  y[0] = p1[1] + ydel*fT[2*it - 2];
655  x[1] = p1[0] + xdel*fT[2*it - 1];
656  y[1] = p1[1] + ydel*fT[2*it - 1];
657  gPad->PaintPolyLine(2, x, y);
658  }
659  }
660 
661  // D R A W F A C E
662  if (icodes[3]==0) { // front & back boxes
663  SetLineColor(1);
664  SetLineStyle(1);
665  SetLineWidth(1);
666  } else {
668  SetLineStyle(fEdgeStyle[fEdgeIdx]);
669  SetLineWidth(fEdgeWidth[fEdgeIdx]);
670  }
672  for (i = 1; i <= np; ++i) {
673  i1 = i;
674  i2 = i + 1;
675  if (i == np) i2 = 1;
676  FindVisibleDraw(&p3[i1*3 - 3], &p3[i2*3 - 3]);
677  view->WCtoNDC(&p3[i1*3 - 3], p1);
678  view->WCtoNDC(&p3[i2*3 - 3], p2);
679  xdel = p2[0] - p1[0];
680  ydel = p2[1] - p1[1];
681  for (it = 1; it <= fNT; ++it) {
682  x[0] = p1[0] + xdel*fT[2*it - 2];
683  y[0] = p1[1] + ydel*fT[2*it - 2];
684  x[1] = p1[0] + xdel*fT[2*it - 1];
685  y[1] = p1[1] + ydel*fT[2*it - 1];
686  gPad->PaintPolyLine(2, x, y);
687  }
688  }
689 
690  // M O D I F Y S C R E E N
691  for (i = 1; i <= np; ++i) {
692  i1 = i;
693  i2 = i + 1;
694  if (i == np) i2 = 1;
695  ModifyScreen(&p3[i1*3 - 3], &p3[i2*3 - 3]);
696  }
697 }
698 
699 
700 ////////////////////////////////////////////////////////////////////////////////
701 /// Draw face - 3rd variant for "MOVING SCREEN" algorithm (draw level lines only)
702 ///
703 /// \param[in] icodes set of codes for the line (not used in this method)
704 /// \param[in] xyz coordinates of nodes
705 /// \param[in] np number of nodes
706 /// \param[in] iface face
707 /// \param[in] tt additional function defined on this face (not used in this method)
708 
710  Int_t *iface, Double_t *tt)
711 {
712  Double_t xdel, ydel;
713  Int_t i, k, i1, i2, il, it;
714  Double_t x[2], y[2];
715  Double_t p1[3], p2[3], p3[36] /* was [3][12] */;
716  TView *view = 0;
717 
718  if (gPad) view = gPad->GetView();
719  if (!view) return;
720 
721  // Parameter adjustments (ftoc)
722  --tt;
723  --iface;
724  xyz -= 4;
725  --icodes;
726 
727  // Copy points to array
728  for (i = 1; i <= np; ++i) {
729  k = iface[i];
730  p3[i*3 - 3] = xyz[k*3 + 1];
731  p3[i*3 - 2] = xyz[k*3 + 2];
732  p3[i*3 - 1] = xyz[k*3 + 3];
733  }
734 
735  // Find level lines
736  FindLevelLines(np, p3, &tt[1]);
737 
738  // Draw level lines
739  if (icodes[3]==0) { // front and back boxes
740  SetLineColor(1);
741  SetLineStyle(1);
742  SetLineWidth(1);
743  } else {
745  SetLineStyle(fEdgeStyle[fEdgeIdx]);
746  SetLineWidth(fEdgeWidth[fEdgeIdx]);
747  }
749  for (il = 1; il <= fNlines; ++il) {
750  FindVisibleDraw(&fPlines[(2*il + 1)*3 - 9], &fPlines[(2*il + 2)*3 - 9]);
751  view->WCtoNDC(&fPlines[(2*il + 1)*3 - 9], p1);
752  view->WCtoNDC(&fPlines[(2*il + 2)*3 - 9], p2);
753  xdel = p2[0] - p1[0];
754  ydel = p2[1] - p1[1];
755  for (it = 1; it <= fNT; ++it) {
756  x[0] = p1[0] + xdel*fT[2*it - 2];
757  y[0] = p1[1] + ydel*fT[2*it - 2];
758  x[1] = p1[0] + xdel*fT[2*it - 1];
759  y[1] = p1[1] + ydel*fT[2*it - 1];
760  gPad->PaintPolyLine(2, x, y);
761  }
762  }
763 
764  // Modify screen
765  for (i = 1; i <= np; ++i) {
766  i1 = i;
767  i2 = i + 1;
768  if (i == np) i2 = 1;
769  ModifyScreen(&p3[i1*3 - 3], &p3[i2*3 - 3]);
770  }
771 }
772 
773 
774 ////////////////////////////////////////////////////////////////////////////////
775 /// Draw face - 2nd variant for "MOVING SCREEN" algorithm (draw face for stacked lego plot)
776 ///
777 /// \param[in] icodes set of codes for the line (not used in this method)
778 /// \param[in] xyz coordinates of nodes
779 /// \param[in] np number of nodes
780 /// \param[in] iface face
781 /// \param[in] tt additional function defined on this face (not used in this method)
782 
784 {
785  Double_t xdel, ydel;
786  Int_t i, k, i1, i2, it;
787  Double_t x[2], y[2];
788  Double_t p1[3], p2[3], p3[36] /* was [3][12] */;
789  TView *view = 0;
790 
791  if (gPad) view = gPad->GetView();
792  if (!view) return;
793 
794  // C O P Y P O I N T S T O A R R A Y
795  /* Parameter adjustments */
796  --tt;
797  --iface;
798  xyz -= 4;
799  --icodes;
800 
801  for (i = 1; i <= np; ++i) {
802  k = iface[i];
803  p3[i*3 - 3] = xyz[k*3 + 1];
804  p3[i*3 - 2] = xyz[k*3 + 2];
805  p3[i*3 - 1] = xyz[k*3 + 3];
806  }
807 
808  // D R A W F A C E
809  if (icodes[3]==0) { // front & back boxes
810  SetLineColor(1);
811  SetLineStyle(1);
812  SetLineWidth(1);
813  } else {
815  SetLineStyle(fEdgeStyle[fEdgeIdx]);
816  SetLineWidth(fEdgeWidth[fEdgeIdx]);
817  }
819  for (i = 1; i <= np; ++i) {
820  i1 = i;
821  i2 = i + 1;
822  if (i == np) i2 = 1;
823  FindVisibleDraw(&p3[i1*3 - 3], &p3[i2*3 - 3]);
824  view->WCtoNDC(&p3[i1*3 - 3], p1);
825  view->WCtoNDC(&p3[i2*3 - 3], p2);
826  xdel = p2[0] - p1[0];
827  ydel = p2[1] - p1[1];
828  for (it = 1; it <= fNT; ++it) {
829  x[0] = p1[0] + xdel*fT[2*it - 2];
830  y[0] = p1[1] + ydel*fT[2*it - 2];
831  x[1] = p1[0] + xdel*fT[2*it - 1];
832  y[1] = p1[1] + ydel*fT[2*it - 1];
833  gPad->PaintPolyLine(2, x, y);
834  }
835  }
836 
837  // M O D I F Y S C R E E N
838  for (i = 1; i <= np; ++i) {
839  i1 = i;
840  i2 = i + 1;
841  if (i == np) i2 = 1;
842  ModifyScreen(&p3[i1*3 - 3], &p3[i2*3 - 3]);
843  }
844 }
845 
846 
847 ////////////////////////////////////////////////////////////////////////////////
848 /// Draw face - 1st variant for "RASTER SCREEN" algorithm (draw face with level lines)
849 ///
850 /// \param[in] icodes set of codes for the line (not used in this method)
851 /// \param[in] xyz coordinates of nodes
852 /// \param[in] np number of nodes
853 /// \param[in] iface face
854 /// \param[in] t additional function defined on this face (not used in this method)
855 
857 {
858  Double_t xdel, ydel;
859  Int_t i, k, i1, i2, il, it;
860  Double_t x[2], y[2];
861  Double_t p1[3], p2[3], p3[36] /* was [3][12] */;
862  Double_t pp[24] /* was [2][12] */;
863  TView *view = 0;
864 
865  if (gPad) view = gPad->GetView();
866  if (!view) return;
867 
868  // C O P Y P O I N T S T O A R R A Y
869  /* Parameter adjustments */
870  --tt;
871  --iface;
872  xyz -= 4;
873  --icodes;
874 
875  for (i = 1; i <= np; ++i) {
876  k = iface[i];
877  if (k < 0) k = -k;
878  p3[i*3 - 3] = xyz[k*3 + 1];
879  p3[i*3 - 2] = xyz[k*3 + 2];
880  p3[i*3 - 1] = xyz[k*3 + 3];
881  view->WCtoNDC(&p3[i*3 - 3], &pp[2*i - 2]);
882  }
883 
884  // F I N D L E V E L L I N E S
885  FindLevelLines(np, p3, &tt[1]);
886 
887  // D R A W L E V E L L I N E S
888  SetLineStyle(3);
889  if (icodes[3]==0) { // front & back boxes
890  SetLineColor(1);
891  SetLineWidth(1);
892  } else {
894  SetLineWidth(fEdgeWidth[fEdgeIdx]);
895  }
897  for (il = 1; il <= fNlines; ++il) {
898  view->WCtoNDC(&fPlines[(2*il + 1)*3 - 9], p1);
899  view->WCtoNDC(&fPlines[(2*il + 2)*3 - 9], p2);
900  FindVisibleLine(p1, p2, 100, fNT, fT);
901  xdel = p2[0] - p1[0];
902  ydel = p2[1] - p1[1];
903  for (it = 1; it <= fNT; ++it) {
904  x[0] = p1[0] + xdel*fT[2*it - 2];
905  y[0] = p1[1] + ydel*fT[2*it - 2];
906  x[1] = p1[0] + xdel*fT[2*it - 1];
907  y[1] = p1[1] + ydel*fT[2*it - 1];
908  gPad->PaintPolyLine(2, x, y);
909  }
910  }
911 
912  // D R A W F A C E
913  if (icodes[3]==0) { // front & back boxes
914  SetLineColor(1);
915  SetLineStyle(1);
916  SetLineWidth(1);
917  } else {
919  SetLineStyle(fEdgeStyle[fEdgeIdx]);
920  SetLineWidth(fEdgeWidth[fEdgeIdx]);
921  }
923  for (i = 1; i <= np; ++i) {
924  if (iface[i] < 0) continue;
925  i1 = i;
926  i2 = i + 1;
927  if (i == np) i2 = 1;
928  FindVisibleLine(&pp[2*i1 - 2], &pp[2*i2 - 2], 100, fNT, fT);
929  xdel = pp[2*i2 - 2] - pp[2*i1 - 2];
930  ydel = pp[2*i2 - 1] - pp[2*i1 - 1];
931  for (it = 1; it <= fNT; ++it) {
932  x[0] = pp[2*i1 - 2] + xdel*fT[2*it - 2];
933  y[0] = pp[2*i1 - 1] + ydel*fT[2*it - 2];
934  x[1] = pp[2*i1 - 2] + xdel*fT[2*it - 1];
935  y[1] = pp[2*i1 - 1] + ydel*fT[2*it - 1];
936  gPad->PaintPolyLine(2, x, y);
937  }
938  }
939 
940  // M O D I F Y S C R E E N
941  FillPolygonBorder(np, pp);
942 }
943 
944 
945 ////////////////////////////////////////////////////////////////////////////////
946 /// Draw face - 2nd variant for "RASTER SCREEN" algorithm (draw face for stacked lego plot)
947 ///
948 /// \param[in] icodes set of codes for the line (not used in this method)
949 /// \param[in] xyz coordinates of nodes
950 /// \param[in] np number of nodes
951 /// \param[in] iface face
952 /// \param[in] tt additional function defined on this face (not used in this method)
953 
955 {
956  Double_t xdel, ydel;
957  Int_t i, k, i1, i2, it;
958  Double_t p[3], x[2], y[2];
959  Double_t pp[24] /* was [2][12] */;
960  TView *view = 0;
961 
962  if (gPad) view = gPad->GetView();
963  if (!view) return;
964 
965  // C O P Y P O I N T S T O A R R A Y
966  /* Parameter adjustments */
967  --tt;
968  --iface;
969  xyz -= 4;
970  --icodes;
971 
972  for (i = 1; i <= np; ++i) {
973  k = iface[i];
974  if (k < 0) k = -k;
975  view->WCtoNDC(&xyz[k*3 + 1], p);
976  pp[2*i - 2] = p[0];
977  pp[2*i - 1] = p[1];
978  }
979 
980  // D R A W F A C E
982  SetLineStyle(fEdgeStyle[fEdgeIdx]);
983  SetLineWidth(fEdgeWidth[fEdgeIdx]);
985  for (i = 1; i <= np; ++i) {
986  if (iface[i] < 0) continue;
987  i1 = i;
988  i2 = i + 1;
989  if (i == np) i2 = 1;
990  FindVisibleLine(&pp[2*i1 - 2], &pp[2*i2 - 2], 100, fNT, fT);
991  xdel = pp[2*i2 - 2] - pp[2*i1 - 2];
992  ydel = pp[2*i2 - 1] - pp[2*i1 - 1];
993  for (it = 1; it <= fNT; ++it) {
994  x[0] = pp[2*i1 - 2] + xdel*fT[2*it - 2];
995  y[0] = pp[2*i1 - 1] + ydel*fT[2*it - 2];
996  x[1] = pp[2*i1 - 2] + xdel*fT[2*it - 1];
997  y[1] = pp[2*i1 - 1] + ydel*fT[2*it - 1];
998  gPad->PaintPolyLine(2, x, y);
999  }
1000  }
1001 
1002  // M O D I F Y R A S T E R S C R E E N
1003  FillPolygonBorder(np, pp);
1004 }
1005 
1006 
1007 ////////////////////////////////////////////////////////////////////////////////
1008 /// Fill polygon with function values at vertexes
1009 ///
1010 /// \param[in] n number of vertexes
1011 /// \param[in] p polygon
1012 /// \param[in] f function values at nodes
1013 ///
1014 /// Errors:
1015 /// - illegal number of vertexes in polygon
1016 /// - illegal call of FillPolygon: no levels
1017 
1019 {
1020  Int_t ilev, i, k, icol, i1, i2, nl, np;
1021  Double_t fmin, fmax;
1022  Double_t x[12], y[12], f1, f2;
1023  Double_t p3[36] /* was [3][12] */;
1024  Double_t funmin, funmax;
1025 
1026  /* Parameter adjustments */
1027  --f;
1028  p -= 4;
1029 
1030  if (n < 3) {
1031  Error("FillPolygon", "illegal number of vertices in polygon (%d)", n);
1032  return;
1033  }
1034 
1035  if (fNlevel == 0) {
1036  // Illegal call of FillPolygon: no levels
1037  return;
1038  }
1039  np = n;
1040  nl = fNlevel;
1041  if (nl < 0) nl = -nl;
1042  fmin = f[1];
1043  fmax = f[1];
1044  for (i = 2; i <= np; ++i) {
1045  if (fmin > f[i]) fmin = f[i];
1046  if (fmax < f[i]) fmax = f[i];
1047  }
1048  funmin = fFunLevel[0] - 1;
1049  if (fmin < funmin) funmin = fmin - 1;
1050  funmax = fFunLevel[nl - 1] + 1;
1051  if (fmax > funmax) funmax = fmax + 1;
1052 
1053  // F I N D A N D D R A W S U B P O L Y G O N S
1054  f2 = funmin;
1055  for (ilev = 1; ilev <= nl+1; ++ilev) {
1056  // S E T L E V E L L I M I T S
1057  f1 = f2;
1058  if (ilev == nl + 1) f2 = funmax;
1059  else f2 = fFunLevel[ilev - 1];
1060  if (fmax < f1) return;
1061  if (fmin > f2) continue;
1062  // F I N D S U B P O L Y G O N
1063  k = 0;
1064  for (i = 1; i <= np; ++i) {
1065  i1 = i;
1066  i2 = i + 1;
1067  if (i == np) i2 = 1;
1068  FindPartEdge(&p[i1*3 + 1], &p[i2*3 + 1], f[i1], f[i2], f1, f2, k, p3);
1069  }
1070  // D R A W S U B P O L Y G O N
1071  if (k < 3) continue;
1072  for (i = 1; i <= k; ++i) {
1073  x[i-1] = p3[i*3-3];
1074  y[i-1] = p3[i*3-2];
1075  if (TMath::IsNaN(x[i-1]) || TMath::IsNaN(y[i-1])) return;
1076  }
1077  if (ilev==1) {
1078  icol=gPad->GetFillColor();
1079  } else {
1080  icol = fColorLevel[ilev - 2];
1081  }
1082  SetFillColor(icol);
1083  SetFillStyle(1001);
1084  TAttFill::Modify();
1085  gPad->PaintFillArea(k, x, y);
1086  }
1087 }
1088 
1089 
1090 ////////////////////////////////////////////////////////////////////////////////
1091 /// Fill a polygon including border ("RASTER SCREEN")
1092 ///
1093 /// \param[in] nn number of polygon nodes
1094 /// \param[in] xy polygon nodes
1095 
1097 {
1098  Int_t kbit, nbit, step, ymin, ymax, test[kLmax], xcur[kLmax], xnex[kLmax],
1099  i, j, k, n, ibase, t, x, y, xscan[24] /* was [2][kLmax] */,
1100  yscan, x1[kLmax+2], y1[kLmax+2], x2[kLmax+2], y2[kLmax+2],
1101  ib, nb, dx, dy, iw, nx, xx, yy, signdx, nstart, xx1, xx2, nxa, nxb;
1102 
1103  // 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
1104  /* Parameter adjustments */
1105  xy -= 3;
1106 
1107  if (fIfrast) return;
1108 
1109  n = nn;
1110  x1[0] = 0;
1111  y1[0] = 0;
1112  for (i = 1; i <= n; ++i) {
1113  x1[i - 1] = Int_t(fNxrast*((xy[2*i + 1] - fXrast) /fDXrast) - 0.01);
1114  y1[i - 1] = Int_t(fNyrast*((xy[2*i + 2] - fYrast) /fDYrast) - 0.01);
1115  }
1116  x1[n] = x1[0];
1117  y1[n] = y1[0];
1118 
1119  // F I N D Y - M I N A N D Y - M A X
1120  // S E T R I G H T E D G E O R I E N T A T I O N
1121  ymin = y1[0];
1122  ymax = y1[0];
1123  for (i = 1; i <= n; ++i) {
1124  if (ymin > y1[i - 1]) ymin = y1[i - 1];
1125  if (ymax < y1[i - 1]) ymax = y1[i - 1];
1126  if (y1[i - 1] <= y1[i]) {x2[i - 1] = x1[i]; y2[i - 1] = y1[i];}
1127  else {
1128  x2[i - 1] = x1[i - 1];
1129  y2[i - 1] = y1[i - 1];
1130  x1[i - 1] = x1[i];
1131  y1[i - 1] = y1[i];
1132  }
1133  }
1134  if (ymin >= fNyrast) return;
1135  if (ymax < 0) return;
1136  if (ymax >= fNyrast) ymax = fNyrast - 1;
1137 
1138  // S O R T L I N E S
1139  for (i = 1; i < n; ++i) {
1140  if (y1[i] >= y1[i - 1]) continue;
1141  y = y1[i];
1142  k = 1;
1143  for (j = i - 1; j >= 1; --j) {
1144  if (y < y1[j - 1]) continue;
1145  k = j + 1;
1146  break;
1147  }
1148  x = x1[i];
1149  xx = x2[i];
1150  yy = y2[i];
1151  for (j = i; j >= k; --j) {
1152  x1[j] = x1[j - 1];
1153  y1[j] = y1[j - 1];
1154  x2[j] = x2[j - 1];
1155  y2[j] = y2[j - 1];
1156  }
1157  x1[k - 1] = x;
1158  y1[k - 1] = y;
1159  x2[k - 1] = xx;
1160  y2[k - 1] = yy;
1161  }
1162 
1163  // S E T I N I T I A L V A L U E S
1164  for (i = 1; i <= n; ++i) {
1165  xcur[i - 1] = x1[i - 1];
1166  dy = y2[i - 1] - y1[i - 1];
1167  dx = x2[i - 1] - x1[i - 1];
1168  signdx = 1;
1169  if (dx < 0) signdx = -1;
1170  if (dx < 0) dx = -dx;
1171  if (dx <= dy) {
1172  t = -(dy + 1) / 2 + dx;
1173  if (t < 0) {
1174  test[i - 1] = t;
1175  xnex[i - 1] = xcur[i - 1];
1176  } else {
1177  test[i - 1] = t - dy;
1178  xnex[i - 1] = xcur[i - 1] + signdx;
1179  }
1180  } else if (dy != 0) {
1181  step = (dx - 1) / (dy + dy) + 1;
1182  test[i - 1] = step*dy - (dx + 1) / 2 - dx;
1183  xnex[i - 1] = xcur[i - 1] + signdx*step;
1184  }
1185  }
1186 
1187  // L O O P O N S C A N L I N E S
1188  nstart = 1;
1189  for (yscan = ymin; yscan <= ymax; ++yscan) {
1190  nx = 0;
1191  nxa = 0;
1192  nxb = kLmax + 1;
1193  for (i = nstart; i <= n; ++i) {
1194  if (y1[i - 1] > yscan) goto L500;
1195  if (y2[i - 1] <= yscan) {
1196  if (i == nstart) ++nstart;
1197  if (y2[i - 1] != yscan)continue;
1198  --nxb;
1199  if (x2[i - 1] >= xcur[i - 1]) {
1200  xscan[2*nxb - 2] = xcur[i - 1];
1201  xscan[2*nxb - 1] = x2[i - 1];
1202  } else {
1203  xscan[2*nxb - 2] = x2[i - 1];
1204  xscan[2*nxb - 1] = xcur[i - 1];
1205  }
1206  continue;
1207  }
1208 
1209  // S T O R E C U R R E N T X
1210  // P R E P A R E X F O R N E X T S C A N - L I N E
1211  ++nxa;
1212  dy = y2[i - 1] - y1[i - 1];
1213  dx = x2[i - 1] - x1[i - 1];
1214  if (dx >= 0) {
1215  signdx = 1;
1216  xscan[2*nxa - 2] = xcur[i - 1];
1217  xscan[2*nxa - 1] = xnex[i - 1];
1218  if (xscan[2*nxa - 2] != xscan[2*nxa - 1]) {
1219  --xscan[2*nxa - 1];
1220  }
1221  } else {
1222  dx = -dx;
1223  signdx = -1;
1224  xscan[2*nxa - 2] = xnex[i - 1];
1225  xscan[2*nxa - 1] = xcur[i - 1];
1226  if (xscan[2*nxa - 2] != xscan[2*nxa - 1]) {
1227  ++xscan[2*nxa - 2];
1228  }
1229  }
1230  xcur[i - 1] = xnex[i - 1];
1231  if (dx <= dy) {
1232  test[i - 1] += dx;
1233  if (test[i - 1] < 0) continue;
1234  test[i - 1] -= dy;
1235  xnex[i - 1] += signdx;
1236  continue;
1237  }
1238  step = dx / dy;
1239  t = test[i - 1] + step*dy;
1240  if (t >= 0) {
1241  test[i - 1] = t - dx;
1242  xnex[i - 1] += signdx*step;
1243  } else {
1244  test[i - 1] = t + dy - dx;
1245  xnex[i - 1] += signdx*(step + 1);
1246  }
1247  }
1248 
1249  // S O R T P O I N T S A L O N G X
1250 L500:
1251  if (yscan < 0) continue;
1252  ibase = yscan*fNxrast;
1253  if (nxa >= 2) {
1254  for (i = 1; i < nxa; ++i) {
1255  for (j = i; j >= 1; --j) {
1256  if (xscan[2*j] >= xscan[2*j - 2]) continue;
1257  x = xscan[2*j];
1258  xscan[2*j] = xscan[2*j - 2];
1259  xscan[2*j - 2] = x;
1260  x = xscan[2*j - 1];
1261  xscan[2*j + 1] = xscan[2*j - 1];
1262  xscan[2*j - 1] = x;
1263  }
1264  }
1265  for (i = 1; i <= nxa; i += 2) {
1266  ++nx;
1267  xscan[2*nx - 2] = xscan[2*i - 2];
1268  x = xscan[2*i + 1];
1269  if (xscan[2*i - 1] > x) x = xscan[2*i - 1];
1270  xscan[2*nx - 1] = x;
1271  }
1272  }
1273  if (nxb <= kLmax) {
1274  for (i = nxb; i <= kLmax; ++i) {
1275  ++nx;
1276  xscan[2*nx - 2] = xscan[2*i - 2];
1277  xscan[2*nx - 1] = xscan[2*i - 1];
1278  }
1279  }
1280  // C O N C A T E N A T E A N D F I L L
1281  while (nx) {
1282  xx1 = xscan[2*nx - 2];
1283  xx2 = xscan[2*nx - 1];
1284  --nx;
1285  k = 1;
1286  while (k <= nx) {
1287  if ((xscan[2*k - 2] <= xx2 + 1) && (xscan[2*k - 1] >= xx1 - 1)) {
1288  if (xscan[2*k - 2] < xx1) xx1 = xscan[2*k - 2];
1289  if (xscan[2*k - 1] > xx2) xx2 = xscan[2*k - 1];
1290  xscan[2*k - 2] = xscan[2*nx - 2];
1291  xscan[2*k - 1] = xscan[2*nx - 1];
1292  --nx;
1293  } else ++k;
1294  }
1295  if (xx1 < 0) xx1 = 0;
1296  if (xx2 >= fNxrast) xx2 = fNxrast - 1;
1297  nbit = xx2 - xx1 + 1;
1298  kbit = ibase + xx1;
1299  iw = kbit / 30;
1300  ib = kbit - iw*30 + 1;
1301  iw = iw + 1;
1302  nb = 30 - ib + 1;
1303  if (nb > nbit) nb = nbit;
1304  fRaster[iw - 1] = fRaster[iw - 1] | fMask[fJmask[nb - 1] + ib - 1];
1305  nbit -= nb;
1306  if (nbit) {
1307  while(nbit > 30) {
1308  fRaster[iw] = fMask[464];
1309  ++iw;
1310  nbit += -30;
1311  }
1312  fRaster[iw] = fRaster[iw] | fMask[fJmask[nbit - 1]];
1313  ++iw;
1314  }
1315  }
1316  }
1317 }
1318 
1319 
1320 ////////////////////////////////////////////////////////////////////////////////
1321 /// Find level lines for face
1322 ///
1323 /// \param[in] np number of nodes
1324 /// \param[in] f face
1325 /// \param[in] t additional function
1326 ///
1327 /// Error: number of points for line not equal 2
1328 
1330 {
1331  Int_t i, k, i1, i2, il, nl;
1332  Double_t tmin, tmax, d1, d2;
1333 
1334  /* Parameter adjustments */
1335  --t;
1336  f -= 4;
1337 
1338  /* Function Body */
1339  fNlines = 0;
1340  if (fNlevel == 0) return;
1341  nl = fNlevel;
1342  if (nl < 0) nl = -nl;
1343 
1344  // F I N D Tmin A N D Tmax
1345  tmin = t[1];
1346  tmax = t[1];
1347  for (i = 2; i <= np; ++i) {
1348  if (t[i] < tmin) tmin = t[i];
1349  if (t[i] > tmax) tmax = t[i];
1350  }
1351  if (tmin >= fFunLevel[nl - 1]) return;
1352  if (tmax <= fFunLevel[0]) return;
1353 
1354  // F I N D L E V E L S L I N E S
1355  for (il = 1; il <= nl; ++il) {
1356  if (tmin >= fFunLevel[il - 1]) continue;
1357  if (tmax <= fFunLevel[il - 1]) return;
1358  if (fNlines >= 200) return;
1359  ++fNlines;
1360  fLevelLine[fNlines - 1] = il;
1361  k = 0;
1362  for (i = 1; i <= np; ++i) {
1363  i1 = i;
1364  i2 = i + 1;
1365  if (i == np) i2 = 1;
1366  d1 = t[i1] - fFunLevel[il - 1];
1367  d2 = t[i2] - fFunLevel[il - 1];
1368  if (d1) {
1369  if (d1*d2 < 0) goto L320;
1370  continue;
1371  }
1372  ++k;
1373  fPlines[(k + 2*fNlines)*3 - 9] = f[i1*3 + 1];
1374  fPlines[(k + 2*fNlines)*3 - 8] = f[i1*3 + 2];
1375  fPlines[(k + 2*fNlines)*3 - 7] = f[i1*3 + 3];
1376  if (k == 1) continue;
1377  goto L340;
1378 L320:
1379  ++k;
1380  d1 /= t[i2] - t[i1];
1381  d2 /= t[i2] - t[i1];
1382  fPlines[(k + 2*fNlines)*3 - 9] = d2*f[i1*3 + 1] - d1*f[i2*3 + 1];
1383  fPlines[(k + 2*fNlines)*3 - 8] = d2*f[i1*3 + 2] - d1*f[i2*3 + 2];
1384  fPlines[(k + 2*fNlines)*3 - 7] = d2*f[i1*3 + 3] - d1*f[i2*3 + 3];
1385  if (k != 1) goto L340;
1386  }
1387  if (k != 2) {
1388  Error("FindLevelLines", "number of points for line not equal 2");
1389  --fNlines;
1390  }
1391 L340:
1392  if (il < 0) return;
1393  }
1394 }
1395 
1396 
1397 ////////////////////////////////////////////////////////////////////////////////
1398 /// Find part of edge where function defined on this edge has value from
1399 /// `fmin` to `fmax`
1400 ///
1401 /// \param[in] p1 1st point
1402 /// \param[in] p2 2nd point
1403 /// \param[in] f1 function value at 1st point
1404 /// \param[in] f2 function value at 2nd point
1405 /// \param[in] fmin min value of layer
1406 /// \param[in] fmax max value of layer
1407 ///
1408 /// \param[out] kpp current number of point
1409 /// \param[out] pp coordinates of new face
1410 
1412  Double_t f2, Double_t fmin,
1413  Double_t fmax, Int_t &kpp, Double_t *pp)
1414 {
1415  Double_t d1, d2;
1416  Int_t k1, k2, kk;
1417 
1418  /* Parameter adjustments */
1419  pp -= 4;
1420  --p2;
1421  --p1;
1422 
1423  k1 = 0;
1424  if (f1 < fmin) k1 = -2;
1425  if (f1 == fmin) k1 = -1;
1426  if (f1 == fmax) k1 = 1;
1427  if (f1 > fmax) k1 = 2;
1428  k2 = 0;
1429  if (f2 < fmin) k2 = -2;
1430  if (f2 == fmin) k2 = -1;
1431  if (f2 == fmax) k2 = 1;
1432  if (f2 > fmax) k2 = 2;
1433  kk = (k1 + 2)*5 + (k2 + 2) + 1;
1434 
1435  // K2: -2 -1 0 +1 +2
1436  // K1: -2 -1 0 +1 +2
1437  switch ((int)kk) {
1438  case 1: return;
1439  case 2: return;
1440  case 3: goto L200;
1441  case 4: goto L200;
1442  case 5: goto L600;
1443  case 6: goto L100;
1444  case 7: goto L100;
1445  case 8: goto L100;
1446  case 9: goto L100;
1447  case 10: goto L500;
1448  case 11: goto L400;
1449  case 12: goto L100;
1450  case 13: goto L100;
1451  case 14: goto L100;
1452  case 15: goto L500;
1453  case 16: goto L400;
1454  case 17: goto L100;
1455  case 18: goto L100;
1456  case 19: goto L100;
1457  case 20: goto L100;
1458  case 21: goto L700;
1459  case 22: goto L300;
1460  case 23: goto L300;
1461  case 24: return;
1462  case 25: return;
1463  }
1464 
1465  // 1 - S T P O I N T
1466 L100:
1467  ++kpp;
1468  pp[kpp*3 + 1] = p1[1];
1469  pp[kpp*3 + 2] = p1[2];
1470  pp[kpp*3 + 3] = p1[3];
1471  return;
1472 
1473  // I N T E R S E C T I O N W I T H Fmin
1474 L200:
1475  ++kpp;
1476  d1 = (fmin - f1) / (f1 - f2);
1477  d2 = (fmin - f2) / (f1 - f2);
1478  pp[kpp*3 + 1] = d2*p1[1] - d1*p2[1];
1479  pp[kpp*3 + 2] = d2*p1[2] - d1*p2[2];
1480  pp[kpp*3 + 3] = d2*p1[3] - d1*p2[3];
1481  return;
1482 
1483  // I N T E R S E C T I O N W I T H Fmax
1484 L300:
1485  ++kpp;
1486  d1 = (fmax - f1) / (f1 - f2);
1487  d2 = (fmax - f2) / (f1 - f2);
1488  pp[kpp*3 + 1] = d2*p1[1] - d1*p2[1];
1489  pp[kpp*3 + 2] = d2*p1[2] - d1*p2[2];
1490  pp[kpp*3 + 3] = d2*p1[3] - d1*p2[3];
1491  return;
1492 
1493  // 1 - S T P O I N T, I N T E R S E C T I O N WITH Fmin
1494 L400:
1495  ++kpp;
1496  pp[kpp*3 + 1] = p1[1];
1497  pp[kpp*3 + 2] = p1[2];
1498  pp[kpp*3 + 3] = p1[3];
1499  ++kpp;
1500  d1 = (fmin - f1) / (f1 - f2);
1501  d2 = (fmin - f2) / (f1 - f2);
1502  pp[kpp*3 + 1] = d2*p1[1] - d1*p2[1];
1503  pp[kpp*3 + 2] = d2*p1[2] - d1*p2[2];
1504  pp[kpp*3 + 3] = d2*p1[3] - d1*p2[3];
1505  return;
1506 
1507  // 1 - S T P O I N T, I N T E R S E C T I O N WITH Fmax
1508 L500:
1509  ++kpp;
1510  pp[kpp*3 + 1] = p1[1];
1511  pp[kpp*3 + 2] = p1[2];
1512  pp[kpp*3 + 3] = p1[3];
1513  ++kpp;
1514  d1 = (fmax - f1) / (f1 - f2);
1515  d2 = (fmax - f2) / (f1 - f2);
1516  pp[kpp*3 + 1] = d2*p1[1] - d1*p2[1];
1517  pp[kpp*3 + 2] = d2*p1[2] - d1*p2[2];
1518  pp[kpp*3 + 3] = d2*p1[3] - d1*p2[3];
1519  return;
1520 
1521  // I N T E R S E C T I O N W I T H Fmin, Fmax
1522 L600:
1523  ++kpp;
1524  d1 = (fmin - f1) / (f1 - f2);
1525  d2 = (fmin - f2) / (f1 - f2);
1526  pp[kpp*3 + 1] = d2*p1[1] - d1*p2[1];
1527  pp[kpp*3 + 2] = d2*p1[2] - d1*p2[2];
1528  pp[kpp*3 + 3] = d2*p1[3] - d1*p2[3];
1529  ++kpp;
1530  d1 = (fmax - f1) / (f1 - f2);
1531  d2 = (fmax - f2) / (f1 - f2);
1532  pp[kpp*3 + 1] = d2*p1[1] - d1*p2[1];
1533  pp[kpp*3 + 2] = d2*p1[2] - d1*p2[2];
1534  pp[kpp*3 + 3] = d2*p1[3] - d1*p2[3];
1535  return;
1536 
1537  // I N T E R S E C T I O N W I T H Fmax, Fmin
1538 L700:
1539  ++kpp;
1540  d1 = (fmax - f1) / (f1 - f2);
1541  d2 = (fmax - f2) / (f1 - f2);
1542  pp[kpp*3 + 1] = d2*p1[1] - d1*p2[1];
1543  pp[kpp*3 + 2] = d2*p1[2] - d1*p2[2];
1544  pp[kpp*3 + 3] = d2*p1[3] - d1*p2[3];
1545  ++kpp;
1546  d1 = (fmin - f1) / (f1 - f2);
1547  d2 = (fmin - f2) / (f1 - f2);
1548  pp[kpp*3 + 1] = d2*p1[1] - d1*p2[1];
1549  pp[kpp*3 + 2] = d2*p1[2] - d1*p2[2];
1550  pp[kpp*3 + 3] = d2*p1[3] - d1*p2[3];
1551 }
1552 
1553 
1554 ////////////////////////////////////////////////////////////////////////////////
1555 /// Find visible parts of line (draw line)
1556 ///
1557 /// \param[in] r1 1-st point of the line
1558 /// \param[in] r2 2-nd point of the line
1559 
1561 {
1562  Double_t yy1u, yy2u;
1563  Int_t i, icase, i1, i2, icase1, icase2, iv, ifback;
1564  Double_t x1, x2, y1, y2, z1, z2, dd, di;
1565  Double_t dt, dy;
1566  Double_t tt, uu, ww, yy, yy1, yy2, yy1d, yy2d;
1567  Double_t *tn = 0;
1568  const Double_t kEpsil = 1.e-6;
1569  /* Parameter adjustments */
1570  --r2;
1571  --r1;
1572  TView *view = 0;
1573 
1574  if (gPad) view = gPad->GetView();
1575  if (view) {
1576  tn = view->GetTN();
1577  if (tn) {
1578  x1 = tn[0]*r1[1] + tn[1]*r1[2] + tn[2]*r1[3] + tn[3];
1579  x2 = tn[0]*r2[1] + tn[1]*r2[2] + tn[2]*r2[3] + tn[3];
1580  y1 = tn[4]*r1[1] + tn[5]*r1[2] + tn[6]*r1[3] + tn[7];
1581  y2 = tn[4]*r2[1] + tn[5]*r2[2] + tn[6]*r2[3] + tn[7];
1582  z1 = tn[8]*r1[1] + tn[9]*r1[2] + tn[10]*r1[3] + tn[11];
1583  z2 = tn[8]*r2[1] + tn[9]*r2[2] + tn[10]*r2[3] + tn[11];
1584  } else {
1585  Error("FindVisibleDraw", "invalid TView in current pad");
1586  return;
1587  }
1588  } else {
1589  Error("FindVisibleDraw", "no TView in current pad");
1590  return;
1591  }
1592 
1593  ifback = 0;
1594  if (x1 >= x2) {
1595  ifback = 1;
1596  ww = x1;
1597  x1 = x2;
1598  x2 = ww;
1599  ww = y1;
1600  y1 = y2;
1601  y2 = ww;
1602  ww = z1;
1603  z1 = z2;
1604  z2 = ww;
1605  }
1606  fNT = 0;
1607  i1 = Int_t((x1 - fX0) / fDX) + 15;
1608  i2 = Int_t((x2 - fX0) / fDX) + 15;
1609  x1 = fX0 + (i1 - 1)*fDX;
1610  x2 = fX0 + (i2 - 1)*fDX;
1611  if (i1 != i2) {
1612 
1613  // 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
1614  di = (Double_t) (i2 - i1);
1615  dy = (y2 - y1) / di;
1616  dt = 1 / di;
1617  iv = -1;
1618  for (i = i1; i <= i2 - 1; ++i) {
1619  yy1 = y1 + dy*(i - i1);
1620  yy2 = yy1 + dy;
1621  yy1u = yy1 - fU[2*i - 2];
1622  yy1d = yy1 - fD[2*i - 2];
1623  yy2u = yy2 - fU[2*i - 1];
1624  yy2d = yy2 - fD[2*i - 1];
1625  tt = dt*(i - i1);
1626  // A N A L I Z E L E F T S I D E
1627  icase1 = 1;
1628  if (yy1u > kEpsil) icase1 = 0;
1629  if (yy1d < -kEpsil) icase1 = 2;
1630  if ((icase1 == 0 || icase1 == 2) && iv <= 0) {
1631  iv = 1;
1632  ++fNT;
1633  fT[2*fNT - 2] = tt;
1634  }
1635  if (icase1 == 1 && iv >= 0) {
1636  iv = -1;
1637  fT[2*fNT - 1] = tt;
1638  }
1639  // A N A L I Z E R I G H T S I D E
1640  icase2 = 1;
1641  if (yy2u > kEpsil) icase2 = 0;
1642  if (yy2d < -kEpsil) icase2 = 2;
1643  icase = icase1*3 + icase2;
1644  if (icase == 1) {
1645  iv = -1;
1646  fT[2*fNT - 1] = tt + dt*(yy1u / (yy1u - yy2u));
1647  }
1648  if (icase == 2) {
1649  fT[2*fNT - 1] = tt + dt*(yy1u / (yy1u - yy2u));
1650  ++fNT;
1651  fT[2*fNT - 2] = tt + dt*(yy1d / (yy1d - yy2d));
1652  }
1653  if (icase == 3) {
1654  iv = 1;
1655  ++fNT;
1656  fT[2*fNT - 2] = tt + dt*(yy1u / (yy1u - yy2u));
1657  }
1658  if (icase == 5) {
1659  iv = 1;
1660  ++fNT;
1661  fT[2*fNT - 2] = tt + dt*(yy1d / (yy1d - yy2d));
1662  }
1663  if (icase == 6) {
1664  fT[2*fNT - 1] = tt + dt*(yy1d / (yy1d - yy2d));
1665  ++fNT;
1666  fT[2*fNT - 2] = tt + dt*(yy1u / (yy1u - yy2u));
1667  }
1668  if (icase == 7) {
1669  iv = -1;
1670  fT[2*fNT - 1] = tt + dt*(yy1d / (yy1d - yy2d));
1671  }
1672  if (fNT + 1 >= 100) break;
1673  }
1674  if (iv > 0) fT[2*fNT - 1] = 1;
1675  } else {
1676 
1677  // V E R T I C A L L I N E
1678  fNT = 1;
1679  fT[0] = 0;
1680  fT[1] = 1;
1681  if (y2 <= y1) {
1682  if (y2 == y1) { fNT = 0; return;}
1683  ifback = 1 - ifback;
1684  yy = y1;
1685  y1 = y2;
1686  y2 = yy;
1687  }
1688  uu = fU[2*i1 - 2];
1689  dd = fD[2*i1 - 2];
1690  if (i1 != 1) {
1691  if (uu < fU[2*i1 - 3]) uu = fU[2*i1 - 3];
1692  if (dd > fD[2*i1 - 3]) dd = fD[2*i1 - 3];
1693  }
1694  // F I N D V I S I B L E P A R T O F L I N E
1695  if (y1 < uu && y2 > dd) {
1696  if (y1 >= dd && y2 <= uu) {fNT = 0; return;}
1697  fNT = 0;
1698  if (dd > y1) {
1699  ++fNT;
1700  fT[2*fNT - 2] = 0;
1701  fT[2*fNT - 1] = (dd - y1) / (y2 - y1);
1702  }
1703  if (uu < y2) {
1704  ++fNT;
1705  fT[2*fNT - 2] = (uu - y1) / (y2 - y1);
1706  fT[2*fNT - 1] = 1;
1707  }
1708  }
1709  }
1710 
1711  if (ifback == 0) return;
1712  if (fNT == 0) return;
1713  for (i = 1; i <= fNT; ++i) {
1714  fT[2*i - 2] = 1 - fT[2*i - 2];
1715  fT[2*i - 1] = 1 - fT[2*i - 1];
1716  }
1717 }
1718 
1719 
1720 ////////////////////////////////////////////////////////////////////////////////
1721 /// Find visible part of a line ("RASTER SCREEN")
1722 ///
1723 /// \param[in] p1 1st point of the line
1724 /// \param[in] p2 2nd point of the line
1725 /// \param[in] ntmax max allowed number of visible segments
1726 ///
1727 /// \param[out] nt number of visible segments of the line
1728 /// \param[out] t visible segments
1729 
1731 {
1732  Double_t ddtt;
1733  Double_t tcur;
1734  Int_t i, incrx, ivis, x1, y1, x2, y2, ib, kb, dx, dy, iw, ix, iy, ifinve, dx2, dy2;
1735  Double_t t1, t2;
1736  Double_t dt;
1737  Double_t tt;
1738  /* Parameter adjustments */
1739  t -= 3;
1740  --p2;
1741  --p1;
1742 
1743  if (fIfrast) {
1744  nt = 1;
1745  t[3] = 0;
1746  t[4] = 1;
1747  return;
1748  }
1749  x1 = Int_t(fNxrast*((p1[1] - fXrast) / fDXrast) - 0.01);
1750  y1 = Int_t(fNyrast*((p1[2] - fYrast) / fDYrast) - 0.01);
1751  x2 = Int_t(fNxrast*((p2[1] - fXrast) / fDXrast) - 0.01);
1752  y2 = Int_t(fNyrast*((p2[2] - fYrast) / fDYrast) - 0.01);
1753  ifinve = 0;
1754  if (y1 > y2) {
1755  ifinve = 1;
1756  iw = x1;
1757  x1 = x2;
1758  x2 = iw;
1759  iw = y1;
1760  y1 = y2;
1761  y2 = iw;
1762  }
1763  nt = 0;
1764  ivis = 0;
1765  if (y1 >= fNyrast) return;
1766  if (y2 < 0) return;
1767  if (x1 >= fNxrast && x2 >= fNxrast) return;
1768  if (x1 < 0 && x2 < 0) return;
1769 
1770  // S E T I N I T I A L V A L U E S
1771  incrx = 1;
1772  dx = x2 - x1;
1773  if (dx < 0) {
1774  dx = -dx;
1775  incrx = -1;
1776  }
1777  dy = y2 - y1;
1778  dx2 = dx + dx;
1779  dy2 = dy + dy;
1780  if (dy > dx) goto L200;
1781 
1782  // D X . G T . D Y
1783  dt = 1./ (Double_t)(dx + 1.);
1784  ddtt = dt*(float).5;
1785  tcur = -(Double_t)dt;
1786  tt = (Double_t) (-(dx + dy2));
1787  iy = y1;
1788  kb = iy*fNxrast + x1 - incrx;
1789  for (ix = x1; incrx < 0 ? ix >= x2 : ix <= x2; ix += incrx) {
1790  kb += incrx;
1791  tcur += dt;
1792  tt += dy2;
1793  if (tt >= 0) {
1794  ++iy;
1795  tt -= dx2;
1796  kb += fNxrast;
1797  }
1798  if (iy < 0) goto L110;
1799  if (iy >= fNyrast) goto L110;
1800  if (ix < 0) goto L110;
1801  if (ix >= fNxrast) goto L110;
1802  iw = kb / 30;
1803  ib = kb - iw*30 + 1;
1804  if (fRaster[iw] & fMask[ib - 1]) goto L110;
1805  if (ivis > 0) continue;
1806  ivis = 1;
1807  ++nt;
1808  t[2*nt + 1] = tcur;
1809  continue;
1810 L110:
1811  if (ivis == 0) continue;
1812  ivis = 0;
1813  t[2*nt + 2] = tcur;
1814  if (nt == ntmax) goto L300;
1815  }
1816  if (ivis > 0) t[2*nt + 2] = tcur + dt + ddtt;
1817  goto L300;
1818 
1819  // D Y . G T . D X
1820 L200:
1821  dt = 1. / (Double_t)(dy + 1.);
1822  ddtt = dt*(float).5;
1823  tcur = -(Double_t)dt;
1824  tt = (Double_t) (-(dy + dx2));
1825  ix = x1;
1826  if (y2 >= fNyrast) y2 = fNyrast - 1;
1827  kb = (y1 - 1)*fNxrast + ix;
1828  for (iy = y1; iy <= y2; ++iy) {
1829  kb += fNxrast;
1830  tcur += dt;
1831  tt += dx2;
1832  if (tt >= 0) {
1833  ix += incrx;
1834  tt -= dy2;
1835  kb += incrx;
1836  }
1837  if (iy < 0) goto L210;
1838  if (ix < 0) goto L210;
1839  if (ix >= fNxrast) goto L210;
1840  iw = kb / 30;
1841  ib = kb - iw*30 + 1;
1842  if (fRaster[iw] & fMask[ib - 1]) goto L210;
1843  if (ivis > 0) continue;
1844  ivis = 1;
1845  ++nt;
1846  t[2*nt + 1] = tcur;
1847  continue;
1848 L210:
1849  if (ivis == 0) continue;
1850  ivis = 0;
1851  t[2*nt + 2] = tcur;
1852  if (nt == ntmax) goto L300;
1853  }
1854  if (ivis > 0) t[2*nt + 2] = tcur + dt;
1855 
1856  // 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
1857 L300:
1858  if (nt == 0) return;
1859  dt *= 1.1;
1860  if (t[3] <= dt) t[3] = 0;
1861  if (t[2*nt + 2] >= 1 - dt) t[2*nt + 2] = 1;
1862  if (ifinve == 0) return;
1863  for (i = 1; i <= nt; ++i) {
1864  t1 = t[2*i + 1];
1865  t2 = t[2*i + 2];
1866  t[2*i + 1] = 1 - t2;
1867  t[2*i + 2] = 1 - t1;
1868  }
1869 }
1870 
1871 
1872 ////////////////////////////////////////////////////////////////////////////////
1873 /// Draw forward faces of surrounding box & axes
1874 ///
1875 /// `ang`is the angle between X and Y axis
1876 
1878 {
1879  /* Initialized data */
1880  static Int_t iface1[4] = { 1,2,6,5 };
1881  static Int_t iface2[4] = { 2,3,7,6 };
1882 
1883  Double_t cosa, sina;
1884  Double_t r[24] /* was [3][8] */, av[24] /* was [3][8] */;
1885  Int_t icodes[3];
1886  Double_t fdummy[1];
1887  Int_t i, ix1, ix2, iy1, iy2, iz1, iz2;
1888  TView *view = 0;
1889 
1890  if (gPad) view = gPad->GetView();
1891  if (!view) {
1892  Error("FrontBox", "no TView in current pad");
1893  return;
1894  }
1895 
1896  cosa = TMath::Cos(kRad*ang);
1897  sina = TMath::Sin(kRad*ang);
1898  view->AxisVertex(ang, av, ix1, ix2, iy1, iy2, iz1, iz2);
1899  for (i = 1; i <= 8; ++i) {
1900  r[i*3 - 3] = av[i*3 - 3] + av[i*3 - 2] * cosa;
1901  r[i*3 - 2] = av[i*3 - 2] * sina;
1902  r[i*3 - 1] = av[i*3 - 1];
1903  }
1904 
1905  // D R A W F O R W A R D F A C E S
1906  icodes[0] = 0;
1907  icodes[1] = 0;
1908  icodes[2] = 0;
1909  (this->*fDrawFace)(icodes, r, 4, iface1, fdummy);
1910  (this->*fDrawFace)(icodes, r, 4, iface2, fdummy);
1911 }
1912 
1913 
1914 ////////////////////////////////////////////////////////////////////////////////
1915 /// Find part of surface with luminosity in the corners. This method is used for
1916 /// Gouraud shading
1917 
1919 {
1920  Int_t iphi;
1921  static Double_t f[108]; /* was [3][4][3][3] */
1922  Int_t i, j, k;
1923  Double_t r, s, x[36]; /* was [4][3][3] */
1924  Double_t y[36]; /* was [4][3][3] */
1925  Double_t z[36]; /* was [4][3][3] */
1926  Int_t incrx[3], incry[3];
1927 
1928  Double_t x1, x2, y1, y2, z1, z2, th, an[27]; /* was [3][3][3] */
1929  Double_t bn[12]; /* was [3][2][2] */
1930 
1931  Double_t rad;
1932  Double_t phi;
1933  Int_t ixt, iyt;
1934 
1935  /* Parameter adjustments */
1936  --t;
1937  face -= 4;
1938 
1939  iphi = 1;
1940  rad = TMath::ATan(1) * (float)4 / (float)180;
1941 
1942  // Find real cell indexes
1943  ixt = ia + Hparam.xfirst - 1;
1944  iyt = ib + Hparam.yfirst - 1;
1945 
1946  // Find increments of neighboring cells
1947  incrx[0] = -1;
1948  incrx[1] = 0;
1949  incrx[2] = 1;
1950  if (ixt == 1) incrx[0] = 0;
1951  if (ixt == Hparam.xlast - 1) incrx[2] = 0;
1952  incry[0] = -1;
1953  incry[1] = 0;
1954  incry[2] = 1;
1955  if (iyt == 1) incry[0] = 0;
1956  if (iyt == Hparam.ylast - 1) incry[2] = 0;
1957 
1958  // Find neighboring faces
1959  Int_t i1, i2;
1960  for (j = 1; j <= 3; ++j) {
1961  for (i = 1; i <= 3; ++i) {
1962  i1 = ia + incrx[i - 1];
1963  i2 = ib + incry[j - 1];
1964  SurfaceFunction(i1, i2, &f[(((i + j*3) << 2) + 1)*3 - 51], &t[1]);
1965  }
1966  }
1967 
1968  // Set face
1969  for (k = 1; k <= 4; ++k) {
1970  for (i = 1; i <= 3; ++i) {
1971  face[i + k*3] = f[i + (k + 32)*3 - 52];
1972  }
1973  }
1974 
1975  // Find coordinates and normales
1976  for (j = 1; j <= 3; ++j) {
1977  for (i = 1; i <= 3; ++i) {
1978  for (k = 1; k <= 4; ++k) {
1979  if (Hoption.System == kPOLAR) {
1980  phi = f[iphi + (k + ((i + j*3) << 2))*3 - 52]*rad;
1981  r = f[3 - iphi + (k + ((i + j*3) << 2))*3 - 52];
1982  x[k + ((i + j*3) << 2) - 17] = r * TMath::Cos(phi);
1983  y[k + ((i + j*3) << 2) - 17] = r * TMath::Sin(phi);
1984  z[k + ((i + j*3) << 2) - 17] = f[(k + ((i + j*3) << 2))*3 - 49];
1985  } else if (Hoption.System == kCYLINDRICAL) {
1986  phi = f[iphi + (k + ((i + j*3) << 2))*3 - 52]*rad;
1987  r = f[(k + ((i + j*3) << 2))*3 - 49];
1988  x[k + ((i + j*3) << 2) - 17] = r*TMath::Cos(phi);
1989  y[k + ((i + j*3) << 2) - 17] = r*TMath::Sin(phi);
1990  z[k + ((i + j*3) << 2) - 17] = f[3 - iphi + (k + ((i + j*3) << 2))*3 - 52];
1991  } else if (Hoption.System == kSPHERICAL) {
1992  phi = f[iphi + (k + ((i + j*3) << 2))*3 - 52]*rad;
1993  th = f[3 - iphi + (k + ((i + j*3) << 2))*3 - 52]*rad;
1994  r = f[(k + ((i + j*3) << 2))*3 - 49];
1995  x[k + ((i + j*3) << 2) - 17] = r*TMath::Sin(th)*TMath::Cos(phi);
1996  y[k + ((i + j*3) << 2) - 17] = r*TMath::Sin(th)*TMath::Sin(phi);
1997  z[k + ((i + j*3) << 2) - 17] = r*TMath::Cos(th);
1998  } else if (Hoption.System == kRAPIDITY) {
1999  phi = f[iphi + (k + ((i + j*3) << 2))*3 - 52]*rad;
2000  th = f[3 - iphi + (k + ((i + j*3) << 2))*3 - 52]*rad;
2001  r = f[(k + ((i + j*3) << 2))*3 - 49];
2002  x[k + ((i + j*3) << 2) - 17] = r*TMath::Cos(phi);
2003  y[k + ((i + j*3) << 2) - 17] = r*TMath::Sin(phi);
2004  z[k + ((i + j*3) << 2) - 17] = r*TMath::Cos(th) / TMath::Sin(th);
2005  } else {
2006  x[k + ((i + j*3) << 2) - 17] = f[(k + ((i + j*3) << 2))*3 - 51];
2007  y[k + ((i + j*3) << 2) - 17] = f[(k + ((i + j*3) << 2))*3 - 50];
2008  z[k + ((i + j*3) << 2) - 17] = f[(k + ((i + j*3) << 2))*3 - 49];
2009  }
2010  }
2011  x1 = x[((i + j*3) << 2) - 14] - x[((i + j*3) << 2) - 16];
2012  x2 = x[((i + j*3) << 2) - 13] - x[((i + j*3) << 2) - 15];
2013  y1 = y[((i + j*3) << 2) - 14] - y[((i + j*3) << 2) - 16];
2014  y2 = y[((i + j*3) << 2) - 13] - y[((i + j*3) << 2) - 15];
2015  z1 = z[((i + j*3) << 2) - 14] - z[((i + j*3) << 2) - 16];
2016  z2 = z[((i + j*3) << 2) - 13] - z[((i + j*3) << 2) - 15];
2017  an[(i + j*3)*3 - 12] = y1*z2 - y2*z1;
2018  an[(i + j*3)*3 - 11] = z1*x2 - z2*x1;
2019  an[(i + j*3)*3 - 10] = x1*y2 - x2*y1;
2020  s = TMath::Sqrt(an[(i + j*3)*3 - 12]*an[(i + j*3)*3 - 12] + an[
2021  (i + j*3)*3 - 11]*an[(i + j*3)*3 - 11] + an[(i
2022  + j*3)*3 - 10]*an[(i + j*3)*3 - 10]);
2023 
2024  an[(i + j*3)*3 - 12] /= s;
2025  an[(i + j*3)*3 - 11] /= s;
2026  an[(i + j*3)*3 - 10] /= s;
2027  }
2028  }
2029 
2030  // Find average normals
2031  for (j = 1; j <= 2; ++j) {
2032  for (i = 1; i <= 2; ++i) {
2033  for (k = 1; k <= 3; ++k) {
2034  bn[k + (i + 2*j)*3 - 10] = an[k + (i + j*3)*3 - 13]
2035  + an[k + (i + 1 + j*3)*3 - 13] + an[k + (i + 1 +
2036  (j + 1)*3)*3 - 13] + an[k + (i + (j + 1)*3)*3 - 13];
2037  }
2038  }
2039  }
2040 
2041  // Set luminosity
2042  Luminosity(bn, t[1]);
2043  Luminosity(&bn[3], t[2]);
2044  Luminosity(&bn[9], t[3]);
2045  Luminosity(&bn[6], t[4]);
2046 }
2047 
2048 
2049 ////////////////////////////////////////////////////////////////////////////////
2050 /// Initialize "MOVING SCREEN" method
2051 ///
2052 /// \param[in] xmin left boundary
2053 /// \param[in] xmax right boundary
2054 
2056 {
2057  fX0 = xmin;
2058  fDX = (xmax - xmin) / 1000;
2059  for (Int_t i = 1; i <= 1000; ++i) {
2060  fU[2*i - 2] = (float)-999;
2061  fU[2*i - 1] = (float)-999;
2062  fD[2*i - 2] = (float)999;
2063  fD[2*i - 1] = (float)999;
2064  }
2065 }
2066 
2067 
2068 ////////////////////////////////////////////////////////////////////////////////
2069 /// Initialize hidden lines removal algorithm (RASTER SCREEN)
2070 ///
2071 /// \param[in] xmin Xmin in the normalized coordinate system
2072 /// \param[in] ymin Ymin in the normalized coordinate system
2073 /// \param[in] xmax Xmax in the normalized coordinate system
2074 /// \param[in] ymax Ymax in the normalized coordinate system
2075 /// \param[in] nx number of pixels along X
2076 /// \param[in] ny number of pixels along Y
2077 
2079 {
2080  Int_t i, j, k, ib, nb;
2081 
2082  fNxrast = nx;
2083  fNyrast = ny;
2084  fXrast = xmin;
2085  fDXrast = xmax - xmin;
2086  fYrast = ymin;
2087  fDYrast = ymax - ymin;
2088 
2089  // Create buffer for raster
2090  Int_t buffersize = nx*ny/30 + 1;
2091  fRaster = new Int_t[buffersize];
2092 
2093  // S E T M A S K S
2094  k = 0;
2095  Int_t pow2 = 1;
2096  for (i = 1; i <= 30; ++i) {
2097  fJmask[i - 1] = k;
2098  k = k + 30 - i + 1;
2099  fMask[i - 1] = pow2;
2100  pow2 *= 2;
2101  }
2102  j = 30;
2103  for (nb = 2; nb <= 30; ++nb) {
2104  for (ib = 1; ib <= 30 - nb + 1; ++ib) {
2105  k = 0;
2106  for (i = ib; i <= ib + nb - 1; ++i) k = k | fMask[i - 1];
2107  ++j;
2108  fMask[j - 1] = k;
2109  }
2110  }
2111 
2112  // C L E A R R A S T E R S C R E E N
2113  ClearRaster();
2114 }
2115 
2116 
2117 ////////////////////////////////////////////////////////////////////////////////
2118 /// Service function for Legos
2119 
2121 {
2122  Int_t i, j, ixt, iyt;
2123  Double_t yval1l, yval2l;
2124  Double_t xlab1l, xlab2l, ylab1l, ylab2l;
2125  Double_t rinrad = gStyle->GetLegoInnerR();
2126  Double_t dangle = 10; //Delta angle for Rapidity option
2127 
2128  /* Parameter adjustments */
2129  t -= 5;
2130  --vv;
2131  ab -= 3;
2132 
2133  ixt = ia + Hparam.xfirst - 1;
2134  iyt = ib + Hparam.yfirst - 1;
2135 
2136  // Compute the cell position in cartesian coordinates
2137  // and compute the LOG if necessary
2138  Double_t xwid = gCurrentHist->GetXaxis()->GetBinWidth(ixt);
2139  Double_t ywid = gCurrentHist->GetYaxis()->GetBinWidth(iyt);
2140  ab[3] = gCurrentHist->GetXaxis()->GetBinLowEdge(ixt) + xwid*Hparam.baroffset;
2141  ab[4] = gCurrentHist->GetYaxis()->GetBinLowEdge(iyt) + ywid*Hparam.baroffset;
2142  ab[5] = ab[3] + xwid*Hparam.barwidth;
2143  ab[8] = ab[4] + ywid*Hparam.barwidth;
2144 
2145  if (Hoption.Logx) {
2146  if (ab[3] > 0) ab[3] = TMath::Log10(ab[3]);
2147  else ab[3] = Hparam.xmin;
2148  if (ab[5] > 0) ab[5] = TMath::Log10(ab[5]);
2149  else ab[5] = Hparam.xmin;
2150  }
2151  // xval1l = Hparam.xmin;
2152  // xval2l = Hparam.xmax;
2153  if (Hoption.Logy) {
2154  if (ab[4] > 0) ab[4] = TMath::Log10(ab[4]);
2155  else ab[4] = Hparam.ymin;
2156  if (ab[8] > 0) ab[8] = TMath::Log10(ab[8]);
2157  else ab[8] = Hparam.ymin;
2158  }
2159  yval1l = Hparam.ymin;
2160  yval2l = Hparam.ymax;
2161 
2162  if (ab[3] < Hparam.xmin) ab[3] = Hparam.xmin;
2163  if (ab[4] < Hparam.ymin) ab[4] = Hparam.ymin;
2164  if (ab[5] > Hparam.xmax) ab[5] = Hparam.xmax;
2165  if (ab[8] > Hparam.ymax) ab[8] = Hparam.ymax;
2166  if (ab[5] < Hparam.xmin) ab[5] = Hparam.xmin;
2167  if (ab[8] < Hparam.ymin) ab[8] = Hparam.ymin;
2168 
2169  xlab1l = gCurrentHist->GetXaxis()->GetXmin();
2170  xlab2l = gCurrentHist->GetXaxis()->GetXmax();
2171  if (Hoption.Logx) {
2172  if (xlab2l>0) {
2173  if (xlab1l>0) xlab1l = TMath::Log10(xlab1l);
2174  else xlab1l = TMath::Log10(0.001*xlab2l);
2175  xlab2l = TMath::Log10(xlab2l);
2176  }
2177  }
2178  ylab1l = gCurrentHist->GetYaxis()->GetXmin();
2179  ylab2l = gCurrentHist->GetYaxis()->GetXmax();
2180  if (Hoption.Logy) {
2181  if (ylab2l>0) {
2182  if (ylab1l>0) ylab1l = TMath::Log10(ylab1l);
2183  else ylab1l = TMath::Log10(0.001*ylab2l);
2184  ylab2l = TMath::Log10(ylab2l);
2185  }
2186  }
2187 
2188  // Transform the cell position in the required coordinate system
2189  if (Hoption.System == kPOLAR) {
2190  ab[3] = 360*(ab[3] - xlab1l) / (xlab2l - xlab1l);
2191  ab[5] = 360*(ab[5] - xlab1l) / (xlab2l - xlab1l);
2192  ab[4] = (ab[4] - yval1l) / (yval2l - yval1l);
2193  ab[8] = (ab[8] - yval1l) / (yval2l - yval1l);
2194  } else if (Hoption.System == kCYLINDRICAL) {
2195  ab[3] = 360*(ab[3] - xlab1l) / (xlab2l - xlab1l);
2196  ab[5] = 360*(ab[5] - xlab1l) / (xlab2l - xlab1l);
2197  } else if (Hoption.System == kSPHERICAL) {
2198  ab[3] = 360*(ab[3] - xlab1l) / (xlab2l - xlab1l);
2199  ab[5] = 360*(ab[5] - xlab1l) / (xlab2l - xlab1l);
2200  ab[4] = 180*(ab[4] - ylab1l) / (ylab2l - ylab1l);
2201  ab[8] = 180*(ab[8] - ylab1l) / (ylab2l - ylab1l);
2202  } else if (Hoption.System == kRAPIDITY) {
2203  ab[3] = 360*(ab[3] - xlab1l) / (xlab2l - xlab1l);
2204  ab[5] = 360*(ab[5] - xlab1l) / (xlab2l - xlab1l);
2205  ab[4] = (180 - dangle*2)*(ab[4] - ylab1l) / (ylab2l - ylab1l) + dangle;
2206  ab[8] = (180 - dangle*2)*(ab[8] - ylab1l) / (ylab2l - ylab1l) + dangle;
2207  }
2208 
2209  // Complete the cell coordinates
2210  ab[6] = ab[4];
2211  ab[7] = ab[5];
2212  ab[9] = ab[3];
2213  ab[10] = ab[8];
2214 
2215  // Get the content of the table, and loop on the
2216  // stack if necessary.
2217  vv[1] = Hparam.zmin;
2218  vv[2] = Hparam.factor*gCurrentHist->GetBinContent(ixt, iyt);
2219 
2220  // In linear scale, 3D boxes all start from 0.
2221  if (Hparam.zmin<0 && !Hoption.Logz && gStyle->GetHistMinimumZero()) {
2222  if (vv[2]<0) {
2223  vv[1] = vv[2];
2224  vv[2] = 0;
2225  } else {
2226  vv[1]=0;
2227  }
2228  }
2229 
2230  TList *stack = gCurrentHist->GetPainter()->GetStack();
2231  Int_t nids = 0; //not yet implemented
2232  if (stack) nids = stack->GetSize();
2233  if (nids) {
2234  for (i = 2; i <= nids + 1; ++i) {
2235  TH1 *hid = (TH1*)stack->At(i-2);
2236  vv[i + 1] = Hparam.factor*hid->GetBinContent(ixt, iyt) + vv[i];
2237  vv[i + 1] = TMath::Max(Hparam.zmin, vv[i + 1]);
2238  //vv[i + 1] = TMath::Min(Hparam.zmax, vv[i + 1]);
2239  }
2240  }
2241 
2242  nv = nids + 2;
2243  for (i = 2; i <= nv; ++i) {
2244  if (Hoption.Logz) {
2245  if (vv[i] > 0)
2246  vv[i] = TMath::Max(Hparam.zmin, (Double_t)TMath::Log10(vv[i]));
2247  else
2248  vv[i] = Hparam.zmin;
2249  vv[i] = TMath::Min(vv[i], Hparam.zmax);
2250  } else {
2251  vv[i] = TMath::Max(Hparam.zmin, vv[i]);
2252  vv[i] = TMath::Min(Hparam.zmax, vv[i]);
2253  }
2254  }
2255 
2256  if (!Hoption.Logz) {
2257  i = 3;
2258  while (i <= nv) {
2259  if (vv[i] < vv[i - 1]) {
2260  vv[i - 1] = vv[i];
2261  i = 3;
2262  continue;
2263  }
2264  ++i;
2265  }
2266  }
2267 
2268  // For cylindrical, spherical and pseudo-rapidity, the content
2269  // is mapped onto the radius
2270  if (Hoption.System == kCYLINDRICAL || Hoption.System == kSPHERICAL || Hoption.System == kRAPIDITY) {
2271  for (i = 1; i <= nv; ++i) {
2272  vv[i] = (1 - rinrad)*((vv[i] - Hparam.zmin) /
2273  (Hparam.zmax - Hparam.zmin)) + rinrad;
2274  }
2275  }
2276 
2277  for (i = 1; i <= nv; ++i) {
2278  for (j = 1; j <= 4; ++j) t[j + (i << 2)] = vv[i];
2279  }
2280 }
2281 
2282 
2283 ////////////////////////////////////////////////////////////////////////////////
2284 /// Draw stack of lego-plots in cartesian coordinates
2285 ///
2286 /// \param[in] ang angle between X ang Y
2287 /// \param[in] nx number of cells along X
2288 /// \param[in] ny number of cells along Y
2289 ///
2290 /// - `chopt` = 'BF' from BACK to FRONT
2291 /// - `chopt` = 'FB' from FRONT to BACK
2292 
2294 {
2295 
2296 
2297  // Local variables
2298  Double_t cosa, sina;
2299  Int_t ivis[4], iface[4];
2300  Double_t tface[4];
2301  Int_t incrx, incry, i1, k1, k2, ix1, iy1, ix2, iy2, i, iv, ix, iy, nv;
2302  Int_t icodes[4];
2303  Double_t zn, xy[8]; // was [2][4]
2304  Double_t xyz[24]; // was [3][8]
2305  Double_t *tn = 0;
2306  TView *view = 0;
2307  Int_t firstStackNumberDrawn=-1 ; // necessary to compute fColorBottom when the 0 option is set and when the stack is seen from below (bottomview, theta<0.)
2308 
2309  sina = TMath::Sin(ang*kRad);
2310  cosa = TMath::Cos(ang*kRad);
2311 
2312  // F I N D T H E M O S T L E F T P O I N T
2313  if (gPad) view = gPad->GetView();
2314  if (!view) {
2315  Error("LegoCartesian", "no TView in current pad");
2316  return;
2317  }
2318  tn = view->GetTN();
2319 
2320  i1 = 1;
2321  if (tn) {
2322  if (tn[0] < 0) i1 = 2;
2323  if (tn[0]*cosa + tn[1]*sina < 0) i1 = 5 - i1;
2324  }
2325 
2326  // Allocate v and tt arrays
2327  Double_t *v, *tt;
2328  Int_t vSize = fNStack+2;
2329  if (vSize > kVSizeMax) {
2330  v = new Double_t[vSize];
2331  tt = new Double_t[4*vSize];
2332  } else {
2333  vSize = kVSizeMax;
2334  v = &gV[0];
2335  tt = &gTT[0];
2336  }
2337 
2338  // D E F I N E O R D E R O F D R A W I N G
2339  if (*chopt == 'B' || *chopt == 'b') {
2340  incrx = -1;
2341  incry = -1;
2342  } else {
2343  incrx = 1;
2344  incry = 1;
2345  }
2346  if (i1 == 1 || i1 == 2) incrx = -incrx;
2347  if (i1 == 2 || i1 == 3) incry = -incry;
2348  ix1 = 1;
2349  iy1 = 1;
2350  if (incrx < 0) ix1 = nx;
2351  if (incry < 0) iy1 = ny;
2352  ix2 = nx - ix1 + 1;
2353  iy2 = ny - iy1 + 1;
2354 
2355  // F I N D V I S I B I L I T Y O F S I D E S
2356  ivis[0] = 0;
2357  ivis[1] = 0;
2358  ivis[2] = 0;
2359  ivis[3] = 0;
2360  nv = 0;
2361  view->FindNormal(0, 1, 0, zn);
2362  if (zn < 0) ivis[0] = 1;
2363  if (zn > 0) ivis[2] = 1;
2364  view->FindNormal(sina, cosa, 0, zn);
2365  if (zn > 0) ivis[1] = 1;
2366  if (zn < 0) ivis[3] = 1;
2367 
2368  // D R A W S T A C K O F L E G O - P L O T S
2369  THistPainter *painter = (THistPainter*)gCurrentHist->GetPainter();
2370  for (iy = iy1; incry < 0 ? iy >= iy2 : iy <= iy2; iy += incry) {
2371  for (ix = ix1; incrx < 0 ? ix >= ix2 : ix <= ix2; ix += incrx) {
2372  if (!painter->IsInside(ix,iy)) continue;
2373  (this->*fLegoFunction)(ix, iy, nv, xy, v, tt);
2374  if (nv < 2 || nv > vSize) continue;
2375  if (Hoption.Zero) {
2376  Double_t total_content=0;
2377  for (iv = 1; iv < nv; ++iv) total_content += v[iv];
2378  if (total_content==0) continue;
2379  }
2380  icodes[0] = ix;
2381  icodes[1] = iy;
2382  for (i = 1; i <= 4; ++i) {
2383  xyz[i*3 - 3] = xy[2*i - 2] + xy[2*i - 1]*cosa;
2384  xyz[i*3 - 2] = xy[2*i - 1]*sina;
2385  xyz[(i + 4)*3 - 3] = xyz[i*3 - 3];
2386  xyz[(i + 4)*3 - 2] = xyz[i*3 - 2];
2387  }
2388  // D R A W S T A C K
2389  firstStackNumberDrawn = -1;
2390  for (iv = 1; iv < nv; ++iv) {
2391  for (i = 1; i <= 4; ++i) {
2392  xyz[i*3 - 1] = v[iv - 1];
2393  xyz[(i + 4)*3 - 1] = v[iv];
2394  }
2395  if (v[iv - 1] == v[iv]) continue;
2396  icodes[2] = iv;
2397  for (i = 1; i <= 4; ++i) {
2398  if (ivis[i - 1] == 0) continue;
2399  k1 = i;
2400  k2 = i + 1;
2401  if (i == 4) k2 = 1;
2402  icodes[3] = k1;
2403  iface[0] = k1;
2404  iface[1] = k2;
2405  iface[2] = k2 + 4;
2406  iface[3] = k1 + 4;
2407  tface[0] = tt[k1 + (iv << 2) - 5];
2408  tface[1] = tt[k2 + (iv << 2) - 5];
2409  tface[2] = tt[k2 + ((iv + 1) << 2) - 5];
2410  tface[3] = tt[k1 + ((iv + 1) << 2) - 5];
2411  fEdgeIdx = iv-1;
2412  (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
2413  }
2414  if ( firstStackNumberDrawn==-1 ) firstStackNumberDrawn = fEdgeIdx;
2415  }
2416  // D R A W B O T T O M F A C E
2417  view->FindNormal(0, 0, 1, zn);
2418  if (zn < 0) {
2419  icodes[2] = 1;
2420  icodes[3] = 5;
2421  for (i = 1; i <= 4; ++i) {
2422  xyz[i*3 - 1] = v[0];
2423  iface[i - 1] = 5 - i;
2424  tface[i - 1] = tt[5 - i - 1];
2425  }
2426  if (!Hoption.Zero) fEdgeIdx = 0;
2427  else {
2428  fEdgeIdx = firstStackNumberDrawn;
2430  }
2431  (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
2432  }
2433  // D R A W T O P F A C E
2434  if (zn > 0) {
2435  icodes[2] = nv - 1;
2436  icodes[3] = 6;
2437  for (i = 1; i <= 4; ++i) {
2438  iface[i - 1] = i + 4;
2439  tface[i - 1] = tt[i + (nv << 2) - 5];
2440  }
2441  Int_t cs = fColorTop;
2442  if ( nv <= 3 ) fEdgeIdx = 0 ; // no stack or stack with only one histo
2443  else {
2444  if ( nv > 2 && (v[nv-1] == v[nv-2])) {
2445  for (iv = nv-1; iv>2; iv--) {
2446  if (v[nv-1] == v[iv-1]) {
2447  fColorTop = fColorMain[iv-2];
2448  fEdgeIdx = iv-2;
2449  }
2450  }
2451  }
2452  }
2453  (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
2454  fColorTop = cs;
2455  }
2456  }
2457  }
2458  if (vSize > kVSizeMax) {
2459  delete [] v;
2460  delete [] tt;
2461  }
2462 }
2463 
2464 
2465 ////////////////////////////////////////////////////////////////////////////////
2466 /// Draw stack of lego-plots in polar coordinates
2467 ///
2468 /// \param[in] iordr order of variables (0 - R,PHI; 1 - PHI,R)
2469 /// \param[in] na number of steps along 1st variable
2470 /// \param[in] nb number of steps along 2nd variable
2471 ///
2472 /// - `chopt` = 'BF' from BACK to FRONT
2473 /// - `chopt` = 'FB' from FRONT to BACK
2474 
2475 void TPainter3dAlgorithms::LegoPolar(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
2476 {
2477 
2478  Int_t iphi, jphi, kphi, incr, nphi, ivis[6], iopt, iphi1, iphi2, iface[4], i, j;
2479  Double_t tface[4];
2480  Int_t incrr, k1, k2, ia, ib, ir1, ir2;
2481  Double_t ab[8]; // was [2][4]
2482  Int_t ir, jr, iv, nr, nv, icodes[4];
2483  Double_t xyz[24]; // was [3][8]
2484  ia = ib = 0;
2485  TView *view = 0;
2486  Int_t firstStackNumberDrawn=-1 ; // necessary to compute fColorBottom when the 0 option is set and when the stack is seen from below (bottomview, theta<0.)
2487 
2488  if (gPad) view = gPad->GetView();
2489  if (!view) {
2490  Error("LegoPolar", "no TView in current pad");
2491  return;
2492  }
2493 
2494  if (iordr == 0) {
2495  jr = 1;
2496  jphi = 2;
2497  nr = na;
2498  nphi = nb;
2499  } else {
2500  jr = 2;
2501  jphi = 1;
2502  nr = nb;
2503  nphi = na;
2504  }
2505  if (nphi > 180) {
2506  Error("LegoPolar", "too many PHI sectors (%d)", nphi);
2507  return;
2508  }
2509  iopt = 2;
2510  if (*chopt == 'B' || *chopt == 'b') iopt = 1;
2511 
2512  // Allocate v and tt arrays
2513  Double_t *v, *tt;
2514  Int_t vSize = fNStack+2;
2515  if (vSize > kVSizeMax) {
2516  v = new Double_t[vSize];
2517  tt = new Double_t[4*vSize];
2518  } else {
2519  vSize = kVSizeMax;
2520  v = &gV[0];
2521  tt = &gTT[0];
2522  }
2523 
2524  // P R E P A R E P H I A R R A Y
2525  // F I N D C R I T I C A L S E C T O R S
2526  nv = 0;
2527  kphi = nphi;
2528  if (iordr == 0) ia = nr;
2529  if (iordr != 0) ib = nr;
2530  for (i = 1; i <= nphi; ++i) {
2531  if (iordr == 0) ib = i;
2532  if (iordr != 0) ia = i;
2533  (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
2534  if (i == 1) fAphi[0] = ab[jphi - 1];
2535  fAphi[i - 1] = (fAphi[i - 1] + ab[jphi - 1]) / (float)2.;
2536  fAphi[i] = ab[jphi + 3];
2537  }
2538  view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
2539 
2540  // E N C O D E V I S I B I L I T Y O F S I D E S
2541  // A N D O R D E R A L O N G R
2542  for (i = 1; i <= nphi; ++i) {
2543  if (!iordr) ib = i;
2544  if (iordr) ia = i;
2545  (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
2546  SideVisibilityEncode(iopt, ab[jphi - 1]*kRad, ab[jphi + 3]*kRad, fAphi[i - 1]);
2547  }
2548 
2549  // D R A W S T A C K O F L E G O - P L O T S
2550  incr = 1;
2551  iphi = iphi1;
2552 L100:
2553  if (iphi > nphi) goto L300;
2554 
2555  // D E C O D E V I S I B I L I T Y O F S I D E S
2556  SideVisibilityDecode(fAphi[iphi - 1], ivis[0], ivis[1], ivis[2], ivis[3], ivis[4], ivis[5], incrr);
2557  ir1 = 1;
2558  if (incrr < 0) ir1 = nr;
2559  ir2 = nr - ir1 + 1;
2560  // D R A W L E G O S F O R S E C T O R
2561  for (ir = ir1; incrr < 0 ? ir >= ir2 : ir <= ir2; ir += incrr) {
2562  if (iordr == 0) { ia = ir; ib = iphi; }
2563  else { ia = iphi; ib = ir; }
2564  (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
2565  if (nv < 2 || nv > vSize) continue;
2566  if (Hoption.Zero) {
2567  Double_t total_content=0;
2568  for (iv = 1; iv < nv; ++iv) total_content += v[iv];
2569  if (total_content==0) continue;
2570  }
2571  icodes[0] = ia;
2572  icodes[1] = ib;
2573  for (i = 1; i <= 4; ++i) {
2574  j = i;
2575  if (iordr != 0 && i == 2) j = 4;
2576  if (iordr != 0 && i == 4) j = 2;
2577  xyz[j*3 - 3] = ab[jr + 2*i - 3]*TMath::Cos(ab[jphi + 2*i - 3]*kRad);
2578  xyz[j*3 - 2] = ab[jr + 2*i - 3]*TMath::Sin(ab[jphi + 2*i - 3]*kRad);
2579  xyz[(j + 4)*3 - 3] = xyz[j*3 - 3];
2580  xyz[(j + 4)*3 - 2] = xyz[j*3 - 2];
2581  }
2582  // D R A W S T A C K
2583  firstStackNumberDrawn = -1;
2584  for (iv = 1; iv < nv; ++iv) {
2585  for (i = 1; i <= 4; ++i) {
2586  xyz[i*3 - 1] = v[iv - 1];
2587  xyz[(i + 4)*3 - 1] = v[iv];
2588  }
2589  if (v[iv - 1] >= v[iv]) continue;
2590  icodes[2] = iv;
2591  for (i = 1; i <= 4; ++i) {
2592  if (ivis[i - 1] == 0) continue;
2593  k1 = i - 1;
2594  if (i == 1) k1 = 4;
2595  k2 = i;
2596  if (xyz[k1*3 - 3] == xyz[k2*3 - 3] && xyz[k1*3 - 2] ==
2597  xyz[k2*3 - 2]) continue;
2598  iface[0] = k1;
2599  iface[1] = k2;
2600  iface[2] = k2 + 4;
2601  iface[3] = k1 + 4;
2602  tface[0] = tt[k1 + (iv << 2) - 5];
2603  tface[1] = tt[k2 + (iv << 2) - 5];
2604  tface[2] = tt[k2 + ((iv + 1) << 2) - 5];
2605  tface[3] = tt[k1 + ((iv + 1) << 2) - 5];
2606  icodes[3] = i;
2607  fEdgeIdx = iv-1;
2608  (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
2609  }
2610  if ( firstStackNumberDrawn==-1 ) firstStackNumberDrawn = fEdgeIdx;
2611  }
2612  // D R A W B O T T O M F A C E
2613  if (ivis[4] != 0) {
2614  icodes[2] = 1;
2615  icodes[3] = 5;
2616  for (i = 1; i <= 4; ++i) {
2617  xyz[i*3 - 1] = v[0];
2618  iface[i - 1] = 5 - i;
2619  tface[i - 1] = tt[5 - i - 1];
2620  }
2621  if (!Hoption.Zero) fEdgeIdx = 0;
2622  else {
2623  fEdgeIdx = firstStackNumberDrawn;
2625  }
2626  (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
2627  }
2628  // D R A W T O P F A C E
2629  if (ivis[5] != 0) {
2630  icodes[2] = nv - 1;
2631  icodes[3] = 6;
2632  for (i = 1; i <= 4; ++i) {
2633  iface[i - 1] = i + 4;
2634  tface[i - 1] = tt[i + (nv << 2) - 5];
2635  }
2636  Int_t cs = fColorTop;
2637  if ( nv <= 3 ) fEdgeIdx = 0 ; // no stack or stack with only one histo
2638  else {
2639  if ( nv > 2 && (v[nv-1] == v[nv-2])) {
2640  for (iv = nv-1; iv>2; iv--) {
2641  if (v[nv-1] == v[iv-1]) {
2642  fColorTop = fColorMain[iv-2];
2643  fEdgeIdx = iv-2;
2644  }
2645  }
2646  }
2647  }
2648  (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
2649  fColorTop = cs;
2650  }
2651  }
2652  // N E X T P H I
2653 L300:
2654  iphi += incr;
2655  if (iphi == 0) iphi = kphi;
2656  if (iphi > kphi) iphi = 1;
2657  if (iphi != iphi2) goto L100;
2658  if (incr == 0) {
2659  if (vSize > kVSizeMax) {
2660  delete [] v;
2661  delete [] tt;
2662  }
2663  return;
2664  }
2665  if (incr < 0) {
2666  incr = 0;
2667  goto L100;
2668  }
2669  incr = -1;
2670  iphi = iphi1;
2671  goto L300;
2672 }
2673 
2674 
2675 ////////////////////////////////////////////////////////////////////////////////
2676 /// Draw stack of lego-plots in cylindrical coordinates
2677 ///
2678 /// \param[in] iordr order of variables (0 - Z,PHI; 1 - PHI,Z)
2679 /// \param[in] na number of steps along 1st variable
2680 /// \param[in] nb number of steps along 2nd variable
2681 ///
2682 /// - `chopt` = 'BF' from BACK to FRONT
2683 /// - `chopt` = 'FB' from FRONT to BACK
2684 
2685 void TPainter3dAlgorithms::LegoCylindrical(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
2686 {
2687 
2688 
2689  Int_t iphi, jphi, kphi, incr, nphi, ivis[6], iopt, iphi1, iphi2, iface[4], i, j;
2690  Double_t tface[4], z;
2691  Double_t ab[8]; // was [2][4]
2692  Int_t ia, ib, idummy, iz1, iz2, nz, incrz, k1, k2, nv;
2693  Int_t iv, iz, jz, icodes[4];
2694  Double_t cosphi[4];
2695  Double_t sinphi[4];
2696  Double_t xyz[24]; // was [3][8]
2697  ia = ib = 0;
2698  TView *view = 0;
2699  Int_t firstStackNumberDrawn=-1 ; // necessary to compute fColorBottom when the 0 option is set and when the stack is seen from below (bottomview, theta<0.)
2700 
2701  if (gPad) view = gPad->GetView();
2702  if (!view) {
2703  Error("LegoCylindrical", "no TView in current pad");
2704  return;
2705  }
2706 
2707  if (iordr == 0) {
2708  jz = 1;
2709  jphi = 2;
2710  nz = na;
2711  nphi = nb;
2712  } else {
2713  jz = 2;
2714  jphi = 1;
2715  nz = nb;
2716  nphi = na;
2717  }
2718  if (nphi > 180) {
2719  Error("LegoCylindrical", "too many PHI sectors (%d)", nphi);
2720  return;
2721  }
2722  iopt = 2;
2723  if (*chopt == 'B' || *chopt == 'b') iopt = 1;
2724 
2725  // Allocate v and tt arrays
2726  Double_t *v, *tt;
2727  Int_t vSize = fNStack+2;
2728  if (vSize > kVSizeMax) {
2729  v = new Double_t[vSize];
2730  tt = new Double_t[4*vSize];
2731  } else {
2732  vSize = kVSizeMax;
2733  v = &gV[0];
2734  tt = &gTT[0];
2735  }
2736 
2737  // P R E P A R E P H I A R R A Y
2738  // F I N D C R I T I C A L S E C T O R S
2739  nv = 0;
2740  kphi = nphi;
2741  if (iordr == 0) ia = nz;
2742  if (iordr != 0) ib = nz;
2743  for (i = 1; i <= nphi; ++i) {
2744  if (iordr == 0) ib = i;
2745  if (iordr != 0) ia = i;
2746  (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
2747  if (i == 1) fAphi[0] = ab[jphi - 1];
2748  fAphi[i - 1] = (fAphi[i - 1] + ab[jphi - 1]) / (float)2.;
2749  fAphi[i] = ab[jphi + 3];
2750  }
2751  view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
2752 
2753  // E N C O D E V I S I B I L I T Y O F S I D E S
2754  // A N D O R D E R A L O N G R
2755  for (i = 1; i <= nphi; ++i) {
2756  if (iordr == 0) ib = i;
2757  if (iordr != 0) ia = i;
2758  (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
2759  SideVisibilityEncode(iopt, ab[jphi - 1]*kRad, ab[jphi + 3]*kRad, fAphi[i - 1]);
2760  }
2761 
2762  // F I N D O R D E R A L O N G Z
2763  incrz = 1;
2764  iz1 = 1;
2765  view->FindNormal(0, 0, 1, z);
2766  if ((z <= 0 && iopt == 1) || (z > 0 && iopt == 2)) {
2767  incrz = -1;
2768  iz1 = nz;
2769  }
2770  iz2 = nz - iz1 + 1;
2771 
2772  // D R A W S T A C K O F L E G O - P L O T S
2773  incr = 1;
2774  iphi = iphi1;
2775 L100:
2776  if (iphi > nphi) goto L400;
2777  // D E C O D E V I S I B I L I T Y O F S I D E S
2778  idummy = 0;
2779  SideVisibilityDecode(fAphi[iphi - 1], ivis[4], ivis[1], ivis[5], ivis[3], ivis[0], ivis[2], idummy);
2780  for (iz = iz1; incrz < 0 ? iz >= iz2 : iz <= iz2; iz += incrz) {
2781  if (iordr == 0) {ia = iz; ib = iphi;}
2782  else {ia = iphi; ib = iz;}
2783  (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
2784  if (nv < 2 || nv > vSize) continue;
2785  icodes[0] = ia;
2786  icodes[1] = ib;
2787  for (i = 1; i <= 4; ++i) {
2788  j = i;
2789  if (iordr != 0 && i == 2) j = 4;
2790  if (iordr != 0 && i == 4) j = 2;
2791  cosphi[j - 1] = TMath::Cos(ab[jphi + 2*i - 3]*kRad);
2792  sinphi[j - 1] = TMath::Sin(ab[jphi + 2*i - 3]*kRad);
2793  xyz[j*3 - 1] = ab[jz + 2*i - 3];
2794  xyz[(j + 4)*3 - 1] = ab[jz + 2*i - 3];
2795  }
2796  // D R A W S T A C K
2797  firstStackNumberDrawn = -1;
2798  for (iv = 1; iv < nv; ++iv) {
2799  for (i = 1; i <= 4; ++i) {
2800  xyz[i*3 - 3] = v[iv - 1]*cosphi[i - 1];
2801  xyz[i*3 - 2] = v[iv - 1]*sinphi[i - 1];
2802  xyz[(i + 4)*3 - 3] = v[iv]*cosphi[i - 1];
2803  xyz[(i + 4)*3 - 2] = v[iv]*sinphi[i - 1];
2804  }
2805  if (v[iv - 1] >= v[iv]) continue;
2806  icodes[2] = iv;
2807  for (i = 1; i <= 4; ++i) {
2808  if (ivis[i - 1] == 0) continue;
2809  k1 = i;
2810  k2 = i - 1;
2811  if (i == 1) k2 = 4;
2812  iface[0] = k1;
2813  iface[1] = k2;
2814  iface[2] = k2 + 4;
2815  iface[3] = k1 + 4;
2816  tface[0] = tt[k1 + (iv << 2) - 5];
2817  tface[1] = tt[k2 + (iv << 2) - 5];
2818  tface[2] = tt[k2 + ((iv + 1) << 2) - 5];
2819  tface[3] = tt[k1 + ((iv + 1) << 2) - 5];
2820  icodes[3] = i;
2821  fEdgeIdx = iv-1;
2822  (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
2823  }
2824  if ( firstStackNumberDrawn==-1 ) firstStackNumberDrawn = fEdgeIdx;
2825  }
2826  // D R A W B O T T O M F A C E
2827  if (ivis[4] != 0 && v[0] > 0) {
2828  icodes[2] = 1;
2829  icodes[3] = 5;
2830  for (i = 1; i <= 4; ++i) {
2831  xyz[i*3 - 3] = v[0]*cosphi[i - 1];
2832  xyz[i*3 - 2] = v[0]*sinphi[i - 1];
2833  iface[i - 1] = i;
2834  tface[i - 1] = tt[i - 1];
2835  }
2836  if (!Hoption.Zero) fEdgeIdx = 0;
2837  else {
2838  fEdgeIdx = firstStackNumberDrawn;
2840  }
2841  (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
2842  }
2843  // D R A W T O P F A C E
2844  if (ivis[5] != 0 && v[nv - 1] > 0) {
2845  icodes[2] = nv - 1;
2846  icodes[3] = 6;
2847  for (i = 1; i <= 4; ++i) {
2848  iface[i - 1] = 5 - i + 4;
2849  tface[i - 1] = tt[5 - i + (nv << 2) - 5];
2850  }
2851  Int_t cs = fColorTop;
2852  if ( nv <= 3 ) fEdgeIdx = 0 ; // no stack or stack with only one histo
2853  else {
2854  if ( nv > 2 && (v[nv-1] == v[nv-2])) {
2855  for (iv = nv-1; iv>2; iv--) {
2856  if (v[nv-1] == v[iv-1]) {
2857  fColorTop = fColorMain[iv-2];
2858  fEdgeIdx = iv-2;
2859  }
2860  }
2861  }
2862  }
2863  (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
2864  fColorTop = cs;
2865  }
2866  }
2867  // N E X T P H I
2868 L400:
2869  iphi += incr;
2870  if (iphi == 0) iphi = kphi;
2871  if (iphi > kphi) iphi = 1;
2872  if (iphi != iphi2) goto L100;
2873  if (incr == 0) {
2874  if (vSize > kVSizeMax) {
2875  delete [] v;
2876  delete [] tt;
2877  }
2878  return;
2879  }
2880  if (incr < 0) {
2881  incr = 0;
2882  goto L100;
2883  }
2884  incr = -1;
2885  iphi = iphi1;
2886  goto L400;
2887 }
2888 
2889 
2890 ////////////////////////////////////////////////////////////////////////////////
2891 /// Draw stack of lego-plots spheric coordinates
2892 ///
2893 /// \param[in] ipsdr pseudo-rapidity flag
2894 /// \param[in] iordr order of variables (0 - THETA,PHI; 1 - PHI,THETA)
2895 /// \param[in] na number of steps along 1st variable
2896 /// \param[in] nb number of steps along 2nd variable
2897 ///
2898 /// - `chopt` = 'BF' from BACK to FRONT
2899 /// - `chopt` = 'FB' from FRONT to BACK
2900 
2901 void TPainter3dAlgorithms::LegoSpherical(Int_t ipsdr, Int_t iordr, Int_t na, Int_t nb, const char *chopt)
2902 {
2903  Int_t iphi, jphi, kphi, incr, nphi, ivis[6], iopt, iphi1, iphi2, iface[4], i, j;
2904  Double_t tface[4], costh[4];
2905  Double_t sinth[4];
2906  Int_t k1, k2, ia, ib, incrth, ith, jth, kth, nth, mth, ith1, ith2, nv;
2907  Double_t ab[8]; // was [2][4]
2908  Double_t th;
2909  Int_t iv, icodes[4];
2910  Double_t zn, cosphi[4];
2911  Double_t sinphi[4], th1, th2, phi;
2912  Double_t xyz[24]; // was [3][8]
2913  Double_t phi1, phi2;
2914  ia = ib = 0;
2915  TView *view = 0;
2916  Int_t firstStackNumberDrawn=-1 ; // necessary to compute fColorBottom when the 0 option is set and when the stack is seen from below (bottomview, theta<0.)
2917 
2918  if (gPad) view = gPad->GetView();
2919  if (!view) {
2920  Error("LegoSpherical", "no TView in current pad");
2921  return;
2922  }
2923 
2924  if (iordr == 0) {
2925  jth = 1;
2926  jphi = 2;
2927  nth = na;
2928  nphi = nb;
2929  } else {
2930  jth = 2;
2931  jphi = 1;
2932  nth = nb;
2933  nphi = na;
2934  }
2935  if (nth > 180) {
2936  Error("LegoSpherical", "too many THETA sectors (%d)", nth);
2937  return;
2938  }
2939  if (nphi > 180) {
2940  Error("LegoSpherical", "too many PHI sectors (%d)", nphi);
2941  return;
2942  }
2943  iopt = 2;
2944  if (*chopt == 'B' || *chopt == 'b') iopt = 1;
2945 
2946  // Allocate v and tt arrays
2947  Double_t *v, *tt;
2948  Int_t vSize = fNStack+2;
2949  if (vSize > kVSizeMax) {
2950  v = new Double_t[vSize];
2951  tt = new Double_t[4*vSize];
2952  } else {
2953  vSize = kVSizeMax;
2954  v = &gV[0];
2955  tt = &gTT[0];
2956  }
2957 
2958  // P R E P A R E P H I A R R A Y
2959  // F I N D C R I T I C A L P H I S E C T O R S
2960  nv = 0;
2961  kphi = nphi;
2962  mth = nth / 2;
2963  if (mth == 0) mth = 1;
2964  if (iordr == 0) ia = mth;
2965  if (iordr != 0) ib = mth;
2966  for (i = 1; i <= nphi; ++i) {
2967  if (iordr == 0) ib = i;
2968  if (iordr != 0) ia = i;
2969  (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
2970  if (i == 1) fAphi[0] = ab[jphi - 1];
2971  fAphi[i - 1] = (fAphi[i - 1] + ab[jphi - 1]) / (float)2.;
2972  fAphi[i] = ab[jphi + 3];
2973  }
2974  view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
2975 
2976  // P R E P A R E T H E T A A R R A Y
2977  if (iordr == 0) ib = 1;
2978  if (iordr != 0) ia = 1;
2979  for (i = 1; i <= nth; ++i) {
2980  if (iordr == 0) ia = i;
2981  if (iordr != 0) ib = i;
2982  (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
2983  if (i == 1) fAphi[0] = ab[jth - 1];
2984  fAphi[i - 1] = (fAphi[i - 1] + ab[jth - 1]) / (float)2.;
2985  fAphi[i] = ab[jth + 3];
2986  }
2987 
2988  // D R A W S T A C K O F L E G O - P L O T S
2989  kth = nth;
2990 
2991  incr = 1;
2992  iphi = iphi1;
2993 L100:
2994  if (iphi > nphi) goto L500;
2995 
2996  // F I N D C R I T I C A L T H E T A S E C T O R S
2997  if (!iordr) {ia = mth; ib = iphi; }
2998  else {ia = iphi;ib = mth; }
2999  (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
3000  phi = (ab[jphi - 1] + ab[jphi + 3]) / (float)2.;
3001  view->FindThetaSectors(iopt, phi, kth, fAphi, ith1, ith2);
3002  incrth = 1;
3003  ith = ith1;
3004 L200:
3005  if (ith > nth) goto L400;
3006  if (iordr == 0) ia = ith;
3007  if (iordr != 0) ib = ith;
3008  (this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
3009  if (nv < 2 || nv > vSize) goto L400;
3010 
3011  // D E F I N E V I S I B I L I T Y O F S I D E S
3012  for (i = 1; i <= 6; ++i) ivis[i - 1] = 0;
3013 
3014  phi1 = kRad*ab[jphi - 1];
3015  phi2 = kRad*ab[jphi + 3];
3016  th1 = kRad*ab[jth - 1];
3017  th2 = kRad*ab[jth + 3];
3018  view->FindNormal(TMath::Sin(phi1), -TMath::Cos(phi1), 0, zn);
3019  if (zn > 0) ivis[1] = 1;
3020  view->FindNormal(-TMath::Sin(phi2), TMath::Cos(phi2), 0, zn);
3021  if (zn > 0) ivis[3] = 1;
3022  phi = (phi1 + phi2) / (float)2.;
3023  view->FindNormal(-TMath::Cos(phi)*TMath::Cos(th1), -TMath::Sin(phi)*TMath::Cos(th1), TMath::Sin(th1), zn);
3024  if (zn > 0) ivis[0] = 1;
3025  view->FindNormal(TMath::Cos(phi)*TMath::Cos(th2), TMath::Sin(phi)*TMath::Cos(th2), -TMath::Sin(th2), zn);
3026  if (zn > 0) ivis[2] = 1;
3027  th = (th1 + th2) / (float)2.;
3028  if (ipsdr == 1) th = kRad*90;
3029  view->FindNormal(TMath::Cos(phi)*TMath::Sin(th), TMath::Sin(phi)*TMath::Sin(th), TMath::Cos(th), zn);
3030  if (zn < 0) ivis[4] = 1;
3031  if (zn > 0) ivis[5] = 1;
3032 
3033  // D R A W S T A C K
3034  icodes[0] = ia;
3035  icodes[1] = ib;
3036  for (i = 1; i <= 4; ++i) {
3037  j = i;
3038  if (iordr != 0 && i == 2) j = 4;
3039  if (iordr != 0 && i == 4) j = 2;
3040  costh[j - 1] = TMath::Cos(kRad*ab[jth + 2*i - 3]);
3041  sinth[j - 1] = TMath::Sin(kRad*ab[jth + 2*i - 3]);
3042  cosphi[j - 1] = TMath::Cos(kRad*ab[jphi + 2*i - 3]);
3043  sinphi[j - 1] = TMath::Sin(kRad*ab[jphi + 2*i - 3]);
3044  }
3045  firstStackNumberDrawn = -1;
3046  for (iv = 1; iv < nv; ++iv) {
3047  if (ipsdr == 1) {
3048  for (i = 1; i <= 4; ++i) {
3049  xyz[i*3 - 3] = v[iv - 1]*cosphi[i - 1];
3050  xyz[i*3 - 2] = v[iv - 1]*sinphi[i - 1];
3051  xyz[i*3 - 1] = v[iv - 1]*costh[i - 1] / sinth[i - 1];
3052  xyz[(i + 4)*3 - 3] = v[iv]*cosphi[i - 1];
3053  xyz[(i + 4)*3 - 2] = v[iv]*sinphi[i - 1];
3054  xyz[(i + 4)*3 - 1] = v[iv]*costh[i - 1] / sinth[i - 1];
3055  }
3056  } else {
3057  for (i = 1; i <= 4; ++i) {
3058  xyz[i*3 - 3] = v[iv - 1]*sinth[i - 1]*cosphi[i - 1];
3059  xyz[i*3 - 2] = v[iv - 1]*sinth[i - 1]*sinphi[i - 1];
3060  xyz[i*3 - 1] = v[iv - 1]*costh[i - 1];
3061  xyz[(i + 4)*3 - 3] = v[iv]*sinth[i - 1]*cosphi[i - 1];
3062  xyz[(i + 4)*3 - 2] = v[iv]*sinth[i - 1]*sinphi[i - 1];
3063  xyz[(i + 4)*3 - 1] = v[iv]*costh[i - 1];
3064  }
3065  }
3066  if (v[iv - 1] >= v[iv]) continue;
3067  icodes[2] = iv;
3068  for (i = 1; i <= 4; ++i) {
3069  if (ivis[i - 1] == 0) continue;
3070  k1 = i - 1;
3071  if (i == 1) k1 = 4;
3072  k2 = i;
3073  iface[0] = k1;
3074  iface[1] = k2;
3075  iface[2] = k2 + 4;
3076  iface[3] = k1 + 4;
3077  tface[0] = tt[k1 + (iv << 2) - 5];
3078  tface[1] = tt[k2 + (iv << 2) - 5];
3079  tface[2] = tt[k2 + ((iv + 1) << 2) - 5];
3080  tface[3] = tt[k1 + ((iv + 1) << 2) - 5];
3081  icodes[3] = i;
3082  fEdgeIdx = iv-1;
3083  (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
3084  }
3085  if ( firstStackNumberDrawn==-1 ) firstStackNumberDrawn = fEdgeIdx;
3086  }
3087  // D R A W B O T T O M F A C E
3088  if (ivis[4] != 0 && v[0] > 0) {
3089  icodes[2] = 1;
3090  icodes[3] = 5;
3091  for (i = 1; i <= 4; ++i) {
3092  if (ipsdr == 1) {
3093  xyz[i*3 - 3] = v[0]*cosphi[i - 1];
3094  xyz[i*3 - 2] = v[0]*sinphi[i - 1];
3095  xyz[i*3 - 1] = v[0]*costh[i - 1] / sinth[i - 1];
3096  } else {
3097  xyz[i*3 - 3] = v[0]*sinth[i - 1]*cosphi[i - 1];
3098  xyz[i*3 - 2] = v[0]*sinth[i - 1]*sinphi[i - 1];
3099  xyz[i*3 - 1] = v[0]*costh[i - 1];
3100  }
3101  iface[i - 1] = 5 - i;
3102  tface[i - 1] = tt[5 - i - 1];
3103  }
3104  if (!Hoption.Zero) fEdgeIdx = 0;
3105  else {
3106  fEdgeIdx = firstStackNumberDrawn;
3108  }
3109  (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
3110  }
3111  // D R A W T O P F A C E
3112  if (ivis[5] != 0 && v[nv - 1] > 0) {
3113  icodes[2] = nv - 1;
3114  icodes[3] = 6;
3115  for (i = 1; i <= 4; ++i) {
3116  iface[i - 1] = i + 4;
3117  tface[i - 1] = tt[i + 4 + 2*nv - 5];
3118  }
3119  Int_t cs = fColorTop;
3120  if ( nv <= 3 ) fEdgeIdx = 0 ; // no stack or stack with only one histo
3121  else {
3122  if ( nv > 2 && (v[nv-1] == v[nv-2])) {
3123  for (iv = nv-1; iv>2; iv--) {
3124  if (v[nv-1] == v[iv-1]) {
3125  fColorTop = fColorMain[iv-2];
3126  fEdgeIdx = iv-2;
3127  }
3128  }
3129  }
3130  }
3131  (this->*fDrawFace)(icodes, xyz, 4, iface, tface);
3132  fColorTop = cs;
3133  }
3134  // N E X T T H E T A
3135 L400:
3136  ith += incrth;
3137  if (ith == 0) ith = kth;
3138  if (ith > kth) ith = 1;
3139  if (ith != ith2) goto L200;
3140  if (incrth == 0) goto L500;
3141  if (incrth < 0) {
3142  incrth = 0;
3143  goto L200;
3144  }
3145  incrth = -1;
3146  ith = ith1;
3147  goto L400;
3148  // N E X T P H I
3149 L500:
3150  iphi += incr;
3151  if (iphi == 0) iphi = kphi;
3152  if (iphi > kphi) iphi = 1;
3153  if (iphi != iphi2) goto L100;
3154  if (incr == 0) {
3155  if (vSize > kVSizeMax) {
3156  delete [] v;
3157  delete [] tt;
3158  }
3159  return;
3160  }
3161  if (incr < 0) {
3162  incr = 0;
3163  goto L100;
3164  }
3165  incr = -1;
3166  iphi = iphi1;
3167  goto L500;
3168 }
3169 
3170 
3171 ////////////////////////////////////////////////////////////////////////////////
3172 /// Set light source
3173 ///
3174 /// \param[in] nl source number: 1 off all light sources, 0 set diffused light
3175 /// \param[in] xl intensity of the light source
3176 /// \param[in] xscr `yscr` `zscr` direction of the light (in respect of the screen)
3177 ///
3178 /// \param[out] irep reply (0 - O.K, -1 error)
3179 
3180 
3182  Double_t yscr, Double_t zscr, Int_t &irep)
3183 {
3184  /* Local variables */
3185  Int_t i;
3186  Double_t s;
3187 
3188  irep = 0;
3189  if (nl < 0) goto L100;
3190  else if (nl == 0) goto L200;
3191  else goto L300;
3192 
3193  // S W I T C H O F F L I G H T S
3194 L100:
3195  fLoff = 1;
3196  fYdl = 0;
3197  for (i = 1; i <= 4; ++i) {
3198  fYls[i - 1] = 0;
3199  }
3200  return;
3201  // S E T D I F F U S E D L I G H T
3202 L200:
3203  if (yl < 0) {
3204  Error("LightSource", "negative light intensity");
3205  irep = -1;
3206  return;
3207  }
3208  fYdl = yl;
3209  goto L400;
3210  // S E T L I G H T S O U R C E
3211 L300:
3212  if (nl > 4 || yl < 0) {
3213  Error("LightSource", "illegal light source number (nl=%d, yl=%f)", nl, yl);
3214  irep = -1;
3215  return;
3216  }
3217  s = TMath::Sqrt(xscr*xscr + yscr*yscr + zscr*zscr);
3218  if (s == 0) {
3219  Error("LightSource", "light source is placed at origin");
3220  irep = -1;
3221  return;
3222  }
3223  fYls[nl - 1] = yl;
3224  fVls[nl*3 - 3] = xscr / s;
3225  fVls[nl*3 - 2] = yscr / s;
3226  fVls[nl*3 - 1] = zscr / s;
3227  // C H E C K L I G H T S
3228 L400:
3229  fLoff = 0;
3230  if (fYdl != 0) return;
3231  for (i = 1; i <= 4; ++i) {
3232  if (fYls[i - 1] != 0) return;
3233  }
3234  fLoff = 1;
3235 }
3236 
3237 
3238 ////////////////////////////////////////////////////////////////////////////////
3239 /// Find surface luminosity at given point
3240 ///
3241 /// \param[in] anorm surface normal at given point
3242 ///
3243 /// \param[out] flum luminosity
3244 
3246 {
3247  /* Local variables */
3248  Double_t cosn, cosr;
3249  Int_t i;
3250  Double_t s, vl[3], vn[3];
3251  TView *view = 0;
3252 
3253  if (gPad) view = gPad->GetView();
3254  if (!view) return;
3255 
3256  /* Parameter adjustments */
3257  --anorm;
3258 
3259  flum = 0;
3260  if (fLoff != 0) return;
3261 
3262  // T R A N S F E R N O R M A L T O SCREEN COORDINATES
3263  view->NormalWCtoNDC(&anorm[1], vn);
3264  s = TMath::Sqrt(vn[0]*vn[0] + vn[1]*vn[1] + vn[2]*vn[2]);
3265  if (vn[2] < 0) s = -(Double_t)s;
3266  vn[0] /= s;
3267  vn[1] /= s;
3268  vn[2] /= s;
3269 
3270  // F I N D L U M I N O S I T Y
3271  flum = fYdl*fQA;
3272  for (i = 1; i <= 4; ++i) {
3273  if (fYls[i - 1] <= 0) continue;
3274  vl[0] = fVls[i*3 - 3];
3275  vl[1] = fVls[i*3 - 2];
3276  vl[2] = fVls[i*3 - 1];
3277  cosn = vl[0]*vn[0] + vl[1]*vn[1] + vl[2]*vn[2];
3278  if (cosn < 0) continue;
3279  cosr = vn[1]*(vn[2]*vl[1] - vn[1]*vl[2]) - vn[0]*(vn[0]*vl[2]
3280  - vn[2]*vl[0]) + vn[2]*cosn;
3281  if (cosr <= 0) cosr = 0;
3282  flum += fYls[i - 1]*(fQD*cosn + fQS*TMath::Power(cosr, fNqs));
3283  }
3284 }
3285 
3286 
3287 ////////////////////////////////////////////////////////////////////////////////
3288 /// Modify SCREEN
3289 ///
3290 /// \param[in] r1 1-st point of the line
3291 /// \param[in] r2 2-nd point of the line
3292 
3294 {
3295  /* Local variables */
3296  Int_t i, i1, i2;
3297  Double_t x1, x2, y1, y2, dy, ww, yy1, yy2, *tn;
3298 
3299  /* Parameter adjustments */
3300  --r2;
3301  --r1;
3302 
3303  TView *view = 0;
3304  if (gPad) view = gPad->GetView();
3305 
3306  if (view) {
3307  tn = view->GetTN();
3308  if (tn) {
3309  x1 = tn[0]*r1[1] + tn[1]*r1[2] + tn[2]*r1[3] + tn[3];
3310  x2 = tn[0]*r2[1] + tn[1]*r2[2] + tn[2]*r2[3] + tn[3];
3311  y1 = tn[4]*r1[1] + tn[5]*r1[2] + tn[6]*r1[3] + tn[7];
3312  y2 = tn[4]*r2[1] + tn[5]*r2[2] + tn[6]*r2[3] + tn[7];
3313  } else {
3314  Error("ModifyScreen", "invalid TView in current pad");
3315  return;
3316  }
3317  } else {
3318  Error("ModifyScreen", "no TView in current pad");
3319  return;
3320  }
3321 
3322  if (x1 >= x2) {
3323  ww = x1;
3324  x1 = x2;
3325  x2 = ww;
3326  ww = y1;
3327  y1 = y2;
3328  y2 = ww;
3329  }
3330  i1 = Int_t((x1 - fX0) / fDX) + 15;
3331  i2 = Int_t((x2 - fX0) / fDX) + 15;
3332  if (i1 == i2) return;
3333 
3334  // M O D I F Y B O U N D A R I E S OF THE SCREEN
3335  dy = (y2 - y1) / (i2 - i1);
3336  for (i = i1; i <= i2 - 1; ++i) {
3337  yy1 = y1 + dy*(i - i1);
3338  yy2 = yy1 + dy;
3339  if (fD[2*i - 2] > yy1) fD[2*i - 2] = yy1;
3340  if (fD[2*i - 1] > yy2) fD[2*i - 1] = yy2;
3341  if (fU[2*i - 2] < yy1) fU[2*i - 2] = yy1;
3342  if (fU[2*i - 1] < yy2) fU[2*i - 1] = yy2;
3343  }
3344 }
3345 
3346 
3347 ////////////////////////////////////////////////////////////////////////////////
3348 /// Store pointer to current algorithm to draw faces
3349 
3350 void TPainter3dAlgorithms::SetDrawFace(DrawFaceFunc_t drface)
3351 {
3352  fDrawFace = drface;
3353 }
3354 
3355 
3356 ////////////////////////////////////////////////////////////////////////////////
3357 /// Store pointer to current lego function
3358 
3360 {
3361  fLegoFunction = fun;
3362 }
3363 
3364 
3365 ////////////////////////////////////////////////////////////////////////////////
3366 /// Store pointer to current surface function
3367 
3369 {
3370  fSurfaceFunction = fun;
3371 }
3372 
3373 
3374 ////////////////////////////////////////////////////////////////////////////////
3375 /// Static function
3376 /// Store pointer to current implicit function
3377 
3379 {
3380  fgCurrentF3 = f3;
3381 }
3382 
3383 
3384 ////////////////////////////////////////////////////////////////////////////////
3385 /// Static function
3386 /// Set the implicit function clipping box "off".
3387 
3389 {
3390  fgF3Clipping = 0;
3391 }
3392 
3393 
3394 ////////////////////////////////////////////////////////////////////////////////
3395 /// Static function
3396 /// Set the implicit function clipping box "on" and define the clipping box.
3397 /// xclip, yclip and zclip is a point within the function range. All the
3398 /// function value having x<=xclip and y<=yclip and z>=zclip are clipped.
3399 
3401  Double_t yclip, Double_t zclip)
3402 {
3403  fgF3Clipping = 1;
3404  fgF3XClip = xclip;
3405  fgF3YClip = yclip;
3406  fgF3ZClip = zclip;
3407 }
3408 
3409 
3410 ////////////////////////////////////////////////////////////////////////////////
3411 /// Store dark color for stack number n
3412 
3414 {
3415  if (n < 0 ) {fColorBottom = color; return;}
3416  if (n > fNStack ) {fColorTop = color; return;}
3417  fColorDark[n] = color;
3418 }
3419 
3420 
3421 ////////////////////////////////////////////////////////////////////////////////
3422 /// Store color for stack number n
3423 
3425 {
3426  if (n < 0 ) {fColorBottom = color; return;}
3427  if (n > fNStack ) {fColorTop = color; return;}
3428  fColorMain[n] = color;
3429 }
3430 
3431 
3432 ////////////////////////////////////////////////////////////////////////////////
3433 
3435 {
3436  // Store edge attributes
3437 
3438  fEdgeColor[n] = color;
3439  fEdgeStyle[n] = style;
3440  fEdgeWidth[n] = width;
3441 }
3442 
3443 
3444 ////////////////////////////////////////////////////////////////////////////////
3445 /// Decode side visibilities and order along R for sector
3446 ///
3447 /// \param[in] val encoded value
3448 ///
3449 /// \param[out] iv1-iv6 visibility of the sides
3450 /// \param[out] ir increment along R
3451 
3452 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)
3453 {
3454  Int_t ivis[6], i, k, num;
3455 
3456  k = Int_t(val);
3457  num = 128;
3458  for (i = 1; i <= 6; ++i) {
3459  ivis[i - 1] = 0;
3460  num /= 2;
3461  if (k < num) continue;
3462  k -= num;
3463  ivis[i - 1] = 1;
3464  }
3465  ir = 1;
3466  if (k == 1) ir = -1;
3467  iv1 = ivis[5];
3468  iv2 = ivis[4];
3469  iv3 = ivis[3];
3470  iv4 = ivis[2];
3471  iv5 = ivis[1];
3472  iv6 = ivis[0];
3473 }
3474 
3475 
3476 ////////////////////////////////////////////////////////////////////////////////
3477 /// Encode side visibilities and order along R for sector
3478 ///
3479 /// \param[in] iopt options: 1: from BACK to FRONT 'BF', 2: from FRONT to BACK 'FB'
3480 /// \param[in] phi1 1st phi of sector
3481 /// \param[in] phi2 2nd phi of sector
3482 ///
3483 /// \param[out] val encoded value
3484 
3486 {
3487  /* Local variables */
3488  Double_t zn, phi;
3489  Int_t k = 0;
3490  TView *view = 0;
3491 
3492  if (gPad) view = gPad->GetView();
3493  if (!view) {
3494  Error("SideVisibilityEncode", "no TView in current pad");
3495  return;
3496  }
3497 
3498  view->FindNormal(0, 0, 1, zn);
3499  if (zn > 0) k += 64;
3500  if (zn < 0) k += 32;
3501  view->FindNormal(-TMath::Sin(phi2), TMath::Cos(phi2), 0, zn);
3502  if (zn > 0) k += 16;
3503  view->FindNormal(TMath::Sin(phi1), -TMath::Cos(phi1), 0, zn);
3504  if (zn > 0) k += 4;
3505  phi = (phi1 + phi2) / (float)2.;
3506  view->FindNormal(TMath::Cos(phi), TMath::Sin(phi), 0, zn);
3507  if (zn > 0) k += 8;
3508  if (zn < 0) k += 2;
3509  if ((zn <= 0 && iopt == 1) || (zn > 0 && iopt == 2)) ++k;
3510  val = Double_t(k);
3511 }
3512 
3513 
3514 ////////////////////////////////////////////////////////////////////////////////
3515 /// Set Spectrum
3516 ///
3517 /// \param[in] nl number of levels
3518 /// \param[in] fmin MIN function value
3519 /// \param[in] fmax MAX function value
3520 /// \param[in] ic initial color index (for 1st level)
3521 /// \param[in] idc color index increment
3522 ///
3523 /// \param[out] irep reply (0 O.K., -1 error)
3524 
3526 {
3527  static const char *where = "Spectrum";
3528 
3529  /* Local variables */
3530  Double_t delf;
3531  Int_t i;
3532 
3533  irep = 0;
3534  if (nl == 0) {fNlevel = 0; return; }
3535 
3536  // C H E C K P A R A M E T E R S
3537  if (fmax <= fmin) {
3538  Error(where, "fmax (%f) less than fmin (%f)", fmax, fmin);
3539  irep = -1;
3540  return;
3541  }
3542  if (nl < 0 || nl > 256) {
3543  Error(where, "illegal number of levels (%d)", nl);
3544  irep = -1;
3545  return;
3546  }
3547  if (ic < 0) {
3548  Error(where, "initial color index is negative");
3549  irep = -1;
3550  return;
3551  }
3552  if (idc < 0) {
3553  Error(where, "color index increment must be positive");
3554  irep = -1;
3555  }
3556 
3557  // S E T S P E C T R
3558  const Int_t kMAXCOL = 50;
3559  delf = (fmax - fmin) / nl;
3560  fNlevel = -(nl + 1);
3561  for (i = 1; i <= nl+1; ++i) {
3562  fFunLevel[i - 1] = fmin + (i - 1)*delf;
3563  fColorLevel[i] = ic + (i - 1)*idc;
3564  if (ic <= kMAXCOL && fColorLevel[i] > kMAXCOL) fColorLevel[i] -= kMAXCOL;
3565  }
3566  fColorLevel[0] = fColorLevel[1];
3567  fColorLevel[nl + 1] = fColorLevel[nl];
3568 }
3569 
3570 
3571 ////////////////////////////////////////////////////////////////////////////////
3572 /// Draw surface in cartesian coordinate system
3573 ///
3574 /// \param[in] ang angle between X ang Y
3575 /// \param[in] nx number of steps along X
3576 /// \param[in] ny number of steps along Y
3577 ///
3578 /// - `chopt` = 'BF' from BACK to FRONT
3579 /// - `chopt` = 'FB' from FRONT to BACK
3580 
3582 {
3583  /* Initialized data */
3584 
3585  Int_t iface[4] = { 1,2,3,4 };
3586 
3587  /* Local variables */
3588  Double_t cosa, sina, f[12] /* was [3][4] */;
3589  Int_t i, incrx, incry, i1, ix, iy;
3590  Double_t tt[4];
3591  Int_t icodes[3], ix1, iy1, ix2, iy2; // was icode[2]. One element more to differentiate front & back boxes from data
3592  Double_t xyz[12] /* was [3][4] */;
3593  Double_t *tn;
3594 
3595  sina = TMath::Sin(ang*kRad);
3596  cosa = TMath::Cos(ang*kRad);
3597 
3598  // F I N D T H E M O S T L E F T P O I N T
3599  TView *view = 0;
3600 
3601  if (gPad) view = gPad->GetView();
3602  if (!view) {
3603  Error("SurfaceCartesian", "no TView in current pad");
3604  return;
3605  }
3606  tn = view->GetTN();
3607 
3608  i1 = 1;
3609  if (tn) {
3610  if (tn[0] < 0) i1 = 2;
3611  if (tn[0]*cosa + tn[1]*sina < 0) i1 = 5 - i1;
3612  }
3613 
3614  // D E F I N E O R D E R O F D R A W I N G
3615  if (*chopt == 'B' || *chopt == 'b') {incrx = -1; incry = -1;}
3616  else {incrx = 1; incry = 1;}
3617  if (i1 == 1 || i1 == 2) incrx = -incrx;
3618  if (i1 == 2 || i1 == 3) incry = -incry;
3619  ix1 = 1;
3620  iy1 = 1;
3621  if (incrx < 0) ix1 = nx;
3622  if (incry < 0) iy1 = ny;
3623  ix2 = nx - ix1 + 1;
3624  iy2 = ny - iy1 + 1;
3625 
3626  // D R A W S U R F A C E
3627  icodes[2] = -1; // -1 for data, 0 for front a back boxes
3628  fEdgeIdx = 0; // constant since stacks are not (yet?) handled for surfaces
3629  THistPainter *painter = (THistPainter*)gCurrentHist->GetPainter();
3630  for (iy = iy1; incry < 0 ? iy >= iy2 : iy <= iy2; iy += incry) {
3631  for (ix = ix1; incrx < 0 ? ix >= ix2 : ix <= ix2; ix += incrx) {
3632  if (!painter->IsInside(ix,iy)) continue;
3633  (this->*fSurfaceFunction)(ix, iy, f, tt);
3634  for (i = 1; i <= 4; ++i) {
3635  xyz[i*3 - 3] = f[i*3 - 3] + f[i*3 - 2]*cosa;
3636  xyz[i*3 - 2] = f[i*3 - 2]*sina;
3637  xyz[i*3 - 1] = f[i*3 - 1];
3638  // added EJB -->
3639  Double_t al, ab;
3640  if (Hoption.Proj == 1 ) {
3641  THistPainter::ProjectAitoff2xy(xyz[i*3 - 3], xyz[i*3 - 2], al, ab);
3642  xyz[i*3 - 3] = al;
3643  xyz[i*3 - 2] = ab;
3644  } else if (Hoption.Proj == 2 ) {
3645  THistPainter::ProjectMercator2xy(xyz[i*3 - 3], xyz[i*3 - 2], al, ab);
3646  xyz[i*3 - 3] = al;
3647  xyz[i*3 - 2] = ab;
3648  } else if (Hoption.Proj == 3) {
3649  THistPainter::ProjectSinusoidal2xy(xyz[i*3 - 3], xyz[i*3 - 2], al, ab);
3650  xyz[i*3 - 3] = al;
3651  xyz[i*3 - 2] = ab;
3652  } else if (Hoption.Proj == 4) {
3653  THistPainter::ProjectParabolic2xy(xyz[i*3 - 3], xyz[i*3 - 2], al, ab);
3654  xyz[i*3 - 3] = al;
3655  xyz[i*3 - 2] = ab;
3656  }
3657  }
3658  icodes[0] = ix;
3659  icodes[1] = iy;
3660  (this->*fDrawFace)(icodes, xyz, 4, iface, tt);
3661  }
3662  }
3663 }
3664 
3665 
3666 ////////////////////////////////////////////////////////////////////////////////
3667 /// Service function for Surfaces
3668 
3670 {
3671  static Int_t ixadd[4] = { 0,1,1,0 };
3672  static Int_t iyadd[4] = { 0,0,1,1 };
3673 
3674  Double_t rinrad = gStyle->GetLegoInnerR();
3675  Double_t dangle = 10; //Delta angle for Rapidity option
3676  Double_t yval1l, yval2l;
3677  Double_t xlab1l, xlab2l, ylab1l, ylab2l;
3678  Int_t i, ixa, iya, icx, ixt, iyt;
3679 
3680  /* Parameter adjustments */
3681  --t;
3682  f -= 4;
3683 
3684  ixt = ia + Hparam.xfirst - 1;
3685  iyt = ib + Hparam.yfirst - 1;
3686 
3687  // xval1l = Hparam.xmin;
3688  // xval2l = Hparam.xmax;
3689  yval1l = Hparam.ymin;
3690  yval2l = Hparam.ymax;
3691 
3692  xlab1l = gCurrentHist->GetXaxis()->GetXmin();
3693  xlab2l = gCurrentHist->GetXaxis()->GetXmax();
3694  if (Hoption.Logx) {
3695  if (xlab2l>0) {
3696  if (xlab1l>0) xlab1l = TMath::Log10(xlab1l);
3697  else xlab1l = TMath::Log10(0.001*xlab2l);
3698  xlab2l = TMath::Log10(xlab2l);
3699  }
3700  }
3701  ylab1l = gCurrentHist->GetYaxis()->GetXmin();
3702  ylab2l = gCurrentHist->GetYaxis()->GetXmax();
3703  if (Hoption.Logy) {
3704  if (ylab2l>0) {
3705  if (ylab1l>0) ylab1l = TMath::Log10(ylab1l);
3706  else ylab1l = TMath::Log10(0.001*ylab2l);
3707  ylab2l = TMath::Log10(ylab2l);
3708  }
3709  }
3710 
3711  for (i = 1; i <= 4; ++i) {
3712  ixa = ixadd[i - 1];
3713  iya = iyadd[i - 1];
3714  Double_t xwid = gCurrentHist->GetXaxis()->GetBinWidth(ixt+ixa);
3715  Double_t ywid = gCurrentHist->GetYaxis()->GetBinWidth(iyt+iya);
3716 
3717  // Compute the cell position in cartesian coordinates
3718  // and compute the LOG if necessary
3719  f[i*3 + 1] = gCurrentHist->GetXaxis()->GetBinLowEdge(ixt+ixa) + 0.5*xwid;
3720  f[i*3 + 2] = gCurrentHist->GetYaxis()->GetBinLowEdge(iyt+iya) + 0.5*ywid;
3721  if (Hoption.Logx) {
3722  if (f[i*3 + 1] > 0) f[i*3 + 1] = TMath::Log10(f[i*3 + 1]);
3723  else f[i*3 + 1] = Hparam.xmin;
3724  }
3725  if (Hoption.Logy) {
3726  if (f[i*3 + 2] > 0) f[i*3 + 2] = TMath::Log10(f[i*3 + 2]);
3727  else f[i*3 + 2] = Hparam.ymin;
3728  }
3729 
3730  // Transform the cell position in the required coordinate system
3731  if (Hoption.System == kPOLAR) {
3732  f[i*3 + 1] = 360*(f[i*3 + 1] - xlab1l) / (xlab2l - xlab1l);
3733  f[i*3 + 2] = (f[i*3 + 2] - yval1l) / (yval2l - yval1l);
3734  } else if (Hoption.System == kCYLINDRICAL) {
3735  f[i*3 + 1] = 360*(f[i*3 + 1] - xlab1l) / (xlab2l - xlab1l);
3736  } else if (Hoption.System == kSPHERICAL) {
3737  f[i*3 + 1] = 360*(f[i*3 + 1] - xlab1l) / (xlab2l - xlab1l);
3738  f[i*3 + 2] = 360*(f[i*3 + 2] - ylab1l) / (ylab2l - ylab1l);
3739  } else if (Hoption.System == kRAPIDITY) {
3740  f[i*3 + 1] = 360*(f[i*3 + 1] - xlab1l) / (xlab2l - xlab1l);
3741  f[i*3 + 2] = (180 - dangle*2)*(f[i*3 + 2] - ylab1l) / (ylab2l - ylab1l) + dangle;
3742  }
3743 
3744  // Get the content of the table. If the X index (ICX) is
3745  // greater than the X size of the table (NCX), that's mean
3746  // IGTABL tried to close the surface and in this case the
3747  // first channel should be used. */
3748  icx = ixt + ixa;
3749  if (icx > Hparam.xlast) icx = 1;
3750  f[i*3+3] = Hparam.factor*gCurrentHist->GetBinContent(icx, iyt + iya);
3751  if (Hoption.Logz) {
3752  if (f[i*3+3] > 0) f[i*3+3] = TMath::Log10(f[i*3+3]);
3753  else f[i*3+3] = Hparam.zmin;
3754  if (f[i*3+3] < Hparam.zmin) f[i*3+3] = Hparam.zmin;
3755  if (f[i*3+3] > Hparam.zmax) f[i*3+3] = Hparam.zmax;
3756  } else {
3757  f[i*3+3] = TMath::Max(Hparam.zmin, f[i*3+3]);
3758  f[i*3+3] = TMath::Min(Hparam.zmax, f[i*3+3]);
3759  }
3760 
3761  // The colors on the surface can represent the content or the errors.
3762  // if (fSumw2.fN) t[i] = gCurrentHist->GetBinError(icx, iyt + iya);
3763  // else t[i] = f[i * 3 + 3];
3764  t[i] = f[i * 3 + 3];
3765  }
3766 
3767  // Define the position of the colored contours for SURF3
3768  if (Hoption.Surf == 23) {
3769  for (i = 1; i <= 4; ++i) f[i * 3 + 3] = fRmax[2];
3770  }
3771 
3772  if (Hoption.System == kCYLINDRICAL || Hoption.System == kSPHERICAL || Hoption.System == kRAPIDITY) {
3773  for (i = 1; i <= 4; ++i) {
3774  f[i*3 + 3] = (1 - rinrad)*((f[i*3 + 3] - Hparam.zmin) /
3775  (Hparam.zmax - Hparam.zmin)) + rinrad;
3776  }
3777  }
3778 }
3779 
3780 
3781 ////////////////////////////////////////////////////////////////////////////////
3782 /// Draw surface in polar coordinates
3783 ///
3784 /// \param[in] iordr order of variables (0 - R,PHI, 1 - PHI,R)
3785 /// \param[in] na number of steps along 1st variable
3786 /// \param[in] nb number of steps along 2nd variable
3787 ///
3788 /// - `chopt` = 'BF' from BACK to FRONT
3789 /// - `chopt` = 'FB' from FRONT to BACK
3790 
3791 void TPainter3dAlgorithms::SurfacePolar(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
3792 {
3793  /* Initialized data */
3794  static Int_t iface[4] = { 1,2,3,4 };
3795  TView *view = 0;
3796 
3797  if (gPad) view = gPad->GetView();
3798  if (!view) {
3799  Error("SurfacePolar", "no TView in current pad");
3800  return;
3801  }
3802 
3803  Int_t iphi, jphi, kphi, incr, nphi, iopt, iphi1, iphi2;
3804  Double_t f[12] /* was [3][4] */;
3805  Int_t i, j, incrr, ir1, ir2;
3806  Double_t z;
3807  Int_t ia, ib, ir, jr, nr, icodes[3]; // was icode[2]. One element more to differentiate front & back boxes from data
3808  Double_t tt[4];
3809  Double_t phi, ttt[4], xyz[12] /* was [3][4] */;
3810  ia = ib = 0;
3811 
3812  if (iordr == 0) {
3813  jr = 1;
3814  jphi = 2;
3815  nr = na;
3816  nphi = nb;
3817  } else {
3818  jr = 2;
3819  jphi = 1;
3820  nr = nb;
3821  nphi = na;
3822  }
3823  if (nphi > 180) {
3824  Error("SurfacePolar", "too many PHI sectors (%d)", nphi);
3825  return;
3826  }
3827  iopt = 2;
3828  if (*chopt == 'B' || *chopt == 'b') iopt = 1;
3829 
3830  // P R E P A R E P H I A R R A Y
3831  // F I N D C R I T I C A L S E C T O R S
3832  kphi = nphi;
3833  if (iordr == 0) ia = nr;
3834  if (iordr != 0) ib = nr;
3835  for (i = 1; i <= nphi; ++i) {
3836  if (iordr == 0) ib = i;
3837  if (iordr != 0) ia = i;
3838  (this->*fSurfaceFunction)(ia, ib, f, tt);
3839  if (i == 1) fAphi[0] = f[jphi - 1];
3840  fAphi[i - 1] = (fAphi[i - 1] + f[jphi - 1]) / (float)2.;
3841  fAphi[i] = f[jphi + 5];
3842  }
3843  view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
3844 
3845  // D R A W S U R F A C E
3846  icodes[2] = -1; // -1 for data, 0 for front a back boxes
3847  fEdgeIdx = 0; // constant since stacks are not (yet?) handled for surfaces
3848  incr = 1;
3849  iphi = iphi1;
3850 L100:
3851  if (iphi > nphi) goto L300;
3852 
3853  // F I N D O R D E R A L O N G R
3854  if (iordr == 0) {ia = nr; ib = iphi;}
3855  else {ia = iphi;ib = nr;}
3856 
3857  (this->*fSurfaceFunction)(ia, ib, f, tt);
3858  phi = kRad*((f[jphi - 1] + f[jphi + 5]) / 2);
3859  view->FindNormal(TMath::Cos(phi), TMath::Sin(phi), 0, z);
3860  incrr = 1;
3861  ir1 = 1;
3862  if ((z <= 0 && iopt == 1) || (z > 0 && iopt == 2)) {
3863  incrr = -1;
3864  ir1 = nr;
3865  }
3866  ir2 = nr - ir1 + 1;
3867  // D R A W S U R F A C E F O R S E C T O R
3868  for (ir = ir1; incrr < 0 ? ir >= ir2 : ir <= ir2; ir += incrr) {
3869  if (iordr == 0) ia = ir;
3870  if (iordr != 0) ib = ir;
3871 
3872  (this->*fSurfaceFunction)(ia, ib, f, tt);
3873  for (i = 1; i <= 4; ++i) {
3874  j = i;
3875  if (iordr != 0 && i == 2) j = 4;
3876  if (iordr != 0 && i == 4) j = 2;
3877  xyz[j*3 - 3] = f[jr + i*3 - 4]*TMath::Cos(f[jphi + i*3 - 4]*kRad);
3878  xyz[j*3 - 2] = f[jr + i*3 - 4]*TMath::Sin(f[jphi + i*3 - 4]*kRad);
3879  xyz[j*3 - 1] = f[i*3 - 1];
3880  ttt[j - 1] = tt[i - 1];
3881  }
3882  icodes[0] = ia;
3883  icodes[1] = ib;
3884  (this->*fDrawFace)(icodes, xyz, 4, iface, ttt);
3885  }
3886  // N E X T P H I
3887 L300:
3888  iphi += incr;
3889  if (iphi == 0) iphi = kphi;
3890  if (iphi > kphi) iphi = 1;
3891  if (iphi != iphi2) goto L100;
3892  if (incr == 0) return;
3893  if (incr < 0) {
3894  incr = 0;
3895  goto L100;
3896  }
3897  incr = -1;
3898  iphi = iphi1;
3899  goto L300;
3900 }
3901 
3902 
3903 ////////////////////////////////////////////////////////////////////////////////
3904 /// Draw surface in cylindrical coordinates
3905 ///
3906 /// \param[in] iordr order of variables (0 - Z,PHI; 1 - PHI,Z)
3907 /// \param[in] na number of steps along 1st variable
3908 /// \param[in] nb number of steps along 2nd variable
3909 ///
3910 /// - `chopt` = 'BF' from BACK to FRONT
3911 /// - `chopt` = 'FB' from FRONT to BACK
3912 
3913 void TPainter3dAlgorithms::SurfaceCylindrical(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
3914 {
3915 
3916 
3917  /* Initialized data */
3918  static Int_t iface[4] = { 1,2,3,4 };
3919 
3920  Int_t iphi, jphi, kphi, incr, nphi, iopt, iphi1, iphi2;
3921  Int_t i, j, incrz, nz, iz1, iz2;
3922  Int_t ia, ib, iz, jz, icodes[3]; // was icode[2]. One element more to differentiate front & back boxes from data
3923  Double_t f[12] /* was [3][4] */;
3924  Double_t z;
3925  Double_t tt[4];
3926  Double_t ttt[4], xyz[12] /* was [3][4] */;
3927  ia = ib = 0;
3928  TView *view = 0;
3929 
3930  if (gPad) view = gPad->GetView();
3931  if (!view) {
3932  Error("SurfaceCylindrical", "no TView in current pad");
3933  return;
3934  }
3935 
3936  if (iordr == 0) {
3937  jz = 1;
3938  jphi = 2;
3939  nz = na;
3940  nphi = nb;
3941  } else {
3942  jz = 2;
3943  jphi = 1;
3944  nz = nb;
3945  nphi = na;
3946  }
3947  if (nphi > 180) {
3948  Error("SurfaceCylindrical", "too many PHI sectors (%d)", nphi);
3949  return;
3950  }
3951  iopt = 2;
3952  if (*chopt == 'B' || *chopt == 'b') iopt = 1;
3953 
3954  // P R E P A R E P H I A R R A Y
3955  // F I N D C R I T I C A L S E C T O R S
3956  kphi = nphi;
3957  if (iordr == 0) ia = nz;
3958  if (iordr != 0) ib = nz;
3959  for (i = 1; i <= nphi; ++i) {
3960  if (iordr == 0) ib = i;
3961  if (iordr != 0) ia = i;
3962  (this->*fSurfaceFunction)(ia, ib, f, tt);
3963  if (i == 1) fAphi[0] = f[jphi - 1];
3964  fAphi[i - 1] = (fAphi[i - 1] + f[jphi - 1]) / (float)2.;
3965  fAphi[i] = f[jphi + 5];
3966  }
3967  view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
3968 
3969  // F I N D O R D E R A L O N G Z
3970  incrz = 1;
3971  iz1 = 1;
3972  view->FindNormal(0, 0, 1, z);
3973  if ((z <= 0 && iopt == 1) || (z > 0 && iopt == 2)) {
3974  incrz = -1;
3975  iz1 = nz;
3976  }
3977  iz2 = nz - iz1 + 1;
3978 
3979  // D R A W S U R F A C E
3980  icodes[2] = -1; // -1 for data, 0 for front a back boxes
3981  fEdgeIdx = 0; // constant since stacks are not (yet?) handled for surfaces
3982  incr = 1;
3983  iphi = iphi1;
3984 L100:
3985  if (iphi > nphi) goto L400;
3986  for (iz = iz1; incrz < 0 ? iz >= iz2 : iz <= iz2; iz += incrz) {
3987  if (iordr == 0) {ia = iz; ib = iphi;}
3988  else {ia = iphi; ib = iz;}
3989  (this->*fSurfaceFunction)(ia, ib, f, tt);
3990  for (i = 1; i <= 4; ++i) {
3991  j = i;
3992  if (iordr == 0 && i == 2) j = 4;
3993  if (iordr == 0 && i == 4) j = 2;
3994  xyz[j*3 - 3] = f[i*3 - 1]*TMath::Cos(f[jphi + i*3 - 4]*kRad);
3995  xyz[j*3 - 2] = f[i*3 - 1]*TMath::Sin(f[jphi + i*3 - 4]*kRad);
3996  xyz[j*3 - 1] = f[jz + i*3 - 4];
3997  ttt[j - 1] = tt[i - 1];
3998  }
3999  icodes[0] = ia;
4000  icodes[1] = ib;
4001  (this->*fDrawFace)(icodes, xyz, 4, iface, ttt);
4002  }
4003  // N E X T P H I
4004 L400:
4005  iphi += incr;
4006  if (iphi == 0) iphi = kphi;
4007  if (iphi > kphi) iphi = 1;
4008  if (iphi != iphi2) goto L100;
4009  if (incr == 0) return;
4010  if (incr < 0) {
4011  incr = 0;
4012  goto L100;
4013  }
4014  incr = -1;
4015  iphi = iphi1;
4016  goto L400;
4017 }
4018 
4019 
4020 ////////////////////////////////////////////////////////////////////////////////
4021 /// Draw surface in spheric coordinates
4022 ///
4023 /// \param[in] ipsdr pseudo-rapidity flag
4024 /// \param[in] iordr order of variables (0 - THETA,PHI; 1 - PHI,THETA)
4025 /// \param[in] na number of steps along 1st variable
4026 /// \param[in] nb number of steps along 2nd variable
4027 ///
4028 /// - `chopt` = 'BF' from BACK to FRONT
4029 /// - `chopt` = 'FB' from FRONT to BACK
4030 
4031 void TPainter3dAlgorithms::SurfaceSpherical(Int_t ipsdr, Int_t iordr, Int_t na, Int_t nb, const char *chopt)
4032 {
4033  /* Initialized data */
4034  static Int_t iface[4] = { 1,2,3,4 };
4035 
4036  Int_t iphi, jphi, kphi, incr, nphi, iopt, iphi1, iphi2;
4037  Int_t i, j, incrth, ith, jth, kth, nth, mth, ith1, ith2;
4038  Int_t ia, ib, icodes[3]; // was icode[2]. One element more to differentiate front & back boxes from data
4039  Double_t f[12] /* was [3][4] */;
4040  Double_t tt[4];
4041  Double_t phi;
4042  Double_t ttt[4], xyz[12] /* was [3][4] */;
4043  ia = ib = 0;
4044  TView *view = 0;
4045 
4046  if (gPad) view = gPad->GetView();
4047  if (!view) {
4048  Error("SurfaceSpherical", "no TView in current pad");
4049  return;
4050  }
4051 
4052  if (iordr == 0) {
4053  jth = 1;
4054  jphi = 2;
4055  nth = na;
4056  nphi = nb;
4057  } else {
4058  jth = 2;
4059  jphi = 1;
4060  nth = nb;
4061  nphi = na;
4062  }
4063  if (nth > 180) {
4064  Error("SurfaceSpherical", "too many THETA sectors (%d)", nth);
4065  return;
4066  }
4067  if (nphi > 180) {
4068  Error("SurfaceSpherical", "too many PHI sectors (%d)", nphi);
4069  return;
4070  }
4071  iopt = 2;
4072  if (*chopt == 'B' || *chopt == 'b') iopt = 1;
4073 
4074  // P R E P A R E P H I A R R A Y
4075  // F I N D C R I T I C A L P H I S E C T O R S
4076  kphi = nphi;
4077  mth = nth / 2;
4078  if (mth == 0) mth = 1;
4079  if (iordr == 0) ia = mth;
4080  if (iordr != 0) ib = mth;
4081  for (i = 1; i <= nphi; ++i) {
4082  if (iordr == 0) ib = i;
4083  if (iordr != 0) ia = i;
4084  (this->*fSurfaceFunction)(ia, ib, f, tt);
4085  if (i == 1) fAphi[0] = f[jphi - 1];
4086  fAphi[i - 1] = (fAphi[i - 1] + f[jphi - 1]) / (float)2.;
4087  fAphi[i] = f[jphi + 5];
4088  }
4089  view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
4090 
4091  // P R E P A R E T H E T A A R R A Y
4092  if (iordr == 0) ib = 1;
4093  if (iordr != 0) ia = 1;
4094  for (i = 1; i <= nth; ++i) {
4095  if (iordr == 0) ia = i;
4096  if (iordr != 0) ib = i;
4097 
4098  (this->*fSurfaceFunction)(ia, ib, f, tt);
4099  if (i == 1) fAphi[0] = f[jth - 1];
4100  fAphi[i - 1] = (fAphi[i - 1] + f[jth - 1]) / (float)2.;
4101  fAphi[i] = f[jth + 5];
4102  }
4103 
4104  // D R A W S U R F A C E
4105  icodes[2] = -1; // -1 for data, 0 for front a back boxes
4106  fEdgeIdx = 0; // constant since stacks are not (yet?) handled for surfaces
4107  kth = nth;
4108  incr = 1;
4109  iphi = iphi1;
4110 L100:
4111  if (iphi > nphi) goto L500;
4112 
4113  // F I N D C R I T I C A L T H E T A S E C T O R S
4114  if (iordr == 0) {ia = mth; ib = iphi;}
4115  else {ia = iphi;ib = mth;}
4116 
4117  (this->*fSurfaceFunction)(ia, ib, f, tt);
4118  phi = (f[jphi - 1] + f[jphi + 5]) / (float)2.;
4119  view->FindThetaSectors(iopt, phi, kth, fAphi, ith1, ith2);
4120  incrth = 1;
4121  ith = ith1;
4122 L200:
4123  if (ith > nth) goto L400;
4124  if (iordr == 0) ia = ith;
4125  if (iordr != 0) ib = ith;
4126 
4127  (this->*fSurfaceFunction)(ia, ib, f, tt);
4128  if (ipsdr == 1) {
4129  for (i = 1; i <= 4; ++i) {
4130  j = i;
4131  if (iordr != 0 && i == 2) j = 4;
4132  if (iordr != 0 && i == 4) j = 2;
4133  xyz[j * 3 - 3] = f[i*3 - 1]*TMath::Cos(f[jphi + i*3 - 4]*kRad);
4134  xyz[j * 3 - 2] = f[i*3 - 1]*TMath::Sin(f[jphi + i*3 - 4]*kRad);
4135  xyz[j * 3 - 1] = f[i*3 - 1]*TMath::Cos(f[jth + i*3 - 4]*kRad) /
4136  TMath::Sin(f[jth + i*3 - 4]*kRad);
4137  ttt[j - 1] = tt[i - 1];
4138  }
4139  } else {
4140  for (i = 1; i <= 4; ++i) {
4141  j = i;
4142  if (iordr != 0 && i == 2) j = 4;
4143  if (iordr != 0 && i == 4) j = 2;
4144  xyz[j*3 - 3] = f[i*3 - 1]*TMath::Sin(f[jth + i*3 - 4]*kRad)*TMath::Cos(f[jphi + i*3 - 4]*kRad);
4145  xyz[j*3 - 2] = f[i*3 - 1]*TMath::Sin(f[jth + i*3 - 4]*kRad)*TMath::Sin(f[jphi + i*3 - 4]*kRad);
4146  xyz[j*3 - 1] = f[i*3 - 1]*TMath::Cos(f[jth + i*3 - 4]*kRad);
4147  ttt[j - 1] = tt[i - 1];
4148  }
4149  }
4150  icodes[0] = ia;
4151  icodes[1] = ib;
4152  (this->*fDrawFace)(icodes, xyz, 4, iface, ttt);
4153  // N E X T T H E T A
4154 L400:
4155  ith += incrth;
4156  if (ith == 0) ith = kth;
4157  if (ith > kth) ith = 1;
4158  if (ith != ith2) goto L200;
4159  if (incrth == 0) goto L500;
4160  if (incrth < 0) {
4161  incrth = 0;
4162  goto L200;
4163  }
4164  incrth = -1;
4165  ith = ith1;
4166  goto L400;
4167  // N E X T P H I
4168 L500:
4169  iphi += incr;
4170  if (iphi == 0) iphi = kphi;
4171  if (iphi > kphi) iphi = 1;
4172  if (iphi != iphi2) goto L100;
4173  if (incr == 0) return;
4174  if (incr < 0) {
4175  incr = 0;
4176  goto L100;
4177  }
4178  incr = -1;
4179  iphi = iphi1;
4180  goto L500;
4181 }
4182 
4183 
4184 ////////////////////////////////////////////////////////////////////////////////
4185 /// Set surface property coefficients
4186 ///
4187 /// \param[in] qqa diffusion coefficient for diffused light [0.,1.]
4188 /// \param[in] qqd diffusion coefficient for direct light [0.,1.]
4189 /// \param[in] qqs diffusion coefficient for reflected light [0.,1.]
4190 /// \param[in] nncs power coefficient for reflected light (.GE.1)
4191 ///
4192 /// Lightness model formula: Y = YD*QA + > YLi*(QD*cosNi+QS*cosRi)
4193 ///
4194 /// \param[out] irep reply (0 - O.K, -1 error)
4195 
4197 {
4198  irep = 0;
4199  if (qqa < 0 || qqa > 1 || qqd < 0 || qqd > 1 || qqs < 0 || qqs > 1 || nnqs < 1) {
4200  Error("SurfaceProperty", "error in coefficients");
4201  irep = -1;
4202  return;
4203  }
4204  fQA = qqa;
4205  fQD = qqd;
4206  fQS = qqs;
4207  fNqs = nnqs;
4208 }
4209 
4210 
4211 ////////////////////////////////////////////////////////////////////////////////
4212 /// Draw implicit function FUN(X,Y,Z) = 0 in cartesian coordinates using
4213 /// hidden surface removal algorithm "Painter".
4214 ///
4215 /// \param[in] rmin min scope coordinates
4216 /// \param[in] rmax max scope coordinates
4217 /// \param[in] nx number of steps along X
4218 /// \param[in] ny number of steps along Y
4219 /// \param[in] nz number of steps along Z
4220 ///
4221 /// - `chopt` = 'BF' from BACK to FRONT
4222 /// - `chopt` = 'FB' from FRONT to BACK
4223 
4225  Int_t nx, Int_t ny, Int_t nz, const char *chopt)
4226 {
4227  Int_t ix, iy, iz;
4228  Int_t ix1, iy1, iz1;
4229  Int_t ix2, iy2, iz2;
4230  Int_t incr, incrx, incry, incrz;
4231  Int_t icodes[3], i, i1, i2, k, nnod, ntria;
4232  Double_t x1=0, x2=0, y1, y2, z1, z2;
4233  Double_t dx, dy, dz;
4234  Double_t p[8][3], pf[8], pn[8][3], t[3], fsurf, w;
4235 
4236  Double_t xyz[kNmaxp][3], xyzn[kNmaxp][3], grad[kNmaxp][3];
4237  Double_t dtria[kNmaxt][6], abcd[kNmaxt][4];
4238  Int_t itria[kNmaxt][3], iorder[kNmaxt];
4239  TView *view = 0;
4240 
4241  if (gPad) view = gPad->GetView();
4242  if (!view) {
4243  Error("ImplicitFunction", "no TView in current pad");
4244  return;
4245  }
4246  Double_t *tnorm = view->GetTnorm();
4247  if (!tnorm) return;
4248 
4249  // D E F I N E O R D E R O F D R A W I N G
4250  if (*chopt == 'B' || *chopt == 'b') {
4251  incrx = +1;
4252  incry = +1;
4253  incrz = +1;
4254  } else {
4255  incrx = -1;
4256  incry = -1;
4257  incrz = -1;
4258  }
4259  if (tnorm[8] < 0.) incrx =-incrx;
4260  if (tnorm[9] < 0.) incry =-incry;
4261  if (tnorm[10] < 0.) incrz =-incrz;
4262  ix1 = 1;
4263  iy1 = 1;
4264  iz1 = 1;
4265  if (incrx == -1) ix1 = nx;
4266  if (incry == -1) iy1 = ny;
4267  if (incrz == -1) iz1 = nz;
4268  ix2 = nx - ix1 + 1;
4269  iy2 = ny - iy1 + 1;
4270  iz2 = nz - iz1 + 1;
4271  dx = (rmax[0]-rmin[0]) / nx;
4272  dy = (rmax[1]-rmin[1]) / ny;
4273  dz = (rmax[2]-rmin[2]) / nz;
4274 
4275  // Define the colors used to draw the function
4276  Float_t r=0., g=0., b=0., hue, light, satur, light2;
4277  TColor *colref = gROOT->GetColor(fgCurrentF3->GetFillColor());
4278  if (colref) colref->GetRGB(r, g, b);
4279  TColor::RGBtoHLS(r, g, b, hue, light, satur);
4280  TColor *acol;
4281  acol = gROOT->GetColor(kF3FillColor1);
4282  if (acol) acol->SetRGB(r, g, b);
4283  if (light >= 0.5) {
4284  light2 = .5*light;
4285  } else {
4286  light2 = 1-.5*light;
4287  }
4288  TColor::HLStoRGB(hue, light2, satur, r, g, b);
4289  acol = gROOT->GetColor(kF3FillColor2);
4290  if (acol) acol->SetRGB(r, g, b);
4291  colref = gROOT->GetColor(fgCurrentF3->GetLineColor());
4292  if (colref) colref->GetRGB(r, g, b);
4293  acol = gROOT->GetColor(kF3LineColor);
4294  if (acol) acol->SetRGB(r, g, b);
4295 
4296  // D R A W F U N C T I O N
4297  for (iz = iz1; incrz < 0 ? iz >= iz2 : iz <= iz2; iz += incrz) {
4298  z1 = (iz-1)*dz + rmin[2];
4299  z2 = z1 + dz;
4300  p[0][2] = z1;
4301  p[1][2] = z1;
4302  p[2][2] = z1;
4303  p[3][2] = z1;
4304  p[4][2] = z2;
4305  p[5][2] = z2;
4306  p[6][2] = z2;
4307  p[7][2] = z2;
4308  for (iy = iy1; incry < 0 ? iy >= iy2 : iy <= iy2; iy += incry) {
4309  y1 = (iy-1)*dy + rmin[1];
4310  y2 = y1 + dy;
4311  p[0][1] = y1;
4312  p[1][1] = y1;
4313  p[2][1] = y2;
4314  p[3][1] = y2;
4315  p[4][1] = y1;
4316  p[5][1] = y1;
4317  p[6][1] = y2;
4318  p[7][1] = y2;
4319  if (incrx == +1) {
4320  x2 = rmin[0];
4321  pf[1] = fgCurrentF3->Eval(x2,y1,z1);
4322  pf[2] = fgCurrentF3->Eval(x2,y2,z1);
4323  pf[5] = fgCurrentF3->Eval(x2,y1,z2);
4324  pf[6] = fgCurrentF3->Eval(x2,y2,z2);
4325  } else {
4326  x1 = rmax[0];
4327  pf[0] = fgCurrentF3->Eval(x1,y1,z1);
4328  pf[3] = fgCurrentF3->Eval(x1,y2,z1);
4329  pf[4] = fgCurrentF3->Eval(x1,y1,z2);
4330  pf[7] = fgCurrentF3->Eval(x1,y2,z2);
4331  }
4332  for (ix = ix1; incrx < 0 ? ix >= ix2 : ix <= ix2; ix += incrx) {
4333  icodes[0] = ix;
4334  icodes[1] = iy;
4335  icodes[2] = iz;
4336  if (incrx == +1) {
4337  x1 = x2;
4338  x2 = x2 + dx;
4339  pf[0] = pf[1];
4340  pf[3] = pf[2];
4341  pf[4] = pf[5];
4342  pf[7] = pf[6];
4343  pf[1] = fgCurrentF3->Eval(x2,y1,z1);
4344  pf[2] = fgCurrentF3->Eval(x2,y2,z1);
4345  pf[5] = fgCurrentF3->Eval(x2,y1,z2);
4346  pf[6] = fgCurrentF3->Eval(x2,y2,z2);
4347  } else {
4348  x2 = x1;
4349  x1 = x1 - dx;
4350  pf[1] = pf[0];
4351  pf[2] = pf[3];
4352  pf[5] = pf[4];
4353  pf[6] = pf[7];
4354  pf[0] = fgCurrentF3->Eval(x1,y1,z1);
4355  pf[3] = fgCurrentF3->Eval(x1,y2,z1);
4356  pf[4] = fgCurrentF3->Eval(x1,y1,z2);
4357  pf[7] = fgCurrentF3->Eval(x1,y2,z2);
4358  }
4359  if (pf[0] >= -kFdel) goto L110;
4360  if (pf[1] >= -kFdel) goto L120;
4361  if (pf[2] >= -kFdel) goto L120;
4362  if (pf[3] >= -kFdel) goto L120;
4363  if (pf[4] >= -kFdel) goto L120;
4364  if (pf[5] >= -kFdel) goto L120;
4365  if (pf[6] >= -kFdel) goto L120;
4366  if (pf[7] >= -kFdel) goto L120;
4367  goto L510;
4368 L110:
4369  if (pf[1] < -kFdel) goto L120;
4370  if (pf[2] < -kFdel) goto L120;
4371  if (pf[3] < -kFdel) goto L120;
4372  if (pf[4] < -kFdel) goto L120;
4373  if (pf[5] < -kFdel) goto L120;
4374  if (pf[6] < -kFdel) goto L120;
4375  if (pf[7] < -kFdel) goto L120;
4376  goto L510;
4377 L120:
4378  p[0][0] = x1;
4379  p[1][0] = x2;
4380  p[2][0] = x2;
4381  p[3][0] = x1;
4382  p[4][0] = x1;
4383  p[5][0] = x2;
4384  p[6][0] = x2;
4385  p[7][0] = x1;
4386 
4387  // F I N D G R A D I E N T S
4388  // Find X-gradient
4389  if (ix == 1) {
4390  pn[0][0] = (pf[1] - pf[0]) / dx;
4391  pn[3][0] = (pf[2] - pf[3]) / dx;
4392  pn[4][0] = (pf[5] - pf[4]) / dx;
4393  pn[7][0] = (pf[6] - pf[7]) / dx;
4394  } else {
4395  pn[0][0] = (pf[1] - fgCurrentF3->Eval(x1-dx,y1,z1)) / (dx + dx);
4396  pn[3][0] = (pf[2] - fgCurrentF3->Eval(x1-dx,y2,z1)) / (dx + dx);
4397  pn[4][0] = (pf[5] - fgCurrentF3->Eval(x1-dx,y1,z2)) / (dx + dx);
4398  pn[7][0] = (pf[6] - fgCurrentF3->Eval(x1-dx,y2,z2)) / (dx + dx);
4399  }
4400  if (ix == nx) {
4401  pn[1][0] = (pf[1] - pf[0]) / dx;
4402  pn[2][0] = (pf[2] - pf[3]) / dx;
4403  pn[5][0] = (pf[5] - pf[4]) / dx;
4404  pn[6][0] = (pf[6] - pf[7]) / dx;
4405  } else {
4406  pn[1][0] = (fgCurrentF3->Eval(x2+dx,y1,z1) - pf[0]) / (dx + dx);
4407  pn[2][0] = (fgCurrentF3->Eval(x2+dx,y2,z1) - pf[3]) / (dx + dx);
4408  pn[5][0] = (fgCurrentF3->Eval(x2+dx,y1,z2) - pf[4]) / (dx + dx);
4409  pn[6][0] = (fgCurrentF3->Eval(x2+dx,y2,z2) - pf[7]) / (dx + dx);
4410  }
4411  // Find Y-gradient
4412  if (iy == 1) {
4413  pn[0][1] = (pf[3] - pf[0]) / dy;
4414  pn[1][1] = (pf[2] - pf[1]) / dy;
4415  pn[4][1] = (pf[7] - pf[4]) / dy;
4416  pn[5][1] = (pf[6] - pf[5]) / dy;
4417  } else {
4418  pn[0][1] = (pf[3] - fgCurrentF3->Eval(x1,y1-dy,z1)) / (dy + dy);
4419  pn[1][1] = (pf[2] - fgCurrentF3->Eval(x2,y1-dy,z1)) / (dy + dy);
4420  pn[4][1] = (pf[7] - fgCurrentF3->Eval(x1,y1-dy,z2)) / (dy + dy);
4421  pn[5][1] = (pf[6] - fgCurrentF3->Eval(x2,y1-dy,z2)) / (dy + dy);
4422  }
4423  if (iy == ny) {
4424  pn[2][1] = (pf[2] - pf[1]) / dy;
4425  pn[3][1] = (pf[3] - pf[0]) / dy;
4426  pn[6][1] = (pf[6] - pf[5]) / dy;
4427  pn[7][1] = (pf[7] - pf[4]) / dy;
4428  } else {
4429  pn[2][1] = (fgCurrentF3->Eval(x2,y2+dy,z1) - pf[1]) / (dy + dy);
4430  pn[3][1] = (fgCurrentF3->Eval(x1,y2+dy,z1) - pf[0]) / (dy + dy);
4431  pn[6][1] = (fgCurrentF3->Eval(x2,y2+dy,z2) - pf[5]) / (dy + dy);
4432  pn[7][1] = (fgCurrentF3->Eval(x1,y2+dy,z2) - pf[4]) / (dy + dy);
4433  }
4434  // Find Z-gradient
4435  if (iz == 1) {
4436  pn[0][2] = (pf[4] - pf[0]) / dz;
4437  pn[1][2] = (pf[5] - pf[1]) / dz;
4438  pn[2][2] = (pf[6] - pf[2]) / dz;
4439  pn[3][2] = (pf[7] - pf[3]) / dz;
4440  } else {
4441  pn[0][2] = (pf[4] - fgCurrentF3->Eval(x1,y1,z1-dz)) / (dz + dz);
4442  pn[1][2] = (pf[5] - fgCurrentF3->Eval(x2,y1,z1-dz)) / (dz + dz);
4443  pn[2][2] = (pf[6] - fgCurrentF3->Eval(x2,y2,z1-dz)) / (dz + dz);
4444  pn[3][2] = (pf[7] - fgCurrentF3->Eval(x1,y2,z1-dz)) / (dz + dz);
4445  }
4446  if (iz == nz) {
4447  pn[4][2] = (pf[4] - pf[0]) / dz;
4448  pn[5][2] = (pf[5] - pf[1]) / dz;
4449  pn[6][2] = (pf[6] - pf[2]) / dz;
4450  pn[7][2] = (pf[7] - pf[3]) / dz;
4451  } else {
4452  pn[4][2] = (fgCurrentF3->Eval(x1,y1,z2+dz) - pf[0]) / (dz + dz);
4453  pn[5][2] = (fgCurrentF3->Eval(x2,y1,z2+dz) - pf[1]) / (dz + dz);
4454  pn[6][2] = (fgCurrentF3->Eval(x2,y2,z2+dz) - pf[2]) / (dz + dz);
4455  pn[7][2] = (fgCurrentF3->Eval(x1,y2,z2+dz) - pf[3]) / (dz + dz);
4456  }
4457  fsurf = 0.;
4458  MarchingCube(fsurf, p, pf, pn, nnod, ntria, xyz, grad, itria);
4459  if (ntria == 0) goto L510;
4460 
4461  for ( i=1 ; i<=nnod ; i++ ) {
4462  view->WCtoNDC(&xyz[i-1][0], &xyzn[i-1][0]);
4463  Luminosity(&grad[i-1][0], w);
4464  grad[i-1][0] = w;
4465  }
4466  ZDepth(xyzn, ntria, itria, dtria, abcd, (Int_t*)iorder);
4467  if (ntria == 0) goto L510;
4468  incr = 1;
4469  if (*chopt == 'B' || *chopt == 'b') incr =-1;
4470  i1 = 1;
4471  if (incr == -1) i1 = ntria;
4472  i2 = ntria - i1 + 1;
4473  // If clipping box is on do not draw the triangles
4474  if (fgF3Clipping) {
4475  if(x2<=fgF3XClip && y2 <=fgF3YClip && z2>=fgF3ZClip) goto L510;
4476  }
4477  // Draw triangles
4478  for (i=i1; incr < 0 ? i >= i2 : i <= i2; i += incr) {
4479  k = iorder[i-1];
4480  t[0] = grad[TMath::Abs(itria[k-1][0])-1][0];
4481  t[1] = grad[TMath::Abs(itria[k-1][1])-1][0];
4482  t[2] = grad[TMath::Abs(itria[k-1][2])-1][0];
4483  (this->*fDrawFace)(icodes, (Double_t*)xyz, 3, &itria[k-1][0], t);
4484  }
4485 L510:
4486  continue;
4487  }
4488  }
4489  }
4490 }
4491 
4492 
4493 ////////////////////////////////////////////////////////////////////////////////
4494 /// Topological decider for "Marching Cubes" algorithm Find set of triangles
4495 /// aproximating the isosurface F(x,y,z)=Fiso inside the cube
4496 ///
4497 /// \param[in] fiso function value for isosurface
4498 /// \param[in] p cube vertexes
4499 /// \param[in] f function values at the vertexes
4500 /// \param[in] g function gradients at the vertexes
4501 ///
4502 /// \param[out] nnod number of nodes (maximum 13)
4503 /// \param[out] ntria number of triangles (maximum 12)
4504 /// \param[out] xyz nodes
4505 /// \param[out] grad node normales (not normalized)
4506 /// \param[out] itria triangles
4507 
4509  Double_t f[8], Double_t g[8][3],
4510  Int_t &nnod, Int_t &ntria,
4511  Double_t xyz[][3],
4512  Double_t grad[][3],
4513  Int_t itria[][3])
4514 {
4515  static Int_t irota[24][8] = { { 1,2,3,4,5,6,7,8 }, { 2,3,4,1,6,7,8,5 },
4516  { 3,4,1,2,7,8,5,6 }, { 4,1,2,3,8,5,6,7 },
4517  { 6,5,8,7,2,1,4,3 }, { 5,8,7,6,1,4,3,2 },
4518  { 8,7,6,5,4,3,2,1 }, { 7,6,5,8,3,2,1,4 },
4519  { 2,6,7,3,1,5,8,4 }, { 6,7,3,2,5,8,4,1 },
4520  { 7,3,2,6,8,4,1,5 }, { 3,2,6,7,4,1,5,8 },
4521  { 5,1,4,8,6,2,3,7 }, { 1,4,8,5,2,3,7,6 },
4522  { 4,8,5,1,3,7,6,2 }, { 8,5,1,4,7,6,2,3 },
4523  { 5,6,2,1,8,7,3,4 }, { 6,2,1,5,7,3,4,8 },
4524  { 2,1,5,6,3,4,8,7 }, { 1,5,6,2,4,8,7,3 },
4525  { 4,3,7,8,1,2,6,5 }, { 3,7,8,4,2,6,5,1 },
4526  { 7,8,4,3,6,5,1,2 }, { 8,4,3,7,5,1,2,6 } };
4527 
4528  static Int_t iwhat[21] = { 1,3,5,65,50,67,74,51,177,105,113,58,165,178,
4529  254,252,250,190,205,188,181 };
4530  Int_t j, i, i1, i2, i3, ir, irt=0, k, k1, k2, incr, icase=0, n;
4531  Int_t itr[3];
4532 
4533  nnod = 0;
4534  ntria = 0;
4535 
4536  // F I N D C O N F I G U R A T I O N T Y P E
4537  for ( i=1; i<=8 ; i++) {
4538  fF8[i-1] = f[i-1] - fiso;
4539  }
4540  for ( ir=1 ; ir<=24 ; ir++ ) {
4541  k = 0;
4542  incr = 1;
4543  for ( i=1 ; i<=8 ; i++ ) {
4544  if (fF8[irota[ir-1][i-1]-1] >= 0.) k = k + incr;
4545  incr = incr + incr;
4546  }
4547  if (k==0 || k==255) return;
4548  for ( i=1 ; i<=21 ; i++ ) {
4549  if (k != iwhat[i-1]) continue;
4550  icase = i;
4551  irt = ir;
4552  goto L200;
4553  }
4554  }
4555 
4556  // R O T A T E C U B E
4557 L200:
4558  for ( i=1 ; i<=8 ; i++ ) {
4559  k = irota[irt-1][i-1];
4560  fF8[i-1] = f[k-1] - fiso;
4561  fP8[i-1][0] = p[k-1][0];
4562  fP8[i-1][1] = p[k-1][1];
4563  fP8[i-1][2] = p[k-1][2];
4564  fG8[i-1][0] = g[k-1][0];
4565  fG8[i-1][1] = g[k-1][1];
4566  fG8[i-1][2] = g[k-1][2];
4567  }
4568 
4569  // V A R I O U S C O N F I G U R A T I O N S
4570  n = 0;
4571  switch ((int)icase) {
4572  case 1:
4573  case 15:
4574  MarchingCubeCase00(1, 4, 9, 0, 0, 0, nnod, ntria, xyz, grad, itria);
4575  goto L400;
4576  case 2:
4577  case 16:
4578  MarchingCubeCase00(2, 4, 9, 10, 0, 0, nnod, ntria, xyz, grad, itria);
4579  goto L400;
4580  case 3:
4581  case 17:
4582  MarchingCubeCase03(nnod, ntria, xyz, grad, itria);
4583  goto L400;
4584  case 4:
4585  case 18:
4586  MarchingCubeCase04(nnod, ntria, xyz, grad, itria);
4587  goto L400;
4588  case 5:
4589  case 19:
4590  MarchingCubeCase00(6, 2, 1, 9, 8, 0, nnod, ntria, xyz, grad, itria);
4591  goto L400;
4592  case 6:
4593  case 20:
4594  MarchingCubeCase06(nnod, ntria, xyz, grad, itria);
4595  goto L400;
4596  case 7:
4597  case 21:
4598  MarchingCubeCase07(nnod, ntria, xyz, grad, itria);
4599  goto L400;
4600  case 8:
4601  MarchingCubeCase00(2, 4, 8, 6, 0, 0, nnod, ntria, xyz, grad, itria);
4602  goto L500;
4603  case 9:
4604  MarchingCubeCase00(1, 4, 12, 7, 6, 10, nnod, ntria, xyz, grad, itria);
4605  goto L500;
4606  case 0:
4607  MarchingCubeCase10(nnod, ntria, xyz, grad, itria);
4608  goto L500;
4609  case 11:
4610  MarchingCubeCase00(1, 4, 8, 7, 11, 10, nnod, ntria, xyz, grad, itria);
4611  goto L500;
4612  case 12:
4613  MarchingCubeCase12(nnod, ntria, xyz, grad, itria);
4614  goto L500;
4615  case 13:
4616  MarchingCubeCase13(nnod, ntria, xyz, grad, itria);
4617  goto L500;
4618  case 14:
4619  MarchingCubeCase00(1, 9, 12, 7, 6, 2, nnod, ntria, xyz, grad, itria);
4620  goto L500;
4621  }
4622 
4623  // I F N E E D E D , I N V E R T T R I A N G L E S
4624 L400:
4625  if (ntria == 0) return;
4626  if (icase <= 14) goto L500;
4627  for ( i=1; i<=ntria ; i++ ) {
4628  i1 = TMath::Abs(itria[i-1][0]);
4629  i2 = TMath::Abs(itria[i-1][1]);
4630  i3 = TMath::Abs(itria[i-1][2]);
4631  if (itria[i-1][2] < 0) i1 =-i1;
4632  if (itria[i-1][1] < 0) i3 =-i3;
4633  if (itria[i-1][0] < 0) i2 =-i2;
4634  itria[i-1][0] = i1;
4635  itria[i-1][1] = i3;
4636  itria[i-1][2] = i2;
4637  }
4638 
4639  // R E M O V E V E R Y S M A L L T R I A N G L E S
4640 L500:
4641  n = n + 1;
4642 L510:
4643  if (n > ntria) return;
4644  for ( i=1 ; i<=3 ; i++ ) {
4645  i1 = i;
4646  i2 = i + 1;
4647  if (i == 3) i2 = 1;
4648  k1 = TMath::Abs(itria[n-1][i1-1]);
4649  k2 = TMath::Abs(itria[n-1][i2-1]);
4650  if (TMath::Abs(xyz[k1-1][0]-xyz[k2-1][0]) > kDel) continue;
4651  if (TMath::Abs(xyz[k1-1][1]-xyz[k2-1][1]) > kDel) continue;
4652  if (TMath::Abs(xyz[k1-1][2]-xyz[k2-1][2]) > kDel) continue;
4653  i3 = i - 1;
4654  if (i == 1) i3 = 3;
4655  goto L530;
4656  }
4657  goto L500;
4658 
4659  // R E M O V E T R I A N G L E
4660 L530:
4661  for ( i=1 ; i<=3 ; i++ ) {
4662  itr[i-1] = itria[n-1][i-1];
4663  itria[n-1][i-1] = itria[ntria-1][i-1];
4664  }
4665  ntria = ntria - 1;
4666  if (ntria == 0) return;
4667  if (itr[i2-1]*itr[i3-1] > 0) goto L510;
4668 
4669  // C O R R E C T O T H E R T R I A N G L E S
4670  if (itr[i2-1] < 0) {
4671  k1 =-itr[i2-1];
4672  k2 =-TMath::Abs(itr[i3-1]);
4673  }
4674  if (itr[i3-1] < 0) {
4675  k1 =-itr[i3-1];
4676  k2 =-TMath::Abs(itr[i1-1]);
4677  }
4678  for ( j=1 ; j<=ntria ; j++ ) {
4679  for ( i=1 ; i<=3 ; i++ ) {
4680  if (itria[j-1][i-1] != k2) continue;
4681  i2 = TMath::Abs(itria[j-1][0]);
4682  if (i != 3) i2 = TMath::Abs(itria[j-1][i]);
4683  if (i2 == k1) itria[j-1][i-1] =-itria[j-1][i-1];
4684  goto L560;
4685  }
4686 L560:
4687  continue;
4688  }
4689  goto L510;
4690 }
4691 
4692 
4693 ////////////////////////////////////////////////////////////////////////////////
4694 /// Consideration of trivial cases: 1,2,5,8,9,11,14
4695 ///
4696 /// \param[in] k1-k6 edges intersected with isosurface
4697 
4699  Int_t k4, Int_t k5, Int_t k6,
4700  Int_t &nnod, Int_t &ntria,
4701  Double_t xyz[52][3],
4702  Double_t grad[52][3],
4703  Int_t itria[48][3])
4704 {
4705  static Int_t it[4][4][3] = { { { 1,2, 3 }, { 0,0, 0 }, { 0,0, 0 }, { 0,0, 0 } },
4706  { { 1,2,-3 }, {-1,3, 4 }, { 0,0, 0 }, { 0,0, 0 } },
4707  { { 1,2,-3 }, {-1,3,-4 }, {-1,4, 5 }, { 0,0, 0 } },
4708  { { 1,2,-3 }, {-1,3,-4 }, {-4,6,-1 }, { 4,5,-6 } }
4709  };
4710  Int_t it2[4][3], i, j;
4711 
4712  Int_t ie[6];
4713 
4714  // S E T N O D E S & N O R M A L E S
4715  ie[0] = k1;
4716  ie[1] = k2;
4717  ie[2] = k3;
4718  ie[3] = k4;
4719  ie[4] = k5;
4720  ie[5] = k6;
4721  nnod = 6;
4722  if (ie[5] == 0) nnod = 5;
4723  if (ie[4] == 0) nnod = 4;
4724  if (ie[3] == 0) nnod = 3;
4725  MarchingCubeFindNodes(nnod, ie, xyz, grad);
4726 
4727  // S E T T R I A N G L E S
4728  ntria = nnod - 2;
4729  // Copy "it" into a 2D matrix to be passed to MarchingCubeSetTriangles
4730  for ( i=0; i<3 ; i++) {
4731  for ( j=0; j<4 ; j++) {
4732  it2[j][i] = it[ntria-1][j][i];
4733  }
4734  }
4735  MarchingCubeSetTriangles(ntria, it2, itria);
4736 }
4737 
4738 
4739 ////////////////////////////////////////////////////////////////////////////////
4740 /// Consider case No 3
4741 
4743  Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
4744 {
4745  Double_t f0;
4746  static Int_t ie[6] = { 4,9,1, 2,11,3 };
4747  static Int_t it1[2][3] = { { 1,2,3 }, { 4,5,6 } };
4748  static Int_t it2[4][3] = { { 1,2,-5 }, { -1,5,6 }, { 5,-2,4 }, { -4,2,3 } };
4749 
4750  // S E T N O D E S & N O R M A L E S
4751  nnod = 6;
4752  MarchingCubeFindNodes(nnod, ie, xyz, grad);
4753 
4754  // F I N D C O N F I G U R A T I O N
4755  f0 = (fF8[0]*fF8[2]-fF8[1]*fF8[3]) / (fF8[0]+fF8[2]-fF8[1]-fF8[3]);
4756  if (f0>=0. && fF8[0]>=0.) goto L100;
4757  if (f0<0. && fF8[0]<0.) goto L100;
4758  ntria = 2;
4759  MarchingCubeSetTriangles(ntria, it1, itria);
4760  return;
4761 
4762  // N O T S E P A R A T E D F R O N T F A C E
4763 L100:
4764  ntria = 4;
4765  MarchingCubeSetTriangles(ntria, it2, itria);
4766 }
4767 
4768 
4769 ////////////////////////////////////////////////////////////////////////////////
4770 /// Consider case No 4
4771 
4773  Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
4774 {
4775  Int_t irep;
4776  static Int_t ie[6] = { 4,9,1, 7,11,6 };
4777  static Int_t it1[2][3] = { { 1,2,3 }, { 4,5,6 } };
4778  static Int_t it2[6][3] = { { 1,2,4 }, { 2,3,6 }, { 3,1,5 },
4779  { 4,5,1 }, { 5,6,3 }, { 6,4,2 } };
4780 
4781  // S E T N O D E S & N O R M A L E S
4782  nnod = 6;
4783  MarchingCubeFindNodes(nnod, ie, xyz, grad);
4784 
4785  // 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 ?
4786  MarchingCubeSurfacePenetration(fF8[0], fF8[1], fF8[2], fF8[3],
4787  fF8[4], fF8[5], fF8[6], fF8[7], irep);
4788  if (irep == 0) {
4789  ntria = 2;
4790  MarchingCubeSetTriangles(ntria, it1, itria);
4791  } else {
4792  ntria = 6;
4793  MarchingCubeSetTriangles(ntria, it2, itria);
4794  }
4795 }
4796 
4797 
4798 ////////////////////////////////////////////////////////////////////////////////
4799 /// Consider case No 6
4800 
4802  Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
4803 {
4804  Double_t f0;
4805  Int_t irep;
4806 
4807  static Int_t ie[7] = { 2,4,9,10, 6,7,11 };
4808  static Int_t it1[5][3] = { { 6,7,-1 }, { -6,1,2 }, { 6,2,3 }, { 6,3,-4 }, { -6,4,5 } };
4809  static Int_t it2[3][3] = { { 1,2,-3 }, { -1,3,4 }, { 5,6,7 } };
4810  static Int_t it3[7][3] = { { 6,7,-1 }, { -6,1,2 }, { 6,2,3 }, { 6,3,-4 }, { -6,4,5 },
4811  { 1,7,-5 }, { -1,5,4 } };
4812 
4813  // S E T N O D E S & N O R M A L E S
4814  nnod = 7;
4815  MarchingCubeFindNodes(nnod, ie, xyz, grad);
4816 
4817  // F I N D C O N F I G U R A T I O N
4818  f0 = (fF8[1]*fF8[6]-fF8[5]*fF8[2]) / (fF8[1]+fF8[6]-fF8[5]-fF8[2]);
4819  if (f0>=0. && fF8[1]>=0.) goto L100;
4820  if (f0<0. && fF8[1]<0.) goto L100;
4821 
4822  // 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 ?
4823  MarchingCubeSurfacePenetration(fF8[2], fF8[1], fF8[5], fF8[6],
4824  fF8[3], fF8[0], fF8[4], fF8[7], irep);
4825  if (irep == 1) {
4826  ntria = 7;
4827  MarchingCubeSetTriangles(ntria, it3, itria);
4828  } else {
4829  ntria = 3;
4830  MarchingCubeSetTriangles(ntria, it2, itria);
4831  }
4832  return;
4833 
4834  // N O T S E P A R A T E D R I G H T F A C E
4835 L100:
4836  ntria = 5;
4837  MarchingCubeSetTriangles(ntria, it1, itria);
4838 }
4839 
4840 
4841 ////////////////////////////////////////////////////////////////////////////////
4842 /// Consider case No 7
4843 
4845  Double_t xyz[52][3], Double_t grad[52][3],
4846  Int_t itria[48][3])
4847 {
4848  Double_t f1, f2, f3;
4849  Int_t icase, irep;
4850  static Int_t ie[9] = { 3,12,4, 1,10,2, 11,6,7 };
4851  static Int_t it[9][9][3] = {
4852  {{ 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}},
4853  {{ 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}},
4854  {{ 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}},
4855  {{-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}},
4856  {{ 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}},
4857  {{-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}},
4858  {{ 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}},
4859  {{ 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}},
4860  {{ -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}}
4861  };
4862 
4863  Int_t it2[9][3], i, j;
4864 
4865  // S E T N O D E S & N O R M A L E S
4866  nnod = 9;
4867  MarchingCubeFindNodes(nnod, ie, xyz, grad);
4868 
4869  // F I N D C O N F I G U R A T I O N
4870  f1 = (fF8[2]*fF8[5]-fF8[1]*fF8[6]) / (fF8[2]+fF8[5]-fF8[1]-fF8[6]);
4871  f2 = (fF8[2]*fF8[7]-fF8[3]*fF8[6]) / (fF8[2]+fF8[7]-fF8[3]-fF8[6]);
4872  f3 = (fF8[2]*fF8[0]-fF8[1]*fF8[3]) / (fF8[2]+fF8[0]-fF8[1]-fF8[3]);
4873  icase = 1;
4874  if (f1>=0. && fF8[2] <0.) icase = icase + 1;
4875  if (f1 <0. && fF8[2]>=0.) icase = icase + 1;
4876  if (f2>=0. && fF8[2] <0.) icase = icase + 2;
4877  if (f2 <0. && fF8[2]>=0.) icase = icase + 2;
4878  if (f3>=0. && fF8[2] <0.) icase = icase + 4;
4879  if (f3 <0. && fF8[2]>=0.) icase = icase + 4;
4880  ntria = 5;
4881 
4882  switch ((int)icase) {
4883  case 1: goto L100;
4884  case 2: goto L400;
4885  case 3: goto L400;
4886  case 4: goto L200;
4887  case 5: goto L400;
4888  case 6: goto L200;
4889  case 7: goto L200;
4890  case 8: goto L300;
4891  }
4892 
4893 L100:
4894  ntria = 3;
4895  goto L400;
4896 
4897  // F I N D A D D I T I O N A L P O I N T
4898 L200:
4899  nnod = 10;
4900  ntria = 9;
4901 
4902  // Copy "it" into a 2D matrix to be passed to MarchingCubeMiddlePoint
4903  for ( i=0; i<3 ; i++) {
4904  for ( j=0; j<9 ; j++) {
4905  it2[j][i] = it[icase-1][j][i];
4906  }
4907  }
4908  MarchingCubeMiddlePoint(9, xyz, grad, it2, &xyz[nnod-1][0], &grad[nnod-1][0]);
4909  goto L400;
4910 
4911  // 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 ?
4912 L300:
4913  MarchingCubeSurfacePenetration(fF8[3], fF8[2], fF8[6], fF8[7],
4914  fF8[0], fF8[1], fF8[5], fF8[4], irep);
4915  if (irep != 2) goto L400;
4916  ntria = 9;
4917  icase = 9;
4918 
4919  // S E T T R I A N G L E S
4920 L400:
4921  // Copy "it" into a 2D matrix to be passed to MarchingCubeSetTriangles
4922  for ( i=0; i<3 ; i++) {
4923  for ( j=0; j<9 ; j++) {
4924  it2[j][i] = it[icase-1][j][i];
4925  }
4926  }
4927  MarchingCubeSetTriangles(ntria, it2, itria);
4928 }
4929 
4930 
4931 ////////////////////////////////////////////////////////////////////////////////
4932 /// Consider case No 10
4933 
4935  Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
4936 {
4937  Double_t f1, f2;
4938  Int_t icase, irep;
4939  static Int_t ie[8] = { 1,3,12,9, 5,7,11,10 };
4940  static Int_t it[6][8][3] = {
4941  {{1,2,-3}, {-1,3,4}, {5,6,-7}, {-5,7,8}, { 0,0,0}, { 0,0,0}, { 0,0,0}, { 0,0,0}},
4942  {{ 9,1,2}, { 9,2,3}, { 9,3,4}, { 9,4,5}, { 9,5,6}, { 9,6,7}, { 9,7,8}, { 9,8,1}},
4943  {{ 9,1,2}, { 9,4,1}, { 9,3,4}, { 9,6,3}, { 9,5,6}, { 9,8,5}, { 9,7,8}, { 9,2,7}},
4944  {{1,2,-7}, {-1,7,8}, {5,6,-3}, {-5,3,4}, { 0,0,0}, { 0,0,0}, { 0,0,0}, { 0,0,0}},
4945  {{1,2,-7}, {-1,7,8}, {2,3,-6}, {-2,6,7}, {3,4,-5}, {-3,5,6}, {4,1,-8}, {-4,8,5}},
4946  {{1,2,-3}, {-1,3,4}, {2,7,-6}, {-2,6,3}, {7,8,-5}, {-7,5,6}, {8,1,-4}, {-8,4,5}}
4947  };
4948  Int_t it2[8][3], i, j;
4949 
4950  // S E T N O D E S & N O R M A L E S
4951  nnod = 8;
4952  MarchingCubeFindNodes(nnod, ie, xyz, grad);
4953 
4954  // F I N D C O N F I G U R A T I O N
4955  f1 = (fF8[0]*fF8[5]-fF8[1]*fF8[4]) / (fF8[0]+fF8[5]-fF8[1]-fF8[4]);
4956  f2 = (fF8[3]*fF8[6]-fF8[2]*fF8[7]) / (fF8[3]+fF8[6]-fF8[2]-fF8[5]);
4957  icase = 1;
4958  if (f1 >= 0.) icase = icase + 1;
4959  if (f2 >= 0.) icase = icase + 2;
4960  if (icase==1 || icase==4) goto L100;
4961 
4962  // D I F F E R E N T T O P A N D B O T T O M
4963  nnod = 9;
4964  ntria = 8;
4965  // Copy "it" into a 2D matrix to be passed to MarchingCubeMiddlePoint
4966  for ( i=0; i<3 ; i++) {
4967  for ( j=0; j<8 ; j++) {
4968  it2[j][i] = it[icase-1][j][i];
4969  }
4970  }
4971  MarchingCubeMiddlePoint(8, xyz, grad, it2, &xyz[nnod-1][0], &grad[nnod-1][0]);
4972  goto L200;
4973 
4974  // 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 ?
4975 L100:
4976  MarchingCubeSurfacePenetration(fF8[0], fF8[1], fF8[5], fF8[4],
4977  fF8[3], fF8[2], fF8[6], fF8[7], irep);
4978  ntria = 4;
4979  if (irep == 0) goto L200;
4980  // "B O T T L E N E C K"
4981  ntria = 8;
4982  if (icase == 1) icase = 5;
4983  if (icase == 4) icase = 6;
4984 
4985  // S E T T R I A N G L E S
4986 L200:
4987  // Copy "it" into a 2D matrix to be passed to MarchingCubeSetTriangles
4988  for ( i=0; i<3 ; i++) {
4989  for ( j=0; j<8 ; j++) {
4990  it2[j][i] = it[icase-1][j][i];
4991  }
4992  }
4993  MarchingCubeSetTriangles(ntria, it2, itria);
4994 }
4995 
4996 
4997 ////////////////////////////////////////////////////////////////////////////////
4998 /// Consider case No 12
4999 
5001  Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
5002 {
5003  Double_t f1, f2;
5004  Int_t icase, irep;
5005  static Int_t ie[8] = { 3,12,4, 1,9,8,6,2 };
5006  static Int_t it[6][8][3] = {
5007  {{ 1,2,3}, {4,5,-6}, {-4,6,8}, { 6,7,8}, { 0,0,0}, { 0,0,0}, { 0,0,0}, { 0,0,0}},
5008  {{-9,1,2}, {9,2,-3}, {-9,3,4}, {9,4,-5}, {-9,5,6}, {9,6,-7}, {-9,7,8}, {9,8,-1}},
5009  {{9,1,-2}, {-9,2,6}, {9,6,-7}, {-9,7,8}, {9,8,-4}, {-9,4,5}, {9,5,-3}, {-9,3,1}},
5010  {{ 3,4,5}, {1,2,-6}, {-1,6,8}, { 6,7,8}, { 0,0,0}, { 0,0,0}, { 0,0,0}, { 0,0,0}},
5011  {{ 7,8,6}, {6,8,-1}, {-6,1,2}, {3,1,-8}, {-3,8,4}, { 3,4,5}, {3,5,-6}, {-3,6,2}},
5012  {{ 7,8,6}, {6,8,-4}, {-6,4,5}, {3,4,-8}, {-3,8,1}, { 3,1,2}, {3,2,-6}, {-3,6,5}}
5013  };
5014  Int_t it2[8][3], i, j;
5015 
5016  // S E T N O D E S & N O R M A L E S
5017  nnod = 8;
5018  MarchingCubeFindNodes(nnod, ie, xyz, grad);
5019 
5020  // F I N D C O N F I G U R A T I O N
5021  f1 = (fF8[0]*fF8[2]-fF8[1]*fF8[3]) / (fF8[0]+fF8[2]-fF8[1]-fF8[3]);
5022  f2 = (fF8[0]*fF8[7]-fF8[3]*fF8[4]) / (fF8[0]+fF8[7]-fF8[3]-fF8[4]);
5023  icase = 1;
5024  if (f1 >= 0.) icase = icase + 1;
5025  if (f2 >= 0.) icase = icase + 2;
5026  if (icase==1 || icase==4) goto L100;
5027 
5028  // F I N D A D D I T I O N A L P O I N T
5029  nnod = 9;
5030  ntria = 8;
5031  // Copy "it" into a 2D matrix to be passed to MarchingCubeMiddlePoint
5032  for ( i=0; i<3 ; i++) {
5033  for ( j=0; j<8 ; j++) {
5034  it2[j][i] = it[icase-1][j][i];
5035  }
5036  }
5037  MarchingCubeMiddlePoint(8, xyz, grad, it2, &xyz[nnod-1][0], &grad[nnod-1][0]);
5038  goto L200;
5039 
5040  // 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 ?
5041 L100:
5042  MarchingCubeSurfacePenetration(fF8[0], fF8[1], fF8[2], fF8[3],
5043  fF8[4], fF8[5], fF8[6], fF8[7], irep);
5044  ntria = 4;
5045  if (irep != 1) goto L200;
5046  // "B O T T L E N E C K"
5047  ntria = 8;
5048  if (icase == 1) icase = 5;
5049  if (icase == 4) icase = 6;
5050 
5051  // S E T T R I A N G L E S
5052 L200:
5053  // Copy "it" into a 2D matrix to be passed to MarchingCubeSetTriangles
5054  for ( i=0; i<3 ; i++) {
5055  for ( j=0; j<8 ; j++) {
5056  it2[j][i] = it[icase-1][j][i];
5057  }
5058  }
5059  MarchingCubeSetTriangles(ntria, it2, itria);
5060 }
5061 
5062 
5063 ////////////////////////////////////////////////////////////////////////////////
5064 /// Consider case No 13
5065 
5067  Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
5068 {
5069  Double_t ff[8];
5070  Double_t f1, f2, f3, f4;
5071  Int_t nr, nf, i, k, incr, n, kr, icase, irep;
5072  static Int_t irota[12][8] = {
5073  {1,2,3,4,5,6,7,8}, {1,5,6,2,4,8,7,3}, {1,4,8,5,2,3,7,6},
5074  {3,7,8,4,2,6,5,1}, {3,2,6,7,4,1,5,8}, {3,4,1,2,7,8,5,6},
5075  {6,7,3,2,5,8,4,1}, {6,5,8,7,2,1,4,3}, {6,2,1,5,7,3,4,8},
5076  {8,4,3,7,5,1,2,6}, {8,5,1,4,7,6,2,3}, {8,7,6,5,4,3,2,1} };
5077  static Int_t iwhat[8] = { 63,62,54,26,50,9,1,0 };
5078  static Int_t ie[12] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
5079  static Int_t iface[6][4] = {
5080  {1,2,3,4}, {5,6,7,8}, {1,2,6,5}, {2,6,7,3}, {4,3,7,8}, {1,5,8,4} };
5081  static Int_t it1[4][3] = { {1,2,10}, {9,5,8}, {6,11,7}, {3,4,12} };
5082  static Int_t it2[4][3] = { {5,6,10}, {1,4,9}, {2,11,3}, {7,8,12} };
5083  static Int_t it3[6][3] = { {10,12,-3}, {-10,3,2}, {12,10,-1}, {-12,1,4},
5084  {9,5,8}, {6,11,7} };
5085  static Int_t it4[6][3] = { {11,9,-1}, {-11,1,2}, {9,11,-3}, {-9,3,4},
5086  {5,6,10}, {7,8,12} };
5087  static Int_t it5[10][3] = { {13,2,-11}, {-13,11,7}, {13,7,-6}, {-13,6,10},
5088  {13,10,1}, {13,1,-4}, {-13,4,12}, {13,12,-3}, {-13,3,2}, {5,8,9} };
5089  static Int_t it6[10][3] = { {13,2,-10}, {-13,10,5}, {13,5,-6}, {-13,6,11},
5090  {13,11,3}, {13,3,-4}, {-13,4,9}, {13,9,-1}, {-13,1,2}, {12,7,8} };
5091  static Int_t it7[12][3] = { {13,2,-11}, {-13,11,7}, {13,7,-6}, {-13,6,10},
5092  {13,10,-5}, {-13,5,8}, {13,8,-9}, {-13,9,1},
5093  {13,1,-4}, {-13,4,12}, {13,12,-3}, {-13,3,2} };
5094  static Int_t it8[6][3] = { {3,8,12}, {3,-2,-8}, {-2,5,-8}, {2,10,-5},
5095  {7,6,11}, {1,4,9} };
5096  static Int_t it9[10][3] = { {7,12,-3}, {-7,3,11}, {11,3,2}, {6,11,-2}, {-6,2,10},
5097  {6,10,5}, {7,6,-5}, {-7,5,8}, {7,8,12}, {1,4,9} };
5098  static Int_t it10[10][3] = { {9,1,-10}, {-9,10,5}, {9,5,8}, {4,9,-8}, {-4,8,12},
5099  {4,12,3}, {1,4,-3}, {-1,3,2}, {1,2,10}, {7,6,11} };
5100 
5101  nnod = 0;
5102  ntria = 0;
5103 
5104  // F I N D C O N F I G U R A T I O N T Y P E
5105  for ( nr=1 ; nr<=12 ; nr++ ) {
5106  k = 0;
5107  incr = 1;
5108  for ( nf=1 ; nf<=6 ; nf++ ) {
5109  f1 = fF8[irota[nr-1][iface[nf-1][0]-1]-1];
5110  f2 = fF8[irota[nr-1][iface[nf-1][1]-1]-1];
5111  f3 = fF8[irota[nr-1][iface[nf-1][2]-1]-1];
5112  f4 = fF8[irota[nr-1][iface[nf-1][3]-1]-1];
5113  if ((f1*f3-f2*f4)/(f1+f3-f2-f4) >= 0.) k = k + incr;
5114  incr = incr + incr;
5115  }
5116  for ( i=1 ; i<=8 ; i++ ) {
5117  if (k != iwhat[i-1]) continue;
5118  icase = i;
5119  kr = nr;
5120  goto L200;
5121  }
5122  }
5123  Error("MarchingCubeCase13", "configuration is not found");
5124  return;
5125 
5126  // R O T A T E C U B E
5127 L200:
5128  if (icase==1 || icase==8) goto L300;
5129  for ( n=1 ; n<=8 ; n++) {
5130  k = irota[kr-1][n-1];
5131  ff[n-1] = fF8[k-1];
5132  for ( i=1 ; i<=3 ; i++ ) {
5133  xyz[n-1][i-1] = fP8[k-1][i-1];
5134  grad[n-1][i-1] = fG8[k-1][i-1];
5135  }
5136  }
5137  for ( n=1 ; n<=8 ; n++ ) {
5138  fF8[n-1] = ff[n-1];
5139  for ( i=1 ; i<=3 ; i++ ) {
5140  fP8[n-1][i-1] = xyz[n-1][i-1];
5141  fG8[n-1][i-1] = grad[n-1][i-1];
5142  }
5143  }
5144 
5145  // S E T N O D E S & N O R M A L E S
5146 L300:
5147  nnod = 12;
5148  MarchingCubeFindNodes(nnod, ie, xyz, grad);
5149 
5150  // V A R I O U S C O N F I G U R A T I O N S
5151  switch ((int)icase) {
5152  case 1:
5153  ntria = 4;
5154  MarchingCubeSetTriangles(ntria, it1, itria);
5155  return;
5156  case 8:
5157  ntria = 4;
5158  MarchingCubeSetTriangles(ntria, it2, itria);
5159  return;
5160  case 2:
5161  ntria = 6;
5162  MarchingCubeSetTriangles(ntria, it3, itria);
5163  return;
5164  case 7:
5165  ntria = 6;
5166  MarchingCubeSetTriangles(ntria, it4, itria);
5167  return;
5168  case 3:
5169  nnod = 13;
5170  ntria = 10;
5171  MarchingCubeMiddlePoint(9, xyz, grad, it5,
5172  &xyz[nnod-1][0], &grad[nnod-1][0]);
5173  MarchingCubeSetTriangles(ntria, it5, itria);
5174  return;
5175  case 6:
5176  nnod = 13;
5177  ntria = 10;
5178  MarchingCubeMiddlePoint(9, xyz, grad, it6,
5179  &xyz[nnod-1][0], &grad[nnod-1][0]);
5180  MarchingCubeSetTriangles(ntria, it6, itria);
5181  return;
5182  case 5:
5183  nnod = 13;
5184  ntria = 12;
5185  MarchingCubeMiddlePoint(12, xyz, grad, it7,
5186  &xyz[nnod-1][0], &grad[nnod-1][0]);
5187  MarchingCubeSetTriangles(ntria, it7, itria);
5188  return;
5189  // 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 ?
5190  case 4:
5191  MarchingCubeSurfacePenetration(fF8[2], fF8[3], fF8[0], fF8[1],
5192  fF8[6], fF8[7], fF8[4], fF8[5], irep);
5193  switch ((int)(irep+1)) {
5194  case 1:
5195  ntria = 6;
5196  MarchingCubeSetTriangles(ntria, it8, itria);
5197  return;
5198  case 2:
5199  ntria = 10;
5200  MarchingCubeSetTriangles(ntria, it9, itria);
5201  return;
5202  case 3:
5203  ntria = 10;
5204  MarchingCubeSetTriangles(ntria, it10, itria);
5205  }
5206  }
5207 }
5208 
5209 
5210 ////////////////////////////////////////////////////////////////////////////////
5211 /// Set triangles (if parameter IALL=1, all edges will be visible)
5212 ///
5213 /// \param[in] ntria number of triangles
5214 /// \param[in] it triangles
5215 ///
5216 /// \param[out] itria triangles
5217 
5219  Int_t itria[48][3])
5220 {
5221  Int_t n, i, k;
5222 
5223  for ( n=1 ; n<=ntria ; n++ ) {
5224  for ( i=1 ; i<=3 ; i++ ) {
5225  k = it[n-1][i-1];
5226  itria[n-1][i-1] = k;
5227  }
5228  }
5229 }
5230 
5231 
5232 ////////////////////////////////////////////////////////////////////////////////
5233 /// Find middle point of a polygon
5234 ///
5235 /// \param[in] nnod number of nodes in the polygon
5236 /// \param[in] xyz node coordinates
5237 /// \param[in] grad node normales
5238 /// \param[in] it division of the polygons into triangles
5239 ///
5240 /// \param[out] pxyz middle point coordinates
5241 /// \param[out] pgrad middle point normale
5242 
5244  Double_t grad[52][3],
5245  Int_t it[][3], Double_t *pxyz,
5246  Double_t *pgrad)
5247 {
5248  Double_t p[3], g[3];
5249  Int_t i, n, k;
5250 
5251  for ( i=1 ; i<=3 ; i++ ) {
5252  p[i-1] = 0.;
5253  g[i-1] = 0.;
5254  }
5255  for ( n=1 ; n<=nnod ; n++ ) {
5256  k = it[n-1][2];
5257  if (k < 0) k =-k;
5258  for ( i=1 ; i<=3 ; i++ ) {
5259  p[i-1] = p[i-1] + xyz[k-1][i-1];
5260  g[i-1] = g[i-1] + grad[k-1][i-1];
5261  }
5262  }
5263  for ( i=1 ; i<=3 ; i++ ) {
5264  pxyz[i-1] = p[i-1] / nnod;
5265  pgrad[i-1] = g[i-1] / nnod;
5266  }
5267 }
5268 
5269 
5270 ////////////////////////////////////////////////////////////////////////////////
5271 /// Check for surface penetration ("bottle neck")
5272 ///
5273 /// \param[in] axx vertex values for 1st face
5274 /// \param[in] bxx vertex values for opposite face
5275 ///
5276 /// \param[out] irep 1,2: there is surface penetration, 0: there is not surface penetration
5277 
5279  Double_t a11, Double_t a01,
5280  Double_t b00, Double_t b10,
5281  Double_t b11, Double_t b01,
5282  Int_t &irep)
5283 {
5284  Double_t a, b, c, d, s0, s1, s2;
5285  Int_t iposa, iposb;
5286 
5287  irep = 0;
5288  a = (a11-a01)*(b00-b10) - (a00-a10)*(b11-b01);
5289  if (a == 0.) return;
5290  b = a01*(b00-b10)-(a11-a01)*b00-(a00-a10)*b01+a00*(b11-b01);
5291  c = a00*b01 - a01*b00;
5292  d = b*b-4*a*c;
5293  if (d <= 0.) return;
5294  d = TMath::Sqrt(d);
5295  if (TMath::Abs(-b+d) > TMath::Abs(2*a)) return;
5296  s1 = (-b+d) / (2*a);
5297  if (s1<0. || s1>1.) return;
5298  if (TMath::Abs(-b-d) > TMath::Abs(2*a)) return;
5299  s2 = (-b-d) / (2*a);
5300  if (s2<0. || s2>1.) return;
5301 
5302  // C A S E N O 4 ?
5303  iposa = 0;
5304  if (a00 >= 0) iposa = iposa + 1;
5305  if (a01 >= 0) iposa = iposa + 2;
5306  if (a10 >= 0) iposa = iposa + 4;
5307  if (a11 >= 0) iposa = iposa + 8;
5308  if (iposa==6 || iposa==9) goto L100;
5309  irep = 1;
5310  return;
5311 
5312  // N O T C A S E N O 4
5313 L100:
5314  s0 = (a00-a01) / (a00+a11-a10-a01);
5315  if (s1>=s0 && s2<s0) return;
5316  if (s1<s0 && s2>=s0) return;
5317  irep = 1;
5318  if (s1 >= s0) irep = 2;
5319 
5320  // C A S E S N O 10, 13 ?
5321  iposb = 0;
5322  if (b00 >= 0) iposb = iposb + 1;
5323  if (b01 >= 0) iposb = iposb + 2;
5324  if (b10 >= 0) iposb = iposb + 4;
5325  if (b11 >= 0) iposb = iposb + 8;
5326  if (iposb!=6 && iposb!=9) return;
5327  s0 = (b00-b01) / (b00+b11-b10-b01);
5328  if (iposa != iposb) goto L200;
5329  // C A S E N O 10
5330  if (irep==1 && s1>s0) return;
5331  if (irep==2 && s1<s0) return;
5332  irep = 0;
5333  return;
5334  // C A S E N O 13
5335 L200:
5336  if (irep==1 && s1<s0) return;
5337  if (irep==2 && s1>s0) return;
5338  irep = 0;
5339 }
5340 
5341 
5342 ////////////////////////////////////////////////////////////////////////////////
5343 /// Find nodes and normales
5344 ///
5345 /// \param[in] nnod number of nodes
5346 /// \param[in] ie edges which have section node
5347 ///
5348 /// \param[out] xyz nodes
5349 /// \param[out] grad ode normales (not normalized)
5350 
5352  Int_t *ie, Double_t xyz[52][3],
5353  Double_t grad[52][3])
5354 {
5355  Int_t n, k, i, n1, n2;
5356  Double_t t;
5357  static Int_t iedge[12][2] = {
5358  {1,2}, {2,3}, {3,4}, {4,1}, {5,6}, {6,7}, {7,8}, {8,5}, {1,5}, {2,6}, {3,7}, {4,8} };
5359 
5360  for ( n=1 ; n<=nnod ; n++ ) {
5361  k = ie[n-1];
5362  if (k < 0) k =-k;
5363  n1 = iedge[k-1][0];
5364  n2 = iedge[k-1][1];
5365  t = fF8[n1-1] / (fF8[n1-1]-fF8[n2-1]);
5366  for ( i=1 ; i<=3 ; i++ ) {
5367  xyz[n-1][i-1] = (fP8[n2-1][i-1]-fP8[n1-1][i-1])*t + fP8[n1-1][i-1];
5368  grad[n-1][i-1] = (fG8[n2-1][i-1]-fG8[n1-1][i-1])*t + fG8[n1-1][i-1];
5369  }
5370  }
5371 }
5372 
5373 
5374 ////////////////////////////////////////////////////////////////////////////////
5375 /// Z-depth algorithm for set of triangles
5376 ///
5377 /// \param[in] xyz nodes
5378 /// \param[in] nface number of triangular faces
5379 /// \param[in] iface faces (triangles)
5380 ///
5381 /// \param[in] dface array for min-max scopes
5382 /// \param[in] abcd array for face plane equations
5383 ///
5384 /// \param[out] iorder face order
5385 
5387  Int_t iface[48][3], Double_t dface[48][6],
5388  Double_t abcd[48][4], Int_t *iorder)
5389 {
5390  Int_t n, nf, i1, i2, i3, i, icur, k, itst, kface, kf, irep;
5391  Int_t nn[3], kk[3];
5392  Double_t wmin, wmax, a, b, c, q, zcur;
5393  Double_t v[2][3], abcdn[4], abcdk[4];
5394 
5395  // S E T I N I T I A L O R D E R
5396  // I G N O R E V E R Y S M A L L F A C E S
5397  // S E T M I N - M A X S C O P E S
5398  // S E T F A C E P L A N E E Q U A T I O N S
5399  nf = 0;
5400  for ( n=1 ; n<=nface ; n++ ) {
5401  i1 = TMath::Abs(iface[n-1][0]);
5402  i2 = TMath::Abs(iface[n-1][1]);
5403  i3 = TMath::Abs(iface[n-1][2]);
5404  // A R E A T E S T
5405  if (TMath::Abs(xyz[i2-1][0]-xyz[i1-1][0])<=kDel &&
5406  TMath::Abs(xyz[i2-1][1]-xyz[i1-1][1])<=kDel &&
5407  TMath::Abs(xyz[i2-1][2]-xyz[i1-1][2])<=kDel) continue;
5408  if (TMath::Abs(xyz[i3-1][0]-xyz[i2-1][0])<=kDel &&
5409  TMath::Abs(xyz[i3-1][1]-xyz[i2-1][1])<=kDel &&
5410  TMath::Abs(xyz[i3-1][2]-xyz[i2-1][2])<=kDel) continue;
5411  if (TMath::Abs(xyz[i1-1][0]-xyz[i3-1][0])<=kDel &&
5412  TMath::Abs(xyz[i1-1][1]-xyz[i3-1][1])<=kDel &&
5413  TMath::Abs(xyz[i1-1][2]-xyz[i3-1][2])<=kDel) continue;
5414  // P R O J E C T I O N T E S T
5415  if (TMath::Abs(xyz[i2-1][0]-xyz[i1-1][0])<=kDel &&
5416  TMath::Abs(xyz[i2-1][1]-xyz[i1-1][1])<=kDel &&
5417  TMath::Abs(xyz[i3-1][0]-xyz[i2-1][0])<=kDel &&
5418  TMath::Abs(xyz[i3-1][1]-xyz[i2-1][1])<=kDel &&
5419  TMath::Abs(xyz[i1-1][0]-xyz[i3-1][0])<=kDel &&
5420  TMath::Abs(xyz[i1-1][1]-xyz[i3-1][1])<=kDel) continue;
5421  nf = nf + 1;
5422  iorder[nf-1] = n;
5423  // F I N D M I N - M A X
5424  for ( i=1 ; i<=3 ; i++ ) {
5425  wmin = xyz[i1-1][i-1];
5426  wmax = xyz[i1-1][i-1];
5427  if (wmin > xyz[i2-1][i-1]) wmin = xyz[i2-1][i-1];
5428  if (wmax < xyz[i2-1][i-1]) wmax = xyz[i2-1][i-1];
5429  if (wmin > xyz[i3-1][i-1]) wmin = xyz[i3-1][i-1];
5430  if (wmax < xyz[i3-1][i-1]) wmax = xyz[i3-1][i-1];
5431  dface[n-1][i-1] = wmin;
5432  dface[n-1][i+2] = wmax;
5433  }
5434  // F I N D F A C E E Q U A T I O N
5435  for ( i=1 ; i<=3 ; i++ ) {
5436  v[0][i-1] = xyz[i2-1][i-1] - xyz[i1-1][i-1];
5437  v[1][i-1] = xyz[i3-1][i-1] - xyz[i2-1][i-1];
5438  }
5439  a = (v[0][1]*v[1][2] - v[0][2]*v[1][1]);
5440  b = (v[0][2]*v[1][0] - v[0][0]*v[1][2]);
5441  c = (v[0][0]*v[1][1] - v[0][1]*v[1][0]);
5442  q = TMath::Sqrt(a*a+b*b+c*c);
5443  if (c < 0.) q =-q;
5444  a = a / q;
5445  b = b / q;
5446  c = c / q;
5447  abcd[n-1][0] = a;
5448  abcd[n-1][1] = b;
5449  abcd[n-1][2] = c;
5450  abcd[n-1][3] =-(a*xyz[i1-1][0] + b*xyz[i1-1][1] + c*xyz[i1-1][2]);
5451  }
5452  nface = nf;
5453  if (nf <= 1) return;
5454 
5455  // S O R T T R I A N G L E S A L O N G Z - M I N
5456  for ( icur=2 ; icur<=nface ; icur++ ) {
5457  k = iorder[icur-1];
5458  zcur = dface[k-1][2];
5459  for ( itst=icur-1 ; itst>=1 ; itst-- ) {
5460  k = iorder[itst-1];
5461  if (zcur < dface[k-1][2]) break;
5462  k = iorder[itst-1];
5463  iorder[itst-1] = iorder[itst];
5464  iorder[itst] = k;
5465  }
5466  }
5467 
5468  // Z - D E P T H A L G O R I T H M
5469  kface = nface;
5470 L300:
5471  if (kface == 1) goto L900;
5472  nf = iorder[kface-1];
5473  if (nf < 0) nf =-nf;
5474  abcdn[0] = abcd[nf-1][0];
5475  abcdn[1] = abcd[nf-1][1];
5476  abcdn[2] = abcd[nf-1][2];
5477  abcdn[3] = abcd[nf-1][3];
5478  nn[0] = TMath::Abs(iface[nf-1][0]);
5479  nn[1] = TMath::Abs(iface[nf-1][1]);
5480  nn[2] = TMath::Abs(iface[nf-1][2]);
5481 
5482  // I N T E R N A L L O O P
5483  for ( k=kface-1 ; k>=1 ; k-- ) {
5484  kf = iorder[k-1];
5485  if (kf < 0) kf =-kf;
5486  if (dface[nf-1][5] > dface[kf-1][2]+kDel) goto L400;
5487  if (iorder[k-1] > 0) goto L900;
5488  goto L800;
5489 
5490  // M I N - M A X T E S T
5491 L400:
5492  if (dface[kf-1][0] >= dface[nf-1][3]-kDel) goto L800;
5493  if (dface[kf-1][3] <= dface[nf-1][0]+kDel) goto L800;
5494  if (dface[kf-1][1] >= dface[nf-1][4]-kDel) goto L800;
5495  if (dface[kf-1][4] <= dface[nf-1][1]+kDel) goto L800;
5496 
5497  // K F B E F O R E N F ?
5498  kk[0] = TMath::Abs(iface[kf-1][0]);
5499  kk[1] = TMath::Abs(iface[kf-1][1]);
5500  kk[2] = TMath::Abs(iface[kf-1][2]);
5501  if (abcdn[0]*xyz[kk[0]-1][0]+abcdn[1]*xyz[kk[0]-1][1]+
5502  abcdn[2]*xyz[kk[0]-1][2]+abcdn[3] < -kDel) goto L500;
5503  if (abcdn[0]*xyz[kk[1]-1][0]+abcdn[1]*xyz[kk[1]-1][1]+
5504  abcdn[2]*xyz[kk[1]-1][2]+abcdn[3] < -kDel) goto L500;
5505  if (abcdn[0]*xyz[kk[2]-1][0]+abcdn[1]*xyz[kk[2]-1][1]+
5506  abcdn[2]*xyz[kk[2]-1][2]+abcdn[3] < -kDel) goto L500;
5507  goto L800;
5508 
5509  // N F A F T E R K F ?
5510 L500:
5511  abcdk[0] = abcd[kf-1][0];
5512  abcdk[1] = abcd[kf-1][1];
5513  abcdk[2] = abcd[kf-1][2];
5514  abcdk[3] = abcd[kf-1][3];
5515  if (abcdk[0]*xyz[nn[0]-1][0]+abcdk[1]*xyz[nn[0]-1][1]+
5516  abcdk[2]*xyz[nn[0]-1][2]+abcdk[3] > kDel) goto L600;
5517  if (abcdk[0]*xyz[nn[1]-1][0]+abcdk[1]*xyz[nn[1]-1][1]+
5518  abcdk[2]*xyz[nn[1]-1][2]+abcdk[3] > kDel) goto L600;
5519  if (abcdk[0]*xyz[nn[2]-1][0]+abcdk[1]*xyz[nn[2]-1][1]+
5520  abcdk[2]*xyz[nn[2]-1][2]+abcdk[3] > kDel) goto L600;
5521  goto L800;
5522 
5523  // E D G E B Y E D G E T E S T
5524  // K F - E D G E S A G A I N S T N F
5525 L600:
5526  for ( i=1 ; i<=3 ; i++ ) {
5527  i1 = kk[i-1];
5528  i2 = kk[0];
5529  if (i != 3) i2 = kk[i];
5530  TestEdge(kDel, xyz, i1, i2, nn, abcdn, irep);
5531  if ( irep<0 ) goto L700;
5532  if ( irep==0 ) continue;
5533  if ( irep>0 ) goto L800;
5534  }
5535  // N F - E D G E S A G A I N S T K F
5536  for ( i=1 ; i<=3 ; i++ ) {
5537  i1 = nn[i-1];
5538  i2 = nn[0];
5539  if (i != 3) i2 = nn[i];
5540  TestEdge(kDel, xyz, i1, i2, kk, abcdk, irep);
5541  if ( irep<0 ) goto L800;
5542  if ( irep==0 ) continue;
5543  if ( irep>0 ) goto L700;
5544  }
5545  goto L800;
5546 
5547  // C H A N G E F A C E O R D E R
5548 L700:
5549  kf = iorder[k-1];
5550  for ( i=k+1 ; i<=kface ; i++ ) {
5551  iorder[i-2] = iorder[i-1];
5552  }
5553  iorder[kface-1] =-kf;
5554  if (kf > 0) goto L300;
5555  goto L900;
5556 L800:
5557  continue;
5558  }
5559 
5560  // N E X T F A C E
5561 L900:
5562  if (iorder[kface-1] < 0) iorder[kface-1] =-iorder[kface-1];
5563  kface = kface - 1;
5564  if (kface > 0) goto L300;
5565 }
5566 
5567 
5568 ////////////////////////////////////////////////////////////////////////////////
5569 /// Test edge against face (triangle)
5570 ///
5571 /// \param[in] del precision
5572 /// \param[in] xyz nodes
5573 /// \param[in] i1 1-st node of edge
5574 /// \param[in] i2 2-nd node of edge
5575 /// \param[in] iface triangular face
5576 /// \param[in] abcd face plane
5577 ///
5578 /// \param[out] irep 1: edge under face, 0: no decision, +1: edge before face
5579 
5581  Int_t iface[3], Double_t abcd[4], Int_t &irep)
5582 {
5583  Int_t k, k1, k2, ixy, i;
5584  Double_t a, b, c, d1, d2, dd, xy, tmin, tmax, tmid, x, y, z;
5585  Double_t d[3], delta[3], t[2];
5586 
5587  irep = 0;
5588 
5589  // F I N D I N T E R S E C T I O N P O I N T S
5590  delta[0] = xyz[i2-1][0] - xyz[i1-1][0];
5591  delta[1] = xyz[i2-1][1] - xyz[i1-1][1];
5592  delta[2] = xyz[i2-1][2] - xyz[i1-1][2];
5593  if (TMath::Abs(delta[0])<=del && TMath::Abs(delta[1])<=del) return;
5594  ixy = 1;
5595  if (TMath::Abs(delta[1]) > TMath::Abs(delta[0])) ixy = 2;
5596  a = delta[1];
5597  b =-delta[0];
5598  c =-(a*xyz[i1-1][0] + b*xyz[i1-1][1]);
5599  d[0] = a*xyz[iface[0]-1][0] + b*xyz[iface[0]-1][1] + c;
5600  d[1] = a*xyz[iface[1]-1][0] + b*xyz[iface[1]-1][1] + c;
5601  d[2] = a*xyz[iface[2]-1][0] + b*xyz[iface[2]-1][1] + c;
5602  k = 0;
5603  for ( i=1 ; i<=3 ; i++ ) {
5604  k1 = i;
5605  k2 = i + 1;
5606  if (i == 3) k2 = 1;
5607  if (d[k1-1]>=0. && d[k2-1]>=0.) continue;
5608  if (d[k1-1] <0. && d[k2-1] <0.) continue;
5609  d1 = d[k1-1] / (d[k1-1] - d[k2-1]);
5610  d2 = d[k2-1] / (d[k1-1] - d[k2-1]);
5611  xy = d1*xyz[iface[k2-1]-1][ixy-1] - d2*xyz[iface[k1-1]-1][ixy-1];
5612  k = k + 1;
5613  t[k-1] = (xy-xyz[i1-1][ixy-1]) / delta[ixy-1];
5614  if (k == 2) goto L200;
5615  }
5616  return;
5617 
5618  // C O M P A R E Z - D E P T H
5619 L200:
5620  tmin = TMath::Min(t[0],t[1]);
5621  tmax = TMath::Max(t[0],t[1]);
5622  if (tmin>1. || tmax<0) return;
5623  if (tmin < 0.) tmin = 0.;
5624  if (tmax > 1.) tmax = 1.;
5625  tmid = (tmin + tmax) / 2.;
5626  x = delta[0]*tmid + xyz[i1-1][0];
5627  y = delta[1]*tmid + xyz[i1-1][1];
5628  z = delta[2]*tmid + xyz[i1-1][2];
5629  dd = abcd[0]*x + abcd[1]*y + abcd[2]*z + abcd[3];
5630  if (dd > del) goto L997;
5631  if (dd <-del) goto L998;
5632  return;
5633 
5634 L997:
5635  irep =+1;
5636  return;
5637 L998:
5638  irep =-1;
5639 }
5640 
5641 
5642 ////////////////////////////////////////////////////////////////////////////////
5643 /// Draw set of isosurfaces for a scalar function defined on a grid.
5644 ///
5645 /// \param[in] ns number of isosurfaces
5646 /// \param[in] s isosurface values
5647 /// \param[in] nx number of slices along X
5648 /// \param[in] ny number of slices along Y
5649 /// \param[in] nz number of slices along Z
5650 /// \param[in] x slices along X
5651 /// \param[in] y slices along Y
5652 /// \param[in] z slices along Z
5653 ///
5654 /// - chopt` = 'BF' from BACK to FRONT
5655 /// - chopt` = 'FB' from FRONT to BACK
5656 
5658  Int_t ny, Int_t nz,
5659  Double_t *x, Double_t *y, Double_t *z,
5660  const char *chopt)
5661 {
5662  Double_t p[8][3], pf[8], pn[8][3];
5663  Double_t p0[3], p1[3], p2[3], p3[3], t[3];
5664  Double_t fsurf, w, d1, d2, df1, df2;
5665  Int_t icodes[3];
5666  Int_t i, i1, i2, j, ibase, nnod, knod, ntria, ktria, iopt, iready;
5667  Int_t ixcrit, iycrit, izcrit, incrx, incry, incrz, incr;
5668  Int_t ix, ix1=0, ix2=0, iy, iy1=0, iy2=0, iz, iz1=0, iz2=0, k, kx, ky, kz, isurf, nsurf;
5669 
5670  Double_t xyz[kNmaxp][3], xyzn[kNmaxp][3], grad[kNmaxp][3];
5671  Double_t dtria[kNmaxt][6], abcd[kNmaxt][4];
5672  Int_t itria[kNmaxt][3], iorder[kNmaxt], iattr[kNmaxt];
5673 
5674  static Int_t ind[8][3] = { { 0,0,0 }, { 1,0,0 }, { 1,0,1 }, { 0,0,1 },
5675  { 0,1,0 }, { 1,1,0 }, { 1,1,1 }, { 0,1,1 } };
5676  for (i=0;i<kNmaxp;i++) {
5677  xyzn[i][0] = 0.;
5678  xyzn[i][1] = 0.;
5679  xyzn[i][2] = 0.;
5680  }
5681 
5682  TView *view = 0;
5683 
5684  if (gPad) view = gPad->GetView();
5685  if (!view) {
5686  Error("ImplicitFunction", "no TView in current pad");
5687  return;
5688  }
5689 
5690  nsurf = ns;
5691  if (nsurf > kNiso) {
5692  Warning("IsoSurface","Number of isosurfaces too large. Increase kNiso");
5693  }
5694  iopt = 2;
5695  if (*chopt == 'B' || *chopt == 'b') iopt = 1;
5696 
5697  // F I N D X - , Y - , Z - C R I T I C A L
5698  // This logic works for parallel projection only.
5699  // For central projection another logic should be implemented.
5700  p0[0] = x[0];
5701  p0[1] = y[0];
5702  p0[2] = z[0];
5703  view->WCtoNDC(p0, p0);
5704  p1[0] = x[nx-1];
5705  p1[1] = y[0];
5706  p1[2] = z[0];
5707  view->WCtoNDC(p1, p1);
5708  p2[0] = x[0];
5709  p2[1] = y[ny-1];
5710  p2[2] = z[0];
5711  view->WCtoNDC(p2, p2);
5712  p3[0] = x[0];
5713  p3[1] = y[0];
5714  p3[2] = z[nz-1];
5715  view->WCtoNDC(p3, p3);
5716  ixcrit = nx;
5717  iycrit = ny;
5718  izcrit = nz;
5719  if (p1[2] < p0[2]) ixcrit = 1;
5720  if (p2[2] < p0[2]) iycrit = 1;
5721  if (p3[2] < p0[2]) izcrit = 1;
5722 
5723  // L O O P A L O N G G R I D
5724  // This logic works for both (parallel & central) projections.
5725  incrx = 1;
5726  incry = 1;
5727  incrz = 1;
5728 L110:
5729  if (incrz >= 0) {
5730  if (iopt == 1) iz1 = 1;
5731  if (iopt == 1) iz2 = izcrit-1;
5732  if (iopt == 2) iz1 = izcrit;
5733  if (iopt == 2) iz2 = nz - 1;
5734  } else {
5735  if (iopt == 1) iz1 = nz - 1;
5736  if (iopt == 1) iz2 = izcrit;
5737  if (iopt == 2) iz1 = izcrit-1;
5738  if (iopt == 2) iz2 = 1;
5739  }
5740  for (iz = iz1; incrz < 0 ? iz >= iz2 : iz <= iz2; iz += incrz) {
5741 L120:
5742  if (incry >= 0) {
5743  if (iopt == 1) iy1 = 1;
5744  if (iopt == 1) iy2 = iycrit-1;
5745  if (iopt == 2) iy1 = iycrit;
5746  if (iopt == 2) iy2 = ny - 1;
5747  } else {
5748  if (iopt == 1) iy1 = ny - 1;
5749  if (iopt == 1) iy2 = iycrit;
5750  if (iopt == 2) iy1 = iycrit-1;
5751  if (iopt == 2) iy2 = 1;
5752  }
5753  for (iy = iy1; incry < 0 ? iy >= iy2 : iy <= iy2; iy += incry) {
5754 L130:
5755  if (incrx >= 0) {
5756  if (iopt == 1) ix1 = 1;
5757  if (iopt == 1) ix2 = ixcrit-1;
5758  if (iopt == 2) ix1 = ixcrit;
5759  if (iopt == 2) ix2 = nx - 1;
5760  } else {
5761  if (iopt == 1) ix1 = nx - 1;
5762  if (iopt == 1) ix2 = ixcrit;
5763  if (iopt == 2) ix1 = ixcrit-1;
5764  if (iopt == 2) ix2 = 1;
5765  }
5766  for (ix = ix1; incrx < 0 ? ix >= ix2 : ix <= ix2; ix += incrx) {
5767  nnod = 0;
5768  ntria = 0;
5769  iready = 0;
5770  for ( isurf=1 ; isurf<=nsurf ; isurf++ ) {
5771  fsurf = s[isurf-1];
5772  if (gCurrentHist->GetBinContent(ix, iy, iz) >= fsurf)
5773  goto L210;
5774  if (gCurrentHist->GetBinContent(ix+1,iy, iz) >= fsurf)
5775  goto L220;
5776  if (gCurrentHist->GetBinContent(ix, iy+1,iz) >= fsurf)
5777  goto L220;
5778  if (gCurrentHist->GetBinContent(ix+1,iy+1,iz) >= fsurf)
5779  goto L220;
5780  if (gCurrentHist->GetBinContent(ix, iy, iz+1) >= fsurf)
5781  goto L220;
5782  if (gCurrentHist->GetBinContent(ix+1,iy, iz+1) >= fsurf)
5783  goto L220;
5784  if (gCurrentHist->GetBinContent(ix, iy+1,iz+1) >= fsurf)
5785  goto L220;
5786  if (gCurrentHist->GetBinContent(ix+1,iy+1,iz+1) >= fsurf)
5787  goto L220;
5788  continue;
5789 L210:
5790  if (gCurrentHist->GetBinContent(ix+1,iy, iz) < fsurf)
5791  goto L220;
5792  if (gCurrentHist->GetBinContent(ix, iy+1,iz) < fsurf)
5793  goto L220;
5794  if (gCurrentHist->GetBinContent(ix+1,iy+1,iz) < fsurf)
5795  goto L220;
5796  if (gCurrentHist->GetBinContent(ix, iy, iz+1) < fsurf)
5797  goto L220;
5798  if (gCurrentHist->GetBinContent(ix+1,iy, iz+1) < fsurf)
5799  goto L220;
5800  if (gCurrentHist->GetBinContent(ix, iy+1,iz+1) < fsurf)
5801  goto L220;
5802  if (gCurrentHist->GetBinContent(ix+1,iy+1,iz+1) < fsurf)
5803  goto L220;
5804  continue;
5805 
5806  // P R E P A R E C U B E ( P A R A L L E P I P E D )
5807 L220:
5808  if (iready !=0) goto L310;
5809  iready = 1;
5810  for ( i=1 ; i<=8 ; i++ ) {
5811  kx = ix + ind[i-1][0];
5812  ky = iy + ind[i-1][1];
5813  kz = iz + ind[i-1][2];
5814  p[i-1][0] = x[kx-1];
5815  p[i-1][1] = y[ky-1];
5816  p[i-1][2] = z[kz-1];
5817  pf[i-1] = gCurrentHist->GetBinContent(kx,ky,kz);
5818  // F I N D X - G R A D I E N T
5819  if (kx == 1) {
5820  pn[i-1][0] = (gCurrentHist->GetBinContent(2,ky,kz) -
5821  gCurrentHist->GetBinContent(1,ky,kz)) /
5822  (x[1]-x[0]);
5823  } else if (kx == nx) {
5824  pn[i-1][0] = (gCurrentHist->GetBinContent(kx,ky,kz) -
5825  gCurrentHist->GetBinContent(kx-1,ky,kz)) /
5826  (x[kx-1]-x[kx-2]);
5827  } else {
5828  d1 = x[kx-1] - x[kx-2];
5829  d2 = x[kx] - x[kx-1];
5830  if (d1 == d2) {
5831  pn[i-1][0] = (gCurrentHist->GetBinContent(kx+1,ky,kz) -
5832  gCurrentHist->GetBinContent(kx-1,ky,kz)) /
5833  (d1+d1);
5834  } else {
5835  df1 = gCurrentHist->GetBinContent(kx,ky,kz) -
5836  gCurrentHist->GetBinContent(kx-1,ky,kz);
5837  df2 = gCurrentHist->GetBinContent(kx+1,ky,kz) -
5838  gCurrentHist->GetBinContent(kx,ky,kz);
5839  pn[i-1][0] = (df1*d2*d2+df2*d1*d1)/(d1*d2*d2+d2*d1*d1);
5840  }
5841  }
5842  // F I N D Y - G R A D I E N T
5843  if (ky == 1) {
5844  pn[i-1][1] = (gCurrentHist->GetBinContent(kx,2,kz) -
5845  gCurrentHist->GetBinContent(kx,1,kz)) /
5846  (y[1]-y[0]);
5847  } else if (ky == ny) {
5848  pn[i-1][1] = (gCurrentHist->GetBinContent(kx,ky,kz) -
5849  gCurrentHist->GetBinContent(kx,ky-1,kz)) /
5850  (y[ky-1]-y[ky-2]);
5851  } else {
5852  d1 = y[ky-1] - y[ky-2];
5853  d2 = y[ky] - y[ky-1];
5854  if (d1 == d2) {
5855  pn[i-1][1] = (gCurrentHist->GetBinContent(kx,ky+1,kz) -
5856  gCurrentHist->GetBinContent(kx,ky-1,kz)) /
5857  (d1+d1);
5858  } else {
5859  df1 = gCurrentHist->GetBinContent(kx,ky,kz) -
5860  gCurrentHist->GetBinContent(kx,ky-1,kz);
5861  df2 = gCurrentHist->GetBinContent(kx,ky+1,kz) -
5862  gCurrentHist->GetBinContent(kx,ky,kz);
5863  pn[i-1][1] = (df1*d2*d2+df2*d1*d1)/(d1*d2*d2+d2*d1*d1);
5864  }
5865  }
5866  // F I N D Z - G R A D I E N T
5867  if (kz == 1) {
5868  pn[i-1][2] = (gCurrentHist->GetBinContent(kx,ky,2) -
5869  gCurrentHist->GetBinContent(kx,ky,1)) /
5870  (z[1]-z[0]);
5871  } else if (kz == nz) {
5872  pn[i-1][2] = (gCurrentHist->GetBinContent(kx,ky,kz) -
5873  gCurrentHist->GetBinContent(kx,ky,kz-1)) /
5874  (z[kz-1]-z[kz-2]);
5875  } else {
5876  d1 = z[kz-1] - z[kz-2];
5877  d2 = z[kz] - z[kz-1];
5878  if (d1 == d2) {
5879  pn[i-1][2] = (gCurrentHist->GetBinContent(kx,ky,kz+1) -
5880  gCurrentHist->GetBinContent(kx,ky,kz-1)) /
5881  (d1+d1);
5882  } else {
5883  df1 = gCurrentHist->GetBinContent(kx,ky,kz) -
5884  gCurrentHist->GetBinContent(kx,ky,kz-1);
5885  df2 = gCurrentHist->GetBinContent(kx,ky,kz+1) -
5886  gCurrentHist->GetBinContent(kx,ky,kz);
5887  pn[i-1][2] = (df1*d2*d2+df2*d1*d1)/(d1*d2*d2+d2*d1*d1);
5888  }
5889  }
5890  }
5891 
5892  // F I N D S E T O F T R I A N G L E S
5893 L310:
5894  Double_t xyz_tmp[kNmaxp][3], grad_tmp[kNmaxp][3];
5895  Int_t itria_tmp[kNmaxt][3], l;
5896 
5897  MarchingCube(s[isurf-1], p, pf, pn, knod, ktria,
5898  xyz_tmp, grad_tmp, itria_tmp);
5899 
5900  for( l=0 ; l<knod ; l++) {
5901  xyz[nnod+l][0] = xyz_tmp[l][0];
5902  xyz[nnod+l][1] = xyz_tmp[l][1];
5903  xyz[nnod+l][2] = xyz_tmp[l][2];
5904  grad[nnod+l][0] = grad_tmp[l][0];
5905  grad[nnod+l][1] = grad_tmp[l][1];
5906  grad[nnod+l][2] = grad_tmp[l][2];
5907  }
5908  for( l=0 ; l<ktria ; l++) {
5909  itria[ntria+l][0] = itria_tmp[l][0];
5910  itria[ntria+l][1] = itria_tmp[l][1];
5911  itria[ntria+l][2] = itria_tmp[l][2];
5912  }
5913 
5914  for ( i=ntria+1 ; i<=ntria+ktria ; i++ ) {
5915  for ( j=1 ; j<=3 ; j++ ){
5916  ibase = nnod;
5917  if (itria[i-1][j-1] < 0) ibase =-nnod;
5918  itria[i-1][j-1] = itria[i-1][j-1] + ibase;
5919  }
5920  iattr[i-1] = isurf;
5921  }
5922  nnod = nnod + knod;
5923  ntria = ntria + ktria;
5924  }
5925 
5926  // D E P T H S O R T, D R A W I N G
5927  if (ntria == 0) continue;
5928  for ( i=1 ; i<=nnod ; i++ ) {
5929  view->WCtoNDC(&xyz[i-1][0], &xyzn[i-1][0]);
5930  Luminosity(&grad[i-1][0], w);
5931  grad[i-1][0] = w;
5932  }
5933  ZDepth(xyzn, ntria, itria, dtria, abcd, (Int_t*)iorder);
5934  if (ntria == 0) continue;
5935  incr = 1;
5936  if (iopt == 1) incr = -1;
5937  i1 = 1;
5938  if (incr == -1) i1 = ntria;
5939  i2 = ntria - i1 + 1;
5940  for (i = i1; incr < 0 ? i >= i2 : i <= i2; i += incr) {
5941  k = iorder[i-1];
5942  t[0] = grad[TMath::Abs(itria[k-1][0])-1][0];
5943  t[1] = grad[TMath::Abs(itria[k-1][1])-1][0];
5944  t[2] = grad[TMath::Abs(itria[k-1][2])-1][0];
5945  icodes[0] = iattr[k-1];
5946  icodes[1] = iattr[k-1];
5947  icodes[2] = iattr[k-1];
5948  DrawFaceGouraudShaded(icodes, xyz, 3, &itria[k-1][0], t);
5949  }
5950  }
5951  incrx = -incrx;
5952  if (incrx < 0) goto L130;
5953  }
5954  incry = -incry;
5955  if (incry < 0) goto L120;
5956  }
5957  incrz = -incrz;
5958  if (incrz < 0) goto L110;
5959 }
5960 
5961 ////////////////////////////////////////////////////////////////////////////////
5962 /// Draw the faces for the Gouraud Shaded Iso surfaces
5963 
5965  Double_t xyz[][3],
5966  Int_t np, Int_t *iface,
5967  Double_t *t)
5968 {
5969  Int_t i, k, irep;
5970  Double_t p3[12][3];
5971  TView *view = 0;
5972 
5973  if (gPad) view = gPad->GetView();
5974  if (!view) {
5975  Error("ImplicitFunction", "no TView in current pad");
5976  return;
5977  }
5978 
5979  if (icodes[0]==1) Spectrum(fNcolor, fFmin, fFmax, fIc1, 1, irep);
5980  if (icodes[0]==2) Spectrum(fNcolor, fFmin, fFmax, fIc2, 1, irep);
5981  if (icodes[0]==3) Spectrum(fNcolor, fFmin, fFmax, fIc3, 1, irep);
5982  for ( i=1 ; i<=np ; i++) {
5983  k = iface[i-1];
5984  if (k<0) k = -k;
5985  view->WCtoNDC(&xyz[k-1][0], &p3[i-1][0]);
5986  }
5987  FillPolygon(np, (Double_t *)p3, (Double_t *)t);
5988 }
const int nx
Definition: kalman.C:16
static Double_t gV[kVSizeMax]
for(Int_t i=0;i< n;i++)
Definition: legend1.C:18
virtual void NormalWCtoNDC(const Float_t *pw, Float_t *pn)=0
void SideVisibilityEncode(Int_t iopt, Double_t phi1, Double_t phi2, Double_t &val)
Encode side visibilities and order along R for sector.
virtual void SetLineWidth(Width_t lwidth)
Definition: TAttLine.h:57
Hparam_t Hparam
void SurfaceProperty(Double_t qqa, Double_t qqd, Double_t qqs, Int_t nnqs, Int_t &irep)
Set surface property coefficients.
float xmin
Definition: THbookFile.cxx:93
const Int_t kVSizeMax
void MarchingCubeCase12(Int_t &nnod, Int_t &ntria, Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
Consider case No 12.
void MarchingCubeCase00(Int_t k1, Int_t k2, Int_t k3, Int_t k4, Int_t k5, Int_t k6, Int_t &nnod, Int_t &ntria, Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
Consideration of trivial cases: 1,2,5,8,9,11,14.
Int_t yfirst
first bin number along Y
Definition: Hparam.h:47
void LegoCartesian(Double_t ang, Int_t nx, Int_t ny, const char *chopt)
Draw stack of lego-plots in cartesian coordinates.
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4629
const Double_t kDel
Double_t factor
multiplication factor (normalization)
Definition: Hparam.h:41
static Int_t ProjectAitoff2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
void MarchingCubeCase06(Int_t &nnod, Int_t &ntria, Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
Consider case No 6.
void MarchingCubeSetTriangles(Int_t ntria, Int_t it[][3], Int_t itria[48][3])
Set triangles (if parameter IALL=1, all edges will be visible)
static double p3(double t, double a, double b, double c, double d)
short Style_t
Definition: RtypesCore.h:76
void SetColorDark(Color_t color, Int_t n=0)
Store dark color for stack number n.
void 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)
Decode side visibilities and order along R for sector.
TVirtualHistPainter * GetPainter(Option_t *option="")
return pointer to painter if painter does not exist, it is created
Definition: TH1.cxx:4096
Histogram option structure.
Definition: Hoption.h:24
const double a11[11]
Definition: RooMath.cxx:491
virtual void WCtoNDC(const Float_t *pw, Float_t *pn)=0
float Float_t
Definition: RtypesCore.h:53
const Int_t kF3LineColor
virtual Double_t * GetRmax()=0
virtual TList * GetStack() const =0
float ymin
Definition: THbookFile.cxx:93
int Proj
1: Aitoff, 2: Mercator, 3: Sinusoidal, 4: Parabolic
Definition: Hoption.h:59
void MarchingCubeFindNodes(Int_t nnod, Int_t *ie, Double_t xyz[52][3], Double_t grad[52][3])
Find nodes and normales.
R__EXTERN TStyle * gStyle
Definition: TStyle.h:423
int Logy
log scale in Y. Also set by histogram option
Definition: Hoption.h:68
static void Optimize(Double_t A1, Double_t A2, Int_t nold, Double_t &BinLow, Double_t &BinHigh, Int_t &nbins, Double_t &BWID, Option_t *option="")
static function to compute reasonable axis limits
See TView3D.
Definition: TView.h:36
virtual ~TPainter3dAlgorithms()
Lego default destructor.
void InitRaster(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Int_t nx, Int_t ny)
Initialize hidden lines removal algorithm (RASTER SCREEN)
void DrawFaceMove3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 3rd variant for "MOVING SCREEN" algorithm (draw level lines only)
const Double_t kFdel
void SurfaceFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Service function for Surfaces.
virtual Double_t GetBinLowEdge(Int_t bin) const
Return low edge of bin.
Definition: TAxis.cxx:489
#define gROOT
Definition: TROOT.h:340
virtual void SetRange(const Double_t *min, const Double_t *max)=0
void ColorFunction(Int_t nl, Double_t *fl, Int_t *icl, Int_t &irep)
Set correspondance between function and color levels.
void MarchingCubeCase03(Int_t &nnod, Int_t &ntria, Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
Consider case No 3.
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:170
int Int_t
Definition: RtypesCore.h:41
TArc * a
Definition: textangle.C:12
static void HLStoRGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Definition: TColor.h:76
virtual Double_t GetBinWidth(Int_t bin) const
Return bin width.
Definition: TAxis.cxx:511
void FindVisibleDraw(Double_t *r1, Double_t *r2)
Find visible parts of line (draw line)
virtual void SetFillStyle(Style_t fstyle)
Definition: TAttFill.h:52
int nbins[3]
void MarchingCubeCase10(Int_t &nnod, Int_t &ntria, Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
Consider case No 10.
Double_t zmin
minimum value along Z
Definition: Hparam.h:39
virtual void Modify()
Change current line attributes if necessary.
Definition: TAttLine.cxx:229
Double_t ymin
minimum value along y
Definition: Hparam.h:35
Double_t zmax
maximum value along Z
Definition: Hparam.h:40
void InitMoveScreen(Double_t xmin, Double_t xmax)
Initialize "MOVING SCREEN" method.
TLatex * t1
Definition: textangle.C:20
static Double_t gTT[4 *kVSizeMax]
int Logx
log scale in X. Also set by histogram option
Definition: Hoption.h:67
Bool_t GetHistMinimumZero() const
Definition: TStyle.h:246
Short_t Abs(Short_t d)
Definition: TMathBase.h:110
virtual TObject * At(Int_t idx) const
Returns the object at position idx. Returns 0 if idx is out of range.
Definition: TList.cxx:310
Double_t ymax
maximum value along y
Definition: Hparam.h:36
static Int_t ProjectMercator2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function.
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Definition: TMath.h:501
Float_t GetLegoInnerR() const
Definition: TStyle.h:248
static void SetF3(TF3 *f3)
Static function Store pointer to current implicit function.
Hoption_t Hoption
void DefineGridLevels(Int_t ndivz)
Define the grid levels drawn in the background of surface and lego plots.
void LegoPolar(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
Draw stack of lego-plots in polar coordinates.
void TestEdge(Double_t del, Double_t xyz[52][3], Int_t i1, Int_t i2, Int_t iface[3], Double_t abcd[4], Int_t &irep)
Test edge against face (triangle)
static const double x2[5]
ClassImp(TPainter3dAlgorithms) TPainter3dAlgorithms
Lego default constructor.
Fill Area Attributes class.
Definition: TAttFill.h:32
Double_t x[n]
Definition: legend1.C:17
int Surf
"SURF" Draw as a Surface (SURF,Surf=1, SURF1,Surf=11, SURF2,Surf=12)
Definition: Hoption.h:48
void DrawFaceMode3(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 3rd option (draw face for stacked lego plot)
void DrawFaceRaster1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "RASTER SCREEN" algorithm (draw face with level lines) ...
TText * tt
Definition: textangle.C:16
void LightSource(Int_t nl, Double_t yl, Double_t xscr, Double_t yscr, Double_t zscr, Int_t &irep)
Set light source.
const int ny
Definition: kalman.C:17
virtual void Modify()
Change current fill area attributes if necessary.
Definition: TAttFill.cxx:206
Double_t Log10(Double_t x)
Definition: TMath.h:529
static double p2(double t, double a, double b, double c)
TText * th2
Definition: textalign.C:17
void DrawFaceMode2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 2nd option (fill in correspondance with function levels)
virtual void AxisVertex(Double_t ang, Double_t *av, Int_t &ix1, Int_t &ix2, Int_t &iy1, Int_t &iy2, Int_t &iz1, Int_t &iz2)=0
virtual Double_t * GetTnorm()=0
Double_t baroffset
offset of bin for bars or legos [0,1]
Definition: Hparam.h:43
virtual Bool_t IsInside(Int_t x, Int_t y)
Return kTRUE if the cell ix, iy is inside one of the graphical cuts.
void ImplicitFunction(Double_t *rmin, Double_t *rmax, Int_t nx, Int_t ny, Int_t nz, const char *chopt)
Draw implicit function FUN(X,Y,Z) = 0 in cartesian coordinates using hidden surface removal algorithm...
void DrawFaceMode1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *t)
Draw face - 1st variant (2 colors: 1st for external surface, 2nd for internal)
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
void LegoCylindrical(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
Draw stack of lego-plots in cylindrical coordinates.
Int_t xfirst
first bin number along X
Definition: Hparam.h:45
Double_t GetXmin() const
Definition: TAxis.h:137
void DrawFaceMove1(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 1st variant for "MOVING SCREEN" algorithm (draw face with level lines) ...
void ClearRaster()
Clear screen.
const Int_t kSPHERICAL
void DrawFaceMove2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "MOVING SCREEN" algorithm (draw face for stacked lego plot) ...
void MarchingCubeCase13(Int_t &nnod, Int_t &ntria, Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
Consider case No 13.
short Color_t
Definition: RtypesCore.h:79
virtual void SetView(Double_t longitude, Double_t latitude, Double_t psi, Int_t &irep)=0
TText * th1
Definition: textalign.C:13
A doubly linked list.
Definition: TList.h:47
static void RGBtoHLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Definition: TColor.h:81
virtual void FindThetaSectors(Int_t iopt, Double_t phi, Int_t &kth, Double_t *ath, Int_t &ith1, Int_t &ith2)=0
void FillPolygon(Int_t n, Double_t *p, Double_t *f)
Fill polygon with function values at vertexes.
void SetDrawFace(DrawFaceFunc_t pointer)
Store pointer to current algorithm to draw faces.
virtual void SetLineColor(Color_t lcolor)
Definition: TAttLine.h:54
static Int_t gEdgeStyle[kVSizeMax+1]
float ymax
Definition: THbookFile.cxx:93
const Int_t kPOLAR
Definition: TView3D.cxx:33
void SetColorMain(Color_t color, Int_t n=0)
Store color for stack number n.
void IsoSurface(Int_t ns, Double_t *s, Int_t nx, Int_t ny, Int_t nz, Double_t *x, Double_t *y, Double_t *z, const char *chopt)
Draw set of isosurfaces for a scalar function defined on a grid.
void FrontBox(Double_t ang)
Draw forward faces of surrounding box & axes.
ROOT::R::TRInterface & r
Definition: Object.C:4
static Int_t gEdgeWidth[kVSizeMax+1]
SVector< double, 2 > v
Definition: Dict.h:5
XPoint xy[kMAXMK]
Definition: TGX11.cxx:122
void FindLevelLines(Int_t np, Double_t *f, Double_t *t)
Find level lines for face.
virtual void SetFillColor(Color_t fcolor)
Definition: TAttFill.h:50
A 3-Dim function with parameters.
Definition: TF3.h:30
void LegoSpherical(Int_t ipsdr, Int_t iordr, Int_t na, Int_t nb, const char *chopt)
Draw stack of lego-plots spheric coordinates.
const Int_t kNmaxp
void LegoFunction(Int_t ia, Int_t ib, Int_t &nv, Double_t *ab, Double_t *vv, Double_t *t)
Service function for Legos.
unsigned int r1[N_CITIES]
Definition: simanTSP.cxx:321
virtual Color_t GetFillColor() const
Definition: TAttFill.h:43
void SurfaceCylindrical(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
Draw surface in cylindrical coordinates.
virtual void GetRGB(Float_t &r, Float_t &g, Float_t &b) const
Definition: TColor.h:54
void MarchingCubeCase07(Int_t &nnod, Int_t &ntria, Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
Consider case No 7.
const Int_t kLmax
void Luminosity(Double_t *anorm, Double_t &flum)
Find surface luminosity at given point.
TLine * l
Definition: textangle.C:4
TAxis * GetYaxis()
Definition: TH1.h:320
float xmax
Definition: THbookFile.cxx:93
static double p1(double t, double a, double b)
virtual Color_t GetLineColor() const
Definition: TAttLine.h:47
static Int_t gEdgeColor[kVSizeMax+1]
Int_t ylast
last bin number along Y
Definition: Hparam.h:48
virtual Double_t * GetRmin()=0
virtual void FindNormal(Double_t x, Double_t y, Double_t z, Double_t &zn)=0
Double_t Cos(Double_t)
Definition: TMath.h:424
void SetLegoFunction(LegoFunc_t pointer)
Store pointer to current lego function.
short Width_t
Definition: RtypesCore.h:78
The histogram painter class.
Definition: THistPainter.h:41
virtual Double_t * GetTN()=0
void SurfaceSpherical(Int_t ipsdr, Int_t iordr, Int_t na, Int_t nb, const char *chopt)
Draw surface in spheric coordinates.
void MarchingCubeCase04(Int_t &nnod, Int_t &ntria, Double_t xyz[52][3], Double_t grad[52][3], Int_t itria[48][3])
Consider case No 4.
void MarchingCubeMiddlePoint(Int_t nnod, Double_t xyz[52][3], Double_t grad[52][3], Int_t it[][3], Double_t *pxyz, Double_t *pgrad)
Find middle point of a polygon.
virtual Int_t GetSize() const
Definition: TCollection.h:95
const Int_t kCYLINDRICAL
static const double x1[5]
double f(double x)
int Zero
if selected with any LEGO option the empty bins are not drawn.
Definition: Hoption.h:62
void DrawFaceGouraudShaded(Int_t *icodes, Double_t xyz[][3], Int_t np, Int_t *iface, Double_t *t)
Draw the faces for the Gouraud Shaded Iso surfaces.
double Double_t
Definition: RtypesCore.h:55
The Legos and Surfaces painter class.
virtual void FindPhiSectors(Int_t iopt, Int_t &kphi, Double_t *aphi, Int_t &iphi1, Int_t &iphi2)=0
void ZDepth(Double_t xyz[52][3], Int_t &nface, Int_t iface[48][3], Double_t dface[48][6], Double_t abcd[48][4], Int_t *iorder)
Z-depth algorithm for set of triangles.
Double_t GetXmax() const
Definition: TAxis.h:138
TCanvas * style()
Definition: style.C:1
Double_t y[n]
Definition: legend1.C:17
virtual void SetRGB(Float_t r, Float_t g, Float_t b)
Initialize this color and its associated colors.
Definition: TColor.cxx:1605
static void SetF3ClippingBoxOn(Double_t xclip, Double_t yclip, Double_t zclip)
Static function Set the implicit function clipping box "on" and define the clipping box...
The TH1 histogram class.
Definition: TH1.h:80
Int_t xlast
last bin number along X
Definition: Hparam.h:46
const Int_t kF3FillColor2
void SetEdgeAtt(Color_t color=1, Style_t style=1, Width_t width=1, Int_t n=0)
The color creation and management class.
Definition: TColor.h:23
void Spectrum(Int_t nl, Double_t fmin, Double_t fmax, Int_t ic, Int_t idc, Int_t &irep)
Set Spectrum.
virtual void SetLineStyle(Style_t lstyle)
Definition: TAttLine.h:56
void MarchingCube(Double_t fiso, Double_t p[8][3], Double_t f[8], Double_t g[8][3], Int_t &nnod, Int_t &ntria, Double_t xyz[][3], Double_t grad[][3], Int_t itria[][3])
Topological decider for "Marching Cubes" algorithm Find set of triangles aproximating the isosurface ...
static TView * CreateView(Int_t system=1, const Double_t *rmin=0, const Double_t *rmax=0)
Create a concrete default 3-d view via the plug-in manager.
Definition: TView.cxx:36
const Int_t kF3FillColor1
void BackBox(Double_t ang)
Draw back surfaces of surrounding box.
Mother of all ROOT objects.
Definition: TObject.h:58
static Int_t ProjectSinusoidal2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code from Ernst-Jan Buis.
static Int_t ProjectParabolic2xy(Double_t l, Double_t b, Double_t &Al, Double_t &Ab)
Static function code from Ernst-Jan Buis.
const Int_t kNiso
const Int_t kNmaxt
void FindVisibleLine(Double_t *p1, Double_t *p2, Int_t ntmax, Int_t &nt, Double_t *t)
Find visible part of a line ("RASTER SCREEN")
Double_t xmin
minimum value along X
Definition: Hparam.h:31
void FindPartEdge(Double_t *p1, Double_t *p2, Double_t f1, Double_t f2, Double_t fmin, Double_t fmax, Int_t &kpp, Double_t *pp)
Find part of edge where function defined on this edge has value from fmin to fmax ...
double f2(const double *x)
void MarchingCubeSurfacePenetration(Double_t a00, Double_t a10, Double_t a11, Double_t a01, Double_t b00, Double_t b10, Double_t b11, Double_t b01, Int_t &irep)
Check for surface penetration ("bottle neck")
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:202
Int_t IsNaN(Double_t x)
Definition: TMath.h:617
static void SetF3ClippingBoxOff()
Static function Set the implicit function clipping box "off".
Double_t xmax
maximum value along X
Definition: Hparam.h:32
void DrawFaceRaster2(Int_t *icodes, Double_t *xyz, Int_t np, Int_t *iface, Double_t *tt)
Draw face - 2nd variant for "RASTER SCREEN" algorithm (draw face for stacked lego plot) ...
Double_t Sin(Double_t)
Definition: TMath.h:421
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
Evaluate this function.
Definition: TF1.cxx:1185
TF1 * f1
Definition: legend1.C:11
const Int_t kRAPIDITY
TH1 * gCurrentHist
int System
type of coordinate system(1=car,2=pol,3=cyl,4=sph,5=psr)
Definition: Hoption.h:54
#define gPad
Definition: TVirtualPad.h:288
void ModifyScreen(Double_t *r1, Double_t *r2)
Modify SCREEN.
static Int_t gColorDark[kVSizeMax+1]
void SurfacePolar(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
Draw surface in polar coordinates.
void SurfaceCartesian(Double_t ang, Int_t nx, Int_t ny, const char *chopt)
Draw surface in cartesian coordinate system.
static Int_t gColorMain[kVSizeMax+1]
void SetSurfaceFunction(SurfaceFunc_t pointer)
Store pointer to current surface function.
Double_t Sqrt(Double_t x)
Definition: TMath.h:464
const Int_t kCARTESIAN
Histogram parameters structure.
Definition: Hparam.h:28
void GouraudFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
Find part of surface with luminosity in the corners.
float * q
Definition: THbookFile.cxx:87
const Int_t n
Definition: legend1.C:16
const Double_t kRad
Line Attributes class.
Definition: TAttLine.h:32
Double_t barwidth
width of bin for bars and legos [0,1]
Definition: Hparam.h:44
void FillPolygonBorder(Int_t nn, Double_t *xy)
Fill a polygon including border ("RASTER SCREEN")
unsigned int r2[N_CITIES]
Definition: simanTSP.cxx:322
int Logz
log scale in Z. Also set by histogram option
Definition: Hoption.h:69
TAxis * GetXaxis()
Definition: TH1.h:319
int Lego
"LEGO" Draw as a Lego plot(LEGO,Lego=1, LEGO1,Lego1=11, LEGO2,Lego=12).
Definition: Hoption.h:46
Double_t ATan(Double_t)
Definition: TMath.h:451
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:904