Logo ROOT   6.16/01
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 correspondance 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 correspondance 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 && gStyle->GetHistMinimumZero()) {
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}
SVector< double, 2 > v
Definition: Dict.h:5
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 double p3(double t, double a, double b, double c, double d)
static double p1(double t, double a, double b)
static double p2(double t, double a, double b, double c)
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:363
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:410
R__EXTERN TStyle * gStyle
Definition: TStyle.h:406
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:210
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:234
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:1696
static void RGBtoHLS(Float_t r, Float_t g, Float_t b, Float_t &h, Float_t &l, Float_t &s)
Definition: TColor.h:77
virtual void GetRGB(Float_t &r, Float_t &g, Float_t &b) const
Definition: TColor.h:50
static void HLStoRGB(Float_t h, Float_t l, Float_t s, Float_t &r, Float_t &g, Float_t &b)
Definition: TColor.h:72
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:1424
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:4251
TAxis * GetYaxis()
Definition: TH1.h:317
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4790
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 correspondance 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 correspondance 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:227
Bool_t GetHistMinimumZero() const
Definition: TStyle.h:224
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:39
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 s
static constexpr double rad
static constexpr double ns
Bool_t IsNaN(Double_t x)
Definition: TMath.h:880
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:212
Double_t ATan(Double_t)
Definition: TMath.h:663
Double_t Sqrt(Double_t x)
Definition: TMath.h:679
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Definition: TMath.h:723
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:180
Double_t Cos(Double_t)
Definition: TMath.h:629
Double_t Sin(Double_t)
Definition: TMath.h:625
Double_t Log10(Double_t x)
Definition: TMath.h:752
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:66
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:68
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:67
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