317 lines
8.5 KiB
C++
317 lines
8.5 KiB
C++
//
|
|
// ********************************************************************
|
|
// * 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: G4VoxelLimits.cc,v 1.7 2002/04/19 08:20:23 gcosmo Exp $
|
|
// GEANT4 tag $Name: geant4-05-00 $
|
|
//
|
|
// class G4VoxelLimits
|
|
//
|
|
// Implementation
|
|
//
|
|
// History:
|
|
//
|
|
// 14.03.02 V. Grichine, cosmetics
|
|
// 13.07.95 P.Kent Initial version
|
|
|
|
#include "G4VoxelLimits.hh"
|
|
|
|
#include "G4ios.hh"
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Empty constructor and destructor
|
|
//
|
|
|
|
G4VoxelLimits::G4VoxelLimits()
|
|
: fxAxisMin(-kInfinity),fxAxisMax(kInfinity),
|
|
fyAxisMin(-kInfinity),fyAxisMax(kInfinity),
|
|
fzAxisMin(-kInfinity),fzAxisMax(kInfinity)
|
|
{
|
|
}
|
|
|
|
G4VoxelLimits::~G4VoxelLimits()
|
|
{
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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 )
|
|
{
|
|
// 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() ;
|
|
/*
|
|
if( abs(x1-x2) < kCarTolerance*kCarTolerance)
|
|
{
|
|
G4cout<<"x1 = "<<x1<<"\t"<<"x2 = "<<x2<<G4endl;
|
|
}
|
|
if( abs(y1-y2) < kCarTolerance*kCarTolerance)
|
|
{
|
|
G4cout<<"y1 = "<<y1<<"\t"<<"y2 = "<<y2<<G4endl;
|
|
}
|
|
if( abs(z1-z2) < kCarTolerance*kCarTolerance)
|
|
{
|
|
G4cout<<"z1 = "<<z1<<"\t"<<"z2 = "<<z2<<G4endl;
|
|
}
|
|
*/
|
|
while ( sCode != eCode )
|
|
{
|
|
// Copy vectors to work variables x1-z1,x2-z2
|
|
// Ensure x1-z1 lies outside volume, swapping vectors and outcodes
|
|
// if necessary
|
|
|
|
if ( sCode )
|
|
{
|
|
if ( sCode & 0x01 ) // Clip against fxAxisMin
|
|
{
|
|
z1 += (fxAxisMin-x1)*(z2-z1)/(x2-x1);
|
|
y1 += (fxAxisMin-x1)*(y2-y1)/(x2-x1);
|
|
x1 = fxAxisMin;
|
|
}
|
|
else if ( sCode & 0x02 ) // Clip against fxAxisMax
|
|
{
|
|
z1 += (fxAxisMax-x1)*(z2-z1)/(x2-x1);
|
|
y1 += (fxAxisMax-x1)*(y2-y1)/(x2-x1);
|
|
x1 = fxAxisMax ;
|
|
}
|
|
else if ( sCode & 0x04 ) // Clip against fyAxisMin
|
|
{
|
|
x1 += (fyAxisMin-y1)*(x2-x1)/(y2-y1);
|
|
z1 += (fyAxisMin-y1)*(z2-z1)/(y2-y1);
|
|
y1 = fyAxisMin;
|
|
}
|
|
else if ( sCode & 0x08 ) // Clip against fyAxisMax
|
|
{
|
|
x1 += (fyAxisMax-y1)*(x2-x1)/(y2-y1);
|
|
z1 += (fyAxisMax-y1)*(z2-z1)/(y2-y1);
|
|
y1 = fyAxisMax;
|
|
}
|
|
else if ( sCode & 0x10 ) // Clip against fzAxisMin
|
|
{
|
|
x1 += (fzAxisMin-z1)*(x2-x1)/(z2-z1);
|
|
y1 += (fzAxisMin-z1)*(y2-y1)/(z2-z1);
|
|
z1 = fzAxisMin;
|
|
}
|
|
else if ( sCode & 0x20 ) // Clip against fzAxisMax
|
|
{
|
|
x1 += (fzAxisMax-z1)*(x2-x1)/(z2-z1);
|
|
y1 += (fzAxisMax-z1)*(y2-y1)/(z2-z1);
|
|
z1 = fzAxisMax;
|
|
}
|
|
}
|
|
if ( eCode ) // Clip 2nd end: repeat of 1st, but 1<>2
|
|
{
|
|
if ( eCode & 0x01 ) // Clip against fxAxisMin
|
|
{
|
|
z2 += (fxAxisMin-x2)*(z1-z2)/(x1-x2);
|
|
y2 += (fxAxisMin-x2)*(y1-y2)/(x1-x2);
|
|
x2 = fxAxisMin;
|
|
}
|
|
else if ( eCode & 0x02 ) // Clip against fxAxisMax
|
|
{
|
|
z2 += (fxAxisMax-x2)*(z1-z2)/(x1-x2);
|
|
y2 += (fxAxisMax-x2)*(y1-y2)/(x1-x2);
|
|
x2 = fxAxisMax;
|
|
}
|
|
else if ( eCode & 0x04 ) // Clip against fyAxisMin
|
|
{
|
|
x2 += (fyAxisMin-y2)*(x1-x2)/(y1-y2);
|
|
z2 += (fyAxisMin-y2)*(z1-z2)/(y1-y2);
|
|
y2 = fyAxisMin;
|
|
}
|
|
else if (eCode&0x08) // Clip against fyAxisMax
|
|
{
|
|
x2 += (fyAxisMax-y2)*(x1-x2)/(y1-y2);
|
|
z2 += (fyAxisMax-y2)*(z1-z2)/(y1-y2);
|
|
y2 = fyAxisMax;
|
|
}
|
|
else if ( eCode & 0x10 ) // Clip against fzAxisMin
|
|
{
|
|
x2 += (fzAxisMin-z2)*(x1-x2)/(z1-z2);
|
|
y2 += (fzAxisMin-z2)*(y1-y2)/(z1-z2);
|
|
z2 = fzAxisMin;
|
|
}
|
|
else if ( eCode & 0x20 ) // Clip against fzAxisMax
|
|
{
|
|
x2 += (fzAxisMax-z2)*(x1-x2)/(z1-z2);
|
|
y2 += (fzAxisMax-z2)*(y1-y2)/(z1-z2);
|
|
z2 = fzAxisMax;
|
|
}
|
|
}
|
|
// G4endl; G4cout<<"x1 = "<<x1<<"\t"<<"x2 = "<<x2<<G4endl<<G4endl;
|
|
pStart = G4ThreeVector(x1,y1,z1);
|
|
pEnd = G4ThreeVector(x2,y2,z2);
|
|
sCode = OutCode(pStart);
|
|
eCode = OutCode(pEnd);
|
|
}
|
|
if ( sCode == 0 && eCode == 0 ) remainsAfterClip = true;
|
|
else remainsAfterClip = false;
|
|
}
|
|
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;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
G4std::ostream& operator << (G4std::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;
|
|
}
|