Files
geant4/source/geometry/solids/specific/src/G4Tet.cc
T
2016-06-09 15:37:50 +02:00

767 lines
24 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 intellectual property of the *
// * Vanderbilt University Free Electron Laser Center *
// * Vanderbilt University, Nashville, TN, USA *
// * Development supported by: *
// * United States MFEL program under grant FA9550-04-1-0045 *
// * and NASA under contract number NNG04CT05P *
// * Written by Marcus H. Mendenhall and Robert A. Weller. *
// * *
// * Contributed to the Geant4 Core, January, 2005. *
// * *
// ********************************************************************
//
// $Id: G4Tet.cc,v 1.11 2006/11/13 08:58:03 gcosmo Exp $
// GEANT4 tag $Name: geant4-09-01 $
//
// class G4Tet
//
// Implementation for G4Tet class
//
// History:
//
// 20040903 - Marcus Mendenhall, created G4Tet
// 20041101 - Marcus Mendenhall, optimized constant dot products with
// fCdotNijk values
// 20041101 - MHM removed tracking error by clipping DistanceToOut to 0
// for surface cases
// 20041101 - MHM many speed optimizations in if statements
// 20041101 - MHM changed vdotn comparisons to 1e-12 instead of 0.0 to
// avoid nearly-parallel problems
// 20041102 - MHM Added extra distance into solid to DistanceToIn(p,v)
// hit testing
// 20041102 - MHM added ability to check for degeneracy without throwing
// G4Exception
// 20041103 - MHM removed many unused variables from class
// 20040803 - Dionysios Anninos, added GetPointOnSurface() method
// 20061112 - MHM added code for G4VSolid GetSurfaceArea()
//
// --------------------------------------------------------------------
#include "G4Tet.hh"
const char G4Tet::CVSVers[]="$Id: G4Tet.cc,v 1.11 2006/11/13 08:58:03 gcosmo Exp $";
#include "G4VoxelLimits.hh"
#include "G4AffineTransform.hh"
#include "G4VPVParameterisation.hh"
#include "Randomize.hh"
#include "G4VGraphicsScene.hh"
#include "G4Polyhedron.hh"
#include "G4NURBS.hh"
#include "G4NURBSbox.hh"
#include "G4VisExtent.hh"
#include "G4ThreeVector.hh"
#include <cmath>
using namespace CLHEP;
////////////////////////////////////////////////////////////////////////
//
// Constructor - create a tetrahedron
// This class is implemented separately from general polyhedra,
// because the simplex geometry can be computed very quickly,
// which may become important in situations imported from mesh generators,
// in which a very large number of G4Tets are created.
// A Tet has all of its geometrical information precomputed
G4Tet::G4Tet(const G4String& pName,
G4ThreeVector anchor,
G4ThreeVector p2,
G4ThreeVector p3,
G4ThreeVector p4, G4bool *degeneracyFlag)
: G4VSolid(pName), fpPolyhedron(0), warningFlag(0)
{
// fV<x><y> is vector from vertex <y> to vertex <x>
//
G4ThreeVector fV21=p2-anchor;
G4ThreeVector fV31=p3-anchor;
G4ThreeVector fV41=p4-anchor;
// make sure this is a correctly oriented set of points for the tetrahedron
//
G4double signed_vol=fV21.cross(fV31).dot(fV41);
if(signed_vol<0.0)
{
G4ThreeVector temp(p4);
p4=p3;
p3=temp;
temp=fV41;
fV41=fV31;
fV31=temp;
}
fCubicVolume = std::abs(signed_vol) / 6.;
G4ThreeVector fV24=p2-p4;
G4ThreeVector fV43=p4-p3;
G4ThreeVector fV32=p3-p2;
fXMin=std::min(std::min(std::min(anchor.x(), p2.x()),p3.x()),p4.x());
fXMax=std::max(std::max(std::max(anchor.x(), p2.x()),p3.x()),p4.x());
fYMin=std::min(std::min(std::min(anchor.y(), p2.y()),p3.y()),p4.y());
fYMax=std::max(std::max(std::max(anchor.y(), p2.y()),p3.y()),p4.y());
fZMin=std::min(std::min(std::min(anchor.z(), p2.z()),p3.z()),p4.z());
fZMax=std::max(std::max(std::max(anchor.z(), p2.z()),p3.z()),p4.z());
fDx=(fXMax-fXMin)*0.5; fDy=(fYMax-fYMin)*0.5; fDz=(fZMax-fZMin)*0.5;
fMiddle=G4ThreeVector(fXMax+fXMin, fYMax+fYMin, fZMax+fZMin)*0.5;
fMaxSize=std::max(std::max(std::max((anchor-fMiddle).mag(),
(p2-fMiddle).mag()),
(p3-fMiddle).mag()),
(p4-fMiddle).mag());
G4bool degenerate=std::abs(signed_vol) < 1e-9*fMaxSize*fMaxSize*fMaxSize;
if(degeneracyFlag) *degeneracyFlag=degenerate;
else if (degenerate)
{
G4Exception("G4Tet::G4Tet()", "InvalidSetup", FatalException,
"Degenerate tetrahedron not allowed.");
}
fTol=1e-9*(std::abs(fXMin)+std::abs(fXMax)+std::abs(fYMin)
+std::abs(fYMax)+std::abs(fZMin)+std::abs(fZMax));
//fTol=kCarTolerance;
fAnchor=anchor;
fP2=p2;
fP3=p3;
fP4=p4;
G4ThreeVector fCenter123=(anchor+p2+p3)*(1.0/3.0); // face center
G4ThreeVector fCenter134=(anchor+p4+p3)*(1.0/3.0);
G4ThreeVector fCenter142=(anchor+p4+p2)*(1.0/3.0);
G4ThreeVector fCenter234=(p2+p3+p4)*(1.0/3.0);
// compute area of each triangular face by cross product
// and sum for total surface area
G4ThreeVector normal123=fV31.cross(fV21);
G4ThreeVector normal134=fV41.cross(fV31);
G4ThreeVector normal142=fV21.cross(fV41);
G4ThreeVector normal234=fV32.cross(fV43);
fSurfaceArea=(
normal123.mag()+
normal134.mag()+
normal142.mag()+
normal234.mag()
)/2.0;
fNormal123=normal123.unit();
fNormal134=normal134.unit();
fNormal142=normal142.unit();
fNormal234=normal234.unit();
fCdotN123=fCenter123.dot(fNormal123);
fCdotN134=fCenter134.dot(fNormal134);
fCdotN142=fCenter142.dot(fNormal142);
fCdotN234=fCenter234.dot(fNormal234);
}
//////////////////////////////////////////////////////////////////////////
//
// Fake default constructor - sets only member data and allocates memory
// for usage restricted to object persistency.
//
G4Tet::G4Tet( __void__& a )
: G4VSolid(a), fCubicVolume(0.), fSurfaceArea(0.), fpPolyhedron(0),
fAnchor(0,0,0), fP2(0,0,0), fP3(0,0,0), fP4(0,0,0), fMiddle(0,0,0),
fNormal123(0,0,0), fNormal142(0,0,0), fNormal134(0,0,0),
fNormal234(0,0,0), warningFlag(0),
fCdotN123(0.), fCdotN142(0.), fCdotN134(0.), fCdotN234(0.),
fXMin(0.), fXMax(0.), fYMin(0.), fYMax(0.), fZMin(0.), fZMax(0.),
fDx(0.), fDy(0.), fDz(0.), fTol(0.), fMaxSize(0.)
{
}
//////////////////////////////////////////////////////////////////////////
//
// Destructor
G4Tet::~G4Tet()
{
delete fpPolyhedron;
}
//////////////////////////////////////////////////////////////////////////
//
// CheckDegeneracy
G4bool G4Tet::CheckDegeneracy( G4ThreeVector anchor,
G4ThreeVector p2,
G4ThreeVector p3,
G4ThreeVector p4 )
{
G4bool result;
G4Tet *object=new G4Tet("temp",anchor,p2,p3,p4,&result);
delete object;
return result;
}
//////////////////////////////////////////////////////////////////////////
//
// Dispatch to parameterisation for replication mechanism dimension
// computation & modification.
void G4Tet::ComputeDimensions(G4VPVParameterisation* ,
const G4int ,
const G4VPhysicalVolume* )
{
}
//////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
G4bool G4Tet::CalculateExtent(const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax) const
{
G4double xMin,xMax;
G4double yMin,yMax;
G4double zMin,zMax;
if (pTransform.IsRotated())
{
G4ThreeVector pp0=pTransform.TransformPoint(fAnchor);
G4ThreeVector pp1=pTransform.TransformPoint(fP2);
G4ThreeVector pp2=pTransform.TransformPoint(fP3);
G4ThreeVector pp3=pTransform.TransformPoint(fP4);
xMin = std::min(std::min(std::min(pp0.x(), pp1.x()),pp2.x()),pp3.x());
xMax = std::max(std::max(std::max(pp0.x(), pp1.x()),pp2.x()),pp3.x());
yMin = std::min(std::min(std::min(pp0.y(), pp1.y()),pp2.y()),pp3.y());
yMax = std::max(std::max(std::max(pp0.y(), pp1.y()),pp2.y()),pp3.y());
zMin = std::min(std::min(std::min(pp0.z(), pp1.z()),pp2.z()),pp3.z());
zMax = std::max(std::max(std::max(pp0.z(), pp1.z()),pp2.z()),pp3.z());
}
else
{
G4double xoffset = pTransform.NetTranslation().x() ;
xMin = xoffset + fXMin;
xMax = xoffset + fXMax;
G4double yoffset = pTransform.NetTranslation().y() ;
yMin = yoffset + fYMin;
yMax = yoffset + fYMax;
G4double zoffset = pTransform.NetTranslation().z() ;
zMin = zoffset + fZMin;
zMax = zoffset + fZMax;
}
if (pVoxelLimit.IsXLimited())
{
if ( (xMin > pVoxelLimit.GetMaxXExtent()+fTol) ||
(xMax < pVoxelLimit.GetMinXExtent()-fTol) ) { return false; }
else
{
xMin = std::max(xMin, pVoxelLimit.GetMinXExtent());
xMax = std::min(xMax, pVoxelLimit.GetMaxXExtent());
}
}
if (pVoxelLimit.IsYLimited())
{
if ( (yMin > pVoxelLimit.GetMaxYExtent()+fTol) ||
(yMax < pVoxelLimit.GetMinYExtent()-fTol) ) { return false; }
else
{
yMin = std::max(yMin, pVoxelLimit.GetMinYExtent());
yMax = std::min(yMax, pVoxelLimit.GetMaxYExtent());
}
}
if (pVoxelLimit.IsZLimited())
{
if ( (zMin > pVoxelLimit.GetMaxZExtent()+fTol) ||
(zMax < pVoxelLimit.GetMinZExtent()-fTol) ) { return false; }
else
{
zMin = std::max(zMin, pVoxelLimit.GetMinZExtent());
zMax = std::min(zMax, pVoxelLimit.GetMaxZExtent());
}
}
switch (pAxis)
{
case kXAxis:
pMin=xMin;
pMax=xMax;
break;
case kYAxis:
pMin=yMin;
pMax=yMax;
break;
case kZAxis:
pMin=zMin;
pMax=zMax;
break;
default:
break;
}
return true;
}
/////////////////////////////////////////////////////////////////////////
//
// Return whether point inside/outside/on surface, using tolerance
EInside G4Tet::Inside(const G4ThreeVector& p) const
{
G4double r123, r134, r142, r234;
// this is written to allow if-statement truncation so the outside test
// (where most of the world is) can fail very quickly and efficiently
if ( (r123=p.dot(fNormal123)-fCdotN123) > fTol ||
(r134=p.dot(fNormal134)-fCdotN134) > fTol ||
(r142=p.dot(fNormal142)-fCdotN142) > fTol ||
(r234=p.dot(fNormal234)-fCdotN234) > fTol )
{
return kOutside; // at least one is out!
}
else if( (r123 < -fTol)&&(r134 < -fTol)&&(r142 < -fTol)&&(r234 < -fTol) )
{
return kInside; // all are definitively inside
}
else
{
return kSurface; // too close to tell
}
}
///////////////////////////////////////////////////////////////////////
//
// Calculate side nearest to p, and return normal
// If two sides are equidistant, normal of first side (x/y/z)
// encountered returned.
// This assumes that we are looking from the inside!
G4ThreeVector G4Tet::SurfaceNormal( const G4ThreeVector& p) const
{
G4double r123=std::abs(p.dot(fNormal123)-fCdotN123);
G4double r134=std::abs(p.dot(fNormal134)-fCdotN134);
G4double r142=std::abs(p.dot(fNormal142)-fCdotN142);
G4double r234=std::abs(p.dot(fNormal234)-fCdotN234);
if( (r123<=r134) && (r123<=r142) && (r123<=r234) ) { return fNormal123; }
else if ( (r134<=r142) && (r134<=r234) ) { return fNormal134; }
else if (r142 <= r234) { return fNormal142; }
return fNormal234;
}
///////////////////////////////////////////////////////////////////////////
//
// Calculate distance to box from an outside point
// - return kInfinity if no intersection.
// All this is very unrolled, for speed.
G4double G4Tet::DistanceToIn(const G4ThreeVector& p,
const G4ThreeVector& v) const
{
G4ThreeVector vu(v.unit()), hp;
G4double vdotn, t, tmin=kInfinity;
G4double extraDistance=10.0*fTol; // a little ways into the solid
vdotn=-vu.dot(fNormal123);
if(vdotn > 1e-12)
{ // this is a candidate face, since it is pointing at us
t=(p.dot(fNormal123)-fCdotN123)/vdotn; // # distance to intersection
if( (t>=-fTol) && (t<tmin) )
{ // if not true, we're going away from this face or it's not close
hp=p+vu*(t+extraDistance); // a little beyond point of intersection
if ( ( hp.dot(fNormal134)-fCdotN134 < 0.0 ) &&
( hp.dot(fNormal142)-fCdotN142 < 0.0 ) &&
( hp.dot(fNormal234)-fCdotN234 < 0.0 ) )
{
tmin=t;
}
}
}
vdotn=-vu.dot(fNormal134);
if(vdotn > 1e-12)
{ // # this is a candidate face, since it is pointing at us
t=(p.dot(fNormal134)-fCdotN134)/vdotn; // # distance to intersection
if( (t>=-fTol) && (t<tmin) )
{ // if not true, we're going away from this face
hp=p+vu*(t+extraDistance); // a little beyond point of intersection
if ( ( hp.dot(fNormal123)-fCdotN123 < 0.0 ) &&
( hp.dot(fNormal142)-fCdotN142 < 0.0 ) &&
( hp.dot(fNormal234)-fCdotN234 < 0.0 ) )
{
tmin=t;
}
}
}
vdotn=-vu.dot(fNormal142);
if(vdotn > 1e-12)
{ // # this is a candidate face, since it is pointing at us
t=(p.dot(fNormal142)-fCdotN142)/vdotn; // # distance to intersection
if( (t>=-fTol) && (t<tmin) )
{ // if not true, we're going away from this face
hp=p+vu*(t+extraDistance); // a little beyond point of intersection
if ( ( hp.dot(fNormal123)-fCdotN123 < 0.0 ) &&
( hp.dot(fNormal134)-fCdotN134 < 0.0 ) &&
( hp.dot(fNormal234)-fCdotN234 < 0.0 ) )
{
tmin=t;
}
}
}
vdotn=-vu.dot(fNormal234);
if(vdotn > 1e-12)
{ // # this is a candidate face, since it is pointing at us
t=(p.dot(fNormal234)-fCdotN234)/vdotn; // # distance to intersection
if( (t>=-fTol) && (t<tmin) )
{ // if not true, we're going away from this face
hp=p+vu*(t+extraDistance); // a little beyond point of intersection
if ( ( hp.dot(fNormal123)-fCdotN123 < 0.0 ) &&
( hp.dot(fNormal134)-fCdotN134 < 0.0 ) &&
( hp.dot(fNormal142)-fCdotN142 < 0.0 ) )
{
tmin=t;
}
}
}
return std::max(0.0,tmin);
}
//////////////////////////////////////////////////////////////////////////
//
// Approximate distance to tet.
// returns distance to sphere centered on bounding box
// - If inside return 0
G4double G4Tet::DistanceToIn(const G4ThreeVector& p) const
{
G4double dd=(p-fMiddle).mag() - fMaxSize - fTol;
return std::max(0.0, dd);
}
/////////////////////////////////////////////////////////////////////////
//
// Calcluate distance to surface of box from inside
// by calculating distances to box's x/y/z planes.
// Smallest distance is exact distance to exiting.
G4double G4Tet::DistanceToOut( const G4ThreeVector& p,const G4ThreeVector& v,
const G4bool calcNorm,
G4bool *validNorm, G4ThreeVector *n) const
{
G4ThreeVector vu(v.unit());
G4double t1=kInfinity,t2=kInfinity,t3=kInfinity,t4=kInfinity, vdotn, tt;
vdotn=vu.dot(fNormal123);
if(vdotn > 1e-12) // #we're heading towards this face, so it is a candidate
{
t1=(fCdotN123-p.dot(fNormal123))/vdotn; // # distance to intersection
}
vdotn=vu.dot(fNormal134);
if(vdotn > 1e-12) // #we're heading towards this face, so it is a candidate
{
t2=(fCdotN134-p.dot(fNormal134))/vdotn; // # distance to intersection
}
vdotn=vu.dot(fNormal142);
if(vdotn > 1e-12) // #we're heading towards this face, so it is a candidate
{
t3=(fCdotN142-p.dot(fNormal142))/vdotn; // # distance to intersection
}
vdotn=vu.dot(fNormal234);
if(vdotn > 1e-12) // #we're heading towards this face, so it is a candidate
{
t4=(fCdotN234-p.dot(fNormal234))/vdotn; // # distance to intersection
}
tt=std::min(std::min(std::min(t1,t2),t3),t4);
if (warningFlag && (tt == kInfinity || tt < -fTol))
{
DumpInfo();
G4cout << "p = " << p / mm << "mm" << G4endl;
G4cout << "v = " << v << G4endl;
G4cout << "t1, t2, t3, t4 (mm) "
<< t1/mm << ", " << t2/mm << ", " << t3/mm << ", " << t4/mm
<< G4endl << G4endl;
G4Exception("G4Tet::DistanceToOut(p,v,...)", "Notification", JustWarning,
"No good intersection found or already outside!?" );
if(validNorm)
{
*validNorm=false; // flag normal as meaningless
}
}
else if(calcNorm && n)
{
static G4ThreeVector normal;
if(tt==t1) { normal=fNormal123; }
else if (tt==t2) { normal=fNormal134; }
else if (tt==t3) { normal=fNormal142; }
else if (tt==t4) { normal=fNormal234; }
n=&normal;
if(validNorm) { *validNorm=true; }
}
return std::max(tt,0.0); // avoid tt<0.0 by a tiny bit
// if we are right on a face
}
////////////////////////////////////////////////////////////////////////////
//
// Calculate exact shortest distance to any boundary from inside
// - If outside return 0
G4double G4Tet::DistanceToOut(const G4ThreeVector& p) const
{
G4double t1,t2,t3,t4;
t1=fCdotN123-p.dot(fNormal123); // distance to plane, positive if inside
t2=fCdotN134-p.dot(fNormal134); // distance to plane
t3=fCdotN142-p.dot(fNormal142); // distance to plane
t4=fCdotN234-p.dot(fNormal234); // distance to plane
// if any one of these is negative, we are outside,
// so return zero in that case
G4double tmin=std::min(std::min(std::min(t1,t2),t3),t4);
return (tmin < fTol)? 0:tmin;
}
////////////////////////////////////////////////////////////////////////
//
// Create a List containing the transformed vertices
// Note: Caller has deletion responsibility
G4ThreeVectorList*
G4Tet::CreateRotatedVertices(const G4AffineTransform& pTransform) const
{
G4ThreeVectorList* vertices = new G4ThreeVectorList();
vertices->reserve(4);
if (vertices)
{
G4ThreeVector vertex0(fAnchor);
G4ThreeVector vertex1(fP2);
G4ThreeVector vertex2(fP3);
G4ThreeVector vertex3(fP4);
vertices->push_back(pTransform.TransformPoint(vertex0));
vertices->push_back(pTransform.TransformPoint(vertex1));
vertices->push_back(pTransform.TransformPoint(vertex2));
vertices->push_back(pTransform.TransformPoint(vertex3));
}
else
{
DumpInfo();
G4Exception("G4Tet::CreateRotatedVertices()",
"FatalError", FatalException,
"Error in allocation of vertices. Out of memory !");
}
return vertices;
}
//////////////////////////////////////////////////////////////////////////
//
// GetEntityType
G4GeometryType G4Tet::GetEntityType() const
{
return G4String("G4Tet");
}
//////////////////////////////////////////////////////////////////////////
//
// Stream object contents to an output stream
std::ostream& G4Tet::StreamInfo(std::ostream& os) const
{
os << "-----------------------------------------------------------\n"
<< " *** Dump for solid - " << GetName() << " ***\n"
<< " ===================================================\n"
<< " Solid type: G4Tet\n"
<< " Parameters: \n"
<< " anchor: " << fAnchor/mm << " mm \n"
<< " p2: " << fP2/mm << " mm \n"
<< " p3: " << fP3/mm << " mm \n"
<< " p4: " << fP4/mm << " mm \n"
<< " normal123: " << fNormal123 << " \n"
<< " normal134: " << fNormal134 << " \n"
<< " normal142: " << fNormal142 << " \n"
<< " normal234: " << fNormal234 << " \n"
<< "-----------------------------------------------------------\n";
return os;
}
////////////////////////////////////////////////////////////////////////
//
// GetPointOnFace
//
// Auxiliary method for get point on surface
G4ThreeVector G4Tet::GetPointOnFace(G4ThreeVector p1, G4ThreeVector p2,
G4ThreeVector p3, G4double& area) const
{
G4double lambda1,lambda2;
G4ThreeVector v, w;
v = p3 - p1;
w = p1 - p2;
lambda1 = RandFlat::shoot(0.,1.);
lambda2 = RandFlat::shoot(0.,lambda1);
area = 0.5*(v.cross(w)).mag();
return (p2 + lambda1*w + lambda2*v);
}
////////////////////////////////////////////////////////////////////////////
//
// GetPointOnSurface
G4ThreeVector G4Tet::GetPointOnSurface() const
{
G4double chose,aOne,aTwo,aThree,aFour;
G4ThreeVector p1, p2, p3, p4;
p1 = GetPointOnFace(fAnchor,fP2,fP3,aOne);
p2 = GetPointOnFace(fAnchor,fP4,fP3,aTwo);
p3 = GetPointOnFace(fAnchor,fP4,fP2,aThree);
p4 = GetPointOnFace(fP4,fP3,fP2,aFour);
chose = RandFlat::shoot(0.,aOne+aTwo+aThree+aFour);
if( (chose>=0.) && (chose <aOne) ) {return p1;}
else if( (chose>=aOne) && (chose < aOne+aTwo) ) {return p2;}
else if( (chose>=aOne+aTwo) && (chose<aOne+aTwo+aThree) ) {return p3;}
return p4;
}
////////////////////////////////////////////////////////////////////////
//
// GetVertices
std::vector<G4ThreeVector> G4Tet::GetVertices() const
{
std::vector<G4ThreeVector> vertices(4);
vertices[0] = fAnchor;
vertices[1] = fP2;
vertices[2] = fP3;
vertices[3] = fP4;
return vertices;
}
////////////////////////////////////////////////////////////////////////
//
// GetCubicVolume
G4double G4Tet::GetCubicVolume()
{
return fCubicVolume;
}
////////////////////////////////////////////////////////////////////////
//
// GetSurfaceArea
G4double G4Tet::GetSurfaceArea()
{
return fSurfaceArea;
}
// Methods for visualisation
////////////////////////////////////////////////////////////////////////
//
// DescribeYourselfTo
void G4Tet::DescribeYourselfTo (G4VGraphicsScene& scene) const
{
scene.AddSolid (*this);
}
////////////////////////////////////////////////////////////////////////
//
// GetExtent
G4VisExtent G4Tet::GetExtent() const
{
return G4VisExtent (fXMin, fXMax, fYMin, fYMax, fZMin, fZMax);
}
////////////////////////////////////////////////////////////////////////
//
// CreatePolyhedron
G4Polyhedron* G4Tet::CreatePolyhedron () const
{
G4Polyhedron *ph=new G4Polyhedron;
G4double xyz[4][3];
static G4int faces[4][4]={{1,3,2,0},{1,4,3,0},{1,2,4,0},{2,3,4,0}};
xyz[0][0]=fAnchor.x(); xyz[0][1]=fAnchor.y(); xyz[0][2]=fAnchor.z();
xyz[1][0]=fP2.x(); xyz[1][1]=fP2.y(); xyz[1][2]=fP2.z();
xyz[2][0]=fP3.x(); xyz[2][1]=fP3.y(); xyz[2][2]=fP3.z();
xyz[3][0]=fP4.x(); xyz[3][1]=fP4.y(); xyz[3][2]=fP4.z();
ph->createPolyhedron(4,4,xyz,faces);
return ph;
}
////////////////////////////////////////////////////////////////////////
//
// CreateNURBS
G4NURBS* G4Tet::CreateNURBS () const
{
return new G4NURBSbox (fDx, fDy, fDz);
}
////////////////////////////////////////////////////////////////////////
//
// GetPolyhedron
G4Polyhedron* G4Tet::GetPolyhedron () const
{
if (!fpPolyhedron ||
fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
fpPolyhedron->GetNumberOfRotationSteps())
{
delete fpPolyhedron;
fpPolyhedron = CreatePolyhedron();
}
return fpPolyhedron;
}