00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include "Riostream.h"
00047
00048 #include "TGeoManager.h"
00049 #include "TGeoVolume.h"
00050 #include "TVirtualGeoPainter.h"
00051 #include "TGeoTube.h"
00052 #include "TGeoCone.h"
00053 #include "TGeoPcon.h"
00054 #include "TVirtualPad.h"
00055 #include "TBuffer3D.h"
00056 #include "TBuffer3DTypes.h"
00057 #include "TMath.h"
00058
00059 ClassImp(TGeoPcon)
00060
00061
00062 TGeoPcon::TGeoPcon()
00063 :TGeoBBox(0, 0, 0),
00064 fNz(0),
00065 fPhi1(0.),
00066 fDphi(0.),
00067 fRmin(NULL),
00068 fRmax(NULL),
00069 fZ(NULL)
00070 {
00071
00072 SetShapeBit(TGeoShape::kGeoPcon);
00073 }
00074
00075
00076 TGeoPcon::TGeoPcon(Double_t phi, Double_t dphi, Int_t nz)
00077 :TGeoBBox(0, 0, 0),
00078 fNz(nz),
00079 fPhi1(phi),
00080 fDphi(dphi),
00081 fRmin(NULL),
00082 fRmax(NULL),
00083 fZ(NULL)
00084 {
00085
00086 SetShapeBit(TGeoShape::kGeoPcon);
00087 if (fPhi1<0) fPhi1+=360.;
00088 fRmin = new Double_t [nz];
00089 fRmax = new Double_t [nz];
00090 fZ = new Double_t [nz];
00091 memset(fRmin, 0, nz*sizeof(Double_t));
00092 memset(fRmax, 0, nz*sizeof(Double_t));
00093 memset(fZ, 0, nz*sizeof(Double_t));
00094 }
00095
00096
00097 TGeoPcon::TGeoPcon(const char *name, Double_t phi, Double_t dphi, Int_t nz)
00098 :TGeoBBox(name, 0, 0, 0),
00099 fNz(nz),
00100 fPhi1(phi),
00101 fDphi(dphi),
00102 fRmin(NULL),
00103 fRmax(NULL),
00104 fZ(NULL)
00105 {
00106
00107 SetShapeBit(TGeoShape::kGeoPcon);
00108 if (fPhi1<0) fPhi1+=360.;
00109 fRmin = new Double_t [nz];
00110 fRmax = new Double_t [nz];
00111 fZ = new Double_t [nz];
00112 memset(fRmin, 0, nz*sizeof(Double_t));
00113 memset(fRmax, 0, nz*sizeof(Double_t));
00114 memset(fZ, 0, nz*sizeof(Double_t));
00115 }
00116
00117
00118 TGeoPcon::TGeoPcon(Double_t *param)
00119 :TGeoBBox(0, 0, 0),
00120 fNz(0),
00121 fPhi1(0.),
00122 fDphi(0.),
00123 fRmin(0),
00124 fRmax(0),
00125 fZ(0)
00126 {
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 SetShapeBit(TGeoShape::kGeoPcon);
00137 SetDimensions(param);
00138 ComputeBBox();
00139 }
00140
00141
00142 TGeoPcon::TGeoPcon(const TGeoPcon& pc) :
00143 TGeoBBox(pc),
00144 fNz(pc.fNz),
00145 fPhi1(pc.fPhi1),
00146 fDphi(pc.fDphi),
00147 fRmin(pc.fRmin),
00148 fRmax(pc.fRmax),
00149 fZ(pc.fZ)
00150 {
00151
00152 }
00153
00154
00155 TGeoPcon& TGeoPcon::operator=(const TGeoPcon& pc)
00156 {
00157
00158 if(this!=&pc) {
00159 TGeoBBox::operator=(pc);
00160 fNz=pc.fNz;
00161 fPhi1=pc.fPhi1;
00162 fDphi=pc.fDphi;
00163 fRmin=pc.fRmin;
00164 fRmax=pc.fRmax;
00165 fZ=pc.fZ;
00166 }
00167 return *this;
00168 }
00169
00170
00171 TGeoPcon::~TGeoPcon()
00172 {
00173
00174 if (fRmin) {delete[] fRmin; fRmin = 0;}
00175 if (fRmax) {delete[] fRmax; fRmax = 0;}
00176 if (fZ) {delete[] fZ; fZ = 0;}
00177 }
00178
00179
00180 Double_t TGeoPcon::Capacity() const
00181 {
00182
00183 Int_t ipl;
00184 Double_t rmin1, rmax1, rmin2, rmax2, phi1, phi2, dz;
00185 Double_t capacity = 0.;
00186 phi1 = fPhi1;
00187 phi2 = fPhi1 + fDphi;
00188 for (ipl=0; ipl<fNz-1; ipl++) {
00189 dz = 0.5*(fZ[ipl+1]-fZ[ipl]);
00190 if (dz < TGeoShape::Tolerance()) continue;
00191 rmin1 = fRmin[ipl];
00192 rmax1 = fRmax[ipl];
00193 rmin2 = fRmin[ipl+1];
00194 rmax2 = fRmax[ipl+1];
00195 capacity += TGeoConeSeg::Capacity(dz,rmin1,rmax1,rmin2,rmax2,phi1,phi2);
00196 }
00197 return capacity;
00198 }
00199
00200
00201 void TGeoPcon::ComputeBBox()
00202 {
00203
00204
00205 for (Int_t isec=0; isec<fNz-1; isec++) {
00206 if (TMath::Abs(fZ[isec]-fZ[isec+1]) < TGeoShape::Tolerance()) fZ[isec+1]=fZ[isec];
00207 if (fZ[isec]>fZ[isec+1]) {
00208 InspectShape();
00209 Fatal("ComputeBBox", "Wrong section order");
00210 }
00211 }
00212
00213 if (TMath::Abs(fZ[1]-fZ[0]) < TGeoShape::Tolerance() ||
00214 TMath::Abs(fZ[fNz-1]-fZ[fNz-2]) < TGeoShape::Tolerance()) {
00215 InspectShape();
00216 Fatal("ComputeBBox","Shape %s at index %d: Not allowed first two or last two sections at same Z",
00217 GetName(), gGeoManager->GetListOfShapes()->IndexOf(this));
00218 }
00219 Double_t zmin = TMath::Min(fZ[0], fZ[fNz-1]);
00220 Double_t zmax = TMath::Max(fZ[0], fZ[fNz-1]);
00221
00222 Double_t rmin, rmax;
00223 rmin = fRmin[TMath::LocMin(fNz, fRmin)];
00224 rmax = fRmax[TMath::LocMax(fNz, fRmax)];
00225 Double_t phi1 = fPhi1;
00226 Double_t phi2 = phi1 + fDphi;
00227
00228 Double_t xc[4];
00229 Double_t yc[4];
00230 xc[0] = rmax*TMath::Cos(phi1*TMath::DegToRad());
00231 yc[0] = rmax*TMath::Sin(phi1*TMath::DegToRad());
00232 xc[1] = rmax*TMath::Cos(phi2*TMath::DegToRad());
00233 yc[1] = rmax*TMath::Sin(phi2*TMath::DegToRad());
00234 xc[2] = rmin*TMath::Cos(phi1*TMath::DegToRad());
00235 yc[2] = rmin*TMath::Sin(phi1*TMath::DegToRad());
00236 xc[3] = rmin*TMath::Cos(phi2*TMath::DegToRad());
00237 yc[3] = rmin*TMath::Sin(phi2*TMath::DegToRad());
00238
00239 Double_t xmin = xc[TMath::LocMin(4, &xc[0])];
00240 Double_t xmax = xc[TMath::LocMax(4, &xc[0])];
00241 Double_t ymin = yc[TMath::LocMin(4, &yc[0])];
00242 Double_t ymax = yc[TMath::LocMax(4, &yc[0])];
00243
00244 Double_t ddp = -phi1;
00245 if (ddp<0) ddp+= 360;
00246 if (ddp<=fDphi) xmax = rmax;
00247 ddp = 90-phi1;
00248 if (ddp<0) ddp+= 360;
00249 if (ddp<=fDphi) ymax = rmax;
00250 ddp = 180-phi1;
00251 if (ddp<0) ddp+= 360;
00252 if (ddp<=fDphi) xmin = -rmax;
00253 ddp = 270-phi1;
00254 if (ddp<0) ddp+= 360;
00255 if (ddp<=fDphi) ymin = -rmax;
00256 fOrigin[0] = (xmax+xmin)/2;
00257 fOrigin[1] = (ymax+ymin)/2;
00258 fOrigin[2] = (zmax+zmin)/2;
00259 fDX = (xmax-xmin)/2;
00260 fDY = (ymax-ymin)/2;
00261 fDZ = (zmax-zmin)/2;
00262 SetShapeBit(kGeoClosedShape);
00263 }
00264
00265
00266 void TGeoPcon::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
00267 {
00268
00269 memset(norm,0,3*sizeof(Double_t));
00270 Double_t r;
00271 Double_t ptnew[3];
00272 Double_t dz, rmin1, rmax1, rmin2, rmax2;
00273 Bool_t is_tube, is_seg;
00274 Double_t phi1=0, phi2=0, c1=0, s1=0, c2=0, s2=0;
00275 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
00276 if (ipl==(fNz-1) || ipl<0) {
00277
00278 norm[2] = TMath::Sign(1., dir[2]);
00279 return;
00280 }
00281 Int_t iplclose = ipl;
00282 if ((fZ[ipl+1]-point[2])<(point[2]-fZ[ipl])) iplclose++;
00283 dz = TMath::Abs(fZ[iplclose]-point[2]);
00284 if (dz<1E-5) {
00285 if (iplclose==0 || iplclose==(fNz-1)) {
00286 norm[2] = TMath::Sign(1., dir[2]);
00287 return;
00288 }
00289 if (iplclose==ipl && TGeoShape::IsSameWithinTolerance(fZ[ipl],fZ[ipl-1])) {
00290 r = TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
00291 if (r<TMath::Max(fRmin[ipl],fRmin[ipl-1]) || r>TMath::Min(fRmax[ipl],fRmax[ipl-1])) {
00292 norm[2] = TMath::Sign(1., dir[2]);
00293 return;
00294 }
00295 } else {
00296 if (TGeoShape::IsSameWithinTolerance(fZ[iplclose],fZ[iplclose+1])) {
00297 r = TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
00298 if (r<TMath::Max(fRmin[iplclose],fRmin[iplclose+1]) || r>TMath::Min(fRmax[iplclose],fRmax[iplclose+1])) {
00299 norm[2] = TMath::Sign(1., dir[2]);
00300 return;
00301 }
00302 }
00303 }
00304 }
00305 memcpy(ptnew, point, 3*sizeof(Double_t));
00306 dz = 0.5*(fZ[ipl+1]-fZ[ipl]);
00307 if (TGeoShape::IsSameWithinTolerance(dz,0.)) {
00308 norm[2] = TMath::Sign(1., dir[2]);
00309 return;
00310 }
00311 ptnew[2] -= 0.5*(fZ[ipl]+fZ[ipl+1]);
00312 rmin1 = fRmin[ipl];
00313 rmax1 = fRmax[ipl];
00314 rmin2 = fRmin[ipl+1];
00315 rmax2 = fRmax[ipl+1];
00316 is_tube = (TGeoShape::IsSameWithinTolerance(rmin1,rmin2) && TGeoShape::IsSameWithinTolerance(rmax1,rmax2))?kTRUE:kFALSE;
00317 is_seg = (fDphi<360)?kTRUE:kFALSE;
00318 if (is_seg) {
00319 phi1 = fPhi1;
00320 if (phi1<0) phi1+=360;
00321 phi2 = phi1 + fDphi;
00322 phi1 *= TMath::DegToRad();
00323 phi2 *= TMath::DegToRad();
00324 c1 = TMath::Cos(phi1);
00325 s1 = TMath::Sin(phi1);
00326 c2 = TMath::Cos(phi2);
00327 s2 = TMath::Sin(phi2);
00328 if (is_tube) TGeoTubeSeg::ComputeNormalS(ptnew,dir,norm,rmin1,rmax1,dz,c1,s1,c2,s2);
00329 else TGeoConeSeg::ComputeNormalS(ptnew,dir,norm,dz,rmin1,rmax1,rmin2,rmax2,c1,s1,c2,s2);
00330 } else {
00331 if (is_tube) TGeoTube::ComputeNormalS(ptnew,dir,norm,rmin1,rmax1,dz);
00332 else TGeoCone::ComputeNormalS(ptnew,dir,norm,dz,rmin1,rmax1,rmin2,rmax2);
00333 }
00334 }
00335
00336
00337 Bool_t TGeoPcon::Contains(Double_t *point) const
00338 {
00339
00340
00341 if ((point[2]<fZ[0]) || (point[2]>fZ[fNz-1])) return kFALSE;
00342
00343 Double_t r2 = point[0]*point[0]+point[1]*point[1];
00344
00345 Int_t izl = 0;
00346 Int_t izh = fNz-1;
00347 Int_t izt = (fNz-1)/2;
00348 while ((izh-izl)>1) {
00349 if (point[2] > fZ[izt]) izl = izt;
00350 else izh = izt;
00351 izt = (izl+izh)>>1;
00352 }
00353
00354
00355
00356 Double_t rmin, rmax;
00357 if (TGeoShape::IsSameWithinTolerance(fZ[izl],fZ[izh]) && TGeoShape::IsSameWithinTolerance(point[2],fZ[izl])) {
00358 rmin = TMath::Min(fRmin[izl], fRmin[izh]);
00359 rmax = TMath::Max(fRmax[izl], fRmax[izh]);
00360 } else {
00361 Double_t dz = fZ[izh] - fZ[izl];
00362 Double_t dz1 = point[2] - fZ[izl];
00363 rmin = (fRmin[izl]*(dz-dz1)+fRmin[izh]*dz1)/dz;
00364 rmax = (fRmax[izl]*(dz-dz1)+fRmax[izh]*dz1)/dz;
00365 }
00366 if ((r2<rmin*rmin) || (r2>rmax*rmax)) return kFALSE;
00367
00368 if (TGeoShape::IsSameWithinTolerance(fDphi,360)) return kTRUE;
00369 if (r2<1E-10) return kTRUE;
00370 Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
00371 if (phi < 0) phi+=360.0;
00372 Double_t ddp = phi-fPhi1;
00373 if (ddp<0) ddp+=360.;
00374 if (ddp<=fDphi) return kTRUE;
00375 return kFALSE;
00376 }
00377
00378
00379 Int_t TGeoPcon::DistancetoPrimitive(Int_t px, Int_t py)
00380 {
00381
00382 Int_t n = gGeoManager->GetNsegments()+1;
00383 const Int_t numPoints = 2*n*fNz;
00384 return ShapeDistancetoPrimitive(numPoints, px, py);
00385 }
00386
00387
00388 Double_t TGeoPcon::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00389 {
00390
00391 if (iact<3 && safe) {
00392 *safe = Safety(point, kTRUE);
00393 if (iact==0) return TGeoShape::Big();
00394 if ((iact==1) && (*safe>step)) return TGeoShape::Big();
00395 }
00396 Double_t snxt = TGeoShape::Big();
00397 Double_t sstep = 1E-6;
00398 Double_t point_new[3];
00399
00400 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
00401 if (ipl<0) ipl=0;
00402 if (ipl==(fNz-1)) ipl--;
00403 Double_t dz = 0.5*(fZ[ipl+1]-fZ[ipl]);
00404 Bool_t special_case = kFALSE;
00405 if (dz<1e-9) {
00406
00407 if (TGeoShape::IsSameWithinTolerance(dir[2], 0)) {
00408 special_case = kTRUE;
00409 } else {
00410
00411 point_new[0] = point[0]+sstep*dir[0];
00412 point_new[1] = point[1]+sstep*dir[1];
00413 point_new[2] = point[2]+sstep*dir[2];
00414 if (!Contains(point_new)) return 0.;
00415 return (DistFromInside(point_new,dir,iact,step,safe)+sstep);
00416 }
00417 }
00418
00419 Bool_t intub = kTRUE;
00420 if (!TGeoShape::IsSameWithinTolerance(fRmin[ipl],fRmin[ipl+1])) intub=kFALSE;
00421 else if (!TGeoShape::IsSameWithinTolerance(fRmax[ipl],fRmax[ipl+1])) intub=kFALSE;
00422
00423 Bool_t inphi=kTRUE;
00424 if (TGeoShape::IsSameWithinTolerance(fDphi,360)) inphi=kFALSE;
00425 memcpy(point_new, point, 2*sizeof(Double_t));
00426
00427 point_new[2] = point[2]-0.5*(fZ[ipl]+fZ[ipl+1]);
00428
00429 Double_t phi1 = fPhi1;
00430 if (phi1<0) phi1+=360.;
00431 Double_t phi2 = phi1+fDphi;
00432 Double_t phim = 0.5*(phi1+phi2);
00433 Double_t c1 = TMath::Cos(phi1*TMath::DegToRad());
00434 Double_t s1 = TMath::Sin(phi1*TMath::DegToRad());
00435 Double_t c2 = TMath::Cos(phi2*TMath::DegToRad());
00436 Double_t s2 = TMath::Sin(phi2*TMath::DegToRad());
00437 Double_t cm = TMath::Cos(phim*TMath::DegToRad());
00438 Double_t sm = TMath::Sin(phim*TMath::DegToRad());
00439 Double_t cdfi = TMath::Cos(0.5*fDphi*TMath::DegToRad());
00440 if (special_case) {
00441 if (inphi) snxt = TGeoTubeSeg::DistFromInsideS(point_new, dir,
00442 TMath::Min(fRmin[ipl],fRmin[ipl+1]), TMath::Max(fRmax[ipl],fRmax[ipl+1]),
00443 dz, c1,s1,c2,s2,cm,sm,cdfi);
00444 else snxt = TGeoTube::DistFromInsideS(point_new, dir,
00445 TMath::Min(fRmin[ipl],fRmin[ipl+1]), TMath::Max(fRmax[ipl],fRmax[ipl+1]),dz);
00446 return snxt;
00447 }
00448 if (intub) {
00449 if (inphi) snxt=TGeoTubeSeg::DistFromInsideS(point_new, dir, fRmin[ipl], fRmax[ipl],dz, c1,s1,c2,s2,cm,sm,cdfi);
00450 else snxt=TGeoTube::DistFromInsideS(point_new, dir, fRmin[ipl], fRmax[ipl],dz);
00451 } else {
00452 if (inphi) snxt=TGeoConeSeg::DistFromInsideS(point_new,dir,dz,fRmin[ipl],fRmax[ipl],fRmin[ipl+1],fRmax[ipl+1],c1,s1,c2,s2,cm,sm,cdfi);
00453 else snxt=TGeoCone::DistFromInsideS(point_new,dir,dz,fRmin[ipl],fRmax[ipl],fRmin[ipl+1], fRmax[ipl+1]);
00454 }
00455
00456 for (Int_t i=0; i<3; i++) point_new[i]=point[i]+(snxt+1E-6)*dir[i];
00457 if (!Contains(&point_new[0])) return snxt;
00458
00459 snxt += DistFromInside(&point_new[0], dir, 3) + 1E-6;
00460 return snxt;
00461 }
00462
00463
00464 Double_t TGeoPcon::DistToSegZ(Double_t *point, Double_t *dir, Int_t &iz, Double_t c1, Double_t s1,
00465 Double_t c2, Double_t s2, Double_t cfio, Double_t sfio, Double_t cdfi) const
00466 {
00467
00468 Double_t zmin=fZ[iz];
00469 Double_t zmax=fZ[iz+1];
00470 if (TGeoShape::IsSameWithinTolerance(zmin,zmax)) {
00471 if (TGeoShape::IsSameWithinTolerance(dir[2],0)) return TGeoShape::Big();
00472 Int_t istep=(dir[2]>0)?1:-1;
00473 iz+=istep;
00474 if (iz<0 || iz>(fNz-2)) return TGeoShape::Big();
00475 return DistToSegZ(point,dir,iz,c1,s1,c2,s2,cfio,sfio,cdfi);
00476 }
00477 Double_t dz=0.5*(zmax-zmin);
00478 Double_t local[3];
00479 memcpy(&local[0], point, 3*sizeof(Double_t));
00480 local[2]=point[2]-0.5*(zmin+zmax);
00481 Double_t snxt;
00482 Double_t rmin1=fRmin[iz];
00483 Double_t rmax1=fRmax[iz];
00484 Double_t rmin2=fRmin[iz+1];
00485 Double_t rmax2=fRmax[iz+1];
00486 Bool_t is_seg=(TGeoShape::IsSameWithinTolerance(fDphi,360))?kFALSE:kTRUE;
00487
00488 if (TGeoShape::IsSameWithinTolerance(rmin1,rmin2) && TGeoShape::IsSameWithinTolerance(rmax1,rmax2)) {
00489 if (!is_seg) snxt=TGeoTube::DistFromOutsideS(local, dir, rmin1, rmax1, dz);
00490 else snxt=TGeoTubeSeg::DistFromOutsideS(local,dir,rmin1,rmax1,dz,c1,s1,c2,s2,cfio,sfio,cdfi);
00491 } else {
00492 if (!is_seg) snxt=TGeoCone::DistFromOutsideS(local,dir,dz,rmin1, rmax1,rmin2,rmax2);
00493 else snxt=TGeoConeSeg::DistFromOutsideS(local,dir,dz,rmin1,rmax1,rmin2,rmax2,c1,s1,c2,s2,cfio,sfio,cdfi);
00494 }
00495 if (snxt<1E20) return snxt;
00496
00497 if (TGeoShape::IsSameWithinTolerance(dir[2],0)) return TGeoShape::Big();
00498 Int_t istep=(dir[2]>0)?1:-1;
00499 iz+=istep;
00500 if (iz<0 || iz>(fNz-2)) return TGeoShape::Big();
00501 return DistToSegZ(point,dir,iz,c1,s1,c2,s2,cfio,sfio,cdfi);
00502 }
00503
00504
00505 Double_t TGeoPcon::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00506 {
00507
00508 if ((iact<3) && safe) {
00509 *safe = Safety(point, kFALSE);
00510 if ((iact==1) && (*safe>step)) return TGeoShape::Big();
00511 if (iact==0) return TGeoShape::Big();
00512 }
00513
00514 if ((point[2]<fZ[0]) && (dir[2]<=0)) return TGeoShape::Big();
00515 if ((point[2]>fZ[fNz-1]) && (dir[2]>=0)) return TGeoShape::Big();
00516
00517 Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
00518 if (sdist>=step) return TGeoShape::Big();
00519
00520 Double_t r2 = point[0]*point[0]+point[1]*point[1];
00521 Double_t radmax=0;
00522 radmax=fRmax[TMath::LocMax(fNz, fRmax)];
00523 if (r2>(radmax*radmax)) {
00524 Double_t rpr=-point[0]*dir[0]-point[1]*dir[1];
00525 Double_t nxy=dir[0]*dir[0]+dir[1]*dir[1];
00526 if (rpr<TMath::Sqrt((r2-radmax*radmax)*nxy)) return TGeoShape::Big();
00527 }
00528
00529
00530 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
00531 Int_t ifirst = ipl;
00532 if (ifirst<0) {
00533 ifirst=0;
00534 } else if (ifirst>=(fNz-1)) ifirst=fNz-2;
00535
00536 Double_t phi=0;
00537 Double_t phi1=0;
00538 Double_t phi2=0;
00539 Double_t c1=0., s1=0., c2=0., s2=0., cfio=0., sfio=0., cdfi=0.;
00540 Bool_t inphi = (fDphi<360)?kTRUE:kFALSE;
00541 if (inphi) {
00542 phi1=fPhi1;
00543 if (phi1<0) phi1+=360;
00544 phi2=(phi1+fDphi)*TMath::DegToRad();
00545 phi1=phi1*TMath::DegToRad();
00546 phi=TMath::ATan2(point[1], point[0]);
00547 if (phi<0) phi+=2.*TMath::Pi();
00548 c1=TMath::Cos(phi1);
00549 s1=TMath::Sin(phi1);
00550 c2=TMath::Cos(phi2);
00551 s2=TMath::Sin(phi2);
00552 Double_t fio=0.5*(phi1+phi2);
00553 cfio=TMath::Cos(fio);
00554 sfio=TMath::Sin(fio);
00555 cdfi=TMath::Cos(0.5*(phi2-phi1));
00556 }
00557
00558
00559 return DistToSegZ(point,dir,ifirst, c1,s1,c2,s2,cfio,sfio,cdfi);
00560 }
00561
00562
00563 void TGeoPcon::DefineSection(Int_t snum, Double_t z, Double_t rmin, Double_t rmax)
00564 {
00565
00566
00567
00568 if ((snum<0) || (snum>=fNz)) return;
00569 fZ[snum] = z;
00570 fRmin[snum] = rmin;
00571 fRmax[snum] = rmax;
00572 if (rmin>rmax)
00573 Warning("DefineSection", "Shape %s: invalid rmin=%g rmax=%g", GetName(), rmin, rmax);
00574 if (snum==(fNz-1)) {
00575
00576 if (fZ[0] > fZ[snum]) {
00577 Int_t iz = 0;
00578 Int_t izi = fNz-1;
00579 Double_t temp;
00580 while (iz<izi) {
00581 temp = fZ[iz];
00582 fZ[iz] = fZ[izi];
00583 fZ[izi] = temp;
00584 temp = fRmin[iz];
00585 fRmin[iz] = fRmin[izi];
00586 fRmin[izi] = temp;
00587 temp = fRmax[iz];
00588 fRmax[iz] = fRmax[izi];
00589 fRmax[izi] = temp;
00590 iz++;
00591 izi--;
00592 }
00593 }
00594 ComputeBBox();
00595 }
00596 }
00597
00598
00599 Int_t TGeoPcon::GetNsegments() const
00600 {
00601
00602 return gGeoManager->GetNsegments();
00603 }
00604
00605
00606 TGeoVolume *TGeoPcon::Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv,
00607 Double_t start, Double_t step)
00608 {
00609
00610
00611
00612
00613
00614
00615 TGeoShape *shape;
00616 TGeoVolume *vol;
00617 TGeoVolumeMulti *vmulti;
00618 TGeoPatternFinder *finder;
00619 TString opt = "";
00620 Double_t zmin = start;
00621 Double_t zmax = start+ndiv*step;
00622 Int_t isect = -1;
00623 Int_t is, id, ipl;
00624 switch (iaxis) {
00625 case 1:
00626 Error("Divide", "Shape %s: cannot divide a pcon on radius", GetName());
00627 return 0;
00628 case 2:
00629 finder = new TGeoPatternCylPhi(voldiv, ndiv, start, start+ndiv*step);
00630 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
00631 voldiv->SetFinder(finder);
00632 finder->SetDivIndex(voldiv->GetNdaughters());
00633 shape = new TGeoPcon(-step/2, step, fNz);
00634 for (is=0; is<fNz; is++)
00635 ((TGeoPcon*)shape)->DefineSection(is, fZ[is], fRmin[is], fRmax[is]);
00636 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
00637 vmulti->AddVolume(vol);
00638 opt = "Phi";
00639 for (id=0; id<ndiv; id++) {
00640 voldiv->AddNodeOffset(vol, id, start+id*step+step/2, opt.Data());
00641 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
00642 }
00643 return vmulti;
00644 case 3:
00645
00646 for (ipl=0; ipl<fNz-1; ipl++) {
00647 if (start<fZ[ipl]) continue;
00648 else {
00649 if ((start+ndiv*step)>fZ[ipl+1]) continue;
00650 }
00651 isect = ipl;
00652 zmin = fZ[isect];
00653 zmax= fZ[isect+1];
00654 break;
00655 }
00656 if (isect<0) {
00657 Error("Divide", "Shape %s: cannot divide pcon on Z if divided region is not between 2 planes", GetName());
00658 return 0;
00659 }
00660 finder = new TGeoPatternZ(voldiv, ndiv, start, start+ndiv*step);
00661 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
00662 voldiv->SetFinder(finder);
00663 finder->SetDivIndex(voldiv->GetNdaughters());
00664 opt = "Z";
00665 for (id=0; id<ndiv; id++) {
00666 Double_t z1 = start+id*step;
00667 Double_t z2 = start+(id+1)*step;
00668 Double_t rmin1 = (fRmin[isect]*(zmax-z1)-fRmin[isect+1]*(zmin-z1))/(zmax-zmin);
00669 Double_t rmax1 = (fRmax[isect]*(zmax-z1)-fRmax[isect+1]*(zmin-z1))/(zmax-zmin);
00670 Double_t rmin2 = (fRmin[isect]*(zmax-z2)-fRmin[isect+1]*(zmin-z2))/(zmax-zmin);
00671 Double_t rmax2 = (fRmax[isect]*(zmax-z2)-fRmax[isect+1]*(zmin-z2))/(zmax-zmin);
00672 Bool_t is_tube = (TGeoShape::IsSameWithinTolerance(fRmin[isect],fRmin[isect+1]) && TGeoShape::IsSameWithinTolerance(fRmax[isect],fRmax[isect+1]))?kTRUE:kFALSE;
00673 Bool_t is_seg = (fDphi<360)?kTRUE:kFALSE;
00674 if (is_seg) {
00675 if (is_tube) shape=new TGeoTubeSeg(fRmin[isect],fRmax[isect],step/2, fPhi1, fPhi1+fDphi);
00676 else shape=new TGeoConeSeg(step/2, rmin1, rmax1, rmin2, rmax2, fPhi1, fPhi1+fDphi);
00677 } else {
00678 if (is_tube) shape=new TGeoTube(fRmin[isect],fRmax[isect],step/2);
00679 else shape = new TGeoCone(step/2,rmin1,rmax1,rmin2,rmax2);
00680 }
00681 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
00682 vmulti->AddVolume(vol);
00683 voldiv->AddNodeOffset(vol, id, start+id*step+step/2, opt.Data());
00684 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
00685 }
00686 return vmulti;
00687 default:
00688 Error("Divide", "Shape %s: Wrong axis %d for division",GetName(), iaxis);
00689 return 0;
00690 }
00691 }
00692
00693
00694 const char *TGeoPcon::GetAxisName(Int_t iaxis) const
00695 {
00696
00697 switch (iaxis) {
00698 case 1:
00699 return "R";
00700 case 2:
00701 return "PHI";
00702 case 3:
00703 return "Z";
00704 default:
00705 return "UNDEFINED";
00706 }
00707 }
00708
00709
00710 Double_t TGeoPcon::GetAxisRange(Int_t iaxis, Double_t &xlo, Double_t &xhi) const
00711 {
00712
00713 xlo = 0;
00714 xhi = 0;
00715 Double_t dx = 0;
00716 switch (iaxis) {
00717 case 2:
00718 xlo = fPhi1;
00719 xhi = fPhi1 + fDphi;
00720 dx = fDphi;
00721 return dx;
00722 case 3:
00723 xlo = fZ[0];
00724 xhi = fZ[fNz-1];
00725 dx = xhi-xlo;
00726 return dx;
00727 }
00728 return dx;
00729 }
00730
00731
00732 void TGeoPcon::GetBoundingCylinder(Double_t *param) const
00733 {
00734
00735
00736 param[0] = fRmin[0];
00737 param[1] = fRmax[0];
00738 for (Int_t i=1; i<fNz; i++) {
00739 if (fRmin[i] < param[0]) param[0] = fRmin[i];
00740 if (fRmax[i] > param[1]) param[1] = fRmax[i];
00741 }
00742 param[0] *= param[0];
00743 param[1] *= param[1];
00744 if (TGeoShape::IsSameWithinTolerance(fDphi,360.)) {
00745 param[2] = 0.;
00746 param[3] = 360.;
00747 return;
00748 }
00749 param[2] = (fPhi1<0)?(fPhi1+360.):fPhi1;
00750 param[3] = param[2]+fDphi;
00751 }
00752
00753
00754 Double_t TGeoPcon::GetRmin(Int_t ipl) const
00755 {
00756
00757 if (ipl<0 || ipl>(fNz-1)) {
00758 Error("GetRmin","ipl=%i out of range (0,%i) in shape %s",ipl,fNz-1,GetName());
00759 return 0.;
00760 }
00761 return fRmin[ipl];
00762 }
00763
00764
00765 Double_t TGeoPcon::GetRmax(Int_t ipl) const
00766 {
00767
00768 if (ipl<0 || ipl>(fNz-1)) {
00769 Error("GetRmax","ipl=%i out of range (0,%i) in shape %s",ipl,fNz-1,GetName());
00770 return 0.;
00771 }
00772 return fRmax[ipl];
00773 }
00774
00775
00776 Double_t TGeoPcon::GetZ(Int_t ipl) const
00777 {
00778
00779 if (ipl<0 || ipl>(fNz-1)) {
00780 Error("GetZ","ipl=%i out of range (0,%i) in shape %s",ipl,fNz-1,GetName());
00781 return 0.;
00782 }
00783 return fZ[ipl];
00784 }
00785
00786
00787 void TGeoPcon::InspectShape() const
00788 {
00789
00790 printf("*** Shape %s: TGeoPcon ***\n", GetName());
00791 printf(" Nz = %i\n", fNz);
00792 printf(" phi1 = %11.5f\n", fPhi1);
00793 printf(" dphi = %11.5f\n", fDphi);
00794 for (Int_t ipl=0; ipl<fNz; ipl++)
00795 printf(" plane %i: z=%11.5f Rmin=%11.5f Rmax=%11.5f\n", ipl, fZ[ipl], fRmin[ipl], fRmax[ipl]);
00796 printf(" Bounding box:\n");
00797 TGeoBBox::InspectShape();
00798 }
00799
00800
00801 TBuffer3D *TGeoPcon::MakeBuffer3D() const
00802 {
00803
00804
00805
00806 const Int_t n = gGeoManager->GetNsegments()+1;
00807 Int_t nz = GetNz();
00808 if (nz < 2) return 0;
00809 Int_t nbPnts = nz*2*n;
00810 if (nbPnts <= 0) return 0;
00811 Double_t dphi = GetDphi();
00812
00813 Bool_t specialCase = kFALSE;
00814 if (TGeoShape::IsSameWithinTolerance(dphi,360)) specialCase = kTRUE;
00815
00816 Int_t nbSegs = 4*(nz*n-1+(specialCase == kTRUE));
00817 Int_t nbPols = 2*(nz*n-1+(specialCase == kTRUE));
00818 TBuffer3D* buff = new TBuffer3D(TBuffer3DTypes::kGeneric,
00819 nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols);
00820 if (buff)
00821 {
00822 SetPoints(buff->fPnts);
00823 SetSegsAndPols(*buff);
00824 }
00825
00826 return buff;
00827 }
00828
00829
00830 void TGeoPcon::SetSegsAndPols(TBuffer3D &buff) const
00831 {
00832
00833 Int_t i, j;
00834 const Int_t n = gGeoManager->GetNsegments()+1;
00835 Int_t nz = GetNz();
00836 if (nz < 2) return;
00837 Int_t nbPnts = nz*2*n;
00838 if (nbPnts <= 0) return;
00839 Double_t dphi = GetDphi();
00840
00841 Bool_t specialCase = kFALSE;
00842 if (TGeoShape::IsSameWithinTolerance(dphi,360)) specialCase = kTRUE;
00843 Int_t c = GetBasicColor();
00844
00845 Int_t indx, indx2, k;
00846 indx = indx2 = 0;
00847
00848
00849
00850 for (i = 0; i < nz*2; i++) {
00851 indx2 = i*n;
00852 for (j = 1; j < n; j++) {
00853 buff.fSegs[indx++] = c;
00854 buff.fSegs[indx++] = indx2+j-1;
00855 buff.fSegs[indx++] = indx2+j;
00856 }
00857 if (specialCase) {
00858 buff.fSegs[indx++] = c;
00859 buff.fSegs[indx++] = indx2+j-1;
00860 buff.fSegs[indx++] = indx2;
00861 }
00862 }
00863
00864
00865 for (i = 0; i < 2; i++) {
00866 indx2 = i*(nz-1)*2*n;
00867 for (j = 0; j < n; j++) {
00868 buff.fSegs[indx++] = c;
00869 buff.fSegs[indx++] = indx2+j;
00870 buff.fSegs[indx++] = indx2+n+j;
00871 }
00872 }
00873
00874
00875 for (i = 0; i < (nz-1); i++) {
00876
00877 indx2 = i*n*2;
00878 for (j = 0; j < n; j++) {
00879 buff.fSegs[indx++] = c+2;
00880 buff.fSegs[indx++] = indx2+j;
00881 buff.fSegs[indx++] = indx2+n*2+j;
00882 }
00883
00884 indx2 = i*n*2+n;
00885 for (j = 0; j < n; j++) {
00886 buff.fSegs[indx++] = c+3;
00887 buff.fSegs[indx++] = indx2+j;
00888 buff.fSegs[indx++] = indx2+n*2+j;
00889 }
00890 }
00891
00892
00893
00894 if (!specialCase) {
00895 for (i = 1; i < (nz-1); i++) {
00896 for (j = 0; j < 2; j++) {
00897 buff.fSegs[indx++] = c;
00898 buff.fSegs[indx++] = 2*i * n + j*(n-1);
00899 buff.fSegs[indx++] = (2*i+1) * n + j*(n-1);
00900 }
00901 }
00902 }
00903
00904 Int_t m = n - 1 + (specialCase == kTRUE);
00905 indx = 0;
00906
00907
00908
00909 for (j = 0; j < n-1; j++) {
00910 buff.fPols[indx++] = c+3;
00911 buff.fPols[indx++] = 4;
00912 buff.fPols[indx++] = 2*nz*m+j;
00913 buff.fPols[indx++] = m+j;
00914 buff.fPols[indx++] = 2*nz*m+j+1;
00915 buff.fPols[indx++] = j;
00916 }
00917 for (j = 0; j < n-1; j++) {
00918 buff.fPols[indx++] = c+3;
00919 buff.fPols[indx++] = 4;
00920 buff.fPols[indx++] = 2*nz*m+n+j;
00921 buff.fPols[indx++] = (nz*2-2)*m+j;
00922 buff.fPols[indx++] = 2*nz*m+n+j+1;
00923 buff.fPols[indx++] = (nz*2-2)*m+m+j;
00924 }
00925 if (specialCase) {
00926 buff.fPols[indx++] = c+3;
00927 buff.fPols[indx++] = 4;
00928 buff.fPols[indx++] = 2*nz*m+j;
00929 buff.fPols[indx++] = m+j;
00930 buff.fPols[indx++] = 2*nz*m;
00931 buff.fPols[indx++] = j;
00932
00933 buff.fPols[indx++] = c+3;
00934 buff.fPols[indx++] = 4;
00935 buff.fPols[indx++] = 2*nz*m+n+j;
00936 buff.fPols[indx++] = (nz*2-2)*m+m+j;
00937 buff.fPols[indx++] = 2*nz*m+n;
00938 buff.fPols[indx++] = (nz*2-2)*m+j;
00939 }
00940
00941
00942 for (k = 0; k < (nz-1); k++) {
00943 for (j = 0; j < n-1; j++) {
00944 buff.fPols[indx++] = c;
00945 buff.fPols[indx++] = 4;
00946 buff.fPols[indx++] = 2*k*m+j;
00947 buff.fPols[indx++] = nz*2*m+(2*k+2)*n+j+1;
00948 buff.fPols[indx++] = (2*k+2)*m+j;
00949 buff.fPols[indx++] = nz*2*m+(2*k+2)*n+j;
00950 }
00951 for (j = 0; j < n-1; j++) {
00952 buff.fPols[indx++] = c+1;
00953 buff.fPols[indx++] = 4;
00954 buff.fPols[indx++] = (2*k+1)*m+j;
00955 buff.fPols[indx++] = nz*2*m+(2*k+3)*n+j;
00956 buff.fPols[indx++] = (2*k+3)*m+j;
00957 buff.fPols[indx++] = nz*2*m+(2*k+3)*n+j+1;
00958 }
00959 if (specialCase) {
00960 buff.fPols[indx++] = c;
00961 buff.fPols[indx++] = 4;
00962 buff.fPols[indx++] = 2*k*m+j;
00963 buff.fPols[indx++] = nz*2*m+(2*k+2)*n;
00964 buff.fPols[indx++] = (2*k+2)*m+j;
00965 buff.fPols[indx++] = nz*2*m+(2*k+2)*n+j;
00966
00967 buff.fPols[indx++] = c+1;
00968 buff.fPols[indx++] = 4;
00969 buff.fPols[indx++] = (2*k+1)*m+j;
00970 buff.fPols[indx++] = nz*2*m+(2*k+3)*n+j;
00971 buff.fPols[indx++] = (2*k+3)*m+j;
00972 buff.fPols[indx++] = nz*2*m+(2*k+3)*n;
00973 }
00974 }
00975
00976
00977
00978 if (!specialCase) {
00979 indx2 = nz*2*(n-1);
00980 for (k = 0; k < (nz-1); k++) {
00981 buff.fPols[indx++] = c+2;
00982 buff.fPols[indx++] = 4;
00983 buff.fPols[indx++] = k==0 ? indx2 : indx2+2*nz*n+2*(k-1);
00984 buff.fPols[indx++] = indx2+2*(k+1)*n;
00985 buff.fPols[indx++] = indx2+2*nz*n+2*k;
00986 buff.fPols[indx++] = indx2+(2*k+3)*n;
00987
00988 buff.fPols[indx++] = c+2;
00989 buff.fPols[indx++] = 4;
00990 buff.fPols[indx++] = k==0 ? indx2+n-1 : indx2+2*nz*n+2*(k-1)+1;
00991 buff.fPols[indx++] = indx2+(2*k+3)*n+n-1;
00992 buff.fPols[indx++] = indx2+2*nz*n+2*k+1;
00993 buff.fPols[indx++] = indx2+2*(k+1)*n+n-1;
00994 }
00995 buff.fPols[indx-8] = indx2+n;
00996 buff.fPols[indx-2] = indx2+2*n-1;
00997 }
00998 }
00999
01000
01001 Double_t TGeoPcon::SafetyToSegment(Double_t *point, Int_t ipl, Bool_t in, Double_t safmin) const
01002 {
01003
01004
01005 Double_t safe = TGeoShape::Big();
01006 if (ipl<0 || ipl>fNz-2) return (safmin+1.);
01007
01008 Double_t dz = 0.5*(fZ[ipl+1]-fZ[ipl]);
01009 if (dz<1E-9) return 1E9;
01010 Double_t ptnew[3];
01011 memcpy(ptnew, point, 3*sizeof(Double_t));
01012 ptnew[2] -= 0.5*(fZ[ipl]+fZ[ipl+1]);
01013 safe = TMath::Abs(ptnew[2])-dz;
01014 if (safe>safmin) return TGeoShape::Big();
01015 Double_t rmin1 = fRmin[ipl];
01016 Double_t rmax1 = fRmax[ipl];
01017 Double_t rmin2 = fRmin[ipl+1];
01018 Double_t rmax2 = fRmax[ipl+1];
01019 Bool_t is_tube = (TGeoShape::IsSameWithinTolerance(rmin1,rmin2) && TGeoShape::IsSameWithinTolerance(rmax1,rmax2))?kTRUE:kFALSE;
01020 Bool_t is_seg = (fDphi<360)?kTRUE:kFALSE;
01021 if (is_seg) {
01022 if (is_tube) safe = TGeoTubeSeg::SafetyS(ptnew,in,rmin1,rmax1, dz,fPhi1,fPhi1+fDphi,0);
01023 else safe = TGeoConeSeg::SafetyS(ptnew,in,dz,rmin1,rmax1,rmin2,rmax2,fPhi1,fPhi1+fDphi,0);
01024 } else {
01025 if (is_tube) safe = TGeoTube::SafetyS(ptnew,in,rmin1,rmax1,dz,0);
01026 else safe = TGeoCone::SafetyS(ptnew,in,dz,rmin1,rmax1,rmin2,rmax2,0);
01027 }
01028 if (safe<0) safe=0;
01029 return safe;
01030 }
01031
01032
01033 Double_t TGeoPcon::Safety(Double_t *point, Bool_t in) const
01034 {
01035
01036
01037
01038
01039 Double_t safmin, saftmp;
01040 Double_t dz;
01041 Int_t ipl, iplane;
01042
01043 if (in) {
01044
01045 ipl = TMath::BinarySearch(fNz, fZ, point[2]);
01046 if (ipl==(fNz-1)) return 0;
01047 if (ipl<0) return 0;
01048 if (ipl>0 && TGeoShape::IsSameWithinTolerance(fZ[ipl-1],fZ[ipl]) && TGeoShape::IsSameWithinTolerance(point[2],fZ[ipl-1])) ipl--;
01049 dz = 0.5*(fZ[ipl+1]-fZ[ipl]);
01050 if (dz<1E-8) {
01051
01052 safmin = TMath::Min(point[2]-fZ[ipl-1],fZ[ipl+2]-point[2]);
01053 saftmp = TGeoShape::Big();
01054 if (fDphi<360) saftmp = TGeoShape::SafetyPhi(point,in,fPhi1,fPhi1+fDphi);
01055 if (saftmp<safmin) safmin = saftmp;
01056 Double_t radius = TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
01057 if (fRmin[ipl]>0) safmin = TMath::Min(safmin, radius-fRmin[ipl]);
01058 if (fRmin[ipl+1]>0) safmin = TMath::Min(safmin, radius-fRmin[ipl+1]);
01059 safmin = TMath::Min(safmin, fRmax[ipl]-radius);
01060 safmin = TMath::Min(safmin, fRmax[ipl+1]-radius);
01061 if (safmin<0) safmin = 0;
01062 return safmin;
01063 }
01064
01065 safmin = SafetyToSegment(point, ipl);
01066 if (safmin>1E10) {
01067
01068 return TGeoShape::Big();
01069 }
01070 if (safmin<1E-6) return TMath::Abs(safmin);
01071
01072 iplane = ipl+1;
01073 saftmp = 0.;
01074 while ((iplane<fNz-1) && saftmp<1E10) {
01075 saftmp = TMath::Abs(SafetyToSegment(point,iplane,kFALSE,safmin));
01076 if (saftmp<safmin) safmin=saftmp;
01077 iplane++;
01078 }
01079
01080 iplane = ipl-1;
01081 saftmp = 0.;
01082 while ((iplane>=0) && saftmp<1E10) {
01083 saftmp = TMath::Abs(SafetyToSegment(point,iplane,kFALSE,safmin));
01084 if (saftmp<safmin) safmin=saftmp;
01085 iplane--;
01086 }
01087 return safmin;
01088 }
01089
01090 ipl = TMath::BinarySearch(fNz, fZ, point[2]);
01091 if (ipl<0) ipl=0;
01092 else if (ipl==fNz-1) ipl=fNz-2;
01093 dz = 0.5*(fZ[ipl+1]-fZ[ipl]);
01094 if (dz<1E-8 && (ipl+2<fNz)) {
01095 ipl++;
01096 dz = 0.5*(fZ[ipl+1]-fZ[ipl]);
01097 }
01098
01099 safmin = SafetyToSegment(point, ipl, kFALSE);
01100 if (safmin<1E-6) return TMath::Abs(safmin);
01101 saftmp = 0.;
01102
01103 iplane = ipl+1;
01104 saftmp = 0.;
01105 while ((iplane<fNz-1) && saftmp<1E10) {
01106 saftmp = TMath::Abs(SafetyToSegment(point,iplane,kFALSE,safmin));
01107 if (saftmp<safmin) safmin=saftmp;
01108 iplane++;
01109 }
01110
01111 iplane = ipl-1;
01112 saftmp = 0.;
01113 while ((iplane>=0) && saftmp<1E10) {
01114 saftmp = TMath::Abs(SafetyToSegment(point,iplane,kFALSE,safmin));
01115 if (saftmp<safmin) safmin=saftmp;
01116 iplane--;
01117 }
01118 return safmin;
01119 }
01120
01121
01122 void TGeoPcon::SavePrimitive(ostream &out, Option_t * )
01123 {
01124
01125 if (TObject::TestBit(kGeoSavePrimitive)) return;
01126 out << " // Shape: " << GetName() << " type: " << ClassName() << endl;
01127 out << " phi1 = " << fPhi1 << ";" << endl;
01128 out << " dphi = " << fDphi << ";" << endl;
01129 out << " nz = " << fNz << ";" << endl;
01130 out << " TGeoPcon *pcon = new TGeoPcon(\"" << GetName() << "\",phi1,dphi,nz);" << endl;
01131 for (Int_t i=0; i<fNz; i++) {
01132 out << " z = " << fZ[i] << ";" << endl;
01133 out << " rmin = " << fRmin[i] << ";" << endl;
01134 out << " rmax = " << fRmax[i] << ";" << endl;
01135 out << " pcon->DefineSection(" << i << ", z,rmin,rmax);" << endl;
01136 }
01137 out << " TGeoShape *" << GetPointerName() << " = pcon;" << endl;
01138 TObject::SetBit(TGeoShape::kGeoSavePrimitive);
01139 }
01140
01141
01142 void TGeoPcon::SetDimensions(Double_t *param)
01143 {
01144
01145 fPhi1 = param[0];
01146 fDphi = param[1];
01147 fNz = (Int_t)param[2];
01148 if (fNz<2) {
01149 Error("SetDimensions","Pcon %s: Number of Z sections must be > 2", GetName());
01150 return;
01151 }
01152 if (fRmin) delete [] fRmin;
01153 if (fRmax) delete [] fRmax;
01154 if (fZ) delete [] fZ;
01155 fRmin = new Double_t [fNz];
01156 fRmax = new Double_t [fNz];
01157 fZ = new Double_t [fNz];
01158 memset(fRmin, 0, fNz*sizeof(Double_t));
01159 memset(fRmax, 0, fNz*sizeof(Double_t));
01160 memset(fZ, 0, fNz*sizeof(Double_t));
01161 for (Int_t i=0; i<fNz; i++)
01162 DefineSection(i, param[3+3*i], param[4+3*i], param[5+3*i]);
01163 }
01164
01165
01166 void TGeoPcon::SetPoints(Double_t *points) const
01167 {
01168
01169 Double_t phi, dphi;
01170 Int_t n = gGeoManager->GetNsegments() + 1;
01171 dphi = fDphi/(n-1);
01172 Int_t i, j;
01173 Int_t indx = 0;
01174
01175 if (points) {
01176 for (i = 0; i < fNz; i++) {
01177 for (j = 0; j < n; j++) {
01178 phi = (fPhi1+j*dphi)*TMath::DegToRad();
01179 points[indx++] = fRmin[i] * TMath::Cos(phi);
01180 points[indx++] = fRmin[i] * TMath::Sin(phi);
01181 points[indx++] = fZ[i];
01182 }
01183 for (j = 0; j < n; j++) {
01184 phi = (fPhi1+j*dphi)*TMath::DegToRad();
01185 points[indx++] = fRmax[i] * TMath::Cos(phi);
01186 points[indx++] = fRmax[i] * TMath::Sin(phi);
01187 points[indx++] = fZ[i];
01188 }
01189 }
01190 }
01191 }
01192
01193
01194 void TGeoPcon::SetPoints(Float_t *points) const
01195 {
01196
01197 Double_t phi, dphi;
01198 Int_t n = gGeoManager->GetNsegments() + 1;
01199 dphi = fDphi/(n-1);
01200 Int_t i, j;
01201 Int_t indx = 0;
01202
01203 if (points) {
01204 for (i = 0; i < fNz; i++) {
01205 for (j = 0; j < n; j++) {
01206 phi = (fPhi1+j*dphi)*TMath::DegToRad();
01207 points[indx++] = fRmin[i] * TMath::Cos(phi);
01208 points[indx++] = fRmin[i] * TMath::Sin(phi);
01209 points[indx++] = fZ[i];
01210 }
01211 for (j = 0; j < n; j++) {
01212 phi = (fPhi1+j*dphi)*TMath::DegToRad();
01213 points[indx++] = fRmax[i] * TMath::Cos(phi);
01214 points[indx++] = fRmax[i] * TMath::Sin(phi);
01215 points[indx++] = fZ[i];
01216 }
01217 }
01218 }
01219 }
01220
01221 Int_t TGeoPcon::GetNmeshVertices() const
01222 {
01223
01224 Int_t n = gGeoManager->GetNsegments()+1;
01225 Int_t numPoints = fNz*2*n;
01226 return numPoints;
01227 }
01228
01229
01230 void TGeoPcon::Sizeof3D() const
01231 {
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243 }
01244
01245
01246 void TGeoPcon::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
01247 {
01248
01249 Int_t n = gGeoManager->GetNsegments()+1;
01250 Int_t nz = GetNz();
01251 nvert = nz*2*n;
01252 Bool_t specialCase = TGeoShape::IsSameWithinTolerance(GetDphi(),360);
01253 nsegs = 4*(nz*n-1+(specialCase == kTRUE));
01254 npols = 2*(nz*n-1+(specialCase == kTRUE));
01255 }
01256
01257
01258 const TBuffer3D & TGeoPcon::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
01259 {
01260
01261 static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
01262
01263 TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
01264
01265 if (reqSections & TBuffer3D::kRawSizes) {
01266 const Int_t n = gGeoManager->GetNsegments()+1;
01267 Int_t nz = GetNz();
01268 Int_t nbPnts = nz*2*n;
01269 if (nz >= 2 && nbPnts > 0) {
01270 Bool_t specialCase = TGeoShape::IsSameWithinTolerance(GetDphi(),360);
01271 Int_t nbSegs = 4*(nz*n-1+(specialCase == kTRUE));
01272 Int_t nbPols = 2*(nz*n-1+(specialCase == kTRUE));
01273 if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
01274 buffer.SetSectionsValid(TBuffer3D::kRawSizes);
01275 }
01276 }
01277 }
01278
01279
01280 if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
01281 SetPoints(buffer.fPnts);
01282 if (!buffer.fLocalFrame) {
01283 TransformPoints(buffer.fPnts, buffer.NbPnts());
01284 }
01285
01286 SetSegsAndPols(buffer);
01287 buffer.SetSectionsValid(TBuffer3D::kRaw);
01288 }
01289
01290 return buffer;
01291 }