TGeoXtru.cxx

Go to the documentation of this file.
00001 // @(#)root/geom:$Id: TGeoXtru.cxx 34235 2010-06-30 12:39:27Z brun $
00002 // Author: Mihaela Gheata   24/01/04
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //_____________________________________________________________________________
00013 // TGeoXtru 
00014 //==========
00015 //   An extrusion with fixed outline shape in x-y and a sequence
00016 // of z extents (segments).  The overall scale of the outline scales
00017 // linearly between z points and the center can have an x-y offset.
00018 //
00019 // Creation of TGeoXtru shape
00020 //=============================
00021 //   A TGeoXtru represents a polygonal extrusion. It is defined by the:
00022 // a. 'Blueprint' of the arbitrary polygon representing any Z section. This
00023 //    is an arbytrary polygon (convex or not) defined by the X/Y positions of
00024 //    its vertices.
00025 // b. A sequence of Z sections ordered on the Z axis. Each section defines the
00026 //   'actual' parameters of the polygon at a given Z. The sections may be 
00027 //    translated with respect to the blueprint and/or scaled. The TGeoXtru
00028 //   segment in between 2 Z sections is a solid represented by the linear 
00029 //   extrusion between the 2 polygons. Two consecutive sections may be defined
00030 //   at same Z position.
00031 //
00032 // 1. TGeoXtru *xtru = TGeoXtru(Int_t nz);
00033 //   where nz=number of Z planes
00034 // 2. Double_t x[nvertices]; // array of X positions of blueprint polygon vertices
00035 //    Double_t y[nvertices]; // array of Y positions of blueprint polygon vertices
00036 // 3. xtru->DefinePolygon(nvertices,x,y);
00037 // 4. DefineSection(0, z0, x0, y0, scale0); // Z position, offset and scale for first section
00038 //    DefineSection(1, z1, x1, y1, scale1); // -''- secons section
00039 //    ....
00040 //    DefineSection(nz-1, zn, xn, yn, scalen); // parameters for last section
00041 //
00042 // *NOTES*
00043 // Currently navigation functionality not fully implemented (only Contains()).
00044 // Decomposition in concave polygons not implemented - drawing in solid mode
00045 // within x3d produces incorrect end-faces
00046 //_____________________________________________________________________________
00047 
00048 #include "Riostream.h"
00049 
00050 #include "TGeoManager.h"
00051 #include "TGeoVolume.h"
00052 #include "TGeoPolygon.h"
00053 #include "TVirtualGeoPainter.h"
00054 #include "TGeoXtru.h"
00055 #include "TVirtualPad.h"
00056 #include "TBuffer3D.h"
00057 #include "TBuffer3DTypes.h"
00058 #include "TClass.h"
00059 #include "TMath.h"
00060 
00061 ClassImp(TGeoXtru)
00062 
00063 //_____________________________________________________________________________
00064 TGeoXtru::TGeoXtru()
00065 {
00066 // dummy ctor
00067    SetShapeBit(TGeoShape::kGeoXtru);
00068    fNvert = 0;
00069    fNz = 0;
00070    fZcurrent = 0.;
00071    fPoly = 0;
00072    fX = 0;
00073    fY = 0;
00074    fXc = 0;
00075    fYc = 0;
00076    fZ = 0;
00077    fScale = 0;
00078    fX0 = 0;
00079    fY0 = 0;
00080    fSeg = 0;
00081    fIz = 0;
00082 }   
00083 
00084 //_____________________________________________________________________________
00085 TGeoXtru::TGeoXtru(Int_t nz)
00086          :TGeoBBox(0, 0, 0)
00087 {
00088 // Default constructor
00089    SetShapeBit(TGeoShape::kGeoXtru);
00090    if (nz<2) {
00091       Error("ctor", "Cannot create TGeoXtru %s with less than 2 Z planes", GetName());
00092       SetShapeBit(TGeoShape::kGeoBad);
00093       return;
00094    }
00095    fNvert = 0;
00096    fNz = nz;   
00097    fZcurrent = 0.;
00098    fPoly = 0;
00099    fX = 0;
00100    fY = 0;
00101    fXc = 0;
00102    fYc = 0;
00103    fZ = new Double_t[nz];
00104    fScale = new Double_t[nz];
00105    fX0 = new Double_t[nz];
00106    fY0 = new Double_t[nz];
00107    fSeg = 0;
00108    fIz = 0;
00109 }
00110 
00111 //_____________________________________________________________________________
00112 TGeoXtru::TGeoXtru(Double_t *param)
00113          :TGeoBBox(0, 0, 0)
00114 {
00115 // Default constructor in GEANT3 style
00116 // param[0] = nz  // number of z planes
00117 //
00118 // param[1] = z1  // Z position of first plane
00119 // param[2] = x1  // X position of first plane
00120 // param[3] = y1  // Y position of first plane
00121 // param[4] = scale1  // scale factor for first plane
00122 // ...
00123 // param[4*(nz-1]+1] = zn
00124 // param[4*(nz-1)+2] = xn
00125 // param[4*(nz-1)+3] = yn
00126 // param[4*(nz-1)+4] = scalen
00127    SetShapeBit(TGeoShape::kGeoXtru);
00128    fNvert = 0;
00129    fNz = 0;
00130    fZcurrent = 0.;
00131    fPoly = 0;
00132    fX = 0;
00133    fY = 0;
00134    fXc = 0;
00135    fYc = 0;
00136    fZ = 0;
00137    fScale = 0;
00138    fX0 = 0;
00139    fY0 = 0;
00140    fSeg = 0;
00141    fIz = 0;
00142    SetDimensions(param);
00143 }
00144 
00145 //_____________________________________________________________________________
00146 TGeoXtru::TGeoXtru(const TGeoXtru& xt) :
00147   TGeoBBox(xt),
00148   fNvert(xt.fNvert),
00149   fNz(xt.fNz),
00150   fZcurrent(xt.fZcurrent),
00151   fPoly(xt.fPoly),
00152   fX(xt.fX),
00153   fY(xt.fY),
00154   fXc(xt.fXc),
00155   fYc(xt.fYc),
00156   fZ(xt.fZ),
00157   fScale(xt.fScale),
00158   fX0(xt.fX0),
00159   fY0(xt.fY0),
00160   fSeg(xt.fSeg),
00161   fIz(xt.fIz)
00162 { 
00163    //copy constructor
00164 }
00165 
00166 //_____________________________________________________________________________
00167 TGeoXtru& TGeoXtru::operator=(const TGeoXtru& xt)
00168 {
00169    //assignment operator
00170    if(this!=&xt) {
00171       TGeoBBox::operator=(xt);
00172       fNvert=xt.fNvert;
00173       fNz=xt.fNz;
00174       fZcurrent=xt.fZcurrent;
00175       fPoly=xt.fPoly;
00176       fX=xt.fX;
00177       fY=xt.fY;
00178       fXc=xt.fXc;
00179       fYc=xt.fYc;
00180       fZ=xt.fZ;
00181       fScale=xt.fScale;
00182       fX0=xt.fX0;
00183       fY0=xt.fY0;
00184       fSeg=xt.fSeg;
00185       fIz=xt.fIz;
00186    } 
00187    return *this;
00188 }
00189 
00190 //_____________________________________________________________________________
00191 TGeoXtru::~TGeoXtru()
00192 {
00193 // destructor
00194    if (fX)  {delete[] fX; fX = 0;}
00195    if (fY)  {delete[] fY; fY = 0;}
00196    if (fXc) {delete[] fXc; fXc = 0;}
00197    if (fYc) {delete[] fYc; fYc = 0;}
00198    if (fZ)  {delete[] fZ; fZ = 0;}
00199    if (fScale) {delete[] fScale; fScale = 0;}
00200    if (fX0)  {delete[] fX0; fX0 = 0;}
00201    if (fY0)  {delete[] fY0; fY0 = 0;}
00202 }
00203 
00204 //_____________________________________________________________________________   
00205 Double_t TGeoXtru::Capacity() const
00206 {
00207 // Compute capacity [length^3] of this shape.
00208    Int_t iz;
00209    Double_t capacity = 0;
00210    Double_t area, dz, sc1, sc2;
00211    TGeoXtru *xtru = (TGeoXtru*)this;
00212    xtru->SetCurrentVertices(0.,0.,1.);  
00213    area = fPoly->Area();
00214    for (iz=0; iz<fNz-1; iz++) {
00215       dz = fZ[iz+1]-fZ[iz];
00216       if (TGeoShape::IsSameWithinTolerance(dz,0)) continue;
00217       sc1 = fScale[iz];
00218       sc2 = fScale[iz+1];
00219       capacity += (area*dz/3.)*(sc1*sc1+sc1*sc2+sc2*sc2);
00220    }
00221    return capacity;
00222 }      
00223 
00224 //_____________________________________________________________________________   
00225 void TGeoXtru::ComputeBBox()
00226 {
00227 // compute bounding box of the pcon
00228    if (!fX || !fZ || !fNvert) {
00229       Error("ComputeBBox", "In shape %s polygon not defined", GetName());
00230       SetShapeBit(TGeoShape::kGeoBad);
00231       return;
00232    }   
00233    Double_t zmin = fZ[0];
00234    Double_t zmax = fZ[fNz-1];
00235    Double_t xmin = TGeoShape::Big();
00236    Double_t xmax = -TGeoShape::Big();
00237    Double_t ymin = TGeoShape::Big();
00238    Double_t ymax = -TGeoShape::Big();
00239    for (Int_t i=0; i<fNz; i++) {
00240       SetCurrentVertices(fX0[i], fY0[i], fScale[i]);
00241       for (Int_t j=0; j<fNvert; j++) {
00242          if (fXc[j]<xmin) xmin=fXc[j];
00243          if (fXc[j]>xmax) xmax=fXc[j];
00244          if (fYc[j]<ymin) ymin=fYc[j];
00245          if (fYc[j]>ymax) ymax=fYc[j];
00246       }
00247    }
00248    fOrigin[0] = 0.5*(xmin+xmax);      
00249    fOrigin[1] = 0.5*(ymin+ymax);      
00250    fOrigin[2] = 0.5*(zmin+zmax);      
00251    fDX = 0.5*(xmax-xmin);
00252    fDY = 0.5*(ymax-ymin);
00253    fDZ = 0.5*(zmax-zmin);
00254 }   
00255 
00256 //_____________________________________________________________________________   
00257 void TGeoXtru::ComputeNormal(Double_t * /*point*/, Double_t *dir, Double_t *norm)
00258 {
00259 // Compute normal to closest surface from POINT. 
00260    if (fIz<0) {  
00261       memset(norm,0,3*sizeof(Double_t));
00262       norm[2] = (dir[2]>0)?1:-1;
00263       return;
00264    }
00265    Double_t vert[12];      
00266    GetPlaneVertices(fIz, fSeg, vert);
00267    GetPlaneNormal(vert, norm);
00268    Double_t ndotd = norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2];
00269    if (ndotd<0) {
00270       norm[0] = -norm[0];
00271       norm[1] = -norm[1];
00272       norm[2] = -norm[2];
00273    }   
00274 }
00275 
00276 //_____________________________________________________________________________
00277 Bool_t TGeoXtru::Contains(Double_t *point) const
00278 {
00279 // test if point is inside this shape
00280    // Check Z range
00281    TGeoXtru *xtru = (TGeoXtru*)this;
00282    if (point[2]<fZ[0]) return kFALSE;   
00283    if (point[2]>fZ[fNz-1]) return kFALSE; 
00284    Int_t iz = TMath::BinarySearch(fNz, fZ, point[2]);
00285    if (iz<0 || iz==fNz-1) return kFALSE;
00286    if (TGeoShape::IsSameWithinTolerance(point[2],fZ[iz])) {
00287       xtru->SetIz(-1);
00288       xtru->SetCurrentVertices(fX0[iz],fY0[iz], fScale[iz]);
00289       if (fPoly->Contains(point)) return kTRUE;
00290       if (iz>1 && TGeoShape::IsSameWithinTolerance(fZ[iz],fZ[iz-1])) {
00291          xtru->SetCurrentVertices(fX0[iz-1],fY0[iz-1], fScale[iz-1]);
00292          return fPoly->Contains(point);
00293       } else if (iz<fNz-2 && TGeoShape::IsSameWithinTolerance(fZ[iz],fZ[iz+1])) {
00294          xtru->SetCurrentVertices(fX0[iz+1],fY0[iz+1], fScale[iz+1]);
00295          return fPoly->Contains(point);
00296       }      
00297    }      
00298    xtru->SetCurrentZ(point[2], iz);
00299    if (TMath::Abs(point[2]-fZ[iz])<TGeoShape::Tolerance() ||
00300        TMath::Abs(fZ[iz+1]-point[2])<TGeoShape::Tolerance())  xtru->SetIz(-1);
00301    // Now fXc,fYc represent the vertices of the section at point[2]
00302    return fPoly->Contains(point);
00303 }
00304 
00305 //_____________________________________________________________________________
00306 Int_t TGeoXtru::DistancetoPrimitive(Int_t px, Int_t py)
00307 {
00308 // compute closest distance from point px,py to each corner
00309    const Int_t numPoints = fNvert*fNz;
00310    return ShapeDistancetoPrimitive(numPoints, px, py);
00311 }
00312 //_____________________________________________________________________________
00313 Double_t TGeoXtru::DistToPlane(Double_t *point, Double_t *dir, Int_t iz, Int_t ivert, Double_t stepmax, Bool_t in) const
00314 {
00315 // Compute distance to a Xtru lateral surface.
00316    Double_t snext;
00317    Double_t vert[12];
00318    Double_t norm[3];
00319    Double_t znew;
00320    Double_t pt[3];
00321    Double_t safe;
00322    if (TGeoShape::IsSameWithinTolerance(fZ[iz],fZ[iz+1]) && !in) {
00323       TGeoXtru *xtru = (TGeoXtru*)this;
00324       snext = (fZ[iz]-point[2])/dir[2];
00325       if (snext<0) return TGeoShape::Big();
00326       pt[0] = point[0]+snext*dir[0];
00327       pt[1] = point[1]+snext*dir[1];
00328       pt[2] = point[2]+snext*dir[2];
00329       if (dir[2] < 0.) xtru->SetCurrentVertices(fX0[iz], fY0[iz], fScale[iz]);
00330       else             xtru->SetCurrentVertices(fX0[iz+1], fY0[iz+1], fScale[iz+1]);
00331       if (!fPoly->Contains(pt)) return TGeoShape::Big();
00332       return snext;
00333    }      
00334    GetPlaneVertices(iz, ivert, vert);
00335    GetPlaneNormal(vert, norm);
00336    Double_t ndotd = norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2];
00337    if (in) {
00338       if (ndotd<=0) return TGeoShape::Big();
00339       safe = (vert[0]-point[0])*norm[0]+
00340              (vert[1]-point[1])*norm[1]+
00341              (vert[2]-point[2])*norm[2];
00342       if (safe<0) return TGeoShape::Big(); // direction outwards plane
00343    } else {
00344       ndotd = -ndotd;
00345       if (ndotd<=0) return TGeoShape::Big(); 
00346       safe = (point[0]-vert[0])*norm[0]+
00347              (point[1]-vert[1])*norm[1]+
00348              (point[2]-vert[2])*norm[2];
00349       if (safe<0) return TGeoShape::Big(); // direction outwards plane
00350    }      
00351    snext = safe/ndotd;
00352    if (snext>stepmax) return TGeoShape::Big();
00353    if (fZ[iz]<fZ[iz+1]) {
00354       znew = point[2] + snext*dir[2];
00355       if (znew<fZ[iz]) return TGeoShape::Big();
00356       if (znew>fZ[iz+1]) return TGeoShape::Big();
00357    }
00358    pt[0] = point[0]+snext*dir[0];
00359    pt[1] = point[1]+snext*dir[1];
00360    pt[2] = point[2]+snext*dir[2];
00361    if (!IsPointInsidePlane(pt, vert, norm)) return TGeoShape::Big();
00362    return snext;         
00363 }
00364 
00365 //_____________________________________________________________________________
00366 Double_t TGeoXtru::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00367 {
00368 // compute distance from inside point to surface of the polycone
00369    // locate Z segment
00370    if (iact<3 && safe) {
00371       *safe = Safety(point, kTRUE);
00372       if (iact==0) return TGeoShape::Big();
00373       if (iact==1 && step<*safe) return TGeoShape::Big();
00374    }   
00375    TGeoXtru *xtru = (TGeoXtru*)this;
00376    Int_t iz = TMath::BinarySearch(fNz, fZ, point[2]);
00377    if (iz < 0) {
00378       if (dir[2]<=0) {
00379          xtru->SetIz(-1);
00380          return 0.;
00381       }
00382       iz = 0;
00383    }            
00384    if (iz==fNz-1) {
00385       if (dir[2]>=0) {
00386          xtru->SetIz(-1);
00387          return 0.;
00388       }   
00389       iz--;
00390    } else {   
00391       if (iz>0) {
00392          if (TGeoShape::IsSameWithinTolerance(point[2],fZ[iz])) {
00393             if (TGeoShape::IsSameWithinTolerance(fZ[iz],fZ[iz+1]) && dir[2]<0) iz++;
00394             else if (TGeoShape::IsSameWithinTolerance(fZ[iz],fZ[iz-1]) && dir[2]>0) iz--;
00395          }   
00396       }
00397    }   
00398    Bool_t convex = fPoly->IsConvex();
00399 //   Double_t stepmax = step;
00400 //   if (stepmax>TGeoShape::Big()) stepmax = TGeoShape::Big();
00401    Double_t snext = TGeoShape::Big();
00402    Double_t dist, sz;
00403    Double_t pt[3];
00404    Int_t iv, ipl, inext;
00405    // we treat the special case when dir[2]=0
00406    if (TGeoShape::IsSameWithinTolerance(dir[2],0)) {
00407       for (iv=0; iv<fNvert; iv++) {
00408          xtru->SetIz(-1);
00409          dist = DistToPlane(point,dir,iz,iv,TGeoShape::Big(),kTRUE);
00410          if (dist<snext) {
00411             snext = dist;
00412             xtru->SetSeg(iv);
00413             if (convex) return snext;
00414          }   
00415       }
00416       return TGeoShape::Tolerance();
00417    }      
00418    
00419    // normal case   
00420    Int_t incseg = (dir[2]>0)?1:-1; 
00421    Int_t iznext = iz;
00422    Bool_t zexit = kFALSE;  
00423    while (iz>=0 && iz<fNz-1) {
00424       // find the distance  to current segment end Z surface
00425       ipl = iz+((incseg+1)>>1); // next plane
00426       inext = ipl+incseg; // next next plane
00427       sz = (fZ[ipl]-point[2])/dir[2];
00428       if (sz<snext) {
00429          iznext += incseg;
00430          // we cross the next Z section before stepmax
00431          pt[0] = point[0]+sz*dir[0];
00432          pt[1] = point[1]+sz*dir[1];
00433          xtru->SetCurrentVertices(fX0[ipl],fY0[ipl],fScale[ipl]);
00434          if (fPoly->Contains(pt)) {
00435             // ray gets through next polygon - is it the last one?
00436             if (ipl==0 || ipl==fNz-1) {
00437                xtru->SetIz(-1);
00438                if (convex) return sz;
00439                zexit = kTRUE;
00440                snext = sz;
00441             }   
00442             // maybe a Z discontinuity - check this
00443             if (!zexit && TGeoShape::IsSameWithinTolerance(fZ[ipl],fZ[inext])) {
00444                xtru->SetCurrentVertices(fX0[inext],fY0[inext],fScale[inext]);
00445                // if we do not cross the next polygone, we are out
00446                if (!fPoly->Contains(pt)) {
00447                   xtru->SetIz(-1);
00448                   if (convex) return sz;
00449                   zexit = kTRUE;
00450                   snext = sz;
00451                } else {  
00452                   iznext = inext;
00453                }   
00454             } 
00455          }
00456       } else {
00457          iznext = fNz-1;   // stop
00458       }   
00459       // ray may cross the lateral surfaces of section iz      
00460       xtru->SetIz(iz);
00461       for (iv=0; iv<fNvert; iv++) {
00462          dist = DistToPlane(point,dir,iz,iv,TGeoShape::Big(),kTRUE); 
00463          if (dist<snext) {
00464             xtru->SetSeg(iv);
00465             snext = dist;
00466             if (convex) return snext;
00467             zexit = kTRUE;
00468          }   
00469       }
00470       if (zexit) return snext;
00471       iz = iznext;
00472    }
00473    return TGeoShape::Tolerance();
00474 }
00475 
00476 //_____________________________________________________________________________
00477 Double_t TGeoXtru::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00478 {
00479 // compute distance from outside point to surface of the tube
00480 //   Warning("DistFromOutside", "not implemented");
00481    if (iact<3 && safe) {
00482       *safe = Safety(point, kTRUE);
00483       if (iact==0) return TGeoShape::Big();
00484       if (iact==1 && step<*safe) return TGeoShape::Big();
00485    }   
00486 // Check if the bounding box is crossed within the requested distance
00487    Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
00488    if (sdist>=step) return TGeoShape::Big();
00489    Double_t stepmax = step;
00490    if (stepmax>TGeoShape::Big()) stepmax = TGeoShape::Big();
00491    Double_t snext = 0.;
00492    Double_t dist = TGeoShape::Big();
00493    Int_t i, iv;
00494    Double_t pt[3];
00495    memcpy(pt,point,3*sizeof(Double_t));
00496    TGeoXtru *xtru = (TGeoXtru*)this;
00497    // We might get out easy with Z checks
00498    Int_t iz = TMath::BinarySearch(fNz, fZ, point[2]);
00499    if (iz<0) {
00500       if (dir[2]<=0) return TGeoShape::Big();
00501       // propagate to first Z plane
00502       snext = (fZ[0] - point[2])/dir[2];
00503       if (snext>stepmax) return TGeoShape::Big();
00504       for (i=0; i<3; i++) pt[i] = point[i] + snext*dir[i];
00505       xtru->SetCurrentVertices(fX0[0],fY0[0],fScale[0]);
00506       if (fPoly->Contains(pt)) {
00507          xtru->SetIz(-1);
00508          return snext;
00509       }   
00510       iz=0; // valid starting value = first segment
00511       stepmax -= snext;
00512    } else {
00513       if (iz==fNz-1) {
00514          if (dir[2]>=0) return TGeoShape::Big();
00515          // propagate to last Z plane
00516          snext = (fZ[fNz-1] - point[2])/dir[2];
00517          if (snext>stepmax) return TGeoShape::Big();
00518          for (i=0; i<3; i++) pt[i] = point[i] + snext*dir[i];
00519          xtru->SetCurrentVertices(fX0[fNz-1],fY0[fNz-1],fScale[fNz-1]);
00520          if (fPoly->Contains(pt)) {
00521             xtru->SetIz(-1);
00522             return snext;
00523          }   
00524          iz = fNz-2; // valid value = last segment
00525          stepmax -= snext;
00526       }
00527    }      
00528    // Check if the bounding box is missed by the track
00529    if (!TGeoBBox::Contains(pt)) {
00530       dist = TGeoBBox::DistFromOutside(pt,dir,3);
00531       if (dist>stepmax) return TGeoShape::Big();
00532       if (dist>1E-6) dist-=1E-6; // decrease snext to make sure we do not cross the xtru
00533       else dist = 0;
00534       for (i=0; i<3; i++) pt[i] += dist*dir[i]; // we are now closer
00535       iz = TMath::BinarySearch(fNz, fZ, pt[2]);      
00536       if (iz<0) iz=0;
00537       else if (iz==fNz-1) iz = fNz-2;
00538       snext += dist;
00539       stepmax -= dist;
00540    }   
00541    // not the case - we have to do some work...
00542    // Start trackink from current iz
00543    // - first solve particular case dir[2]=0
00544    Bool_t convex = fPoly->IsConvex();
00545    Bool_t hit = kFALSE;
00546    if (TGeoShape::IsSameWithinTolerance(dir[2],0)) {
00547       // loop lateral planes to see if we cross something
00548       xtru->SetIz(iz);
00549       for (iv=0; iv<fNvert; iv++) {
00550          dist = DistToPlane(pt,dir,iz,iv,stepmax,kFALSE);
00551          if (dist<stepmax) {
00552             xtru->SetSeg(iv);
00553             if (convex) return (snext+dist);
00554             stepmax = dist;
00555             hit = kTRUE;
00556          }   
00557       }
00558       if (hit) return (snext+stepmax);
00559       return TGeoShape::Big();
00560    }   
00561    // general case
00562    Int_t incseg = (dir[2]>0)?1:-1;
00563    while (iz>=0 && iz<fNz-1) {
00564       // compute distance to lateral planes
00565       xtru->SetIz(iz);
00566       if (TGeoShape::IsSameWithinTolerance(fZ[iz],fZ[iz+1])) xtru->SetIz(-1);
00567       for (iv=0; iv<fNvert; iv++) {
00568          dist = DistToPlane(pt,dir,iz,iv,stepmax,kFALSE);
00569          if (dist<stepmax) {
00570             // HIT
00571             xtru->SetSeg(iv);
00572             if (convex) return (snext+dist);
00573             stepmax = dist;
00574             hit = kTRUE;
00575          }   
00576       }
00577       if (hit) return (snext+stepmax);
00578       iz += incseg;
00579    }   
00580    return TGeoShape::Big();  
00581 }
00582 
00583 //_____________________________________________________________________________
00584 Bool_t TGeoXtru::DefinePolygon(Int_t nvert, const Double_t *xv, const Double_t *yv)
00585 {
00586 // Creates the polygon representing the blueprint of any Xtru section.
00587 //   nvert     = number of vertices >2
00588 //   xv[nvert] = array of X vertex positions 
00589 //   yv[nvert] = array of Y vertex positions 
00590 // *NOTE* should be called before DefineSection or ctor with 'param'
00591    if (nvert<3) {
00592       Error("DefinePolygon","In shape %s cannot create polygon with less than 3 vertices", GetName());
00593       SetShapeBit(TGeoShape::kGeoBad);
00594       return kFALSE;
00595    }
00596    for (Int_t i=0; i<nvert-1; i++) {
00597       for (Int_t j=i+1; j<nvert; j++) {
00598          if (TMath::Abs(xv[i]-xv[j])<TGeoShape::Tolerance() &&
00599              TMath::Abs(yv[i]-yv[j])<TGeoShape::Tolerance()) {
00600              Error("DefinePolygon","In shape %s 2 vertices cannot be identical",GetName());
00601              SetShapeBit(TGeoShape::kGeoBad);
00602 //             return kFALSE;
00603           }   
00604       }
00605    }
00606    fNvert = nvert;
00607    if (fX) delete [] fX;
00608    fX = new Double_t[nvert];
00609    if (fY) delete [] fY;
00610    fY = new Double_t[nvert];
00611    if (fXc) delete [] fXc;
00612    fXc = new Double_t[nvert];
00613    if (fYc) delete [] fYc;
00614    fYc = new Double_t[nvert];
00615    memcpy(fX,xv,nvert*sizeof(Double_t));
00616    memcpy(fXc,xv,nvert*sizeof(Double_t));
00617    memcpy(fY,yv,nvert*sizeof(Double_t));
00618    memcpy(fYc,yv,nvert*sizeof(Double_t));
00619    
00620    if (fPoly) delete fPoly;
00621    fPoly = new TGeoPolygon(nvert);
00622    fPoly->SetXY(fXc,fYc); // initialize with current coordinates
00623    fPoly->FinishPolygon();
00624    if (fPoly->IsIllegalCheck()) {
00625       Error("DefinePolygon", "Shape %s of type XTRU has an illegal polygon.", GetName());
00626    }   
00627    return kTRUE;
00628 }
00629 
00630 //_____________________________________________________________________________
00631 void TGeoXtru::DefineSection(Int_t snum, Double_t z, Double_t x0, Double_t y0, Double_t scale)
00632 {
00633 // defines z position of a section plane, rmin and rmax at this z.
00634    if ((snum<0) || (snum>=fNz)) return;
00635    fZ[snum]  = z;
00636    fX0[snum] = x0;
00637    fY0[snum] = y0;
00638    fScale[snum] = scale;
00639    if (snum) {
00640       if (fZ[snum]<fZ[snum-1]) {
00641          Warning("DefineSection", "In shape: %s, Z position of section "
00642                  "%i, z=%e, not in increasing order, %i, z=%e",
00643                  GetName(),snum,fZ[snum],snum-1,fZ[snum-1]);
00644          return;
00645       }   
00646    }
00647    if (snum==(fNz-1)) {
00648       ComputeBBox();
00649       if (TestShapeBit(TGeoShape::kGeoBad)) InspectShape();
00650    }   
00651 }
00652             
00653 //_____________________________________________________________________________
00654 Double_t TGeoXtru::GetZ(Int_t ipl) const
00655 {
00656 // Return the Z coordinate for segment ipl.
00657    if (ipl<0 || ipl>(fNz-1)) {
00658       Error("GetZ","In shape %s, ipl=%i out of range (0,%i)",GetName(),ipl,fNz-1);
00659       return 0.;
00660    }
00661    return fZ[ipl];
00662 }      
00663 //_____________________________________________________________________________
00664 void TGeoXtru::GetPlaneNormal(const Double_t *vert, Double_t *norm) const
00665 {
00666 // Returns normal vector to the planar quadrilateral defined by vector VERT.
00667 // The normal points outwards the xtru.
00668    Double_t cross = 0.;
00669    Double_t v1[3], v2[3];
00670    v1[0] = vert[9]-vert[0];
00671    v1[1] = vert[10]-vert[1];
00672    v1[2] = vert[11]-vert[2];
00673    v2[0] = vert[3]-vert[0];
00674    v2[1] = vert[4]-vert[1];
00675    v2[2] = vert[5]-vert[2];
00676    norm[0] = v1[1]*v2[2]-v1[2]*v2[1];
00677    cross += norm[0]*norm[0];
00678    norm[1] = v1[2]*v2[0]-v1[0]*v2[2];
00679    cross += norm[1]*norm[1];
00680    norm[2] = v1[0]*v2[1]-v1[1]*v2[0];
00681    cross += norm[2]*norm[2];
00682    if (cross < TGeoShape::Tolerance()) return;
00683    cross = 1./TMath::Sqrt(cross);
00684    for (Int_t i=0; i<3; i++) norm[i] *= cross;
00685 }   
00686 
00687 //_____________________________________________________________________________
00688 void TGeoXtru::GetPlaneVertices(Int_t iz, Int_t ivert, Double_t *vert) const
00689 {
00690 // Returns (x,y,z) of 3 vertices of the surface defined by Z sections (iz, iz+1)
00691 // and polygon vertices (ivert, ivert+1). No range check.
00692    Double_t x,y,z1,z2;
00693    Int_t iv1 = (ivert+1)%fNvert;
00694    Int_t icrt = 0;
00695    z1 = fZ[iz];
00696    z2 = fZ[iz+1];
00697    if (fPoly->IsClockwise()) {
00698       x = fX[ivert]*fScale[iz]+fX0[iz];
00699       y = fY[ivert]*fScale[iz]+fY0[iz];
00700       vert[icrt++] = x;
00701       vert[icrt++] = y;
00702       vert[icrt++] = z1;
00703       x = fX[iv1]*fScale[iz]+fX0[iz];
00704       y = fY[iv1]*fScale[iz]+fY0[iz];
00705       vert[icrt++] = x;
00706       vert[icrt++] = y;
00707       vert[icrt++] = z1;
00708       x = fX[iv1]*fScale[iz+1]+fX0[iz+1];
00709       y = fY[iv1]*fScale[iz+1]+fY0[iz+1];
00710       vert[icrt++] = x;
00711       vert[icrt++] = y;
00712       vert[icrt++] = z2;
00713       x = fX[ivert]*fScale[iz+1]+fX0[iz+1];
00714       y = fY[ivert]*fScale[iz+1]+fY0[iz+1];
00715       vert[icrt++] = x;
00716       vert[icrt++] = y;
00717       vert[icrt++] = z2;
00718    } else {
00719       x = fX[iv1]*fScale[iz]+fX0[iz];
00720       y = fY[iv1]*fScale[iz]+fY0[iz];
00721       vert[icrt++] = x;
00722       vert[icrt++] = y;
00723       vert[icrt++] = z1;
00724       x = fX[ivert]*fScale[iz]+fX0[iz];
00725       y = fY[ivert]*fScale[iz]+fY0[iz];
00726       vert[icrt++] = x;
00727       vert[icrt++] = y;
00728       vert[icrt++] = z1;
00729       x = fX[ivert]*fScale[iz+1]+fX0[iz+1];
00730       y = fY[ivert]*fScale[iz+1]+fY0[iz+1];
00731       vert[icrt++] = x;
00732       vert[icrt++] = y;
00733       vert[icrt++] = z2;
00734       x = fX[iv1]*fScale[iz+1]+fX0[iz+1];
00735       y = fY[iv1]*fScale[iz+1]+fY0[iz+1];
00736       vert[icrt++] = x;
00737       vert[icrt++] = y;
00738       vert[icrt++] = z2;
00739    }
00740 }
00741 //_____________________________________________________________________________
00742 Bool_t TGeoXtru::IsPointInsidePlane(Double_t *point, Double_t *vert, Double_t *norm) const
00743 {
00744 // Check if the quadrilateral defined by VERT contains a coplanar POINT.
00745    Double_t v1[3], v2[3];
00746    Double_t cross;
00747    Int_t j,k;
00748    for (Int_t i=0; i<4; i++) { // loop vertices
00749       j = 3*i;
00750       k = 3*((i+1)%4);
00751       v1[0] = point[0]-vert[j];
00752       v1[1] = point[1]-vert[j+1];
00753       v1[2] = point[2]-vert[j+2];
00754       v2[0] = vert[k]-vert[j];
00755       v2[1] = vert[k+1]-vert[j+1];
00756       v2[2] = vert[k+2]-vert[j+2];
00757       cross = (v1[1]*v2[2]-v1[2]*v2[1])*norm[0]+
00758               (v1[2]*v2[0]-v1[0]*v2[2])*norm[1]+
00759               (v1[0]*v2[1]-v1[1]*v2[0])*norm[2];
00760       if (cross<0) return kFALSE;
00761    }
00762    return kTRUE;   
00763 }
00764 
00765 //_____________________________________________________________________________
00766 void TGeoXtru::InspectShape() const
00767 {
00768 // Print actual Xtru parameters.
00769    printf("*** Shape %s: TGeoXtru ***\n", GetName());
00770    printf("    Nz    = %i\n", fNz);
00771    printf("    List of (x,y) of polygon vertices:\n");
00772    for (Int_t ivert = 0; ivert<fNvert; ivert++)
00773       printf("    x = %11.5f  y = %11.5f\n", fX[ivert],fY[ivert]);
00774    for (Int_t ipl=0; ipl<fNz; ipl++)
00775       printf("     plane %i: z=%11.5f x0=%11.5f y0=%11.5f scale=%11.5f\n", ipl, fZ[ipl], fX0[ipl], fY0[ipl], fScale[ipl]);
00776    printf(" Bounding box:\n");
00777    TGeoBBox::InspectShape();
00778 }
00779 
00780 //_____________________________________________________________________________
00781 TBuffer3D *TGeoXtru::MakeBuffer3D() const
00782 { 
00783    // Creates a TBuffer3D describing *this* shape.
00784    // Coordinates are in local reference frame.
00785    Int_t nz = GetNz();
00786    Int_t nvert = GetNvert();
00787    Int_t nbPnts = nz*nvert;
00788    Int_t nbSegs = nvert*(2*nz-1);
00789    Int_t nbPols = nvert*(nz-1)+2;
00790 
00791    TBuffer3D* buff = new TBuffer3D(TBuffer3DTypes::kGeneric,
00792                                    nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*(nbPols-2)+2*(2+nvert));
00793    if (buff)
00794    {
00795       SetPoints(buff->fPnts);   
00796       SetSegsAndPols(*buff);
00797    }
00798 
00799    return buff; 
00800 }
00801 
00802 //_____________________________________________________________________________
00803 void TGeoXtru::SetSegsAndPols(TBuffer3D &buff) const
00804 {
00805 // Fill TBuffer3D structure for segments and polygons.
00806    Int_t nz = GetNz();
00807    Int_t nvert = GetNvert();
00808    Int_t c = GetBasicColor();
00809 
00810    Int_t i,j;
00811    Int_t indx, indx2, k;
00812    indx = indx2 = 0;
00813    for (i=0; i<nz; i++) {
00814       // loop Z planes
00815       indx2 = i*nvert;
00816       // loop polygon segments
00817       for (j=0; j<nvert; j++) {
00818          k = (j+1)%nvert;
00819          buff.fSegs[indx++] = c;
00820          buff.fSegs[indx++] = indx2+j;
00821          buff.fSegs[indx++] = indx2+k;
00822       }
00823    } // total: nz*nvert polygon segments
00824    for (i=0; i<nz-1; i++) {
00825       // loop Z planes
00826       indx2 = i*nvert;
00827       // loop polygon segments
00828       for (j=0; j<nvert; j++) {
00829          k = j + nvert;
00830          buff.fSegs[indx++] = c;
00831          buff.fSegs[indx++] = indx2+j;
00832          buff.fSegs[indx++] = indx2+k;
00833       }
00834    } // total (nz-1)*nvert lateral segments
00835 
00836    indx = 0;
00837 
00838    // fill lateral polygons
00839    for (i=0; i<nz-1; i++) {
00840       indx2 = i*nvert;
00841       for (j=0; j<nvert; j++) {
00842       k = (j+1)%nvert;
00843       buff.fPols[indx++] = c+j%3;
00844       buff.fPols[indx++] = 4;
00845       buff.fPols[indx++] = indx2+j;
00846       buff.fPols[indx++] = nz*nvert+indx2+k;
00847       buff.fPols[indx++] = indx2+nvert+j;
00848       buff.fPols[indx++] = nz*nvert+indx2+j;
00849       }
00850    } // total (nz-1)*nvert polys
00851    buff.fPols[indx++] = c+2;
00852    buff.fPols[indx++] = nvert;
00853    indx2 = 0;
00854    for (j = nvert - 1; j >= 0; --j) {
00855       buff.fPols[indx++] = indx2+j;
00856    }
00857 
00858    buff.fPols[indx++] = c;
00859    buff.fPols[indx++] = nvert;
00860    indx2 = (nz-1)*nvert;
00861  
00862    for (j=0; j<nvert; j++) {
00863       buff.fPols[indx++] = indx2+j;
00864    }
00865 }
00866 
00867 //_____________________________________________________________________________
00868 Double_t TGeoXtru::SafetyToSector(Double_t *point, Int_t iz, Double_t safmin)
00869 {
00870 // Compute safety to sector iz, returning also the closest segment index.
00871    Double_t safz = TGeoShape::Big();
00872    Double_t saf1, saf2;
00873    Bool_t in1, in2;
00874    Int_t iseg;
00875    Double_t safe = TGeoShape::Big();
00876    // segment-break case
00877    if (TGeoShape::IsSameWithinTolerance(fZ[iz],fZ[iz+1])) {
00878       safz = TMath::Abs(point[2]-fZ[iz]);
00879       if (safz>safmin) return TGeoShape::Big();
00880       SetCurrentVertices(fX0[iz], fY0[iz], fScale[iz]);
00881       saf1 = fPoly->Safety(point, iseg);
00882       in1 = fPoly->Contains(point);
00883       if (!in1 && saf1>safmin) return TGeoShape::Big(); 
00884       SetCurrentVertices(fX0[iz+1], fY0[iz+1], fScale[iz+1]);
00885       saf2 = fPoly->Safety(point, iseg);
00886       in2 = fPoly->Contains(point);
00887       if ((in1&!in2)|(in2&!in1)) {
00888          safe = safz; 
00889       } else {
00890          safe = TMath::Min(saf1,saf2);
00891          safe = TMath::Max(safe, safz);
00892       }
00893       if (safe>safmin) return TGeoShape::Big();
00894       return safe;
00895    }      
00896    // normal case
00897    safz = fZ[iz]-point[2];
00898    if (safz>safmin) return TGeoShape::Big();
00899    if (safz<0) {
00900       saf1 = point[2]-fZ[iz+1];
00901       if (saf1>safmin) return TGeoShape::Big(); 
00902       if (saf1<0) {
00903          safz = TMath::Max(safz, saf1); // we are in between the 2 Z segments - we ignore safz
00904       } else {
00905          safz = saf1;
00906       }
00907    }         
00908    SetCurrentZ(point[2],iz);
00909    saf1 = fPoly->Safety(point, iseg);
00910    Double_t vert[12];
00911    Double_t norm[3];
00912    GetPlaneVertices(iz,iseg,vert);
00913    GetPlaneNormal(vert, norm);
00914    saf1 = saf1*TMath::Sqrt(1.-norm[2]*norm[2]);
00915    if (fPoly->Contains(point)) saf1 = -saf1;
00916    safe = TMath::Max(safz, saf1);
00917    safe = TMath::Abs(safe);
00918    if (safe>safmin) return TGeoShape::Big();
00919    return safe;
00920 }
00921 
00922 //_____________________________________________________________________________
00923 Double_t TGeoXtru::Safety(Double_t *point, Bool_t in) const
00924 {
00925 // computes the closest distance from given point to this shape, according
00926 // to option. The matching point on the shape is stored in spoint.
00927    //---> localize the Z segment
00928    Double_t safmin = TGeoShape::Big();
00929    Double_t safe;
00930    Double_t safz = TGeoShape::Big();
00931    TGeoXtru *xtru = (TGeoXtru*)this;
00932    Int_t iz;
00933    if (in) {
00934       safmin = TMath::Min(point[2]-fZ[0], fZ[fNz-1]-point[2]);
00935       for (iz=0; iz<fNz-1; iz++) {
00936          safe = xtru->SafetyToSector(point, iz, safmin);
00937          if (safe<safmin) safmin = safe;
00938       }
00939       return safmin;
00940    }
00941    iz = TMath::BinarySearch(fNz, fZ, point[2]);
00942    if (iz<0) {
00943       iz = 0;
00944       safz = fZ[0] - point[2];
00945    } else {
00946       if (iz==fNz-1) {
00947          iz = fNz-2;
00948          safz = point[2] - fZ[fNz-1];
00949       }
00950    }
00951    // loop segments from iz up
00952    Int_t i;
00953    for (i=iz; i<fNz-1; i++) {
00954       safe = xtru->SafetyToSector(point,i,safmin);
00955       if (safe<safmin) safmin=safe;
00956    }
00957    // loop segments from iz-1 down
00958    for (i=iz-1; i>0; i--) {            
00959       safe = xtru->SafetyToSector(point,i,safmin);
00960       if (safe<safmin) safmin=safe;
00961    }
00962    safe = TMath::Min(safmin, safz);
00963    return safe;
00964 }
00965 
00966 //_____________________________________________________________________________
00967 void TGeoXtru::SavePrimitive(ostream &out, Option_t * /*option*/ /*= ""*/)
00968 {
00969 // Save a primitive as a C++ statement(s) on output stream "out".
00970    if (TObject::TestBit(kGeoSavePrimitive)) return;   
00971    out << "   // Shape: " << GetName() << " type: " << ClassName() << endl;
00972    out << "   nz       = " << fNz << ";" << endl;
00973    out << "   nvert    = " << fNvert << ";" << endl;
00974    out << "   TGeoXtru *xtru = new TGeoXtru(nz);" << endl;
00975    out << "   xtru->SetName(\"" << GetName() << "\");" << endl;
00976    Int_t i;
00977    for (i=0; i<fNvert; i++) {
00978       out << "   xvert[" << i << "] = " << fX[i] << ";   yvert[" << i << "] = " << fY[i] << ";" << endl;
00979    }
00980    out << "   xtru->DefinePolygon(nvert,xvert,yvert);" << endl;
00981    for (i=0; i<fNz; i++) {
00982       out << "   zsect  = " << fZ[i] << ";" << endl; 
00983       out << "   x0     = " << fX0[i] << ";" << endl; 
00984       out << "   y0     = " << fY0[i] << ";" << endl; 
00985       out << "   scale0 = " << fScale[i] << ";" << endl; 
00986       out << "   xtru->DefineSection(" << i << ",zsect,x0,y0,scale0);" << endl;
00987    }
00988    out << "   TGeoShape *" << GetPointerName() << " = xtru;" << endl;
00989    TObject::SetBit(TGeoShape::kGeoSavePrimitive);
00990 }         
00991 
00992 //_____________________________________________________________________________
00993 void TGeoXtru::SetCurrentZ(Double_t z, Int_t iz)
00994 {
00995 // Recompute current section vertices for a given Z position within range of section iz.
00996    Double_t x0, y0, scale, a, b;
00997    Int_t ind1, ind2;
00998    ind1 = iz;
00999    ind2 = iz+1;   
01000    Double_t invdz = 1./(fZ[ind2]-fZ[ind1]);
01001    a = (fX0[ind1]*fZ[ind2]-fX0[ind2]*fZ[ind1])*invdz;
01002    b = (fX0[ind2]-fX0[ind1])*invdz;
01003    x0 = a+b*z;
01004    a = (fY0[ind1]*fZ[ind2]-fY0[ind2]*fZ[ind1])*invdz;
01005    b = (fY0[ind2]-fY0[ind1])*invdz;
01006    y0 = a+b*z;
01007    a = (fScale[ind1]*fZ[ind2]-fScale[ind2]*fZ[ind1])*invdz;
01008    b = (fScale[ind2]-fScale[ind1])*invdz;
01009    scale = a+b*z;
01010    SetCurrentVertices(x0,y0,scale);
01011 }
01012       
01013 //_____________________________________________________________________________
01014 void TGeoXtru::SetCurrentVertices(Double_t x0, Double_t y0, Double_t scale)      
01015 {
01016 // Set current vertex coordinates according X0, Y0 and SCALE.
01017    for (Int_t i=0; i<fNvert; i++) {
01018       fXc[i] = scale*fX[i] + x0;
01019       fYc[i] = scale*fY[i] + y0;
01020    }   
01021 }
01022 
01023 //_____________________________________________________________________________
01024 void TGeoXtru::SetDimensions(Double_t *param)
01025 {
01026 // param[0] = nz  // number of z planes
01027 //
01028 // param[1] = z1  // Z position of first plane
01029 // param[2] = x1  // X position of first plane
01030 // param[3] = y1  // Y position of first plane
01031 // param[4] = scale1  // scale factor for first plane
01032 // ...
01033 // param[4*(nz-1]+1] = zn
01034 // param[4*(nz-1)+2] = xn
01035 // param[4*(nz-1)+3] = yn
01036 // param[4*(nz-1)+4] = scalen
01037    fNz = (Int_t)param[0];   
01038    if (fNz<2) {
01039       Error("SetDimensions","Cannot create TGeoXtru %s with less than 2 Z planes",GetName());
01040       SetShapeBit(TGeoShape::kGeoBad);
01041       return;
01042    }
01043    if (fZ) delete [] fZ;
01044    if (fScale) delete [] fScale;
01045    if (fX0) delete [] fX0;
01046    if (fY0) delete [] fY0;
01047    fZ = new Double_t[fNz];
01048    fScale = new Double_t[fNz];
01049    fX0 = new Double_t[fNz];
01050    fY0 = new Double_t[fNz];
01051    
01052    for (Int_t i=0; i<fNz; i++) 
01053       DefineSection(i, param[1+4*i], param[2+4*i], param[3+4*i], param[4+4*i]);
01054 }   
01055 
01056 //_____________________________________________________________________________
01057 void TGeoXtru::SetPoints(Double_t *points) const
01058 {
01059 // create polycone mesh points
01060    Int_t i, j;
01061    Int_t indx = 0;
01062    TGeoXtru *xtru = (TGeoXtru*)this;
01063    if (points) {
01064       for (i = 0; i < fNz; i++) {
01065          xtru->SetCurrentVertices(fX0[i], fY0[i], fScale[i]);
01066          if (fPoly->IsClockwise()) {
01067             for (j = 0; j < fNvert; j++) {
01068                points[indx++] = fXc[j];
01069                points[indx++] = fYc[j];
01070                points[indx++] = fZ[i];
01071             }
01072          } else {
01073             for (j = 0; j < fNvert; j++) {
01074                points[indx++] = fXc[fNvert-1-j];
01075                points[indx++] = fYc[fNvert-1-j];
01076                points[indx++] = fZ[i];
01077             }
01078          }   
01079       }
01080    }
01081 }
01082 
01083 //_____________________________________________________________________________
01084 void TGeoXtru::SetPoints(Float_t *points) const
01085 {
01086 // create polycone mesh points
01087    Int_t i, j;
01088    Int_t indx = 0;
01089    TGeoXtru *xtru = (TGeoXtru*)this;
01090    if (points) {
01091       for (i = 0; i < fNz; i++) {
01092          xtru->SetCurrentVertices(fX0[i], fY0[i], fScale[i]);
01093          if (fPoly->IsClockwise()) {
01094             for (j = 0; j < fNvert; j++) {
01095                points[indx++] = fXc[j];
01096                points[indx++] = fYc[j];
01097                points[indx++] = fZ[i];
01098             }
01099          } else {
01100             for (j = 0; j < fNvert; j++) {
01101                points[indx++] = fXc[fNvert-1-j];
01102                points[indx++] = fYc[fNvert-1-j];
01103                points[indx++] = fZ[i];
01104             }
01105          }   
01106       }
01107    }
01108 }
01109 
01110 //_____________________________________________________________________________
01111 void TGeoXtru::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
01112 {
01113 // Returns numbers of vertices, segments and polygons composing the shape mesh.
01114    Int_t nz = GetNz();
01115    Int_t nv = GetNvert();
01116    nvert = nz*nv;
01117    nsegs = nv*(2*nz-1);
01118    npols = nv*(nz-1)+2;
01119 }
01120 
01121 //_____________________________________________________________________________
01122 Int_t TGeoXtru::GetNmeshVertices() const
01123 {
01124 // Return number of vertices of the mesh representation
01125    Int_t numPoints = fNz*fNvert;
01126    return numPoints;
01127 }
01128 
01129 //_____________________________________________________________________________
01130 void TGeoXtru::Sizeof3D() const
01131 {
01132 ///// fill size of this 3-D object
01133 ///   TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
01134 ///   if (!painter) return;
01135 ///
01136 ///   Int_t numPoints = fNz*fNvert;
01137 ///   Int_t numSegs   = fNvert*(2*fNz-1);
01138 ///   Int_t numPolys  = fNvert*(fNz-1)+2;
01139 ///   painter->AddSize3D(numPoints, numSegs, numPolys);
01140 }
01141 
01142 //_____________________________________________________________________________
01143 void TGeoXtru::Streamer(TBuffer &R__b)
01144 {
01145    // Stream an object of class TGeoVolume.
01146    if (R__b.IsReading()) {
01147       R__b.ReadClassBuffer(TGeoXtru::Class(), this);
01148       if (fPoly) fPoly->SetXY(fXc,fYc); // initialize with current coordinates   
01149    } else {
01150       R__b.WriteClassBuffer(TGeoXtru::Class(), this);
01151    }
01152 }
01153 
01154 //_____________________________________________________________________________
01155 const TBuffer3D & TGeoXtru::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
01156 {
01157 // Fills a static 3D buffer and returns a reference.
01158    static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
01159 
01160    TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
01161 
01162    if (reqSections & TBuffer3D::kRawSizes) {
01163       Int_t nz = GetNz();
01164       Int_t nvert = GetNvert();
01165       Int_t nbPnts = nz*nvert;
01166       Int_t nbSegs = nvert*(2*nz-1);
01167       Int_t nbPols = nvert*(nz-1)+2;            
01168       if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*(nbPols-2)+2*(2+nvert))) {
01169          buffer.SetSectionsValid(TBuffer3D::kRawSizes);
01170       }
01171    }
01172    // TODO: Push down to TGeoShape?
01173    if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
01174       SetPoints(buffer.fPnts);
01175       if (!buffer.fLocalFrame) {
01176          TransformPoints(buffer.fPnts, buffer.NbPnts());
01177       }
01178 
01179       SetSegsAndPols(buffer);      
01180       buffer.SetSectionsValid(TBuffer3D::kRaw);
01181    }
01182       
01183    return buffer;
01184 }

Generated on Tue Jul 5 14:12:59 2011 for ROOT_528-00b_version by  doxygen 1.5.1