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 #include "Riostream.h"
00035
00036 #include "TGeoPgon.h"
00037
00038 #include "TGeoManager.h"
00039 #include "TGeoVolume.h"
00040 #include "TVirtualGeoPainter.h"
00041 #include "TGeoTube.h"
00042 #include "TVirtualPad.h"
00043 #include "TBuffer3D.h"
00044 #include "TBuffer3DTypes.h"
00045 #include "TMath.h"
00046
00047 ClassImp(TGeoPgon)
00048
00049
00050 TGeoPgon::TGeoPgon()
00051 {
00052
00053 SetShapeBit(TGeoShape::kGeoPgon);
00054 fNedges = 0;
00055 }
00056
00057
00058 TGeoPgon::TGeoPgon(Double_t phi, Double_t dphi, Int_t nedges, Int_t nz)
00059 :TGeoPcon(phi, dphi, nz)
00060 {
00061
00062 SetShapeBit(TGeoShape::kGeoPgon);
00063 fNedges = nedges;
00064 }
00065
00066
00067 TGeoPgon::TGeoPgon(const char *name, Double_t phi, Double_t dphi, Int_t nedges, Int_t nz)
00068 :TGeoPcon(name, phi, dphi, nz)
00069 {
00070
00071 SetShapeBit(TGeoShape::kGeoPgon);
00072 fNedges = nedges;
00073 }
00074
00075
00076 TGeoPgon::TGeoPgon(Double_t *param)
00077 :TGeoPcon()
00078 {
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 SetShapeBit(TGeoShape::kGeoPgon);
00090 SetDimensions(param);
00091 ComputeBBox();
00092 }
00093
00094
00095 TGeoPgon::~TGeoPgon()
00096 {
00097
00098 }
00099
00100
00101 Double_t TGeoPgon::Capacity() const
00102 {
00103
00104 Int_t ipl;
00105 Double_t rmin1, rmax1, rmin2, rmax2, dphi, dz;
00106 Double_t capacity = 0.;
00107 dphi = fDphi/fNedges;
00108 Double_t tphi2 = TMath::Tan(0.5*dphi*TMath::DegToRad());
00109 for (ipl=0; ipl<fNz-1; ipl++) {
00110 dz = fZ[ipl+1]-fZ[ipl];
00111 if (dz < TGeoShape::Tolerance()) continue;
00112 rmin1 = fRmin[ipl];
00113 rmax1 = fRmax[ipl];
00114 rmin2 = fRmin[ipl+1];
00115 rmax2 = fRmax[ipl+1];
00116 capacity += fNedges*(tphi2/3.)*dz*(rmax1*rmax1+rmax1*rmax2+rmax2*rmax2 -
00117 rmin1*rmin1-rmin1*rmin2-rmin2*rmin2);
00118 }
00119 return capacity;
00120 }
00121
00122
00123 void TGeoPgon::ComputeBBox()
00124 {
00125
00126
00127 for (Int_t isec=0; isec<fNz-1; isec++) {
00128 if (fZ[isec]>fZ[isec+1]) {
00129 InspectShape();
00130 Fatal("ComputeBBox", "Wrong section order");
00131 }
00132 }
00133
00134 if (TMath::Abs(fZ[1]-fZ[0]) < TGeoShape::Tolerance() ||
00135 TMath::Abs(fZ[fNz-1]-fZ[fNz-2]) < TGeoShape::Tolerance()) {
00136 InspectShape();
00137 Fatal("ComputeBBox","Shape %s at index %d: Not allowed first two or last two sections at same Z",
00138 GetName(), gGeoManager->GetListOfShapes()->IndexOf(this));
00139 }
00140 Double_t zmin = TMath::Min(fZ[0], fZ[fNz-1]);
00141 Double_t zmax = TMath::Max(fZ[0], fZ[fNz-1]);
00142
00143 Double_t rmin, rmax;
00144 Double_t divphi = fDphi/fNedges;
00145
00146 rmin = fRmin[TMath::LocMin(fNz, fRmin)];
00147 rmax = fRmax[TMath::LocMax(fNz, fRmax)];
00148 rmax = rmax/TMath::Cos(0.5*divphi*TMath::DegToRad());
00149 Double_t phi1 = fPhi1;
00150 Double_t phi2 = phi1 + fDphi;
00151
00152 Double_t xc[4];
00153 Double_t yc[4];
00154 xc[0] = rmax*TMath::Cos(phi1*TMath::DegToRad());
00155 yc[0] = rmax*TMath::Sin(phi1*TMath::DegToRad());
00156 xc[1] = rmax*TMath::Cos(phi2*TMath::DegToRad());
00157 yc[1] = rmax*TMath::Sin(phi2*TMath::DegToRad());
00158 xc[2] = rmin*TMath::Cos(phi1*TMath::DegToRad());
00159 yc[2] = rmin*TMath::Sin(phi1*TMath::DegToRad());
00160 xc[3] = rmin*TMath::Cos(phi2*TMath::DegToRad());
00161 yc[3] = rmin*TMath::Sin(phi2*TMath::DegToRad());
00162
00163 Double_t xmin = xc[TMath::LocMin(4, &xc[0])];
00164 Double_t xmax = xc[TMath::LocMax(4, &xc[0])];
00165 Double_t ymin = yc[TMath::LocMin(4, &yc[0])];
00166 Double_t ymax = yc[TMath::LocMax(4, &yc[0])];
00167
00168 Double_t ddp = -phi1;
00169 if (ddp<0) ddp+= 360;
00170 if (ddp<=fDphi) xmax = rmax;
00171 ddp = 90-phi1;
00172 if (ddp<0) ddp+= 360;
00173 if (ddp<=fDphi) ymax = rmax;
00174 ddp = 180-phi1;
00175 if (ddp<0) ddp+= 360;
00176 if (ddp<=fDphi) xmin = -rmax;
00177 ddp = 270-phi1;
00178 if (ddp<0) ddp+= 360;
00179 if (ddp<=fDphi) ymin = -rmax;
00180 fOrigin[0] = 0.5*(xmax+xmin);
00181 fOrigin[1] = 0.5*(ymax+ymin);
00182 fOrigin[2] = 0.5*(zmax+zmin);
00183 fDX = 0.5*(xmax-xmin);
00184 fDY = 0.5*(ymax-ymin);
00185 fDZ = 0.5*(zmax-zmin);
00186 SetShapeBit(kGeoClosedShape);
00187 }
00188
00189
00190 void TGeoPgon::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
00191 {
00192
00193 memset(norm,0,3*sizeof(Double_t));
00194 Double_t phi1=0, phi2=0, c1=0, s1=0, c2=0, s2=0;
00195 Double_t dz, rmin1, rmin2;
00196 Bool_t is_seg = (fDphi<360)?kTRUE:kFALSE;
00197 if (is_seg) {
00198 phi1 = fPhi1;
00199 if (phi1<0) phi1+=360;
00200 phi2 = phi1 + fDphi;
00201 phi1 *= TMath::DegToRad();
00202 phi2 *= TMath::DegToRad();
00203 c1 = TMath::Cos(phi1);
00204 s1 = TMath::Sin(phi1);
00205 c2 = TMath::Cos(phi2);
00206 s2 = TMath::Sin(phi2);
00207 if (TGeoShape::IsCloseToPhi(1E-5, point, c1,s1,c2,s2)) {
00208 TGeoShape::NormalPhi(point,dir,norm,c1,s1,c2,s2);
00209 return;
00210 }
00211 }
00212
00213 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
00214 if (ipl==(fNz-1) || ipl<0) {
00215
00216 norm[2] = TMath::Sign(1., dir[2]);
00217 return;
00218 }
00219 Int_t iplclose = ipl;
00220 if ((fZ[ipl+1]-point[2])<(point[2]-fZ[ipl])) iplclose++;
00221 dz = TMath::Abs(fZ[iplclose]-point[2]);
00222
00223 Double_t divphi = fDphi/fNedges;
00224 Double_t phi = TMath::ATan2(point[1], point[0])*TMath::RadToDeg();
00225 while (phi<fPhi1) phi+=360.;
00226 Double_t ddp = phi-fPhi1;
00227 Int_t ipsec = Int_t(ddp/divphi);
00228 Double_t ph0 = (fPhi1+divphi*(ipsec+0.5))*TMath::DegToRad();
00229
00230 Double_t r, rsum, rpgon, ta, calf;
00231 r = TMath::Abs(point[0]*TMath::Cos(ph0)+point[1]*TMath::Sin(ph0));
00232 if (dz<1E-5) {
00233 if (iplclose==0 || iplclose==(fNz-1)) {
00234 norm[2] = TMath::Sign(1., dir[2]);
00235 return;
00236 }
00237 if (iplclose==ipl && TGeoShape::IsSameWithinTolerance(fZ[ipl],fZ[ipl-1])) {
00238 if (r<TMath::Max(fRmin[ipl],fRmin[ipl-1]) || r>TMath::Min(fRmax[ipl],fRmax[ipl-1])) {
00239 norm[2] = TMath::Sign(1., dir[2]);
00240 return;
00241 }
00242 } else {
00243 if (TGeoShape::IsSameWithinTolerance(fZ[iplclose],fZ[iplclose+1])) {
00244 if (r<TMath::Max(fRmin[iplclose],fRmin[iplclose+1]) || r>TMath::Min(fRmax[iplclose],fRmax[iplclose+1])) {
00245 norm[2] = TMath::Sign(1., dir[2]);
00246 return;
00247 }
00248 }
00249 }
00250 }
00251
00252 dz = fZ[ipl+1]-fZ[ipl];
00253 rmin1 = fRmin[ipl];
00254 rmin2 = fRmin[ipl+1];
00255 rsum = rmin1+rmin2;
00256 Double_t safe = TGeoShape::Big();
00257 if (rsum>1E-10) {
00258 ta = (rmin2-rmin1)/dz;
00259 calf = 1./TMath::Sqrt(1+ta*ta);
00260 rpgon = rmin1 + (point[2]-fZ[ipl])*ta;
00261 safe = TMath::Abs(r-rpgon);
00262 norm[0] = calf*TMath::Cos(ph0);
00263 norm[1] = calf*TMath::Sin(ph0);
00264 norm[2] = -calf*ta;
00265 }
00266 ta = (fRmax[ipl+1]-fRmax[ipl])/dz;
00267 calf = 1./TMath::Sqrt(1+ta*ta);
00268 rpgon = fRmax[ipl] + (point[2]-fZ[ipl])*ta;
00269 if (safe>TMath::Abs(rpgon-r)) {
00270 norm[0] = calf*TMath::Cos(ph0);
00271 norm[1] = calf*TMath::Sin(ph0);
00272 norm[2] = -calf*ta;
00273 }
00274 if (norm[0]*dir[0]+norm[1]*dir[1]+norm[2]*dir[2]<0) {
00275 norm[0] = -norm[0];
00276 norm[1] = -norm[1];
00277 norm[2] = -norm[2];
00278 }
00279 }
00280
00281
00282 Bool_t TGeoPgon::Contains(Double_t *point) const
00283 {
00284
00285
00286 if (point[2]<fZ[0]) return kFALSE;
00287 if (point[2]>fZ[fNz-1]) return kFALSE;
00288 Double_t divphi = fDphi/fNedges;
00289
00290 Double_t phi = TMath::ATan2(point[1], point[0])*TMath::RadToDeg();
00291 while (phi < fPhi1) phi += 360.0;
00292 Double_t ddp = phi-fPhi1;
00293 if (ddp>fDphi) return kFALSE;
00294
00295 Int_t ipsec = TMath::Min(Int_t(ddp/divphi), fNedges-1);
00296 Double_t ph0 = (fPhi1+divphi*(ipsec+0.5))*TMath::DegToRad();
00297
00298 Double_t r = point[0]*TMath::Cos(ph0) + point[1]*TMath::Sin(ph0);
00299
00300 Int_t iz = TMath::BinarySearch(fNz, fZ, point[2]);
00301 if (iz==fNz-1) {
00302 if (r<fRmin[iz]) return kFALSE;
00303 if (r>fRmax[iz]) return kFALSE;
00304 return kTRUE;
00305 }
00306 Double_t dz = fZ[iz+1]-fZ[iz];
00307 Double_t rmin, rmax;
00308 if (dz<1E-8) {
00309
00310 rmin = TMath::Min(fRmin[iz], fRmin[iz+1]);
00311 rmax = TMath::Max(fRmax[iz], fRmax[iz+1]);
00312 if (r<rmin) return kFALSE;
00313 if (r>rmax) return kFALSE;
00314 return kTRUE;
00315 }
00316
00317 Double_t dzrat = (point[2]-fZ[iz])/dz;
00318 rmin = fRmin[iz]+dzrat*(fRmin[iz+1]-fRmin[iz]);
00319
00320 if (r < rmin) return kFALSE;
00321 rmax = fRmax[iz]+dzrat*(fRmax[iz+1]-fRmax[iz]);
00322 if (r > rmax) return kFALSE;
00323
00324 return kTRUE;
00325 }
00326
00327
00328 Double_t TGeoPgon::DistFromInside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00329 {
00330
00331
00332 if (iact<3 && safe) {
00333 *safe = Safety(point, kTRUE);
00334 if (iact==0) return TGeoShape::Big();
00335 if (iact==1 && step<*safe) return TGeoShape::Big();
00336 }
00337
00338 Int_t ipl, ipsec;
00339 ipl = TMath::BinarySearch(fNz, fZ, point[2]);
00340 if (ipl==fNz-1) {
00341 if (dir[2]>=0) return 0.;
00342 ipl--;
00343 }
00344 if (ipl<0) {
00345
00346 if (dir[2]<=0) return 0.;
00347 ipl++;
00348 }
00349 Double_t stepmax = step;
00350 Double_t *sph = gGeoManager->GetDblBuffer(fNedges+2);
00351 Int_t *iph = gGeoManager->GetIntBuffer(fNedges+2);
00352
00353 LocatePhi(point, ipsec);
00354 if (ipsec<0) {
00355
00356 Double_t phi1 = fPhi1*TMath::DegToRad();
00357 Double_t phi2 = (fPhi1+fDphi)*TMath::DegToRad();
00358 if ((point[0]*dir[1]-point[1]*dir[0])>0) {
00359
00360 if ((point[0]*TMath::Cos(phi1)+point[1]*TMath::Sin(phi1)) <
00361 (point[0]*TMath::Cos(phi2)+point[1]*TMath::Sin(phi2))) {
00362
00363 return 0.0;
00364 } else {
00365
00366 ipsec = 0;
00367 }
00368 } else {
00369
00370 if ((point[0]*TMath::Cos(phi1)+point[1]*TMath::Sin(phi1)) >
00371 (point[0]*TMath::Cos(phi2)+point[1]*TMath::Sin(phi2))) {
00372
00373 return 0.0;
00374 } else {
00375
00376 ipsec = fNedges-1;
00377 }
00378 }
00379 }
00380 Int_t ipln = -1;
00381 if (TGeoShape::IsSameWithinTolerance(fZ[ipl],fZ[ipl+1])) {
00382 ipln = ipl;
00383 } else {
00384 if (fNz>3 && ipl>0 && ipl<fNz-3 && TGeoShape::IsSameWithinTolerance(fZ[ipl+1],fZ[ipl+2]) && TGeoShape::IsSameWithinTolerance(point[2],fZ[ipl+1])) {
00385 ipln = ipl+1;
00386 } else {
00387 if (ipl>1 && TGeoShape::IsSameWithinTolerance(fZ[ipl],fZ[ipl-1]) && TGeoShape::IsSameWithinTolerance(point[2],fZ[ipl])) ipln = ipl-1;
00388 }
00389 }
00390 if (ipln>0) {
00391
00392 Double_t divphi = fDphi/fNedges;
00393 Double_t phi = (fPhi1 + (ipsec+0.5)*divphi)*TMath::DegToRad();
00394 Double_t cphi = TMath::Cos(phi);
00395 Double_t sphi = TMath::Sin(phi);
00396 Double_t rproj = point[0]*cphi+point[1]*sphi;
00397 if (dir[2]>0) {
00398 ipl = ipln+1;
00399 if (rproj>fRmin[ipln] && rproj<fRmin[ipln+1]) return 0.0;
00400 if (rproj<fRmax[ipln] && rproj>fRmax[ipln+1]) return 0.0;
00401 } else {
00402 ipl = ipln-1;
00403 if (rproj<fRmin[ipln] && rproj>fRmin[ipln+1]) return 0.0;
00404 if (rproj>fRmax[ipln] && rproj<fRmax[ipln+1]) return 0.0;
00405 }
00406 }
00407
00408 Int_t icrossed;
00409 icrossed = GetPhiCrossList(point,dir,ipsec,sph,iph, stepmax);
00410 Double_t snext;
00411 if (TMath::Abs(dir[2])<TGeoShape::Tolerance()) {
00412 if (SliceCrossingInZ(point, dir, icrossed, iph, sph, snext, stepmax)) return snext;
00413 if (snext>TGeoShape::Tolerance()) return TGeoShape::Big();
00414 return 0.;
00415 }
00416 if (SliceCrossingIn(point, dir, ipl, icrossed, iph, sph, snext, stepmax)) return snext;
00417 if (snext>TGeoShape::Tolerance()) return TGeoShape::Big();
00418 return 0.;
00419 }
00420
00421
00422 void TGeoPgon::LocatePhi(Double_t *point, Int_t &ipsec) const
00423 {
00424
00425 Double_t phi = TMath::ATan2(point[1], point[0])*TMath::RadToDeg();
00426 while (phi<fPhi1) phi+=360.;
00427 ipsec = Int_t(fNedges*(phi-fPhi1)/fDphi);
00428 if (ipsec>fNedges-1) ipsec = -1;
00429 }
00430
00431
00432 Int_t TGeoPgon::GetPhiCrossList(Double_t *point, Double_t *dir, Int_t istart, Double_t *sphi, Int_t *iphi, Double_t stepmax) const
00433 {
00434
00435 Double_t rxy, phi, cph, sph;
00436 Int_t icrossed = 0;
00437 if ((1.-TMath::Abs(dir[2]))<1E-8) {
00438
00439 iphi[0] = istart;
00440 sphi[0] = stepmax;
00441 return 1;
00442 }
00443 Bool_t shootorig = (TMath::Abs(point[0]*dir[1]-point[1]*dir[0])<1E-8)?kTRUE:kFALSE;
00444 Double_t divphi = fDphi/fNedges;
00445 if (shootorig) {
00446 Double_t rdotn = point[0]*dir[0]+point[1]*dir[1];
00447 if (rdotn>0) {
00448 sphi[icrossed] = stepmax;
00449 iphi[icrossed++] = istart;
00450 return icrossed;
00451 }
00452 sphi[icrossed] = TMath::Sqrt((point[0]*point[0]+point[1]*point[1])/(1.-dir[2]*dir[2]));
00453 iphi[icrossed++] = istart;
00454 if (sphi[icrossed-1]>stepmax) {
00455 sphi[icrossed-1] = stepmax;
00456 return icrossed;
00457 }
00458 phi = TMath::ATan2(dir[1], dir[0])*TMath::RadToDeg();
00459 while (phi<fPhi1) phi+=360.;
00460 istart = Int_t((phi-fPhi1)/divphi);
00461 if (istart>fNedges-1) istart=-1;
00462 iphi[icrossed] = istart;
00463 sphi[icrossed] = stepmax;
00464 icrossed++;
00465 return icrossed;
00466 }
00467 Int_t incsec = Int_t(TMath::Sign(1., point[0]*dir[1]-point[1]*dir[0]));
00468 Int_t ist;
00469 if (istart<0) ist=(incsec>0)?0:fNedges;
00470 else ist=(incsec>0)?(istart+1):istart;
00471 Bool_t crossing = kTRUE;
00472 Bool_t gapdone = kFALSE;
00473 divphi *= TMath::DegToRad();
00474 Double_t phi1 = fPhi1*TMath::DegToRad();
00475 while (crossing) {
00476 if (istart<0) gapdone = kTRUE;
00477 phi = phi1+ist*divphi;
00478 cph = TMath::Cos(phi);
00479 sph = TMath::Sin(phi);
00480 crossing = IsCrossingSemiplane(point,dir,cph,sph,sphi[icrossed],rxy);
00481 if (!crossing) sphi[icrossed] = stepmax;
00482 iphi[icrossed++] = istart;
00483 if (crossing) {
00484 if (sphi[icrossed-1]>stepmax) {
00485 sphi[icrossed-1] = stepmax;
00486 return icrossed;
00487 }
00488 if (istart<0) {
00489 istart = (incsec>0)?0:(fNedges-1);
00490 } else {
00491 istart += incsec;
00492 if (istart>fNedges-1) istart=(fDphi<360.)?(-1):0;
00493 else if (istart<0 && TGeoShape::IsSameWithinTolerance(fDphi,360)) istart=fNedges-1;
00494 }
00495 if (istart<0) {
00496 if (gapdone) return icrossed;
00497 ist=(incsec>0)?0:fNedges;
00498 } else {
00499 ist=(incsec>0)?(istart+1):istart;
00500 }
00501 }
00502 }
00503 return icrossed;
00504 }
00505
00506
00507 Bool_t TGeoPgon::SliceCrossingInZ(Double_t *point, Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *stepphi, Double_t &snext, Double_t stepmax) const
00508 {
00509
00510 snext = 0.;
00511 if (!nphi) return kFALSE;
00512 Int_t i;
00513 Double_t rmin, rmax;
00514 Double_t apg,bpg;
00515 Double_t pt[3];
00516 if (iphi[0]<0 && nphi==1) return kFALSE;
00517
00518 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
00519 if (ipl<0 || ipl==fNz-1) return kFALSE;
00520 if (TMath::Abs(point[2]-fZ[ipl])<TGeoShape::Tolerance()) {
00521 if (ipl<fNz-2 && TGeoShape::IsSameWithinTolerance(fZ[ipl],fZ[ipl+1])) {
00522 rmin = TMath::Min(fRmin[ipl], fRmin[ipl+1]);
00523 rmax = TMath::Max(fRmax[ipl], fRmax[ipl+1]);
00524 } else if (ipl>1 && TGeoShape::IsSameWithinTolerance(fZ[ipl],fZ[ipl-1])) {
00525 rmin = TMath::Min(fRmin[ipl], fRmin[ipl+1]);
00526 rmax = TMath::Max(fRmax[ipl], fRmax[ipl+1]);
00527 } else {
00528 rmin = fRmin[ipl];
00529 rmax = fRmax[ipl];
00530 }
00531 } else {
00532 rmin = Rpg(point[2], ipl, kTRUE, apg,bpg);
00533 rmax = Rpg(point[2], ipl, kFALSE, apg,bpg);
00534 }
00535 Int_t iphcrt;
00536 Double_t divphi = TMath::DegToRad()*fDphi/fNedges;
00537 Double_t rproj, ndot, dist;
00538 Double_t phi1 = fPhi1*TMath::DegToRad();
00539 Double_t cosph, sinph;
00540 Double_t snextphi = 0.;
00541 Double_t step = 0;
00542 Double_t phi;
00543 memcpy(pt,point,3*sizeof(Double_t));
00544 for (iphcrt=0; iphcrt<nphi; iphcrt++) {
00545 if (step>stepmax) {
00546 snext = step;
00547 return kFALSE;
00548 }
00549 if (iphi[iphcrt]<0) {
00550 snext = step;
00551 return kTRUE;
00552 }
00553
00554 snextphi = stepphi[iphcrt];
00555 phi = phi1+(iphi[iphcrt]+0.5)*divphi;
00556 cosph = TMath::Cos(phi);
00557 sinph = TMath::Sin(phi);
00558 rproj = pt[0]*cosph+pt[1]*sinph;
00559 dist = TGeoShape::Big();
00560 ndot = dir[0]*cosph+dir[1]*sinph;
00561 if (!TGeoShape::IsSameWithinTolerance(ndot,0)) {
00562 dist = (ndot>0)?((rmax-rproj)/ndot):((rmin-rproj)/ndot);
00563 if (dist<0) dist=0.;
00564 }
00565 if (dist < (snextphi-step)) {
00566 snext = step + dist;
00567 if (snext<stepmax) return kTRUE;
00568 return kFALSE;
00569 }
00570 step = snextphi;
00571 for (i=0; i<3; i++) pt[i] = point[i]+step*dir[i];
00572 }
00573 snext = step;
00574 return kFALSE;
00575 }
00576
00577
00578 Bool_t TGeoPgon::SliceCrossingZ(Double_t *point, Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *stepphi, Double_t &snext, Double_t stepmax) const
00579 {
00580
00581 if (!nphi) return kFALSE;
00582 Int_t i;
00583 Double_t rmin, rmax;
00584 Double_t apg,bpg;
00585 Double_t pt[3];
00586 if (iphi[0]<0 && nphi==1) return kFALSE;
00587
00588 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
00589 if (ipl<0 || ipl==fNz-1) return kFALSE;
00590 if (TMath::Abs(point[2]-fZ[ipl])<TGeoShape::Tolerance()) {
00591 if (ipl<fNz-2 && TGeoShape::IsSameWithinTolerance(fZ[ipl],fZ[ipl+1])) {
00592 rmin = TMath::Min(fRmin[ipl], fRmin[ipl+1]);
00593 rmax = TMath::Max(fRmax[ipl], fRmax[ipl+1]);
00594 } else if (ipl>1 && TGeoShape::IsSameWithinTolerance(fZ[ipl],fZ[ipl-1])) {
00595 rmin = TMath::Min(fRmin[ipl], fRmin[ipl+1]);
00596 rmax = TMath::Max(fRmax[ipl], fRmax[ipl+1]);
00597 } else {
00598 rmin = fRmin[ipl];
00599 rmax = fRmax[ipl];
00600 }
00601 } else {
00602 rmin = Rpg(point[2], ipl, kTRUE, apg,bpg);
00603 rmax = Rpg(point[2], ipl, kFALSE, apg,bpg);
00604 }
00605 Int_t iphcrt;
00606 Double_t divphi = TMath::DegToRad()*fDphi/fNedges;
00607 Double_t rproj, ndot, dist;
00608 Double_t phi1 = fPhi1*TMath::DegToRad();
00609 Double_t cosph, sinph;
00610 Double_t snextphi = 0.;
00611 Double_t step = 0;
00612 Double_t phi;
00613 memcpy(pt,point,3*sizeof(Double_t));
00614 for (iphcrt=0; iphcrt<nphi; iphcrt++) {
00615 if (step>stepmax) return kFALSE;
00616 snextphi = stepphi[iphcrt];
00617 if (iphi[iphcrt]<0) {
00618 if (iphcrt==nphi-1) return kFALSE;
00619 if (snextphi>stepmax) return kFALSE;
00620 for (i=0; i<3; i++) pt[i] = point[i]+snextphi*dir[i];
00621 phi = phi1+(iphi[iphcrt+1]+0.5)*divphi;
00622 cosph = TMath::Cos(phi);
00623 sinph = TMath::Sin(phi);
00624 rproj = pt[0]*cosph+pt[1]*sinph;
00625 if (rproj<rmin || rproj>rmax) {
00626 step = snextphi;
00627 continue;
00628 }
00629 snext = snextphi;
00630 return kTRUE;
00631 }
00632
00633 phi = phi1+(iphi[iphcrt]+0.5)*divphi;
00634 cosph = TMath::Cos(phi);
00635 sinph = TMath::Sin(phi);
00636 rproj = pt[0]*cosph+pt[1]*sinph;
00637 dist = TGeoShape::Big();
00638 ndot = dir[0]*cosph+dir[1]*sinph;
00639 if (rproj<rmin) {
00640 dist = (ndot>0)?((rmin-rproj)/ndot):TGeoShape::Big();
00641 } else {
00642 dist = (ndot<0)?((rmax-rproj)/ndot):TGeoShape::Big();
00643 }
00644 if (dist<1E10) {
00645 snext = step+dist;
00646 if (snext<stepmax) return kTRUE;
00647 }
00648 step = snextphi;
00649 for (i=0; i<3; i++) pt[i] = point[i]+step*dir[i];
00650 }
00651 return kFALSE;
00652 }
00653
00654
00655 Bool_t TGeoPgon::SliceCrossingIn(Double_t *point, Double_t *dir, Int_t ipl, Int_t nphi, Int_t *iphi, Double_t *stepphi, Double_t &snext, Double_t stepmax) const
00656 {
00657
00658
00659
00660 snext = 0.;
00661 if (!nphi) return kFALSE;
00662 Int_t i;
00663 Int_t iphstart = 0;
00664 Double_t pt[3];
00665 if (iphi[0]<0) {
00666 if (stepphi[0]>TGeoShape::Tolerance()) return kFALSE;
00667 iphstart = 1;
00668 }
00669 if (nphi>1 && iphi[1]<0 && stepphi[0]<TGeoShape::Tolerance()) {
00670 snext = stepphi[0];
00671 return kTRUE;
00672 }
00673
00674 Double_t snextphi = 0.;
00675 Double_t step = 0;
00676 Int_t incseg = (dir[2]>0)?1:-1;
00677
00678 Int_t iplstart = ipl;
00679 Int_t iphcrt = 0;
00680 Double_t apr=TGeoShape::Big(), bpr=0, db=0;
00681 Double_t rpg=0, rnew=0, znew=0;
00682 Double_t rpgin=0,rpgout=0,apgin=0,apgout=0,bpgin=0,bpgout=0;
00683 Double_t divphi = TMath::DegToRad()*fDphi/fNedges;
00684 Double_t phi1 = fPhi1*TMath::DegToRad();
00685 Double_t phi=0, dz=0;
00686 Double_t cosph=0, sinph=0;
00687 Double_t distz=0, distr=0, din=0, dout=0;
00688 Double_t invdir = 1./dir[2];
00689 memcpy(pt,point,3*sizeof(Double_t));
00690 for (iphcrt=iphstart; iphcrt<nphi; iphcrt++) {
00691
00692 if (step>stepmax) {
00693 snext = step;
00694 return kFALSE;
00695 }
00696 if (iphi[iphcrt]<0) {
00697 snext = snextphi;
00698 return kTRUE;
00699 }
00700 snextphi = stepphi[iphcrt];
00701 phi = phi1+(iphi[iphcrt]+0.5)*divphi;
00702 cosph = TMath::Cos(phi);
00703 sinph = TMath::Sin(phi);
00704 Double_t rproj = Rproj(pt[2], pt, dir, cosph, sinph, apr, bpr);
00705
00706 while (ipl>=0 && ipl<fNz-1) {
00707 din = dout = TGeoShape::Big();
00708
00709 distz = (fZ[ipl+((1+incseg)>>1)]-pt[2])*invdir;
00710
00711 dz = fZ[ipl+1] - fZ[ipl];
00712 if (dz < TGeoShape::Tolerance()) {
00713 rnew = apr+bpr*fZ[ipl];
00714 rpg = (rnew-fRmin[ipl])*(rnew-fRmin[ipl+1]);
00715 if (rpg<=0) din=distz;
00716 rpg = (rnew-fRmax[ipl])*(rnew-fRmax[ipl+1]);
00717 if (rpg<=0) dout=distz;
00718 distr = TMath::Min(din, dout);
00719 } else {
00720 rpgin = Rpg(pt[2], ipl, kTRUE, apgin, bpgin);
00721 db = bpgin-bpr;
00722 if (TMath::Abs(db) > TGeoShape::Tolerance()) {
00723 znew = (apr-apgin)/db;
00724 din = (znew-pt[2])*invdir;
00725 }
00726 rpgout = Rpg(pt[2], ipl, kFALSE, apgout, bpgout);
00727 db = bpgout-bpr;
00728 if (TMath::Abs(db) > TGeoShape::Tolerance()) {
00729 znew = (apr-apgout)/db;
00730 dout = (znew-pt[2])*invdir;
00731 }
00732
00733 Double_t dinp = (din>TMath::Abs(snext-TGeoShape::Tolerance()))?din:TGeoShape::Big();
00734 Double_t doutp = (dout>TMath::Abs(snext-TGeoShape::Tolerance()))?dout:TGeoShape::Big();
00735 distr = TMath::Min(dinp, doutp);
00736 if (iphcrt==iphstart && ipl==iplstart) {
00737 if (rproj<rpgin+TGeoShape::Tolerance()) {
00738 Double_t ndotd = dir[0]*cosph+dir[1]*sinph+dir[2]*(fRmin[ipl]-fRmin[ipl+1])/dz;
00739 if (ndotd<0) {
00740 snext = (din<0)?step:(step+din);
00741 return kTRUE;
00742 }
00743 distr = TMath::Max(din,dout);
00744 if (distr<TGeoShape::Tolerance()) distr=TGeoShape::Big();
00745 } else if (rproj>rpgout-TGeoShape::Tolerance()) {
00746 Double_t ndotd = dir[0]*cosph+dir[1]*sinph+dir[2]*(fRmax[ipl]-fRmax[ipl+1])/dz;
00747 if (ndotd>0) {
00748 snext = (dout<0)?step:(step+dout);
00749 return kTRUE;
00750 }
00751 distr = TMath::Max(din,dout);
00752 if (distr<TGeoShape::Tolerance()) distr=TGeoShape::Big();
00753 }
00754 }
00755 }
00756 if (distr<snext-TGeoShape::Tolerance()) distr=TGeoShape::Big();
00757 if (snextphi < step+TMath::Min(distz,distr)) {
00758 for (i=0; i<3; i++) pt[i] = point[i] + snextphi*dir[i];
00759 step = snextphi;
00760 snext = 0.0;
00761 break;
00762 }
00763 if (distr<=distz+TGeoShape::Tolerance()) {
00764 step += distr;
00765 snext = step;
00766 return (step>stepmax)?kFALSE:kTRUE;
00767 }
00768
00769 snext = distz;
00770 if ((ipl+incseg<0) || (ipl+incseg>fNz-2)) {
00771
00772 step += distz;
00773 snext = step;
00774 return (step>stepmax)?kFALSE:kTRUE;
00775 }
00776 ipl += incseg;
00777 }
00778 }
00779 snext = TGeoShape::Big();
00780 return kFALSE;
00781 }
00782
00783
00784 Bool_t TGeoPgon::SliceCrossing(Double_t *point, Double_t *dir, Int_t nphi, Int_t *iphi, Double_t *stepphi, Double_t &snext, Double_t stepmax) const
00785 {
00786
00787
00788 if (!nphi) return kFALSE;
00789 Int_t i;
00790 Double_t pt[3];
00791 if (iphi[0]<0 && nphi==1) return kFALSE;
00792
00793 Double_t snextphi = 0.;
00794 Double_t step = 0;
00795
00796 Int_t incseg = (dir[2]>0)?1:-1;
00797 Int_t ipl = TMath::BinarySearch(fNz, fZ, point[2]);
00798 if (ipl<0) {
00799 ipl = 0;
00800 if (incseg<0) return kFALSE;
00801 } else {
00802 if (ipl==fNz-1) {
00803 ipl = fNz-2;
00804 if (incseg>0) return kFALSE;
00805 } else {
00806 if (TMath::Abs(point[2]-fZ[ipl])<TGeoShape::Tolerance()) {
00807
00808 if ((ipl+incseg)<0 || (ipl+incseg)>fNz-1) return kFALSE;
00809 if (TGeoShape::IsSameWithinTolerance(fZ[ipl],fZ[ipl+incseg])) ipl += incseg;
00810
00811 if (incseg<0) {
00812 if (TGeoShape::IsSameWithinTolerance(fZ[ipl],fZ[ipl+1])) ipl--;
00813 }
00814 }
00815 }
00816 }
00817
00818 Int_t iphcrt;
00819 Double_t apg,bpg;
00820 Double_t rpgin;
00821 Double_t rpgout;
00822 Double_t divphi = TMath::DegToRad()*fDphi/fNedges;
00823 Double_t phi1 = fPhi1*TMath::DegToRad();
00824 Double_t phi;
00825 Double_t cosph, sinph;
00826 Double_t rproj;
00827 memcpy(pt,point,3*sizeof(Double_t));
00828 for (iphcrt=0; iphcrt<nphi; iphcrt++) {
00829
00830 if (step>stepmax) return kFALSE;
00831
00832 snextphi = stepphi[iphcrt];
00833 if (iphi[iphcrt]<0) {
00834 if (iphcrt==nphi-1) return kFALSE;
00835 if (snextphi>stepmax) return kFALSE;
00836 for (i=0; i<3; i++) pt[i] = point[i]+snextphi*dir[i];
00837
00838 if (incseg>0) {
00839
00840 while (pt[2]>fZ[ipl+1]) {
00841 ipl++;
00842 if (ipl>fNz-2) return kFALSE;
00843 }
00844 } else {
00845 while (pt[2]<fZ[ipl]) {
00846 ipl--;
00847 if (ipl<0) return kFALSE;
00848 }
00849 }
00850
00851 rpgin = Rpg(pt[2],ipl,kTRUE,apg,bpg);
00852 rpgout = Rpg(pt[2],ipl,kFALSE,apg,bpg);
00853 phi = phi1+(iphi[iphcrt+1]+0.5)*divphi;
00854 cosph = TMath::Cos(phi);
00855 sinph = TMath::Sin(phi);
00856
00857 rproj = pt[0]*cosph+pt[1]*sinph;
00858 if (rproj<rpgin || rproj>rpgout) {
00859 step = snextphi;
00860 continue;
00861 }
00862 snext = snextphi;
00863 return kTRUE;
00864 }
00865 if (IsCrossingSlice(point, dir, iphi[iphcrt], step, ipl, snext, TMath::Min(snextphi, stepmax)))
00866 return kTRUE;
00867 step = snextphi;
00868 }
00869 return kFALSE;
00870 }
00871
00872 Bool_t TGeoPgon::IsCrossingSlice(Double_t *point, Double_t *dir, Int_t iphi, Double_t sstart, Int_t &ipl, Double_t &snext, Double_t stepmax) const
00873 {
00874
00875 if (ipl<0 || ipl>fNz-2) return kFALSE;
00876 if (sstart>stepmax) return kFALSE;
00877 Double_t pt[3];
00878 memcpy(pt, point, 3*sizeof(Double_t));
00879 if (sstart>0) for (Int_t i=0; i<3; i++) pt[i] += sstart*dir[i];
00880 stepmax -= sstart;
00881 Double_t step;
00882 Int_t incseg = (dir[2]>0)?1:-1;
00883 Double_t invdir = 1./dir[2];
00884 Double_t divphi = TMath::DegToRad()*fDphi/fNedges;
00885 Double_t phi = fPhi1*TMath::DegToRad() + (iphi+0.5)*divphi;
00886 Double_t cphi = TMath::Cos(phi);
00887 Double_t sphi = TMath::Sin(phi);
00888 Double_t apr = TGeoShape::Big();
00889 Double_t bpr = 0.;
00890 Rproj(pt[2], point, dir, cphi, sphi, apr, bpr);
00891 Double_t dz;
00892
00893 Int_t icrtseg = ipl;
00894 Int_t isegstart = ipl;
00895 Int_t iseglast = (incseg>0)?(fNz-1):-1;
00896 Double_t din,dout,rdot,rnew,rpg,apg,bpg,db,znew;
00897
00898 for (ipl=isegstart; ipl!=iseglast; ipl+=incseg) {
00899 step = (fZ[ipl+1-((1+incseg)>>1)]-pt[2])*invdir;
00900 if (step>0) {
00901 if (step>stepmax) {
00902 ipl = icrtseg;
00903 return kFALSE;
00904 }
00905 icrtseg = ipl;
00906 }
00907 din = dout = TGeoShape::Big();
00908 dz = fZ[ipl+1]-fZ[ipl];
00909
00910
00911 if (TGeoShape::IsSameWithinTolerance(dz,0)) rdot = dir[2]*TMath::Sign(1.,fRmin[ipl]-fRmin[ipl+1]);
00912 else rdot = dir[0]*cphi+dir[1]*sphi+dir[2]*(fRmin[ipl]-fRmin[ipl+1])/dz;
00913 if (rdot>0) {
00914
00915
00916 if (TGeoShape::IsSameWithinTolerance(dz,0)) {
00917 rnew = apr+bpr*fZ[ipl];
00918 rpg = (rnew-fRmin[ipl])*(rnew-fRmin[ipl+1]);
00919 if (rpg<=0) din=(fZ[ipl]-pt[2])*invdir;
00920 } else {
00921 rpg = Rpg(pt[2], ipl, kTRUE, apg, bpg);
00922 db = bpg-bpr;
00923 if (!TGeoShape::IsSameWithinTolerance(db,0)) {
00924 znew = (apr-apg)/db;
00925 if (znew>fZ[ipl] && znew<fZ[ipl+1]) {
00926 din=(znew-pt[2])*invdir;
00927 if (din<0) din=TGeoShape::Big();
00928 }
00929 }
00930 }
00931 }
00932
00933
00934 if (TGeoShape::IsSameWithinTolerance(dz,0)) rdot = dir[2]*TMath::Sign(1.,fRmax[ipl]-fRmax[ipl+1]);
00935 else rdot = dir[0]*cphi+dir[1]*sphi+dir[2]*(fRmax[ipl]-fRmax[ipl+1])/dz;
00936 if (rdot<0) {
00937
00938
00939 if (TGeoShape::IsSameWithinTolerance(dz,0)) {
00940 rnew = apr+bpr*fZ[ipl];
00941 rpg = (rnew-fRmax[ipl])*(rnew-fRmax[ipl+1]);
00942 if (rpg<=0) dout=(fZ[ipl]-pt[2])*invdir;
00943 } else {
00944 rpg = Rpg(pt[2], ipl, kFALSE, apg, bpg);
00945 db = bpg-bpr;
00946 if (!TGeoShape::IsSameWithinTolerance(db,0)) {
00947 znew = (apr-apg)/db;
00948 if (znew>fZ[ipl] && znew<fZ[ipl+1]) dout=(znew-pt[2])*invdir;
00949 if (dout<0) dout=TGeoShape::Big();
00950 }
00951 }
00952 }
00953
00954 step = TMath::Min(din, dout);
00955 if (step<1E10) {
00956
00957 if (step>stepmax) {
00958 ipl = icrtseg;
00959 return kFALSE;
00960 }
00961 snext = sstart+step;
00962 return kTRUE;
00963 }
00964 }
00965 ipl = icrtseg;
00966 return kFALSE;
00967 }
00968
00969
00970 Double_t TGeoPgon::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact, Double_t step, Double_t *safe) const
00971 {
00972
00973 if (iact<3 && safe) {
00974 *safe = Safety(point, kFALSE);
00975 if (iact==0) return TGeoShape::Big();
00976 if (iact==1 && step<*safe) return TGeoShape::Big();
00977 }
00978
00979 Double_t sdist = TGeoBBox::DistFromOutside(point,dir, fDX, fDY, fDZ, fOrigin, step);
00980 if (sdist>=step) return TGeoShape::Big();
00981
00982 if (dir[2]<=0 && TMath::Abs(point[2]-fZ[0])<TGeoShape::Tolerance()) return TGeoShape::Big();
00983 if (dir[2]>=0 && TMath::Abs(point[2]-fZ[fNz-1])<TGeoShape::Tolerance()) return TGeoShape::Big();
00984
00985 Double_t pt[3];
00986 memcpy(pt,point,3*sizeof(Double_t));
00987
00988 Int_t ipl;
00989 Int_t i, ipsec;
00990 ipl = TMath::BinarySearch(fNz, fZ, pt[2]);
00991
00992 Double_t divphi=fDphi/fNedges;
00993
00994 Double_t snext = 0.;
00995 Double_t stepmax = step;
00996 Double_t rpr, snewcross;
00997 Double_t r2 = pt[0]*pt[0]+pt[1]*pt[1];
00998 Double_t radmax = fRmax[TMath::LocMax(fNz, fRmax)];
00999 radmax = radmax/TMath::Cos(0.5*divphi*TMath::DegToRad());
01000 radmax += 1E-8;
01001 if (r2>(radmax*radmax) || pt[2]<fZ[0] || pt[2]>fZ[fNz-1]) {
01002 pt[2] -= 0.5*(fZ[0]+fZ[fNz-1]);
01003 snext = TGeoTube::DistFromOutsideS(pt,dir,0.,radmax,0.5*(fZ[fNz-1]-fZ[0]));
01004 if (snext>1E10) return TGeoShape::Big();
01005 if (snext>stepmax) return TGeoShape::Big();
01006 stepmax -= snext;
01007 pt[2] = point[2];
01008 for (i=0; i<3; i++) pt[i] += snext*dir[i];
01009 Bool_t checkz = (ipl<0 && TMath::Abs(pt[2]-fZ[0])<1E-8)?kTRUE:kFALSE;
01010 if (!checkz) checkz = (ipl==fNz-1 && TMath::Abs(pt[2]-fZ[fNz-1])<1E-8)?kTRUE:kFALSE;
01011 if (checkz) {
01012 Double_t rmin,rmax;
01013 if (ipl<0) {
01014 rmin = fRmin[0];
01015 rmax = fRmax[0];
01016 } else {
01017 rmin = fRmin[fNz-1];
01018 rmax = fRmax[fNz-1];
01019 }
01020 Double_t phi = TMath::ATan2(pt[1], pt[0])*TMath::RadToDeg();
01021 while (phi < fPhi1) phi += 360.0;
01022 Double_t ddp = phi-fPhi1;
01023 if (ddp<=fDphi) {
01024 ipsec = Int_t(ddp/divphi);
01025 Double_t ph0 = (fPhi1+divphi*(ipsec+0.5))*TMath::DegToRad();
01026 rpr = pt[0]*TMath::Cos(ph0) + pt[1]*TMath::Sin(ph0);
01027 if (rpr>=rmin && rpr<=rmax) return snext;
01028 }
01029 }
01030 }
01031 Double_t *sph = gGeoManager->GetDblBuffer(fNedges+2);
01032 Int_t *iph = gGeoManager->GetIntBuffer(fNedges+2);
01033 Int_t icrossed;
01034
01035
01036 if (TMath::Abs(dir[2])<TGeoShape::Tolerance()) {
01037 LocatePhi(pt, ipsec);
01038 icrossed = GetPhiCrossList(pt,dir,ipsec,sph,iph, stepmax);
01039 if (SliceCrossingZ(pt, dir, icrossed, iph, sph, snewcross, stepmax)) return (snext+snewcross);
01040 return TGeoShape::Big();
01041 }
01042
01043 divphi *= TMath::DegToRad();
01044 Bool_t inphi = kTRUE;
01045 Double_t ph = TMath::ATan2(pt[1], pt[0])*TMath::RadToDeg();
01046 while (ph<fPhi1) ph+=360.;
01047 ipsec = Int_t(fNedges*(ph-fPhi1)/fDphi);
01048 if (ipsec>fNedges-1) ipsec = -1;
01049 Double_t phim = fPhi1+0.5*fDphi;
01050 Double_t ddp = TMath::Abs(ph-phim);
01051 if (fDphi<360.0) {
01052 inphi = (ddp<0.5*fDphi+TGeoShape::Tolerance())?kTRUE:kFALSE;
01053 }
01054 ipl = TMath::BinarySearch(fNz, fZ, pt[2]);
01055 if (ipl<0) ipl=0;
01056 if (ipl==fNz-1) ipl--;
01057 Bool_t inz = kTRUE;
01058 if (pt[2]>fZ[fNz-1]+TGeoShape::Tolerance()) inz=kFALSE;
01059 if (pt[2]<fZ[0]-TGeoShape::Tolerance()) inz=kFALSE;
01060 Bool_t onphi = kFALSE;
01061 if (inphi && inz) {
01062 Bool_t done = kFALSE;
01063 Double_t dz = fZ[ipl+1]-fZ[ipl];
01064 Double_t phi = fPhi1*TMath::DegToRad() + (ipsec+0.5)*divphi;
01065 Double_t cphi = TMath::Cos(phi);
01066 Double_t sphi = TMath::Sin(phi);
01067 Double_t rproj = pt[0]*cphi+pt[1]*sphi;
01068 if (TGeoShape::IsSameWithinTolerance(dz,0)) {
01069 if (rproj<fRmin[ipl] && rproj>fRmin[ipl+1] && dir[2]>0) return 0.0;
01070 if (rproj>fRmin[ipl] && rproj<fRmin[ipl+1] && dir[2]<0) return 0.0;
01071 if (rproj>fRmax[ipl] && rproj<fRmax[ipl+1] && dir[2]>0) return 0.0;
01072 if (rproj<fRmax[ipl] && rproj>fRmax[ipl+1] && dir[2]<0) return 0.0;
01073 done = kTRUE;
01074 }
01075 if (!done) {
01076 Double_t apgout,bpgout;
01077 Double_t rpgout = Rpg(pt[2], ipl, kFALSE, apgout, bpgout);
01078 if (rproj<rpgout+1.E-8) {
01079 Double_t apgin,bpgin;
01080 Double_t rpgin = Rpg(pt[2], ipl, kTRUE, apgin, bpgin);
01081 if (rproj>rpgin-1.E-8) {
01082 Double_t safrmin = rproj-rpgin;
01083 Double_t safrmax = rpgout-rproj;
01084 Double_t safz = TMath::Min(pt[2]-fZ[ipl],fZ[ipl+1]-pt[2]);
01085 Double_t safphi = TGeoShape::Big();
01086 if (fDphi<360) {
01087 safphi=rproj*TMath::Sin((ddp-0.5*fDphi)*TMath::DegToRad());
01088 safphi = TMath::Abs(safphi);
01089 }
01090
01091 Double_t dzinv = 1./dz;
01092 if (safrmin<safz && safrmin<safrmax && safrmin<safphi) {
01093
01094 Double_t ndotd = dir[0]*cphi+dir[1]*sphi+dir[2]*(fRmin[ipl]-fRmin[ipl+1])*dzinv;
01095
01096 if (ndotd>0) return snext;
01097 done = kTRUE;
01098 }
01099 if (!done && safrmax<safz && safrmax<safphi) {
01100 Double_t ndotd = dir[0]*cphi+dir[1]*sphi+dir[2]*(fRmax[ipl]-fRmax[ipl+1])*dzinv;
01101
01102 if (ndotd<0) return snext;
01103 done = kTRUE;
01104 }
01105 if (!done && safz<safphi) {
01106 done = kTRUE;
01107 Int_t iplc = ipl;
01108 if (TMath::Abs(pt[2]-fZ[ipl]) > TMath::Abs(fZ[ipl+1]-pt[2])) iplc++;
01109 if (iplc==0 || iplc==fNz-1) {
01110 if (pt[2]*dir[2]<0) return snext;
01111 return TGeoShape::Big();
01112 } else {
01113 if (TGeoShape::IsSameWithinTolerance(fZ[iplc],fZ[iplc+1])) {
01114 if (dir[2]>0) {
01115 if (rproj<fRmin[iplc] && rproj>fRmin[iplc+1]) return snext;
01116 if (rproj>fRmax[iplc] && rproj<fRmax[iplc+1]) return snext;
01117 } else {
01118 if (rproj>fRmin[iplc] && rproj<fRmin[iplc+1]) return snext;
01119 if (rproj<fRmax[iplc] && rproj>fRmax[iplc+1]) return snext;
01120 }
01121 } else if (TGeoShape::IsSameWithinTolerance(fZ[iplc],fZ[iplc-1])) {
01122 if (dir[2]>0) {
01123 if (rproj<fRmin[iplc-1] && rproj>fRmin[iplc]) return snext;
01124 if (rproj>fRmax[iplc-1] && rproj<fRmax[iplc]) return snext;
01125 } else {
01126 if (rproj>fRmin[iplc-1] && rproj<fRmin[iplc]) return snext;
01127 if (rproj<fRmax[iplc-1] && rproj>fRmax[iplc]) return snext;
01128 }
01129 }
01130 }
01131 }
01132 if (!done) {
01133
01134 onphi = kTRUE;
01135 }
01136 }
01137 }
01138 }
01139 }
01140 icrossed = GetPhiCrossList(pt,dir,ipsec,sph,iph, stepmax);
01141 if (onphi) {
01142 if (!icrossed) return snext;
01143 if (iph[0]<0 && sph[0]<TGeoShape::Tolerance()) return (snext+sph[0]);
01144 if (iph[0]>=0 && sph[0]>TGeoShape::Tolerance()) return snext;
01145 }
01146
01147 if (SliceCrossing(pt, dir, icrossed, iph, sph, snewcross, stepmax)) {
01148 snext += snewcross;
01149 return snext;
01150 }
01151 return TGeoShape::Big();
01152 }
01153
01154
01155 Int_t TGeoPgon::DistancetoPrimitive(Int_t px, Int_t py)
01156 {
01157
01158 Int_t n = fNedges+1;
01159 const Int_t numPoints = 2*n*fNz;
01160 return ShapeDistancetoPrimitive(numPoints, px, py);
01161 }
01162
01163
01164 TGeoVolume *TGeoPgon::Divide(TGeoVolume *voldiv, const char *divname, Int_t iaxis, Int_t ndiv,
01165 Double_t start, Double_t step)
01166 {
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176 TGeoShape *shape;
01177 TGeoVolume *vol;
01178 TGeoVolumeMulti *vmulti;
01179 TGeoPatternFinder *finder;
01180 TString opt = "";
01181 Int_t nedges = fNedges;
01182 Double_t zmin = start;
01183 Double_t zmax = start+ndiv*step;
01184 Int_t isect = -1;
01185 Int_t is, id, ipl;
01186 switch (iaxis) {
01187 case 1:
01188 Error("Divide", "makes no sense dividing a pgon on radius");
01189 return 0;
01190 case 2:
01191 if (fNedges%ndiv) {
01192 Error("Divide", "ndiv should divide number of pgon edges");
01193 return 0;
01194 }
01195 nedges = fNedges/ndiv;
01196 finder = new TGeoPatternCylPhi(voldiv, ndiv, start, start+ndiv*step);
01197 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
01198 voldiv->SetFinder(finder);
01199 finder->SetDivIndex(voldiv->GetNdaughters());
01200 shape = new TGeoPgon(-step/2, step, nedges, fNz);
01201 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
01202 vmulti->AddVolume(vol);
01203 for (is=0; is<fNz; is++)
01204 ((TGeoPgon*)shape)->DefineSection(is, fZ[is], fRmin[is], fRmax[is]);
01205 opt = "Phi";
01206 for (id=0; id<ndiv; id++) {
01207 voldiv->AddNodeOffset(vol, id, start+id*step+step/2, opt.Data());
01208 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
01209 }
01210 return vmulti;
01211 case 3:
01212
01213 for (ipl=0; ipl<fNz-1; ipl++) {
01214 if (start<fZ[ipl]) continue;
01215 else {
01216 if ((start+ndiv*step)>fZ[ipl+1]) continue;
01217 }
01218 isect = ipl;
01219 zmin = fZ[isect];
01220 zmax = fZ[isect+1];
01221 break;
01222 }
01223 if (isect<0) {
01224 Error("Divide", "cannot divide pcon on Z if divided region is not between 2 consecutive planes");
01225 return 0;
01226 }
01227 finder = new TGeoPatternZ(voldiv, ndiv, start, start+ndiv*step);
01228 vmulti = gGeoManager->MakeVolumeMulti(divname, voldiv->GetMedium());
01229 voldiv->SetFinder(finder);
01230 finder->SetDivIndex(voldiv->GetNdaughters());
01231 opt = "Z";
01232 for (id=0; id<ndiv; id++) {
01233 Double_t z1 = start+id*step;
01234 Double_t z2 = start+(id+1)*step;
01235 Double_t rmin1 = (fRmin[isect]*(zmax-z1)-fRmin[isect+1]*(zmin-z1))/(zmax-zmin);
01236 Double_t rmax1 = (fRmax[isect]*(zmax-z1)-fRmax[isect+1]*(zmin-z1))/(zmax-zmin);
01237 Double_t rmin2 = (fRmin[isect]*(zmax-z2)-fRmin[isect+1]*(zmin-z2))/(zmax-zmin);
01238 Double_t rmax2 = (fRmax[isect]*(zmax-z2)-fRmax[isect+1]*(zmin-z2))/(zmax-zmin);
01239 shape = new TGeoPgon(fPhi1, fDphi, nedges, 2);
01240 ((TGeoPgon*)shape)->DefineSection(0, -step/2, rmin1, rmax1);
01241 ((TGeoPgon*)shape)->DefineSection(1, step/2, rmin2, rmax2);
01242 vol = new TGeoVolume(divname, shape, voldiv->GetMedium());
01243 vmulti->AddVolume(vol);
01244 voldiv->AddNodeOffset(vol, id, start+id*step+step/2, opt.Data());
01245 ((TGeoNodeOffset*)voldiv->GetNodes()->At(voldiv->GetNdaughters()-1))->SetFinder(finder);
01246 }
01247 return vmulti;
01248 default:
01249 Error("Divide", "Wrong axis type for division");
01250 return 0;
01251 }
01252 }
01253
01254
01255 void TGeoPgon::GetBoundingCylinder(Double_t *param) const
01256 {
01257
01258
01259 param[0] = fRmin[0];
01260 param[1] = fRmax[0];
01261 for (Int_t i=1; i<fNz; i++) {
01262 if (fRmin[i] < param[0]) param[0] = fRmin[i];
01263 if (fRmax[i] > param[1]) param[1] = fRmax[i];
01264 }
01265 Double_t divphi = fDphi/fNedges;
01266 param[1] /= TMath::Cos(0.5*divphi*TMath::DegToRad());
01267 param[0] *= param[0];
01268 param[1] *= param[1];
01269 if (TGeoShape::IsSameWithinTolerance(fDphi,360)) {
01270 param[2] = 0.;
01271 param[3] = 360.;
01272 return;
01273 }
01274 param[2] = (fPhi1<0)?(fPhi1+360.):fPhi1;
01275 param[3] = param[2]+fDphi;
01276 }
01277
01278
01279 void TGeoPgon::InspectShape() const
01280 {
01281
01282 printf("*** Shape %s: TGeoPgon ***\n", GetName());
01283 printf(" Nedges = %i\n", fNedges);
01284 TGeoPcon::InspectShape();
01285 }
01286
01287
01288 TBuffer3D *TGeoPgon::MakeBuffer3D() const
01289 {
01290
01291
01292
01293 const Int_t n = GetNsegments()+1;
01294 Int_t nz = GetNz();
01295 if (nz < 2) return 0;
01296 Int_t nbPnts = nz*2*n;
01297 if (nbPnts <= 0) return 0;
01298 Double_t dphi = GetDphi();
01299 Bool_t specialCase = kFALSE;
01300 if (TGeoShape::IsSameWithinTolerance(dphi,360)) specialCase = kTRUE;
01301 Int_t nbSegs = 4*(nz*n-1+(specialCase == kTRUE));
01302 Int_t nbPols = 2*(nz*n-1+(specialCase == kTRUE));
01303
01304 TBuffer3D* buff = new TBuffer3D(TBuffer3DTypes::kGeneric,
01305 nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols);
01306 if (buff)
01307 {
01308 SetPoints(buff->fPnts);
01309 SetSegsAndPols(*buff);
01310 }
01311
01312 return buff;
01313 }
01314
01315
01316 void TGeoPgon::SetSegsAndPols(TBuffer3D &buff) const
01317 {
01318
01319 Int_t i, j;
01320 const Int_t n = GetNsegments()+1;
01321 Int_t nz = GetNz();
01322 if (nz < 2) return;
01323 Int_t nbPnts = nz*2*n;
01324 if (nbPnts <= 0) return;
01325 Double_t dphi = GetDphi();
01326 Bool_t specialCase = kFALSE;
01327 if (TGeoShape::IsSameWithinTolerance(dphi,360)) specialCase = kTRUE;
01328 Int_t c = GetBasicColor();
01329
01330 Int_t indx, indx2, k;
01331 indx = indx2 = 0;
01332
01333
01334
01335 for (i = 0; i < nz*2; i++) {
01336 indx2 = i*n;
01337 for (j = 1; j < n; j++) {
01338 buff.fSegs[indx++] = c;
01339 buff.fSegs[indx++] = indx2+j-1;
01340 buff.fSegs[indx++] = indx2+j;
01341 }
01342 if (specialCase) {
01343 buff.fSegs[indx++] = c;
01344 buff.fSegs[indx++] = indx2+j-1;
01345 buff.fSegs[indx++] = indx2;
01346 }
01347 }
01348
01349
01350 for (i = 0; i < 2; i++) {
01351 indx2 = i*(nz-1)*2*n;
01352 for (j = 0; j < n; j++) {
01353 buff.fSegs[indx++] = c;
01354 buff.fSegs[indx++] = indx2+j;
01355 buff.fSegs[indx++] = indx2+n+j;
01356 }
01357 }
01358
01359
01360 for (i = 0; i < (nz-1); i++) {
01361
01362 indx2 = i*n*2;
01363 for (j = 0; j < n; j++) {
01364 buff.fSegs[indx++] = c+2;
01365 buff.fSegs[indx++] = indx2+j;
01366 buff.fSegs[indx++] = indx2+n*2+j;
01367 }
01368
01369 indx2 = i*n*2+n;
01370 for (j = 0; j < n; j++) {
01371 buff.fSegs[indx++] = c+3;
01372 buff.fSegs[indx++] = indx2+j;
01373 buff.fSegs[indx++] = indx2+n*2+j;
01374 }
01375 }
01376
01377
01378
01379 if (!specialCase) {
01380 for (i = 1; i < (nz-1); i++) {
01381 for (j = 0; j < 2; j++) {
01382 buff.fSegs[indx++] = c;
01383 buff.fSegs[indx++] = 2*i * n + j*(n-1);
01384 buff.fSegs[indx++] = (2*i+1) * n + j*(n-1);
01385 }
01386 }
01387 }
01388
01389 Int_t m = n - 1 + (specialCase == kTRUE);
01390 indx = 0;
01391
01392
01393
01394 i = 0;
01395 for (j = 0; j < n-1; j++) {
01396 buff.fPols[indx++] = c+3;
01397 buff.fPols[indx++] = 4;
01398 buff.fPols[indx++] = 2*nz*m+i*n+j;
01399 buff.fPols[indx++] = i*(nz*2-2)*m+m+j;
01400 buff.fPols[indx++] = 2*nz*m+i*n+j+1;
01401 buff.fPols[indx++] = i*(nz*2-2)*m+j;
01402 }
01403 if (specialCase) {
01404 buff.fPols[indx++] = c+3;
01405 buff.fPols[indx++] = 4;
01406 buff.fPols[indx++] = 2*nz*m+i*n+j;
01407 buff.fPols[indx++] = i*(nz*2-2)*m+m+j;
01408 buff.fPols[indx++] = 2*nz*m+i*n;
01409 buff.fPols[indx++] = i*(nz*2-2)*m+j;
01410 }
01411 i = 1;
01412 for (j = 0; j < n-1; j++) {
01413 buff.fPols[indx++] = c+3;
01414 buff.fPols[indx++] = 4;
01415 buff.fPols[indx++] = i*(nz*2-2)*m+j;
01416 buff.fPols[indx++] = 2*nz*m+i*n+j+1;
01417 buff.fPols[indx++] = i*(nz*2-2)*m+m+j;
01418 buff.fPols[indx++] = 2*nz*m+i*n+j;
01419 }
01420 if (specialCase) {
01421 buff.fPols[indx++] = c+3;
01422 buff.fPols[indx++] = 4;
01423 buff.fPols[indx++] = i*(nz*2-2)*m+j;
01424 buff.fPols[indx++] = 2*nz*m+i*n;
01425 buff.fPols[indx++] = i*(nz*2-2)*m+m+j;
01426 buff.fPols[indx++] = 2*nz*m+i*n+j;
01427 }
01428
01429
01430 for (k = 0; k < (nz-1); k++) {
01431 i = 0;
01432 for (j = 0; j < n-1; j++) {
01433 buff.fPols[indx++] = c+i;
01434 buff.fPols[indx++] = 4;
01435 buff.fPols[indx++] = nz*2*m+(2*k+i*1+2)*n+j+1;
01436 buff.fPols[indx++] = (2*k+i*1+2)*m+j;
01437 buff.fPols[indx++] = nz*2*m+(2*k+i*1+2)*n+j;
01438 buff.fPols[indx++] = (2*k+i*1)*m+j;
01439 }
01440 if (specialCase) {
01441 buff.fPols[indx++] = c+i;
01442 buff.fPols[indx++] = 4;
01443 buff.fPols[indx++] = nz*2*m+(2*k+i*1+2)*n;
01444 buff.fPols[indx++] = (2*k+i*1+2)*m+j;
01445 buff.fPols[indx++] = nz*2*m+(2*k+i*1+2)*n+j;
01446 buff.fPols[indx++] = (2*k+i*1)*m+j;
01447 }
01448 i = 1;
01449 for (j = 0; j < n-1; j++) {
01450 buff.fPols[indx++] = c+i;
01451 buff.fPols[indx++] = 4;
01452 buff.fPols[indx++] = (2*k+i*1)*m+j;
01453 buff.fPols[indx++] = nz*2*m+(2*k+i*1+2)*n+j;
01454 buff.fPols[indx++] = (2*k+i*1+2)*m+j;
01455 buff.fPols[indx++] = nz*2*m+(2*k+i*1+2)*n+j+1;
01456 }
01457 if (specialCase) {
01458 buff.fPols[indx++] = c+i;
01459 buff.fPols[indx++] = 4;
01460 buff.fPols[indx++] = (2*k+i*1)*m+j;
01461 buff.fPols[indx++] = nz*2*m+(2*k+i*1+2)*n+j;
01462 buff.fPols[indx++] = (2*k+i*1+2)*m+j;
01463 buff.fPols[indx++] = nz*2*m+(2*k+i*1+2)*n;
01464 }
01465 }
01466
01467
01468
01469 if (!specialCase) {
01470 indx2 = nz*2*(n-1);
01471 for (k = 0; k < (nz-1); k++) {
01472 buff.fPols[indx++] = c+2;
01473 buff.fPols[indx++] = 4;
01474 buff.fPols[indx++] = k==0 ? indx2 : indx2+2*nz*n+2*(k-1);
01475 buff.fPols[indx++] = indx2+2*(k+1)*n;
01476 buff.fPols[indx++] = indx2+2*nz*n+2*k;
01477 buff.fPols[indx++] = indx2+(2*k+3)*n;
01478
01479 buff.fPols[indx++] = c+2;
01480 buff.fPols[indx++] = 4;
01481 buff.fPols[indx++] = k==0 ? indx2+n-1 : indx2+2*nz*n+2*(k-1)+1;
01482 buff.fPols[indx++] = indx2+(2*k+3)*n+n-1;
01483 buff.fPols[indx++] = indx2+2*nz*n+2*k+1;
01484 buff.fPols[indx++] = indx2+2*(k+1)*n+n-1;
01485 }
01486 buff.fPols[indx-8] = indx2+n;
01487 buff.fPols[indx-2] = indx2+2*n-1;
01488 }
01489 }
01490
01491
01492 Double_t TGeoPgon::Rpg(Double_t z, Int_t ipl, Bool_t inner, Double_t &a, Double_t &b) const
01493 {
01494
01495
01496
01497
01498 Double_t rpg;
01499 if (ipl<0 || ipl>fNz-2) {
01500 Fatal("Rpg", "Plane index parameter ipl=%i out of range\n", ipl);
01501 return 0;
01502 }
01503 Double_t dz = fZ[ipl+1] - fZ[ipl];
01504 if (dz<TGeoShape::Tolerance()) {
01505
01506 rpg = (inner)?TMath::Min(fRmin[ipl],fRmin[ipl+1]):TMath::Max(fRmax[ipl],fRmax[ipl+1]);
01507 a = rpg;
01508 b = 0.;
01509 return rpg;
01510 }
01511 Double_t r1=0, r2=0;
01512 if (inner) {
01513 r1 = fRmin[ipl];
01514 r2 = fRmin[ipl+1];
01515 } else {
01516 r1 = fRmax[ipl];
01517 r2 = fRmax[ipl+1];
01518 }
01519 Double_t dzinv = 1./dz;
01520 a = (r1*fZ[ipl+1]-r2*fZ[ipl])*dzinv;
01521 b = (r2-r1)*dzinv;
01522 return (a+b*z);
01523 }
01524
01525
01526 Double_t TGeoPgon::Rproj(Double_t z, Double_t *point, Double_t *dir, Double_t cphi, Double_t sphi, Double_t &a, Double_t &b) const
01527 {
01528
01529
01530
01531 if (TMath::Abs(dir[2])<1E-8) {
01532 a = b = TGeoShape::Big();
01533 return TGeoShape::Big();
01534 }
01535 Double_t invdirz = 1./dir[2];
01536 a = ((point[0]*dir[2]-point[2]*dir[0])*cphi+(point[1]*dir[2]-point[2]*dir[1])*sphi)*invdirz;
01537 b = (dir[0]*cphi+dir[1]*sphi)*invdirz;
01538 return (a+b*z);
01539 }
01540
01541
01542 Double_t TGeoPgon::SafetyToSegment(Double_t *point, Int_t ipl, Int_t iphi, Bool_t in, Double_t safphi, Double_t safmin) const
01543 {
01544
01545 Double_t saf[3];
01546 Double_t safe;
01547 Int_t i;
01548 Double_t r,rpgon, ta, calf;
01549 if (ipl<0 || ipl>fNz-2) return (safmin+1.);
01550
01551 Double_t dz = fZ[ipl+1]-fZ[ipl];
01552 if (dz<1E-9) return 1E9;
01553 Double_t znew = point[2] - 0.5*(fZ[ipl]+fZ[ipl+1]);
01554 saf[0] = 0.5*dz - TMath::Abs(znew);
01555 if (-saf[0]>safmin) return TGeoShape::Big();
01556 Double_t rmin1 = fRmin[ipl];
01557 Double_t rmax1 = fRmax[ipl];
01558 Double_t rmin2 = fRmin[ipl+1];
01559 Double_t rmax2 = fRmax[ipl+1];
01560 Double_t divphi = fDphi/fNedges;
01561 if (iphi<0) {
01562 Double_t f = 1./TMath::Cos(0.5*divphi*TMath::DegToRad());
01563 rmax1 *= f;
01564 rmax2 *= f;
01565 r = TMath::Sqrt(point[0]*point[0]+point[1]*point[1]);
01566 Double_t ro1 = 0.5*(rmin1+rmin2);
01567 Double_t tg1 = (rmin2-rmin1)/dz;
01568 Double_t cr1 = 1./TMath::Sqrt(1.+tg1*tg1);
01569 Double_t ro2 = 0.5*(rmax1+rmax2);
01570 Double_t tg2 = (rmax2-rmax1)/dz;
01571 Double_t cr2 = 1./TMath::Sqrt(1.+tg2*tg2);
01572 Double_t rin = tg1*znew+ro1;
01573 Double_t rout = tg2*znew+ro2;
01574 saf[1] = (ro1>0)?((r-rin)*cr1):TGeoShape::Big();
01575 saf[2] = (rout-r)*cr2;
01576 for (i=0; i<3; i++) saf[i]=-saf[i];
01577 safe = saf[TMath::LocMax(3,saf)];
01578 safe = TMath::Max(safe, safphi);
01579 if (safe<0) safe = 0;
01580 return safe;
01581 }
01582 Double_t ph0 = (fPhi1+divphi*(iphi+0.5))*TMath::DegToRad();
01583 r = point[0]*TMath::Cos(ph0)+point[1]*TMath::Sin(ph0);
01584 if (rmin1+rmin2>1E-10) {
01585 ta = (rmin2-rmin1)/dz;
01586 calf = 1./TMath::Sqrt(1+ta*ta);
01587 rpgon = rmin1 + (point[2]-fZ[ipl])*ta;
01588 saf[1] = (r-rpgon)*calf;
01589 } else {
01590 saf[1] = TGeoShape::Big();
01591 }
01592 ta = (rmax2-rmax1)/dz;
01593 calf = 1./TMath::Sqrt(1+ta*ta);
01594 rpgon = rmax1 + (point[2]-fZ[ipl])*ta;
01595 saf[2] = (rpgon-r)*calf;
01596 if (in) {
01597 safe = saf[TMath::LocMin(3,saf)];
01598 safe = TMath::Min(safe, safphi);
01599 } else {
01600 for (i=0; i<3; i++) saf[i]=-saf[i];
01601 safe = saf[TMath::LocMax(3,saf)];
01602 safe = TMath::Max(safe, safphi);
01603 }
01604 if (safe<0) safe=0;
01605 return safe;
01606 }
01607
01608
01609 Double_t TGeoPgon::Safety(Double_t *point, Bool_t in) const
01610 {
01611
01612
01613 Double_t safmin, saftmp, safphi;
01614 Double_t dz;
01615 Int_t ipl, iplane, iphi;
01616 LocatePhi(point, iphi);
01617 safphi = TGeoShape::SafetyPhi(point,in,fPhi1, fPhi1+fDphi);
01618 if (in) {
01619
01620 ipl = TMath::BinarySearch(fNz, fZ, point[2]);
01621 if (ipl==(fNz-1)) return 0;
01622 if (ipl<0) return 0;
01623 dz = 0.5*(fZ[ipl+1]-fZ[ipl]);
01624 if (dz<1E-8) return 0;
01625
01626 safmin = SafetyToSegment(point, ipl, iphi, in, safphi);
01627 if (safmin>1E10) {
01628
01629 return TGeoShape::Big();
01630 }
01631 if (safmin<1E-6) return TMath::Abs(safmin);
01632
01633 iplane = ipl+1;
01634 saftmp = 0.;
01635 while ((iplane<fNz-1) && saftmp<1E10) {
01636 saftmp = TMath::Abs(SafetyToSegment(point,iplane,iphi,kFALSE,safphi,safmin));
01637 if (saftmp<safmin) safmin=saftmp;
01638 iplane++;
01639 }
01640
01641 iplane = ipl-1;
01642 saftmp = 0.;
01643 while ((iplane>=0) && saftmp<1E10) {
01644 saftmp = TMath::Abs(SafetyToSegment(point,iplane,iphi,kFALSE,safphi,safmin));
01645 if (saftmp<safmin) safmin=saftmp;
01646 iplane--;
01647 }
01648 return safmin;
01649 }
01650
01651 ipl = TMath::BinarySearch(fNz, fZ, point[2]);
01652 if (ipl<0) ipl=0;
01653 else if (ipl==fNz-1) ipl=fNz-2;
01654 dz = 0.5*(fZ[ipl+1]-fZ[ipl]);
01655 if (dz<1E-8) {
01656 ipl++;
01657 if (ipl>fNz-2) return 0.;
01658 dz = 0.5*(fZ[ipl+1]-fZ[ipl]);
01659 }
01660
01661 safmin = SafetyToSegment(point, ipl,iphi,kFALSE,safphi);
01662 if (safmin<1E-6) return TMath::Abs(safmin);
01663 saftmp = 0.;
01664
01665 iplane = ipl+1;
01666 saftmp = 0.;
01667 while ((iplane<fNz-1) && saftmp<1E10) {
01668 saftmp = TMath::Abs(SafetyToSegment(point,iplane,iphi,kFALSE,safphi,safmin));
01669 if (saftmp<safmin) safmin=saftmp;
01670 iplane++;
01671 }
01672
01673 iplane = ipl-1;
01674 saftmp = 0.;
01675 while ((iplane>=0) && saftmp<1E10) {
01676 saftmp = TMath::Abs(SafetyToSegment(point,iplane,iphi, kFALSE,safphi,safmin));
01677 if (saftmp<safmin) safmin=saftmp;
01678 iplane--;
01679 }
01680 return safmin;
01681 }
01682
01683
01684 void TGeoPgon::SavePrimitive(ostream &out, Option_t * )
01685 {
01686
01687 if (TObject::TestBit(kGeoSavePrimitive)) return;
01688 out << " // Shape: " << GetName() << " type: " << ClassName() << endl;
01689 out << " phi1 = " << fPhi1 << ";" << endl;
01690 out << " dphi = " << fDphi << ";" << endl;
01691 out << " nedges = " << fNedges << ";" << endl;
01692 out << " nz = " << fNz << ";" << endl;
01693 out << " TGeoPgon *pgon = new TGeoPgon(\"" << GetName() << "\",phi1,dphi,nedges,nz);" << endl;
01694 for (Int_t i=0; i<fNz; i++) {
01695 out << " z = " << fZ[i] << ";" << endl;
01696 out << " rmin = " << fRmin[i] << ";" << endl;
01697 out << " rmax = " << fRmax[i] << ";" << endl;
01698 out << " pgon->DefineSection(" << i << ", z,rmin,rmax);" << endl;
01699 }
01700 out << " TGeoShape *" << GetPointerName() << " = pgon;" << endl;
01701 TObject::SetBit(TGeoShape::kGeoSavePrimitive);
01702 }
01703
01704
01705 void TGeoPgon::SetDimensions(Double_t *param)
01706 {
01707
01708 fPhi1 = param[0];
01709 fDphi = param[1];
01710 fNedges = (Int_t)param[2];
01711 fNz = (Int_t)param[3];
01712 if (fNz<2) {
01713 Error("SetDimensions","Pgon %s: Number of Z sections must be > 2", GetName());
01714 return;
01715 }
01716 if (fRmin) delete [] fRmin;
01717 if (fRmax) delete [] fRmax;
01718 if (fZ) delete [] fZ;
01719 fRmin = new Double_t [fNz];
01720 fRmax = new Double_t [fNz];
01721 fZ = new Double_t [fNz];
01722 memset(fRmin, 0, fNz*sizeof(Double_t));
01723 memset(fRmax, 0, fNz*sizeof(Double_t));
01724 memset(fZ, 0, fNz*sizeof(Double_t));
01725 for (Int_t i=0; i<fNz; i++)
01726 DefineSection(i, param[4+3*i], param[5+3*i], param[6+3*i]);
01727 }
01728
01729
01730 void TGeoPgon::SetPoints(Double_t *points) const
01731 {
01732
01733 Double_t phi, dphi;
01734 Int_t n = fNedges + 1;
01735 dphi = fDphi/(n-1);
01736 Double_t factor = 1./TMath::Cos(TMath::DegToRad()*dphi/2);
01737 Int_t i, j;
01738 Int_t indx = 0;
01739
01740 if (points) {
01741 for (i = 0; i < fNz; i++) {
01742 for (j = 0; j < n; j++) {
01743 phi = (fPhi1+j*dphi)*TMath::DegToRad();
01744 points[indx++] = factor * fRmin[i] * TMath::Cos(phi);
01745 points[indx++] = factor * fRmin[i] * TMath::Sin(phi);
01746 points[indx++] = fZ[i];
01747 }
01748 for (j = 0; j < n; j++) {
01749 phi = (fPhi1+j*dphi)*TMath::DegToRad();
01750 points[indx++] = factor * fRmax[i] * TMath::Cos(phi);
01751 points[indx++] = factor * fRmax[i] * TMath::Sin(phi);
01752 points[indx++] = fZ[i];
01753 }
01754 }
01755 }
01756 }
01757
01758
01759 void TGeoPgon::SetPoints(Float_t *points) const
01760 {
01761
01762 Double_t phi, dphi;
01763 Int_t n = fNedges + 1;
01764 dphi = fDphi/(n-1);
01765 Double_t factor = 1./TMath::Cos(TMath::DegToRad()*dphi/2);
01766 Int_t i, j;
01767 Int_t indx = 0;
01768
01769 if (points) {
01770 for (i = 0; i < fNz; i++) {
01771 for (j = 0; j < n; j++) {
01772 phi = (fPhi1+j*dphi)*TMath::DegToRad();
01773 points[indx++] = factor * fRmin[i] * TMath::Cos(phi);
01774 points[indx++] = factor * fRmin[i] * TMath::Sin(phi);
01775 points[indx++] = fZ[i];
01776 }
01777 for (j = 0; j < n; j++) {
01778 phi = (fPhi1+j*dphi)*TMath::DegToRad();
01779 points[indx++] = factor * fRmax[i] * TMath::Cos(phi);
01780 points[indx++] = factor * fRmax[i] * TMath::Sin(phi);
01781 points[indx++] = fZ[i];
01782 }
01783 }
01784 }
01785 }
01786
01787
01788 void TGeoPgon::GetMeshNumbers(Int_t &nvert, Int_t &nsegs, Int_t &npols) const
01789 {
01790
01791 Int_t n = fNedges+1;
01792 Int_t nz = GetNz();
01793 nvert = nz*2*n;
01794 Bool_t specialCase = (TGeoShape::IsSameWithinTolerance(GetDphi(),360));
01795 nsegs = 4*(nz*n-1+(specialCase == kTRUE));
01796 npols = 2*(nz*n-1+(specialCase == kTRUE));
01797 }
01798
01799
01800 Int_t TGeoPgon::GetNmeshVertices() const
01801 {
01802
01803 Int_t n = fNedges+1;
01804 Int_t numPoints = fNz*2*n;
01805 return numPoints;
01806 }
01807
01808
01809 void TGeoPgon::Sizeof3D() const
01810 {
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822 }
01823
01824
01825 const TBuffer3D & TGeoPgon::GetBuffer3D(Int_t reqSections, Bool_t localFrame) const
01826 {
01827
01828 static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
01829
01830 TGeoBBox::FillBuffer3D(buffer, reqSections, localFrame);
01831
01832 if (reqSections & TBuffer3D::kRawSizes) {
01833 const Int_t n = GetNsegments()+1;
01834 Int_t nz = GetNz();
01835 Int_t nbPnts = nz*2*n;
01836 if (nz >= 2 && nbPnts > 0) {
01837 Bool_t specialCase = (TGeoShape::IsSameWithinTolerance(GetDphi(),360));
01838 Int_t nbSegs = 4*(nz*n-1+(specialCase == kTRUE));
01839 Int_t nbPols = 2*(nz*n-1+(specialCase == kTRUE));
01840 if (buffer.SetRawSizes(nbPnts, 3*nbPnts, nbSegs, 3*nbSegs, nbPols, 6*nbPols)) {
01841 buffer.SetSectionsValid(TBuffer3D::kRawSizes);
01842 }
01843 }
01844 }
01845
01846
01847 if ((reqSections & TBuffer3D::kRaw) && buffer.SectionsValid(TBuffer3D::kRawSizes)) {
01848 SetPoints(buffer.fPnts);
01849 if (!buffer.fLocalFrame) {
01850 TransformPoints(buffer.fPnts, buffer.NbPnts());
01851 }
01852
01853 SetSegsAndPols(buffer);
01854 buffer.SetSectionsValid(TBuffer3D::kRaw);
01855 }
01856
01857 return buffer;
01858 }