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