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