TGeoBoolNode.cxx

Go to the documentation of this file.
00001 // @(#):$Id: TGeoBoolNode.cxx 37482 2010-12-10 09:04:19Z agheata $
00002 // Author: Andrei Gheata   30/05/02
00003 // TGeoBoolNode::Contains and parser implemented by Mihaela Gheata
00004 
00005    
00006 /*************************************************************************
00007  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00008  * All rights reserved.                                                  *
00009  *                                                                       *
00010  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00011  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
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 //  TGeoBoolNode - base class for Boolean operations between two shapes.
00030 //===============
00031 // A Boolean node describes a Boolean operation between 'left' and 'right' 
00032 // shapes positioned with respect to an ARBITRARY reference frame. The boolean
00033 // node is referenced by a mother composite shape and its shape components may
00034 // be primitive but also composite shapes. The later situation leads to a binary
00035 // tree hierarchy. When the parent composite shape is used to create a volume,
00036 // the reference frame of the volume is chosen to match the frame in which 
00037 // node shape components were defined.
00038 //
00039 // The positioned shape components may or may not be disjoint. The specific 
00040 // implementations for Boolean nodes are:
00041 //
00042 //    TGeoUnion - representing the Boolean  union of two positioned shapes
00043 //
00044 //    TGeoSubtraction - representing the Boolean subtraction of two positioned 
00045 //                shapes
00046 // 
00047 //    TGeoIntersection - representing the Boolean intersection of two positioned
00048 //                shapes
00049 //_____________________________________________________________________________
00050 
00051 ClassImp(TGeoBoolNode)
00052 
00053 //______________________________________________________________________________
00054 TGeoBoolNode::TGeoBoolNode()
00055 {
00056 // Default constructor
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 // Constructor called by TGeoCompositeShape providing 2 subexpressions for the 2 branches.
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 // Constructor providing left and right shapes and matrices (in the Boolean operation).
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 // Destructor.
00114 // --- deletion of components handled by TGeoManager class.
00115    if (fPoints) delete [] fPoints;
00116 }
00117 
00118 //______________________________________________________________________________
00119 Bool_t TGeoBoolNode::MakeBranch(const char *expr, Bool_t left)
00120 {
00121 // Expands the boolean expression either on left or right branch, creating
00122 // component elements (composite shapes and boolean nodes). Returns true on success.
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          // elementary shape
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          // composite shape - union
00153          newshape = sleft;
00154          newshape += "+";
00155          newshape += sright;
00156          shape = new TGeoCompositeShape(newshape.Data());
00157          break;
00158       case 2:
00159          // composite shape - difference
00160          newshape = sleft;
00161          newshape += "-";
00162          newshape += sright;
00163          shape = new TGeoCompositeShape(newshape.Data());
00164          break;
00165       case 3:
00166          // composite shape - intersection
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 // Special schema for feeding the 3D buffers to the painter client.
00192    TVirtualViewer3D * viewer = gPad->GetViewer3D();
00193    if (!viewer) return;
00194 
00195    // Components of composite shape hierarchies for local frame viewers are painted 
00196    // in coordinate frame of the top level composite shape. So we force 
00197    // conversion to this.  See TGeoPainter::PaintNode for loading of GLMatrix.
00198    Bool_t localFrame = kFALSE; //viewer->PreferLocalFrame();
00199 
00200    TGeoHMatrix *glmat = (TGeoHMatrix*)TGeoShape::GetTransform();
00201    TGeoHMatrix mat;
00202    mat = glmat; // keep a copy
00203 
00204    // Now perform fetch and add of the two components buffers.
00205    // Note we assume that composite shapes are always completely added
00206    // so don't bother to get addDaughters flag from viewer->AddObject()
00207 
00208    // Setup matrix and fetch/add the left component buffer
00209    glmat->Multiply(fLeftMat);
00210    //fLeft->Paint(option);
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    // Setup matrix and fetch/add the right component buffer
00218    *glmat = &mat;
00219    glmat->Multiply(fRightMat);
00220    //fRight->Paint(option);
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 // Register all matrices of the boolean node and descendents.
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 // Save a primitive as a C++ statement(s) on output stream "out".
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 // Fill buffer with shape vertices.
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 // Fill buffer with shape vertices.
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 // Register size of this 3D object
00278    fLeft->Sizeof3D();
00279    fRight->Sizeof3D();
00280 }
00281 ClassImp(TGeoUnion)
00282 
00283 //______________________________________________________________________________
00284 void TGeoUnion::Paint(Option_t *option)
00285 {
00286 // Paint method.
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 // Default constructor
00303 }
00304 
00305 //______________________________________________________________________________
00306 TGeoUnion::TGeoUnion(const char *expr1, const char *expr2)
00307           :TGeoBoolNode(expr1, expr2)
00308 {
00309 // Constructor
00310 }
00311 
00312 //______________________________________________________________________________
00313 TGeoUnion::TGeoUnion(TGeoShape *left, TGeoShape *right, TGeoMatrix *lmat, TGeoMatrix *rmat)
00314           :TGeoBoolNode(left,right,lmat,rmat)
00315 {
00316 // Constructor providing pointers to components
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 // Destructor
00326 // --- deletion of components handled by TGeoManager class.
00327 }
00328 
00329 //______________________________________________________________________________
00330 void TGeoUnion::ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Double_t *origin)
00331 {
00332 // Compute bounding box corresponding to a union of two shapes.
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 // Find if a union of two shapes contains a given point
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 // Normal computation in POINT. The orientation is chosen so that DIR.dot.NORM>0.
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    // Propagate forward/backward to see which of the components is intersected first
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 /*px*/, Int_t /*py*/)
00439 {
00440 // Compute minimum distance to shape vertices.
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 // Computes distance from a given point inside the shape to its boundary.
00449    if (iact<3 && safe) {
00450       // compute safe distance
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    // May be a pathological case when the point is on the boundary
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             // propagate to exit of left shape
00496             inside1 = kFALSE;
00497             for (i=0; i<3; i++) master[i] += d1*dir[i];
00498             // check if propagated point is in right shape        
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             // propagate to exit of right shape
00508             inside2 = kFALSE;
00509             for (i=0; i<3; i++) master[i] += d2*dir[i];
00510             // check if propagated point is in left shape        
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          // propagate to exit of left shape
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          // check if propagated point is in right shape        
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          // propagate to exit of right shape
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          // check if propagated point is in left shape        
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 // Compute distance from a given outside point to the shape.
00561    if (iact<3 && safe) {
00562       // compute safe distance
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 // Returns number of vertices for the composite shape described by this union.
00590    Int_t itot=0;
00591    Double_t point[3];
00592    Double_t tolerance = TGeoShape::Tolerance();
00593    if (fNpoints) return fNpoints;
00594    // Local points for the left shape
00595    Int_t nleft = fLeft->GetNmeshVertices();
00596    Double_t *points1 = new Double_t[3*nleft];
00597    fLeft->SetPoints(points1);
00598    // Local points for the right shape
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 // Compute safety distance for a union node;
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 // Save a primitive as a C++ statement(s) on output stream "out".
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 // Register 3D size of this shape.
00661    TGeoBoolNode::Sizeof3D();
00662 }
00663    
00664 
00665 ClassImp(TGeoSubtraction)
00666 
00667 //______________________________________________________________________________
00668 void TGeoSubtraction::Paint(Option_t *option)
00669 {
00670 // Paint method.
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 // Default constructor
00687 }
00688 
00689 //______________________________________________________________________________
00690 TGeoSubtraction::TGeoSubtraction(const char *expr1, const char *expr2)
00691           :TGeoBoolNode(expr1, expr2)
00692 {
00693 // Constructor
00694 }
00695 
00696 //______________________________________________________________________________
00697 TGeoSubtraction::TGeoSubtraction(TGeoShape *left, TGeoShape *right, TGeoMatrix *lmat, TGeoMatrix *rmat)
00698                 :TGeoBoolNode(left,right,lmat,rmat)
00699 {
00700 // Constructor providing pointers to components
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 // Destructor
00710 // --- deletion of components handled by TGeoManager class.
00711 }
00712 
00713 //______________________________________________________________________________
00714 void TGeoSubtraction::ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Double_t *origin)
00715 {
00716 // Compute bounding box corresponding to a subtraction of two shapes.
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 // Normal computation in POINT. The orientation is chosen so that DIR.dot.NORM>0.
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    // point is inside left shape, but not inside the right
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 // Find if a subtraction of two shapes contains a given point
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 /*px*/, Int_t /*py*/)
00809 {
00810 // Compute minimum distance to shape vertices
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 // Compute distance from a given point inside to the shape boundary.
00819    if (iact<3 && safe) {
00820       // compute safe distance
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 // Compute distance from a given point outside to the shape.
00849    if (iact<3 && safe) {
00850       // compute safe distance
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    // check if inside '-'
00864    Bool_t inside = fRight->Contains(&local[0]);
00865    Double_t epsil = 0.;
00866    while (1) {
00867       if (inside) {
00868          // propagate to outside of '-'
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          // now master outside '-'; check if inside '+'
00875          fLeftMat->MasterToLocal(&master[0], &local[0]);
00876          if (fLeft->Contains(&local[0])) return snxt;
00877       } 
00878       // master outside '-' and outside '+' ;  find distances to both
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       // propagate to '-'
00891       snxt += d1+epsil;
00892       for (i=0; i<3; i++) master[i] += (d1+1E-8)*dir[i];
00893       epsil = 1.E-8;
00894       // now inside '-' and not inside '+'
00895       fRightMat->MasterToLocal(&master[0], &local[0]);
00896       inside = kTRUE;
00897    }
00898 }
00899 
00900 //______________________________________________________________________________
00901 Int_t TGeoSubtraction::GetNpoints()
00902 {
00903 // Returns number of vertices for the composite shape described by this subtraction.
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 // Compute safety distance for a union node;
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 // Save a primitive as a C++ statement(s) on output stream "out".
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 // Register 3D size of this shape.
00973    TGeoBoolNode::Sizeof3D();
00974 }
00975 
00976 ClassImp(TGeoIntersection)
00977 
00978 //______________________________________________________________________________
00979 void TGeoIntersection::Paint(Option_t *option)
00980 {
00981 // Paint method.
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 // Default constructor
00998 }
00999 
01000 //______________________________________________________________________________
01001 TGeoIntersection::TGeoIntersection(const char *expr1, const char *expr2)
01002           :TGeoBoolNode(expr1, expr2)
01003 {
01004 // Constructor
01005 }
01006 
01007 //______________________________________________________________________________
01008 TGeoIntersection::TGeoIntersection(TGeoShape *left, TGeoShape *right, TGeoMatrix *lmat, TGeoMatrix *rmat)
01009                  :TGeoBoolNode(left,right,lmat,rmat)
01010 {
01011 // Constructor providing pointers to components
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 // Destructor
01021 // --- deletion of components handled by TGeoManager class.
01022 }
01023 
01024 //______________________________________________________________________________
01025 void TGeoIntersection::ComputeBBox(Double_t &dx, Double_t &dy, Double_t &dz, Double_t *origin)
01026 {
01027 // Compute bounding box corresponding to a intersection of two shapes.
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 // Normal computation in POINT. The orientation is chosen so that DIR.dot.NORM>0.
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    // point is inside intersection.
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 // Find if a intersection of two shapes contains a given point
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 /*px*/, Int_t /*py*/)
01187 {
01188 // Compute minimum distance to shape vertices
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 // Compute distance from a given point inside to the shape boundary.
01197    if (iact<3 && safe) {
01198       // compute safe distance
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 // Compute distance from a given point outside to the shape.
01227    Double_t tol = TGeoShape::Tolerance();
01228    if (iact<3 && safe) {
01229       // compute safe distance
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          // propagate to left shape
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          // Push rpt to avoid a bad boundary condition
01269          for (i=0; i<3; i++) rpt[i] += tol*rdir[i];
01270          // check if propagated point is inside right shape
01271          inright = fRight->Contains(rpt);
01272          if (inright) return snext;
01273          // here inleft=true, inright=false         
01274       } else {
01275          // propagate to right shape
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          // Push lpt to avoid a bad boundary condition
01282          for (i=0; i<3; i++) lpt[i] += tol*ldir[i];
01283          // check if propagated point is inside left shape
01284          inleft = fLeft->Contains(lpt);
01285          if (inleft) return snext;
01286          // here inleft=false, inright=true
01287       }            
01288    }   
01289    return snext;
01290 }      
01291 
01292 //______________________________________________________________________________
01293 Int_t TGeoIntersection::GetNpoints()
01294 {
01295 // Returns number of vertices for the composite shape described by this intersection.
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 // Compute safety distance for a union node;
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 // Save a primitive as a C++ statement(s) on output stream "out".
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 // Register 3D size of this shape.
01365    TGeoBoolNode::Sizeof3D();
01366 }

Generated on Tue Jul 5 14:12:55 2011 for ROOT_528-00b_version by  doxygen 1.5.1