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