Files
geant4/source/geometry/management/src/G4VSolid.cc
T
2016-06-08 15:09:25 +02:00

309 lines
8.9 KiB
C++

// This code implementation is the intellectual property of
// the RD44 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: G4VSolid.cc,v 1.1 1999/01/07 16:07:22 gunter Exp $
// GEANT4 tag $Name: geant4-00-01 $
//
// class G4VSolid
//
// Implementation for solid base class
//
//
// History:
// 10.07.95 P.Kent Added == operator, solid Store entry
// 30.06.95 P.Kent
#include "G4VSolid.hh"
#include "G4SolidStore.hh"
#include "G4VoxelLimits.hh"
// Constructor
// - Copies name
// - Add ourselves to solid Store
G4VSolid::G4VSolid(const G4String& name) :
fshapeName(name)
{
G4SolidStore::GetInstance()->append(this);
}
// Destructor (virtual)
// - Remove ourselves from solid Store
G4VSolid::~G4VSolid()
{
G4SolidStore::GetInstance()->remove(this);
}
// Returns name by value
G4String G4VSolid::GetName() const
{
return fshapeName;
}
void G4VSolid::SetName(const G4String& name)
{
fshapeName=name;
}
// Throw exception if ComputeDimensions called for illegal derived class
void G4VSolid::ComputeDimensions(G4VPVParameterisation* p,
const G4int n,
const G4VPhysicalVolume* pRep)
{
G4Exception("G4VSolid::ComputeDimensions called illegally: not overloaded by derived class");
}
// Calculate the maximum and minimum extents of the convex polygon pPolygon
// along the axis pAxis, within the limits pVoxelLimit
void G4VSolid::CalculateClippedPolygonExtent(G4ThreeVectorList& pPolygon,
const G4VoxelLimits& pVoxelLimit,
const EAxis pAxis,
G4double& pMin, G4double& pMax) const
{
G4int noLeft,i;
G4double component;
ClipPolygon(pPolygon,pVoxelLimit);
noLeft=pPolygon.entries();
if (noLeft)
{
for (i=0;i<noLeft;i++)
{
component=pPolygon(i).operator()(pAxis);
if (component<pMin)
{
pMin=component;
}
else if (component>pMax)
{
pMax=component;
}
}
}
}
// Calculate the maximum and minimum extents of the polygon described
// by the vertices: pSectionIndex->pSectionIndex+1->
// pSectionIndex+2->pSectionIndex+3->pSectionIndex
// in the List pVertices
//
// If the minimum is <pMin pMin is set to the new minimum
// If the maximum is >pMax pMax is set to the new maximum
//
// No modifications are made to pVertices
void G4VSolid::ClipCrossSection(G4ThreeVectorList* pVertices,
const G4int pSectionIndex,
const G4VoxelLimits& pVoxelLimit,
const EAxis pAxis,
G4double& pMin, G4double& pMax) const
{
G4ThreeVectorList polygon;
polygon.append(pVertices->operator()(pSectionIndex));
polygon.append(pVertices->operator()(pSectionIndex+1));
polygon.append(pVertices->operator()(pSectionIndex+2));
polygon.append(pVertices->operator()(pSectionIndex+3));
CalculateClippedPolygonExtent(polygon,pVoxelLimit,pAxis,pMin,pMax);
return;
}
// Calculate the maximum and minimum extents of the polygons
// joining the CrossSections at pSectionIndex->pSectionIndex+3 and
// pSectionIndex+4->pSectionIndex7
//
// in the List pVertices, within the boundaries of the voxel limits pVoxelLimit
//
// If the minimum is <pMin pMin is set to the new minimum
// If the maximum is >pMax pMax is set to the new maximum
//
// No modifications are made to pVertices
void G4VSolid::ClipBetweenSections(G4ThreeVectorList* pVertices,
const G4int pSectionIndex,
const G4VoxelLimits& pVoxelLimit,
const EAxis pAxis,
G4double& pMin, G4double& pMax) const
{
G4ThreeVectorList polygon;
polygon.append(pVertices->operator()(pSectionIndex));
polygon.append(pVertices->operator()(pSectionIndex+4));
polygon.append(pVertices->operator()(pSectionIndex+5));
polygon.append(pVertices->operator()(pSectionIndex+1));
CalculateClippedPolygonExtent(polygon,pVoxelLimit,pAxis,pMin,pMax);
polygon.clear();
polygon.append(pVertices->operator()(pSectionIndex+1));
polygon.append(pVertices->operator()(pSectionIndex+5));
polygon.append(pVertices->operator()(pSectionIndex+6));
polygon.append(pVertices->operator()(pSectionIndex+2));
CalculateClippedPolygonExtent(polygon,pVoxelLimit,pAxis,pMin,pMax);
polygon.clear();
polygon.append(pVertices->operator()(pSectionIndex+2));
polygon.append(pVertices->operator()(pSectionIndex+6));
polygon.append(pVertices->operator()(pSectionIndex+7));
polygon.append(pVertices->operator()(pSectionIndex+3));
CalculateClippedPolygonExtent(polygon,pVoxelLimit,pAxis,pMin,pMax);
polygon.clear();
polygon.append(pVertices->operator()(pSectionIndex+3));
polygon.append(pVertices->operator()(pSectionIndex+7));
polygon.append(pVertices->operator()(pSectionIndex+4));
polygon.append(pVertices->operator()(pSectionIndex));
CalculateClippedPolygonExtent(polygon,pVoxelLimit,pAxis,pMin,pMax);
return;
}
// Clip the convex polygon described by the vertices at
// pSectionIndex ->pSectionIndex+3 within pVertices to the limits pVoxelLimit
//
// Set pMin to the smallest
//
// Calculate the extent of the polygon along pAxis, when clipped to the
// limits pVoxelLimit. If the polygon exists after clippin, set pMin to
// the polygon's minimum extent along the axis if <pMin, and set pMax to
// the polygon's maximum extent along the axis if >pMax.
//
// The polygon is described by a set of vectors, where each vector represents
// a vertex, so that the polygon is described by the vertex sequence:
// 0th->1st 1st->2nd 2nd->... nth->0th
//
// Modifications to the polygon are made
//
// NOTE: Execessive copying during clipping
void G4VSolid::ClipPolygon(G4ThreeVectorList& pPolygon,
const G4VoxelLimits& pVoxelLimit) const
{
G4ThreeVectorList outputPolygon;
if (pVoxelLimit.IsLimited())
{
if (pVoxelLimit.IsXLimited())
{
G4VoxelLimits simpleLimit1;
simpleLimit1.AddLimit(kXAxis,pVoxelLimit.GetMinXExtent(),kInfinity);
ClipPolygonToSimpleLimits(pPolygon,outputPolygon,
simpleLimit1);
pPolygon.clear();
if (!outputPolygon.entries())
{
return;
}
G4VoxelLimits simpleLimit2;
simpleLimit2.AddLimit(kXAxis,-kInfinity,pVoxelLimit.GetMaxXExtent());
ClipPolygonToSimpleLimits(outputPolygon,pPolygon,simpleLimit2);
if (!pPolygon.entries())
{
return;
}
else
{
outputPolygon.clear();
}
}
if (pVoxelLimit.IsYLimited())
{
G4VoxelLimits simpleLimit1;
simpleLimit1.AddLimit(kYAxis,pVoxelLimit.GetMinYExtent(),kInfinity);
ClipPolygonToSimpleLimits(pPolygon,outputPolygon,
simpleLimit1);
// Must always clear pPolygon - for clip to simpleLimit2 and incase of
// early exit
pPolygon.clear();
if (!outputPolygon.entries())
{
return;
}
G4VoxelLimits simpleLimit2;
simpleLimit2.AddLimit(kYAxis,-kInfinity,pVoxelLimit.GetMaxYExtent());
ClipPolygonToSimpleLimits(outputPolygon,pPolygon,simpleLimit2);
if (!pPolygon.entries())
{
return;
}
else
{
outputPolygon.clear();
}
}
if (pVoxelLimit.IsZLimited())
{
G4VoxelLimits simpleLimit1;
simpleLimit1.AddLimit(kZAxis,pVoxelLimit.GetMinZExtent(),kInfinity);
ClipPolygonToSimpleLimits(pPolygon,outputPolygon,
simpleLimit1);
// Must always clear pPolygon - for clip to simpleLimit2 and incase of
// early exit
pPolygon.clear();
if (!outputPolygon.entries())
{
return;
}
G4VoxelLimits simpleLimit2;
simpleLimit2.AddLimit(kZAxis,-kInfinity,pVoxelLimit.GetMaxZExtent());
ClipPolygonToSimpleLimits(outputPolygon,pPolygon,simpleLimit2);
// Return after final clip - no cleanup
}
}
}
// pVoxelLimits must be only limited along one axis, and either the maximum
// along the axis must be +kInfinity, or the minimum -kInfinity
void G4VSolid::ClipPolygonToSimpleLimits(G4ThreeVectorList& pPolygon,
G4ThreeVectorList& outputPolygon,
const G4VoxelLimits& pVoxelLimit) const
{
G4int i;
G4int noVertices=pPolygon.entries();
G4ThreeVector vEnd,vStart;
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
{
}
}
}
}