00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "Riostream.h"
00015
00016 #include "TGeoCompositeShape.h"
00017 #include "TGeoMatrix.h"
00018 #include "TGeoManager.h"
00019
00020 #include "TGeoBoolNode.h"
00021
00022 #include "TVirtualPad.h"
00023 #include "TVirtualViewer3D.h"
00024 #include "TBuffer3D.h"
00025 #include "TBuffer3DTypes.h"
00026 #include "TMath.h"
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 ClassImp(TGeoBoolNode)
00052
00053
00054 TGeoBoolNode::TGeoBoolNode()
00055 {
00056
00057 fLeft = 0;
00058 fRight = 0;
00059 fLeftMat = 0;
00060 fRightMat = 0;
00061 fSelected = 0;
00062 fNpoints = 0;
00063 fPoints = 0;
00064 }
00065
00066
00067 TGeoBoolNode::TGeoBoolNode(const char *expr1, const char *expr2)
00068 {
00069
00070 fLeft = 0;
00071 fRight = 0;
00072 fLeftMat = 0;
00073 fRightMat = 0;
00074 fSelected = 0;
00075 fNpoints = 0;
00076 fPoints = 0;
00077 if (!MakeBranch(expr1, kTRUE)) {
00078 return;
00079 }
00080 if (!MakeBranch(expr2, kFALSE)) {
00081 return;
00082 }
00083 }
00084
00085
00086 TGeoBoolNode::TGeoBoolNode(TGeoShape *left, TGeoShape *right, TGeoMatrix *lmat, TGeoMatrix *rmat)
00087 {
00088
00089 fSelected = 0;
00090 fLeft = left;
00091 fRight = right;
00092 fLeftMat = lmat;
00093 fNpoints = 0;
00094 fPoints = 0;
00095 if (!fLeftMat) fLeftMat = gGeoIdentity;
00096 else fLeftMat->RegisterYourself();
00097 fRightMat = rmat;
00098 if (!fRightMat) fRightMat = gGeoIdentity;
00099 else fRightMat->RegisterYourself();
00100 if (!fLeft) {
00101 Error("ctor", "left shape is NULL");
00102 return;
00103 }
00104 if (!fRight) {
00105 Error("ctor", "right shape is NULL");
00106 return;
00107 }
00108 }
00109
00110
00111 TGeoBoolNode::~TGeoBoolNode()
00112 {
00113
00114
00115 if (fPoints) delete [] fPoints;
00116 }
00117
00118
00119 Bool_t TGeoBoolNode::MakeBranch(const char *expr, Bool_t left)
00120 {
00121
00122
00123 TString sleft, sright, stransf;
00124 Int_t boolop = TGeoManager::Parse(expr, sleft, sright, stransf);
00125 if (boolop<0) {
00126 Error("MakeBranch", "invalid expresion");
00127 return kFALSE;
00128 }
00129 TGeoShape *shape = 0;
00130 TGeoMatrix *mat;
00131 TString newshape;
00132
00133 if (stransf.Length() == 0) {
00134 mat = gGeoIdentity;
00135 } else {
00136 mat = (TGeoMatrix*)gGeoManager->GetListOfMatrices()->FindObject(stransf.Data());
00137 }
00138 if (!mat) {
00139 Error("MakeBranch", "transformation %s not found", stransf.Data());
00140 return kFALSE;
00141 }
00142 switch (boolop) {
00143 case 0:
00144
00145 shape = (TGeoShape*)gGeoManager->GetListOfShapes()->FindObject(sleft.Data());
00146 if (!shape) {
00147 Error("MakeBranch", "shape %s not found", sleft.Data());
00148 return kFALSE;
00149 }
00150 break;
00151 case 1:
00152
00153 newshape = sleft;
00154 newshape += "+";
00155 newshape += sright;
00156 shape = new TGeoCompositeShape(newshape.Data());
00157 break;
00158 case 2:
00159
00160 newshape = sleft;
00161 newshape += "-";
00162 newshape += sright;
00163 shape = new TGeoCompositeShape(newshape.Data());
00164 break;
00165 case 3:
00166
00167 newshape = sleft;
00168 newshape += "*";
00169 newshape += sright;
00170 shape = new TGeoCompositeShape(newshape.Data());
00171 break;
00172 }
00173 if (boolop && (!shape || !shape->IsValid())) {
00174 Error("MakeBranch", "Shape %s not valid", newshape.Data());
00175 if (shape) delete shape;
00176 return kFALSE;
00177 }
00178 if (left) {
00179 fLeft = shape;
00180 fLeftMat = mat;
00181 } else {
00182 fRight = shape;
00183 fRightMat = mat;
00184 }
00185 return kTRUE;
00186 }
00187
00188
00189 void TGeoBoolNode::Paint(Option_t * option)
00190 {
00191
00192 TVirtualViewer3D * viewer = gPad->GetViewer3D();
00193 if (!viewer) return;
00194
00195
00196
00197
00198 Bool_t localFrame = kFALSE;
00199
00200 TGeoHMatrix *glmat = (TGeoHMatrix*)TGeoShape::GetTransform();
00201 TGeoHMatrix mat;
00202 mat = glmat;
00203
00204
00205
00206
00207
00208
00209 glmat->Multiply(fLeftMat);
00210
00211 if (TGeoCompositeShape *left = dynamic_cast<TGeoCompositeShape *>(fLeft)) left->PaintComposite(option);
00212 else {
00213 const TBuffer3D & leftBuffer = fLeft->GetBuffer3D(TBuffer3D::kAll, localFrame);
00214 viewer->AddObject(leftBuffer);
00215 }
00216
00217
00218 *glmat = &mat;
00219 glmat->Multiply(fRightMat);
00220
00221 if (TGeoCompositeShape *right = dynamic_cast<TGeoCompositeShape *>(fRight)) right->PaintComposite(option);
00222 else {
00223 const TBuffer3D & rightBuffer = fRight->GetBuffer3D(TBuffer3D::kAll, localFrame);
00224 viewer->AddObject(rightBuffer);
00225 }
00226
00227 *glmat = &mat;
00228 }
00229
00230
00231 void TGeoBoolNode::RegisterMatrices()
00232 {
00233
00234 if (!fLeftMat->IsIdentity()) fLeftMat->RegisterYourself();
00235 if (!fRightMat->IsIdentity()) fRightMat->RegisterYourself();
00236 if (fLeft->IsComposite()) ((TGeoCompositeShape*)fLeft)->GetBoolNode()->RegisterMatrices();
00237 if (fRight->IsComposite()) ((TGeoCompositeShape*)fRight)->GetBoolNode()->RegisterMatrices();
00238 }
00239
00240
00241 void TGeoBoolNode::SavePrimitive(ostream &out, Option_t *option )
00242 {
00243
00244 fLeft->SavePrimitive(out,option);
00245 fRight->SavePrimitive(out,option);
00246 if (!fLeftMat->IsIdentity()) {
00247 fLeftMat->RegisterYourself();
00248 fLeftMat->SavePrimitive(out,option);
00249 }
00250 if (!fRightMat->IsIdentity()) {
00251 fRightMat->RegisterYourself();
00252 fRightMat->SavePrimitive(out,option);
00253 }
00254 }
00255
00256
00257 void TGeoBoolNode::SetPoints(Double_t *points) const
00258 {
00259
00260 TGeoBoolNode *bn = (TGeoBoolNode*)this;
00261 Int_t npoints = bn->GetNpoints();
00262 memcpy(points, fPoints, 3*npoints*sizeof(Double_t));
00263 }
00264
00265
00266 void TGeoBoolNode::SetPoints(Float_t *points) const
00267 {
00268
00269 TGeoBoolNode *bn = (TGeoBoolNode*)this;
00270 Int_t npoints = bn->GetNpoints();
00271 for (Int_t i=0; i<3*npoints; i++) points[i] = fPoints[i];
00272 }
00273
00274
00275 void TGeoBoolNode::Sizeof3D() const
00276 {
00277
00278 fLeft->Sizeof3D();
00279 fRight->Sizeof3D();
00280 }
00281 ClassImp(TGeoUnion)
00282
00283
00284 void TGeoUnion::Paint(Option_t *option)
00285 {
00286
00287 TVirtualViewer3D *viewer = gPad->GetViewer3D();
00288
00289 if (!viewer) {
00290 Error("Paint", "gPad->GetViewer3D() returned 0, cannot work with composite!\n");
00291 return;
00292 }
00293
00294 viewer->AddCompositeOp(TBuffer3D::kCSUnion);
00295
00296 TGeoBoolNode::Paint(option);
00297 }
00298
00299
00300 TGeoUnion::TGeoUnion()
00301 {
00302
00303 }
00304
00305
00306 TGeoUnion::TGeoUnion(const char *expr1, const char *expr2)
00307 :TGeoBoolNode(expr1, expr2)
00308 {
00309
00310 }
00311
00312
00313 TGeoUnion::TGeoUnion(TGeoShape *left, TGeoShape *right, TGeoMatrix *lmat, TGeoMatrix *rmat)
00314 :TGeoBoolNode(left,right,lmat,rmat)
00315 {
00316
00317 if (left->TestShapeBit(TGeoShape::kGeoHalfSpace) || right->TestShapeBit(TGeoShape::kGeoHalfSpace)) {
00318 Fatal("TGeoUnion", "Unions with a half-space (%s + %s) not allowed", left->GetName(), right->GetName());
00319 }
00320 }
00321
00322
00323 TGeoUnion::~TGeoUnion()
00324 {
00325
00326
00327 }
00328
00329
00330 void TGeoUnion::ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Double_t *origin)
00331 {
00332
00333 if (((TGeoBBox*)fLeft)->IsNullBox()) fLeft->ComputeBBox();
00334 if (((TGeoBBox*)fRight)->IsNullBox()) fRight->ComputeBBox();
00335 Double_t vert[48];
00336 Double_t pt[3];
00337 Int_t i;
00338 Double_t xmin, xmax, ymin, ymax, zmin, zmax;
00339 xmin = ymin = zmin = TGeoShape::Big();
00340 xmax = ymax = zmax = -TGeoShape::Big();
00341 ((TGeoBBox*)fLeft)->SetBoxPoints(&vert[0]);
00342 ((TGeoBBox*)fRight)->SetBoxPoints(&vert[24]);
00343 for (i=0; i<8; i++) {
00344 fLeftMat->LocalToMaster(&vert[3*i], &pt[0]);
00345 if (pt[0]<xmin) xmin=pt[0];
00346 if (pt[0]>xmax) xmax=pt[0];
00347 if (pt[1]<ymin) ymin=pt[1];
00348 if (pt[1]>ymax) ymax=pt[1];
00349 if (pt[2]<zmin) zmin=pt[2];
00350 if (pt[2]>zmax) zmax=pt[2];
00351 }
00352 for (i=8; i<16; i++) {
00353 fRightMat->LocalToMaster(&vert[3*i], &pt[0]);
00354 if (pt[0]<xmin) xmin=pt[0];
00355 if (pt[0]>xmax) xmax=pt[0];
00356 if (pt[1]<ymin) ymin=pt[1];
00357 if (pt[1]>ymax) ymax=pt[1];
00358 if (pt[2]<zmin) zmin=pt[2];
00359 if (pt[2]>zmax) zmax=pt[2];
00360 }
00361 dx = 0.5*(xmax-xmin);
00362 origin[0] = 0.5*(xmin+xmax);
00363 dy = 0.5*(ymax-ymin);
00364 origin[1] = 0.5*(ymin+ymax);
00365 dz = 0.5*(zmax-zmin);
00366 origin[2] = 0.5*(zmin+zmax);
00367 }
00368
00369
00370 Bool_t TGeoUnion::Contains(Double_t *point) const
00371 {
00372
00373 Double_t local[3];
00374 TGeoBoolNode *node = (TGeoBoolNode*)this;
00375 fLeftMat->MasterToLocal(point, &local[0]);
00376 Bool_t inside = fLeft->Contains(&local[0]);
00377 if (inside) {
00378 node->SetSelected(1);
00379 return kTRUE;
00380 }
00381 fRightMat->MasterToLocal(point, &local[0]);
00382 inside = fRight->Contains(&local[0]);
00383 if (inside) node->SetSelected(2);
00384 return inside;
00385 }
00386
00387
00388 void TGeoUnion::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
00389 {
00390
00391 norm[0] = norm[1] = 0.;
00392 norm[2] = 1.;
00393 Double_t local[3];
00394 Double_t ldir[3], lnorm[3];
00395 if (fSelected == 1) {
00396 fLeftMat->MasterToLocal(point, local);
00397 fLeftMat->MasterToLocalVect(dir, ldir);
00398 fLeft->ComputeNormal(local,ldir,lnorm);
00399 fLeftMat->LocalToMasterVect(lnorm, norm);
00400 return;
00401 }
00402 if (fSelected == 2) {
00403 fRightMat->MasterToLocal(point, local);
00404 fRightMat->MasterToLocalVect(dir, ldir);
00405 fRight->ComputeNormal(local,ldir,lnorm);
00406 fRightMat->LocalToMasterVect(lnorm, norm);
00407 return;
00408 }
00409 fLeftMat->MasterToLocal(point, local);
00410 if (fLeft->Contains(local)) {
00411 fLeftMat->MasterToLocalVect(dir, ldir);
00412 fLeft->ComputeNormal(local,ldir,lnorm);
00413 fLeftMat->LocalToMasterVect(lnorm, norm);
00414 return;
00415 }
00416 fRightMat->MasterToLocal(point, local);
00417 if (fRight->Contains(local)) {
00418 fRightMat->MasterToLocalVect(dir, ldir);
00419 fRight->ComputeNormal(local,ldir,lnorm);
00420 fRightMat->LocalToMasterVect(lnorm, norm);
00421 return;
00422 }
00423
00424 local[0] = point[0] + 1E-5*dir[0];
00425 local[1] = point[1] + 1E-5*dir[1];
00426 local[2] = point[2] + 1E-5*dir[2];
00427
00428 if (!Contains(local)) {
00429 local[0] = point[0] - 1E-5*dir[0];
00430 local[1] = point[1] - 1E-5*dir[1];
00431 local[2] = point[2] - 1E-5*dir[2];
00432 if (!Contains(local)) return;
00433 }
00434 ComputeNormal(local,dir,norm);
00435 }
00436
00437
00438 Int_t TGeoUnion::DistanceToPrimitive(Int_t , Int_t )
00439 {
00440
00441 return 9999;
00442 }
00443
00444
00445 Double_t TGeoUnion::DistFromInside(Double_t *point, Double_t *dir, Int_t iact,
00446 Double_t step, Double_t *safe) const
00447 {
00448
00449 if (iact<3 && safe) {
00450
00451 *safe = Safety(point,kTRUE);
00452 if (iact==0) return TGeoShape::Big();
00453 if (iact==1 && step<*safe) return TGeoShape::Big();
00454 }
00455
00456 Double_t local[3], local1[3], master[3], ldir[3], rdir[3], pushed[3];
00457 memcpy(master, point, 3*sizeof(Double_t));
00458 Int_t i;
00459 TGeoBoolNode *node = (TGeoBoolNode*)this;
00460 Double_t d1=0., d2=0., snxt=0., eps=0.;
00461 fLeftMat->MasterToLocalVect(dir, ldir);
00462 fRightMat->MasterToLocalVect(dir, rdir);
00463 fLeftMat->MasterToLocal(point, local);
00464 Bool_t inside1 = fLeft->Contains(local);
00465 if (inside1) d1 = fLeft->DistFromInside(local, ldir, 3);
00466 else memcpy(local1, local, 3*sizeof(Double_t));
00467 fRightMat->MasterToLocal(point, local);
00468 Bool_t inside2 = fRight->Contains(local);
00469 if (inside2) d2 = fRight->DistFromInside(local, rdir, 3);
00470 if (!(inside1 | inside2)) {
00471
00472 d1 = fLeft->DistFromOutside(local1, ldir, 3);
00473 if (d1<2.*TGeoShape::Tolerance()) {
00474 eps = d1+TGeoShape::Tolerance();
00475 for (i=0; i<3; i++) local1[i] += eps*ldir[i];
00476 inside1 = kTRUE;
00477 d1 = fLeft->DistFromInside(local1, ldir, 3);
00478 d1 += eps;
00479 } else {
00480 d2 = fRight->DistFromOutside(local, rdir, 3);
00481 if (d2<2.*TGeoShape::Tolerance()) {
00482 eps = d2+TGeoShape::Tolerance();
00483 for (i=0; i<3; i++) local[i] += eps*rdir[i];
00484 inside2 = kTRUE;
00485 d2 = fRight->DistFromInside(local, rdir, 3);
00486 d2 += eps;
00487 }
00488 }
00489 }
00490 while (inside1 || inside2) {
00491 if (inside1 && inside2) {
00492 if (d1<d2) {
00493 snxt += d1;
00494 node->SetSelected(1);
00495
00496 inside1 = kFALSE;
00497 for (i=0; i<3; i++) master[i] += d1*dir[i];
00498
00499 fRightMat->MasterToLocal(master, local);
00500 inside2 = fRight->Contains(local);
00501 if (!inside2) return snxt;
00502 d2 = fRight->DistFromInside(local, rdir, 3);
00503 if (d2 < TGeoShape::Tolerance()) return snxt;
00504 } else {
00505 snxt += d2;
00506 node->SetSelected(2);
00507
00508 inside2 = kFALSE;
00509 for (i=0; i<3; i++) master[i] += d2*dir[i];
00510
00511 fLeftMat->MasterToLocal(master, local);
00512 inside1 = fLeft->Contains(local);
00513 if (!inside1) return snxt;
00514 d1 = fLeft->DistFromInside(local, ldir, 3);
00515 if (d1 < TGeoShape::Tolerance()) return snxt;
00516 }
00517 }
00518 if (inside1) {
00519 snxt += d1;
00520 node->SetSelected(1);
00521
00522 inside1 = kFALSE;
00523 for (i=0; i<3; i++) {
00524 master[i] += d1*dir[i];
00525 pushed[i] = master[i]+(1.+d1)*TGeoShape::Tolerance()*dir[i];
00526 }
00527
00528 fRightMat->MasterToLocal(pushed, local);
00529 inside2 = fRight->Contains(local);
00530 if (!inside2) return snxt;
00531 d2 = fRight->DistFromInside(local, rdir, 3);
00532 if (d2 < TGeoShape::Tolerance()) return snxt;
00533 d2 += (1.+d1)*TGeoShape::Tolerance();
00534 }
00535 if (inside2) {
00536 snxt += d2;
00537 node->SetSelected(2);
00538
00539 inside2 = kFALSE;
00540 for (i=0; i<3; i++) {
00541 master[i] += d2*dir[i];
00542 pushed[i] = master[i]+(1.+d2)*TGeoShape::Tolerance()*dir[i];
00543 }
00544
00545 fLeftMat->MasterToLocal(pushed, local);
00546 inside1 = fLeft->Contains(local);
00547 if (!inside1) return snxt;
00548 d1 = fLeft->DistFromInside(local, ldir, 3);
00549 if (d1 < TGeoShape::Tolerance()) return snxt;
00550 d1 += (1.+d2)*TGeoShape::Tolerance();
00551 }
00552 }
00553 return snxt;
00554 }
00555
00556
00557 Double_t TGeoUnion::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact,
00558 Double_t step, Double_t *safe) const
00559 {
00560
00561 if (iact<3 && safe) {
00562
00563 *safe = Safety(point,kFALSE);
00564 if (iact==0) return TGeoShape::Big();
00565 if (iact==1 && step<*safe) return TGeoShape::Big();
00566 }
00567 TGeoBoolNode *node = (TGeoBoolNode*)this;
00568 Double_t local[3], ldir[3], rdir[3];
00569 Double_t d1, d2, snxt;
00570 fLeftMat->MasterToLocal(point, &local[0]);
00571 fLeftMat->MasterToLocalVect(dir, &ldir[0]);
00572 fRightMat->MasterToLocalVect(dir, &rdir[0]);
00573 d1 = fLeft->DistFromOutside(&local[0], &ldir[0], iact, step, safe);
00574 fRightMat->MasterToLocal(point, &local[0]);
00575 d2 = fRight->DistFromOutside(&local[0], &rdir[0], iact, step, safe);
00576 if (d1<d2) {
00577 snxt = d1;
00578 node->SetSelected(1);
00579 } else {
00580 snxt = d2;
00581 node->SetSelected(2);
00582 }
00583 return snxt;
00584 }
00585
00586
00587 Int_t TGeoUnion::GetNpoints()
00588 {
00589
00590 Int_t itot=0;
00591 Double_t point[3];
00592 Double_t tolerance = TGeoShape::Tolerance();
00593 if (fNpoints) return fNpoints;
00594
00595 Int_t nleft = fLeft->GetNmeshVertices();
00596 Double_t *points1 = new Double_t[3*nleft];
00597 fLeft->SetPoints(points1);
00598
00599 Int_t nright = fRight->GetNmeshVertices();
00600 Double_t *points2 = new Double_t[3*nright];
00601 fRight->SetPoints(points2);
00602 Double_t *points = new Double_t[3*(nleft+nright)];
00603 for (Int_t i=0; i<nleft; i++) {
00604 if (TMath::Abs(points1[3*i])<tolerance && TMath::Abs(points1[3*i+1])<tolerance) continue;
00605 fLeftMat->LocalToMaster(&points1[3*i], &points[3*itot]);
00606 fRightMat->MasterToLocal(&points[3*itot], point);
00607 if (!fRight->Contains(point)) itot++;
00608 }
00609 for (Int_t i=0; i<nright; i++) {
00610 if (TMath::Abs(points2[3*i])<tolerance && TMath::Abs(points2[3*i+1])<tolerance) continue;
00611 fRightMat->LocalToMaster(&points2[3*i], &points[3*itot]);
00612 fLeftMat->MasterToLocal(&points[3*itot], point);
00613 if (!fLeft->Contains(point)) itot++;
00614 }
00615 fNpoints = itot;
00616 fPoints = new Double_t[3*fNpoints];
00617 memcpy(fPoints, points, 3*fNpoints*sizeof(Double_t));
00618 delete [] points1;
00619 delete [] points2;
00620 delete [] points;
00621 return fNpoints;
00622 }
00623
00624
00625 Double_t TGeoUnion::Safety(Double_t *point, Bool_t in) const
00626 {
00627
00628 Double_t local1[3], local2[3];
00629 fLeftMat->MasterToLocal(point,local1);
00630 Bool_t in1 = fLeft->Contains(local1);
00631 fRightMat->MasterToLocal(point,local2);
00632 Bool_t in2 = fRight->Contains(local2);
00633 Bool_t intrue = in1 | in2;
00634 if (intrue^in) return 0.0;
00635 Double_t saf1 = fLeft->Safety(local1, in1);
00636 Double_t saf2 = fRight->Safety(local2, in2);
00637 if (in1 && in2) return TMath::Min(saf1, saf2);
00638 if (in1) return saf1;
00639 if (in2) return saf2;
00640 return TMath::Min(saf1,saf2);
00641 }
00642
00643
00644 void TGeoUnion::SavePrimitive(ostream &out, Option_t *option )
00645 {
00646
00647 TGeoBoolNode::SavePrimitive(out,option);
00648 out << " pBoolNode = new TGeoUnion(";
00649 out << fLeft->GetPointerName() << ",";
00650 out << fRight->GetPointerName() << ",";
00651 if (!fLeftMat->IsIdentity()) out << fLeftMat->GetPointerName() << ",";
00652 else out << "0,";
00653 if (!fRightMat->IsIdentity()) out << fRightMat->GetPointerName() << ");" << endl;
00654 else out << "0);" << endl;
00655 }
00656
00657
00658 void TGeoUnion::Sizeof3D() const
00659 {
00660
00661 TGeoBoolNode::Sizeof3D();
00662 }
00663
00664
00665 ClassImp(TGeoSubtraction)
00666
00667
00668 void TGeoSubtraction::Paint(Option_t *option)
00669 {
00670
00671 TVirtualViewer3D *viewer = gPad->GetViewer3D();
00672
00673 if (!viewer) {
00674 Error("Paint", "gPad->GetViewer3D() returned 0, cannot work with composite!\n");
00675 return;
00676 }
00677
00678 viewer->AddCompositeOp(TBuffer3D::kCSDifference);
00679
00680 TGeoBoolNode::Paint(option);
00681 }
00682
00683
00684 TGeoSubtraction::TGeoSubtraction()
00685 {
00686
00687 }
00688
00689
00690 TGeoSubtraction::TGeoSubtraction(const char *expr1, const char *expr2)
00691 :TGeoBoolNode(expr1, expr2)
00692 {
00693
00694 }
00695
00696
00697 TGeoSubtraction::TGeoSubtraction(TGeoShape *left, TGeoShape *right, TGeoMatrix *lmat, TGeoMatrix *rmat)
00698 :TGeoBoolNode(left,right,lmat,rmat)
00699 {
00700
00701 if (left->TestShapeBit(TGeoShape::kGeoHalfSpace)) {
00702 Fatal("TGeoSubstraction", "Substractions from a half-space (%s) not allowed", left->GetName());
00703 }
00704 }
00705
00706
00707 TGeoSubtraction::~TGeoSubtraction()
00708 {
00709
00710
00711 }
00712
00713
00714 void TGeoSubtraction::ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Double_t *origin)
00715 {
00716
00717 TGeoBBox *box = (TGeoBBox*)fLeft;
00718 if (box->IsNullBox()) fLeft->ComputeBBox();
00719 Double_t vert[24];
00720 Double_t pt[3];
00721 Int_t i;
00722 Double_t xmin, xmax, ymin, ymax, zmin, zmax;
00723 xmin = ymin = zmin = TGeoShape::Big();
00724 xmax = ymax = zmax = -TGeoShape::Big();
00725 box->SetBoxPoints(&vert[0]);
00726 for (i=0; i<8; i++) {
00727 fLeftMat->LocalToMaster(&vert[3*i], &pt[0]);
00728 if (pt[0]<xmin) xmin=pt[0];
00729 if (pt[0]>xmax) xmax=pt[0];
00730 if (pt[1]<ymin) ymin=pt[1];
00731 if (pt[1]>ymax) ymax=pt[1];
00732 if (pt[2]<zmin) zmin=pt[2];
00733 if (pt[2]>zmax) zmax=pt[2];
00734 }
00735 dx = 0.5*(xmax-xmin);
00736 origin[0] = 0.5*(xmin+xmax);
00737 dy = 0.5*(ymax-ymin);
00738 origin[1] = 0.5*(ymin+ymax);
00739 dz = 0.5*(zmax-zmin);
00740 origin[2] = 0.5*(zmin+zmax);
00741 }
00742
00743
00744 void TGeoSubtraction::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
00745 {
00746
00747 norm[0] = norm[1] = 0.;
00748 norm[2] = 1.;
00749 Double_t local[3], ldir[3], lnorm[3];
00750 if (fSelected == 1) {
00751 fLeftMat->MasterToLocal(point, local);
00752 fLeftMat->MasterToLocalVect(dir, ldir);
00753 fLeft->ComputeNormal(local,ldir,lnorm);
00754 fLeftMat->LocalToMasterVect(lnorm, norm);
00755 return;
00756 }
00757 if (fSelected == 2) {
00758 fRightMat->MasterToLocal(point, local);
00759 fRightMat->MasterToLocalVect(dir, ldir);
00760 fRight->ComputeNormal(local,ldir,lnorm);
00761 fRightMat->LocalToMasterVect(lnorm, norm);
00762 return;
00763 }
00764 fRightMat->MasterToLocal(point,local);
00765 if (fRight->Contains(local)) {
00766 fRightMat->MasterToLocalVect(dir,ldir);
00767 fRight->ComputeNormal(local,ldir, lnorm);
00768 fRightMat->LocalToMasterVect(lnorm,norm);
00769 return;
00770 }
00771 fLeftMat->MasterToLocal(point,local);
00772 if (!fLeft->Contains(local)) {
00773 fLeftMat->MasterToLocalVect(dir,ldir);
00774 fLeft->ComputeNormal(local,ldir, lnorm);
00775 fLeftMat->LocalToMasterVect(lnorm,norm);
00776 return;
00777 }
00778
00779 local[0] = point[0]+1E-5*dir[0];
00780 local[1] = point[1]+1E-5*dir[1];
00781 local[2] = point[2]+1E-5*dir[2];
00782 if (Contains(local)) {
00783 local[0] = point[0]-1E-5*dir[0];
00784 local[1] = point[1]-1E-5*dir[1];
00785 local[2] = point[2]-1E-5*dir[2];
00786 if (Contains(local)) return;
00787 }
00788 ComputeNormal(local,dir,norm);
00789 }
00790
00791
00792 Bool_t TGeoSubtraction::Contains(Double_t *point) const
00793 {
00794
00795 Double_t local[3];
00796 TGeoBoolNode *node = (TGeoBoolNode*)this;
00797 fLeftMat->MasterToLocal(point, &local[0]);
00798 Bool_t inside = fLeft->Contains(&local[0]);
00799 if (inside) node->SetSelected(1);
00800 else return kFALSE;
00801 fRightMat->MasterToLocal(point, &local[0]);
00802 inside = !fRight->Contains(&local[0]);
00803 if (!inside) node->SetSelected(2);
00804 return inside;
00805 }
00806
00807
00808 Int_t TGeoSubtraction::DistanceToPrimitive(Int_t , Int_t )
00809 {
00810
00811 return 9999;
00812 }
00813
00814
00815 Double_t TGeoSubtraction::DistFromInside(Double_t *point, Double_t *dir, Int_t iact,
00816 Double_t step, Double_t *safe) const
00817 {
00818
00819 if (iact<3 && safe) {
00820
00821 *safe = Safety(point,kTRUE);
00822 if (iact==0) return TGeoShape::Big();
00823 if (iact==1 && step<*safe) return TGeoShape::Big();
00824 }
00825 TGeoBoolNode *node = (TGeoBoolNode*)this;
00826 Double_t local[3], ldir[3], rdir[3];
00827 Double_t d1, d2, snxt=0.;
00828 fLeftMat->MasterToLocal(point, &local[0]);
00829 fLeftMat->MasterToLocalVect(dir, &ldir[0]);
00830 fRightMat->MasterToLocalVect(dir, &rdir[0]);
00831 d1 = fLeft->DistFromInside(&local[0], &ldir[0], iact, step, safe);
00832 fRightMat->MasterToLocal(point, &local[0]);
00833 d2 = fRight->DistFromOutside(&local[0], &rdir[0], iact, step, safe);
00834 if (d1<d2) {
00835 snxt = d1;
00836 node->SetSelected(1);
00837 } else {
00838 snxt = d2;
00839 node->SetSelected(2);
00840 }
00841 return snxt;
00842 }
00843
00844
00845 Double_t TGeoSubtraction::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact,
00846 Double_t step, Double_t *safe) const
00847 {
00848
00849 if (iact<3 && safe) {
00850
00851 *safe = Safety(point,kFALSE);
00852 if (iact==0) return TGeoShape::Big();
00853 if (iact==1 && step<*safe) return TGeoShape::Big();
00854 }
00855 TGeoBoolNode *node = (TGeoBoolNode*)this;
00856 Double_t local[3], master[3], ldir[3], rdir[3];
00857 memcpy(&master[0], point, 3*sizeof(Double_t));
00858 Int_t i;
00859 Double_t d1, d2, snxt=0.;
00860 fRightMat->MasterToLocal(point, &local[0]);
00861 fLeftMat->MasterToLocalVect(dir, &ldir[0]);
00862 fRightMat->MasterToLocalVect(dir, &rdir[0]);
00863
00864 Bool_t inside = fRight->Contains(&local[0]);
00865 Double_t epsil = 0.;
00866 while (1) {
00867 if (inside) {
00868
00869 node->SetSelected(2);
00870 d1 = fRight->DistFromInside(&local[0], &rdir[0], iact, step, safe);
00871 snxt += d1+epsil;
00872 for (i=0; i<3; i++) master[i] += (d1+1E-8)*dir[i];
00873 epsil = 1.E-8;
00874
00875 fLeftMat->MasterToLocal(&master[0], &local[0]);
00876 if (fLeft->Contains(&local[0])) return snxt;
00877 }
00878
00879 node->SetSelected(1);
00880 fLeftMat->MasterToLocal(&master[0], &local[0]);
00881 d2 = fLeft->DistFromOutside(&local[0], &ldir[0], iact, step, safe);
00882 if (d2>1E20) return TGeoShape::Big();
00883
00884 fRightMat->MasterToLocal(&master[0], &local[0]);
00885 d1 = fRight->DistFromOutside(&local[0], &rdir[0], iact, step, safe);
00886 if (d2<d1-TGeoShape::Tolerance()) {
00887 snxt += d2+epsil;
00888 return snxt;
00889 }
00890
00891 snxt += d1+epsil;
00892 for (i=0; i<3; i++) master[i] += (d1+1E-8)*dir[i];
00893 epsil = 1.E-8;
00894
00895 fRightMat->MasterToLocal(&master[0], &local[0]);
00896 inside = kTRUE;
00897 }
00898 }
00899
00900
00901 Int_t TGeoSubtraction::GetNpoints()
00902 {
00903
00904 Int_t itot=0;
00905 Double_t point[3];
00906 Double_t tolerance = TGeoShape::Tolerance();
00907 if (fNpoints) return fNpoints;
00908 Int_t nleft = fLeft->GetNmeshVertices();
00909 Int_t nright = fRight->GetNmeshVertices();
00910 Double_t *points = new Double_t[3*(nleft+nright)];
00911 Double_t *points1 = new Double_t[3*nleft];
00912 fLeft->SetPoints(points1);
00913 for (Int_t i=0; i<nleft; i++) {
00914 if (TMath::Abs(points1[3*i])<tolerance && TMath::Abs(points1[3*i+1])<tolerance) continue;
00915 fLeftMat->LocalToMaster(&points1[3*i], &points[3*itot]);
00916 fRightMat->MasterToLocal(&points[3*itot], point);
00917 if (!fRight->Contains(point)) itot++;
00918 }
00919 Double_t *points2 = new Double_t[3*nright];
00920 fRight->SetPoints(points2);
00921 for (Int_t i=0; i<nright; i++) {
00922 if (TMath::Abs(points2[3*i])<tolerance && TMath::Abs(points2[3*i+1])<tolerance) continue;
00923 fRightMat->LocalToMaster(&points2[3*i], &points[3*itot]);
00924 fLeftMat->MasterToLocal(&points[3*itot], point);
00925 if (fLeft->Contains(point)) itot++;
00926 }
00927 fNpoints = itot;
00928 fPoints = new Double_t[3*fNpoints];
00929 memcpy(fPoints, points, 3*fNpoints*sizeof(Double_t));
00930 delete [] points1;
00931 delete [] points2;
00932 delete [] points;
00933 return fNpoints;
00934 }
00935
00936
00937 Double_t TGeoSubtraction::Safety(Double_t *point, Bool_t in) const
00938 {
00939
00940 Double_t local1[3], local2[3];
00941 fLeftMat->MasterToLocal(point,local1);
00942 Bool_t in1 = fLeft->Contains(local1);
00943 fRightMat->MasterToLocal(point,local2);
00944 Bool_t in2 = fRight->Contains(local2);
00945 Bool_t intrue = in1 && (!in2);
00946 if (in^intrue) return 0.0;
00947 Double_t saf1 = fLeft->Safety(local1, in1);
00948 Double_t saf2 = fRight->Safety(local2, in2);
00949 if (in1 && in2) return saf2;
00950 if (in1) return TMath::Min(saf1,saf2);
00951 if (in2) return TMath::Max(saf1,saf2);
00952 return saf1;
00953 }
00954
00955
00956 void TGeoSubtraction::SavePrimitive(ostream &out, Option_t *option )
00957 {
00958
00959 TGeoBoolNode::SavePrimitive(out,option);
00960 out << " pBoolNode = new TGeoSubtraction(";
00961 out << fLeft->GetPointerName() << ",";
00962 out << fRight->GetPointerName() << ",";
00963 if (!fLeftMat->IsIdentity()) out << fLeftMat->GetPointerName() << ",";
00964 else out << "0,";
00965 if (!fRightMat->IsIdentity()) out << fRightMat->GetPointerName() << ");" << endl;
00966 else out << "0);" << endl;
00967 }
00968
00969
00970 void TGeoSubtraction::Sizeof3D() const
00971 {
00972
00973 TGeoBoolNode::Sizeof3D();
00974 }
00975
00976 ClassImp(TGeoIntersection)
00977
00978
00979 void TGeoIntersection::Paint(Option_t *option)
00980 {
00981
00982 TVirtualViewer3D *viewer = gPad->GetViewer3D();
00983
00984 if (!viewer) {
00985 Error("Paint", "gPad->GetViewer3D() returned 0, cannot work with composite!\n");
00986 return;
00987 }
00988
00989 viewer->AddCompositeOp(TBuffer3D::kCSIntersection);
00990
00991 TGeoBoolNode::Paint(option);
00992 }
00993
00994
00995 TGeoIntersection::TGeoIntersection()
00996 {
00997
00998 }
00999
01000
01001 TGeoIntersection::TGeoIntersection(const char *expr1, const char *expr2)
01002 :TGeoBoolNode(expr1, expr2)
01003 {
01004
01005 }
01006
01007
01008 TGeoIntersection::TGeoIntersection(TGeoShape *left, TGeoShape *right, TGeoMatrix *lmat, TGeoMatrix *rmat)
01009 :TGeoBoolNode(left,right,lmat,rmat)
01010 {
01011
01012 Bool_t hs1 = (fLeft->TestShapeBit(TGeoShape::kGeoHalfSpace))?kTRUE:kFALSE;
01013 Bool_t hs2 = (fRight->TestShapeBit(TGeoShape::kGeoHalfSpace))?kTRUE:kFALSE;
01014 if (hs1 && hs2) Fatal("ctor", "cannot intersect two half-spaces: %s * %s", left->GetName(), right->GetName());
01015 }
01016
01017
01018 TGeoIntersection::~TGeoIntersection()
01019 {
01020
01021
01022 }
01023
01024
01025 void TGeoIntersection::ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Double_t *origin)
01026 {
01027
01028 Bool_t hs1 = (fLeft->TestShapeBit(TGeoShape::kGeoHalfSpace))?kTRUE:kFALSE;
01029 Bool_t hs2 = (fRight->TestShapeBit(TGeoShape::kGeoHalfSpace))?kTRUE:kFALSE;
01030 Double_t vert[48];
01031 Double_t pt[3];
01032 Int_t i;
01033 Double_t xmin1, xmax1, ymin1, ymax1, zmin1, zmax1;
01034 Double_t xmin2, xmax2, ymin2, ymax2, zmin2, zmax2;
01035 xmin1 = ymin1 = zmin1 = xmin2 = ymin2 = zmin2 = TGeoShape::Big();
01036 xmax1 = ymax1 = zmax1 = xmax2 = ymax2 = zmax2 = -TGeoShape::Big();
01037 if (!hs1) {
01038 if (((TGeoBBox*)fLeft)->IsNullBox()) fLeft->ComputeBBox();
01039 ((TGeoBBox*)fLeft)->SetBoxPoints(&vert[0]);
01040 for (i=0; i<8; i++) {
01041 fLeftMat->LocalToMaster(&vert[3*i], &pt[0]);
01042 if (pt[0]<xmin1) xmin1=pt[0];
01043 if (pt[0]>xmax1) xmax1=pt[0];
01044 if (pt[1]<ymin1) ymin1=pt[1];
01045 if (pt[1]>ymax1) ymax1=pt[1];
01046 if (pt[2]<zmin1) zmin1=pt[2];
01047 if (pt[2]>zmax1) zmax1=pt[2];
01048 }
01049 }
01050 if (!hs2) {
01051 if (((TGeoBBox*)fRight)->IsNullBox()) fRight->ComputeBBox();
01052 ((TGeoBBox*)fRight)->SetBoxPoints(&vert[24]);
01053 for (i=8; i<16; i++) {
01054 fRightMat->LocalToMaster(&vert[3*i], &pt[0]);
01055 if (pt[0]<xmin2) xmin2=pt[0];
01056 if (pt[0]>xmax2) xmax2=pt[0];
01057 if (pt[1]<ymin2) ymin2=pt[1];
01058 if (pt[1]>ymax2) ymax2=pt[1];
01059 if (pt[2]<zmin2) zmin2=pt[2];
01060 if (pt[2]>zmax2) zmax2=pt[2];
01061 }
01062 }
01063 if (hs1) {
01064 dx = 0.5*(xmax2-xmin2);
01065 origin[0] = 0.5*(xmax2+xmin2);
01066 dy = 0.5*(ymax2-ymin2);
01067 origin[1] = 0.5*(ymax2+ymin2);
01068 dz = 0.5*(zmax2-zmin2);
01069 origin[2] = 0.5*(zmax2+zmin2);
01070 return;
01071 }
01072 if (hs2) {
01073 dx = 0.5*(xmax1-xmin1);
01074 origin[0] = 0.5*(xmax1+xmin1);
01075 dy = 0.5*(ymax1-ymin1);
01076 origin[1] = 0.5*(ymax1+ymin1);
01077 dz = 0.5*(zmax1-zmin1);
01078 origin[2] = 0.5*(zmax1+zmin1);
01079 return;
01080 }
01081 Double_t sort[4];
01082 Int_t isort[4];
01083 sort[0] = xmin1;
01084 sort[1] = xmax1;
01085 sort[2] = xmin2;
01086 sort[3] = xmax2;
01087 TMath::Sort(4, &sort[0], &isort[0], kFALSE);
01088 if (isort[1]%2) {
01089 Warning("ComputeBBox", "shapes %s and %s do not intersect", fLeft->GetName(), fRight->GetName());
01090 dx = dy = dz = 0;
01091 memset(origin, 0, 3*sizeof(Double_t));
01092 return;
01093 }
01094 dx = 0.5*(sort[isort[2]]-sort[isort[1]]);
01095 origin[0] = 0.5*(sort[isort[1]]+sort[isort[2]]);
01096 sort[0] = ymin1;
01097 sort[1] = ymax1;
01098 sort[2] = ymin2;
01099 sort[3] = ymax2;
01100 TMath::Sort(4, &sort[0], &isort[0], kFALSE);
01101 if (isort[1]%2) {
01102 Warning("ComputeBBox", "shapes %s and %s do not intersect", fLeft->GetName(), fRight->GetName());
01103 dx = dy = dz = 0;
01104 memset(origin, 0, 3*sizeof(Double_t));
01105 return;
01106 }
01107 dy = 0.5*(sort[isort[2]]-sort[isort[1]]);
01108 origin[1] = 0.5*(sort[isort[1]]+sort[isort[2]]);
01109 sort[0] = zmin1;
01110 sort[1] = zmax1;
01111 sort[2] = zmin2;
01112 sort[3] = zmax2;
01113 TMath::Sort(4, &sort[0], &isort[0], kFALSE);
01114 if (isort[1]%2) {
01115 Warning("ComputeBBox", "shapes %s and %s do not intersect", fLeft->GetName(), fRight->GetName());
01116 dx = dy = dz = 0;
01117 memset(origin, 0, 3*sizeof(Double_t));
01118 return;
01119 }
01120 dz = 0.5*(sort[isort[2]]-sort[isort[1]]);
01121 origin[2] = 0.5*(sort[isort[1]]+sort[isort[2]]);
01122 }
01123
01124
01125 void TGeoIntersection::ComputeNormal(Double_t *point, Double_t *dir, Double_t *norm)
01126 {
01127
01128 Double_t local[3], ldir[3], lnorm[3];
01129 norm[0] = norm[1] = 0.;
01130 norm[2] = 1.;
01131 if (fSelected == 1) {
01132 fLeftMat->MasterToLocal(point, local);
01133 fLeftMat->MasterToLocalVect(dir, ldir);
01134 fLeft->ComputeNormal(local,ldir,lnorm);
01135 fLeftMat->LocalToMasterVect(lnorm, norm);
01136 return;
01137 }
01138 if (fSelected == 2) {
01139 fRightMat->MasterToLocal(point, local);
01140 fRightMat->MasterToLocalVect(dir, ldir);
01141 fRight->ComputeNormal(local,ldir,lnorm);
01142 fRightMat->LocalToMasterVect(lnorm, norm);
01143 return;
01144 }
01145 fLeftMat->MasterToLocal(point,local);
01146 if (!fLeft->Contains(local)) {
01147 fLeftMat->MasterToLocalVect(dir,ldir);
01148 fLeft->ComputeNormal(local,ldir,lnorm);
01149 fLeftMat->LocalToMasterVect(lnorm,norm);
01150 return;
01151 }
01152 fRightMat->MasterToLocal(point,local);
01153 if (!fRight->Contains(local)) {
01154 fRightMat->MasterToLocalVect(dir,ldir);
01155 fRight->ComputeNormal(local,ldir,lnorm);
01156 fRightMat->LocalToMasterVect(lnorm,norm);
01157 return;
01158 }
01159
01160 local[0] = point[0] + 1E-5*dir[0];
01161 local[1] = point[1] + 1E-5*dir[1];
01162 local[2] = point[2] + 1E-5*dir[2];
01163 if (Contains(local)) {
01164 local[0] = point[0] - 1E-5*dir[0];
01165 local[1] = point[1] - 1E-5*dir[1];
01166 local[2] = point[2] - 1E-5*dir[2];
01167 if (Contains(local)) return;
01168 }
01169 ComputeNormal(local,dir,norm);
01170 }
01171
01172
01173 Bool_t TGeoIntersection::Contains(Double_t *point) const
01174 {
01175
01176 Double_t local[3];
01177 fLeftMat->MasterToLocal(point, &local[0]);
01178 Bool_t inside = fLeft->Contains(&local[0]);
01179 if (!inside) return kFALSE;
01180 fRightMat->MasterToLocal(point, &local[0]);
01181 inside = fRight->Contains(&local[0]);
01182 return inside;
01183 }
01184
01185
01186 Int_t TGeoIntersection::DistanceToPrimitive(Int_t , Int_t )
01187 {
01188
01189 return 9999;
01190 }
01191
01192
01193 Double_t TGeoIntersection::DistFromInside(Double_t *point, Double_t *dir, Int_t iact,
01194 Double_t step, Double_t *safe) const
01195 {
01196
01197 if (iact<3 && safe) {
01198
01199 *safe = Safety(point,kTRUE);
01200 if (iact==0) return TGeoShape::Big();
01201 if (iact==1 && step<*safe) return TGeoShape::Big();
01202 }
01203 TGeoBoolNode *node = (TGeoBoolNode*)this;
01204 Double_t local[3], ldir[3], rdir[3];
01205 Double_t d1, d2, snxt=0.;
01206 fLeftMat->MasterToLocal(point, &local[0]);
01207 fLeftMat->MasterToLocalVect(dir, &ldir[0]);
01208 fRightMat->MasterToLocalVect(dir, &rdir[0]);
01209 d1 = fLeft->DistFromInside(&local[0], &ldir[0], iact, step, safe);
01210 fRightMat->MasterToLocal(point, &local[0]);
01211 d2 = fRight->DistFromInside(&local[0], &rdir[0], iact, step, safe);
01212 if (d1<d2) {
01213 snxt = d1;
01214 node->SetSelected(1);
01215 } else {
01216 snxt = d2;
01217 node->SetSelected(2);
01218 }
01219 return snxt;
01220 }
01221
01222
01223 Double_t TGeoIntersection::DistFromOutside(Double_t *point, Double_t *dir, Int_t iact,
01224 Double_t step, Double_t *safe) const
01225 {
01226
01227 Double_t tol = TGeoShape::Tolerance();
01228 if (iact<3 && safe) {
01229
01230 *safe = Safety(point,kFALSE);
01231 if (iact==0) return TGeoShape::Big();
01232 if (iact==1 && step<*safe) return TGeoShape::Big();
01233 }
01234 TGeoBoolNode *node = (TGeoBoolNode*)this;
01235 Double_t lpt[3], rpt[3], master[3], ldir[3], rdir[3];
01236 memcpy(master, point, 3*sizeof(Double_t));
01237 Int_t i;
01238 Double_t d1 = 0.;
01239 Double_t d2 = 0.;
01240 fLeftMat->MasterToLocal(point, lpt);
01241 fRightMat->MasterToLocal(point, rpt);
01242 fLeftMat->MasterToLocalVect(dir, ldir);
01243 fRightMat->MasterToLocalVect(dir, rdir);
01244 Bool_t inleft = fLeft->Contains(lpt);
01245 Bool_t inright = fRight->Contains(rpt);
01246 node->SetSelected(0);
01247 Double_t snext = 0.0;
01248 if (inleft && inright) return snext;
01249
01250 while (1) {
01251 d1 = d2 = 0.0;
01252 if (!inleft) {
01253 d1 = fLeft->DistFromOutside(lpt,ldir,3);
01254 if (d1>1E20) return TGeoShape::Big();
01255 }
01256 if (!inright) {
01257 d2 = fRight->DistFromOutside(rpt,rdir,3);
01258 if (d2>1E20) return TGeoShape::Big();
01259 }
01260
01261 if (d1>d2) {
01262
01263 snext += d1;
01264 node->SetSelected(1);
01265 inleft = kTRUE;
01266 for (i=0; i<3; i++) master[i] += d1*dir[i];
01267 fRightMat->MasterToLocal(master,rpt);
01268
01269 for (i=0; i<3; i++) rpt[i] += tol*rdir[i];
01270
01271 inright = fRight->Contains(rpt);
01272 if (inright) return snext;
01273
01274 } else {
01275
01276 snext += d2;
01277 node->SetSelected(2);
01278 inright = kTRUE;
01279 for (i=0; i<3; i++) master[i] += d2*dir[i];
01280 fLeftMat->MasterToLocal(master,lpt);
01281
01282 for (i=0; i<3; i++) lpt[i] += tol*ldir[i];
01283
01284 inleft = fLeft->Contains(lpt);
01285 if (inleft) return snext;
01286
01287 }
01288 }
01289 return snext;
01290 }
01291
01292
01293 Int_t TGeoIntersection::GetNpoints()
01294 {
01295
01296 Int_t itot=0;
01297 Double_t point[3];
01298 Double_t tolerance = TGeoShape::Tolerance();
01299 if (fNpoints) return fNpoints;
01300 Int_t nleft = fLeft->GetNmeshVertices();
01301 Int_t nright = fRight->GetNmeshVertices();
01302 Double_t *points = new Double_t[3*(nleft+nright)];
01303 Double_t *points1 = new Double_t[3*nleft];
01304 fLeft->SetPoints(points1);
01305 for (Int_t i=0; i<nleft; i++) {
01306 if (TMath::Abs(points1[3*i])<tolerance && TMath::Abs(points1[3*i+1])<tolerance) continue;
01307 fLeftMat->LocalToMaster(&points1[3*i], &points[3*itot]);
01308 fRightMat->MasterToLocal(&points[3*itot], point);
01309 if (fRight->Contains(point)) itot++;
01310 }
01311 Double_t *points2 = new Double_t[3*nright];
01312 fRight->SetPoints(points2);
01313 for (Int_t i=0; i<nright; i++) {
01314 if (TMath::Abs(points2[3*i])<tolerance && TMath::Abs(points2[3*i+1])<tolerance) continue;
01315 fRightMat->LocalToMaster(&points2[3*i], &points[3*itot]);
01316 fLeftMat->MasterToLocal(&points[3*itot], point);
01317 if (fLeft->Contains(point)) itot++;
01318 }
01319 fNpoints = itot;
01320 fPoints = new Double_t[3*fNpoints];
01321 memcpy(fPoints, points, 3*fNpoints*sizeof(Double_t));
01322 delete [] points1;
01323 delete [] points2;
01324 delete [] points;
01325 return fNpoints;
01326 }
01327
01328
01329 Double_t TGeoIntersection::Safety(Double_t *point, Bool_t in) const
01330 {
01331
01332 Double_t local1[3], local2[3];
01333 fLeftMat->MasterToLocal(point,local1);
01334 Bool_t in1 = fLeft->Contains(local1);
01335 fRightMat->MasterToLocal(point,local2);
01336 Bool_t in2 = fRight->Contains(local2);
01337 Bool_t intrue = in1 & in2;
01338 if (in^intrue) return 0.0;
01339 Double_t saf1 = fLeft->Safety(local1, in1);
01340 Double_t saf2 = fRight->Safety(local2, in2);
01341 if (in1 && in2) return TMath::Min(saf1, saf2);
01342 if (in1) return saf2;
01343 if (in2) return saf1;
01344 return TMath::Max(saf1,saf2);
01345 }
01346
01347
01348 void TGeoIntersection::SavePrimitive(ostream &out, Option_t *option )
01349 {
01350
01351 TGeoBoolNode::SavePrimitive(out,option);
01352 out << " pBoolNode = new TGeoIntersection(";
01353 out << fLeft->GetPointerName() << ",";
01354 out << fRight->GetPointerName() << ",";
01355 if (!fLeftMat->IsIdentity()) out << fLeftMat->GetPointerName() << ",";
01356 else out << "0,";
01357 if (!fRightMat->IsIdentity()) out << fRightMat->GetPointerName() << ");" << endl;
01358 else out << "0);" << endl;
01359 }
01360
01361
01362 void TGeoIntersection::Sizeof3D() const
01363 {
01364
01365 TGeoBoolNode::Sizeof3D();
01366 }