224 lines
6.5 KiB
Plaintext
224 lines
6.5 KiB
Plaintext
// This code implementation is the intellectual property of
|
|
// the GEANT4 collaboration.
|
|
//
|
|
// By copying, distributing or modifying the Program (or any work
|
|
// based on the Program) you indicate your acceptance of this statement,
|
|
// and all its terms.
|
|
//
|
|
// $Id: G4ParameterisedNavigation.icc,v 1.1.10.1 1999/12/07 20:48:41 gunter Exp $
|
|
// GEANT4 tag $Name: geant4-01-00 $
|
|
//
|
|
//
|
|
// class G4ParameterisedNavigation Inline implementation
|
|
|
|
|
|
inline G4ParameterisedNavigation::G4ParameterisedNavigation() :
|
|
fVoxelNode(0),fVoxelHeader(0)
|
|
{
|
|
}
|
|
|
|
inline G4SmartVoxelNode* G4ParameterisedNavigation::VoxelLocate(G4SmartVoxelHeader *pHead,
|
|
const G4ThreeVector &localPoint)
|
|
{
|
|
EAxis targetHeaderAxis;
|
|
G4double targetHeaderMin,targetHeaderNodeWidth;
|
|
G4int targetHeaderNoSlices,targetNodeNo;
|
|
|
|
targetHeaderAxis=pHead->GetAxis();
|
|
targetHeaderNoSlices=pHead->GetNoSlices();
|
|
targetHeaderMin=pHead->GetMinExtent();
|
|
targetHeaderNodeWidth=(pHead->GetMaxExtent()-targetHeaderMin)/targetHeaderNoSlices;
|
|
targetNodeNo=G4int ((localPoint(targetHeaderAxis)-targetHeaderMin)/targetHeaderNodeWidth);
|
|
// Rounding protection
|
|
if (targetNodeNo<0)
|
|
{
|
|
targetNodeNo=0;
|
|
}
|
|
else if (targetNodeNo>=targetHeaderNoSlices)
|
|
{
|
|
targetNodeNo=targetHeaderNoSlices-1;
|
|
}
|
|
fVoxelAxis=targetHeaderAxis;
|
|
fVoxelNoSlices=targetHeaderNoSlices;
|
|
fVoxelSliceWidth=targetHeaderNodeWidth;
|
|
fVoxelNodeNo=targetNodeNo;
|
|
fVoxelHeader=pHead;
|
|
fVoxelNode=pHead->GetSlice(targetNodeNo)->GetNode();
|
|
return fVoxelNode;
|
|
}
|
|
|
|
// Compute safety from specified point to collected voxel boundaries
|
|
// using already located point
|
|
|
|
inline G4double G4ParameterisedNavigation::ComputeVoxelSafety(const G4ThreeVector&localPoint) const
|
|
{
|
|
|
|
G4double voxelSafety, plusVoxelSafety, minusVoxelSafety;
|
|
G4double curNodeOffset,minCurCommonDelta,maxCurCommonDelta;
|
|
G4int minCurNodeNoDelta,maxCurNodeNoDelta;
|
|
|
|
// Compute linear intersection distance to boundaries of max/min
|
|
// to collected nodes at current level
|
|
curNodeOffset=fVoxelNodeNo*fVoxelSliceWidth;
|
|
minCurCommonDelta=localPoint(fVoxelAxis)
|
|
-fVoxelHeader->GetMinExtent()
|
|
-curNodeOffset;
|
|
maxCurNodeNoDelta=fVoxelNode->GetMaxEquivalentSliceNo()-fVoxelNodeNo;
|
|
minCurNodeNoDelta=fVoxelNodeNo-fVoxelNode->GetMinEquivalentSliceNo();
|
|
maxCurCommonDelta=fVoxelSliceWidth-minCurCommonDelta;
|
|
|
|
plusVoxelSafety= minCurNodeNoDelta*fVoxelSliceWidth+minCurCommonDelta;
|
|
minusVoxelSafety=maxCurNodeNoDelta*fVoxelSliceWidth+maxCurCommonDelta;
|
|
|
|
voxelSafety= min(plusVoxelSafety,minusVoxelSafety);
|
|
|
|
if (voxelSafety<0)
|
|
{
|
|
voxelSafety=0;
|
|
}
|
|
|
|
return voxelSafety;
|
|
}
|
|
|
|
|
|
// Find the next voxel from the current voxel and point in the specified
|
|
// direction
|
|
//
|
|
// Return false if all voxels considered
|
|
// [current Step ends inside same voxel or leaves all voxels]
|
|
// true otherwise
|
|
inline G4bool G4ParameterisedNavigation::LocateNextVoxel(const G4ThreeVector& localPoint,
|
|
const G4ThreeVector& localDirection,
|
|
const G4double currentStep)
|
|
{
|
|
|
|
|
|
G4bool isNewVoxel;
|
|
G4int newNodeNo;
|
|
G4double minVal,maxVal,curMinExtent,curCoord;
|
|
|
|
curMinExtent=fVoxelHeader->GetMinExtent();
|
|
curCoord=localPoint(fVoxelAxis)+currentStep*localDirection(fVoxelAxis);
|
|
minVal=curMinExtent
|
|
+fVoxelNode->GetMinEquivalentSliceNo()*fVoxelSliceWidth;
|
|
|
|
isNewVoxel=false;
|
|
|
|
if (minVal<=curCoord)
|
|
{
|
|
maxVal=curMinExtent
|
|
+(fVoxelNode->GetMaxEquivalentSliceNo()+1)*fVoxelSliceWidth;
|
|
if (maxVal<curCoord)
|
|
{
|
|
newNodeNo=fVoxelNode->GetMaxEquivalentSliceNo()+1;
|
|
if (newNodeNo<fVoxelHeader->GetNoSlices())
|
|
{
|
|
fVoxelNodeNo=newNodeNo;
|
|
fVoxelNode=fVoxelHeader->GetSlice(newNodeNo)->GetNode();
|
|
isNewVoxel=true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
newNodeNo=fVoxelNode->GetMinEquivalentSliceNo()-1;
|
|
// Must locate from newNodeNo no and down to setup stack and fVoxelNode
|
|
// Repeat or earlier code...
|
|
if (newNodeNo>=0)
|
|
{
|
|
fVoxelNodeNo=newNodeNo;
|
|
fVoxelNode=fVoxelHeader->GetSlice(newNodeNo)->GetNode();
|
|
isNewVoxel=true;
|
|
}
|
|
}
|
|
return isNewVoxel;
|
|
}
|
|
|
|
inline G4bool G4ParameterisedNavigation::LevelLocate(G4NavigationHistory& history,
|
|
const G4VPhysicalVolume *blockedVol,
|
|
const G4int blockedNum,
|
|
const G4ThreeVector &globalPoint,
|
|
const G4ThreeVector* globalDirection,
|
|
const G4bool pLocatedOnEdge,
|
|
G4ThreeVector &localPoint)
|
|
{
|
|
|
|
G4SmartVoxelHeader *motherVoxelHeader;
|
|
G4SmartVoxelNode *motherVoxelNode;
|
|
G4VPhysicalVolume *motherPhysical,*pPhysical;
|
|
G4VPVParameterisation *pParam;
|
|
G4LogicalVolume *motherLogical;
|
|
G4VSolid *pSolid;
|
|
G4ThreeVector samplePoint;
|
|
G4int voxelNoDaughters,sampleNo,replicaNo;
|
|
|
|
motherPhysical=history.GetTopVolume();
|
|
motherLogical=motherPhysical->GetLogicalVolume();
|
|
motherVoxelHeader=motherLogical->GetVoxelHeader();
|
|
// localPoint=history.GetTopTransform().TransformPoint(globalPoint);
|
|
// Find the voxel containing the point
|
|
motherVoxelNode=VoxelLocate(motherVoxelHeader,localPoint);
|
|
|
|
voxelNoDaughters=motherVoxelNode->GetNoContained();
|
|
if (voxelNoDaughters==0) return false;
|
|
|
|
pPhysical=motherLogical->GetDaughter(0);
|
|
// pSolid=pPhysical->GetLogicalVolume()->GetSolid(); // Now it can vary
|
|
pParam=pPhysical->GetParameterisation();
|
|
|
|
//
|
|
// Search replicated daughter volume
|
|
//
|
|
for (sampleNo=voxelNoDaughters-1;sampleNo>=0;sampleNo--)
|
|
{
|
|
replicaNo=motherVoxelNode->GetVolume(sampleNo);
|
|
if (replicaNo!=blockedNum||pPhysical!=blockedVol)
|
|
{
|
|
// Obtain solid (as it can vary) and
|
|
// obtain its parameters
|
|
pSolid=pParam->ComputeSolid(replicaNo, pPhysical);
|
|
pSolid->ComputeDimensions(pParam,
|
|
replicaNo,
|
|
pPhysical);
|
|
pParam->ComputeTransformation(replicaNo,
|
|
pPhysical);
|
|
// Setup volume with mother ptr
|
|
pPhysical->Setup(motherPhysical);
|
|
history.NewLevel(pPhysical,
|
|
kParameterised,
|
|
replicaNo);
|
|
samplePoint=history.GetTopTransform().TransformPoint(globalPoint);
|
|
if (! G4AuxiliaryNavServices::
|
|
CheckPointOnSurface(pSolid, samplePoint, globalDirection,
|
|
history.GetTopTransform(), pLocatedOnEdge) )
|
|
{
|
|
history.BackLevel();
|
|
}
|
|
else
|
|
{
|
|
// Enter this daughter
|
|
// blockedVol=0;
|
|
localPoint=samplePoint;
|
|
// Set the correct copy number in physical
|
|
pPhysical->SetCopyNo(replicaNo);
|
|
// Set the correct solid and material in Logical Volume
|
|
G4LogicalVolume *pLogical=pPhysical->GetLogicalVolume();
|
|
pLogical->SetSolid( pSolid );
|
|
pLogical->SetMaterial( pParam->ComputeMaterial(replicaNo,
|
|
pPhysical));
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|