277 lines
8.5 KiB
C++
277 lines
8.5 KiB
C++
//
|
|
// ********************************************************************
|
|
// * License and Disclaimer *
|
|
// * *
|
|
// * The Geant4 software is copyright of the Copyright Holders of *
|
|
// * the Geant4 Collaboration. It is provided under the terms and *
|
|
// * conditions of the Geant4 Software License, included in the file *
|
|
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
|
// * include a list of copyright holders. *
|
|
// * *
|
|
// * 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. Please see the license in the file LICENSE and URL above *
|
|
// * for the full disclaimer and the limitation of liability. *
|
|
// * *
|
|
// * This code implementation is the result of the scientific and *
|
|
// * technical work of the GEANT4 collaboration. *
|
|
// * By using, copying, modifying or distributing the software (or *
|
|
// * any work based on the software) you agree to acknowledge its *
|
|
// * use in resulting scientific publications, and indicate your *
|
|
// * acceptance of all terms of the Geant4 Software license. *
|
|
// ********************************************************************
|
|
//
|
|
// Class G4VoxelLimits implementation
|
|
//
|
|
// 13.07.95, P.Kent - Initial version
|
|
// --------------------------------------------------------------------
|
|
|
|
#include "G4VoxelLimits.hh"
|
|
|
|
#include "G4ios.hh"
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Further restrict limits
|
|
// No checks for illegal restrictions
|
|
//
|
|
void G4VoxelLimits::AddLimit( const EAxis pAxis,
|
|
const G4double pMin,
|
|
const G4double pMax )
|
|
{
|
|
if ( pAxis == kXAxis )
|
|
{
|
|
if ( pMin > fxAxisMin ) fxAxisMin = pMin ;
|
|
if ( pMax < fxAxisMax ) fxAxisMax = pMax ;
|
|
}
|
|
else if ( pAxis == kYAxis )
|
|
{
|
|
if ( pMin > fyAxisMin ) fyAxisMin = pMin ;
|
|
if ( pMax < fyAxisMax ) fyAxisMax = pMax ;
|
|
}
|
|
else
|
|
{
|
|
assert( pAxis == kZAxis ) ;
|
|
|
|
if ( pMin > fzAxisMin ) fzAxisMin = pMin ;
|
|
if ( pMax < fzAxisMax ) fzAxisMax = pMax ;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ClipToLimits
|
|
//
|
|
// Clip the line segment pStart->pEnd to the volume described by the
|
|
// current limits. Return true if the line remains after clipping,
|
|
// else false, and leave the vectors in an undefined state.
|
|
//
|
|
// Process:
|
|
//
|
|
// Use Cohen-Sutherland clipping in 3D
|
|
// [Fundamentals of Interactive Computer Graphics,Foley & Van Dam]
|
|
//
|
|
G4bool G4VoxelLimits::ClipToLimits( G4ThreeVector& pStart,
|
|
G4ThreeVector& pEnd ) const
|
|
{
|
|
G4int sCode, eCode ;
|
|
G4bool remainsAfterClip ;
|
|
|
|
// Determine if line is trivially inside (both outcodes==0) or outside
|
|
// (logical AND of outcodes !=0)
|
|
|
|
sCode = OutCode(pStart) ;
|
|
eCode = OutCode(pEnd) ;
|
|
|
|
if ( (sCode & eCode) != 0 )
|
|
{
|
|
// Trivially outside, no intersection with region
|
|
|
|
remainsAfterClip = false;
|
|
}
|
|
else if ( sCode == 0 && eCode == 0 )
|
|
{
|
|
// Trivially inside, no intersections
|
|
|
|
remainsAfterClip = true ;
|
|
}
|
|
else
|
|
{
|
|
// Line segment *may* cut volume boundaries
|
|
// At most, one end point is inside
|
|
|
|
G4double x1, y1, z1, x2, y2, z2 ;
|
|
|
|
x1 = pStart.x() ;
|
|
y1 = pStart.y() ;
|
|
z1 = pStart.z() ;
|
|
|
|
x2 = pEnd.x() ;
|
|
y2 = pEnd.y() ;
|
|
z2 = pEnd.z() ;
|
|
|
|
while ( sCode != eCode ) // Loop checking, 06.08.2015, G.Cosmo
|
|
{
|
|
// Copy vectors to work variables x1-z1,x2-z2
|
|
// Ensure x1-z1 lies outside volume, swapping vectors and outcodes
|
|
// if necessary
|
|
|
|
if ( sCode != 0 )
|
|
{
|
|
if ( (sCode & 0x01) != 0 ) // Clip against fxAxisMin
|
|
{
|
|
z1 += (fxAxisMin-x1)*(z2-z1)/(x2-x1);
|
|
y1 += (fxAxisMin-x1)*(y2-y1)/(x2-x1);
|
|
x1 = fxAxisMin;
|
|
}
|
|
else if ( (sCode & 0x02) != 0 ) // Clip against fxAxisMax
|
|
{
|
|
z1 += (fxAxisMax-x1)*(z2-z1)/(x2-x1);
|
|
y1 += (fxAxisMax-x1)*(y2-y1)/(x2-x1);
|
|
x1 = fxAxisMax ;
|
|
}
|
|
else if ( (sCode & 0x04) != 0 ) // Clip against fyAxisMin
|
|
{
|
|
x1 += (fyAxisMin-y1)*(x2-x1)/(y2-y1);
|
|
z1 += (fyAxisMin-y1)*(z2-z1)/(y2-y1);
|
|
y1 = fyAxisMin;
|
|
}
|
|
else if ( (sCode & 0x08) != 0 ) // Clip against fyAxisMax
|
|
{
|
|
x1 += (fyAxisMax-y1)*(x2-x1)/(y2-y1);
|
|
z1 += (fyAxisMax-y1)*(z2-z1)/(y2-y1);
|
|
y1 = fyAxisMax;
|
|
}
|
|
else if ( (sCode & 0x10) != 0 ) // Clip against fzAxisMin
|
|
{
|
|
x1 += (fzAxisMin-z1)*(x2-x1)/(z2-z1);
|
|
y1 += (fzAxisMin-z1)*(y2-y1)/(z2-z1);
|
|
z1 = fzAxisMin;
|
|
}
|
|
else if ( (sCode & 0x20) != 0 ) // Clip against fzAxisMax
|
|
{
|
|
x1 += (fzAxisMax-z1)*(x2-x1)/(z2-z1);
|
|
y1 += (fzAxisMax-z1)*(y2-y1)/(z2-z1);
|
|
z1 = fzAxisMax;
|
|
}
|
|
}
|
|
if ( eCode != 0 ) // Clip 2nd end: repeat of 1st, but 1<>2
|
|
{
|
|
if ( (eCode & 0x01) != 0 ) // Clip against fxAxisMin
|
|
{
|
|
z2 += (fxAxisMin-x2)*(z1-z2)/(x1-x2);
|
|
y2 += (fxAxisMin-x2)*(y1-y2)/(x1-x2);
|
|
x2 = fxAxisMin;
|
|
}
|
|
else if ( (eCode & 0x02) != 0 ) // Clip against fxAxisMax
|
|
{
|
|
z2 += (fxAxisMax-x2)*(z1-z2)/(x1-x2);
|
|
y2 += (fxAxisMax-x2)*(y1-y2)/(x1-x2);
|
|
x2 = fxAxisMax;
|
|
}
|
|
else if ( (eCode & 0x04) != 0 ) // Clip against fyAxisMin
|
|
{
|
|
x2 += (fyAxisMin-y2)*(x1-x2)/(y1-y2);
|
|
z2 += (fyAxisMin-y2)*(z1-z2)/(y1-y2);
|
|
y2 = fyAxisMin;
|
|
}
|
|
else if ((eCode&0x08) != 0) // Clip against fyAxisMax
|
|
{
|
|
x2 += (fyAxisMax-y2)*(x1-x2)/(y1-y2);
|
|
z2 += (fyAxisMax-y2)*(z1-z2)/(y1-y2);
|
|
y2 = fyAxisMax;
|
|
}
|
|
else if ( (eCode & 0x10) != 0 ) // Clip against fzAxisMin
|
|
{
|
|
x2 += (fzAxisMin-z2)*(x1-x2)/(z1-z2);
|
|
y2 += (fzAxisMin-z2)*(y1-y2)/(z1-z2);
|
|
z2 = fzAxisMin;
|
|
}
|
|
else if ( (eCode & 0x20) != 0 ) // Clip against fzAxisMax
|
|
{
|
|
x2 += (fzAxisMax-z2)*(x1-x2)/(z1-z2);
|
|
y2 += (fzAxisMax-z2)*(y1-y2)/(z1-z2);
|
|
z2 = fzAxisMax;
|
|
}
|
|
}
|
|
pStart = G4ThreeVector(x1,y1,z1);
|
|
pEnd = G4ThreeVector(x2,y2,z2);
|
|
sCode = OutCode(pStart);
|
|
eCode = OutCode(pEnd);
|
|
}
|
|
remainsAfterClip = sCode == 0 && eCode == 0;
|
|
}
|
|
return remainsAfterClip;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Calculate the `outcode' for the specified vector:
|
|
// The following bits are set:
|
|
// 0 pVec.x()<fxAxisMin && IsXLimited()
|
|
// 1 pVec.x()>fxAxisMax && IsXLimited()
|
|
// 2 pVec.y()<fyAxisMin && IsYLimited()
|
|
// 3 pVec.y()>fyAxisMax && IsYLimited()
|
|
// 4 pVec.z()<fzAxisMin && IsZLimited()
|
|
// 5 pVec.z()>fzAxisMax && IsZLimited()
|
|
//
|
|
G4int G4VoxelLimits::OutCode( const G4ThreeVector& pVec ) const
|
|
{
|
|
G4int code = 0 ; // The outcode
|
|
|
|
if ( IsXLimited() )
|
|
{
|
|
if ( pVec.x() < fxAxisMin ) code |= 0x01 ;
|
|
if ( pVec.x() > fxAxisMax ) code |= 0x02 ;
|
|
}
|
|
if ( IsYLimited() )
|
|
{
|
|
if ( pVec.y() < fyAxisMin ) code |= 0x04 ;
|
|
if ( pVec.y() > fyAxisMax ) code |= 0x08 ;
|
|
}
|
|
if (IsZLimited())
|
|
{
|
|
if ( pVec.z() < fzAxisMin ) code |= 0x10 ;
|
|
if ( pVec.z() > fzAxisMax ) code |= 0x20 ;
|
|
}
|
|
return code;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::ostream& operator << (std::ostream& os, const G4VoxelLimits& pLim)
|
|
{
|
|
os << "{";
|
|
if (pLim.IsXLimited())
|
|
{
|
|
os << "(" << pLim.GetMinXExtent()
|
|
<< "," << pLim.GetMaxXExtent() << ") ";
|
|
}
|
|
else
|
|
{
|
|
os << "(-,-) ";
|
|
}
|
|
if (pLim.IsYLimited())
|
|
{
|
|
os << "(" << pLim.GetMinYExtent()
|
|
<< "," << pLim.GetMaxYExtent() << ") ";
|
|
}
|
|
else
|
|
{
|
|
os << "(-,-) ";
|
|
}
|
|
if (pLim.IsZLimited())
|
|
{
|
|
os << "(" << pLim.GetMinZExtent()
|
|
<< "," << pLim.GetMaxZExtent() << ")";
|
|
}
|
|
else
|
|
{
|
|
os << "(-,-)";
|
|
}
|
|
os << "}";
|
|
return os;
|
|
}
|