00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #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
00054
00056
00057
00058
00059
00060 G4UnionSolid:: G4UnionSolid( const G4String& pName,
00061 G4VSolid* pSolidA ,
00062 G4VSolid* pSolidB )
00063 : G4BooleanSolid(pName,pSolidA,pSolidB)
00064 {
00065 }
00066
00068
00069
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
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
00096
00097
00098 G4UnionSolid::G4UnionSolid( __void__& a )
00099 : G4BooleanSolid(a)
00100 {
00101 }
00102
00104
00105
00106
00107 G4UnionSolid::~G4UnionSolid()
00108 {
00109 }
00110
00112
00113
00114
00115 G4UnionSolid::G4UnionSolid(const G4UnionSolid& rhs)
00116 : G4BooleanSolid (rhs)
00117 {
00118 }
00119
00121
00122
00123
00124 G4UnionSolid& G4UnionSolid::operator = (const G4UnionSolid& rhs)
00125 {
00126
00127
00128 if (this == &rhs) { return *this; }
00129
00130
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 ;
00165 }
00166
00168
00169
00170
00171
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
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
00280
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
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
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
00364 while( fPtrSolidA->Inside(p+dist*v) != kOutside &&
00365 disTmp > 0.5*kCarTolerance ) ;
00366 }
00367 else
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
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
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
00422
00423
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
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
00494
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
00509
00510 return 0;
00511 }