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