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 #include "G4PhantomParameterisation.hh"
00037
00038 #include "globals.hh"
00039 #include "G4VSolid.hh"
00040 #include "G4VPhysicalVolume.hh"
00041 #include "G4LogicalVolume.hh"
00042 #include "G4VVolumeMaterialScanner.hh"
00043 #include "G4GeometryTolerance.hh"
00044
00045
00046 G4PhantomParameterisation::G4PhantomParameterisation()
00047 : fVoxelHalfX(0.), fVoxelHalfY(0.), fVoxelHalfZ(0.),
00048 fNoVoxelX(0), fNoVoxelY(0), fNoVoxelZ(0), fNoVoxelXY(0), fNoVoxel(0),
00049 fMaterialIndices(0), fContainerSolid(0),
00050 fContainerWallX(0.), fContainerWallY(0.), fContainerWallZ(0.),
00051 bSkipEqualMaterials(true)
00052 {
00053 kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
00054 }
00055
00056
00057
00058 G4PhantomParameterisation::~G4PhantomParameterisation()
00059 {
00060 }
00061
00062
00063
00064 void G4PhantomParameterisation::
00065 BuildContainerSolid( G4VPhysicalVolume *pMotherPhysical )
00066 {
00067 fContainerSolid = pMotherPhysical->GetLogicalVolume()->GetSolid();
00068 fContainerWallX = fNoVoxelX * fVoxelHalfX;
00069 fContainerWallY = fNoVoxelY * fVoxelHalfY;
00070 fContainerWallZ = fNoVoxelZ * fVoxelHalfZ;
00071
00072
00073 }
00074
00075
00076 void G4PhantomParameterisation::
00077 BuildContainerSolid( G4VSolid *pMotherSolid )
00078 {
00079 fContainerSolid = pMotherSolid;
00080 fContainerWallX = fNoVoxelX * fVoxelHalfX;
00081 fContainerWallY = fNoVoxelY * fVoxelHalfY;
00082 fContainerWallZ = fNoVoxelZ * fVoxelHalfZ;
00083
00084
00085 }
00086
00087
00088
00089 void G4PhantomParameterisation::
00090 ComputeTransformation(const G4int copyNo, G4VPhysicalVolume *physVol ) const
00091 {
00092
00093
00094 G4ThreeVector trans = GetTranslation( copyNo );
00095
00096 physVol->SetTranslation( trans );
00097 }
00098
00099
00100
00101 G4ThreeVector G4PhantomParameterisation::
00102 GetTranslation(const G4int copyNo ) const
00103 {
00104 CheckCopyNo( copyNo );
00105
00106 size_t nx;
00107 size_t ny;
00108 size_t nz;
00109
00110 ComputeVoxelIndices( copyNo, nx, ny, nz );
00111
00112 G4ThreeVector trans( (2*nx+1)*fVoxelHalfX - fContainerWallX,
00113 (2*ny+1)*fVoxelHalfY - fContainerWallY,
00114 (2*nz+1)*fVoxelHalfZ - fContainerWallZ);
00115 return trans;
00116 }
00117
00118
00119
00120 G4VSolid* G4PhantomParameterisation::
00121 ComputeSolid(const G4int, G4VPhysicalVolume *pPhysicalVol)
00122 {
00123 return pPhysicalVol->GetLogicalVolume()->GetSolid();
00124 }
00125
00126
00127
00128 G4Material* G4PhantomParameterisation::
00129 ComputeMaterial(const G4int copyNo, G4VPhysicalVolume *, const G4VTouchable *)
00130 {
00131 CheckCopyNo( copyNo );
00132 size_t matIndex = GetMaterialIndex(copyNo);
00133
00134 return fMaterials[ matIndex ];
00135 }
00136
00137
00138
00139 size_t G4PhantomParameterisation::
00140 GetMaterialIndex( size_t copyNo ) const
00141 {
00142 CheckCopyNo( copyNo );
00143
00144 if( !fMaterialIndices ) { return 0; }
00145 return *(fMaterialIndices+copyNo);
00146 }
00147
00148
00149
00150 size_t G4PhantomParameterisation::
00151 GetMaterialIndex( size_t nx, size_t ny, size_t nz ) const
00152 {
00153 size_t copyNo = nx + fNoVoxelX*ny + fNoVoxelXY*nz;
00154 return GetMaterialIndex( copyNo );
00155 }
00156
00157
00158
00159 G4Material* G4PhantomParameterisation::GetMaterial( size_t nx, size_t ny, size_t nz) const
00160 {
00161 return fMaterials[GetMaterialIndex(nx,ny,nz)];
00162 }
00163
00164
00165 G4Material* G4PhantomParameterisation::GetMaterial( size_t copyNo ) const
00166 {
00167 return fMaterials[GetMaterialIndex(copyNo)];
00168 }
00169
00170
00171 void G4PhantomParameterisation::
00172 ComputeVoxelIndices(const G4int copyNo, size_t& nx,
00173 size_t& ny, size_t& nz ) const
00174 {
00175 CheckCopyNo( copyNo );
00176 nx = size_t(copyNo%fNoVoxelX);
00177 ny = size_t( (copyNo/fNoVoxelX)%fNoVoxelY );
00178 nz = size_t(copyNo/fNoVoxelXY);
00179 }
00180
00181
00182
00183 void G4PhantomParameterisation::
00184 CheckVoxelsFillContainer( G4double contX, G4double contY, G4double contZ ) const
00185 {
00186 G4double toleranceForWarning = 0.25*kCarTolerance;
00187
00188
00189
00190
00191
00192
00193 G4double toleranceForError = 1.*kCarTolerance;
00194
00195
00196
00197 if( std::fabs(contX-fNoVoxelX*fVoxelHalfX) >= toleranceForError
00198 || std::fabs(contY-fNoVoxelY*fVoxelHalfY) >= toleranceForError
00199 || std::fabs(contZ-fNoVoxelZ*fVoxelHalfZ) >= toleranceForError )
00200 {
00201 std::ostringstream message;
00202 message << "Voxels do not fully fill the container: "
00203 << fContainerSolid->GetName() << G4endl
00204 << " DiffX= " << contX-fNoVoxelX*fVoxelHalfX << G4endl
00205 << " DiffY= " << contY-fNoVoxelY*fVoxelHalfY << G4endl
00206 << " DiffZ= " << contZ-fNoVoxelZ*fVoxelHalfZ << G4endl
00207 << " Maximum difference is: " << toleranceForError;
00208 G4Exception("G4PhantomParameterisation::CheckVoxelsFillContainer()",
00209 "GeomNav0002", FatalException, message);
00210
00211 }
00212 else if( std::fabs(contX-fNoVoxelX*fVoxelHalfX) >= toleranceForWarning
00213 || std::fabs(contY-fNoVoxelY*fVoxelHalfY) >= toleranceForWarning
00214 || std::fabs(contZ-fNoVoxelZ*fVoxelHalfZ) >= toleranceForWarning )
00215 {
00216 std::ostringstream message;
00217 message << "Voxels do not fully fill the container: "
00218 << fContainerSolid->GetName() << G4endl
00219 << " DiffX= " << contX-fNoVoxelX*fVoxelHalfX << G4endl
00220 << " DiffY= " << contY-fNoVoxelY*fVoxelHalfY << G4endl
00221 << " DiffZ= " << contZ-fNoVoxelZ*fVoxelHalfZ << G4endl
00222 << " Maximum difference is: " << toleranceForWarning;
00223 G4Exception("G4PhantomParameterisation::CheckVoxelsFillContainer()",
00224 "GeomNav1002", JustWarning, message);
00225 }
00226 }
00227
00228
00229
00230 G4int G4PhantomParameterisation::
00231 GetReplicaNo( const G4ThreeVector& localPoint, const G4ThreeVector& localDir )
00232 {
00233
00234
00235
00236 if( fContainerSolid->Inside( localPoint ) == kOutside )
00237 {
00238 std::ostringstream message;
00239 message << "Point outside voxels!" << G4endl
00240 << " localPoint - " << localPoint
00241 << " - is outside container solid: "
00242 << fContainerSolid->GetName() << G4endl;
00243 G4Exception("G4PhantomParameterisation::GetReplicaNo()", "GeomNav0003",
00244 FatalErrorInArgument, message);
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 G4double fx = (localPoint.x()+fContainerWallX+kCarTolerance)/(fVoxelHalfX*2.);
00260 G4int nx = G4int(fx);
00261
00262 G4double fy = (localPoint.y()+fContainerWallY+kCarTolerance)/(fVoxelHalfY*2.);
00263 G4int ny = G4int(fy);
00264
00265 G4double fz = (localPoint.z()+fContainerWallZ+kCarTolerance)/(fVoxelHalfZ*2.);
00266 G4int nz = G4int(fz);
00267
00268
00269
00270
00271
00272
00273
00274
00275 if( fx - nx < kCarTolerance/fVoxelHalfX )
00276 {
00277 if( localDir.x() < 0 )
00278 {
00279 if( nx != 0 )
00280 {
00281 nx -= 1;
00282 }
00283 }
00284 else
00285 {
00286 if( nx == G4int(fNoVoxelX) )
00287 {
00288 nx -= 1;
00289 }
00290 }
00291 }
00292 if( fy - ny < kCarTolerance/fVoxelHalfY )
00293 {
00294 if( localDir.y() < 0 )
00295 {
00296 if( ny != 0 )
00297 {
00298 ny -= 1;
00299 }
00300 }
00301 else
00302 {
00303 if( ny == G4int(fNoVoxelY) )
00304 {
00305 ny -= 1;
00306 }
00307 }
00308 }
00309 if( fz - nz < kCarTolerance/fVoxelHalfZ )
00310 {
00311 if( localDir.z() < 0 )
00312 {
00313 if( nz != 0 )
00314 {
00315 nz -= 1;
00316 }
00317 }
00318 else
00319 {
00320 if( nz == G4int(fNoVoxelZ) )
00321 {
00322 nz -= 1;
00323 }
00324 }
00325 }
00326
00327 G4int copyNo = nx + fNoVoxelX*ny + fNoVoxelXY*nz;
00328
00329
00330
00331 G4bool isOK = true;
00332 if( nx < 0 )
00333 {
00334 nx = 0;
00335 isOK = false;
00336 }
00337 else if( nx >= G4int(fNoVoxelX) )
00338 {
00339 nx = fNoVoxelX-1;
00340 isOK = false;
00341 }
00342 if( ny < 0 )
00343 {
00344 ny = 0;
00345 isOK = false;
00346 }
00347 else if( ny >= G4int(fNoVoxelY) )
00348 {
00349 ny = fNoVoxelY-1;
00350 isOK = false;
00351 }
00352 if( nz < 0 )
00353 {
00354 nz = 0;
00355 isOK = false;
00356 }
00357 else if( nz >= G4int(fNoVoxelZ) )
00358 {
00359 nz = fNoVoxelZ-1;
00360 isOK = false;
00361 }
00362 if( !isOK )
00363 {
00364 std::ostringstream message;
00365 message << "Corrected the copy number! It was negative or too big" << G4endl
00366 << " LocalPoint: " << localPoint << G4endl
00367 << " LocalDir: " << localDir << G4endl
00368 << " Voxel container size: " << fContainerWallX
00369 << " " << fContainerWallY << " " << fContainerWallZ << G4endl
00370 << " LocalPoint - wall: "
00371 << localPoint.x()-fContainerWallX << " "
00372 << localPoint.y()-fContainerWallY << " "
00373 << localPoint.z()-fContainerWallZ;
00374 G4Exception("G4PhantomParameterisation::GetReplicaNo()",
00375 "GeomNav1002", JustWarning, message);
00376 copyNo = nx + fNoVoxelX*ny + fNoVoxelXY*nz;
00377 }
00378
00379
00380
00381 return copyNo;
00382 }
00383
00384
00385
00386 void G4PhantomParameterisation::CheckCopyNo( const G4int copyNo ) const
00387 {
00388 if( copyNo < 0 || copyNo >= G4int(fNoVoxel) )
00389 {
00390 std::ostringstream message;
00391 message << "Copy number is negative or too big!" << G4endl
00392 << " Copy number: " << copyNo << G4endl
00393 << " Total number of voxels: " << fNoVoxel;
00394 G4Exception("G4PhantomParameterisation::CheckCopyNo()",
00395 "GeomNav0002", FatalErrorInArgument, message);
00396 }
00397 }