Import Geant4 2.0.0 source tree
This commit is contained in:
@@ -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
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user