Import Geant4 2.0.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-08 15:42:07 +02:00
parent 103bda00c8
commit e7d7193284
3106 changed files with 171117 additions and 90550 deletions
@@ -0,0 +1,441 @@
// 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: G4ClippablePolygon.cc,v 1.2 2000/04/18 19:07:11 davidw Exp $
// GEANT4 tag $Name: geant4-02-00 $
//
//
// --------------------------------------------------------------------
// GEANT 4 class source file
//
//
// G4ClippablePolygon.cc
//
// Includes code from G4VSolid (P. Kent, V. Grichine, J. Allison)
//
// --------------------------------------------------------------------
#include "G4ClippablePolygon.hh"
#include "G4VoxelLimits.hh"
//
// AddVertexInOrder
//
void G4ClippablePolygon::AddVertexInOrder( const G4ThreeVector vertex )
{
vertices.append( vertex );
}
//
// ClearAllVertices
//
void G4ClippablePolygon::ClearAllVertices()
{
vertices.clear();
}
//
// Clip
//
G4bool G4ClippablePolygon::Clip( const G4VoxelLimits &voxelLimit )
{
if (voxelLimit.IsLimited()) {
ClipAlongOneAxis( voxelLimit, kXAxis );
ClipAlongOneAxis( voxelLimit, kYAxis );
ClipAlongOneAxis( voxelLimit, kZAxis );
}
return (vertices.entries() > 0);
}
//
// PartialClip
//
// Clip, while ignoring the indicated axis
//
G4bool G4ClippablePolygon::PartialClip( const G4VoxelLimits &voxelLimit, const EAxis IgnoreMe )
{
if (voxelLimit.IsLimited()) {
if (IgnoreMe != kXAxis) ClipAlongOneAxis( voxelLimit, kXAxis );
if (IgnoreMe != kYAxis) ClipAlongOneAxis( voxelLimit, kYAxis );
if (IgnoreMe != kZAxis) ClipAlongOneAxis( voxelLimit, kZAxis );
}
return (vertices.entries() > 0);
}
//
// GetExtent
//
G4bool G4ClippablePolygon::GetExtent( const EAxis axis,
G4double &min, G4double &max ) const
{
//
// Okay, how many entries do we have?
//
G4int noLeft = vertices.entries();
//
// Return false if nothing is left
//
if (noLeft == 0) return false;
//
// Initialize min and max to our first vertex
//
min = max = vertices(0).operator()( axis );
//
// Compare to the rest
//
G4int i;
for( i=1; i<noLeft; i++ ) {
G4double component = vertices(i).operator()( axis );
if (component < min )
min = component;
else if (component > max )
max = component;
}
return true;
}
//
// GetMinPoint
//
// Returns pointer to minimum point along the specified axis.
// Take care! Do not use pointer after destroying parent polygon.
//
const G4ThreeVector *G4ClippablePolygon::GetMinPoint( const EAxis axis ) const
{
G4int noLeft = vertices.entries();
if (noLeft==0) G4Exception( "G4ClippablePolygon::GetMinPoint -- empty polygon" );
const G4ThreeVector *answer = &(vertices[0]);
G4double min = answer->operator()(axis);
G4int i;
for( i=1; i<noLeft; i++ ) {
G4double component = vertices(i).operator()( axis );
if (component < min) {
answer = &(vertices[i]);
min = component;
}
}
return answer;
}
//
// GetMaxPoint
//
// Returns pointer to maximum point along the specified axis.
// Take care! Do not use pointer after destroying parent polygon.
//
const G4ThreeVector *G4ClippablePolygon::GetMaxPoint( const EAxis axis ) const
{
G4int noLeft = vertices.entries();
if (noLeft==0) G4Exception( "G4ClippablePolygon::GetMaxPoint -- empty polygon" );
const G4ThreeVector *answer = &(vertices[0]);
G4double max = answer->operator()(axis);
G4int i;
for( i=1; i<noLeft; i++ ) {
G4double component = vertices(i).operator()( axis );
if (component > max) {
answer = &(vertices[i]);
max = component;
}
}
return answer;
}
//
// InFrontOf
//
// Decide if this polygon is in "front" of another when
// viewed along the specified axis. For our purposes here,
// it is sufficient to use the minimum extent of the
// polygon along the axis to determine this.
//
// In case the minima of the two polygons are equal,
// we use a more sophisticated test.
//
// Note that it is possible for the two following
// statements to both return true or both return false:
// polygon1.InFrontOf(polygon2)
// polygon2.BehindOf(polygon1)
//
G4bool G4ClippablePolygon::InFrontOf( const G4ClippablePolygon &other, EAxis axis ) const
{
//
// If things are empty, do something semi-sensible
//
G4int noLeft = vertices.entries();
if (noLeft==0) return false;
if (other.Empty()) return true;
//
// Get minimum of other polygon
//
const G4ThreeVector *minPointOther = other.GetMinPoint( axis );
const G4double minOther = minPointOther->operator()(axis);
//
// Get minimum of this polygon
//
const G4ThreeVector *minPoint = GetMinPoint( axis );
const G4double min = minPoint->operator()(axis);
//
// Easy decision
//
if (min < minOther-kCarTolerance) return true; // Clear winner
if (minOther < min-kCarTolerance) return false; // Clear loser
//
// We have a tie (this will not be all that rare since our
// polygons are connected)
//
// Check to see if there is a vertex in the other polygon
// that is behind this one (or vice versa)
//
G4bool answer;
G4ThreeVector normalOther = other.GetNormal();
if (fabs(normalOther(axis)) > fabs(normal(axis))) {
G4double minP, maxP;
GetPlanerExtent( *minPointOther, normalOther, minP, maxP );
answer = (normalOther(axis) > 0) ? (minP < -kCarTolerance) : (maxP > +kCarTolerance);
}
else {
G4double minP, maxP;
other.GetPlanerExtent( *minPoint, normal, minP, maxP );
answer = (normal(axis) > 0) ? (maxP > +kCarTolerance) : (minP < -kCarTolerance);
}
return answer;
}
//
// BehindOf
//
// Decide if this polygon is behind another.
// See notes in method "InFrontOf"
//
G4bool G4ClippablePolygon::BehindOf( const G4ClippablePolygon &other, EAxis axis ) const
{
//
// If things are empty, do something semi-sensible
//
G4int noLeft = vertices.entries();
if (noLeft==0) return false;
if (other.Empty()) return true;
//
// Get minimum of other polygon
//
const G4ThreeVector *maxPointOther = other.GetMaxPoint( axis );
const G4double maxOther = maxPointOther->operator()(axis);
//
// Get minimum of this polygon
//
const G4ThreeVector *maxPoint = GetMaxPoint( axis );
const G4double max = maxPoint->operator()(axis);
//
// Easy decision
//
if (max > maxOther+kCarTolerance) return true; // Clear winner
if (maxOther > max+kCarTolerance) return false; // Clear loser
//
// We have a tie (this will not be all that rare since our
// polygons are connected)
//
// Check to see if there is a vertex in the other polygon
// that is in front of this one (or vice versa)
//
G4bool answer;
G4ThreeVector normalOther = other.GetNormal();
if (fabs(normalOther(axis)) > fabs(normal(axis))) {
G4double minP, maxP;
GetPlanerExtent( *maxPointOther, normalOther, minP, maxP );
answer = (normalOther(axis) > 0) ? (maxP > +kCarTolerance) : (minP < -kCarTolerance);
}
else {
G4double minP, maxP;
other.GetPlanerExtent( *maxPoint, normal, minP, maxP );
answer = (normal(axis) > 0) ? (minP < -kCarTolerance) : (maxP > +kCarTolerance);
}
return answer;
}
//
// GetPlanerExtent
//
// Get min/max distance in or out of a plane
//
G4bool G4ClippablePolygon::GetPlanerExtent( const G4ThreeVector &pointOnPlane,
const G4ThreeVector &planeNormal,
G4double &min, G4double &max ) const
{
//
// Okay, how many entries do we have?
//
G4int noLeft = vertices.entries();
//
// Return false if nothing is left
//
if (noLeft == 0) return false;
//
// Initialize min and max to our first vertex
//
min = max = planeNormal.dot(vertices(0)-pointOnPlane);
//
// Compare to the rest
//
G4int i;
for( i=1; i<noLeft; i++ ) {
G4double component = planeNormal.dot(vertices(i) - pointOnPlane);
if (component < min )
min = component;
else if (component > max )
max = component;
}
return true;
}
//
// Clip along just one axis, as specified in voxelLimit
//
void G4ClippablePolygon::ClipAlongOneAxis( const G4VoxelLimits &voxelLimit, const EAxis axis )
{
if (!voxelLimit.IsLimited(axis)) return;
G4ThreeVectorList tempPolygon;
//
// Build a "simple" voxelLimit that includes only the min extent
// and apply this to our vertices, producing result in tempPolygon
//
G4VoxelLimits simpleLimit1;
simpleLimit1.AddLimit( axis, voxelLimit.GetMinExtent(axis), kInfinity );
ClipToSimpleLimits( vertices, tempPolygon, simpleLimit1 );
//
// If nothing is left from the above clip, we might as well return now
// (but with an empty vertices)
//
if (tempPolygon.entries() == 0) {
vertices.clear();
return;
}
//
// Now do the same, but using a "simple" limit that includes only the max extent.
// Apply this to out tempPolygon, producing result in vertices.
//
G4VoxelLimits simpleLimit2;
simpleLimit2.AddLimit( axis, -kInfinity, voxelLimit.GetMaxExtent(axis) );
ClipToSimpleLimits( tempPolygon, vertices, simpleLimit2 );
//
// If nothing is left, return now
//
if (vertices.entries() == 0) return;
}
// pVoxelLimits must be only limited along one axis, and either the maximum
// along the axis must be +kInfinity, or the minimum -kInfinity
void G4ClippablePolygon::ClipToSimpleLimits( G4ThreeVectorList& pPolygon,
G4ThreeVectorList& outputPolygon,
const G4VoxelLimits& pVoxelLimit )
{
G4int i;
G4int noVertices=pPolygon.entries();
G4ThreeVector vEnd,vStart;
outputPolygon.clear();
for (i=0;i<noVertices;i++)
{
vStart=pPolygon(i);
if (i==noVertices-1)
{
vEnd=pPolygon(0);
}
else
{
vEnd=pPolygon(i+1);
}
if (pVoxelLimit.Inside(vStart))
{
if (pVoxelLimit.Inside(vEnd))
{
// vStart and vEnd inside -> output end point
outputPolygon.insert(vEnd);
}
else
{
// vStart inside, vEnd outside -> output crossing point
pVoxelLimit.ClipToLimits(vStart,vEnd);
outputPolygon.insert(vEnd);
}
}
else
{
if (pVoxelLimit.Inside(vEnd))
{
// vStart outside, vEnd inside -> output inside section
pVoxelLimit.ClipToLimits(vStart,vEnd);
outputPolygon.insert(vStart);
outputPolygon.insert(vEnd);
}
else
// Both point outside -> no output
{
}
}
}
}