// // ******************************************************************** // * DISCLAIMER * // * * // * The following disclaimer summarizes all the specific disclaimers * // * of contributors to this software. The specific disclaimers,which * // * govern, are listed with their locations in: * // * http://cern.ch/geant4/license * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. * // * * // * 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.4 2001/07/11 10:00:30 gunter Exp $ // GEANT4 tag $Name: geant4-04-00 $ // // // class G4ParameterisedNavigation Inline implementation inline G4ParameterisedNavigation::G4ParameterisedNavigation() : fVoxelHeader(0), fVoxelNode(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= G4std::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 (maxValGetMaxEquivalentSliceNo()+1; if (newNodeNoGetNoSlices()) { 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; }