G4UnionSolid.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * License and Disclaimer                                           *
00004 // *                                                                  *
00005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
00006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
00007 // * conditions of the Geant4 Software License,  included in the file *
00008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
00009 // * include a list of copyright holders.                             *
00010 // *                                                                  *
00011 // * Neither the authors of this software system, nor their employing *
00012 // * institutes,nor the agencies providing financial support for this *
00013 // * work  make  any representation or  warranty, express or implied, *
00014 // * regarding  this  software system or assume any liability for its *
00015 // * use.  Please see the license in the file  LICENSE  and URL above *
00016 // * for the full disclaimer and the limitation of liability.         *
00017 // *                                                                  *
00018 // * This  code  implementation is the result of  the  scientific and *
00019 // * technical work of the GEANT4 collaboration.                      *
00020 // * By using,  copying,  modifying or  distributing the software (or *
00021 // * any work based  on the software)  you  agree  to acknowledge its *
00022 // * use  in  resulting  scientific  publications,  and indicate your *
00023 // * acceptance of all terms of the Geant4 Software license.          *
00024 // ********************************************************************
00025 //
00026 //
00027 // $Id$
00028 //
00029 // Implementation of methods for the class G4IntersectionSolid
00030 //
00031 // History:
00032 //
00033 // 12.09.98 V.Grichine: first implementation
00034 // 28.11.98 V.Grichine: fix while loops in DistToIn/Out 
00035 // 27.07.99 V.Grichine: modifications in DistToOut(p,v,...), while -> do-while
00036 // 16.03.01 V.Grichine: modifications in CalculateExtent()
00037 //
00038 // --------------------------------------------------------------------
00039 
00040 #include <sstream>
00041 
00042 #include "G4UnionSolid.hh"
00043 
00044 #include "G4SystemOfUnits.hh"
00045 #include "G4VoxelLimits.hh"
00046 #include "G4VPVParameterisation.hh"
00047 #include "G4GeometryTolerance.hh"
00048 
00049 #include "G4VGraphicsScene.hh"
00050 #include "G4Polyhedron.hh"
00051 #include "HepPolyhedronProcessor.h"
00052 #include "G4NURBS.hh"
00053 // #include "G4NURBSbox.hh"
00054 
00056 //
00057 // Transfer all data members to G4BooleanSolid which is responsible
00058 // for them. pName will be in turn sent to G4VSolid
00059 
00060 G4UnionSolid:: G4UnionSolid( const G4String& pName,
00061                                    G4VSolid* pSolidA ,
00062                                    G4VSolid* pSolidB )
00063   : G4BooleanSolid(pName,pSolidA,pSolidB)
00064 {
00065 }
00066 
00068 //
00069 // Constructor
00070  
00071 G4UnionSolid::G4UnionSolid( const G4String& pName,
00072                                   G4VSolid* pSolidA ,
00073                                   G4VSolid* pSolidB ,
00074                                   G4RotationMatrix* rotMatrix,
00075                             const G4ThreeVector& transVector )
00076   : G4BooleanSolid(pName,pSolidA,pSolidB,rotMatrix,transVector)
00077 
00078 {
00079 }
00080 
00082 //
00083 // Constructor
00084  
00085 G4UnionSolid::G4UnionSolid( const G4String& pName,
00086                                   G4VSolid* pSolidA ,
00087                                   G4VSolid* pSolidB ,
00088                             const G4Transform3D& transform )
00089   : G4BooleanSolid(pName,pSolidA,pSolidB,transform)
00090 {
00091 } 
00092 
00094 //
00095 // Fake default constructor - sets only member data and allocates memory
00096 //                            for usage restricted to object persistency.
00097 
00098 G4UnionSolid::G4UnionSolid( __void__& a )
00099   : G4BooleanSolid(a)
00100 {
00101 }
00102 
00104 //
00105 // Destructor
00106 
00107 G4UnionSolid::~G4UnionSolid()
00108 {
00109 }
00110 
00112 //
00113 // Copy constructor
00114 
00115 G4UnionSolid::G4UnionSolid(const G4UnionSolid& rhs)
00116   : G4BooleanSolid (rhs)
00117 {
00118 }
00119 
00121 //
00122 // Assignment operator
00123 
00124 G4UnionSolid& G4UnionSolid::operator = (const G4UnionSolid& rhs) 
00125 {
00126   // Check assignment to self
00127   //
00128   if (this == &rhs)  { return *this; }
00129 
00130   // Copy base class data
00131   //
00132   G4BooleanSolid::operator=(rhs);
00133 
00134   return *this;
00135 }  
00136 
00138 //
00139 //
00140      
00141 G4bool 
00142 G4UnionSolid::CalculateExtent( const EAxis pAxis,
00143                                const G4VoxelLimits& pVoxelLimit,
00144                                const G4AffineTransform& pTransform,
00145                                      G4double& pMin,
00146                                      G4double& pMax ) const 
00147 {
00148   G4bool   touchesA, touchesB, out ;
00149   G4double minA =  kInfinity, minB =  kInfinity, 
00150            maxA = -kInfinity, maxB = -kInfinity; 
00151 
00152   touchesA = fPtrSolidA->CalculateExtent( pAxis, pVoxelLimit, 
00153                                           pTransform, minA, maxA);
00154   touchesB= fPtrSolidB->CalculateExtent( pAxis, pVoxelLimit, 
00155                                          pTransform, minB, maxB);
00156   if( touchesA || touchesB )
00157   {
00158     pMin = std::min( minA, minB ); 
00159     pMax = std::max( maxA, maxB );
00160     out  = true ; 
00161   }
00162   else out = false ;
00163 
00164   return out ;  // It exists in this slice if either one does.
00165 }
00166  
00168 //
00169 // Important comment: When solids A and B touch together along flat
00170 // surface the surface points will be considered as kSurface, while points 
00171 // located around will correspond to kInside
00172 
00173 EInside G4UnionSolid::Inside( const G4ThreeVector& p ) const
00174 {
00175   EInside positionA = fPtrSolidA->Inside(p);
00176   if (positionA == kInside)  { return kInside; }
00177 
00178   EInside positionB = fPtrSolidB->Inside(p);
00179 
00180   if( positionB == kInside  ||
00181     ( positionA == kSurface && positionB == kSurface &&
00182         ( fPtrSolidA->SurfaceNormal(p) + 
00183           fPtrSolidB->SurfaceNormal(p) ).mag2() < 
00184           1000*G4GeometryTolerance::GetInstance()->GetRadialTolerance() ) )
00185   {
00186     return kInside;
00187   }
00188   else
00189   {
00190     if( ( positionB == kSurface ) || ( positionA == kSurface ) )
00191       { return kSurface; }
00192     else
00193       { return kOutside; } 
00194   }
00195 }
00196 
00198 //
00199 //
00200 
00201 G4ThreeVector 
00202 G4UnionSolid::SurfaceNormal( const G4ThreeVector& p ) const 
00203 {
00204     G4ThreeVector normal;
00205 
00206 #ifdef G4BOOLDEBUG
00207     if( Inside(p) == kOutside )
00208     {
00209       G4cout << "WARNING - Invalid call in "
00210              << "G4UnionSolid::SurfaceNormal(p)" << G4endl
00211              << "  Point p is outside !" << G4endl;
00212       G4cout << "          p = " << p << G4endl;
00213       G4cerr << "WARNING - Invalid call in "
00214              << "G4UnionSolid::SurfaceNormal(p)" << G4endl
00215              << "  Point p is outside !" << G4endl;
00216       G4cerr << "          p = " << p << G4endl;
00217     }
00218 #endif
00219 
00220     if(fPtrSolidA->Inside(p) == kSurface && fPtrSolidB->Inside(p) != kInside) 
00221     {
00222        normal= fPtrSolidA->SurfaceNormal(p) ;
00223     }
00224     else if(fPtrSolidB->Inside(p) == kSurface && 
00225             fPtrSolidA->Inside(p) != kInside)
00226     {
00227        normal= fPtrSolidB->SurfaceNormal(p) ;
00228     }
00229     else 
00230     {
00231       normal= fPtrSolidA->SurfaceNormal(p) ;
00232 #ifdef G4BOOLDEBUG
00233       if(Inside(p)==kInside)
00234       {
00235         G4cout << "WARNING - Invalid call in "
00236              << "G4UnionSolid::SurfaceNormal(p)" << G4endl
00237              << "  Point p is inside !" << G4endl;
00238         G4cout << "          p = " << p << G4endl;
00239         G4cerr << "WARNING - Invalid call in "
00240              << "G4UnionSolid::SurfaceNormal(p)" << G4endl
00241              << "  Point p is inside !" << G4endl;
00242         G4cerr << "          p = " << p << G4endl;
00243       }
00244 #endif
00245     }
00246     return normal;
00247 }
00248 
00250 //
00251 // The same algorithm as in DistanceToIn(p)
00252 
00253 G4double 
00254 G4UnionSolid::DistanceToIn( const G4ThreeVector& p,
00255                                    const G4ThreeVector& v  ) const 
00256 {
00257 #ifdef G4BOOLDEBUG
00258   if( Inside(p) == kInside )
00259   {
00260     G4cout << "WARNING - Invalid call in "
00261            << "G4UnionSolid::DistanceToIn(p,v)" << G4endl
00262            << "  Point p is inside !" << G4endl;
00263     G4cout << "          p = " << p << G4endl;
00264     G4cout << "          v = " << v << G4endl;
00265     G4cerr << "WARNING - Invalid call in "
00266            << "G4UnionSolid::DistanceToIn(p,v)" << G4endl
00267            << "  Point p is inside !" << G4endl;
00268     G4cerr << "          p = " << p << G4endl;
00269     G4cerr << "          v = " << v << G4endl;
00270   }
00271 #endif
00272 
00273   return std::min(fPtrSolidA->DistanceToIn(p,v),
00274                     fPtrSolidB->DistanceToIn(p,v) ) ;
00275 }
00276 
00278 //
00279 // Approximate nearest distance from the point p to the union of
00280 // two solids
00281 
00282 G4double 
00283 G4UnionSolid::DistanceToIn( const G4ThreeVector& p) const 
00284 {
00285 #ifdef G4BOOLDEBUG
00286   if( Inside(p) == kInside )
00287   {
00288     G4cout << "WARNING - Invalid call in "
00289            << "G4UnionSolid::DistanceToIn(p)" << G4endl
00290            << "  Point p is inside !" << G4endl;
00291     G4cout << "          p = " << p << G4endl;
00292     G4cerr << "WARNING - Invalid call in "
00293            << "G4UnionSolid::DistanceToIn(p)" << G4endl
00294            << "  Point p is inside !" << G4endl;
00295     G4cerr << "          p = " << p << G4endl;
00296   }
00297 #endif
00298   G4double distA = fPtrSolidA->DistanceToIn(p) ;
00299   G4double distB = fPtrSolidB->DistanceToIn(p) ;
00300   G4double safety = std::min(distA,distB) ;
00301   if(safety < 0.0) safety = 0.0 ;
00302   return safety ;
00303 }
00304 
00306 //
00307 // The same algorithm as DistanceToOut(p)
00308 
00309 G4double 
00310 G4UnionSolid::DistanceToOut( const G4ThreeVector& p,
00311            const G4ThreeVector& v,
00312            const G4bool calcNorm,
00313                  G4bool *validNorm,
00314                  G4ThreeVector *n      ) const 
00315 {
00316   G4double  dist = 0.0, disTmp = 0.0 ;
00317   G4ThreeVector normTmp;
00318   G4ThreeVector* nTmp= &normTmp;
00319 
00320   if( Inside(p) == kOutside )
00321   {
00322 #ifdef G4BOOLDEBUG
00323       G4cout << "Position:"  << G4endl << G4endl;
00324       G4cout << "p.x() = "   << p.x()/mm << " mm" << G4endl;
00325       G4cout << "p.y() = "   << p.y()/mm << " mm" << G4endl;
00326       G4cout << "p.z() = "   << p.z()/mm << " mm" << G4endl << G4endl;
00327       G4cout << "Direction:" << G4endl << G4endl;
00328       G4cout << "v.x() = "   << v.x() << G4endl;
00329       G4cout << "v.y() = "   << v.y() << G4endl;
00330       G4cout << "v.z() = "   << v.z() << G4endl << G4endl;
00331       G4cout << "WARNING - Invalid call in "
00332              << "G4UnionSolid::DistanceToOut(p,v)" << G4endl
00333              << "  Point p is outside !" << G4endl;
00334       G4cout << "          p = " << p << G4endl;
00335       G4cout << "          v = " << v << G4endl;
00336       G4cerr << "WARNING - Invalid call in "
00337              << "G4UnionSolid::DistanceToOut(p,v)" << G4endl
00338              << "  Point p is outside !" << G4endl;
00339       G4cerr << "          p = " << p << G4endl;
00340       G4cerr << "          v = " << v << G4endl;
00341 #endif
00342   }
00343   else
00344   {
00345     EInside positionA = fPtrSolidA->Inside(p) ;
00346     // EInside positionB = fPtrSolidB->Inside(p) ;
00347 
00348     if( positionA != kOutside )
00349     { 
00350       do
00351       {
00352         disTmp = fPtrSolidA->DistanceToOut(p+dist*v,v,calcNorm,
00353                                            validNorm,nTmp)        ;
00354         dist += disTmp ;
00355 
00356         if(fPtrSolidB->Inside(p+dist*v) != kOutside)
00357         { 
00358           disTmp = fPtrSolidB->DistanceToOut(p+dist*v,v,calcNorm,
00359                                             validNorm,nTmp)         ;
00360           dist += disTmp ;
00361         }
00362       }
00363       //     while( Inside(p+dist*v) == kInside ) ;
00364            while( fPtrSolidA->Inside(p+dist*v) != kOutside && 
00365                   disTmp > 0.5*kCarTolerance ) ;
00366     }
00367     else // if( positionB != kOutside )
00368     {
00369       do
00370       {
00371         disTmp = fPtrSolidB->DistanceToOut(p+dist*v,v,calcNorm,
00372                                            validNorm,nTmp)        ; 
00373         dist += disTmp ;
00374 
00375         if(fPtrSolidA->Inside(p+dist*v) != kOutside)
00376         { 
00377           disTmp = fPtrSolidA->DistanceToOut(p+dist*v,v,calcNorm,
00378                                             validNorm,nTmp)         ;
00379           dist += disTmp ;
00380         }
00381       }
00382       //  while( Inside(p+dist*v) == kInside ) ;
00383         while( (fPtrSolidB->Inside(p+dist*v) != kOutside)
00384             && (disTmp > 0.5*kCarTolerance) ) ;
00385     }
00386   }
00387   if( calcNorm )
00388   { 
00389      *validNorm = false ;
00390      *n         = *nTmp ;   
00391   }
00392   return dist ;
00393 }
00394 
00396 //
00397 // Inverted algorithm of DistanceToIn(p)
00398 
00399 G4double 
00400 G4UnionSolid::DistanceToOut( const G4ThreeVector& p ) const 
00401 {
00402   G4double distout = 0.0;
00403   if( Inside(p) == kOutside )
00404   {
00405 #ifdef G4BOOLDEBUG
00406     G4cout << "WARNING - Invalid call in "
00407            << "G4UnionSolid::DistanceToOut(p)" << G4endl
00408            << "  Point p is outside !" << G4endl;
00409     G4cout << "          p = " << p << G4endl;
00410     G4cerr << "WARNING - Invalid call in "
00411            << "G4UnionSolid::DistanceToOut(p)" << G4endl
00412            << "  Point p is outside !" << G4endl;
00413     G4cerr << "          p = " << p << G4endl;
00414 #endif
00415   }
00416   else
00417   {
00418     EInside positionA = fPtrSolidA->Inside(p) ;
00419     EInside positionB = fPtrSolidB->Inside(p) ;
00420   
00421     //  Is this equivalent ??
00422     //    if( ! (  (positionA == kOutside)) && 
00423     //             (positionB == kOutside))  ) 
00424     if((positionA == kInside  && positionB == kInside  ) ||
00425        (positionA == kInside  && positionB == kSurface ) ||
00426        (positionA == kSurface && positionB == kInside  )     )
00427     {     
00428       distout= std::max(fPtrSolidA->DistanceToOut(p),
00429                           fPtrSolidB->DistanceToOut(p) ) ;
00430     }
00431     else
00432     {
00433       if(positionA == kOutside)
00434       {
00435         distout= fPtrSolidB->DistanceToOut(p) ;
00436       }
00437       else
00438       {
00439         distout= fPtrSolidA->DistanceToOut(p) ;
00440       }
00441     }
00442   }
00443   return distout;
00444 }
00445 
00447 //
00448 //
00449 
00450 G4GeometryType G4UnionSolid::GetEntityType() const 
00451 {
00452   return G4String("G4UnionSolid");
00453 }
00454 
00456 //
00457 // Make a clone of the object
00458 
00459 G4VSolid* G4UnionSolid::Clone() const
00460 {
00461   return new G4UnionSolid(*this);
00462 }
00463 
00465 //
00466 //
00467 
00468 void 
00469 G4UnionSolid::ComputeDimensions(       G4VPVParameterisation*,
00470                                  const G4int,
00471                                  const G4VPhysicalVolume* ) 
00472 {
00473 }
00474 
00476 //
00477 //                    
00478 
00479 void 
00480 G4UnionSolid::DescribeYourselfTo ( G4VGraphicsScene& scene ) const 
00481 {
00482   scene.AddSolid (*this);
00483 }
00484 
00486 //
00487 //
00488 
00489 G4Polyhedron* 
00490 G4UnionSolid::CreatePolyhedron () const 
00491 {
00492   HepPolyhedronProcessor processor;
00493   // Stack components and components of components recursively
00494   // See G4BooleanSolid::StackPolyhedron
00495   G4Polyhedron* top = StackPolyhedron(processor, this);
00496   G4Polyhedron* result = new G4Polyhedron(*top);
00497   if (processor.execute(*result)) { return result; }
00498   else { return 0; }
00499 }
00500 
00502 //
00503 //
00504 
00505 G4NURBS*      
00506 G4UnionSolid::CreateNURBS      () const 
00507 {
00508   // Take into account boolean operation - see CreatePolyhedron.
00509   // return new G4NURBSbox (1.0, 1.0, 1.0);
00510   return 0;
00511 }

Generated on Mon May 27 17:50:07 2013 for Geant4 by  doxygen 1.4.7