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
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 #include "TObjArray.h"
00145 #include "TEnv.h"
00146 #include "TError.h"
00147
00148 #include "TGeoMatrix.h"
00149 #include "TGeoManager.h"
00150 #include "TGeoVolume.h"
00151 #include "TGeoShape.h"
00152 #include "TVirtualGeoPainter.h"
00153 #include "TBuffer3D.h"
00154 #include "TBuffer3DTypes.h"
00155 #include "TMath.h"
00156
00157 ClassImp(TGeoShape)
00158
00159 TGeoMatrix *TGeoShape::fgTransform = NULL;
00160 Double_t TGeoShape::fgEpsMch = 2.220446049250313e-16;
00161
00162 TGeoShape::TGeoShape()
00163 {
00164
00165 fShapeBits = 0;
00166 fShapeId = 0;
00167 if (!gGeoManager) {
00168 gGeoManager = new TGeoManager("Geometry", "default geometry");
00169
00170 }
00171
00172
00173 }
00174
00175
00176 TGeoShape::TGeoShape(const char *name)
00177 :TNamed(name, "")
00178 {
00179
00180 fShapeBits = 0;
00181 fShapeId = 0;
00182 if (!gGeoManager) {
00183 gGeoManager = new TGeoManager("Geometry", "default geometry");
00184
00185 }
00186 fShapeId = gGeoManager->GetListOfShapes()->GetSize();
00187 gGeoManager->AddShape(this);
00188 }
00189
00190
00191 TGeoShape::~TGeoShape()
00192 {
00193
00194 if (gGeoManager) gGeoManager->GetListOfShapes()->Remove(this);
00195 }
00196
00197
00198 Double_t TGeoShape::ComputeEpsMch()
00199 {
00200
00201
00202 Double_t temp1 = 1.0;
00203 Double_t temp2 = 1.0 + temp1;
00204 Double_t mchEps;
00205 while (temp2>1.0) {
00206 mchEps = temp1;
00207 temp1 /= 2;
00208 temp2 = 1.0 + temp1;
00209 }
00210 fgEpsMch = mchEps;
00211 return fgEpsMch;
00212 }
00213
00214
00215 Double_t TGeoShape::EpsMch()
00216 {
00217
00218
00219 return fgEpsMch;
00220 }
00221
00222
00223 const char *TGeoShape::GetName() const
00224 {
00225
00226 if (!strlen(fName)) {
00227 return ((TObject *)this)->ClassName();
00228 }
00229 return TNamed::GetName();
00230 }
00231
00232
00233 Int_t TGeoShape::ShapeDistancetoPrimitive(Int_t numpoints, Int_t px, Int_t py) const
00234 {
00235
00236 TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
00237 if (!painter) return 9999;
00238 return painter->ShapeDistancetoPrimitive(this, numpoints, px, py);
00239 }
00240
00241
00242 Bool_t TGeoShape::IsCloseToPhi(Double_t epsil, Double_t *point, Double_t c1, Double_t s1, Double_t c2, Double_t s2)
00243 {
00244
00245 Double_t saf1 = TGeoShape::Big();
00246 Double_t saf2 = TGeoShape::Big();
00247 if (point[0]*c1+point[1]*s1 >= 0) saf1 = TMath::Abs(-point[0]*s1 + point[1]*c1);
00248 if (point[0]*c2+point[1]*s2 >= 0) saf2 = TMath::Abs(point[0]*s2 - point[1]*c2);
00249 Double_t saf = TMath::Min(saf1,saf2);
00250 if (saf<epsil) return kTRUE;
00251 return kFALSE;
00252 }
00253
00254
00255 Bool_t TGeoShape::IsInPhiRange(Double_t *point, Double_t phi1, Double_t phi2)
00256 {
00257
00258 Double_t phi = TMath::ATan2(point[1], point[0]) * TMath::RadToDeg();
00259 while (phi<phi1) phi+=360.;
00260 Double_t ddp = phi-phi1;
00261 if (ddp>phi2-phi1) return kFALSE;
00262 return kTRUE;
00263 }
00264
00265
00266 Bool_t TGeoShape::IsCrossingSemiplane(Double_t *point, Double_t *dir, Double_t cphi, Double_t sphi, Double_t &snext, Double_t &rxy)
00267 {
00268
00269
00270
00271 snext = rxy = TGeoShape::Big();
00272 Double_t nx = -sphi;
00273 Double_t ny = cphi;
00274 Double_t rxy0 = point[0]*cphi+point[1]*sphi;
00275 Double_t rdotn = point[0]*nx + point[1]*ny;
00276 if (TMath::Abs(rdotn)<TGeoShape::Tolerance()) {
00277 snext = 0.0;
00278 rxy = rxy0;
00279 return kTRUE;
00280 }
00281 if (rdotn<0) {
00282 rdotn = -rdotn;
00283 } else {
00284 nx = -nx;
00285 ny = -ny;
00286 }
00287 Double_t ddotn = dir[0]*nx + dir[1]*ny;
00288 if (ddotn<=0) return kFALSE;
00289 snext = rdotn/ddotn;
00290 rxy = rxy0+snext*(dir[0]*cphi+dir[1]*sphi);
00291 if (rxy<0) return kFALSE;
00292 return kTRUE;
00293 }
00294
00295
00296 Bool_t TGeoShape::IsSameWithinTolerance(Double_t a, Double_t b)
00297 {
00298
00299 if (TMath::Abs(a-b)<1.E-10) return kTRUE;
00300 return kFALSE;
00301 }
00302
00303
00304 Bool_t TGeoShape::IsSegCrossing(Double_t x1, Double_t y1, Double_t x2, Double_t y2,Double_t x3, Double_t y3,Double_t x4, Double_t y4)
00305 {
00306
00307
00308 Double_t eps = TGeoShape::Tolerance();
00309 Bool_t stand1 = kFALSE;
00310 Double_t dx1 = x2-x1;
00311 Bool_t stand2 = kFALSE;
00312 Double_t dx2 = x4-x3;
00313 Double_t xm = 0.;
00314 Double_t ym = 0.;
00315 Double_t a1 = 0.;
00316 Double_t b1 = 0.;
00317 Double_t a2 = 0.;
00318 Double_t b2 = 0.;
00319 if (TMath::Abs(dx1) < eps) stand1 = kTRUE;
00320 if (TMath::Abs(dx2) < eps) stand2 = kTRUE;
00321 if (!stand1) {
00322 a1 = (x2*y1-x1*y2)/dx1;
00323 b1 = (y2-y1)/dx1;
00324 }
00325 if (!stand2) {
00326 a2 = (x4*y3-x3*y4)/dx2;
00327 b2 = (y4-y3)/dx2;
00328 }
00329 if (stand1 && stand2) {
00330
00331 if (TMath::Abs(x1-x3)<eps) {
00332
00333 if ((y3-y1)*(y3-y2)<-eps || (y4-y1)*(y4-y2)<-eps ||
00334 (y1-y3)*(y1-y4)<-eps || (y2-y3)*(y2-y4)<-eps) return kTRUE;
00335 return kFALSE;
00336 }
00337
00338 return kFALSE;
00339 }
00340
00341 if (stand1) {
00342
00343 xm = x1;
00344 ym = a2+b2*xm;
00345 } else {
00346 if (stand2) {
00347
00348 xm = x3;
00349 ym = a1+b1*xm;
00350 } else {
00351
00352 if (TMath::Abs(b1-b2)<eps) {
00353
00354 if (TMath::Abs(y3-(a1+b1*x3))>eps) return kFALSE;
00355
00356 if ((x3-x1)*(x3-x2)<-eps || (x4-x1)*(x4-x2)<-eps ||
00357 (x1-x3)*(x1-x4)<-eps || (x2-x3)*(x2-x4)<-eps) return kTRUE;
00358 return kFALSE;
00359 }
00360 xm = (a1-a2)/(b2-b1);
00361 ym = (a1*b2-a2*b1)/(b2-b1);
00362 }
00363 }
00364
00365 Double_t check = (xm-x1)*(xm-x2)+(ym-y1)*(ym-y2);
00366 if (check > -eps) return kFALSE;
00367 check = (xm-x3)*(xm-x4)+(ym-y3)*(ym-y4);
00368 if (check > -eps) return kFALSE;
00369 return kTRUE;
00370 }
00371
00372
00373 Double_t TGeoShape::DistToPhiMin(Double_t *point, Double_t *dir, Double_t s1, Double_t c1,
00374 Double_t s2, Double_t c2, Double_t sm, Double_t cm, Bool_t in)
00375 {
00376
00377 Double_t sfi1=TGeoShape::Big();
00378 Double_t sfi2=TGeoShape::Big();
00379 Double_t s=0;
00380 Double_t un = dir[0]*s1-dir[1]*c1;
00381 if (!in) un=-un;
00382 if (un>0) {
00383 s=-point[0]*s1+point[1]*c1;
00384 if (!in) s=-s;
00385 if (s>=0) {
00386 s /= un;
00387 if (((point[0]+s*dir[0])*sm-(point[1]+s*dir[1])*cm)>=0) sfi1=s;
00388 }
00389 }
00390 un = -dir[0]*s2+dir[1]*c2;
00391 if (!in) un=-un;
00392 if (un>0) {
00393 s=point[0]*s2-point[1]*c2;
00394 if (!in) s=-s;
00395 if (s>=0) {
00396 s /= un;
00397 if ((-(point[0]+s*dir[0])*sm+(point[1]+s*dir[1])*cm)>=0) sfi2=s;
00398 }
00399 }
00400 return TMath::Min(sfi1, sfi2);
00401 }
00402
00403
00404 void TGeoShape::NormalPhi(Double_t *point, Double_t *dir, Double_t *norm, Double_t c1, Double_t s1, Double_t c2, Double_t s2)
00405 {
00406
00407 Double_t saf1 = TGeoShape::Big();
00408 Double_t saf2 = TGeoShape::Big();
00409 if (point[0]*c1+point[1]*s1 >= 0) saf1 = TMath::Abs(-point[0]*s1 + point[1]*c1);
00410 if (point[0]*c2+point[1]*s2 >= 0) saf2 = TMath::Abs(point[0]*s2 - point[1]*c2);
00411 Double_t c,s;
00412 if (saf1<saf2) {
00413 c=c1;
00414 s=s1;
00415 } else {
00416 c=c2;
00417 s=s2;
00418 }
00419 norm[2] = 0;
00420 norm[0] = -s;
00421 norm[1] = c;
00422 if (dir[0]*norm[0]+dir[1]*norm[1] < 0) {
00423 norm[0] = s;
00424 norm[1] = -c;
00425 }
00426 }
00427
00428
00429 Double_t TGeoShape::SafetyPhi(Double_t *point, Bool_t in, Double_t phi1, Double_t phi2)
00430 {
00431
00432
00433 Bool_t inphi = TGeoShape::IsInPhiRange(point, phi1, phi2);
00434 if (inphi && !in) return -TGeoShape::Big();
00435 phi1 *= TMath::DegToRad();
00436 phi2 *= TMath::DegToRad();
00437 Double_t c1 = TMath::Cos(phi1);
00438 Double_t s1 = TMath::Sin(phi1);
00439 Double_t c2 = TMath::Cos(phi2);
00440 Double_t s2 = TMath::Sin(phi2);
00441 Double_t rsq = point[0]*point[0]+point[1]*point[1];
00442 Double_t rproj = point[0]*c1+point[1]*s1;
00443 Double_t safsq = rsq-rproj*rproj;
00444 if (safsq<0) return 0.;
00445 Double_t saf1 = (rproj<0)?TGeoShape::Big():TMath::Sqrt(safsq);
00446 rproj = point[0]*c2+point[1]*s2;
00447 safsq = rsq-rproj*rproj;
00448 if (safsq<0) return 0.;
00449 Double_t saf2 = (rproj<0)?TGeoShape::Big():TMath::Sqrt(safsq);
00450 Double_t safe = TMath::Min(saf1, saf2);
00451 if (safe>1E10) {
00452 if (in) return TGeoShape::Big();
00453 return -TGeoShape::Big();
00454 }
00455 return safe;
00456 }
00457
00458
00459 void TGeoShape::SetShapeBit(UInt_t f, Bool_t set)
00460 {
00461
00462 if (set) {
00463 SetShapeBit(f);
00464 } else {
00465 ResetShapeBit(f);
00466 }
00467 }
00468
00469
00470 TGeoMatrix *TGeoShape::GetTransform()
00471 {
00472
00473 return fgTransform;
00474 }
00475
00476
00477 void TGeoShape::SetTransform(TGeoMatrix *matrix)
00478 {
00479
00480 fgTransform = matrix;
00481 }
00482
00483
00484 void TGeoShape::TransformPoints(Double_t *points, UInt_t NbPnts) const
00485 {
00486
00487 UInt_t i,j;
00488 Double_t dlocal[3];
00489 Double_t dmaster[3];
00490 if (fgTransform) {
00491 for (j = 0; j < NbPnts; j++) {
00492 i = 3*j;
00493 fgTransform->LocalToMaster(&points[i], dmaster);
00494 points[i] = dmaster[0];
00495 points[i+1] = dmaster[1];
00496 points[i+2] = dmaster[2];
00497 }
00498 return;
00499 }
00500 if (!gGeoManager) return;
00501 Bool_t bomb = (gGeoManager->GetBombMode()==0)?kFALSE:kTRUE;
00502
00503 for (j = 0; j < NbPnts; j++) {
00504 i = 3*j;
00505 dlocal[0] = points[3*j];
00506 dlocal[1] = points[3*j+1];
00507 dlocal[2] = points[3*j+2];
00508 if (gGeoManager->IsMatrixTransform()) {
00509 TGeoHMatrix *glmat = gGeoManager->GetGLMatrix();
00510 if (bomb) glmat->LocalToMasterBomb(&points[i], dmaster);
00511 else glmat->LocalToMaster(&points[i], dmaster);
00512 } else {
00513 if (bomb) gGeoManager->LocalToMasterBomb(&points[i], dmaster);
00514 else gGeoManager->LocalToMaster(&points[i],dmaster);
00515 }
00516 points[i] = dmaster[0];
00517 points[i+1] = dmaster[1];
00518 points[i+2] = dmaster[2];
00519 }
00520 }
00521
00522
00523 void TGeoShape::FillBuffer3D(TBuffer3D & buffer, Int_t reqSections, Bool_t localFrame) const
00524 {
00525
00526
00527
00528
00529
00530
00531 if (reqSections & TBuffer3D::kRaw) {
00532 if (!(reqSections & TBuffer3D::kRawSizes) && !buffer.SectionsValid(TBuffer3D::kRawSizes)) {
00533 R__ASSERT(kFALSE);
00534 }
00535 }
00536
00537 if (reqSections & TBuffer3D::kCore) {
00538
00539 buffer.ClearSectionsValid();
00540
00541
00542 if (!gGeoManager) {
00543 R__ASSERT(kFALSE);
00544 return;
00545 }
00546 const TGeoVolume * paintVolume = gGeoManager->GetPaintVolume();
00547 if (!paintVolume) paintVolume = gGeoManager->GetTopVolume();
00548 if (!paintVolume) {
00549 buffer.fID = const_cast<TGeoShape *>(this);
00550 buffer.fColor = 0;
00551 buffer.fTransparency = 0;
00552
00553
00554 } else {
00555 buffer.fID = const_cast<TGeoVolume *>(paintVolume);
00556 buffer.fColor = paintVolume->GetLineColor();
00557
00558 buffer.fTransparency = paintVolume->GetTransparency();
00559 Double_t visdensity = gGeoManager->GetVisDensity();
00560 if (visdensity>0 && paintVolume->GetMedium()) {
00561 if (paintVolume->GetMaterial()->GetDensity() < visdensity) {
00562 buffer.fTransparency = 90;
00563 }
00564 }
00565 }
00566
00567 buffer.fLocalFrame = localFrame;
00568 Bool_t r1,r2=kFALSE;
00569 r1 = gGeoManager->IsMatrixReflection();
00570 if (paintVolume && paintVolume->GetShape()) {
00571 if (paintVolume->GetShape()->IsReflected()) {
00572
00573
00574 if (buffer.Type() < TBuffer3DTypes::kTube) r2 = kTRUE;
00575 }
00576 }
00577 buffer.fReflection = ((r1&(!r2))|(r2&!(r1)));
00578
00579
00580 if (localFrame) {
00581 TGeoMatrix * localMasterMat = 0;
00582 if (TGeoShape::GetTransform()) {
00583 localMasterMat = TGeoShape::GetTransform();
00584 } else {
00585 localMasterMat = gGeoManager->GetCurrentMatrix();
00586
00587
00588
00589
00590 if (gGeoManager->IsMatrixTransform() && !IsComposite()) {
00591 localMasterMat = gGeoManager->GetGLMatrix();
00592 }
00593 }
00594 if (!localMasterMat) {
00595 R__ASSERT(kFALSE);
00596 return;
00597 }
00598 localMasterMat->GetHomogenousMatrix(buffer.fLocalMaster);
00599 } else {
00600 buffer.SetLocalMasterIdentity();
00601 }
00602
00603 buffer.SetSectionsValid(TBuffer3D::kCore);
00604 }
00605 }
00606
00607
00608 Int_t TGeoShape::GetBasicColor() const
00609 {
00610
00611 Int_t basicColor = 0;
00612 if (gGeoManager) {
00613 const TGeoVolume * volume = gGeoManager->GetPaintVolume();
00614 if (volume) {
00615 basicColor = ((volume->GetLineColor() %8) -1) * 4;
00616 if (basicColor < 0) basicColor = 0;
00617 }
00618 }
00619 return basicColor;
00620 }
00621
00622
00623 const TBuffer3D &TGeoShape::GetBuffer3D(Int_t , Bool_t ) const
00624 {
00625
00626 static TBuffer3D buffer(TBuffer3DTypes::kGeneric);
00627 Warning("GetBuffer3D", "this must be implemented for shapes in a TGeoPainter hierarchy. This will be come a pure virtual fn eventually.");
00628 return buffer;
00629 }
00630
00631
00632 const char *TGeoShape::GetPointerName() const
00633 {
00634
00635 static TString name;
00636 Int_t uid = GetUniqueID();
00637 if (uid) name = TString::Format("p%s_%d", GetName(),uid);
00638 else name = TString::Format("p%s", GetName());
00639 return name.Data();
00640 }
00641
00642
00643 void TGeoShape::ExecuteEvent(Int_t event, Int_t px, Int_t py)
00644 {
00645
00646 if (!gGeoManager) return;
00647 TVirtualGeoPainter *painter = gGeoManager->GetPainter();
00648 painter->ExecuteShapeEvent(this, event, px, py);
00649 }
00650
00651
00652 void TGeoShape::Draw(Option_t *option)
00653 {
00654
00655 TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
00656 if (option && strlen(option) > 0) {
00657 painter->DrawShape(this, option);
00658 } else {
00659 painter->DrawShape(this, gEnv->GetValue("Viewer3D.DefaultDrawOption",""));
00660 }
00661 }
00662
00663
00664 void TGeoShape::Paint(Option_t *option)
00665 {
00666
00667 TVirtualGeoPainter *painter = gGeoManager->GetGeomPainter();
00668 if (option && strlen(option) > 0) {
00669 painter->PaintShape(this, option);
00670 } else {
00671 painter->PaintShape(this, gEnv->GetValue("Viewer3D.DefaultDrawOption",""));
00672 }
00673 }