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