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
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 #include "G4ParameterisedNavigation.hh"
00051 #include "G4TouchableHistory.hh"
00052 #include "G4VNestedParameterisation.hh"
00053
00054
00055
00056
00057
00058 G4ParameterisedNavigation::G4ParameterisedNavigation()
00059 : fVoxelAxis(kUndefined), fVoxelNoSlices(0), fVoxelSliceWidth(0.),
00060 fVoxelNodeNo(0), fVoxelHeader(0)
00061 {
00062 }
00063
00064
00065
00066
00067
00068 G4ParameterisedNavigation::~G4ParameterisedNavigation()
00069 {
00070 }
00071
00072
00073
00074
00075
00076 G4double G4ParameterisedNavigation::
00077 ComputeStep(const G4ThreeVector& localPoint,
00078 const G4ThreeVector& localDirection,
00079 const G4double currentProposedStepLength,
00080 G4double& newSafety,
00081 G4NavigationHistory& history,
00082 G4bool& validExitNormal,
00083 G4ThreeVector& exitNormal,
00084 G4bool& exiting,
00085 G4bool& entering,
00086 G4VPhysicalVolume *(*pBlockedPhysical),
00087 G4int& blockedReplicaNo)
00088 {
00089 G4VPhysicalVolume *motherPhysical, *samplePhysical;
00090 G4VPVParameterisation *sampleParam;
00091 G4LogicalVolume *motherLogical;
00092 G4VSolid *motherSolid, *sampleSolid;
00093 G4ThreeVector sampleDirection;
00094 G4double ourStep=currentProposedStepLength, motherSafety, ourSafety;
00095 G4int sampleNo;
00096
00097 G4bool initialNode, noStep;
00098 G4SmartVoxelNode *curVoxelNode;
00099 G4int curNoVolumes, contentNo;
00100 G4double voxelSafety;
00101
00102
00103
00104 EAxis axis;
00105 G4int nReplicas;
00106 G4double width, offset;
00107 G4bool consuming;
00108
00109 motherPhysical = history.GetTopVolume();
00110 motherLogical = motherPhysical->GetLogicalVolume();
00111 motherSolid = motherLogical->GetSolid();
00112
00113
00114
00115
00116
00117 motherSafety = motherSolid->DistanceToOut(localPoint);
00118 ourSafety = motherSafety;
00119
00120 #ifdef G4VERBOSE
00121 if ( fCheck )
00122 {
00123 if( motherSafety < 0.0 )
00124 {
00125 motherSolid->DumpInfo();
00126 std::ostringstream message;
00127 message << "Negative Safety In Voxel Navigation !" << G4endl
00128 << " Current solid " << motherSolid->GetName()
00129 << " gave negative safety: " << motherSafety << G4endl
00130 << " for the current (local) point " << localPoint;
00131 G4Exception("G4ParameterisedNavigation::ComputeStep()",
00132 "GeomNav0003", FatalException, message);
00133 }
00134 if( motherSolid->Inside(localPoint)==kOutside )
00135 {
00136 std::ostringstream message;
00137 message << "Point is outside Current Volume !" << G4endl
00138 << " Point " << localPoint
00139 << " is outside current volume " << motherPhysical->GetName()
00140 << G4endl;
00141 G4double estDistToSolid= motherSolid->DistanceToIn(localPoint);
00142 G4cout << " Estimated isotropic distance to solid (distToIn)= "
00143 << estDistToSolid;
00144 if( estDistToSolid > 100.0 * motherSolid->GetTolerance() )
00145 {
00146 motherSolid->DumpInfo();
00147 G4Exception("G4ParameterisedNavigation::ComputeStep()",
00148 "GeomNav0003", FatalException, message,
00149 "Point is far outside Current Volume !");
00150 }
00151 else
00152 G4Exception("G4ParameterisedNavigation::ComputeStep()",
00153 "GeomNav1002", JustWarning, message,
00154 "Point is a little outside Current Volume.");
00155 }
00156 }
00157 #endif
00158
00159
00160
00161
00162
00163 initialNode = true;
00164 noStep = true;
00165
00166
00167
00168
00169 samplePhysical = motherLogical->GetDaughter(0);
00170 samplePhysical->GetReplicationData(axis,nReplicas,width,offset,consuming);
00171 fBList.Enlarge(nReplicas);
00172 fBList.Reset();
00173
00174
00175
00176 if (exiting && (*pBlockedPhysical==samplePhysical) && validExitNormal)
00177 {
00178 if (localDirection.dot(exitNormal)>=kMinExitingNormalCosine)
00179 {
00180
00181
00182 fBList.BlockVolume(blockedReplicaNo);
00183 ourSafety = 0;
00184 }
00185 }
00186 exiting = false;
00187 entering = false;
00188
00189 sampleParam = samplePhysical->GetParameterisation();
00190
00191 do
00192 {
00193 curVoxelNode = fVoxelNode;
00194 curNoVolumes = curVoxelNode->GetNoContained();
00195
00196 for ( contentNo=curNoVolumes-1; contentNo>=0; contentNo-- )
00197 {
00198 sampleNo = curVoxelNode->GetVolume(contentNo);
00199 if ( !fBList.IsBlocked(sampleNo) )
00200 {
00201 fBList.BlockVolume(sampleNo);
00202
00203
00204
00205 sampleSolid = IdentifyAndPlaceSolid( sampleNo, samplePhysical,
00206 sampleParam );
00207
00208 G4AffineTransform sampleTf(samplePhysical->GetRotation(),
00209 samplePhysical->GetTranslation());
00210 sampleTf.Invert();
00211 const G4ThreeVector samplePoint = sampleTf.TransformPoint(localPoint);
00212 const G4double sampleSafety = sampleSolid->DistanceToIn(samplePoint);
00213 if ( sampleSafety<ourSafety )
00214 {
00215 ourSafety = sampleSafety;
00216 }
00217 if ( sampleSafety<=ourStep )
00218 {
00219 sampleDirection = sampleTf.TransformAxis(localDirection);
00220 G4double sampleStep =
00221 sampleSolid->DistanceToIn(samplePoint, sampleDirection);
00222 if ( sampleStep<=ourStep )
00223 {
00224 ourStep = sampleStep;
00225 entering = true;
00226 exiting = false;
00227 *pBlockedPhysical = samplePhysical;
00228 blockedReplicaNo = sampleNo;
00229 #ifdef G4VERBOSE
00230
00231
00232
00233
00234 if ( ( fCheck ) && ( sampleStep < kInfinity ) )
00235 {
00236 G4ThreeVector intersectionPoint;
00237 intersectionPoint= samplePoint + sampleStep * sampleDirection;
00238 EInside insideIntPt= sampleSolid->Inside(intersectionPoint);
00239 if( insideIntPt != kSurface )
00240 {
00241 G4int oldcoutPrec = G4cout.precision(16);
00242 std::ostringstream message;
00243 message << "Navigator gets conflicting response from Solid."
00244 << G4endl
00245 << " Inaccurate solid DistanceToIn"
00246 << " for solid " << sampleSolid->GetName() << G4endl
00247 << " Solid gave DistanceToIn = "
00248 << sampleStep << " yet returns " ;
00249 if( insideIntPt == kInside )
00250 message << "-kInside-";
00251 else if( insideIntPt == kOutside )
00252 message << "-kOutside-";
00253 else
00254 message << "-kSurface-";
00255 message << " for this point !" << G4endl
00256 << " Point = " << intersectionPoint
00257 << G4endl;
00258 if ( insideIntPt != kInside )
00259 message << " DistanceToIn(p) = "
00260 << sampleSolid->DistanceToIn(intersectionPoint);
00261 if ( insideIntPt != kOutside )
00262 message << " DistanceToOut(p) = "
00263 << sampleSolid->DistanceToOut(intersectionPoint);
00264 G4Exception("G4ParameterisedNavigation::ComputeStep()",
00265 "GeomNav1002", JustWarning, message);
00266 G4cout.precision(oldcoutPrec);
00267 }
00268 }
00269 #endif
00270 }
00271 }
00272 }
00273 }
00274
00275 if ( initialNode )
00276 {
00277 initialNode = false;
00278 voxelSafety = ComputeVoxelSafety(localPoint,axis);
00279 if ( voxelSafety<ourSafety )
00280 {
00281 ourSafety = voxelSafety;
00282 }
00283 if ( currentProposedStepLength<ourSafety )
00284 {
00285
00286
00287 noStep = false;
00288 entering = false;
00289 exiting = false;
00290 *pBlockedPhysical = 0;
00291 ourStep = kInfinity;
00292 }
00293 else
00294 {
00295
00296
00297
00298 if ( motherSafety<=ourStep )
00299 {
00300 G4double motherStep = motherSolid->DistanceToOut(localPoint,
00301 localDirection,
00302 true,
00303 &validExitNormal,
00304 &exitNormal);
00305 #ifdef G4VERBOSE
00306 if ( fCheck )
00307 if( ( motherStep < 0.0 ) || ( motherStep >= kInfinity) )
00308 {
00309 G4int oldPrOut= G4cout.precision(16);
00310 G4int oldPrErr= G4cerr.precision(16);
00311 std::ostringstream message;
00312 message << "Current point is outside the current solid !"
00313 << G4endl
00314 << " Problem in Navigation" << G4endl
00315 << " Point (local coordinates): "
00316 << localPoint << G4endl
00317 << " Local Direction: "
00318 << localDirection << G4endl
00319 << " Solid: " << motherSolid->GetName();
00320 motherSolid->DumpInfo();
00321 G4Exception("G4ParameterisedNavigation::ComputeStep()",
00322 "GeomNav0003", FatalException, message);
00323 G4cout.precision(oldPrOut);
00324 G4cerr.precision(oldPrErr);
00325 }
00326 #endif
00327 if ( motherStep<=ourStep )
00328 {
00329 ourStep = motherStep;
00330 exiting = true;
00331 entering = false;
00332 if ( validExitNormal )
00333 {
00334 const G4RotationMatrix *rot = motherPhysical->GetRotation();
00335 if (rot)
00336 {
00337 exitNormal *= rot->inverse();
00338 }
00339 }
00340 }
00341 else
00342 {
00343 validExitNormal = false;
00344 }
00345 }
00346 }
00347 newSafety=ourSafety;
00348 }
00349 if (noStep)
00350 {
00351 noStep = LocateNextVoxel(localPoint, localDirection, ourStep, axis);
00352 }
00353 } while (noStep);
00354
00355 return ourStep;
00356 }
00357
00358
00359
00360
00361
00362 G4double
00363 G4ParameterisedNavigation::ComputeSafety(const G4ThreeVector& localPoint,
00364 const G4NavigationHistory& history,
00365 const G4double )
00366 {
00367 G4VPhysicalVolume *motherPhysical, *samplePhysical;
00368 G4VPVParameterisation *sampleParam;
00369 G4LogicalVolume *motherLogical;
00370 G4VSolid *motherSolid, *sampleSolid;
00371 G4double motherSafety, ourSafety;
00372 G4int sampleNo, curVoxelNodeNo;
00373
00374 G4SmartVoxelNode *curVoxelNode;
00375 G4int curNoVolumes, contentNo;
00376 G4double voxelSafety;
00377
00378
00379
00380 EAxis axis;
00381 G4int nReplicas;
00382 G4double width, offset;
00383 G4bool consuming;
00384
00385 motherPhysical = history.GetTopVolume();
00386 motherLogical = motherPhysical->GetLogicalVolume();
00387 motherSolid = motherLogical->GetSolid();
00388
00389
00390
00391
00392
00393 motherSafety = motherSolid->DistanceToOut(localPoint);
00394 ourSafety = motherSafety;
00395
00396
00397
00398
00399
00400
00401
00402
00403 samplePhysical = motherLogical->GetDaughter(0);
00404 samplePhysical->GetReplicationData(axis, nReplicas,
00405 width, offset, consuming);
00406 sampleParam = samplePhysical->GetParameterisation();
00407
00408
00409
00410 if ( axis==kUndefined )
00411 {
00412 curVoxelNode = fVoxelNode;
00413 }
00414 else
00415 {
00416 curVoxelNodeNo = G4int((localPoint(fVoxelAxis)
00417 -fVoxelHeader->GetMinExtent()) / fVoxelSliceWidth );
00418 curVoxelNode = fVoxelHeader->GetSlice(curVoxelNodeNo)->GetNode();
00419 fVoxelNodeNo = curVoxelNodeNo;
00420 fVoxelNode = curVoxelNode;
00421 }
00422 curNoVolumes = curVoxelNode->GetNoContained();
00423
00424 for ( contentNo=curNoVolumes-1; contentNo>=0; contentNo-- )
00425 {
00426 sampleNo = curVoxelNode->GetVolume(contentNo);
00427
00428
00429
00430 sampleSolid= IdentifyAndPlaceSolid( sampleNo,samplePhysical,sampleParam );
00431
00432 G4AffineTransform sampleTf(samplePhysical->GetRotation(),
00433 samplePhysical->GetTranslation());
00434 sampleTf.Invert();
00435 const G4ThreeVector samplePoint = sampleTf.TransformPoint(localPoint);
00436 G4double sampleSafety = sampleSolid->DistanceToIn(samplePoint);
00437 if ( sampleSafety<ourSafety )
00438 {
00439 ourSafety = sampleSafety;
00440 }
00441 }
00442
00443 voxelSafety = ComputeVoxelSafety(localPoint,axis);
00444 if ( voxelSafety<ourSafety )
00445 {
00446 ourSafety=voxelSafety;
00447 }
00448
00449 return ourSafety;
00450 }
00451
00452
00453
00454
00455
00456
00457
00458
00459 G4double G4ParameterisedNavigation::
00460 ComputeVoxelSafety(const G4ThreeVector& localPoint,
00461 const EAxis pAxis) const
00462 {
00463
00464
00465
00466 if ( pAxis==kUndefined )
00467 {
00468 return G4VoxelNavigation::ComputeVoxelSafety(localPoint);
00469 }
00470
00471 G4double voxelSafety, plusVoxelSafety, minusVoxelSafety;
00472 G4double curNodeOffset, minCurCommonDelta, maxCurCommonDelta;
00473 G4int minCurNodeNoDelta, maxCurNodeNoDelta;
00474
00475
00476
00477
00478 curNodeOffset = fVoxelNodeNo*fVoxelSliceWidth;
00479 minCurCommonDelta = localPoint(fVoxelAxis)
00480 - fVoxelHeader->GetMinExtent()-curNodeOffset;
00481 maxCurNodeNoDelta = fVoxelNode->GetMaxEquivalentSliceNo()-fVoxelNodeNo;
00482 minCurNodeNoDelta = fVoxelNodeNo-fVoxelNode->GetMinEquivalentSliceNo();
00483 maxCurCommonDelta = fVoxelSliceWidth-minCurCommonDelta;
00484 plusVoxelSafety = minCurNodeNoDelta*fVoxelSliceWidth+minCurCommonDelta;
00485 minusVoxelSafety = maxCurNodeNoDelta*fVoxelSliceWidth+maxCurCommonDelta;
00486 voxelSafety = std::min(plusVoxelSafety,minusVoxelSafety);
00487
00488 if ( voxelSafety<0 )
00489 {
00490 voxelSafety = 0;
00491 }
00492
00493 return voxelSafety;
00494 }
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 G4bool G4ParameterisedNavigation::
00508 LocateNextVoxel( const G4ThreeVector& localPoint,
00509 const G4ThreeVector& localDirection,
00510 const G4double currentStep,
00511 const EAxis pAxis)
00512 {
00513
00514
00515
00516 if ( pAxis==kUndefined )
00517 {
00518 return G4VoxelNavigation::LocateNextVoxel(localPoint,
00519 localDirection,
00520 currentStep);
00521 }
00522
00523 G4bool isNewVoxel;
00524 G4int newNodeNo;
00525 G4double minVal, maxVal, curMinExtent, curCoord;
00526
00527 curMinExtent = fVoxelHeader->GetMinExtent();
00528 curCoord = localPoint(fVoxelAxis)+currentStep*localDirection(fVoxelAxis);
00529 minVal = curMinExtent+fVoxelNode->GetMinEquivalentSliceNo()*fVoxelSliceWidth;
00530 isNewVoxel = false;
00531
00532 if ( minVal<=curCoord )
00533 {
00534 maxVal = curMinExtent
00535 + (fVoxelNode->GetMaxEquivalentSliceNo()+1)*fVoxelSliceWidth;
00536 if ( maxVal<curCoord )
00537 {
00538 newNodeNo = fVoxelNode->GetMaxEquivalentSliceNo()+1;
00539 if ( newNodeNo<fVoxelHeader->GetNoSlices() )
00540 {
00541 fVoxelNodeNo = newNodeNo;
00542 fVoxelNode = fVoxelHeader->GetSlice(newNodeNo)->GetNode();
00543 isNewVoxel = true;
00544 }
00545 }
00546 }
00547 else
00548 {
00549 newNodeNo = fVoxelNode->GetMinEquivalentSliceNo()-1;
00550
00551
00552
00553
00554 if ( newNodeNo>=0 )
00555 {
00556 fVoxelNodeNo = newNodeNo;
00557 fVoxelNode = fVoxelHeader->GetSlice(newNodeNo)->GetNode();
00558 isNewVoxel = true;
00559 }
00560 }
00561 return isNewVoxel;
00562 }
00563
00564
00565
00566
00567
00568 G4bool
00569 G4ParameterisedNavigation::LevelLocate( G4NavigationHistory& history,
00570 const G4VPhysicalVolume* blockedVol,
00571 const G4int blockedNum,
00572 const G4ThreeVector& globalPoint,
00573 const G4ThreeVector* globalDirection,
00574 const G4bool pLocatedOnEdge,
00575 G4ThreeVector& localPoint )
00576 {
00577 G4SmartVoxelHeader *motherVoxelHeader;
00578 G4SmartVoxelNode *motherVoxelNode;
00579 G4VPhysicalVolume *motherPhysical, *pPhysical;
00580 G4VPVParameterisation *pParam;
00581 G4LogicalVolume *motherLogical;
00582 G4VSolid *pSolid;
00583 G4ThreeVector samplePoint;
00584 G4int voxelNoDaughters, replicaNo;
00585
00586 motherPhysical = history.GetTopVolume();
00587 motherLogical = motherPhysical->GetLogicalVolume();
00588 motherVoxelHeader = motherLogical->GetVoxelHeader();
00589
00590
00591
00592 motherVoxelNode = ParamVoxelLocate(motherVoxelHeader,localPoint);
00593
00594 voxelNoDaughters = motherVoxelNode->GetNoContained();
00595 if ( voxelNoDaughters==0 ) { return false; }
00596
00597 pPhysical = motherLogical->GetDaughter(0);
00598 pParam = pPhysical->GetParameterisation();
00599
00600
00601
00602
00603 G4TouchableHistory parentTouchable( history );
00604
00605
00606
00607 for ( register int sampleNo=voxelNoDaughters-1; sampleNo>=0; sampleNo-- )
00608 {
00609 replicaNo = motherVoxelNode->GetVolume(sampleNo);
00610 if ( (replicaNo!=blockedNum) || (pPhysical!=blockedVol) )
00611 {
00612
00613
00614 pSolid = IdentifyAndPlaceSolid( replicaNo, pPhysical, pParam );
00615
00616
00617
00618 history.NewLevel(pPhysical, kParameterised, replicaNo);
00619 samplePoint = history.GetTopTransform().TransformPoint(globalPoint);
00620 if ( !G4AuxiliaryNavServices::CheckPointOnSurface( pSolid, samplePoint,
00621 globalDirection, history.GetTopTransform(), pLocatedOnEdge) )
00622 {
00623 history.BackLevel();
00624 }
00625 else
00626 {
00627
00628
00629 localPoint = samplePoint;
00630
00631
00632
00633 pPhysical->SetCopyNo(replicaNo);
00634
00635
00636
00637 G4LogicalVolume *pLogical = pPhysical->GetLogicalVolume();
00638 pLogical->SetSolid(pSolid);
00639 pLogical->UpdateMaterial(pParam->ComputeMaterial(replicaNo,
00640 pPhysical, &parentTouchable) );
00641 return true;
00642 }
00643 }
00644 }
00645 return false;
00646 }