Files
geant4/source/geometry/solids/specific/src/G4EllipticalTube.cc
T
2019-12-06 15:12:28 +01:00

800 lines
23 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 result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// G4EllipticalTube implementation
//
// Author: David C. Williams (davidw@scipp.ucsc.edu)
// Revision: Evgueni Tcherniaev (evgueni.tcherniaev@cern.ch), 23.12.2019
// --------------------------------------------------------------------
#include "G4EllipticalTube.hh"
#if !(defined(G4GEOM_USE_UELLIPTICALTUBE) && defined(G4GEOM_USE_SYS_USOLIDS))
#include "G4GeomTools.hh"
#include "G4RandomTools.hh"
#include "G4ClippablePolygon.hh"
#include "G4AffineTransform.hh"
#include "G4VoxelLimits.hh"
#include "G4BoundingEnvelope.hh"
#include "Randomize.hh"
#include "G4VGraphicsScene.hh"
#include "G4VisExtent.hh"
#include "G4AutoLock.hh"
namespace
{
G4Mutex polyhedronMutex = G4MUTEX_INITIALIZER;
}
using namespace CLHEP;
//////////////////////////////////////////////////////////////////////////
//
// Constructor
G4EllipticalTube::G4EllipticalTube( const G4String &name,
G4double Dx,
G4double Dy,
G4double Dz )
: G4VSolid(name), fDx(Dx), fDy(Dy), fDz(Dz)
{
CheckParameters();
}
//////////////////////////////////////////////////////////////////////////
//
// Fake default constructor - sets only member data and allocates memory
// for usage restricted to object persistency.
G4EllipticalTube::G4EllipticalTube( __void__& a )
: G4VSolid(a), halfTolerance(0.), fDx(0.), fDy(0.), fDz(0.),
fRsph(0.), fDDx(0.), fDDy(0.), fSx(0.), fSy(0.), fR(0.),
fQ1(0.), fQ2(0.), fScratch(0.)
{
}
//////////////////////////////////////////////////////////////////////////
//
// Destructor
G4EllipticalTube::~G4EllipticalTube()
{
delete fpPolyhedron; fpPolyhedron = nullptr;
}
//////////////////////////////////////////////////////////////////////////
//
// Copy constructor
G4EllipticalTube::G4EllipticalTube(const G4EllipticalTube& rhs)
: G4VSolid(rhs), halfTolerance(rhs.halfTolerance),
fDx(rhs.fDx), fDy(rhs.fDy), fDz(rhs.fDz),
fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
fRsph(rhs.fRsph), fDDx(rhs.fDDx), fDDy(rhs.fDDy),
fSx(rhs.fSx), fSy(rhs.fSy), fR(rhs.fR),
fQ1(rhs.fQ1), fQ2(rhs.fQ2), fScratch(rhs.fScratch)
{
}
//////////////////////////////////////////////////////////////////////////
//
// Assignment operator
G4EllipticalTube& G4EllipticalTube::operator = (const G4EllipticalTube& rhs)
{
// Check assignment to self
//
if (this == &rhs) { return *this; }
// Copy base class data
//
G4VSolid::operator=(rhs);
// Copy data
//
halfTolerance = rhs.halfTolerance;
fDx = rhs.fDx;
fDy = rhs.fDy;
fDz = rhs.fDz;
fCubicVolume = rhs.fCubicVolume;
fSurfaceArea = rhs.fSurfaceArea;
fRsph = rhs.fRsph;
fDDx = rhs.fDDx;
fDDy = rhs.fDDy;
fSx = rhs.fSx;
fSy = rhs.fSy;
fR = rhs.fR;
fQ1 = rhs.fQ1;
fQ2 = rhs.fQ2;
fScratch = rhs.fScratch;
fRebuildPolyhedron = false;
delete fpPolyhedron; fpPolyhedron = nullptr;
return *this;
}
//////////////////////////////////////////////////////////////////////////
//
// Check dimensions
void G4EllipticalTube::CheckParameters()
{
// Check dimensions
//
halfTolerance = 0.5*kCarTolerance; // half tolerance
G4double dmin = 2*kCarTolerance;
if (fDx < dmin || fDy < dmin || fDz < dmin)
{
std::ostringstream message;
message << "Invalid (too small or negative) dimensions for Solid: "
<< GetName()
<< "\n Dx = " << fDx
<< "\n Dy = " << fDy
<< "\n Dz = " << fDz;
G4Exception("G4EllipticalTube::CheckParameters()", "GeomSolids0002",
FatalException, message);
}
// Set pre-calculatated values
//
halfTolerance = 0.5*kCarTolerance; // half tolerance
fRsph = std::sqrt(fDx * fDx + fDy * fDy + fDz * fDz); // radius of surrounding sphere
fDDx = fDx * fDx; // X semi-axis squared
fDDy = fDy * fDy; // Y semi-axis squared
fR = std::min(fDx, fDy); // resulting radius, after scaling elipse to circle
fSx = fR / fDx; // X scale factor
fSy = fR / fDy; // Y scale factor
fQ1 = 0.5 / fR; // distance approxiamtion dist = Q1 * (x^2 + y^2) - Q2
fQ2 = 0.5 * (fR + halfTolerance * halfTolerance / fR);
fScratch = 2. * fR * fR * DBL_EPSILON; // scratch within calculation error thickness
// fScratch = (B * B / A) * (2. + halfTolerance / A) * halfTolerance; // alternative
}
//////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4EllipticalTube::BoundingLimits( G4ThreeVector& pMin,
G4ThreeVector& pMax ) const
{
pMin.set(-fDx,-fDy,-fDz);
pMax.set( fDx, fDy, fDz);
}
//////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
G4bool
G4EllipticalTube::CalculateExtent( const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax ) const
{
G4ThreeVector bmin, bmax;
G4bool exist;
// Check bounding box (bbox)
//
BoundingLimits(bmin,bmax);
G4BoundingEnvelope bbox(bmin,bmax);
#ifdef G4BBOX_EXTENT
return bbox.CalculateExtent(pAxis,pVoxelLimit, pTransform, pMin, pMax);
#endif
if (bbox.BoundingBoxVsVoxelLimits(pAxis, pVoxelLimit, pTransform, pMin, pMax))
{
return exist = (pMin < pMax) ? true : false;
}
G4double dx = fDx;
G4double dy = fDy;
G4double dz = fDz;
// Set bounding envelope (benv) and calculate extent
//
const G4int NSTEPS = 24; // number of steps for whole circle
G4double ang = twopi/NSTEPS;
G4double sinHalf = std::sin(0.5*ang);
G4double cosHalf = std::cos(0.5*ang);
G4double sinStep = 2.*sinHalf*cosHalf;
G4double cosStep = 1. - 2.*sinHalf*sinHalf;
G4double sx = dx/cosHalf;
G4double sy = dy/cosHalf;
G4double sinCur = sinHalf;
G4double cosCur = cosHalf;
G4ThreeVectorList baseA(NSTEPS),baseB(NSTEPS);
for (G4int k=0; k<NSTEPS; ++k)
{
baseA[k].set(sx*cosCur,sy*sinCur,-dz);
baseB[k].set(sx*cosCur,sy*sinCur, dz);
G4double sinTmp = sinCur;
sinCur = sinCur*cosStep + cosCur*sinStep;
cosCur = cosCur*cosStep - sinTmp*sinStep;
}
std::vector<const G4ThreeVectorList *> polygons(2);
polygons[0] = &baseA;
polygons[1] = &baseB;
G4BoundingEnvelope benv(bmin, bmax, polygons);
exist = benv.CalculateExtent(pAxis, pVoxelLimit, pTransform, pMin, pMax);
return exist;
}
//////////////////////////////////////////////////////////////////////////
//
// Determine where is point: inside, outside or on surface
//
EInside G4EllipticalTube::Inside( const G4ThreeVector& p ) const
{
G4double x = p.x() * fSx;
G4double y = p.y() * fSy;
G4double distR = fQ1 * (x * x + y * y) - fQ2;
G4double distZ = std::abs(p.z()) - fDz;
G4double dist = std::max(distR, distZ);
if (dist > halfTolerance) return kOutside;
return (dist > -halfTolerance) ? kSurface : kInside;
}
//////////////////////////////////////////////////////////////////////////
//
// Return unit normal at surface closest to p
G4ThreeVector G4EllipticalTube::SurfaceNormal( const G4ThreeVector& p ) const
{
G4ThreeVector norm(0, 0, 0);
G4int nsurf = 0;
// check lateral surface
G4double x = p.x() * fSx;
G4double y = p.y() * fSy;
G4double distR = fQ1 * (x * x + y * y) - fQ2;
if (std::abs(distR) <= halfTolerance)
{
norm = G4ThreeVector(p.x() * fDDy, p.y() * fDDx, 0.).unit();
++nsurf;
}
// check lateral bases
G4double distZ = std::abs(p.z()) - fDz;
if (std::abs(distZ) <= halfTolerance)
{
norm.setZ(p.z() < 0 ? -1. : 1.);
++nsurf;
}
// return normal
if (nsurf == 1) return norm;
else if (nsurf > 1) return norm.unit(); // edge
else
{
// Point is not on the surface
//
#ifdef G4SPECDEBUG
std::ostringstream message;
G4int oldprc = message.precision(16);
message << "Point p is not on surface (!?) of solid: "
<< GetName() << G4endl;
message << "Position:\n";
message << " p.x() = " << p.x()/mm << " mm\n";
message << " p.y() = " << p.y()/mm << " mm\n";
message << " p.z() = " << p.z()/mm << " mm";
G4cout.precision(oldprc);
G4Exception("G4EllipticalTube::SurfaceNormal(p)", "GeomSolids1002",
JustWarning, message );
DumpInfo();
#endif
return ApproxSurfaceNormal(p);
}
}
//////////////////////////////////////////////////////////////////////////
//
// Find surface nearest to point and return corresponding normal.
// The algorithm is similar to the algorithm used in Inside().
// This method normally should not be called.
G4ThreeVector
G4EllipticalTube::ApproxSurfaceNormal( const G4ThreeVector& p ) const
{
G4double x = p.x() * fSx;
G4double y = p.y() * fSy;
G4double distR = fQ1 * (x * x + y * y) - fQ2;
G4double distZ = std::abs(p.z()) - fDz;
if (distR > distZ && (x * x + y * y) > 0)
return G4ThreeVector(p.x() * fDDy, p.y() * fDDx, 0.).unit();
else
return G4ThreeVector(0, 0, (p.z() < 0 ? -1. : 1.));
}
//////////////////////////////////////////////////////////////////////////
//
// Calculate distance to shape from outside, along normalised vector,
// return kInfinity if no intersection, or distance < halfTolerance
G4double G4EllipticalTube::DistanceToIn( const G4ThreeVector& p,
const G4ThreeVector& v ) const
{
G4double offset = 0.;
G4ThreeVector pcur = p;
// Check if point is flying away
//
G4double safex = std::abs(pcur.x()) - fDx;
G4double safey = std::abs(pcur.y()) - fDy;
G4double safez = std::abs(pcur.z()) - fDz;
if (safez >= -halfTolerance && pcur.z() * v.z() >= 0.) return kInfinity;
if (safey >= -halfTolerance && pcur.y() * v.y() >= 0.) return kInfinity;
if (safex >= -halfTolerance && pcur.x() * v.x() >= 0.) return kInfinity;
// Relocate point, if required
//
G4double Dmax = 32. * fRsph;
if (std::max(std::max(safex, safey), safez) > Dmax)
{
offset = (1. - 1.e-08) * pcur.mag() - 2. * fRsph;
pcur += offset * v;
G4double dist = DistanceToIn(pcur, v);
return (dist == kInfinity) ? kInfinity : dist + offset;
}
// Scale elliptical tube to cylinder
//
G4double px = pcur.x() * fSx;
G4double py = pcur.y() * fSy;
G4double pz = pcur.z();
G4double vx = v.x() * fSx;
G4double vy = v.y() * fSy;
G4double vz = v.z();
// Set coefficients of quadratic equation: A t^2 + 2B t + C = 0
//
G4double rr = px * px + py * py;
G4double A = vx * vx + vy * vy;
G4double B = px * vx + py * vy;
G4double C = rr - fR * fR;
G4double D = B * B - A * C;
// Check if point is flying away relative to lateral surface
//
G4double distR = fQ1 * rr - fQ2;
G4bool parallelToZ = (A < DBL_EPSILON || std::abs(vz) >= 1.);
if (distR >= -halfTolerance && (B >= 0. || parallelToZ)) return kInfinity;
// Find intersection with Z planes
//
G4double invz = (vz == 0) ? DBL_MAX : -1./vz;
G4double dz = std::copysign(fDz, invz);
G4double tzmin = (pz - dz) * invz;
G4double tzmax = (pz + dz) * invz;
// Solve qudratic equation. There are two cases special where D <= 0:
// 1) trajectory parallel to Z axis (A = 0, B = 0, C - any, D = 0)
// 2) touch (D = 0) or no intersection (D < 0) with lateral surface
//
if (parallelToZ) return (tzmin<halfTolerance) ? offset : tzmin + offset; // 1)
if (D <= A * A * fScratch) return kInfinity; // 2)
// Find roots of quadratic equation
G4double tmp = -B - std::copysign(std::sqrt(D), B);
G4double t1 = tmp / A;
G4double t2 = C / tmp;
G4double trmin = std::min(t1, t2);
G4double trmax = std::max(t1, t2);
// Return distance
G4double tin = std::max(tzmin, trmin);
G4double tout = std::min(tzmax, trmax);
if (tout <= tin + halfTolerance) return kInfinity; // touch or no hit
return (tin<halfTolerance) ? offset : tin + offset;
}
//////////////////////////////////////////////////////////////////////////
//
// Estimate distance to the surface from outside,
// returns 0 if point is inside
G4double G4EllipticalTube::DistanceToIn( const G4ThreeVector& p ) const
{
// safety distance to bounding box
G4double distX = std::abs(p.x()) - fDx;
G4double distY = std::abs(p.y()) - fDy;
G4double distZ = std::abs(p.z()) - fDz;
G4double distB = std::max(std::max(distX, distY), distZ);
// return (distB < 0) ? 0 : distB;
// safety distance to lateral surface
G4double x = p.x() * fSx;
G4double y = p.y() * fSy;
G4double distR = std::sqrt(x * x + y * y) - fR;
// return SafetyToIn
G4double dist = std::max(distB, distR);
return (dist < 0) ? 0 : dist;
}
//////////////////////////////////////////////////////////////////////////
//
// Calculate distance to shape from inside and find normal
// at exit point, if required
// - when leaving the surface, return 0
G4double G4EllipticalTube::DistanceToOut( const G4ThreeVector& p,
const G4ThreeVector& v,
const G4bool calcNorm,
G4bool* validNorm,
G4ThreeVector* n ) const
{
// Check if point flying away relative to Z planes
//
G4double pz = p.z();
G4double vz = v.z();
G4double distZ = std::abs(pz) - fDz;
if (distZ >= -halfTolerance && pz * vz > 0)
{
if (calcNorm)
{
*validNorm = true;
n->set(0, 0, (pz < 0) ? -1. : 1.);
}
return 0.;
}
G4double tzmax = (vz == 0) ? DBL_MAX : (std::copysign(fDz, vz) - pz) / vz;
// Scale elliptical tube to cylinder
//
G4double px = p.x() * fSx;
G4double py = p.y() * fSy;
G4double vx = v.x() * fSx;
G4double vy = v.y() * fSy;
// Check if point is flying away relative to lateral surface
//
G4double rr = px * px + py * py;
G4double B = px * vx + py * vy;
G4double distR = fQ1 * rr - fQ2;
if (distR >= -halfTolerance && B > 0.)
{
if (calcNorm)
{
*validNorm = true;
*n = G4ThreeVector(px * fDDy, py * fDDx, 0.).unit();
}
return 0.;
}
// Just in case check if point is outside, normally it should never be
//
if (std::max(distZ, distR) > halfTolerance)
{
#ifdef G4SPECDEBUG
std::ostringstream message;
G4int oldprc = message.precision(16);
message << "Point p is outside (!?) of solid: "
<< GetName() << G4endl;
message << "Position: " << p << G4endl;;
message << "Direction: " << v;
G4cout.precision(oldprc);
G4Exception("G4EllipticalTube::DistanceToOut(p,v)", "GeomSolids1002",
JustWarning, message );
DumpInfo();
#endif
if (calcNorm)
{
*validNorm = true;
*n = ApproxSurfaceNormal(p);
}
return 0.;
}
// Set coefficients of quadratic equation: A t^2 + 2B t + C = 0
//
G4double A = vx * vx + vy * vy;
G4double C = rr - fR * fR;
G4double D = B * B - A * C;
// Solve qudratic equation. There are two special cases where D <= 0:
// 1) trajectory parallel to Z axis (A = 0, B = 0, C - any, D = 0)
// 2) touch (D = 0) or no intersection (D < 0) with lateral surface
//
G4bool parallelToZ = (A < DBL_EPSILON || std::abs(vz) >= 1.);
if (parallelToZ) // 1)
{
if (calcNorm)
{
*validNorm = true;
n->set(0, 0, (vz < 0) ? -1. : 1.);
}
return tzmax;
}
if (D <= A * A * fScratch) // 2)
{
if (calcNorm)
{
*validNorm = true;
*n = G4ThreeVector(px * fDDy, py * fDDx, 0.).unit();
}
return 0.;
}
// Find roots of quadratic equation
G4double tmp = -B - std::copysign(std::sqrt(D), B);
G4double t1 = tmp / A;
G4double t2 = C / tmp;
G4double trmax = std::max(t1, t2);
// Return distance
G4double tmax = std::min(tzmax, trmax);
// Set normal, if required, and return distance
//
if (calcNorm)
{
*validNorm = true;
G4ThreeVector pnew = p + tmax * v;
if (tmax == tzmax)
n->set(0, 0, (pnew.z() < 0) ? -1. : 1.);
else
*n = G4ThreeVector(pnew.x() * fDDy, pnew.y() * fDDx, 0.).unit();
}
return tmax;
}
//////////////////////////////////////////////////////////////////////////
//
// Estimate distance to the surface from inside,
// returns 0 if point is outside
//
G4double G4EllipticalTube::DistanceToOut( const G4ThreeVector& p ) const
{
#ifdef G4SPECDEBUG
if( Inside(p) == kOutside )
{
std::ostringstream message;
G4int oldprc = message.precision(16);
message << "Point p is outside (!?) of solid: " << GetName() << "\n"
<< "Position:\n"
<< " p.x() = " << p.x()/mm << " mm\n"
<< " p.y() = " << p.y()/mm << " mm\n"
<< " p.z() = " << p.z()/mm << " mm";
message.precision(oldprc) ;
G4Exception("G4ElliptocalTube::DistanceToOut(p)", "GeomSolids1002",
JustWarning, message);
DumpInfo();
}
#endif
// safety distance to Z-bases
G4double distZ = fDz - std::abs(p.z());
// safety distance lateral surface
G4double x = p.x() * fSx;
G4double y = p.y() * fSy;
G4double distR = fR - std::sqrt(x * x + y * y);
// return SafetyToOut
G4double dist = std::min(distZ, distR);
return (dist < 0) ? 0 : dist;
}
//////////////////////////////////////////////////////////////////////////
//
// GetEntityType
G4GeometryType G4EllipticalTube::GetEntityType() const
{
return G4String("G4EllipticalTube");
}
//////////////////////////////////////////////////////////////////////////
//
// Make a clone of the object
G4VSolid* G4EllipticalTube::Clone() const
{
return new G4EllipticalTube(*this);
}
//////////////////////////////////////////////////////////////////////////
//
// Return volume
G4double G4EllipticalTube::GetCubicVolume()
{
if (fCubicVolume == 0.)
{
fCubicVolume = twopi * fDx * fDy * fDz;
}
return fCubicVolume;
}
//////////////////////////////////////////////////////////////////////////
//
// Return cached surface area
G4double G4EllipticalTube::GetCachedSurfaceArea() const
{
G4ThreadLocalStatic G4double cached_Dx = 0;
G4ThreadLocalStatic G4double cached_Dy = 0;
G4ThreadLocalStatic G4double cached_Dz = 0;
G4ThreadLocalStatic G4double cached_area = 0;
if (cached_Dx != fDx || cached_Dy != fDy || cached_Dz != fDz)
{
cached_Dx = fDx;
cached_Dy = fDy;
cached_Dz = fDz;
cached_area = 2.*(pi*fDx*fDy + G4GeomTools::EllipsePerimeter(fDx, fDy)*fDz);
}
return cached_area;
}
//////////////////////////////////////////////////////////////////////////
//
// Return surface area
G4double G4EllipticalTube::GetSurfaceArea()
{
if(fSurfaceArea == 0.)
{
fSurfaceArea = GetCachedSurfaceArea();
}
return fSurfaceArea;
}
//////////////////////////////////////////////////////////////////////////
//
// Stream object contents to output stream
std::ostream& G4EllipticalTube::StreamInfo(std::ostream& os) const
{
G4int oldprc = os.precision(16);
os << "-----------------------------------------------------------\n"
<< " *** Dump for solid - " << GetName() << " ***\n"
<< " ===================================================\n"
<< " Solid type: G4EllipticalTube\n"
<< " Parameters: \n"
<< " length Z: " << fDz/mm << " mm \n"
<< " lateral surface equation: \n"
<< " (X / " << fDx << ")^2 + (Y / " << fDy << ")^2 = 1 \n"
<< "-----------------------------------------------------------\n";
os.precision(oldprc);
return os;
}
//////////////////////////////////////////////////////////////////////////
//
// Pick up a random point on the surface
G4ThreeVector G4EllipticalTube::GetPointOnSurface() const
{
// Select surface (0 - base at -Z, 1 - base at +Z, 2 - lateral surface)
//
G4double sbase = pi * fDx * fDy;
G4double ssurf = GetCachedSurfaceArea();
G4double select = ssurf * G4UniformRand();
G4int k = 0;
if (select > sbase) k = 1;
if (select > 2. * sbase) k = 2;
// Pick random point on selected surface (rejection sampling)
//
G4ThreeVector p;
switch (k) {
case 0: // base at -Z
{
G4TwoVector rho = G4RandomPointInEllipse(fDx, fDy);
p.set(rho.x(), rho.y(), -fDz);
break;
}
case 1: // base at +Z
{
G4TwoVector rho = G4RandomPointInEllipse(fDx, fDy);
p.set(rho.x(), rho.y(), fDz);
break;
}
case 2: // lateral surface
{
G4TwoVector rho = G4RandomPointOnEllipse(fDx, fDy);
p.set(rho.x(), rho.y(), (2. * G4UniformRand() - 1.) * fDz);
break;
}
}
return p;
}
//////////////////////////////////////////////////////////////////////////
//
// CreatePolyhedron
G4Polyhedron* G4EllipticalTube::CreatePolyhedron() const
{
// create cylinder with radius=1...
//
G4Polyhedron* eTube = new G4PolyhedronTube(0., 1., fDz);
// apply non-uniform scaling...
//
eTube->Transform(G4Scale3D(fDx, fDy, 1.));
return eTube;
}
//////////////////////////////////////////////////////////////////////////
//
// GetPolyhedron
G4Polyhedron* G4EllipticalTube::GetPolyhedron () const
{
if (fpPolyhedron == nullptr ||
fRebuildPolyhedron ||
fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
fpPolyhedron->GetNumberOfRotationSteps())
{
G4AutoLock l(&polyhedronMutex);
delete fpPolyhedron;
fpPolyhedron = CreatePolyhedron();
fRebuildPolyhedron = false;
l.unlock();
}
return fpPolyhedron;
}
//////////////////////////////////////////////////////////////////////////
//
// DescribeYourselfTo
void G4EllipticalTube::DescribeYourselfTo( G4VGraphicsScene& scene ) const
{
scene.AddSolid (*this);
}
//////////////////////////////////////////////////////////////////////////
//
// GetExtent
G4VisExtent G4EllipticalTube::GetExtent() const
{
return G4VisExtent( -fDx, fDx, -fDy, fDy, -fDz, fDz );
}
#endif // !defined(G4GEOM_USE_UELLIPTICALTUBE) || !defined(G4GEOM_USE_SYS_USOLIDS)