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