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