// @(#)root/histpainter:$Id$ // Author: Rene Brun, Evgueni Tcherniaev, Olivier Couet 12/12/94 /************************************************************************* * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ //______________________________________________________________________________ /* Begin_Html
The original Fortran implementation was adapted to HIGZ/PAW by Olivier Couet and Evgueni Tcherniaev.
This class is a subset of the original system. It has been converted to a C++
class by Rene Brun.
End_Html */
#include
*/
//End_Html
// Local variables
Double_t cosa, sina;
Int_t ivis[4], iface[4];
Double_t tface[4];
Int_t incrx, incry, i1, k1, k2, ix1, iy1, ix2, iy2, i, iv, ix, iy, nv;
Int_t icodes[4];
Double_t zn, xy[8]; // was [2][4]
Double_t xyz[24]; // was [3][8]
Double_t *tn = 0;
TView *view = 0;
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.)
sina = TMath::Sin(ang*kRad);
cosa = TMath::Cos(ang*kRad);
// F I N D T H E M O S T L E F T P O I N T
if (gPad) view = gPad->GetView();
if (!view) {
Error("LegoCartesian", "no TView in current pad");
return;
}
tn = view->GetTN();
i1 = 1;
if (tn) {
if (tn[0] < 0) i1 = 2;
if (tn[0]*cosa + tn[1]*sina < 0) i1 = 5 - i1;
}
// Allocate v and tt arrays
Double_t *v, *tt;
Int_t vSize = fNStack+2;
if (vSize > kVSizeMax) {
v = new Double_t[vSize];
tt = new Double_t[4*vSize];
} else {
vSize = kVSizeMax;
v = &gV[0];
tt = &gTT[0];
}
// D E F I N E O R D E R O F D R A W I N G
if (*chopt == 'B' || *chopt == 'b') {
incrx = -1;
incry = -1;
} else {
incrx = 1;
incry = 1;
}
if (i1 == 1 || i1 == 2) incrx = -incrx;
if (i1 == 2 || i1 == 3) incry = -incry;
ix1 = 1;
iy1 = 1;
if (incrx < 0) ix1 = nx;
if (incry < 0) iy1 = ny;
ix2 = nx - ix1 + 1;
iy2 = ny - iy1 + 1;
// F I N D V I S I B I L I T Y O F S I D E S
ivis[0] = 0;
ivis[1] = 0;
ivis[2] = 0;
ivis[3] = 0;
nv = 0;
view->FindNormal(0, 1, 0, zn);
if (zn < 0) ivis[0] = 1;
if (zn > 0) ivis[2] = 1;
view->FindNormal(sina, cosa, 0, zn);
if (zn > 0) ivis[1] = 1;
if (zn < 0) ivis[3] = 1;
// D R A W S T A C K O F L E G O - P L O T S
THistPainter *painter = (THistPainter*)gCurrentHist->GetPainter();
for (iy = iy1; incry < 0 ? iy >= iy2 : iy <= iy2; iy += incry) {
for (ix = ix1; incrx < 0 ? ix >= ix2 : ix <= ix2; ix += incrx) {
if (!painter->IsInside(ix,iy)) continue;
(this->*fLegoFunction)(ix, iy, nv, xy, v, tt);
if (nv < 2 || nv > vSize) continue;
if (Hoption.Zero) {
Double_t total_content=0;
for (iv = 1; iv < nv; ++iv) total_content += v[iv];
if (total_content==0) continue;
}
icodes[0] = ix;
icodes[1] = iy;
for (i = 1; i <= 4; ++i) {
xyz[i*3 - 3] = xy[2*i - 2] + xy[2*i - 1]*cosa;
xyz[i*3 - 2] = xy[2*i - 1]*sina;
xyz[(i + 4)*3 - 3] = xyz[i*3 - 3];
xyz[(i + 4)*3 - 2] = xyz[i*3 - 2];
}
// D R A W S T A C K
firstStackNumberDrawn = -1;
for (iv = 1; iv < nv; ++iv) {
for (i = 1; i <= 4; ++i) {
xyz[i*3 - 1] = v[iv - 1];
xyz[(i + 4)*3 - 1] = v[iv];
}
if (v[iv - 1] == v[iv]) continue;
icodes[2] = iv;
for (i = 1; i <= 4; ++i) {
if (ivis[i - 1] == 0) continue;
k1 = i;
k2 = i + 1;
if (i == 4) k2 = 1;
icodes[3] = k1;
iface[0] = k1;
iface[1] = k2;
iface[2] = k2 + 4;
iface[3] = k1 + 4;
tface[0] = tt[k1 + (iv << 2) - 5];
tface[1] = tt[k2 + (iv << 2) - 5];
tface[2] = tt[k2 + ((iv + 1) << 2) - 5];
tface[3] = tt[k1 + ((iv + 1) << 2) - 5];
fEdgeIdx = iv-1;
(this->*fDrawFace)(icodes, xyz, 4, iface, tface);
}
if ( firstStackNumberDrawn==-1 ) firstStackNumberDrawn = fEdgeIdx;
}
// D R A W B O T T O M F A C E
view->FindNormal(0, 0, 1, zn);
if (zn < 0) {
icodes[2] = 1;
icodes[3] = 5;
for (i = 1; i <= 4; ++i) {
xyz[i*3 - 1] = v[0];
iface[i - 1] = 5 - i;
tface[i - 1] = tt[5 - i - 1];
}
if (!Hoption.Zero) fEdgeIdx = 0;
else {
fEdgeIdx = firstStackNumberDrawn;
fColorBottom = fColorMain[fEdgeIdx];
}
(this->*fDrawFace)(icodes, xyz, 4, iface, tface);
}
// D R A W T O P F A C E
if (zn > 0) {
icodes[2] = nv - 1;
icodes[3] = 6;
for (i = 1; i <= 4; ++i) {
iface[i - 1] = i + 4;
tface[i - 1] = tt[i + (nv << 2) - 5];
}
Int_t cs = fColorTop;
if ( nv <= 3 ) fEdgeIdx = 0 ; // no stack or stack with only one histo
else {
if ( nv > 2 && (v[nv-1] == v[nv-2])) {
for (iv = nv-1; iv>2; iv--) {
if (v[nv-1] == v[iv-1]) {
fColorTop = fColorMain[iv-2];
fEdgeIdx = iv-2;
}
}
}
}
(this->*fDrawFace)(icodes, xyz, 4, iface, tface);
fColorTop = cs;
}
}
}
if (vSize > kVSizeMax) {
delete [] v;
delete [] tt;
}
}
//______________________________________________________________________________
void TPainter3dAlgorithms::LegoPolar(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
{
// Draw stack of lego-plots in polar coordinates
//
// Input: IORDR - order of variables (0 - R,PHI; 1 - PHI,R)
// NA - number of steps along 1st variable
// NB - number of steps along 2nd variable
//
// FUN(IA,IB,NV,AB,V,TT) - external routine
// IA - cell number for 1st variable
// IB - cell number for 2nd variable
// NV - number of values for given cell
// AB(2,4) - coordinates of the cell corners
// V(NV) - cell values
// TT(4,*) - additional function
//
// DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
// ICODES(*) - set of codes for this face
// ICODES(1) - IA
// ICODES(2) - IB
// ICODES(3) - IV
// ICODES(4) - side: 1-internal,2-right,3-external,4-left
// 5-bottom, 6-top
// XYZ(3,*) - coordinates of nodes
// NP - number of nodes in face
// IFACE(NP) - face
// T(NP) - additional function
//
// CHOPT - options: 'BF' - from BACK to FRONT
// 'FB' - from FRONT to BACK
//
//Begin_Html
/*
*/
//End_Html
Int_t iphi, jphi, kphi, incr, nphi, ivis[6], iopt, iphi1, iphi2, iface[4], i, j;
Double_t tface[4];
Int_t incrr, k1, k2, ia, ib, ir1, ir2;
Double_t ab[8]; // was [2][4]
Int_t ir, jr, iv, nr, nv, icodes[4];
Double_t xyz[24]; // was [3][8]
ia = ib = 0;
TView *view = 0;
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.)
if (gPad) view = gPad->GetView();
if (!view) {
Error("LegoPolar", "no TView in current pad");
return;
}
if (iordr == 0) {
jr = 1;
jphi = 2;
nr = na;
nphi = nb;
} else {
jr = 2;
jphi = 1;
nr = nb;
nphi = na;
}
if (nphi > 180) {
Error("LegoPolar", "too many PHI sectors (%d)", nphi);
return;
}
iopt = 2;
if (*chopt == 'B' || *chopt == 'b') iopt = 1;
// Allocate v and tt arrays
Double_t *v, *tt;
Int_t vSize = fNStack+2;
if (vSize > kVSizeMax) {
v = new Double_t[vSize];
tt = new Double_t[4*vSize];
} else {
vSize = kVSizeMax;
v = &gV[0];
tt = &gTT[0];
}
// P R E P A R E P H I A R R A Y
// F I N D C R I T I C A L S E C T O R S
nv = 0;
kphi = nphi;
if (iordr == 0) ia = nr;
if (iordr != 0) ib = nr;
for (i = 1; i <= nphi; ++i) {
if (iordr == 0) ib = i;
if (iordr != 0) ia = i;
(this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
if (i == 1) fAphi[0] = ab[jphi - 1];
fAphi[i - 1] = (fAphi[i - 1] + ab[jphi - 1]) / (float)2.;
fAphi[i] = ab[jphi + 3];
}
view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
// E N C O D E V I S I B I L I T Y O F S I D E S
// A N D O R D E R A L O N G R
for (i = 1; i <= nphi; ++i) {
if (!iordr) ib = i;
if (iordr) ia = i;
(this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
SideVisibilityEncode(iopt, ab[jphi - 1]*kRad, ab[jphi + 3]*kRad, fAphi[i - 1]);
}
// D R A W S T A C K O F L E G O - P L O T S
incr = 1;
iphi = iphi1;
L100:
if (iphi > nphi) goto L300;
// D E C O D E V I S I B I L I T Y O F S I D E S
SideVisibilityDecode(fAphi[iphi - 1], ivis[0], ivis[1], ivis[2], ivis[3], ivis[4], ivis[5], incrr);
ir1 = 1;
if (incrr < 0) ir1 = nr;
ir2 = nr - ir1 + 1;
// D R A W L E G O S F O R S E C T O R
for (ir = ir1; incrr < 0 ? ir >= ir2 : ir <= ir2; ir += incrr) {
if (iordr == 0) { ia = ir; ib = iphi; }
else { ia = iphi; ib = ir; }
(this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
if (nv < 2 || nv > vSize) continue;
if (Hoption.Zero) {
Double_t total_content=0;
for (iv = 1; iv < nv; ++iv) total_content += v[iv];
if (total_content==0) continue;
}
icodes[0] = ia;
icodes[1] = ib;
for (i = 1; i <= 4; ++i) {
j = i;
if (iordr != 0 && i == 2) j = 4;
if (iordr != 0 && i == 4) j = 2;
xyz[j*3 - 3] = ab[jr + 2*i - 3]*TMath::Cos(ab[jphi + 2*i - 3]*kRad);
xyz[j*3 - 2] = ab[jr + 2*i - 3]*TMath::Sin(ab[jphi + 2*i - 3]*kRad);
xyz[(j + 4)*3 - 3] = xyz[j*3 - 3];
xyz[(j + 4)*3 - 2] = xyz[j*3 - 2];
}
// D R A W S T A C K
firstStackNumberDrawn = -1;
for (iv = 1; iv < nv; ++iv) {
for (i = 1; i <= 4; ++i) {
xyz[i*3 - 1] = v[iv - 1];
xyz[(i + 4)*3 - 1] = v[iv];
}
if (v[iv - 1] >= v[iv]) continue;
icodes[2] = iv;
for (i = 1; i <= 4; ++i) {
if (ivis[i - 1] == 0) continue;
k1 = i - 1;
if (i == 1) k1 = 4;
k2 = i;
if (xyz[k1*3 - 3] == xyz[k2*3 - 3] && xyz[k1*3 - 2] ==
xyz[k2*3 - 2]) continue;
iface[0] = k1;
iface[1] = k2;
iface[2] = k2 + 4;
iface[3] = k1 + 4;
tface[0] = tt[k1 + (iv << 2) - 5];
tface[1] = tt[k2 + (iv << 2) - 5];
tface[2] = tt[k2 + ((iv + 1) << 2) - 5];
tface[3] = tt[k1 + ((iv + 1) << 2) - 5];
icodes[3] = i;
fEdgeIdx = iv-1;
(this->*fDrawFace)(icodes, xyz, 4, iface, tface);
}
if ( firstStackNumberDrawn==-1 ) firstStackNumberDrawn = fEdgeIdx;
}
// D R A W B O T T O M F A C E
if (ivis[4] != 0) {
icodes[2] = 1;
icodes[3] = 5;
for (i = 1; i <= 4; ++i) {
xyz[i*3 - 1] = v[0];
iface[i - 1] = 5 - i;
tface[i - 1] = tt[5 - i - 1];
}
if (!Hoption.Zero) fEdgeIdx = 0;
else {
fEdgeIdx = firstStackNumberDrawn;
fColorBottom = fColorMain[fEdgeIdx];
}
(this->*fDrawFace)(icodes, xyz, 4, iface, tface);
}
// D R A W T O P F A C E
if (ivis[5] != 0) {
icodes[2] = nv - 1;
icodes[3] = 6;
for (i = 1; i <= 4; ++i) {
iface[i - 1] = i + 4;
tface[i - 1] = tt[i + (nv << 2) - 5];
}
Int_t cs = fColorTop;
if ( nv <= 3 ) fEdgeIdx = 0 ; // no stack or stack with only one histo
else {
if ( nv > 2 && (v[nv-1] == v[nv-2])) {
for (iv = nv-1; iv>2; iv--) {
if (v[nv-1] == v[iv-1]) {
fColorTop = fColorMain[iv-2];
fEdgeIdx = iv-2;
}
}
}
}
(this->*fDrawFace)(icodes, xyz, 4, iface, tface);
fColorTop = cs;
}
}
// N E X T P H I
L300:
iphi += incr;
if (iphi == 0) iphi = kphi;
if (iphi > kphi) iphi = 1;
if (iphi != iphi2) goto L100;
if (incr == 0) {
if (vSize > kVSizeMax) {
delete [] v;
delete [] tt;
}
return;
}
if (incr < 0) {
incr = 0;
goto L100;
}
incr = -1;
iphi = iphi1;
goto L300;
}
//______________________________________________________________________________
void TPainter3dAlgorithms::LegoCylindrical(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
{
// Draw stack of lego-plots in cylindrical coordinates
//
// Input: IORDR - order of variables (0 - Z,PHI; 1 - PHI,Z)
// NA - number of steps along 1st variable
// NPHI - number of steps along 2nd variable
//
// FUN(IA,IB,NV,AB,V,TT) - external routine
// IA - cell number for 1st variable
// IB - cell number for 2nd variable
// NV - number of values for given cell
// AB(2,4) - coordinates of the cell corners
// V(NV) - cell values
// TT(4,*) - additional function
//
// DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
// ICODES(*) - set of codes for this face
// ICODES(1) - IA
// ICODES(2) - IB
// ICODES(3) - IV
// ICODES(4) - side: 1,2,3,4 - ordinary sides
// 5-bottom,6-top
// XYZ(3,*) - coordinates of nodes
// NP - number of nodes in face
// IFACE(NP) - face
// T(NP) - additional function
//
// CHOPT - options: 'BF' - from BACK to FRONT
// 'FB' - from FRONT to BACK
//
//Begin_Html
/*
*/
//End_Html
Int_t iphi, jphi, kphi, incr, nphi, ivis[6], iopt, iphi1, iphi2, iface[4], i, j;
Double_t tface[4], z;
Double_t ab[8]; // was [2][4]
Int_t ia, ib, idummy, iz1, iz2, nz, incrz, k1, k2, nv;
Int_t iv, iz, jz, icodes[4];
Double_t cosphi[4];
Double_t sinphi[4];
Double_t xyz[24]; // was [3][8]
ia = ib = 0;
TView *view = 0;
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.)
if (gPad) view = gPad->GetView();
if (!view) {
Error("LegoCylindrical", "no TView in current pad");
return;
}
if (iordr == 0) {
jz = 1;
jphi = 2;
nz = na;
nphi = nb;
} else {
jz = 2;
jphi = 1;
nz = nb;
nphi = na;
}
if (nphi > 180) {
Error("LegoCylindrical", "too many PHI sectors (%d)", nphi);
return;
}
iopt = 2;
if (*chopt == 'B' || *chopt == 'b') iopt = 1;
// Allocate v and tt arrays
Double_t *v, *tt;
Int_t vSize = fNStack+2;
if (vSize > kVSizeMax) {
v = new Double_t[vSize];
tt = new Double_t[4*vSize];
} else {
vSize = kVSizeMax;
v = &gV[0];
tt = &gTT[0];
}
// P R E P A R E P H I A R R A Y
// F I N D C R I T I C A L S E C T O R S
nv = 0;
kphi = nphi;
if (iordr == 0) ia = nz;
if (iordr != 0) ib = nz;
for (i = 1; i <= nphi; ++i) {
if (iordr == 0) ib = i;
if (iordr != 0) ia = i;
(this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
if (i == 1) fAphi[0] = ab[jphi - 1];
fAphi[i - 1] = (fAphi[i - 1] + ab[jphi - 1]) / (float)2.;
fAphi[i] = ab[jphi + 3];
}
view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
// E N C O D E V I S I B I L I T Y O F S I D E S
// A N D O R D E R A L O N G R
for (i = 1; i <= nphi; ++i) {
if (iordr == 0) ib = i;
if (iordr != 0) ia = i;
(this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
SideVisibilityEncode(iopt, ab[jphi - 1]*kRad, ab[jphi + 3]*kRad, fAphi[i - 1]);
}
// F I N D O R D E R A L O N G Z
incrz = 1;
iz1 = 1;
view->FindNormal(0, 0, 1, z);
if ((z <= 0 && iopt == 1) || (z > 0 && iopt == 2)) {
incrz = -1;
iz1 = nz;
}
iz2 = nz - iz1 + 1;
// D R A W S T A C K O F L E G O - P L O T S
incr = 1;
iphi = iphi1;
L100:
if (iphi > nphi) goto L400;
// D E C O D E V I S I B I L I T Y O F S I D E S
idummy = 0;
SideVisibilityDecode(fAphi[iphi - 1], ivis[4], ivis[1], ivis[5], ivis[3], ivis[0], ivis[2], idummy);
for (iz = iz1; incrz < 0 ? iz >= iz2 : iz <= iz2; iz += incrz) {
if (iordr == 0) {ia = iz; ib = iphi;}
else {ia = iphi; ib = iz;}
(this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
if (nv < 2 || nv > vSize) continue;
icodes[0] = ia;
icodes[1] = ib;
for (i = 1; i <= 4; ++i) {
j = i;
if (iordr != 0 && i == 2) j = 4;
if (iordr != 0 && i == 4) j = 2;
cosphi[j - 1] = TMath::Cos(ab[jphi + 2*i - 3]*kRad);
sinphi[j - 1] = TMath::Sin(ab[jphi + 2*i - 3]*kRad);
xyz[j*3 - 1] = ab[jz + 2*i - 3];
xyz[(j + 4)*3 - 1] = ab[jz + 2*i - 3];
}
// D R A W S T A C K
firstStackNumberDrawn = -1;
for (iv = 1; iv < nv; ++iv) {
for (i = 1; i <= 4; ++i) {
xyz[i*3 - 3] = v[iv - 1]*cosphi[i - 1];
xyz[i*3 - 2] = v[iv - 1]*sinphi[i - 1];
xyz[(i + 4)*3 - 3] = v[iv]*cosphi[i - 1];
xyz[(i + 4)*3 - 2] = v[iv]*sinphi[i - 1];
}
if (v[iv - 1] >= v[iv]) continue;
icodes[2] = iv;
for (i = 1; i <= 4; ++i) {
if (ivis[i - 1] == 0) continue;
k1 = i;
k2 = i - 1;
if (i == 1) k2 = 4;
iface[0] = k1;
iface[1] = k2;
iface[2] = k2 + 4;
iface[3] = k1 + 4;
tface[0] = tt[k1 + (iv << 2) - 5];
tface[1] = tt[k2 + (iv << 2) - 5];
tface[2] = tt[k2 + ((iv + 1) << 2) - 5];
tface[3] = tt[k1 + ((iv + 1) << 2) - 5];
icodes[3] = i;
fEdgeIdx = iv-1;
(this->*fDrawFace)(icodes, xyz, 4, iface, tface);
}
if ( firstStackNumberDrawn==-1 ) firstStackNumberDrawn = fEdgeIdx;
}
// D R A W B O T T O M F A C E
if (ivis[4] != 0 && v[0] > 0) {
icodes[2] = 1;
icodes[3] = 5;
for (i = 1; i <= 4; ++i) {
xyz[i*3 - 3] = v[0]*cosphi[i - 1];
xyz[i*3 - 2] = v[0]*sinphi[i - 1];
iface[i - 1] = i;
tface[i - 1] = tt[i - 1];
}
if (!Hoption.Zero) fEdgeIdx = 0;
else {
fEdgeIdx = firstStackNumberDrawn;
fColorBottom = fColorMain[fEdgeIdx];
}
(this->*fDrawFace)(icodes, xyz, 4, iface, tface);
}
// D R A W T O P F A C E
if (ivis[5] != 0 && v[nv - 1] > 0) {
icodes[2] = nv - 1;
icodes[3] = 6;
for (i = 1; i <= 4; ++i) {
iface[i - 1] = 5 - i + 4;
tface[i - 1] = tt[5 - i + (nv << 2) - 5];
}
Int_t cs = fColorTop;
if ( nv <= 3 ) fEdgeIdx = 0 ; // no stack or stack with only one histo
else {
if ( nv > 2 && (v[nv-1] == v[nv-2])) {
for (iv = nv-1; iv>2; iv--) {
if (v[nv-1] == v[iv-1]) {
fColorTop = fColorMain[iv-2];
fEdgeIdx = iv-2;
}
}
}
}
(this->*fDrawFace)(icodes, xyz, 4, iface, tface);
fColorTop = cs;
}
}
// N E X T P H I
L400:
iphi += incr;
if (iphi == 0) iphi = kphi;
if (iphi > kphi) iphi = 1;
if (iphi != iphi2) goto L100;
if (incr == 0) {
if (vSize > kVSizeMax) {
delete [] v;
delete [] tt;
}
return;
}
if (incr < 0) {
incr = 0;
goto L100;
}
incr = -1;
iphi = iphi1;
goto L400;
}
//______________________________________________________________________________
void TPainter3dAlgorithms::LegoSpherical(Int_t ipsdr, Int_t iordr, Int_t na, Int_t nb, const char *chopt)
{
// Draw stack of lego-plots spheric coordinates
//
// Input: IPSDR - pseudo-rapidity flag
// IORDR - order of variables (0 - THETA,PHI; 1 - PHI,THETA)
// NA - number of steps along 1st variable
// NB - number of steps along 2nd variable
//
// FUN(IA,IB,NV,AB,V,TT) - external routine
// IA - cell number for 1st variable
// IB - cell number for 2nd variable
// NV - number of values for given cell
// AB(2,4) - coordinates of the cell corners
// V(NV) - cell values
// TT(4,*) - additional function
//
// DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
// ICODES(*) - set of codes for this face
// ICODES(1) - IA
// ICODES(2) - IB
// ICODES(3) - IV
// ICODES(4) - side: 1,2,3,4 - ordinary sides
// 5-bottom,6-top
// XYZ(3,*) - coordinates of nodes
// NP - number of nodes in face
// IFACE(NP) - face
// T(NP) - additional function
//
// CHOPT - options: 'BF' - from BACK to FRONT
// 'FB' - from FRONT to BACK
Int_t iphi, jphi, kphi, incr, nphi, ivis[6], iopt, iphi1, iphi2, iface[4], i, j;
Double_t tface[4], costh[4];
Double_t sinth[4];
Int_t k1, k2, ia, ib, incrth, ith, jth, kth, nth, mth, ith1, ith2, nv;
Double_t ab[8]; // was [2][4]
Double_t th;
Int_t iv, icodes[4];
Double_t zn, cosphi[4];
Double_t sinphi[4], th1, th2, phi;
Double_t xyz[24]; // was [3][8]
Double_t phi1, phi2;
ia = ib = 0;
TView *view = 0;
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.)
if (gPad) view = gPad->GetView();
if (!view) {
Error("LegoSpherical", "no TView in current pad");
return;
}
if (iordr == 0) {
jth = 1;
jphi = 2;
nth = na;
nphi = nb;
} else {
jth = 2;
jphi = 1;
nth = nb;
nphi = na;
}
if (nth > 180) {
Error("LegoSpherical", "too many THETA sectors (%d)", nth);
return;
}
if (nphi > 180) {
Error("LegoSpherical", "too many PHI sectors (%d)", nphi);
return;
}
iopt = 2;
if (*chopt == 'B' || *chopt == 'b') iopt = 1;
// Allocate v and tt arrays
Double_t *v, *tt;
Int_t vSize = fNStack+2;
if (vSize > kVSizeMax) {
v = new Double_t[vSize];
tt = new Double_t[4*vSize];
} else {
vSize = kVSizeMax;
v = &gV[0];
tt = &gTT[0];
}
// P R E P A R E P H I A R R A Y
// F I N D C R I T I C A L P H I S E C T O R S
nv = 0;
kphi = nphi;
mth = nth / 2;
if (mth == 0) mth = 1;
if (iordr == 0) ia = mth;
if (iordr != 0) ib = mth;
for (i = 1; i <= nphi; ++i) {
if (iordr == 0) ib = i;
if (iordr != 0) ia = i;
(this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
if (i == 1) fAphi[0] = ab[jphi - 1];
fAphi[i - 1] = (fAphi[i - 1] + ab[jphi - 1]) / (float)2.;
fAphi[i] = ab[jphi + 3];
}
view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
// P R E P A R E T H E T A A R R A Y
if (iordr == 0) ib = 1;
if (iordr != 0) ia = 1;
for (i = 1; i <= nth; ++i) {
if (iordr == 0) ia = i;
if (iordr != 0) ib = i;
(this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
if (i == 1) fAphi[0] = ab[jth - 1];
fAphi[i - 1] = (fAphi[i - 1] + ab[jth - 1]) / (float)2.;
fAphi[i] = ab[jth + 3];
}
// D R A W S T A C K O F L E G O - P L O T S
kth = nth;
incr = 1;
iphi = iphi1;
L100:
if (iphi > nphi) goto L500;
// F I N D C R I T I C A L T H E T A S E C T O R S
if (!iordr) {ia = mth; ib = iphi; }
else {ia = iphi;ib = mth; }
(this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
phi = (ab[jphi - 1] + ab[jphi + 3]) / (float)2.;
view->FindThetaSectors(iopt, phi, kth, fAphi, ith1, ith2);
incrth = 1;
ith = ith1;
L200:
if (ith > nth) goto L400;
if (iordr == 0) ia = ith;
if (iordr != 0) ib = ith;
(this->*fLegoFunction)(ia, ib, nv, ab, v, tt);
if (nv < 2 || nv > vSize) goto L400;
// D E F I N E V I S I B I L I T Y O F S I D E S
for (i = 1; i <= 6; ++i) ivis[i - 1] = 0;
phi1 = kRad*ab[jphi - 1];
phi2 = kRad*ab[jphi + 3];
th1 = kRad*ab[jth - 1];
th2 = kRad*ab[jth + 3];
view->FindNormal(TMath::Sin(phi1), -TMath::Cos(phi1), 0, zn);
if (zn > 0) ivis[1] = 1;
view->FindNormal(-TMath::Sin(phi2), TMath::Cos(phi2), 0, zn);
if (zn > 0) ivis[3] = 1;
phi = (phi1 + phi2) / (float)2.;
view->FindNormal(-TMath::Cos(phi)*TMath::Cos(th1), -TMath::Sin(phi)*TMath::Cos(th1), TMath::Sin(th1), zn);
if (zn > 0) ivis[0] = 1;
view->FindNormal(TMath::Cos(phi)*TMath::Cos(th2), TMath::Sin(phi)*TMath::Cos(th2), -TMath::Sin(th2), zn);
if (zn > 0) ivis[2] = 1;
th = (th1 + th2) / (float)2.;
if (ipsdr == 1) th = kRad*90;
view->FindNormal(TMath::Cos(phi)*TMath::Sin(th), TMath::Sin(phi)*TMath::Sin(th), TMath::Cos(th), zn);
if (zn < 0) ivis[4] = 1;
if (zn > 0) ivis[5] = 1;
// D R A W S T A C K
icodes[0] = ia;
icodes[1] = ib;
for (i = 1; i <= 4; ++i) {
j = i;
if (iordr != 0 && i == 2) j = 4;
if (iordr != 0 && i == 4) j = 2;
costh[j - 1] = TMath::Cos(kRad*ab[jth + 2*i - 3]);
sinth[j - 1] = TMath::Sin(kRad*ab[jth + 2*i - 3]);
cosphi[j - 1] = TMath::Cos(kRad*ab[jphi + 2*i - 3]);
sinphi[j - 1] = TMath::Sin(kRad*ab[jphi + 2*i - 3]);
}
firstStackNumberDrawn = -1;
for (iv = 1; iv < nv; ++iv) {
if (ipsdr == 1) {
for (i = 1; i <= 4; ++i) {
xyz[i*3 - 3] = v[iv - 1]*cosphi[i - 1];
xyz[i*3 - 2] = v[iv - 1]*sinphi[i - 1];
xyz[i*3 - 1] = v[iv - 1]*costh[i - 1] / sinth[i - 1];
xyz[(i + 4)*3 - 3] = v[iv]*cosphi[i - 1];
xyz[(i + 4)*3 - 2] = v[iv]*sinphi[i - 1];
xyz[(i + 4)*3 - 1] = v[iv]*costh[i - 1] / sinth[i - 1];
}
} else {
for (i = 1; i <= 4; ++i) {
xyz[i*3 - 3] = v[iv - 1]*sinth[i - 1]*cosphi[i - 1];
xyz[i*3 - 2] = v[iv - 1]*sinth[i - 1]*sinphi[i - 1];
xyz[i*3 - 1] = v[iv - 1]*costh[i - 1];
xyz[(i + 4)*3 - 3] = v[iv]*sinth[i - 1]*cosphi[i - 1];
xyz[(i + 4)*3 - 2] = v[iv]*sinth[i - 1]*sinphi[i - 1];
xyz[(i + 4)*3 - 1] = v[iv]*costh[i - 1];
}
}
if (v[iv - 1] >= v[iv]) continue;
icodes[2] = iv;
for (i = 1; i <= 4; ++i) {
if (ivis[i - 1] == 0) continue;
k1 = i - 1;
if (i == 1) k1 = 4;
k2 = i;
iface[0] = k1;
iface[1] = k2;
iface[2] = k2 + 4;
iface[3] = k1 + 4;
tface[0] = tt[k1 + (iv << 2) - 5];
tface[1] = tt[k2 + (iv << 2) - 5];
tface[2] = tt[k2 + ((iv + 1) << 2) - 5];
tface[3] = tt[k1 + ((iv + 1) << 2) - 5];
icodes[3] = i;
fEdgeIdx = iv-1;
(this->*fDrawFace)(icodes, xyz, 4, iface, tface);
}
if ( firstStackNumberDrawn==-1 ) firstStackNumberDrawn = fEdgeIdx;
}
// D R A W B O T T O M F A C E
if (ivis[4] != 0 && v[0] > 0) {
icodes[2] = 1;
icodes[3] = 5;
for (i = 1; i <= 4; ++i) {
if (ipsdr == 1) {
xyz[i*3 - 3] = v[0]*cosphi[i - 1];
xyz[i*3 - 2] = v[0]*sinphi[i - 1];
xyz[i*3 - 1] = v[0]*costh[i - 1] / sinth[i - 1];
} else {
xyz[i*3 - 3] = v[0]*sinth[i - 1]*cosphi[i - 1];
xyz[i*3 - 2] = v[0]*sinth[i - 1]*sinphi[i - 1];
xyz[i*3 - 1] = v[0]*costh[i - 1];
}
iface[i - 1] = 5 - i;
tface[i - 1] = tt[5 - i - 1];
}
if (!Hoption.Zero) fEdgeIdx = 0;
else {
fEdgeIdx = firstStackNumberDrawn;
fColorBottom = fColorMain[fEdgeIdx];
}
(this->*fDrawFace)(icodes, xyz, 4, iface, tface);
}
// D R A W T O P F A C E
if (ivis[5] != 0 && v[nv - 1] > 0) {
icodes[2] = nv - 1;
icodes[3] = 6;
for (i = 1; i <= 4; ++i) {
iface[i - 1] = i + 4;
tface[i - 1] = tt[i + 4 + 2*nv - 5];
}
Int_t cs = fColorTop;
if ( nv <= 3 ) fEdgeIdx = 0 ; // no stack or stack with only one histo
else {
if ( nv > 2 && (v[nv-1] == v[nv-2])) {
for (iv = nv-1; iv>2; iv--) {
if (v[nv-1] == v[iv-1]) {
fColorTop = fColorMain[iv-2];
fEdgeIdx = iv-2;
}
}
}
}
(this->*fDrawFace)(icodes, xyz, 4, iface, tface);
fColorTop = cs;
}
// N E X T T H E T A
L400:
ith += incrth;
if (ith == 0) ith = kth;
if (ith > kth) ith = 1;
if (ith != ith2) goto L200;
if (incrth == 0) goto L500;
if (incrth < 0) {
incrth = 0;
goto L200;
}
incrth = -1;
ith = ith1;
goto L400;
// N E X T P H I
L500:
iphi += incr;
if (iphi == 0) iphi = kphi;
if (iphi > kphi) iphi = 1;
if (iphi != iphi2) goto L100;
if (incr == 0) {
if (vSize > kVSizeMax) {
delete [] v;
delete [] tt;
}
return;
}
if (incr < 0) {
incr = 0;
goto L100;
}
incr = -1;
iphi = iphi1;
goto L500;
}
//______________________________________________________________________________
void TPainter3dAlgorithms::LightSource(Int_t nl, Double_t yl, Double_t xscr,
Double_t yscr, Double_t zscr, Int_t &irep)
{
// Set light source
//
// Input: NL - source number: -1 off all light sources
// 0 set diffused light
// YL - intensity of the light source
// XSCR |
// YSCR > direction of the light (in respect of the screen)
// ZSCR |
//
// Output: IREP - reply : 0 - O.K.
// -1 - error in light sources definition:
// negative intensity
// source number greater than max
// light source is placed at origin
/* Local variables */
Int_t i;
Double_t s;
irep = 0;
if (nl < 0) goto L100;
else if (nl == 0) goto L200;
else goto L300;
// S W I T C H O F F L I G H T S
L100:
fLoff = 1;
fYdl = 0;
for (i = 1; i <= 4; ++i) {
fYls[i - 1] = 0;
}
return;
// S E T D I F F U S E D L I G H T
L200:
if (yl < 0) {
Error("LightSource", "negative light intensity");
irep = -1;
return;
}
fYdl = yl;
goto L400;
// S E T L I G H T S O U R C E
L300:
if (nl > 4 || yl < 0) {
Error("LightSource", "illegal light source number (nl=%d, yl=%f)", nl, yl);
irep = -1;
return;
}
s = TMath::Sqrt(xscr*xscr + yscr*yscr + zscr*zscr);
if (s == 0) {
Error("LightSource", "light source is placed at origin");
irep = -1;
return;
}
fYls[nl - 1] = yl;
fVls[nl*3 - 3] = xscr / s;
fVls[nl*3 - 2] = yscr / s;
fVls[nl*3 - 1] = zscr / s;
// C H E C K L I G H T S
L400:
fLoff = 0;
if (fYdl != 0) return;
for (i = 1; i <= 4; ++i) {
if (fYls[i - 1] != 0) return;
}
fLoff = 1;
}
//______________________________________________________________________________
void TPainter3dAlgorithms::Luminosity(Double_t *anorm, Double_t &flum)
{
// Find surface luminosity at given point
// --
// Lightness model formula: Y = YD*QA + > YLi*(QD*cosNi+QS*cosRi)
// --
//
// B1 = VN(3)*VL(2) - VN(2)*VL(3)
// B2 = VN(1)*VL(3) - VN(3)*VL(1)
// B3 = VN(2)*VL(1) - VN(1)*VL(2)
// B4 = VN(1)*VL(1) + VN(2)*VL(2) + VN(3)*VL(3)
// VR(1) = VN(3)*B2 - VN(2)*B3 + VN(1)*B4
// VR(2) =-VN(3)*B1 + VN(1)*B3 + VN(2)*B4
// VR(3) = VN(2)*B1 - VN(1)*B2 + VN(3)*B4
// S = SQRT(VR(1)*VR(1)+VR(2)*VR(2)+VR(3)*VR(3))
// VR(1) = VR(1)/S
// VR(2) = VR(2)/S
// VR(3) = VR(3)/S
// COSR = VR(1)*0. + VR(2)*0. + VR(3)*1.
//
// References: WCtoNDC
//
// Input: ANORM(3) - surface normal at given point
//
// Output: FLUM - luminosity
/* Local variables */
Double_t cosn, cosr;
Int_t i;
Double_t s, vl[3], vn[3];
TView *view = 0;
if (gPad) view = gPad->GetView();
if (!view) return;
/* Parameter adjustments */
--anorm;
flum = 0;
if (fLoff != 0) return;
// T R A N S F E R N O R M A L T O SCREEN COORDINATES
view->NormalWCtoNDC(&anorm[1], vn);
s = TMath::Sqrt(vn[0]*vn[0] + vn[1]*vn[1] + vn[2]*vn[2]);
if (vn[2] < 0) s = -(Double_t)s;
vn[0] /= s;
vn[1] /= s;
vn[2] /= s;
// F I N D L U M I N O S I T Y
flum = fYdl*fQA;
for (i = 1; i <= 4; ++i) {
if (fYls[i - 1] <= 0) continue;
vl[0] = fVls[i*3 - 3];
vl[1] = fVls[i*3 - 2];
vl[2] = fVls[i*3 - 1];
cosn = vl[0]*vn[0] + vl[1]*vn[1] + vl[2]*vn[2];
if (cosn < 0) continue;
cosr = vn[1]*(vn[2]*vl[1] - vn[1]*vl[2]) - vn[0]*(vn[0]*vl[2]
- vn[2]*vl[0]) + vn[2]*cosn;
if (cosr <= 0) cosr = 0;
flum += fYls[i - 1]*(fQD*cosn + fQS*TMath::Power(cosr, fNqs));
}
}
//______________________________________________________________________________
void TPainter3dAlgorithms::ModifyScreen(Double_t *r1, Double_t *r2)
{
// Modify SCREEN
//
// Input: R1(3) - 1-st point of the line
// R2(3) - 2-nd point of the line
/* Local variables */
Int_t i, i1, i2;
Double_t x1, x2, y1, y2, dy, ww, yy1, yy2, *tn;
/* Parameter adjustments */
--r2;
--r1;
TView *view = 0;
if (gPad) view = gPad->GetView();
if (view) {
tn = view->GetTN();
if (tn) {
x1 = tn[0]*r1[1] + tn[1]*r1[2] + tn[2]*r1[3] + tn[3];
x2 = tn[0]*r2[1] + tn[1]*r2[2] + tn[2]*r2[3] + tn[3];
y1 = tn[4]*r1[1] + tn[5]*r1[2] + tn[6]*r1[3] + tn[7];
y2 = tn[4]*r2[1] + tn[5]*r2[2] + tn[6]*r2[3] + tn[7];
} else {
Error("ModifyScreen", "invalid TView in current pad");
return;
}
} else {
Error("ModifyScreen", "no TView in current pad");
return;
}
if (x1 >= x2) {
ww = x1;
x1 = x2;
x2 = ww;
ww = y1;
y1 = y2;
y2 = ww;
}
i1 = Int_t((x1 - fX0) / fDX) + 15;
i2 = Int_t((x2 - fX0) / fDX) + 15;
if (i1 == i2) return;
// M O D I F Y B O U N D A R I E S OF THE SCREEN
dy = (y2 - y1) / (i2 - i1);
for (i = i1; i <= i2 - 1; ++i) {
yy1 = y1 + dy*(i - i1);
yy2 = yy1 + dy;
if (fD[2*i - 2] > yy1) fD[2*i - 2] = yy1;
if (fD[2*i - 1] > yy2) fD[2*i - 1] = yy2;
if (fU[2*i - 2] < yy1) fU[2*i - 2] = yy1;
if (fU[2*i - 1] < yy2) fU[2*i - 1] = yy2;
}
}
//______________________________________________________________________________
void TPainter3dAlgorithms::SetDrawFace(DrawFaceFunc_t drface)
{
// Store pointer to current algorithm to draw faces
fDrawFace = drface;
}
//______________________________________________________________________________
void TPainter3dAlgorithms::SetLegoFunction(LegoFunc_t fun)
{
// Store pointer to current lego function
fLegoFunction = fun;
}
//______________________________________________________________________________
void TPainter3dAlgorithms::SetSurfaceFunction(SurfaceFunc_t fun)
{
// Store pointer to current surface function
fSurfaceFunction = fun;
}
//______________________________________________________________________________
void TPainter3dAlgorithms::SetF3(TF3 *f3)
{
// Static function
// Store pointer to current implicit function
fgCurrentF3 = f3;
}
//______________________________________________________________________________
void TPainter3dAlgorithms::SetF3ClippingBoxOff()
{
// static function
// Set the implicit function clipping box "off".
fgF3Clipping = 0;
}
//______________________________________________________________________________
void TPainter3dAlgorithms::SetF3ClippingBoxOn(Double_t xclip,
Double_t yclip, Double_t zclip)
{
// static function
// Set the implicit function clipping box "on" and define the clipping box.
// xclip, yclip and zclip is a point within the function range. All the
// function value having x<=xclip and y<=yclip and z>=zclip are clipped.
fgF3Clipping = 1;
fgF3XClip = xclip;
fgF3YClip = yclip;
fgF3ZClip = zclip;
}
//______________________________________________________________________________
void TPainter3dAlgorithms::SetColorDark(Color_t color, Int_t n)
{
// Store dark color for stack number n
if (n < 0 ) {fColorBottom = color; return;}
if (n > fNStack ) {fColorTop = color; return;}
fColorDark[n] = color;
}
//______________________________________________________________________________
void TPainter3dAlgorithms::SetColorMain(Color_t color, Int_t n)
{
// Store color for stack number n
if (n < 0 ) {fColorBottom = color; return;}
if (n > fNStack ) {fColorTop = color; return;}
fColorMain[n] = color;
}
//______________________________________________________________________________
void TPainter3dAlgorithms::SetEdgeAtt(Color_t color, Style_t style, Width_t width, Int_t n)
{
// Store edge attributes
fEdgeColor[n] = color;
fEdgeStyle[n] = style;
fEdgeWidth[n] = width;
}
//______________________________________________________________________________
void TPainter3dAlgorithms::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
//
// Input: VAL - encoded value
//
// Output: IV1 ... IV6 - visibility of the sides
// IR - increment along R
Int_t ivis[6], i, k, num;
k = Int_t(val);
num = 128;
for (i = 1; i <= 6; ++i) {
ivis[i - 1] = 0;
num /= 2;
if (k < num) continue;
k -= num;
ivis[i - 1] = 1;
}
ir = 1;
if (k == 1) ir = -1;
iv1 = ivis[5];
iv2 = ivis[4];
iv3 = ivis[3];
iv4 = ivis[2];
iv5 = ivis[1];
iv6 = ivis[0];
}
//______________________________________________________________________________
void TPainter3dAlgorithms::SideVisibilityEncode(Int_t iopt, Double_t phi1, Double_t phi2, Double_t &val)
{
// Encode side visibilities and order along R for sector
//
// Input: IOPT - options: 1 - from BACK to FRONT 'BF'
// 2 - from FRONT to BACK 'FB'
// PHI1 - 1st phi of sector
// PHI2 - 2nd phi of sector
//
// Output: VAL - encoded value
/* Local variables */
Double_t zn, phi;
Int_t k = 0;
TView *view = 0;
if (gPad) view = gPad->GetView();
if (!view) {
Error("SideVisibilityEncode", "no TView in current pad");
return;
}
view->FindNormal(0, 0, 1, zn);
if (zn > 0) k += 64;
if (zn < 0) k += 32;
view->FindNormal(-TMath::Sin(phi2), TMath::Cos(phi2), 0, zn);
if (zn > 0) k += 16;
view->FindNormal(TMath::Sin(phi1), -TMath::Cos(phi1), 0, zn);
if (zn > 0) k += 4;
phi = (phi1 + phi2) / (float)2.;
view->FindNormal(TMath::Cos(phi), TMath::Sin(phi), 0, zn);
if (zn > 0) k += 8;
if (zn < 0) k += 2;
if ((zn <= 0 && iopt == 1) || (zn > 0 && iopt == 2)) ++k;
val = Double_t(k);
}
//______________________________________________________________________________
void TPainter3dAlgorithms::Spectrum(Int_t nl, Double_t fmin, Double_t fmax, Int_t ic, Int_t idc, Int_t &irep)
{
// Set Spectrum
//
// Input: NL - number of levels
// FMIN - MIN function value
// FMAX - MAX function value
// IC - initial color index (for 1st level)
// IDC - color index increment
//
// Output: IREP - reply: 0 O.K.
// -1 error in parameters
// F_max less than F_min
// illegal number of levels
// initial color index is negative
// color index increment must be positive
static const char *where = "Spectrum";
/* Local variables */
Double_t delf;
Int_t i;
irep = 0;
if (nl == 0) {fNlevel = 0; return; }
// C H E C K P A R A M E T E R S
if (fmax <= fmin) {
Error(where, "fmax (%f) less than fmin (%f)", fmax, fmin);
irep = -1;
return;
}
if (nl < 0 || nl > 256) {
Error(where, "illegal number of levels (%d)", nl);
irep = -1;
return;
}
if (ic < 0) {
Error(where, "initial color index is negative");
irep = -1;
return;
}
if (idc < 0) {
Error(where, "color index increment must be positive");
irep = -1;
}
// S E T S P E C T R
const Int_t kMAXCOL = 50;
delf = (fmax - fmin) / nl;
fNlevel = -(nl + 1);
for (i = 1; i <= nl+1; ++i) {
fFunLevel[i - 1] = fmin + (i - 1)*delf;
fColorLevel[i] = ic + (i - 1)*idc;
if (ic <= kMAXCOL && fColorLevel[i] > kMAXCOL) fColorLevel[i] -= kMAXCOL;
}
fColorLevel[0] = fColorLevel[1];
fColorLevel[nl + 1] = fColorLevel[nl];
}
//______________________________________________________________________________
void TPainter3dAlgorithms::SurfaceCartesian(Double_t ang, Int_t nx, Int_t ny, const char *chopt)
{
// Draw surface in cartesian coordinate system
//
// Input: ANG - angle between X ang Y
// NX - number of steps along X
// NY - number of steps along Y
//
// FUN(IX,IY,F,T) - external routine
// IX - X number of the cell
// IY - Y number of the cell
// F(3,4) - face which corresponds to the cell
// T(4) - additional function (for example: temperature)
//
// DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
// ICODES(*) - set of codes for this face
// ICODES(1) - IX
// ICODES(2) - IY
// NP - number of nodes in face
// IFACE(NP) - face
// T(NP) - additional function
//
// CHOPT - options: 'BF' - from BACK to FRONT
// 'FB' - from FRONT to BACK
/* Initialized data */
Int_t iface[4] = { 1,2,3,4 };
/* Local variables */
Double_t cosa, sina, f[12] /* was [3][4] */;
Int_t i, incrx, incry, i1, ix, iy;
Double_t tt[4];
Int_t icodes[3], ix1, iy1, ix2, iy2; // was icode[2]. One element more to differentiate front & back boxes from data
Double_t xyz[12] /* was [3][4] */;
Double_t *tn;
sina = TMath::Sin(ang*kRad);
cosa = TMath::Cos(ang*kRad);
// F I N D T H E M O S T L E F T P O I N T
TView *view = 0;
if (gPad) view = gPad->GetView();
if (!view) {
Error("SurfaceCartesian", "no TView in current pad");
return;
}
tn = view->GetTN();
i1 = 1;
if (tn) {
if (tn[0] < 0) i1 = 2;
if (tn[0]*cosa + tn[1]*sina < 0) i1 = 5 - i1;
}
// D E F I N E O R D E R O F D R A W I N G
if (*chopt == 'B' || *chopt == 'b') {incrx = -1; incry = -1;}
else {incrx = 1; incry = 1;}
if (i1 == 1 || i1 == 2) incrx = -incrx;
if (i1 == 2 || i1 == 3) incry = -incry;
ix1 = 1;
iy1 = 1;
if (incrx < 0) ix1 = nx;
if (incry < 0) iy1 = ny;
ix2 = nx - ix1 + 1;
iy2 = ny - iy1 + 1;
// D R A W S U R F A C E
icodes[2] = -1; // -1 for data, 0 for front a back boxes
fEdgeIdx = 0; // constant since stacks are not (yet?) handled for surfaces
THistPainter *painter = (THistPainter*)gCurrentHist->GetPainter();
for (iy = iy1; incry < 0 ? iy >= iy2 : iy <= iy2; iy += incry) {
for (ix = ix1; incrx < 0 ? ix >= ix2 : ix <= ix2; ix += incrx) {
if (!painter->IsInside(ix,iy)) continue;
(this->*fSurfaceFunction)(ix, iy, f, tt);
for (i = 1; i <= 4; ++i) {
xyz[i*3 - 3] = f[i*3 - 3] + f[i*3 - 2]*cosa;
xyz[i*3 - 2] = f[i*3 - 2]*sina;
xyz[i*3 - 1] = f[i*3 - 1];
// added EJB -->
Double_t al, ab;
if (Hoption.Proj == 1 ) {
THistPainter::ProjectAitoff2xy(xyz[i*3 - 3], xyz[i*3 - 2], al, ab);
xyz[i*3 - 3] = al;
xyz[i*3 - 2] = ab;
} else if (Hoption.Proj == 2 ) {
THistPainter::ProjectMercator2xy(xyz[i*3 - 3], xyz[i*3 - 2], al, ab);
xyz[i*3 - 3] = al;
xyz[i*3 - 2] = ab;
} else if (Hoption.Proj == 3) {
THistPainter::ProjectSinusoidal2xy(xyz[i*3 - 3], xyz[i*3 - 2], al, ab);
xyz[i*3 - 3] = al;
xyz[i*3 - 2] = ab;
} else if (Hoption.Proj == 4) {
THistPainter::ProjectParabolic2xy(xyz[i*3 - 3], xyz[i*3 - 2], al, ab);
xyz[i*3 - 3] = al;
xyz[i*3 - 2] = ab;
}
}
icodes[0] = ix;
icodes[1] = iy;
(this->*fDrawFace)(icodes, xyz, 4, iface, tt);
}
}
}
//______________________________________________________________________________
void TPainter3dAlgorithms::SurfaceFunction(Int_t ia, Int_t ib, Double_t *f, Double_t *t)
{
// Service function for Surfaces
static Int_t ixadd[4] = { 0,1,1,0 };
static Int_t iyadd[4] = { 0,0,1,1 };
Double_t rinrad = gStyle->GetLegoInnerR();
Double_t dangle = 10; //Delta angle for Rapidity option
Double_t yval1l, yval2l;
Double_t xlab1l, xlab2l, ylab1l, ylab2l;
Int_t i, ixa, iya, icx, ixt, iyt;
/* Parameter adjustments */
--t;
f -= 4;
ixt = ia + Hparam.xfirst - 1;
iyt = ib + Hparam.yfirst - 1;
// xval1l = Hparam.xmin;
// xval2l = Hparam.xmax;
yval1l = Hparam.ymin;
yval2l = Hparam.ymax;
xlab1l = gCurrentHist->GetXaxis()->GetXmin();
xlab2l = gCurrentHist->GetXaxis()->GetXmax();
if (Hoption.Logx) {
if (xlab2l>0) {
if (xlab1l>0) xlab1l = TMath::Log10(xlab1l);
else xlab1l = TMath::Log10(0.001*xlab2l);
xlab2l = TMath::Log10(xlab2l);
}
}
ylab1l = gCurrentHist->GetYaxis()->GetXmin();
ylab2l = gCurrentHist->GetYaxis()->GetXmax();
if (Hoption.Logy) {
if (ylab2l>0) {
if (ylab1l>0) ylab1l = TMath::Log10(ylab1l);
else ylab1l = TMath::Log10(0.001*ylab2l);
ylab2l = TMath::Log10(ylab2l);
}
}
for (i = 1; i <= 4; ++i) {
ixa = ixadd[i - 1];
iya = iyadd[i - 1];
Double_t xwid = gCurrentHist->GetXaxis()->GetBinWidth(ixt+ixa);
Double_t ywid = gCurrentHist->GetYaxis()->GetBinWidth(iyt+iya);
// Compute the cell position in cartesian coordinates
// and compute the LOG if necessary
f[i*3 + 1] = gCurrentHist->GetXaxis()->GetBinLowEdge(ixt+ixa) + 0.5*xwid;
f[i*3 + 2] = gCurrentHist->GetYaxis()->GetBinLowEdge(iyt+iya) + 0.5*ywid;
if (Hoption.Logx) {
if (f[i*3 + 1] > 0) f[i*3 + 1] = TMath::Log10(f[i*3 + 1]);
else f[i*3 + 1] = Hparam.xmin;
}
if (Hoption.Logy) {
if (f[i*3 + 2] > 0) f[i*3 + 2] = TMath::Log10(f[i*3 + 2]);
else f[i*3 + 2] = Hparam.ymin;
}
// Transform the cell position in the required coordinate system
if (Hoption.System == kPOLAR) {
f[i*3 + 1] = 360*(f[i*3 + 1] - xlab1l) / (xlab2l - xlab1l);
f[i*3 + 2] = (f[i*3 + 2] - yval1l) / (yval2l - yval1l);
} else if (Hoption.System == kCYLINDRICAL) {
f[i*3 + 1] = 360*(f[i*3 + 1] - xlab1l) / (xlab2l - xlab1l);
} else if (Hoption.System == kSPHERICAL) {
f[i*3 + 1] = 360*(f[i*3 + 1] - xlab1l) / (xlab2l - xlab1l);
f[i*3 + 2] = 360*(f[i*3 + 2] - ylab1l) / (ylab2l - ylab1l);
} else if (Hoption.System == kRAPIDITY) {
f[i*3 + 1] = 360*(f[i*3 + 1] - xlab1l) / (xlab2l - xlab1l);
f[i*3 + 2] = (180 - dangle*2)*(f[i*3 + 2] - ylab1l) / (ylab2l - ylab1l) + dangle;
}
// Get the content of the table. If the X index (ICX) is
// greater than the X size of the table (NCX), that's mean
// IGTABL tried to close the surface and in this case the
// first channel should be used. */
icx = ixt + ixa;
if (icx > Hparam.xlast) icx = 1;
f[i*3+3] = Hparam.factor*gCurrentHist->GetBinContent(icx, iyt + iya);
if (Hoption.Logz) {
if (f[i*3+3] > 0) f[i*3+3] = TMath::Log10(f[i*3+3]);
else f[i*3+3] = Hparam.zmin;
if (f[i*3+3] < Hparam.zmin) f[i*3+3] = Hparam.zmin;
if (f[i*3+3] > Hparam.zmax) f[i*3+3] = Hparam.zmax;
} else {
f[i*3+3] = TMath::Max(Hparam.zmin, f[i*3+3]);
f[i*3+3] = TMath::Min(Hparam.zmax, f[i*3+3]);
}
// The colors on the surface can represent the content or the errors.
// if (fSumw2.fN) t[i] = gCurrentHist->GetBinError(icx, iyt + iya);
// else t[i] = f[i * 3 + 3];
t[i] = f[i * 3 + 3];
}
// Define the position of the colored contours for SURF3
if (Hoption.Surf == 23) {
for (i = 1; i <= 4; ++i) f[i * 3 + 3] = fRmax[2];
}
if (Hoption.System == kCYLINDRICAL || Hoption.System == kSPHERICAL || Hoption.System == kRAPIDITY) {
for (i = 1; i <= 4; ++i) {
f[i*3 + 3] = (1 - rinrad)*((f[i*3 + 3] - Hparam.zmin) /
(Hparam.zmax - Hparam.zmin)) + rinrad;
}
}
}
//______________________________________________________________________________
void TPainter3dAlgorithms::SurfacePolar(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
{
// Draw surface in polar coordinates
//
// Input: IORDR - order of variables (0 - R,PHI, 1 - PHI,R)
// NA - number of steps along 1st variable
// NB - number of steps along 2nd variable
//
// FUN(IA,IB,F,T) - external routine
// IA - cell number for 1st variable
// IB - cell number for 2nd variable
// F(3,4) - face which corresponds to the cell
// F(1,*) - A
// F(2,*) - B
// F(3,*) - Z
// T(4) - additional function (for example: temperature)
//
// DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
// ICODES(*) - set of codes for this face
// ICODES(1) - IA
// ICODES(2) - IB
// XYZ(3,*) - coordinates of nodes
// NP - number of nodes in face
// IFACE(NP) - face
// T(NP) - additional function
//
// CHOPT - options: 'BF' - from BACK to FRONT
// 'FB' - from FRONT to BACK
/* Initialized data */
static Int_t iface[4] = { 1,2,3,4 };
TView *view = 0;
if (gPad) view = gPad->GetView();
if (!view) {
Error("SurfacePolar", "no TView in current pad");
return;
}
Int_t iphi, jphi, kphi, incr, nphi, iopt, iphi1, iphi2;
Double_t f[12] /* was [3][4] */;
Int_t i, j, incrr, ir1, ir2;
Double_t z;
Int_t ia, ib, ir, jr, nr, icodes[3]; // was icode[2]. One element more to differentiate front & back boxes from data
Double_t tt[4];
Double_t phi, ttt[4], xyz[12] /* was [3][4] */;
ia = ib = 0;
if (iordr == 0) {
jr = 1;
jphi = 2;
nr = na;
nphi = nb;
} else {
jr = 2;
jphi = 1;
nr = nb;
nphi = na;
}
if (nphi > 180) {
Error("SurfacePolar", "too many PHI sectors (%d)", nphi);
return;
}
iopt = 2;
if (*chopt == 'B' || *chopt == 'b') iopt = 1;
// P R E P A R E P H I A R R A Y
// F I N D C R I T I C A L S E C T O R S
kphi = nphi;
if (iordr == 0) ia = nr;
if (iordr != 0) ib = nr;
for (i = 1; i <= nphi; ++i) {
if (iordr == 0) ib = i;
if (iordr != 0) ia = i;
(this->*fSurfaceFunction)(ia, ib, f, tt);
if (i == 1) fAphi[0] = f[jphi - 1];
fAphi[i - 1] = (fAphi[i - 1] + f[jphi - 1]) / (float)2.;
fAphi[i] = f[jphi + 5];
}
view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
// D R A W S U R F A C E
icodes[2] = -1; // -1 for data, 0 for front a back boxes
fEdgeIdx = 0; // constant since stacks are not (yet?) handled for surfaces
incr = 1;
iphi = iphi1;
L100:
if (iphi > nphi) goto L300;
// F I N D O R D E R A L O N G R
if (iordr == 0) {ia = nr; ib = iphi;}
else {ia = iphi;ib = nr;}
(this->*fSurfaceFunction)(ia, ib, f, tt);
phi = kRad*((f[jphi - 1] + f[jphi + 5]) / 2);
view->FindNormal(TMath::Cos(phi), TMath::Sin(phi), 0, z);
incrr = 1;
ir1 = 1;
if ((z <= 0 && iopt == 1) || (z > 0 && iopt == 2)) {
incrr = -1;
ir1 = nr;
}
ir2 = nr - ir1 + 1;
// D R A W S U R F A C E F O R S E C T O R
for (ir = ir1; incrr < 0 ? ir >= ir2 : ir <= ir2; ir += incrr) {
if (iordr == 0) ia = ir;
if (iordr != 0) ib = ir;
(this->*fSurfaceFunction)(ia, ib, f, tt);
for (i = 1; i <= 4; ++i) {
j = i;
if (iordr != 0 && i == 2) j = 4;
if (iordr != 0 && i == 4) j = 2;
xyz[j*3 - 3] = f[jr + i*3 - 4]*TMath::Cos(f[jphi + i*3 - 4]*kRad);
xyz[j*3 - 2] = f[jr + i*3 - 4]*TMath::Sin(f[jphi + i*3 - 4]*kRad);
xyz[j*3 - 1] = f[i*3 - 1];
ttt[j - 1] = tt[i - 1];
}
icodes[0] = ia;
icodes[1] = ib;
(this->*fDrawFace)(icodes, xyz, 4, iface, ttt);
}
// N E X T P H I
L300:
iphi += incr;
if (iphi == 0) iphi = kphi;
if (iphi > kphi) iphi = 1;
if (iphi != iphi2) goto L100;
if (incr == 0) return;
if (incr < 0) {
incr = 0;
goto L100;
}
incr = -1;
iphi = iphi1;
goto L300;
}
//______________________________________________________________________________
void TPainter3dAlgorithms::SurfaceCylindrical(Int_t iordr, Int_t na, Int_t nb, const char *chopt)
{
// Draw surface in cylindrical coordinates
//
// Input: IORDR - order of variables (0 - Z,PHI, 1 - PHI,Z)
// NA - number of steps along 1st variable
// NB - number of steps along 2nd variable
//
// FUN(IA,IB,F,T) - external routine
// IA - cell number for 1st variable
// IB - cell number for 2nd variable
// F(3,4) - face which corresponds to the cell
// F(1,*) - A
// F(2,*) - B
// F(3,*) - R
// T(4) - additional function (for example: temperature)
//
// DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
// ICODES(*) - set of codes for this face
// ICODES(1) - IA
// ICODES(2) - IB
// XYZ(3,*) - coordinates of nodes
// NP - number of nodes in face
// IFACE(NP) - face
// T(NP) - additional function
//
// CHOPT - options: 'BF' - from BACK to FRONT
// 'FB' - from FRONT to BACK
//
//Begin_Html
/*
*/
//End_Html
/* Initialized data */
static Int_t iface[4] = { 1,2,3,4 };
Int_t iphi, jphi, kphi, incr, nphi, iopt, iphi1, iphi2;
Int_t i, j, incrz, nz, iz1, iz2;
Int_t ia, ib, iz, jz, icodes[3]; // was icode[2]. One element more to differentiate front & back boxes from data
Double_t f[12] /* was [3][4] */;
Double_t z;
Double_t tt[4];
Double_t ttt[4], xyz[12] /* was [3][4] */;
ia = ib = 0;
TView *view = 0;
if (gPad) view = gPad->GetView();
if (!view) {
Error("SurfaceCylindrical", "no TView in current pad");
return;
}
if (iordr == 0) {
jz = 1;
jphi = 2;
nz = na;
nphi = nb;
} else {
jz = 2;
jphi = 1;
nz = nb;
nphi = na;
}
if (nphi > 180) {
Error("SurfaceCylindrical", "too many PHI sectors (%d)", nphi);
return;
}
iopt = 2;
if (*chopt == 'B' || *chopt == 'b') iopt = 1;
// P R E P A R E P H I A R R A Y
// F I N D C R I T I C A L S E C T O R S
kphi = nphi;
if (iordr == 0) ia = nz;
if (iordr != 0) ib = nz;
for (i = 1; i <= nphi; ++i) {
if (iordr == 0) ib = i;
if (iordr != 0) ia = i;
(this->*fSurfaceFunction)(ia, ib, f, tt);
if (i == 1) fAphi[0] = f[jphi - 1];
fAphi[i - 1] = (fAphi[i - 1] + f[jphi - 1]) / (float)2.;
fAphi[i] = f[jphi + 5];
}
view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
// F I N D O R D E R A L O N G Z
incrz = 1;
iz1 = 1;
view->FindNormal(0, 0, 1, z);
if ((z <= 0 && iopt == 1) || (z > 0 && iopt == 2)) {
incrz = -1;
iz1 = nz;
}
iz2 = nz - iz1 + 1;
// D R A W S U R F A C E
icodes[2] = -1; // -1 for data, 0 for front a back boxes
fEdgeIdx = 0; // constant since stacks are not (yet?) handled for surfaces
incr = 1;
iphi = iphi1;
L100:
if (iphi > nphi) goto L400;
for (iz = iz1; incrz < 0 ? iz >= iz2 : iz <= iz2; iz += incrz) {
if (iordr == 0) {ia = iz; ib = iphi;}
else {ia = iphi; ib = iz;}
(this->*fSurfaceFunction)(ia, ib, f, tt);
for (i = 1; i <= 4; ++i) {
j = i;
if (iordr == 0 && i == 2) j = 4;
if (iordr == 0 && i == 4) j = 2;
xyz[j*3 - 3] = f[i*3 - 1]*TMath::Cos(f[jphi + i*3 - 4]*kRad);
xyz[j*3 - 2] = f[i*3 - 1]*TMath::Sin(f[jphi + i*3 - 4]*kRad);
xyz[j*3 - 1] = f[jz + i*3 - 4];
ttt[j - 1] = tt[i - 1];
}
icodes[0] = ia;
icodes[1] = ib;
(this->*fDrawFace)(icodes, xyz, 4, iface, ttt);
}
// N E X T P H I
L400:
iphi += incr;
if (iphi == 0) iphi = kphi;
if (iphi > kphi) iphi = 1;
if (iphi != iphi2) goto L100;
if (incr == 0) return;
if (incr < 0) {
incr = 0;
goto L100;
}
incr = -1;
iphi = iphi1;
goto L400;
}
//______________________________________________________________________________
void TPainter3dAlgorithms::SurfaceSpherical(Int_t ipsdr, Int_t iordr, Int_t na, Int_t nb, const char *chopt)
{
// Draw surface in spheric coordinates
//
// Input: IPSDR - pseudo-rapidity flag
// IORDR - order of variables (0 - THETA,PHI; 1 - PHI,THETA)
// NA - number of steps along 1st variable
// NB - number of steps along 2nd variable
//
// FUN(IA,IB,F,T) - external routine
// IA - cell number for 1st variable
// IB - cell number for 2nd variable
// F(3,4) - face which corresponds to the cell
// F(1,*) - A
// F(2,*) - B
// F(3,*) - R
// T(4) - additional function (for example: temperature)
//
// DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
// ICODES(*) - set of codes for this face
// ICODES(1) - IA
// ICODES(2) - IB
// XYZ(3,*) - coordinates of nodes
// NP - number of nodes in face
// IFACE(NP) - face
// T(NP) - additional function
//
// CHOPT - options: 'BF' - from BACK to FRONT
// 'FB' - from FRONT to BACK
/* Initialized data */
static Int_t iface[4] = { 1,2,3,4 };
Int_t iphi, jphi, kphi, incr, nphi, iopt, iphi1, iphi2;
Int_t i, j, incrth, ith, jth, kth, nth, mth, ith1, ith2;
Int_t ia, ib, icodes[3]; // was icode[2]. One element more to differentiate front & back boxes from data
Double_t f[12] /* was [3][4] */;
Double_t tt[4];
Double_t phi;
Double_t ttt[4], xyz[12] /* was [3][4] */;
ia = ib = 0;
TView *view = 0;
if (gPad) view = gPad->GetView();
if (!view) {
Error("SurfaceSpherical", "no TView in current pad");
return;
}
if (iordr == 0) {
jth = 1;
jphi = 2;
nth = na;
nphi = nb;
} else {
jth = 2;
jphi = 1;
nth = nb;
nphi = na;
}
if (nth > 180) {
Error("SurfaceSpherical", "too many THETA sectors (%d)", nth);
return;
}
if (nphi > 180) {
Error("SurfaceSpherical", "too many PHI sectors (%d)", nphi);
return;
}
iopt = 2;
if (*chopt == 'B' || *chopt == 'b') iopt = 1;
// P R E P A R E P H I A R R A Y
// F I N D C R I T I C A L P H I S E C T O R S
kphi = nphi;
mth = nth / 2;
if (mth == 0) mth = 1;
if (iordr == 0) ia = mth;
if (iordr != 0) ib = mth;
for (i = 1; i <= nphi; ++i) {
if (iordr == 0) ib = i;
if (iordr != 0) ia = i;
(this->*fSurfaceFunction)(ia, ib, f, tt);
if (i == 1) fAphi[0] = f[jphi - 1];
fAphi[i - 1] = (fAphi[i - 1] + f[jphi - 1]) / (float)2.;
fAphi[i] = f[jphi + 5];
}
view->FindPhiSectors(iopt, kphi, fAphi, iphi1, iphi2);
// P R E P A R E T H E T A A R R A Y
if (iordr == 0) ib = 1;
if (iordr != 0) ia = 1;
for (i = 1; i <= nth; ++i) {
if (iordr == 0) ia = i;
if (iordr != 0) ib = i;
(this->*fSurfaceFunction)(ia, ib, f, tt);
if (i == 1) fAphi[0] = f[jth - 1];
fAphi[i - 1] = (fAphi[i - 1] + f[jth - 1]) / (float)2.;
fAphi[i] = f[jth + 5];
}
// D R A W S U R F A C E
icodes[2] = -1; // -1 for data, 0 for front a back boxes
fEdgeIdx = 0; // constant since stacks are not (yet?) handled for surfaces
kth = nth;
incr = 1;
iphi = iphi1;
L100:
if (iphi > nphi) goto L500;
// F I N D C R I T I C A L T H E T A S E C T O R S
if (iordr == 0) {ia = mth; ib = iphi;}
else {ia = iphi;ib = mth;}
(this->*fSurfaceFunction)(ia, ib, f, tt);
phi = (f[jphi - 1] + f[jphi + 5]) / (float)2.;
view->FindThetaSectors(iopt, phi, kth, fAphi, ith1, ith2);
incrth = 1;
ith = ith1;
L200:
if (ith > nth) goto L400;
if (iordr == 0) ia = ith;
if (iordr != 0) ib = ith;
(this->*fSurfaceFunction)(ia, ib, f, tt);
if (ipsdr == 1) {
for (i = 1; i <= 4; ++i) {
j = i;
if (iordr != 0 && i == 2) j = 4;
if (iordr != 0 && i == 4) j = 2;
xyz[j * 3 - 3] = f[i*3 - 1]*TMath::Cos(f[jphi + i*3 - 4]*kRad);
xyz[j * 3 - 2] = f[i*3 - 1]*TMath::Sin(f[jphi + i*3 - 4]*kRad);
xyz[j * 3 - 1] = f[i*3 - 1]*TMath::Cos(f[jth + i*3 - 4]*kRad) /
TMath::Sin(f[jth + i*3 - 4]*kRad);
ttt[j - 1] = tt[i - 1];
}
} else {
for (i = 1; i <= 4; ++i) {
j = i;
if (iordr != 0 && i == 2) j = 4;
if (iordr != 0 && i == 4) j = 2;
xyz[j*3 - 3] = f[i*3 - 1]*TMath::Sin(f[jth + i*3 - 4]*kRad)*TMath::Cos(f[jphi + i*3 - 4]*kRad);
xyz[j*3 - 2] = f[i*3 - 1]*TMath::Sin(f[jth + i*3 - 4]*kRad)*TMath::Sin(f[jphi + i*3 - 4]*kRad);
xyz[j*3 - 1] = f[i*3 - 1]*TMath::Cos(f[jth + i*3 - 4]*kRad);
ttt[j - 1] = tt[i - 1];
}
}
icodes[0] = ia;
icodes[1] = ib;
(this->*fDrawFace)(icodes, xyz, 4, iface, ttt);
// N E X T T H E T A
L400:
ith += incrth;
if (ith == 0) ith = kth;
if (ith > kth) ith = 1;
if (ith != ith2) goto L200;
if (incrth == 0) goto L500;
if (incrth < 0) {
incrth = 0;
goto L200;
}
incrth = -1;
ith = ith1;
goto L400;
// N E X T P H I
L500:
iphi += incr;
if (iphi == 0) iphi = kphi;
if (iphi > kphi) iphi = 1;
if (iphi != iphi2) goto L100;
if (incr == 0) return;
if (incr < 0) {
incr = 0;
goto L100;
}
incr = -1;
iphi = iphi1;
goto L500;
}
//______________________________________________________________________________
void TPainter3dAlgorithms::SurfaceProperty(Double_t qqa, Double_t qqd, Double_t qqs, Int_t nnqs, Int_t &irep)
{
// Set surface property coefficients
//
// Input: QQA - diffusion coefficient for diffused light [0.,1.]
// QQD - diffusion coefficient for direct light [0.,1.]
// QQS - diffusion coefficient for reflected light [0.,1.]
// NNCS - power coefficient for reflected light (.GE.1)
//
// --
// Lightness model formula: Y = YD*QA + > YLi*(QD*cosNi+QS*cosRi)
// --
//
// Output: IREP - reply : 0 - O.K.
// -1 - error in cooefficients
irep = 0;
if (qqa < 0 || qqa > 1 || qqd < 0 || qqd > 1 || qqs < 0 || qqs > 1 || nnqs < 1) {
Error("SurfaceProperty", "error in coefficients");
irep = -1;
return;
}
fQA = qqa;
fQD = qqd;
fQS = qqs;
fNqs = nnqs;
}
//______________________________________________________________________________
void TPainter3dAlgorithms::ImplicitFunction(Double_t *rmin, Double_t *rmax,
Int_t nx, Int_t ny, Int_t nz, const char *chopt)
{
// Draw implicit function FUN(X,Y,Z) = 0 in cartesian coordinates using
// hidden surface removal algorithm "Painter".
//
// Input: FUN - external routine FUN(X,Y,Z)
// RMIN(3) - min scope coordinates
// RMAX(3) - max scope coordinates
// NX - number of steps along X
// NY - number of steps along Y
// NZ - number of steps along Z
//
// DRFACE(ICODES,XYZ,NP,IFACE,T) - routine for face drawing
// ICODES(*) - set of codes for this face
// ICODES(1) - 1
// ICODES(2) - 1
// ICODES(3) - 1
// NP - number of nodes in face
// IFACE(NP) - face
// T(NP) - additional function (lightness)
//
// CHOPT - options: 'BF' - from BACK to FRONT
// 'FB' - from FRONT to BACK
Int_t ix, iy, iz;
Int_t ix1, iy1, iz1;
Int_t ix2, iy2, iz2;
Int_t incr, incrx, incry, incrz;
Int_t icodes[3], i, i1, i2, k, nnod, ntria;
Double_t x1=0, x2=0, y1, y2, z1, z2;
Double_t dx, dy, dz;
Double_t p[8][3], pf[8], pn[8][3], t[3], fsurf, w;
Double_t xyz[kNmaxp][3], xyzn[kNmaxp][3], grad[kNmaxp][3];
Double_t dtria[kNmaxt][6], abcd[kNmaxt][4];
Int_t itria[kNmaxt][3], iorder[kNmaxt];
TView *view = 0;
if (gPad) view = gPad->GetView();
if (!view) {
Error("ImplicitFunction", "no TView in current pad");
return;
}
Double_t *tnorm = view->GetTnorm();
if (!tnorm) return;
// D E F I N E O R D E R O F D R A W I N G
if (*chopt == 'B' || *chopt == 'b') {
incrx = +1;
incry = +1;
incrz = +1;
} else {
incrx = -1;
incry = -1;
incrz = -1;
}
if (tnorm[8] < 0.) incrx =-incrx;
if (tnorm[9] < 0.) incry =-incry;
if (tnorm[10] < 0.) incrz =-incrz;
ix1 = 1;
iy1 = 1;
iz1 = 1;
if (incrx == -1) ix1 = nx;
if (incry == -1) iy1 = ny;
if (incrz == -1) iz1 = nz;
ix2 = nx - ix1 + 1;
iy2 = ny - iy1 + 1;
iz2 = nz - iz1 + 1;
dx = (rmax[0]-rmin[0]) / nx;
dy = (rmax[1]-rmin[1]) / ny;
dz = (rmax[2]-rmin[2]) / nz;
// Define the colors used to draw the function
Float_t r=0., g=0., b=0., hue, light, satur, light2;
TColor *colref = gROOT->GetColor(fgCurrentF3->GetFillColor());
if (colref) colref->GetRGB(r, g, b);
TColor::RGBtoHLS(r, g, b, hue, light, satur);
TColor *acol;
acol = gROOT->GetColor(kF3FillColor1);
if (acol) acol->SetRGB(r, g, b);
if (light >= 0.5) {
light2 = .5*light;
} else {
light2 = 1-.5*light;
}
TColor::HLStoRGB(hue, light2, satur, r, g, b);
acol = gROOT->GetColor(kF3FillColor2);
if (acol) acol->SetRGB(r, g, b);
colref = gROOT->GetColor(fgCurrentF3->GetLineColor());
if (colref) colref->GetRGB(r, g, b);
acol = gROOT->GetColor(kF3LineColor);
if (acol) acol->SetRGB(r, g, b);
// D R A W F U N C T I O N
for (iz = iz1; incrz < 0 ? iz >= iz2 : iz <= iz2; iz += incrz) {
z1 = (iz-1)*dz + rmin[2];
z2 = z1 + dz;
p[0][2] = z1;
p[1][2] = z1;
p[2][2] = z1;
p[3][2] = z1;
p[4][2] = z2;
p[5][2] = z2;
p[6][2] = z2;
p[7][2] = z2;
for (iy = iy1; incry < 0 ? iy >= iy2 : iy <= iy2; iy += incry) {
y1 = (iy-1)*dy + rmin[1];
y2 = y1 + dy;
p[0][1] = y1;
p[1][1] = y1;
p[2][1] = y2;
p[3][1] = y2;
p[4][1] = y1;
p[5][1] = y1;
p[6][1] = y2;
p[7][1] = y2;
if (incrx == +1) {
x2 = rmin[0];
pf[1] = fgCurrentF3->Eval(x2,y1,z1);
pf[2] = fgCurrentF3->Eval(x2,y2,z1);
pf[5] = fgCurrentF3->Eval(x2,y1,z2);
pf[6] = fgCurrentF3->Eval(x2,y2,z2);
} else {
x1 = rmax[0];
pf[0] = fgCurrentF3->Eval(x1,y1,z1);
pf[3] = fgCurrentF3->Eval(x1,y2,z1);
pf[4] = fgCurrentF3->Eval(x1,y1,z2);
pf[7] = fgCurrentF3->Eval(x1,y2,z2);
}
for (ix = ix1; incrx < 0 ? ix >= ix2 : ix <= ix2; ix += incrx) {
icodes[0] = ix;
icodes[1] = iy;
icodes[2] = iz;
if (incrx == +1) {
x1 = x2;
x2 = x2 + dx;
pf[0] = pf[1];
pf[3] = pf[2];
pf[4] = pf[5];
pf[7] = pf[6];
pf[1] = fgCurrentF3->Eval(x2,y1,z1);
pf[2] = fgCurrentF3->Eval(x2,y2,z1);
pf[5] = fgCurrentF3->Eval(x2,y1,z2);
pf[6] = fgCurrentF3->Eval(x2,y2,z2);
} else {
x2 = x1;
x1 = x1 - dx;
pf[1] = pf[0];
pf[2] = pf[3];
pf[5] = pf[4];
pf[6] = pf[7];
pf[0] = fgCurrentF3->Eval(x1,y1,z1);
pf[3] = fgCurrentF3->Eval(x1,y2,z1);
pf[4] = fgCurrentF3->Eval(x1,y1,z2);
pf[7] = fgCurrentF3->Eval(x1,y2,z2);
}
if (pf[0] >= -kFdel) goto L110;
if (pf[1] >= -kFdel) goto L120;
if (pf[2] >= -kFdel) goto L120;
if (pf[3] >= -kFdel) goto L120;
if (pf[4] >= -kFdel) goto L120;
if (pf[5] >= -kFdel) goto L120;
if (pf[6] >= -kFdel) goto L120;
if (pf[7] >= -kFdel) goto L120;
goto L510;
L110:
if (pf[1] < -kFdel) goto L120;
if (pf[2] < -kFdel) goto L120;
if (pf[3] < -kFdel) goto L120;
if (pf[4] < -kFdel) goto L120;
if (pf[5] < -kFdel) goto L120;
if (pf[6] < -kFdel) goto L120;
if (pf[7] < -kFdel) goto L120;
goto L510;
L120:
p[0][0] = x1;
p[1][0] = x2;
p[2][0] = x2;
p[3][0] = x1;
p[4][0] = x1;
p[5][0] = x2;
p[6][0] = x2;
p[7][0] = x1;
// F I N D G R A D I E N T S
// Find X-gradient
if (ix == 1) {
pn[0][0] = (pf[1] - pf[0]) / dx;
pn[3][0] = (pf[2] - pf[3]) / dx;
pn[4][0] = (pf[5] - pf[4]) / dx;
pn[7][0] = (pf[6] - pf[7]) / dx;
} else {
pn[0][0] = (pf[1] - fgCurrentF3->Eval(x1-dx,y1,z1)) / (dx + dx);
pn[3][0] = (pf[2] - fgCurrentF3->Eval(x1-dx,y2,z1)) / (dx + dx);
pn[4][0] = (pf[5] - fgCurrentF3->Eval(x1-dx,y1,z2)) / (dx + dx);
pn[7][0] = (pf[6] - fgCurrentF3->Eval(x1-dx,y2,z2)) / (dx + dx);
}
if (ix == nx) {
pn[1][0] = (pf[1] - pf[0]) / dx;
pn[2][0] = (pf[2] - pf[3]) / dx;
pn[5][0] = (pf[5] - pf[4]) / dx;
pn[6][0] = (pf[6] - pf[7]) / dx;
} else {
pn[1][0] = (fgCurrentF3->Eval(x2+dx,y1,z1) - pf[0]) / (dx + dx);
pn[2][0] = (fgCurrentF3->Eval(x2+dx,y2,z1) - pf[3]) / (dx + dx);
pn[5][0] = (fgCurrentF3->Eval(x2+dx,y1,z2) - pf[4]) / (dx + dx);
pn[6][0] = (fgCurrentF3->Eval(x2+dx,y2,z2) - pf[7]) / (dx + dx);
}
// Find Y-gradient
if (iy == 1) {
pn[0][1] = (pf[3] - pf[0]) / dy;
pn[1][1] = (pf[2] - pf[1]) / dy;
pn[4][1] = (pf[7] - pf[4]) / dy;
pn[5][1] = (pf[6] - pf[5]) / dy;
} else {
pn[0][1] = (pf[3] - fgCurrentF3->Eval(x1,y1-dy,z1)) / (dy + dy);
pn[1][1] = (pf[2] - fgCurrentF3->Eval(x2,y1-dy,z1)) / (dy + dy);
pn[4][1] = (pf[7] - fgCurrentF3->Eval(x1,y1-dy,z2)) / (dy + dy);
pn[5][1] = (pf[6] - fgCurrentF3->Eval(x2,y1-dy,z2)) / (dy + dy);
}
if (iy == ny) {
pn[2][1] = (pf[2] - pf[1]) / dy;
pn[3][1] = (pf[3] - pf[0]) / dy;
pn[6][1] = (pf[6] - pf[5]) / dy;
pn[7][1] = (pf[7] - pf[4]) / dy;
} else {
pn[2][1] = (fgCurrentF3->Eval(x2,y2+dy,z1) - pf[1]) / (dy + dy);
pn[3][1] = (fgCurrentF3->Eval(x1,y2+dy,z1) - pf[0]) / (dy + dy);
pn[6][1] = (fgCurrentF3->Eval(x2,y2+dy,z2) - pf[5]) / (dy + dy);
pn[7][1] = (fgCurrentF3->Eval(x1,y2+dy,z2) - pf[4]) / (dy + dy);
}
// Find Z-gradient
if (iz == 1) {
pn[0][2] = (pf[4] - pf[0]) / dz;
pn[1][2] = (pf[5] - pf[1]) / dz;
pn[2][2] = (pf[6] - pf[2]) / dz;
pn[3][2] = (pf[7] - pf[3]) / dz;
} else {
pn[0][2] = (pf[4] - fgCurrentF3->Eval(x1,y1,z1-dz)) / (dz + dz);
pn[1][2] = (pf[5] - fgCurrentF3->Eval(x2,y1,z1-dz)) / (dz + dz);
pn[2][2] = (pf[6] - fgCurrentF3->Eval(x2,y2,z1-dz)) / (dz + dz);
pn[3][2] = (pf[7] - fgCurrentF3->Eval(x1,y2,z1-dz)) / (dz + dz);
}
if (iz == nz) {
pn[4][2] = (pf[4] - pf[0]) / dz;
pn[5][2] = (pf[5] - pf[1]) / dz;
pn[6][2] = (pf[6] - pf[2]) / dz;
pn[7][2] = (pf[7] - pf[3]) / dz;
} else {
pn[4][2] = (fgCurrentF3->Eval(x1,y1,z2+dz) - pf[0]) / (dz + dz);
pn[5][2] = (fgCurrentF3->Eval(x2,y1,z2+dz) - pf[1]) / (dz + dz);
pn[6][2] = (fgCurrentF3->Eval(x2,y2,z2+dz) - pf[2]) / (dz + dz);
pn[7][2] = (fgCurrentF3->Eval(x1,y2,z2+dz) - pf[3]) / (dz + dz);
}
fsurf = 0.;
MarchingCube(fsurf, p, pf, pn, nnod, ntria, xyz, grad, itria);
if (ntria == 0) goto L510;
for ( i=1 ; i<=nnod ; i++ ) {
view->WCtoNDC(&xyz[i-1][0], &xyzn[i-1][0]);
Luminosity(&grad[i-1][0], w);
grad[i-1][0] = w;
}
ZDepth(xyzn, ntria, itria, dtria, abcd, (Int_t*)iorder);
if (ntria == 0) goto L510;
incr = 1;
if (*chopt == 'B' || *chopt == 'b') incr =-1;
i1 = 1;
if (incr == -1) i1 = ntria;
i2 = ntria - i1 + 1;
// If clipping box is on do not draw the triangles
if (fgF3Clipping) {
if(x2<=fgF3XClip && y2 <=fgF3YClip && z2>=fgF3ZClip) goto L510;
}
// Draw triangles
for (i=i1; incr < 0 ? i >= i2 : i <= i2; i += incr) {
k = iorder[i-1];
t[0] = grad[TMath::Abs(itria[k-1][0])-1][0];
t[1] = grad[TMath::Abs(itria[k-1][1])-1][0];
t[2] = grad[TMath::Abs(itria[k-1][2])-1][0];
(this->*fDrawFace)(icodes, (Double_t*)xyz, 3, &itria[k-1][0], t);
}
L510:
continue;
}
}
}
}
//______________________________________________________________________________
void TPainter3dAlgorithms::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
// aproximating the isosurface F(x,y,z)=Fiso inside the cube
// (improved version)
//
// Input: FISO - function value for isosurface
// P(3,8) - cube vertexes
// F(8) - function values at the vertexes
// G(3,8) - function gradients at the vertexes
//
// Output: NNOD - number of nodes (maximum 13)
// NTRIA - number of triangles (maximum 12)
// XYZ(3,*) - nodes
// GRAD(3,*) - node normales (not normalized)
// ITRIA(3,*) - triangles
//
static Int_t irota[24][8] = { { 1,2,3,4,5,6,7,8 }, { 2,3,4,1,6,7,8,5 },
{ 3,4,1,2,7,8,5,6 }, { 4,1,2,3,8,5,6,7 },
{ 6,5,8,7,2,1,4,3 }, { 5,8,7,6,1,4,3,2 },
{ 8,7,6,5,4,3,2,1 }, { 7,6,5,8,3,2,1,4 },
{ 2,6,7,3,1,5,8,4 }, { 6,7,3,2,5,8,4,1 },
{ 7,3,2,6,8,4,1,5 }, { 3,2,6,7,4,1,5,8 },
{ 5,1,4,8,6,2,3,7 }, { 1,4,8,5,2,3,7,6 },
{ 4,8,5,1,3,7,6,2 }, { 8,5,1,4,7,6,2,3 },
{ 5,6,2,1,8,7,3,4 }, { 6,2,1,5,7,3,4,8 },
{ 2,1,5,6,3,4,8,7 }, { 1,5,6,2,4,8,7,3 },
{ 4,3,7,8,1,2,6,5 }, { 3,7,8,4,2,6,5,1 },
{ 7,8,4,3,6,5,1,2 }, { 8,4,3,7,5,1,2,6 } };
static Int_t iwhat[21] = { 1,3,5,65,50,67,74,51,177,105,113,58,165,178,
254,252,250,190,205,188,181 };
Int_t j, i, i1, i2, i3, ir, irt=0, k, k1, k2, incr, icase=0, n;
Int_t itr[3];
nnod = 0;
ntria = 0;
// F I N D C O N F I G U R A T I O N T Y P E
for ( i=1; i<=8 ; i++) {
fF8[i-1] = f[i-1] - fiso;
}
for ( ir=1 ; ir<=24 ; ir++ ) {
k = 0;
incr = 1;
for ( i=1 ; i<=8 ; i++ ) {
if (fF8[irota[ir-1][i-1]-1] >= 0.) k = k + incr;
incr = incr + incr;
}
if (k==0 || k==255) return;
for ( i=1 ; i<=21 ; i++ ) {
if (k != iwhat[i-1]) continue;
icase = i;
irt = ir;
goto L200;
}
}
// R O T A T E C U B E
L200:
for ( i=1 ; i<=8 ; i++ ) {
k = irota[irt-1][i-1];
fF8[i-1] = f[k-1] - fiso;
fP8[i-1][0] = p[k-1][0];
fP8[i-1][1] = p[k-1][1];
fP8[i-1][2] = p[k-1][2];
fG8[i-1][0] = g[k-1][0];
fG8[i-1][1] = g[k-1][1];
fG8[i-1][2] = g[k-1][2];
}
// V A R I O U S C O N F I G U R A T I O N S
n = 0;
switch ((int)icase) {
case 1:
case 15:
MarchingCubeCase00(1, 4, 9, 0, 0, 0, nnod, ntria, xyz, grad, itria);
goto L400;
case 2:
case 16:
MarchingCubeCase00(2, 4, 9, 10, 0, 0, nnod, ntria, xyz, grad, itria);
goto L400;
case 3:
case 17:
MarchingCubeCase03(nnod, ntria, xyz, grad, itria);
goto L400;
case 4:
case 18:
MarchingCubeCase04(nnod, ntria, xyz, grad, itria);
goto L400;
case 5:
case 19:
MarchingCubeCase00(6, 2, 1, 9, 8, 0, nnod, ntria, xyz, grad, itria);
goto L400;
case 6:
case 20:
MarchingCubeCase06(nnod, ntria, xyz, grad, itria);
goto L400;
case 7:
case 21:
MarchingCubeCase07(nnod, ntria, xyz, grad, itria);
goto L400;
case 8:
MarchingCubeCase00(2, 4, 8, 6, 0, 0, nnod, ntria, xyz, grad, itria);
goto L500;
case 9:
MarchingCubeCase00(1, 4, 12, 7, 6, 10, nnod, ntria, xyz, grad, itria);
goto L500;
case 0:
MarchingCubeCase10(nnod, ntria, xyz, grad, itria);
goto L500;
case 11:
MarchingCubeCase00(1, 4, 8, 7, 11, 10, nnod, ntria, xyz, grad, itria);
goto L500;
case 12:
MarchingCubeCase12(nnod, ntria, xyz, grad, itria);
goto L500;
case 13:
MarchingCubeCase13(nnod, ntria, xyz, grad, itria);
goto L500;
case 14:
MarchingCubeCase00(1, 9, 12, 7, 6, 2, nnod, ntria, xyz, grad, itria);
goto L500;
}
// I F N E E D E D , I N V E R T T R I A N G L E S
L400:
if (ntria == 0) return;
if (icase <= 14) goto L500;
for ( i=1; i<=ntria ; i++ ) {
i1 = TMath::Abs(itria[i-1][0]);
i2 = TMath::Abs(itria[i-1][1]);
i3 = TMath::Abs(itria[i-1][2]);
if (itria[i-1][2] < 0) i1 =-i1;
if (itria[i-1][1] < 0) i3 =-i3;
if (itria[i-1][0] < 0) i2 =-i2;
itria[i-1][0] = i1;
itria[i-1][1] = i3;
itria[i-1][2] = i2;
}
// R E M O V E V E R Y S M A L L T R I A N G L E S
L500:
n = n + 1;
L510:
if (n > ntria) return;
for ( i=1 ; i<=3 ; i++ ) {
i1 = i;
i2 = i + 1;
if (i == 3) i2 = 1;
k1 = TMath::Abs(itria[n-1][i1-1]);
k2 = TMath::Abs(itria[n-1][i2-1]);
if (TMath::Abs(xyz[k1-1][0]-xyz[k2-1][0]) > kDel) continue;
if (TMath::Abs(xyz[k1-1][1]-xyz[k2-1][1]) > kDel) continue;
if (TMath::Abs(xyz[k1-1][2]-xyz[k2-1][2]) > kDel) continue;
i3 = i - 1;
if (i == 1) i3 = 3;
goto L530;
}
goto L500;
// R E M O V E T R I A N G L E
L530:
for ( i=1 ; i<=3 ; i++ ) {
itr[i-1] = itria[n-1][i-1];
itria[n-1][i-1] = itria[ntria-1][i-1];
}
ntria = ntria - 1;
if (ntria == 0) return;
if (itr[i2-1]*itr[i3-1] > 0) goto L510;
// C O R R E C T O T H E R T R I A N G L E S
if (itr[i2-1] < 0) {
k1 =-itr[i2-1];
k2 =-TMath::Abs(itr[i3-1]);
}
if (itr[i3-1] < 0) {
k1 =-itr[i3-1];
k2 =-TMath::Abs(itr[i1-1]);
}
for ( j=1 ; j<=ntria ; j++ ) {
for ( i=1 ; i<=3 ; i++ ) {
if (itria[j-1][i-1] != k2) continue;
i2 = TMath::Abs(itria[j-1][0]);
if (i != 3) i2 = TMath::Abs(itria[j-1][i]);
if (i2 == k1) itria[j-1][i-1] =-itria[j-1][i-1];
goto L560;
}
L560:
continue;
}
goto L510;
}
//______________________________________________________________________________
void TPainter3dAlgorithms::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
//
// Input: K1,...,K6 - edges intersected with isosurface
//
// Output: the same as for IHMCUB
static Int_t it[4][4][3] = { { { 1,2, 3 }, { 0,0, 0 }, { 0,0, 0 }, { 0,0, 0 } },
{ { 1,2,-3 }, {-1,3, 4 }, { 0,0, 0 }, { 0,0, 0 } },
{ { 1,2,-3 }, {-1,3,-4 }, {-1,4, 5 }, { 0,0, 0 } },
{ { 1,2,-3 }, {-1,3,-4 }, {-4,6,-1 }, { 4,5,-6 } }
};
Int_t it2[4][3], i, j;
Int_t ie[6];
// S E T N O D E S & N O R M A L E S
ie[0] = k1;
ie[1] = k2;
ie[2] = k3;
ie[3] = k4;
ie[4] = k5;
ie[5] = k6;
nnod = 6;
if (ie[5] == 0) nnod = 5;
if (ie[4] == 0) nnod = 4;
if (ie[3] == 0) nnod = 3;
MarchingCubeFindNodes(nnod, ie, xyz, grad);
// S E T T R I A N G L E S
ntria = nnod - 2;
// Copy "it" into a 2D matrix to be passed to MarchingCubeSetTriangles
for ( i=0; i<3 ; i++) {
for ( j=0; j<4 ; j++) {
it2[j][i] = it[ntria-1][j][i];
}
}
MarchingCubeSetTriangles(ntria, it2, itria);
}
//______________________________________________________________________________
void TPainter3dAlgorithms::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
//
// Input: see common HCMCUB
//
// Output: the same as for IHMCUB
Double_t f0;
static Int_t ie[6] = { 4,9,1, 2,11,3 };
static Int_t it1[2][3] = { { 1,2,3 }, { 4,5,6 } };
static Int_t it2[4][3] = { { 1,2,-5 }, { -1,5,6 }, { 5,-2,4 }, { -4,2,3 } };
// S E T N O D E S & N O R M A L E S
nnod = 6;
MarchingCubeFindNodes(nnod, ie, xyz, grad);
// F I N D C O N F I G U R A T I O N
f0 = (fF8[0]*fF8[2]-fF8[1]*fF8[3]) / (fF8[0]+fF8[2]-fF8[1]-fF8[3]);
if (f0>=0. && fF8[0]>=0.) goto L100;
if (f0<0. && fF8[0]<0.) goto L100;
ntria = 2;
MarchingCubeSetTriangles(ntria, it1, itria);
return;
// N O T S E P A R A T E D F R O N T F A C E
L100:
ntria = 4;
MarchingCubeSetTriangles(ntria, it2, itria);
}
//______________________________________________________________________________
void TPainter3dAlgorithms::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
//
// Input: see common HCMCUB
//
// Output: the same as for IHMCUB
Int_t irep;
static Int_t ie[6] = { 4,9,1, 7,11,6 };
static Int_t it1[2][3] = { { 1,2,3 }, { 4,5,6 } };
static Int_t it2[6][3] = { { 1,2,4 }, { 2,3,6 }, { 3,1,5 },
{ 4,5,1 }, { 5,6,3 }, { 6,4,2 } };
// S E T N O D E S & N O R M A L E S
nnod = 6;
MarchingCubeFindNodes(nnod, ie, xyz, grad);
// 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 ?
MarchingCubeSurfacePenetration(fF8[0], fF8[1], fF8[2], fF8[3],
fF8[4], fF8[5], fF8[6], fF8[7], irep);
if (irep == 0) {
ntria = 2;
MarchingCubeSetTriangles(ntria, it1, itria);
} else {
ntria = 6;
MarchingCubeSetTriangles(ntria, it2, itria);
}
}
//______________________________________________________________________________
void TPainter3dAlgorithms::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
//
// Input: see common HCMCUB
//
// Output: the same as for IHMCUB
Double_t f0;
Int_t irep;
static Int_t ie[7] = { 2,4,9,10, 6,7,11 };
static Int_t it1[5][3] = { { 6,7,-1 }, { -6,1,2 }, { 6,2,3 }, { 6,3,-4 }, { -6,4,5 } };
static Int_t it2[3][3] = { { 1,2,-3 }, { -1,3,4 }, { 5,6,7 } };
static Int_t it3[7][3] = { { 6,7,-1 }, { -6,1,2 }, { 6,2,3 }, { 6,3,-4 }, { -6,4,5 },
{ 1,7,-5 }, { -1,5,4 } };
// S E T N O D E S & N O R M A L E S
nnod = 7;
MarchingCubeFindNodes(nnod, ie, xyz, grad);
// F I N D C O N F I G U R A T I O N
f0 = (fF8[1]*fF8[6]-fF8[5]*fF8[2]) / (fF8[1]+fF8[6]-fF8[5]-fF8[2]);
if (f0>=0. && fF8[1]>=0.) goto L100;
if (f0<0. && fF8[1]<0.) goto L100;
// 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 ?
MarchingCubeSurfacePenetration(fF8[2], fF8[1], fF8[5], fF8[6],
fF8[3], fF8[0], fF8[4], fF8[7], irep);
if (irep == 1) {
ntria = 7;
MarchingCubeSetTriangles(ntria, it3, itria);
} else {
ntria = 3;
MarchingCubeSetTriangles(ntria, it2, itria);
}
return;
// N O T S E P A R A T E D R I G H T F A C E
L100:
ntria = 5;
MarchingCubeSetTriangles(ntria, it1, itria);
}
//______________________________________________________________________________
void TPainter3dAlgorithms::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
//
// Input: see common HCMCUB
//
// Output: the same as for IHMCUB
Double_t f1, f2, f3;
Int_t icase, irep;
static Int_t ie[9] = { 3,12,4, 1,10,2, 11,6,7 };
static Int_t it[9][9][3] = {
{{ 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}},
{{ 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}},
{{ 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}},
{{-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}},
{{ 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}},
{{-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}},
{{ 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}},
{{ 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}},
{{ -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}}
};
Int_t it2[9][3], i, j;
// S E T N O D E S & N O R M A L E S
nnod = 9;
MarchingCubeFindNodes(nnod, ie, xyz, grad);
// F I N D C O N F I G U R A T I O N
f1 = (fF8[2]*fF8[5]-fF8[1]*fF8[6]) / (fF8[2]+fF8[5]-fF8[1]-fF8[6]);
f2 = (fF8[2]*fF8[7]-fF8[3]*fF8[6]) / (fF8[2]+fF8[7]-fF8[3]-fF8[6]);
f3 = (fF8[2]*fF8[0]-fF8[1]*fF8[3]) / (fF8[2]+fF8[0]-fF8[1]-fF8[3]);
icase = 1;
if (f1>=0. && fF8[2] <0.) icase = icase + 1;
if (f1 <0. && fF8[2]>=0.) icase = icase + 1;
if (f2>=0. && fF8[2] <0.) icase = icase + 2;
if (f2 <0. && fF8[2]>=0.) icase = icase + 2;
if (f3>=0. && fF8[2] <0.) icase = icase + 4;
if (f3 <0. && fF8[2]>=0.) icase = icase + 4;
ntria = 5;
switch ((int)icase) {
case 1: goto L100;
case 2: goto L400;
case 3: goto L400;
case 4: goto L200;
case 5: goto L400;
case 6: goto L200;
case 7: goto L200;
case 8: goto L300;
}
L100:
ntria = 3;
goto L400;
// F I N D A D D I T I O N A L P O I N T
L200:
nnod = 10;
ntria = 9;
// Copy "it" into a 2D matrix to be passed to MarchingCubeMiddlePoint
for ( i=0; i<3 ; i++) {
for ( j=0; j<9 ; j++) {
it2[j][i] = it[icase-1][j][i];
}
}
MarchingCubeMiddlePoint(9, xyz, grad, it2, &xyz[nnod-1][0], &grad[nnod-1][0]);
goto L400;
// 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 ?
L300:
MarchingCubeSurfacePenetration(fF8[3], fF8[2], fF8[6], fF8[7],
fF8[0], fF8[1], fF8[5], fF8[4], irep);
if (irep != 2) goto L400;
ntria = 9;
icase = 9;
// S E T T R I A N G L E S
L400:
// Copy "it" into a 2D matrix to be passed to MarchingCubeSetTriangles
for ( i=0; i<3 ; i++) {
for ( j=0; j<9 ; j++) {
it2[j][i] = it[icase-1][j][i];
}
}
MarchingCubeSetTriangles(ntria, it2, itria);
}
//______________________________________________________________________________
void TPainter3dAlgorithms::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
//
// Input: see common HCMCUB
//
// Output: the same as for IHMCUB
Double_t f1, f2;
Int_t icase, irep;
static Int_t ie[8] = { 1,3,12,9, 5,7,11,10 };
static Int_t it[6][8][3] = {
{{1,2,-3}, {-1,3,4}, {5,6,-7}, {-5,7,8}, { 0,0,0}, { 0,0,0}, { 0,0,0}, { 0,0,0}},
{{ 9,1,2}, { 9,2,3}, { 9,3,4}, { 9,4,5}, { 9,5,6}, { 9,6,7}, { 9,7,8}, { 9,8,1}},
{{ 9,1,2}, { 9,4,1}, { 9,3,4}, { 9,6,3}, { 9,5,6}, { 9,8,5}, { 9,7,8}, { 9,2,7}},
{{1,2,-7}, {-1,7,8}, {5,6,-3}, {-5,3,4}, { 0,0,0}, { 0,0,0}, { 0,0,0}, { 0,0,0}},
{{1,2,-7}, {-1,7,8}, {2,3,-6}, {-2,6,7}, {3,4,-5}, {-3,5,6}, {4,1,-8}, {-4,8,5}},
{{1,2,-3}, {-1,3,4}, {2,7,-6}, {-2,6,3}, {7,8,-5}, {-7,5,6}, {8,1,-4}, {-8,4,5}}
};
Int_t it2[8][3], i, j;
// S E T N O D E S & N O R M A L E S
nnod = 8;
MarchingCubeFindNodes(nnod, ie, xyz, grad);
// F I N D C O N F I G U R A T I O N
f1 = (fF8[0]*fF8[5]-fF8[1]*fF8[4]) / (fF8[0]+fF8[5]-fF8[1]-fF8[4]);
f2 = (fF8[3]*fF8[6]-fF8[2]*fF8[7]) / (fF8[3]+fF8[6]-fF8[2]-fF8[5]);
icase = 1;
if (f1 >= 0.) icase = icase + 1;
if (f2 >= 0.) icase = icase + 2;
if (icase==1 || icase==4) goto L100;
// D I F F E R E N T T O P A N D B O T T O M
nnod = 9;
ntria = 8;
// Copy "it" into a 2D matrix to be passed to MarchingCubeMiddlePoint
for ( i=0; i<3 ; i++) {
for ( j=0; j<8 ; j++) {
it2[j][i] = it[icase-1][j][i];
}
}
MarchingCubeMiddlePoint(8, xyz, grad, it2, &xyz[nnod-1][0], &grad[nnod-1][0]);
goto L200;
// 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 ?
L100:
MarchingCubeSurfacePenetration(fF8[0], fF8[1], fF8[5], fF8[4],
fF8[3], fF8[2], fF8[6], fF8[7], irep);
ntria = 4;
if (irep == 0) goto L200;
// "B O T T L E N E C K"
ntria = 8;
if (icase == 1) icase = 5;
if (icase == 4) icase = 6;
// S E T T R I A N G L E S
L200:
// Copy "it" into a 2D matrix to be passed to MarchingCubeSetTriangles
for ( i=0; i<3 ; i++) {
for ( j=0; j<8 ; j++) {
it2[j][i] = it[icase-1][j][i];
}
}
MarchingCubeSetTriangles(ntria, it2, itria);
}
//______________________________________________________________________________
void TPainter3dAlgorithms::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
//
// Input: see common HCMCUB
//
// Output: the same as for IHMCUB
Double_t f1, f2;
Int_t icase, irep;
static Int_t ie[8] = { 3,12,4, 1,9,8,6,2 };
static Int_t it[6][8][3] = {
{{ 1,2,3}, {4,5,-6}, {-4,6,8}, { 6,7,8}, { 0,0,0}, { 0,0,0}, { 0,0,0}, { 0,0,0}},
{{-9,1,2}, {9,2,-3}, {-9,3,4}, {9,4,-5}, {-9,5,6}, {9,6,-7}, {-9,7,8}, {9,8,-1}},
{{9,1,-2}, {-9,2,6}, {9,6,-7}, {-9,7,8}, {9,8,-4}, {-9,4,5}, {9,5,-3}, {-9,3,1}},
{{ 3,4,5}, {1,2,-6}, {-1,6,8}, { 6,7,8}, { 0,0,0}, { 0,0,0}, { 0,0,0}, { 0,0,0}},
{{ 7,8,6}, {6,8,-1}, {-6,1,2}, {3,1,-8}, {-3,8,4}, { 3,4,5}, {3,5,-6}, {-3,6,2}},
{{ 7,8,6}, {6,8,-4}, {-6,4,5}, {3,4,-8}, {-3,8,1}, { 3,1,2}, {3,2,-6}, {-3,6,5}}
};
Int_t it2[8][3], i, j;
// S E T N O D E S & N O R M A L E S
nnod = 8;
MarchingCubeFindNodes(nnod, ie, xyz, grad);
// F I N D C O N F I G U R A T I O N
f1 = (fF8[0]*fF8[2]-fF8[1]*fF8[3]) / (fF8[0]+fF8[2]-fF8[1]-fF8[3]);
f2 = (fF8[0]*fF8[7]-fF8[3]*fF8[4]) / (fF8[0]+fF8[7]-fF8[3]-fF8[4]);
icase = 1;
if (f1 >= 0.) icase = icase + 1;
if (f2 >= 0.) icase = icase + 2;
if (icase==1 || icase==4) goto L100;
// F I N D A D D I T I O N A L P O I N T
nnod = 9;
ntria = 8;
// Copy "it" into a 2D matrix to be passed to MarchingCubeMiddlePoint
for ( i=0; i<3 ; i++) {
for ( j=0; j<8 ; j++) {
it2[j][i] = it[icase-1][j][i];
}
}
MarchingCubeMiddlePoint(8, xyz, grad, it2, &xyz[nnod-1][0], &grad[nnod-1][0]);
goto L200;
// 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 ?
L100:
MarchingCubeSurfacePenetration(fF8[0], fF8[1], fF8[2], fF8[3],
fF8[4], fF8[5], fF8[6], fF8[7], irep);
ntria = 4;
if (irep != 1) goto L200;
// "B O T T L E N E C K"
ntria = 8;
if (icase == 1) icase = 5;
if (icase == 4) icase = 6;
// S E T T R I A N G L E S
L200:
// Copy "it" into a 2D matrix to be passed to MarchingCubeSetTriangles
for ( i=0; i<3 ; i++) {
for ( j=0; j<8 ; j++) {
it2[j][i] = it[icase-1][j][i];
}
}
MarchingCubeSetTriangles(ntria, it2, itria);
}
//______________________________________________________________________________
void TPainter3dAlgorithms::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
//
// Input: see common HCMCUB
//
// Output: the same as for IHMCUB
Double_t ff[8];
Double_t f1, f2, f3, f4;
Int_t nr, nf, i, k, incr, n, kr, icase, irep;
static Int_t irota[12][8] = {
{1,2,3,4,5,6,7,8}, {1,5,6,2,4,8,7,3}, {1,4,8,5,2,3,7,6},
{3,7,8,4,2,6,5,1}, {3,2,6,7,4,1,5,8}, {3,4,1,2,7,8,5,6},
{6,7,3,2,5,8,4,1}, {6,5,8,7,2,1,4,3}, {6,2,1,5,7,3,4,8},
{8,4,3,7,5,1,2,6}, {8,5,1,4,7,6,2,3}, {8,7,6,5,4,3,2,1} };
static Int_t iwhat[8] = { 63,62,54,26,50,9,1,0 };
static Int_t ie[12] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
static Int_t iface[6][4] = {
{1,2,3,4}, {5,6,7,8}, {1,2,6,5}, {2,6,7,3}, {4,3,7,8}, {1,5,8,4} };
static Int_t it1[4][3] = { {1,2,10}, {9,5,8}, {6,11,7}, {3,4,12} };
static Int_t it2[4][3] = { {5,6,10}, {1,4,9}, {2,11,3}, {7,8,12} };
static Int_t it3[6][3] = { {10,12,-3}, {-10,3,2}, {12,10,-1}, {-12,1,4},
{9,5,8}, {6,11,7} };
static Int_t it4[6][3] = { {11,9,-1}, {-11,1,2}, {9,11,-3}, {-9,3,4},
{5,6,10}, {7,8,12} };
static Int_t it5[10][3] = { {13,2,-11}, {-13,11,7}, {13,7,-6}, {-13,6,10},
{13,10,1}, {13,1,-4}, {-13,4,12}, {13,12,-3}, {-13,3,2}, {5,8,9} };
static Int_t it6[10][3] = { {13,2,-10}, {-13,10,5}, {13,5,-6}, {-13,6,11},
{13,11,3}, {13,3,-4}, {-13,4,9}, {13,9,-1}, {-13,1,2}, {12,7,8} };
static Int_t it7[12][3] = { {13,2,-11}, {-13,11,7}, {13,7,-6}, {-13,6,10},
{13,10,-5}, {-13,5,8}, {13,8,-9}, {-13,9,1},
{13,1,-4}, {-13,4,12}, {13,12,-3}, {-13,3,2} };
static Int_t it8[6][3] = { {3,8,12}, {3,-2,-8}, {-2,5,-8}, {2,10,-5},
{7,6,11}, {1,4,9} };
static Int_t it9[10][3] = { {7,12,-3}, {-7,3,11}, {11,3,2}, {6,11,-2}, {-6,2,10},
{6,10,5}, {7,6,-5}, {-7,5,8}, {7,8,12}, {1,4,9} };
static Int_t it10[10][3] = { {9,1,-10}, {-9,10,5}, {9,5,8}, {4,9,-8}, {-4,8,12},
{4,12,3}, {1,4,-3}, {-1,3,2}, {1,2,10}, {7,6,11} };
nnod = 0;
ntria = 0;
// F I N D C O N F I G U R A T I O N T Y P E
for ( nr=1 ; nr<=12 ; nr++ ) {
k = 0;
incr = 1;
for ( nf=1 ; nf<=6 ; nf++ ) {
f1 = fF8[irota[nr-1][iface[nf-1][0]-1]-1];
f2 = fF8[irota[nr-1][iface[nf-1][1]-1]-1];
f3 = fF8[irota[nr-1][iface[nf-1][2]-1]-1];
f4 = fF8[irota[nr-1][iface[nf-1][3]-1]-1];
if ((f1*f3-f2*f4)/(f1+f3-f2-f4) >= 0.) k = k + incr;
incr = incr + incr;
}
for ( i=1 ; i<=8 ; i++ ) {
if (k != iwhat[i-1]) continue;
icase = i;
kr = nr;
goto L200;
}
}
Error("MarchingCubeCase13", "configuration is not found");
return;
// R O T A T E C U B E
L200:
if (icase==1 || icase==8) goto L300;
for ( n=1 ; n<=8 ; n++) {
k = irota[kr-1][n-1];
ff[n-1] = fF8[k-1];
for ( i=1 ; i<=3 ; i++ ) {
xyz[n-1][i-1] = fP8[k-1][i-1];
grad[n-1][i-1] = fG8[k-1][i-1];
}
}
for ( n=1 ; n<=8 ; n++ ) {
fF8[n-1] = ff[n-1];
for ( i=1 ; i<=3 ; i++ ) {
fP8[n-1][i-1] = xyz[n-1][i-1];
fG8[n-1][i-1] = grad[n-1][i-1];
}
}
// S E T N O D E S & N O R M A L E S
L300:
nnod = 12;
MarchingCubeFindNodes(nnod, ie, xyz, grad);
// V A R I O U S C O N F I G U R A T I O N S
switch ((int)icase) {
case 1:
ntria = 4;
MarchingCubeSetTriangles(ntria, it1, itria);
return;
case 8:
ntria = 4;
MarchingCubeSetTriangles(ntria, it2, itria);
return;
case 2:
ntria = 6;
MarchingCubeSetTriangles(ntria, it3, itria);
return;
case 7:
ntria = 6;
MarchingCubeSetTriangles(ntria, it4, itria);
return;
case 3:
nnod = 13;
ntria = 10;
MarchingCubeMiddlePoint(9, xyz, grad, it5,
&xyz[nnod-1][0], &grad[nnod-1][0]);
MarchingCubeSetTriangles(ntria, it5, itria);
return;
case 6:
nnod = 13;
ntria = 10;
MarchingCubeMiddlePoint(9, xyz, grad, it6,
&xyz[nnod-1][0], &grad[nnod-1][0]);
MarchingCubeSetTriangles(ntria, it6, itria);
return;
case 5:
nnod = 13;
ntria = 12;
MarchingCubeMiddlePoint(12, xyz, grad, it7,
&xyz[nnod-1][0], &grad[nnod-1][0]);
MarchingCubeSetTriangles(ntria, it7, itria);
return;
// 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 ?
case 4:
MarchingCubeSurfacePenetration(fF8[2], fF8[3], fF8[0], fF8[1],
fF8[6], fF8[7], fF8[4], fF8[5], irep);
switch ((int)(irep+1)) {
case 1:
ntria = 6;
MarchingCubeSetTriangles(ntria, it8, itria);
return;
case 2:
ntria = 10;
MarchingCubeSetTriangles(ntria, it9, itria);
return;
case 3:
ntria = 10;
MarchingCubeSetTriangles(ntria, it10, itria);
}
}
}
//______________________________________________________________________________
void TPainter3dAlgorithms::MarchingCubeSetTriangles(Int_t ntria, Int_t it[][3],
Int_t itria[48][3])
{
// Set triangles (if parameter IALL=1, all edges will be visible)
//
// Input: NTRIA - number of triangles
// IT(3,*) - triangles
//
// Output: ITRIA(3,*) - triangles
Int_t n, i, k;
for ( n=1 ; n<=ntria ; n++ ) {
for ( i=1 ; i<=3 ; i++ ) {
k = it[n-1][i-1];
itria[n-1][i-1] = k;
}
}
}
//______________________________________________________________________________
void TPainter3dAlgorithms::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
//
// Input: NNOD - number of nodes in the polygon
// XYZ(3,*) - node coordinates
// GRAD(3,*) - node normales
// IT(3,*) - division of the polygons into triangles
//
// Output: PXYZ(3) - middle point coordinates
// PGRAD(3) - middle point normale
Double_t p[3], g[3];
Int_t i, n, k;
for ( i=1 ; i<=3 ; i++ ) {
p[i-1] = 0.;
g[i-1] = 0.;
}
for ( n=1 ; n<=nnod ; n++ ) {
k = it[n-1][2];
if (k < 0) k =-k;
for ( i=1 ; i<=3 ; i++ ) {
p[i-1] = p[i-1] + xyz[k-1][i-1];
g[i-1] = g[i-1] + grad[k-1][i-1];
}
}
for ( i=1 ; i<=3 ; i++ ) {
pxyz[i-1] = p[i-1] / nnod;
pgrad[i-1] = g[i-1] / nnod;
}
}
//______________________________________________________________________________
void TPainter3dAlgorithms::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")
//
// Input: A00,A10,A11,A01 - vertex values for 1st face
// B00,B10,B11,B01 - vertex values for opposite face
//
// Output: IREP - 1,2 - there is surface penetration
// 0 - there is not surface penetration
Double_t a, b, c, d, s0, s1, s2;
Int_t iposa, iposb;
irep = 0;
a = (a11-a01)*(b00-b10) - (a00-a10)*(b11-b01);
if (a == 0.) return;
b = a01*(b00-b10)-(a11-a01)*b00-(a00-a10)*b01+a00*(b11-b01);
c = a00*b01 - a01*b00;
d = b*b-4*a*c;
if (d <= 0.) return;
d = TMath::Sqrt(d);
if (TMath::Abs(-b+d) > TMath::Abs(2*a)) return;
s1 = (-b+d) / (2*a);
if (s1<0. || s1>1.) return;
if (TMath::Abs(-b-d) > TMath::Abs(2*a)) return;
s2 = (-b-d) / (2*a);
if (s2<0. || s2>1.) return;
// C A S E N O 4 ?
iposa = 0;
if (a00 >= 0) iposa = iposa + 1;
if (a01 >= 0) iposa = iposa + 2;
if (a10 >= 0) iposa = iposa + 4;
if (a11 >= 0) iposa = iposa + 8;
if (iposa==6 || iposa==9) goto L100;
irep = 1;
return;
// N O T C A S E N O 4
L100:
s0 = (a00-a01) / (a00+a11-a10-a01);
if (s1>=s0 && s2