Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // class G4VoxelNavigation Implementation 26 // class G4VoxelNavigation Implementation 27 // 27 // 28 // Author: P.Kent, 1996 28 // Author: P.Kent, 1996 29 // 29 // 30 // ------------------------------------------- 30 // -------------------------------------------------------------------- >> 31 #include <ostream> >> 32 31 #include "G4VoxelNavigation.hh" 33 #include "G4VoxelNavigation.hh" 32 #include "G4GeometryTolerance.hh" 34 #include "G4GeometryTolerance.hh" 33 #include "G4VoxelSafety.hh" 35 #include "G4VoxelSafety.hh" 34 36 35 #include "G4AuxiliaryNavServices.hh" 37 #include "G4AuxiliaryNavServices.hh" 36 38 37 #include <cassert> << 38 #include <ostream> << 39 << 40 // ******************************************* 39 // ******************************************************************** 41 // Constructor 40 // Constructor 42 // ******************************************* 41 // ******************************************************************** 43 // 42 // 44 G4VoxelNavigation::G4VoxelNavigation() 43 G4VoxelNavigation::G4VoxelNavigation() 45 : fVoxelAxisStack(kNavigatorVoxelStackMax,kX << 44 : fBList(), >> 45 fVoxelAxisStack(kNavigatorVoxelStackMax,kXAxis), 46 fVoxelNoSlicesStack(kNavigatorVoxelStackMa 46 fVoxelNoSlicesStack(kNavigatorVoxelStackMax,0), 47 fVoxelSliceWidthStack(kNavigatorVoxelStack 47 fVoxelSliceWidthStack(kNavigatorVoxelStackMax,0.), 48 fVoxelNodeNoStack(kNavigatorVoxelStackMax, 48 fVoxelNodeNoStack(kNavigatorVoxelStackMax,0), 49 fVoxelHeaderStack(kNavigatorVoxelStackMax, 49 fVoxelHeaderStack(kNavigatorVoxelStackMax,(G4SmartVoxelHeader*)nullptr) 50 { 50 { 51 fLogger= new G4NavigationLogger("G4VoxelNavi 51 fLogger= new G4NavigationLogger("G4VoxelNavigation"); 52 fpVoxelSafety= new G4VoxelSafety(); 52 fpVoxelSafety= new G4VoxelSafety(); 53 fHalfTolerance= 0.5*G4GeometryTolerance::Get 53 fHalfTolerance= 0.5*G4GeometryTolerance::GetInstance()->GetSurfaceTolerance(); 54 54 55 #ifdef G4DEBUG_NAVIGATION 55 #ifdef G4DEBUG_NAVIGATION 56 SetVerboseLevel(5); // Reports most about 56 SetVerboseLevel(5); // Reports most about daughter volumes 57 #endif 57 #endif 58 } 58 } 59 59 60 // ******************************************* 60 // ******************************************************************** 61 // Destructor 61 // Destructor 62 // ******************************************* 62 // ******************************************************************** 63 // 63 // 64 G4VoxelNavigation::~G4VoxelNavigation() 64 G4VoxelNavigation::~G4VoxelNavigation() 65 { 65 { 66 delete fpVoxelSafety; 66 delete fpVoxelSafety; 67 delete fLogger; 67 delete fLogger; 68 } 68 } 69 69 70 // ------------------------------------------- << 71 // Input: << 72 // exiting: : last step exited << 73 // blockedPhysical : phys volume last exit << 74 // blockedReplicaNo : copy/replica number o << 75 // Output: << 76 // entering : if true, found candid << 77 // blockedPhysical : candidate phys volume << 78 // blockedReplicaNo : copy/replica number << 79 // exiting: : will exit current (mo << 80 // In/Out << 81 // ------------------------------------------- << 82 << 83 // ******************************************* 70 // ******************************************************************** 84 // ComputeStep 71 // ComputeStep 85 // ******************************************* 72 // ******************************************************************** 86 // 73 // 87 G4double 74 G4double 88 G4VoxelNavigation::ComputeStep( const G4ThreeV 75 G4VoxelNavigation::ComputeStep( const G4ThreeVector& localPoint, 89 const G4ThreeV 76 const G4ThreeVector& localDirection, 90 const G4double 77 const G4double currentProposedStepLength, 91 G4double 78 G4double& newSafety, 92 /* const */ G4Naviga << 79 G4NavigationHistory& history, 93 G4bool& 80 G4bool& validExitNormal, 94 G4ThreeV 81 G4ThreeVector& exitNormal, 95 G4bool& 82 G4bool& exiting, 96 G4bool& 83 G4bool& entering, 97 G4VPhysi 84 G4VPhysicalVolume* (*pBlockedPhysical), 98 G4int& b 85 G4int& blockedReplicaNo ) 99 { 86 { 100 G4VPhysicalVolume *motherPhysical, *samplePh 87 G4VPhysicalVolume *motherPhysical, *samplePhysical, *blockedExitedVol=nullptr; 101 G4LogicalVolume *motherLogical; 88 G4LogicalVolume *motherLogical; 102 G4VSolid *motherSolid; 89 G4VSolid *motherSolid; 103 G4ThreeVector sampleDirection; 90 G4ThreeVector sampleDirection; 104 G4double ourStep=currentProposedStepLength, 91 G4double ourStep=currentProposedStepLength, ourSafety; 105 G4double motherSafety, motherStep = DBL_MAX; 92 G4double motherSafety, motherStep = DBL_MAX; 106 G4int localNoDaughters, sampleNo; 93 G4int localNoDaughters, sampleNo; 107 94 108 G4bool initialNode, noStep; 95 G4bool initialNode, noStep; 109 G4SmartVoxelNode *curVoxelNode; 96 G4SmartVoxelNode *curVoxelNode; 110 G4long curNoVolumes, contentNo; << 97 G4int curNoVolumes, contentNo; 111 G4double voxelSafety; 98 G4double voxelSafety; 112 99 113 motherPhysical = history.GetTopVolume(); 100 motherPhysical = history.GetTopVolume(); 114 motherLogical = motherPhysical->GetLogicalVo 101 motherLogical = motherPhysical->GetLogicalVolume(); 115 motherSolid = motherLogical->GetSolid(); 102 motherSolid = motherLogical->GetSolid(); 116 103 117 // 104 // 118 // Compute mother safety 105 // Compute mother safety 119 // 106 // 120 107 121 motherSafety = motherSolid->DistanceToOut(lo 108 motherSafety = motherSolid->DistanceToOut(localPoint); 122 ourSafety = motherSafety; // 109 ourSafety = motherSafety; // Working isotropic safety 123 110 124 #ifdef G4VERBOSE 111 #ifdef G4VERBOSE 125 if ( fCheck ) 112 if ( fCheck ) 126 { 113 { 127 fLogger->PreComputeStepLog (motherPhysical 114 fLogger->PreComputeStepLog (motherPhysical, motherSafety, localPoint); 128 } 115 } 129 #endif 116 #endif 130 117 131 // 118 // 132 // Compute daughter safeties & intersections 119 // Compute daughter safeties & intersections 133 // 120 // 134 121 135 // Exiting normal optimisation 122 // Exiting normal optimisation 136 // 123 // 137 if ( exiting && validExitNormal ) 124 if ( exiting && validExitNormal ) 138 { 125 { 139 if ( localDirection.dot(exitNormal)>=kMinE 126 if ( localDirection.dot(exitNormal)>=kMinExitingNormalCosine ) 140 { 127 { 141 // Block exited daughter volume 128 // Block exited daughter volume 142 // 129 // 143 blockedExitedVol = *pBlockedPhysical; 130 blockedExitedVol = *pBlockedPhysical; 144 ourSafety = 0; 131 ourSafety = 0; 145 } 132 } 146 } 133 } 147 exiting = false; 134 exiting = false; 148 entering = false; 135 entering = false; 149 136 150 // For extra checking, get the distance to 137 // For extra checking, get the distance to Mother early !! 151 G4bool motherValidExitNormal = false; 138 G4bool motherValidExitNormal = false; 152 G4ThreeVector motherExitNormal(0.0, 0.0, 0.0 139 G4ThreeVector motherExitNormal(0.0, 0.0, 0.0); 153 140 154 #ifdef G4VERBOSE 141 #ifdef G4VERBOSE 155 if ( fCheck ) 142 if ( fCheck ) 156 { 143 { 157 // Compute early -- a) for validity 144 // Compute early -- a) for validity 158 // b) to check against an 145 // b) to check against answer of daughters! 159 motherStep = motherSolid->DistanceToOut(lo 146 motherStep = motherSolid->DistanceToOut(localPoint, 160 lo 147 localDirection, 161 tr 148 true, 162 &mo 149 &motherValidExitNormal, 163 &mo 150 &motherExitNormal); >> 151 >> 152 fLogger->PostComputeStepLog(motherSolid, localPoint, localDirection, >> 153 motherStep, motherSafety); >> 154 >> 155 if( (motherStep >= kInfinity) || (motherStep < 0.0) ) >> 156 { >> 157 // Error - indication of being outside solid !! >> 158 // >> 159 fLogger->ReportOutsideMother(localPoint, localDirection, motherPhysical); >> 160 >> 161 ourStep = 0.0; >> 162 >> 163 exiting = true; >> 164 entering = false; >> 165 >> 166 // validExitNormal= motherValidExitNormal; >> 167 // exitNormal= motherExitNormal; >> 168 // Makes sense and is useful only if the point is very close ... >> 169 // Alternatives: i) validExitNormal= false; >> 170 // ii) Check safety from outside and choose !! >> 171 validExitNormal = false; >> 172 >> 173 *pBlockedPhysical = nullptr; // or motherPhysical ? >> 174 blockedReplicaNo = 0; // or motherReplicaNumber ? >> 175 >> 176 newSafety = 0.0; >> 177 return ourStep; >> 178 } 164 } 179 } 165 #endif 180 #endif 166 181 167 localNoDaughters = (G4int)motherLogical->Get << 182 localNoDaughters = motherLogical->GetNoDaughters(); 168 183 169 fBList.Enlarge(localNoDaughters); 184 fBList.Enlarge(localNoDaughters); 170 fBList.Reset(); 185 fBList.Reset(); 171 186 172 initialNode = true; 187 initialNode = true; 173 noStep = true; 188 noStep = true; 174 189 175 while (noStep) 190 while (noStep) 176 { 191 { 177 curVoxelNode = fVoxelNode; 192 curVoxelNode = fVoxelNode; 178 curNoVolumes = curVoxelNode->GetNoContaine 193 curNoVolumes = curVoxelNode->GetNoContained(); 179 for (contentNo=curNoVolumes-1; contentNo>= 194 for (contentNo=curNoVolumes-1; contentNo>=0; contentNo--) 180 { 195 { 181 sampleNo = curVoxelNode->GetVolume((G4in << 196 sampleNo = curVoxelNode->GetVolume(contentNo); 182 if ( !fBList.IsBlocked(sampleNo) ) 197 if ( !fBList.IsBlocked(sampleNo) ) 183 { 198 { 184 fBList.BlockVolume(sampleNo); 199 fBList.BlockVolume(sampleNo); 185 samplePhysical = motherLogical->GetDau 200 samplePhysical = motherLogical->GetDaughter(sampleNo); 186 if ( samplePhysical!=blockedExitedVol 201 if ( samplePhysical!=blockedExitedVol ) 187 { 202 { 188 G4AffineTransform sampleTf(samplePhy 203 G4AffineTransform sampleTf(samplePhysical->GetRotation(), 189 samplePhy 204 samplePhysical->GetTranslation()); 190 sampleTf.Invert(); 205 sampleTf.Invert(); 191 const G4ThreeVector samplePoint = 206 const G4ThreeVector samplePoint = 192 sampleTf.TransformPoint(l 207 sampleTf.TransformPoint(localPoint); 193 const G4VSolid *sampleSolid = 208 const G4VSolid *sampleSolid = 194 samplePhysical->GetLogica 209 samplePhysical->GetLogicalVolume()->GetSolid(); 195 const G4double sampleSafety = 210 const G4double sampleSafety = 196 sampleSolid->DistanceToIn 211 sampleSolid->DistanceToIn(samplePoint); 197 212 198 if ( sampleSafety<ourSafety ) 213 if ( sampleSafety<ourSafety ) 199 { 214 { 200 ourSafety = sampleSafety; 215 ourSafety = sampleSafety; 201 } 216 } 202 if ( sampleSafety<=ourStep ) 217 if ( sampleSafety<=ourStep ) 203 { 218 { 204 sampleDirection = sampleTf.Transfo 219 sampleDirection = sampleTf.TransformAxis(localDirection); 205 G4double sampleStep = 220 G4double sampleStep = 206 sampleSolid->DistanceToIn 221 sampleSolid->DistanceToIn(samplePoint, sampleDirection); 207 #ifdef G4VERBOSE 222 #ifdef G4VERBOSE 208 if( fCheck ) 223 if( fCheck ) 209 { 224 { 210 fLogger->PrintDaughterLog(sample 225 fLogger->PrintDaughterLog(sampleSolid, samplePoint, 211 sample 226 sampleSafety, true, 212 sample 227 sampleDirection, sampleStep); 213 } 228 } 214 #endif 229 #endif 215 if ( sampleStep<=ourStep ) 230 if ( sampleStep<=ourStep ) 216 { 231 { 217 ourStep = sampleStep; 232 ourStep = sampleStep; 218 entering = true; 233 entering = true; 219 exiting = false; 234 exiting = false; 220 *pBlockedPhysical = samplePhysic 235 *pBlockedPhysical = samplePhysical; 221 blockedReplicaNo = -1; 236 blockedReplicaNo = -1; 222 #ifdef G4VERBOSE 237 #ifdef G4VERBOSE 223 // Check to see that the resulti 238 // Check to see that the resulting point is indeed in/on volume. 224 // This could be done only for s 239 // This could be done only for successful candidate. 225 if ( fCheck ) 240 if ( fCheck ) 226 { 241 { 227 fLogger->AlongComputeStepLog ( 242 fLogger->AlongComputeStepLog (sampleSolid, samplePoint, 228 sampleDirection, localDirect 243 sampleDirection, localDirection, sampleSafety, sampleStep); 229 } 244 } 230 #endif 245 #endif 231 } 246 } 232 #ifdef G4VERBOSE 247 #ifdef G4VERBOSE 233 if ( fCheck && ( sampleStep < kInf 248 if ( fCheck && ( sampleStep < kInfinity ) 234 && ( sampleStep >= mot 249 && ( sampleStep >= motherStep ) ) 235 { 250 { 236 // The intersection point with 251 // The intersection point with the daughter is after the exit 237 // point from the mother volume 252 // point from the mother volume. Double check this !! 238 fLogger->CheckDaughterEntryPoin 253 fLogger->CheckDaughterEntryPoint(sampleSolid, 239 254 samplePoint, sampleDirection, 240 255 motherSolid, 241 256 localPoint, localDirection, 242 257 motherStep, sampleStep); 243 } 258 } 244 #endif 259 #endif 245 } 260 } 246 #ifdef G4VERBOSE 261 #ifdef G4VERBOSE 247 else // ie if sampleSafety > outStep 262 else // ie if sampleSafety > outStep 248 { 263 { 249 if( fCheck ) 264 if( fCheck ) 250 { 265 { 251 fLogger->PrintDaughterLog(sample 266 fLogger->PrintDaughterLog(sampleSolid, samplePoint, 252 sample 267 sampleSafety, false, 253 G4Thre 268 G4ThreeVector(0.,0.,0.), -1.0 ); 254 } 269 } 255 } 270 } 256 #endif 271 #endif 257 } 272 } 258 } 273 } 259 } 274 } 260 if (initialNode) 275 if (initialNode) 261 { 276 { 262 initialNode = false; 277 initialNode = false; 263 voxelSafety = ComputeVoxelSafety(localPo 278 voxelSafety = ComputeVoxelSafety(localPoint); 264 if ( voxelSafety<ourSafety ) 279 if ( voxelSafety<ourSafety ) 265 { 280 { 266 ourSafety = voxelSafety; 281 ourSafety = voxelSafety; 267 } 282 } 268 if ( currentProposedStepLength<ourSafety 283 if ( currentProposedStepLength<ourSafety ) 269 { 284 { 270 // Guaranteed physics limited 285 // Guaranteed physics limited 271 // 286 // 272 noStep = false; 287 noStep = false; 273 entering = false; 288 entering = false; 274 exiting = false; 289 exiting = false; 275 *pBlockedPhysical = nullptr; 290 *pBlockedPhysical = nullptr; 276 ourStep = kInfinity; 291 ourStep = kInfinity; 277 } 292 } 278 else 293 else 279 { 294 { 280 // 295 // 281 // Compute mother intersection if requ 296 // Compute mother intersection if required 282 // 297 // 283 if ( motherSafety<=ourStep ) 298 if ( motherSafety<=ourStep ) 284 { 299 { 285 // In case of check mode this is a d << 300 if( !fCheck ) 286 motherStep = motherSolid->DistanceTo << 301 { >> 302 motherStep = motherSolid->DistanceToOut(localPoint, localDirection, 287 true, &motherVal 303 true, &motherValidExitNormal, &motherExitNormal); >> 304 } >> 305 // Not correct - unless mother limits step (see below) >> 306 // validExitNormal= motherValidExitNormal; >> 307 // exitNormal= motherExitNormal; 288 #ifdef G4VERBOSE 308 #ifdef G4VERBOSE 289 if ( fCheck ) << 309 else // check_mode 290 { 310 { 291 fLogger->PostComputeStepLog(mother 311 fLogger->PostComputeStepLog(motherSolid, localPoint, localDirection, 292 mother 312 motherStep, motherSafety); 293 if( motherValidExitNormal ) 313 if( motherValidExitNormal ) 294 { 314 { 295 fLogger->CheckAndReportBadNormal 315 fLogger->CheckAndReportBadNormal(motherExitNormal, 296 << 316 localPoint, localDirection, 297 << 317 motherStep, motherSolid, 298 "From 318 "From motherSolid::DistanceToOut" ); 299 } 319 } 300 } 320 } 301 #endif 321 #endif 302 if( (motherStep >= kInfinity) || (mo 322 if( (motherStep >= kInfinity) || (motherStep < 0.0) ) 303 { 323 { 304 #ifdef G4VERBOSE 324 #ifdef G4VERBOSE 305 if( fCheck ) // Error - indication 325 if( fCheck ) // Error - indication of being outside solid !! 306 { 326 { 307 fLogger->ReportOutsideMother(loc 327 fLogger->ReportOutsideMother(localPoint, localDirection, 308 mot 328 motherPhysical); 309 } 329 } 310 #endif 330 #endif 311 motherStep = 0.0; 331 motherStep = 0.0; 312 ourStep = 0.0; 332 ourStep = 0.0; 313 exiting = true; 333 exiting = true; 314 entering = false; 334 entering = false; 315 335 316 // validExitNormal= motherValidExi 336 // validExitNormal= motherValidExitNormal; 317 // exitNormal= motherExitNormal; 337 // exitNormal= motherExitNormal; 318 // Useful only if the point is ver 338 // Useful only if the point is very close to surface 319 // => but it would need to be rota 339 // => but it would need to be rotated to grand-mother ref frame ! 320 validExitNormal= false; 340 validExitNormal= false; 321 341 322 *pBlockedPhysical = nullptr; // or 342 *pBlockedPhysical = nullptr; // or motherPhysical ? 323 blockedReplicaNo = 0; // or mothe 343 blockedReplicaNo = 0; // or motherReplicaNumber ? 324 344 325 newSafety = 0.0; 345 newSafety = 0.0; 326 return ourStep; 346 return ourStep; 327 } 347 } 328 348 329 if ( motherStep<=ourStep ) 349 if ( motherStep<=ourStep ) 330 { 350 { 331 ourStep = motherStep; 351 ourStep = motherStep; 332 exiting = true; 352 exiting = true; 333 entering = false; 353 entering = false; 334 354 335 // Exit normal: Natural location t 355 // Exit normal: Natural location to set these;confirmed short step 336 // 356 // 337 validExitNormal = motherValidExitN 357 validExitNormal = motherValidExitNormal; 338 exitNormal = motherExitNormal; 358 exitNormal = motherExitNormal; 339 359 340 if ( validExitNormal ) 360 if ( validExitNormal ) 341 { 361 { 342 const G4RotationMatrix *rot = mo 362 const G4RotationMatrix *rot = motherPhysical->GetRotation(); 343 if (rot != nullptr) << 363 if (rot) 344 { 364 { 345 exitNormal *= rot->inverse(); 365 exitNormal *= rot->inverse(); 346 #ifdef G4VERBOSE 366 #ifdef G4VERBOSE 347 if( fCheck ) 367 if( fCheck ) 348 { << 368 fLogger->CheckAndReportBadNormal(exitNormal, // rotated 349 fLogger->CheckAndReportBadNo << 369 motherExitNormal, // original 350 << 370 *rot, 351 << 371 "From RotationMatrix" ); 352 << 353 } << 354 #endif 372 #endif 355 } 373 } 356 } 374 } 357 } 375 } 358 else 376 else 359 { 377 { 360 validExitNormal = false; 378 validExitNormal = false; 361 } 379 } 362 } 380 } 363 } 381 } 364 newSafety = ourSafety; 382 newSafety = ourSafety; 365 } 383 } 366 if (noStep) 384 if (noStep) 367 { 385 { 368 noStep = LocateNextVoxel(localPoint, loc 386 noStep = LocateNextVoxel(localPoint, localDirection, ourStep); 369 } 387 } 370 } // end -while (noStep)- loop 388 } // end -while (noStep)- loop 371 389 372 return ourStep; 390 return ourStep; 373 } 391 } 374 392 375 // ******************************************* 393 // ******************************************************************** 376 // ComputeVoxelSafety 394 // ComputeVoxelSafety 377 // 395 // 378 // Computes safety from specified point to vox 396 // Computes safety from specified point to voxel boundaries 379 // using already located point 397 // using already located point 380 // o collected boundaries for most derived lev 398 // o collected boundaries for most derived level 381 // o adjacent boundaries for previous levels 399 // o adjacent boundaries for previous levels 382 // ******************************************* 400 // ******************************************************************** 383 // 401 // 384 G4double 402 G4double 385 G4VoxelNavigation::ComputeVoxelSafety(const G4 403 G4VoxelNavigation::ComputeVoxelSafety(const G4ThreeVector& localPoint) const 386 { 404 { 387 G4SmartVoxelHeader *curHeader; 405 G4SmartVoxelHeader *curHeader; 388 G4double voxelSafety, curNodeWidth; 406 G4double voxelSafety, curNodeWidth; 389 G4double curNodeOffset, minCurCommonDelta, m 407 G4double curNodeOffset, minCurCommonDelta, maxCurCommonDelta; 390 G4int minCurNodeNoDelta, maxCurNodeNoDelta; 408 G4int minCurNodeNoDelta, maxCurNodeNoDelta; 391 G4int localVoxelDepth, curNodeNo; 409 G4int localVoxelDepth, curNodeNo; 392 EAxis curHeaderAxis; 410 EAxis curHeaderAxis; 393 411 394 localVoxelDepth = fVoxelDepth; 412 localVoxelDepth = fVoxelDepth; 395 413 396 curHeader = fVoxelHeaderStack[localVoxelDept 414 curHeader = fVoxelHeaderStack[localVoxelDepth]; 397 curHeaderAxis = fVoxelAxisStack[localVoxelDe 415 curHeaderAxis = fVoxelAxisStack[localVoxelDepth]; 398 curNodeNo = fVoxelNodeNoStack[localVoxelDept 416 curNodeNo = fVoxelNodeNoStack[localVoxelDepth]; 399 curNodeWidth = fVoxelSliceWidthStack[localVo 417 curNodeWidth = fVoxelSliceWidthStack[localVoxelDepth]; 400 418 401 // Compute linear intersection distance to b 419 // Compute linear intersection distance to boundaries of max/min 402 // to collected nodes at current level 420 // to collected nodes at current level 403 // 421 // 404 curNodeOffset = curNodeNo*curNodeWidth; 422 curNodeOffset = curNodeNo*curNodeWidth; 405 maxCurNodeNoDelta = fVoxelNode->GetMaxEquiva 423 maxCurNodeNoDelta = fVoxelNode->GetMaxEquivalentSliceNo()-curNodeNo; 406 minCurNodeNoDelta = curNodeNo-fVoxelNode->Ge 424 minCurNodeNoDelta = curNodeNo-fVoxelNode->GetMinEquivalentSliceNo(); 407 minCurCommonDelta = localPoint(curHeaderAxis 425 minCurCommonDelta = localPoint(curHeaderAxis) 408 - curHeader->GetMinExten 426 - curHeader->GetMinExtent() - curNodeOffset; 409 maxCurCommonDelta = curNodeWidth-minCurCommo 427 maxCurCommonDelta = curNodeWidth-minCurCommonDelta; 410 428 411 if ( minCurNodeNoDelta<maxCurNodeNoDelta ) 429 if ( minCurNodeNoDelta<maxCurNodeNoDelta ) 412 { 430 { 413 voxelSafety = minCurNodeNoDelta*curNodeWid 431 voxelSafety = minCurNodeNoDelta*curNodeWidth; 414 voxelSafety += minCurCommonDelta; 432 voxelSafety += minCurCommonDelta; 415 } 433 } 416 else if (maxCurNodeNoDelta < minCurNodeNoDel 434 else if (maxCurNodeNoDelta < minCurNodeNoDelta) 417 { 435 { 418 voxelSafety = maxCurNodeNoDelta*curNodeWid 436 voxelSafety = maxCurNodeNoDelta*curNodeWidth; 419 voxelSafety += maxCurCommonDelta; 437 voxelSafety += maxCurCommonDelta; 420 } 438 } 421 else // (maxCurNodeNoDelta == minCurNodeN 439 else // (maxCurNodeNoDelta == minCurNodeNoDelta) 422 { 440 { 423 voxelSafety = minCurNodeNoDelta*curNodeWid 441 voxelSafety = minCurNodeNoDelta*curNodeWidth; 424 voxelSafety += std::min(minCurCommonDelta, 442 voxelSafety += std::min(minCurCommonDelta,maxCurCommonDelta); 425 } 443 } 426 444 427 // Compute isotropic safety to boundaries of 445 // Compute isotropic safety to boundaries of previous levels 428 // [NOT to collected boundaries] 446 // [NOT to collected boundaries] 429 447 430 // Loop checking, 07.10.2016, JA 448 // Loop checking, 07.10.2016, JA 431 while ( (localVoxelDepth>0) && (voxelSafety> 449 while ( (localVoxelDepth>0) && (voxelSafety>0) ) 432 { 450 { 433 localVoxelDepth--; 451 localVoxelDepth--; 434 curHeader = fVoxelHeaderStack[localVoxelDe 452 curHeader = fVoxelHeaderStack[localVoxelDepth]; 435 curHeaderAxis = fVoxelAxisStack[localVoxel 453 curHeaderAxis = fVoxelAxisStack[localVoxelDepth]; 436 curNodeNo = fVoxelNodeNoStack[localVoxelDe 454 curNodeNo = fVoxelNodeNoStack[localVoxelDepth]; 437 curNodeWidth = fVoxelSliceWidthStack[local 455 curNodeWidth = fVoxelSliceWidthStack[localVoxelDepth]; 438 curNodeOffset = curNodeNo*curNodeWidth; 456 curNodeOffset = curNodeNo*curNodeWidth; 439 minCurCommonDelta = localPoint(curHeaderAx 457 minCurCommonDelta = localPoint(curHeaderAxis) 440 - curHeader->GetMinExt 458 - curHeader->GetMinExtent() - curNodeOffset; 441 maxCurCommonDelta = curNodeWidth-minCurCom 459 maxCurCommonDelta = curNodeWidth-minCurCommonDelta; 442 460 443 if ( minCurCommonDelta<voxelSafety ) 461 if ( minCurCommonDelta<voxelSafety ) 444 { 462 { 445 voxelSafety = minCurCommonDelta; 463 voxelSafety = minCurCommonDelta; 446 } 464 } 447 if ( maxCurCommonDelta<voxelSafety ) 465 if ( maxCurCommonDelta<voxelSafety ) 448 { 466 { 449 voxelSafety = maxCurCommonDelta; 467 voxelSafety = maxCurCommonDelta; 450 } 468 } 451 } 469 } 452 if ( voxelSafety<0 ) 470 if ( voxelSafety<0 ) 453 { 471 { 454 voxelSafety = 0; 472 voxelSafety = 0; 455 } 473 } 456 474 457 return voxelSafety; 475 return voxelSafety; 458 } 476 } 459 477 460 // ******************************************* 478 // ******************************************************************** 461 // LocateNextVoxel 479 // LocateNextVoxel 462 // 480 // 463 // Finds the next voxel from the current voxel 481 // Finds the next voxel from the current voxel and point 464 // in the specified direction 482 // in the specified direction 465 // 483 // 466 // Returns false if all voxels considered 484 // Returns false if all voxels considered 467 // [current Step ends inside same 485 // [current Step ends inside same voxel or leaves all voxels] 468 // true otherwise 486 // true otherwise 469 // [the information on the next v 487 // [the information on the next voxel is put into the set of 470 // fVoxel* variables & "stacks"] 488 // fVoxel* variables & "stacks"] 471 // ******************************************* 489 // ******************************************************************** 472 // 490 // 473 G4bool 491 G4bool 474 G4VoxelNavigation::LocateNextVoxel(const G4Thr 492 G4VoxelNavigation::LocateNextVoxel(const G4ThreeVector& localPoint, 475 const G4Thr 493 const G4ThreeVector& localDirection, 476 const G4dou 494 const G4double currentStep) 477 { 495 { 478 G4SmartVoxelHeader *workHeader=nullptr, *new 496 G4SmartVoxelHeader *workHeader=nullptr, *newHeader=nullptr; 479 G4SmartVoxelProxy *newProxy=nullptr; 497 G4SmartVoxelProxy *newProxy=nullptr; 480 G4SmartVoxelNode *newVoxelNode=nullptr; 498 G4SmartVoxelNode *newVoxelNode=nullptr; 481 G4ThreeVector targetPoint, voxelPoint; 499 G4ThreeVector targetPoint, voxelPoint; 482 G4double workNodeWidth, workMinExtent, workC 500 G4double workNodeWidth, workMinExtent, workCoord; 483 G4double minVal, maxVal, newDistance=0.; 501 G4double minVal, maxVal, newDistance=0.; 484 G4double newHeaderMin, newHeaderNodeWidth; 502 G4double newHeaderMin, newHeaderNodeWidth; 485 G4int depth=0, newDepth=0, workNodeNo=0, new 503 G4int depth=0, newDepth=0, workNodeNo=0, newNodeNo=0, newHeaderNoSlices=0; 486 EAxis workHeaderAxis, newHeaderAxis; 504 EAxis workHeaderAxis, newHeaderAxis; 487 G4bool isNewVoxel = false; 505 G4bool isNewVoxel = false; 488 506 489 G4double currentDistance = currentStep; 507 G4double currentDistance = currentStep; 490 508 491 // Determine if end of Step within current v 509 // Determine if end of Step within current voxel 492 // 510 // 493 for (depth=0; depth<fVoxelDepth; ++depth) 511 for (depth=0; depth<fVoxelDepth; ++depth) 494 { 512 { 495 targetPoint = localPoint+localDirection*cu 513 targetPoint = localPoint+localDirection*currentDistance; 496 newDistance = currentDistance; 514 newDistance = currentDistance; 497 workHeader = fVoxelHeaderStack[depth]; 515 workHeader = fVoxelHeaderStack[depth]; 498 workHeaderAxis = fVoxelAxisStack[depth]; 516 workHeaderAxis = fVoxelAxisStack[depth]; 499 workNodeNo = fVoxelNodeNoStack[depth]; 517 workNodeNo = fVoxelNodeNoStack[depth]; 500 workNodeWidth = fVoxelSliceWidthStack[dept 518 workNodeWidth = fVoxelSliceWidthStack[depth]; 501 workMinExtent = workHeader->GetMinExtent() 519 workMinExtent = workHeader->GetMinExtent(); 502 workCoord = targetPoint(workHeaderAxis); 520 workCoord = targetPoint(workHeaderAxis); 503 minVal = workMinExtent+workNodeNo*workNode 521 minVal = workMinExtent+workNodeNo*workNodeWidth; 504 522 505 if ( minVal<=workCoord+fHalfTolerance ) 523 if ( minVal<=workCoord+fHalfTolerance ) 506 { 524 { 507 maxVal = minVal+workNodeWidth; 525 maxVal = minVal+workNodeWidth; 508 if ( maxVal<=workCoord-fHalfTolerance ) 526 if ( maxVal<=workCoord-fHalfTolerance ) 509 { 527 { 510 // Must consider next voxel 528 // Must consider next voxel 511 // 529 // 512 newNodeNo = workNodeNo+1; 530 newNodeNo = workNodeNo+1; 513 newHeader = workHeader; 531 newHeader = workHeader; 514 newDistance = (maxVal-localPoint(workH 532 newDistance = (maxVal-localPoint(workHeaderAxis)) 515 / localDirection(workHeade 533 / localDirection(workHeaderAxis); 516 isNewVoxel = true; 534 isNewVoxel = true; 517 newDepth = depth; 535 newDepth = depth; 518 } 536 } 519 } 537 } 520 else 538 else 521 { 539 { 522 newNodeNo = workNodeNo-1; 540 newNodeNo = workNodeNo-1; 523 newHeader = workHeader; 541 newHeader = workHeader; 524 newDistance = (minVal-localPoint(workHea 542 newDistance = (minVal-localPoint(workHeaderAxis)) 525 / localDirection(workHeaderA 543 / localDirection(workHeaderAxis); 526 isNewVoxel = true; 544 isNewVoxel = true; 527 newDepth = depth; 545 newDepth = depth; 528 } 546 } 529 currentDistance = newDistance; 547 currentDistance = newDistance; 530 } 548 } 531 targetPoint = localPoint+localDirection*curr 549 targetPoint = localPoint+localDirection*currentDistance; 532 550 533 // Check if end of Step within collected bou 551 // Check if end of Step within collected boundaries of current voxel 534 // 552 // 535 depth = fVoxelDepth; 553 depth = fVoxelDepth; 536 { 554 { 537 workHeader = fVoxelHeaderStack[depth]; 555 workHeader = fVoxelHeaderStack[depth]; 538 workHeaderAxis = fVoxelAxisStack[depth]; 556 workHeaderAxis = fVoxelAxisStack[depth]; 539 workNodeNo = fVoxelNodeNoStack[depth]; 557 workNodeNo = fVoxelNodeNoStack[depth]; 540 workNodeWidth = fVoxelSliceWidthStack[dept 558 workNodeWidth = fVoxelSliceWidthStack[depth]; 541 workMinExtent = workHeader->GetMinExtent() 559 workMinExtent = workHeader->GetMinExtent(); 542 workCoord = targetPoint(workHeaderAxis); 560 workCoord = targetPoint(workHeaderAxis); 543 minVal = workMinExtent+fVoxelNode->GetMinE 561 minVal = workMinExtent+fVoxelNode->GetMinEquivalentSliceNo()*workNodeWidth; 544 562 545 if ( minVal<=workCoord+fHalfTolerance ) 563 if ( minVal<=workCoord+fHalfTolerance ) 546 { 564 { 547 maxVal = workMinExtent+(fVoxelNode->GetM 565 maxVal = workMinExtent+(fVoxelNode->GetMaxEquivalentSliceNo()+1) 548 *workNodeWidth; 566 *workNodeWidth; 549 if ( maxVal<=workCoord-fHalfTolerance ) 567 if ( maxVal<=workCoord-fHalfTolerance ) 550 { 568 { 551 newNodeNo = fVoxelNode->GetMaxEquivale 569 newNodeNo = fVoxelNode->GetMaxEquivalentSliceNo()+1; 552 newHeader = workHeader; 570 newHeader = workHeader; 553 newDistance = (maxVal-localPoint(workH 571 newDistance = (maxVal-localPoint(workHeaderAxis)) 554 / localDirection(workHeade 572 / localDirection(workHeaderAxis); 555 isNewVoxel = true; 573 isNewVoxel = true; 556 newDepth = depth; 574 newDepth = depth; 557 } 575 } 558 } 576 } 559 else 577 else 560 { 578 { 561 newNodeNo = fVoxelNode->GetMinEquivalent 579 newNodeNo = fVoxelNode->GetMinEquivalentSliceNo()-1; 562 newHeader = workHeader; 580 newHeader = workHeader; 563 newDistance = (minVal-localPoint(workHea 581 newDistance = (minVal-localPoint(workHeaderAxis)) 564 / localDirection(workHeaderA 582 / localDirection(workHeaderAxis); 565 isNewVoxel = true; 583 isNewVoxel = true; 566 newDepth = depth; 584 newDepth = depth; 567 } 585 } 568 currentDistance = newDistance; 586 currentDistance = newDistance; 569 } 587 } 570 if (isNewVoxel) 588 if (isNewVoxel) 571 { 589 { 572 // Compute new voxel & adjust voxel stack 590 // Compute new voxel & adjust voxel stack 573 // 591 // 574 // newNodeNo=Candidate node no at 592 // newNodeNo=Candidate node no at 575 // newDepth =refinement depth of crossed v 593 // newDepth =refinement depth of crossed voxel boundary 576 // newHeader=Header for crossed voxel 594 // newHeader=Header for crossed voxel 577 // newDistance=distance to crossed voxel b 595 // newDistance=distance to crossed voxel boundary (along the track) 578 // 596 // 579 if ( (newNodeNo<0) || (newNodeNo>=G4int(ne 597 if ( (newNodeNo<0) || (newNodeNo>=G4int(newHeader->GetNoSlices()))) 580 { 598 { 581 // Leaving mother volume 599 // Leaving mother volume 582 // 600 // 583 isNewVoxel = false; 601 isNewVoxel = false; 584 } 602 } 585 else 603 else 586 { 604 { 587 // Compute intersection point on the lea 605 // Compute intersection point on the least refined 588 // voxel boundary that is hit 606 // voxel boundary that is hit 589 // 607 // 590 voxelPoint = localPoint+localDirection*n 608 voxelPoint = localPoint+localDirection*newDistance; 591 fVoxelNodeNoStack[newDepth] = newNodeNo; 609 fVoxelNodeNoStack[newDepth] = newNodeNo; 592 fVoxelDepth = newDepth; 610 fVoxelDepth = newDepth; 593 newVoxelNode = nullptr; << 611 newVoxelNode = 0; 594 while ( newVoxelNode == nullptr ) << 612 while ( !newVoxelNode ) 595 { 613 { 596 newProxy = newHeader->GetSlice(newNode 614 newProxy = newHeader->GetSlice(newNodeNo); 597 if (newProxy->IsNode()) 615 if (newProxy->IsNode()) 598 { 616 { 599 newVoxelNode = newProxy->GetNode(); 617 newVoxelNode = newProxy->GetNode(); 600 } 618 } 601 else 619 else 602 { 620 { 603 ++fVoxelDepth; 621 ++fVoxelDepth; 604 newHeader = newProxy->GetHeader(); 622 newHeader = newProxy->GetHeader(); 605 newHeaderAxis = newHeader->GetAxis() 623 newHeaderAxis = newHeader->GetAxis(); 606 newHeaderNoSlices = (G4int)newHeader << 624 newHeaderNoSlices = newHeader->GetNoSlices(); 607 newHeaderMin = newHeader->GetMinExte 625 newHeaderMin = newHeader->GetMinExtent(); 608 newHeaderNodeWidth = (newHeader->Get 626 newHeaderNodeWidth = (newHeader->GetMaxExtent()-newHeaderMin) 609 / newHeaderNoSlic 627 / newHeaderNoSlices; 610 newNodeNo = G4int( (voxelPoint(newHe 628 newNodeNo = G4int( (voxelPoint(newHeaderAxis)-newHeaderMin) 611 / newHeaderNodeWi 629 / newHeaderNodeWidth ); 612 // Rounding protection 630 // Rounding protection 613 // 631 // 614 if ( newNodeNo<0 ) 632 if ( newNodeNo<0 ) 615 { 633 { 616 newNodeNo=0; 634 newNodeNo=0; 617 } 635 } 618 else if ( newNodeNo>=newHeaderNoSlic 636 else if ( newNodeNo>=newHeaderNoSlices ) 619 { 637 { 620 newNodeNo = newHeaderNoSlices-1; 638 newNodeNo = newHeaderNoSlices-1; 621 } 639 } 622 // Stack info for stepping 640 // Stack info for stepping 623 // 641 // 624 fVoxelAxisStack[fVoxelDepth] = newHe 642 fVoxelAxisStack[fVoxelDepth] = newHeaderAxis; 625 fVoxelNoSlicesStack[fVoxelDepth] = n 643 fVoxelNoSlicesStack[fVoxelDepth] = newHeaderNoSlices; 626 fVoxelSliceWidthStack[fVoxelDepth] = 644 fVoxelSliceWidthStack[fVoxelDepth] = newHeaderNodeWidth; 627 fVoxelNodeNoStack[fVoxelDepth] = new 645 fVoxelNodeNoStack[fVoxelDepth] = newNodeNo; 628 fVoxelHeaderStack[fVoxelDepth] = new 646 fVoxelHeaderStack[fVoxelDepth] = newHeader; 629 } 647 } 630 } 648 } 631 fVoxelNode = newVoxelNode; 649 fVoxelNode = newVoxelNode; 632 } 650 } 633 } 651 } 634 return isNewVoxel; 652 return isNewVoxel; 635 } 653 } 636 654 637 // ******************************************* 655 // ******************************************************************** 638 // ComputeSafety 656 // ComputeSafety 639 // 657 // 640 // Calculates the isotropic distance to the ne 658 // Calculates the isotropic distance to the nearest boundary from the 641 // specified point in the local coordinate sys 659 // specified point in the local coordinate system. 642 // The localpoint utilised must be within the 660 // The localpoint utilised must be within the current volume. 643 // ******************************************* 661 // ******************************************************************** 644 // 662 // 645 G4double 663 G4double 646 G4VoxelNavigation::ComputeSafety(const G4Three 664 G4VoxelNavigation::ComputeSafety(const G4ThreeVector& localPoint, 647 const G4Navig 665 const G4NavigationHistory& history, 648 const G4doubl 666 const G4double maxLength) 649 { 667 { 650 G4VPhysicalVolume *motherPhysical, *samplePh 668 G4VPhysicalVolume *motherPhysical, *samplePhysical; 651 G4LogicalVolume *motherLogical; 669 G4LogicalVolume *motherLogical; 652 G4VSolid *motherSolid; 670 G4VSolid *motherSolid; 653 G4double motherSafety, ourSafety; 671 G4double motherSafety, ourSafety; 654 G4int sampleNo; 672 G4int sampleNo; 655 G4SmartVoxelNode *curVoxelNode; 673 G4SmartVoxelNode *curVoxelNode; 656 G4long curNoVolumes, contentNo; << 674 G4int curNoVolumes, contentNo; 657 G4double voxelSafety; 675 G4double voxelSafety; 658 676 659 motherPhysical = history.GetTopVolume(); 677 motherPhysical = history.GetTopVolume(); 660 motherLogical = motherPhysical->GetLogicalVo 678 motherLogical = motherPhysical->GetLogicalVolume(); 661 motherSolid = motherLogical->GetSolid(); 679 motherSolid = motherLogical->GetSolid(); 662 680 663 if( fBestSafety ) 681 if( fBestSafety ) 664 { 682 { 665 return fpVoxelSafety->ComputeSafety( local 683 return fpVoxelSafety->ComputeSafety( localPoint,*motherPhysical,maxLength ); 666 } 684 } 667 685 668 // 686 // 669 // Compute mother safety 687 // Compute mother safety 670 // 688 // 671 689 672 motherSafety = motherSolid->DistanceToOut(lo 690 motherSafety = motherSolid->DistanceToOut(localPoint); 673 ourSafety = motherSafety; // 691 ourSafety = motherSafety; // Working isotropic safety 674 692 675 if( motherSafety == 0.0 ) 693 if( motherSafety == 0.0 ) 676 { 694 { 677 #ifdef G4DEBUG_NAVIGATION 695 #ifdef G4DEBUG_NAVIGATION 678 // Check that point is inside mother volum 696 // Check that point is inside mother volume 679 EInside insideMother = motherSolid->Insid 697 EInside insideMother = motherSolid->Inside(localPoint); 680 698 681 if( insideMother == kOutside ) 699 if( insideMother == kOutside ) 682 { 700 { 683 G4ExceptionDescription message; 701 G4ExceptionDescription message; 684 message << "Safety method called for loc 702 message << "Safety method called for location outside current Volume." << G4endl 685 << "Location for safety is Outside th 703 << "Location for safety is Outside this volume. " << G4endl 686 << "The approximate distance to the s 704 << "The approximate distance to the solid " 687 << "(safety from outside) is: " 705 << "(safety from outside) is: " 688 << motherSolid->DistanceToIn( localPo 706 << motherSolid->DistanceToIn( localPoint ) << G4endl; 689 message << " Problem occurred with phys 707 message << " Problem occurred with physical volume: " 690 << " Name: " << motherPhysical->GetNa 708 << " Name: " << motherPhysical->GetName() 691 << " Copy No: " << motherPhysical->Ge 709 << " Copy No: " << motherPhysical->GetCopyNo() << G4endl 692 << " Local Point = " << localPoint 710 << " Local Point = " << localPoint << G4endl; 693 message << " Description of solid: " << 711 message << " Description of solid: " << G4endl 694 << *motherSolid << G4endl; 712 << *motherSolid << G4endl; 695 G4Exception("G4VoxelNavigation::ComputeS 713 G4Exception("G4VoxelNavigation::ComputeSafety()", "GeomNav0003", 696 JustWarning, message); 714 JustWarning, message); 697 } 715 } 698 716 699 // Following check is NOT for an issue - i 717 // Following check is NOT for an issue - it is only for information 700 // It is allowed that a solid gives appro 718 // It is allowed that a solid gives approximate safety - even zero. 701 // 719 // 702 if( insideMother == kInside ) // && fVerbo 720 if( insideMother == kInside ) // && fVerbose ) 703 { 721 { 704 G4ExceptionDescription messageIn; 722 G4ExceptionDescription messageIn; 705 723 706 messageIn << " Point is Inside, but safe 724 messageIn << " Point is Inside, but safety is Zero ." << G4endl; 707 messageIn << " Inexact safety for volume 725 messageIn << " Inexact safety for volume " << motherPhysical->GetName() << G4endl 708 << " Solid: Name= " << motherSol 726 << " Solid: Name= " << motherSolid->GetName() 709 << " Type= " << motherSolid->Ge 727 << " Type= " << motherSolid->GetEntityType() << G4endl; 710 messageIn << " Local point= " << localP 728 messageIn << " Local point= " << localPoint << G4endl; 711 messageIn << " Solid parameters: " << G 729 messageIn << " Solid parameters: " << G4endl << *motherSolid << G4endl; 712 G4Exception("G4VoxelNavigation::ComputeS 730 G4Exception("G4VoxelNavigation::ComputeSafety()", "GeomNav0003", 713 JustWarning, messageIn); 731 JustWarning, messageIn); 714 } 732 } 715 #endif 733 #endif 716 // if( insideMother != kInside ) 734 // if( insideMother != kInside ) 717 return 0.0; 735 return 0.0; 718 } 736 } 719 737 720 #ifdef G4VERBOSE 738 #ifdef G4VERBOSE 721 if( fCheck ) 739 if( fCheck ) 722 { 740 { 723 fLogger->ComputeSafetyLog (motherSolid,loc << 741 fLogger->ComputeSafetyLog (motherSolid,localPoint,motherSafety,true,true); 724 } 742 } 725 #endif 743 #endif 726 // 744 // 727 // Compute daughter safeties 745 // Compute daughter safeties 728 // 746 // 729 // Look only inside the current Voxel only ( 747 // Look only inside the current Voxel only (in the first version). 730 // 748 // 731 curVoxelNode = fVoxelNode; 749 curVoxelNode = fVoxelNode; 732 curNoVolumes = curVoxelNode->GetNoContained( 750 curNoVolumes = curVoxelNode->GetNoContained(); 733 751 734 for ( contentNo=curNoVolumes-1; contentNo>=0 752 for ( contentNo=curNoVolumes-1; contentNo>=0; contentNo-- ) 735 { 753 { 736 sampleNo = curVoxelNode->GetVolume((G4int) << 754 sampleNo = curVoxelNode->GetVolume(contentNo); 737 samplePhysical = motherLogical->GetDaughte 755 samplePhysical = motherLogical->GetDaughter(sampleNo); 738 756 739 G4AffineTransform sampleTf(samplePhysical- 757 G4AffineTransform sampleTf(samplePhysical->GetRotation(), 740 samplePhysical- 758 samplePhysical->GetTranslation()); 741 sampleTf.Invert(); 759 sampleTf.Invert(); 742 const G4ThreeVector samplePoint = sampleTf 760 const G4ThreeVector samplePoint = sampleTf.TransformPoint(localPoint); 743 const G4VSolid* sampleSolid= samplePhysica 761 const G4VSolid* sampleSolid= samplePhysical->GetLogicalVolume()->GetSolid(); 744 G4double sampleSafety = sampleSolid->Dista 762 G4double sampleSafety = sampleSolid->DistanceToIn(samplePoint); 745 if ( sampleSafety<ourSafety ) 763 if ( sampleSafety<ourSafety ) 746 { 764 { 747 ourSafety = sampleSafety; 765 ourSafety = sampleSafety; 748 } 766 } 749 #ifdef G4VERBOSE 767 #ifdef G4VERBOSE 750 if( fCheck ) 768 if( fCheck ) 751 { 769 { 752 fLogger->ComputeSafetyLog(sampleSolid, s 770 fLogger->ComputeSafetyLog(sampleSolid, samplePoint, 753 sampleSafety, << 771 sampleSafety, false, false); 754 } 772 } 755 #endif 773 #endif 756 } 774 } 757 voxelSafety = ComputeVoxelSafety(localPoint) 775 voxelSafety = ComputeVoxelSafety(localPoint); 758 if ( voxelSafety<ourSafety ) 776 if ( voxelSafety<ourSafety ) 759 { 777 { 760 ourSafety = voxelSafety; 778 ourSafety = voxelSafety; 761 } 779 } 762 return ourSafety; 780 return ourSafety; 763 } 781 } 764 782 765 void G4VoxelNavigation::RelocateWithinVolume( << 766 << 767 { << 768 auto motherLogical = motherPhysical->GetLogi << 769 << 770 assert(motherLogical != nullptr); << 771 << 772 if ( auto pVoxelHeader = motherLogical->GetV << 773 VoxelLocate( pVoxelHeader, localPoint ); << 774 } << 775 << 776 // ******************************************* 783 // ******************************************************************** 777 // SetVerboseLevel 784 // SetVerboseLevel 778 // ******************************************* 785 // ******************************************************************** 779 // 786 // 780 void G4VoxelNavigation::SetVerboseLevel(G4int 787 void G4VoxelNavigation::SetVerboseLevel(G4int level) 781 { 788 { 782 if( fLogger != nullptr ) { fLogger->SetVerbo << 789 if( fLogger ) fLogger->SetVerboseLevel(level); 783 if( fpVoxelSafety != nullptr) { fpVoxelSafet << 790 if( fpVoxelSafety) fpVoxelSafety->SetVerboseLevel(level); 784 } 791 } 785 792