Import Geant4 10.4.0 source tree

This commit is contained in:
Gabriele Cosmo
2017-12-08 12:52:30 +01:00
parent 98e455a940
commit fc6af9e721
2166 changed files with 276760 additions and 100873 deletions
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4EllipticalCone.cc 104316 2017-05-24 13:04:23Z gcosmo $
// $Id: G4EllipticalCone.cc 105454 2017-07-27 13:16:40Z gcosmo $
//
// Implementation of G4EllipticalCone class
//
@@ -34,6 +34,7 @@
// xy plane above z = 0.
//
// Author: Dionysios Anninos
// Revised: Evgueni Tcherniaev
//
// --------------------------------------------------------------------
@@ -41,6 +42,7 @@
#include "G4EllipticalCone.hh"
#include "G4RandomTools.hh"
#include "G4GeomTools.hh"
#include "G4ClippablePolygon.hh"
#include "G4VoxelLimits.hh"
@@ -64,10 +66,10 @@ namespace
using namespace CLHEP;
//////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//
// Constructor - check parameters
//
G4EllipticalCone::G4EllipticalCone(const G4String& pName,
G4double pxSemiAxis,
G4double pySemiAxis,
@@ -76,10 +78,6 @@ G4EllipticalCone::G4EllipticalCone(const G4String& pName,
: G4VSolid(pName), fRebuildPolyhedron(false), fpPolyhedron(0),
fCubicVolume(0.), fSurfaceArea(0.), zTopCut(0.)
{
kRadTolerance = G4GeometryTolerance::GetInstance()->GetRadialTolerance();
halfRadTol = 0.5*kRadTolerance;
halfCarTol = 0.5*kCarTolerance;
// Check Semi-Axis & Z-cut
@@ -87,15 +85,19 @@ G4EllipticalCone::G4EllipticalCone(const G4String& pName,
if ( (pxSemiAxis <= 0.) || (pySemiAxis <= 0.) || (pzMax <= 0.) )
{
std::ostringstream message;
message << "Invalid semi-axis or height - " << GetName();
message << "Invalid semi-axis or height for solid: " << GetName()
<< "\n X semi-axis, Y semi-axis, height = "
<< pxSemiAxis << ", " << pySemiAxis << ", " << pzMax;
G4Exception("G4EllipticalCone::G4EllipticalCone()", "GeomSolids0002",
FatalErrorInArgument, message);
}
}
if ( pzTopCut <= 0 )
{
std::ostringstream message;
message << "Invalid z-coordinate for cutting plane - " << GetName();
G4Exception("G4EllipticalCone::G4EllipticalCone()", "InvalidSetup",
message << "Invalid z-coordinate for cutting plane for solid: " << GetName()
<< "\n Z top cut = " << pzTopCut;
G4Exception("G4EllipticalCone::G4EllipticalCone()", "GeomSolids0002",
FatalErrorInArgument, message);
}
@@ -103,47 +105,46 @@ G4EllipticalCone::G4EllipticalCone(const G4String& pName,
SetZCut(pzTopCut);
}
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//
// Fake default constructor - sets only member data and allocates memory
// for usage restricted to object persistency.
//
G4EllipticalCone::G4EllipticalCone( __void__& a )
: G4VSolid(a), fRebuildPolyhedron(false), fpPolyhedron(0),
kRadTolerance(0.), halfRadTol(0.), halfCarTol(0.), fCubicVolume(0.),
fSurfaceArea(0.), xSemiAxis(0.), ySemiAxis(0.), zheight(0.),
semiAxisMax(0.), zTopCut(0.)
halfCarTol(0.), fCubicVolume(0.), fSurfaceArea(0.),
xSemiAxis(0.), ySemiAxis(0.), zheight(0.), zTopCut(0.),
cosAxisMin(0.), invXX(0.), invYY(0.)
{
}
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//
// Destructor
//
G4EllipticalCone::~G4EllipticalCone()
{
delete fpPolyhedron; fpPolyhedron = 0;
}
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//
// Copy constructor
//
G4EllipticalCone::G4EllipticalCone(const G4EllipticalCone& rhs)
: G4VSolid(rhs),
fRebuildPolyhedron(false), fpPolyhedron(0),
kRadTolerance(rhs.kRadTolerance),
halfRadTol(rhs.halfRadTol), halfCarTol(rhs.halfCarTol),
: G4VSolid(rhs), fRebuildPolyhedron(false), fpPolyhedron(0),
halfCarTol(rhs.halfCarTol),
fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
xSemiAxis(rhs.xSemiAxis), ySemiAxis(rhs.ySemiAxis), zheight(rhs.zheight),
semiAxisMax(rhs.semiAxisMax), zTopCut(rhs.zTopCut)
xSemiAxis(rhs.xSemiAxis), ySemiAxis(rhs.ySemiAxis),
zheight(rhs.zheight), zTopCut(rhs.zTopCut),
cosAxisMin(rhs.cosAxisMin), invXX(rhs.invXX), invYY(rhs.invYY)
{
}
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//
// Assignment operator
//
G4EllipticalCone& G4EllipticalCone::operator = (const G4EllipticalCone& rhs)
{
// Check assignment to self
@@ -156,18 +157,19 @@ G4EllipticalCone& G4EllipticalCone::operator = (const G4EllipticalCone& rhs)
// Copy data
//
kRadTolerance = rhs.kRadTolerance;
halfRadTol = rhs.halfRadTol; halfCarTol = rhs.halfCarTol;
halfCarTol = rhs.halfCarTol;
fCubicVolume = rhs.fCubicVolume; fSurfaceArea = rhs.fSurfaceArea;
xSemiAxis = rhs.xSemiAxis; ySemiAxis = rhs.ySemiAxis;
zheight = rhs.zheight; semiAxisMax = rhs.semiAxisMax; zTopCut = rhs.zTopCut;
zheight = rhs.zheight; zTopCut = rhs.zTopCut;
cosAxisMin = rhs.cosAxisMin; invXX = rhs.invXX; invYY = rhs.invYY;
fRebuildPolyhedron = false;
delete fpPolyhedron; fpPolyhedron = 0;
return *this;
}
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//
// Get bounding box
@@ -196,10 +198,10 @@ void G4EllipticalCone::BoundingLimits(G4ThreeVector& pMin,
}
}
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
//
G4bool
G4EllipticalCone::CalculateExtent(const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
@@ -257,158 +259,94 @@ G4EllipticalCone::CalculateExtent(const EAxis pAxis,
return exist;
}
////////////////////////////////////////////////////////////////////////
//
// Return whether point inside/outside/on surface
// Split into radius, phi, theta checks
// Each check modifies `in', or returns as approprate
/////////////////////////////////////////////////////////////////////////
//
// Determine where is point: inside, outside or on surface
EInside G4EllipticalCone::Inside(const G4ThreeVector& p) const
{
G4double rad2oo, // outside surface outer tolerance
rad2oi; // outside surface inner tolerance
EInside in;
G4double hp = std::sqrt(p.x()*p.x()*invXX + p.y()*p.y()*invYY) + p.z();
G4double ds = (hp - zheight)*cosAxisMin;
G4double dz = std::abs(p.z()) - zTopCut;
G4double dist = std::max(ds,dz);
// check this side of z cut first, because that's fast
//
if ( (p.z() < -zTopCut - halfCarTol)
|| (p.z() > zTopCut + halfCarTol ) )
{
return in = kOutside;
}
rad2oo= sqr(p.x()/( xSemiAxis + halfRadTol ))
+ sqr(p.y()/( ySemiAxis + halfRadTol ));
if ( rad2oo > sqr( zheight-p.z() ) )
{
return in = kOutside;
}
// rad2oi= sqr( p.x()*(1.0 + 0.5*kRadTolerance/(xSemiAxis*xSemiAxis)) )
// + sqr( p.y()*(1.0 + 0.5*kRadTolerance/(ySemiAxis*ySemiAxis)) );
rad2oi = sqr(p.x()/( xSemiAxis - halfRadTol ))
+ sqr(p.y()/( ySemiAxis - halfRadTol ));
if (rad2oi < sqr( zheight-p.z() ) )
{
in = ( ( p.z() < -zTopCut + halfRadTol )
|| ( p.z() > zTopCut - halfRadTol ) ) ? kSurface : kInside;
}
else
{
in = kSurface;
}
return in;
if (dist > halfCarTol) return kOutside;
return (dist > -halfCarTol) ? kSurface : kInside;
}
/////////////////////////////////////////////////////////////////////////
//
// Return unit normal of surface closest to p not protected against p=0
//
// Return unit normal at surface closest to p
G4ThreeVector G4EllipticalCone::SurfaceNormal( const G4ThreeVector& p) const
{
G4ThreeVector norm(0,0,0);
G4int nsurf = 0; // number of surfaces where p is placed
G4double rx = sqr(p.x()/xSemiAxis),
ry = sqr(p.y()/ySemiAxis);
G4double rds = std::sqrt(rx + ry);
G4ThreeVector norm;
if( (p.z() < -zTopCut) && ((rx+ry) < sqr(zTopCut + zheight)) )
G4double hp = std::sqrt(p.x()*p.x()*invXX + p.y()*p.y()*invYY) + p.z();
G4double ds = (hp - zheight)*cosAxisMin;
if (std::abs(ds) <= halfCarTol)
{
return G4ThreeVector( 0., 0., -1. );
norm = G4ThreeVector(p.x()*invXX, p.y()*invYY, hp - p.z());
G4double mag = norm.mag();
if (mag == 0) return G4ThreeVector(0,0,1); // apex
norm *= (1/mag);
++nsurf;
}
G4double dz = std::abs(p.z()) - zTopCut;
if (std::abs(dz) <= halfCarTol)
{
norm += G4ThreeVector(0., 0.,(p.z() < 0) ? -1. : 1.);
++nsurf;
}
if( (p.z() > (zheight > zTopCut ? zheight : zTopCut)) &&
((rx+ry) < sqr(zheight-zTopCut)) )
if (nsurf == 1) return norm;
else if (nsurf > 1) return norm.unit(); // elliptic edge
else
{
return G4ThreeVector( 0., 0., 1. );
// Point is not on the surface
//
#ifdef G4CSGDEBUG
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("G4EllipticalCone::SurfaceNormal(p)", "GeomSolids1002",
JustWarning, message );
DumpInfo();
#endif
return ApproxSurfaceNormal(p);
}
if( p.z() > rds + 2.*zTopCut - zheight )
{
if ( p.z() > zTopCut )
{
if( p.x() == 0. )
{
norm = G4ThreeVector( 0., p.y() < 0. ? -1. : 1., 1. );
return norm /= norm.mag();
}
if( p.y() == 0. )
{
norm = G4ThreeVector( p.x() < 0. ? -1. : 1., 0., 1. );
return norm /= norm.mag();
}
G4double k = std::fabs(p.x()/p.y());
G4double c2 = sqr(zheight-zTopCut)/(1./sqr(xSemiAxis)+sqr(k/ySemiAxis));
G4double x = std::sqrt(c2);
G4double y = k*x;
x /= sqr(xSemiAxis);
y /= sqr(ySemiAxis);
norm = G4ThreeVector( p.x() < 0. ? -x : x,
p.y() < 0. ? -y : y,
- ( zheight - zTopCut ) );
norm /= norm.mag();
norm += G4ThreeVector( 0., 0., 1. );
return norm /= norm.mag();
}
return G4ThreeVector( 0., 0., 1. );
}
if( p.z() < rds - 2.*zTopCut - zheight )
{
if( p.x() == 0. )
{
norm = G4ThreeVector( 0., p.y() < 0. ? -1. : 1., -1. );
return norm /= norm.mag();
}
if( p.y() == 0. )
{
norm = G4ThreeVector( p.x() < 0. ? -1. : 1., 0., -1. );
return norm /= norm.mag();
}
G4double k = std::fabs(p.x()/p.y());
G4double c2 = sqr(zheight+zTopCut)/(1./sqr(xSemiAxis)+sqr(k/ySemiAxis));
G4double x = std::sqrt(c2);
G4double y = k*x;
x /= sqr(xSemiAxis);
y /= sqr(ySemiAxis);
norm = G4ThreeVector( p.x() < 0. ? -x : x,
p.y() < 0. ? -y : y,
- ( zheight - zTopCut ) );
norm /= norm.mag();
norm += G4ThreeVector( 0., 0., -1. );
return norm /= norm.mag();
}
norm = G4ThreeVector(p.x()/sqr(xSemiAxis), p.y()/sqr(ySemiAxis), rds);
G4double k = std::tan(pi/8.);
G4double c = -zTopCut - k*(zTopCut + zheight);
if( p.z() < -k*rds + c )
return G4ThreeVector (0.,0.,-1.);
return norm /= norm.mag();
}
//////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//
// 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
G4EllipticalCone::ApproxSurfaceNormal(const G4ThreeVector& p) const
{
G4double hp = std::sqrt(p.x()*p.x()*invXX + p.y()*p.y()*invYY) + p.z();
G4double ds = (hp - zheight)*cosAxisMin;
G4double dz = std::abs(p.z()) - zTopCut;
if (ds > dz && std::abs(hp - p.z()) > halfCarTol)
return G4ThreeVector(p.x()*invXX, p.y()*invYY, hp - p.z()).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 intersection distance <= tolerance
//
G4double G4EllipticalCone::DistanceToIn( const G4ThreeVector& p,
const G4ThreeVector& v ) const
{
@@ -442,7 +380,7 @@ G4double G4EllipticalCone::DistanceToIn( const G4ThreeVector& p,
//
if ( sqr(p.x()/( xSemiAxis - halfCarTol ))
+ sqr(p.y()/( ySemiAxis - halfCarTol )) <= sqr( zheight+zTopCut ) )
+ sqr(p.y()/( ySemiAxis - halfCarTol )) <= sqr( zheight + zTopCut ) )
return kInfinity;
}
@@ -521,7 +459,7 @@ G4double G4EllipticalCone::DistanceToIn( const G4ThreeVector& p,
// check to see if Z plane is relevant
//
if (p.z() < -zTopCut - 0.5*kCarTolerance)
if (p.z() < -zTopCut - halfCarTol)
{
if (v.z() <= 0.0)
return distMin;
@@ -530,13 +468,13 @@ G4double G4EllipticalCone::DistanceToIn( const G4ThreeVector& p,
if ( sqr((lambda*v.x()+p.x())/xSemiAxis) +
sqr((lambda*v.y()+p.y())/ySemiAxis) <=
sqr(zTopCut + zheight + 0.5*kRadTolerance) )
sqr(zTopCut + zheight + halfCarTol) )
{
return distMin = std::fabs(lambda);
}
}
if (p.z() > zTopCut+0.5*kCarTolerance)
if (p.z() > zTopCut + halfCarTol)
{
if (v.z() >= 0.0)
{ return distMin; }
@@ -545,7 +483,7 @@ G4double G4EllipticalCone::DistanceToIn( const G4ThreeVector& p,
if ( sqr((lambda*v.x() + p.x())/xSemiAxis) +
sqr((lambda*v.y() + p.y())/ySemiAxis) <=
sqr(zheight - zTopCut + 0.5*kRadTolerance) )
sqr(zheight - zTopCut + halfCarTol) )
{
return distMin = std::fabs(lambda);
}
@@ -589,7 +527,7 @@ G4double G4EllipticalCone::DistanceToIn( const G4ThreeVector& p,
// case below is when it hits or grazes the surface
//
if ( (discr >= - halfCarTol ) && (discr < halfCarTol ) )
if ( (discr >= -halfCarTol ) && (discr < halfCarTol ) )
{
return distMin = std::fabs(-B/(2.*A));
}
@@ -622,7 +560,7 @@ G4double G4EllipticalCone::DistanceToIn( const G4ThreeVector& p,
lambda = minus ;
// check normal vector n * v < 0
G4ThreeVector pin = p + lambda*v;
if(std::fabs(pin.z())<zTopCut+0.5*kCarTolerance)
if(std::fabs(pin.z())< zTopCut + halfCarTol)
{
G4ThreeVector truenorm(pin.x()/(xSemiAxis*xSemiAxis),
pin.y()/(ySemiAxis*ySemiAxis),
@@ -638,7 +576,7 @@ G4double G4EllipticalCone::DistanceToIn( const G4ThreeVector& p,
lambda = plus ;
// check normal vector n * v < 0
G4ThreeVector pin = p + lambda*v;
if(std::fabs(pin.z())<zTopCut+0.5*kCarTolerance)
if(std::fabs(pin.z()) < zTopCut + halfCarTol)
{
G4ThreeVector truenorm(pin.x()/(xSemiAxis*xSemiAxis),
pin.y()/(ySemiAxis*ySemiAxis),
@@ -653,69 +591,25 @@ G4double G4EllipticalCone::DistanceToIn( const G4ThreeVector& p,
return distMin ;
}
//////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//
// Calculate distance (<= actual) to closest surface of shape from outside
// Return 0 if point inside
//
G4double G4EllipticalCone::DistanceToIn(const G4ThreeVector& p) const
{
G4double distR, distR2, distZ, maxDim;
G4double distRad;
// check if the point lies either below z=-zTopCut in bottom elliptical
// region or on top within cut elliptical region
//
if( (p.z() <= -zTopCut) && (sqr(p.x()/xSemiAxis) + sqr(p.y()/ySemiAxis)
<= sqr(zTopCut + zheight + 0.5*kCarTolerance )) )
{
//return distZ = std::fabs(zTopCut - p.z());
return distZ = std::fabs(zTopCut + p.z());
}
if( (p.z() >= zTopCut) && (sqr(p.x()/xSemiAxis)+sqr(p.y()/ySemiAxis)
<= sqr(zheight - zTopCut + kCarTolerance/2.0 )) )
{
return distZ = std::fabs(p.z() - zTopCut);
}
// below we use the following approximation: we take the largest of the
// axes and find the shortest distance to the circular (cut) cone of that
// radius.
//
maxDim = xSemiAxis >= ySemiAxis ? xSemiAxis:ySemiAxis;
distRad = std::sqrt(p.x()*p.x()+p.y()*p.y());
if( p.z() > maxDim*distRad + zTopCut*(1.+maxDim)-sqr(maxDim)*zheight )
{
distR2 = sqr(p.z() - zTopCut) + sqr(distRad - maxDim*(zheight - zTopCut));
return std::sqrt( distR2 );
}
if( distRad > maxDim*( zheight - p.z() ) )
{
if( p.z() > maxDim*distRad - (zTopCut*(1.+maxDim)+sqr(maxDim)*zheight) )
{
G4double zVal = (p.z()-maxDim*(distRad-maxDim*zheight))/(1.+sqr(maxDim));
G4double rVal = maxDim*(zheight - zVal);
return distR = std::sqrt(sqr(p.z() - zVal) + sqr(distRad - rVal));
}
}
if( distRad <= maxDim*(zheight - p.z()) )
{
distR2 = sqr(distRad - maxDim*(zheight + zTopCut)) + sqr(p.z() + zTopCut);
return std::sqrt( distR2 );
}
return distR = 0;
G4double hp = std::sqrt(p.x()*p.x()*invXX + p.y()*p.y()*invYY) + p.z();
G4double ds = (hp - zheight)*cosAxisMin;
G4double dz = std::abs(p.z()) - zTopCut;
G4double dist = std::max(ds,dz);
return (dist > 0) ? dist : 0.;
}
/////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
//
// Calculate distance to surface of shape from `inside',
// allowing for tolerance
//
G4double G4EllipticalCone::DistanceToOut(const G4ThreeVector& p,
const G4ThreeVector& v,
const G4bool calcNorm,
@@ -734,7 +628,7 @@ G4double G4EllipticalCone::DistanceToOut(const G4ThreeVector& p,
if ( (sqr((p.x() + lambda*v.x())/xSemiAxis) +
sqr((p.y() + lambda*v.y())/ySemiAxis)) <
sqr(zheight + zTopCut + 0.5*kCarTolerance) )
sqr(zheight + zTopCut + halfCarTol) )
{
distMin = std::fabs(lambda);
@@ -750,7 +644,7 @@ G4double G4EllipticalCone::DistanceToOut(const G4ThreeVector& p,
if ( (sqr((p.x() + lambda*v.x())/xSemiAxis)
+ sqr((p.y() + lambda*v.y())/ySemiAxis) )
< (sqr(zheight - zTopCut + 0.5*kCarTolerance)) )
< (sqr(zheight - zTopCut + halfCarTol)) )
{
distMin = std::fabs(lambda);
if (!calcNorm) { return distMin; }
@@ -770,17 +664,17 @@ G4double G4EllipticalCone::DistanceToOut(const G4ThreeVector& p,
G4double discr = B*B - 4.*A*C;
if ( discr >= - 0.5*kCarTolerance && discr < 0.5*kCarTolerance )
if ( discr >= - halfCarTol && discr < halfCarTol )
{
if(!calcNorm) { return distMin = std::fabs(-B/(2.*A)); }
}
else if ( discr > 0.5*kCarTolerance )
else if ( discr > halfCarTol )
{
G4double plus = (-B+std::sqrt(discr))/(2.*A);
G4double minus = (-B-std::sqrt(discr))/(2.*A);
if ( plus > 0.5*kCarTolerance && minus > 0.5*kCarTolerance )
if ( plus > halfCarTol && minus > halfCarTol )
{
// take the shorter distance
//
@@ -791,12 +685,12 @@ G4double G4EllipticalCone::DistanceToOut(const G4ThreeVector& p,
// at least one solution is close to zero or negative
// so, take small positive solution or zero
//
lambda = plus > -0.5*kCarTolerance ? plus : 0;
lambda = plus > -halfCarTol ? plus : 0;
}
if ( std::fabs(lambda) < distMin )
{
if( std::fabs(lambda) > 0.5*kCarTolerance)
if( std::fabs(lambda) > halfCarTol)
{
distMin = std::fabs(lambda);
surface = kCurvedSurf;
@@ -869,7 +763,7 @@ G4double G4EllipticalCone::DistanceToOut(const G4ThreeVector& p,
}
}
if (distMin<0.5*kCarTolerance) { distMin=0; }
if (distMin < halfCarTol) { distMin=0; }
return distMin;
}
@@ -877,74 +771,54 @@ G4double G4EllipticalCone::DistanceToOut(const G4ThreeVector& p,
/////////////////////////////////////////////////////////////////////////
//
// Calculate distance (<=actual) to closest surface of shape from inside
//
G4double G4EllipticalCone::DistanceToOut(const G4ThreeVector& p) const
{
#ifdef G4SPECSDEBUG
if( Inside(p) == kOutside )
{
DumpInfo();
std::ostringstream message;
G4int oldprc = message.precision(16);
message << "Point p is outside !?" << G4endl
<< "Position:" << G4endl
<< " p.x() = " << p.x()/mm << " mm" << G4endl
<< " p.y() = " << p.y()/mm << " mm" << G4endl
<< " p.z() = " << p.z()/mm << " mm";
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("G4Ellipsoid::DistanceToOut(p)", "GeomSolids1002",
JustWarning, message);
DumpInfo();
}
#endif
// The safety is calculated in the scaled space where elliptical cone
// becomes a circular cone with radius equal to the smaller of the axes
//
G4double px = p.x(), py = p.y(), pz = p.z();
G4double axis;
if (xSemiAxis < ySemiAxis)
{
axis = xSemiAxis;
py *= xSemiAxis/ySemiAxis; // scale y
}
else
{
axis = ySemiAxis;
px *= ySemiAxis/xSemiAxis; // scale x
}
G4double distZ = zTopCut - std::abs(pz) ;
if (distZ <= 0) return 0; // point is outside
G4double rho = axis*(zheight-pz); // radius at z = p.z()
G4double pr = std::sqrt(px*px+py*py);
if (pr >= rho) return 0; // point is outside
G4double distR = (rho-pr)/std::sqrt(1+axis*axis);
return std::min(distR,distZ);
G4double hp = std::sqrt(p.x()*p.x()*invXX + p.y()*p.y()*invYY) + p.z();
G4double ds = (zheight - hp)*cosAxisMin;
G4double dz = zTopCut - std::abs(p.z());
G4double dist = std::min(ds,dz);
return (dist > 0) ? dist : 0.;
}
//////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//
// GetEntityType
//
G4GeometryType G4EllipticalCone::GetEntityType() const
{
return G4String("G4EllipticalCone");
}
//////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//
// Make a clone of the object
//
G4VSolid* G4EllipticalCone::Clone() const
{
return new G4EllipticalCone(*this);
}
//////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//
// Stream object contents to an output stream
//
std::ostream& G4EllipticalCone::StreamInfo( std::ostream& os ) const
{
G4int oldprc = os.precision(16);
@@ -966,69 +840,87 @@ std::ostream& G4EllipticalCone::StreamInfo( std::ostream& os ) const
/////////////////////////////////////////////////////////////////////////
//
// GetPointOnSurface
//
// returns quasi-uniformly distributed point on surface of elliptical cone
//
// Return random point on the surface of the solid
G4ThreeVector G4EllipticalCone::GetPointOnSurface() const
{
G4double x0 = xSemiAxis*zheight; // x semi axis at z=0
G4double y0 = ySemiAxis*zheight; // y semi axis at z=0
G4double s0 = G4GeomTools::EllipticConeLateralArea(x0,y0,zheight);
G4double kmin = (zTopCut >= zheight ) ? 0. : (zheight - zTopCut)/zheight;
G4double kmax = (zTopCut >= zheight ) ? 2. : (zheight + zTopCut)/zheight;
G4double phi, sinphi, cosphi, aOne, aTwo, aThree,
chose, zRand, rRand1, rRand2;
G4double rOne = std::sqrt(sqr(xSemiAxis)
+ sqr(ySemiAxis))*(zheight - zTopCut);
G4double rTwo = std::sqrt(sqr(xSemiAxis)
+ sqr(ySemiAxis))*(zheight + zTopCut);
G4int it1=0, it2=0;
aOne = pi*(rOne + rTwo)*std::sqrt(sqr(rOne - rTwo)+sqr(2.*zTopCut));
aTwo = pi*xSemiAxis*ySemiAxis*sqr(zheight+zTopCut);
aThree = pi*xSemiAxis*ySemiAxis*sqr(zheight-zTopCut);
phi = G4RandFlat::shoot(0.,twopi);
cosphi = std::cos(phi);
sinphi = std::sin(phi);
if(zTopCut >= zheight) aThree = 0.;
chose = G4RandFlat::shoot(0.,aOne+aTwo+aThree);
if((chose>=0.) && (chose<aOne))
{
zRand = G4RandFlat::shoot(-zTopCut,zTopCut);
return G4ThreeVector(xSemiAxis*(zheight-zRand)*cosphi,
ySemiAxis*(zheight-zRand)*sinphi,zRand);
}
else if((chose>=aOne) && (chose<aOne+aTwo))
{
do // Loop checking, 13.08.2015, G.Cosmo
{
rRand1 = G4RandFlat::shoot(0.,1.) ;
rRand2 = G4RandFlat::shoot(0.,1.) ;
} while (( rRand2 >= rRand1 ) && (++it1 < 1000)) ;
return G4ThreeVector(rRand1*xSemiAxis*(zheight+zTopCut)*cosphi,
rRand1*ySemiAxis*(zheight+zTopCut)*sinphi, -zTopCut);
}
// else
// Set areas (base at -Z, side surface, base at +Z)
//
G4double szmin = pi*x0*y0*kmax*kmax;
G4double szmax = pi*x0*y0*kmin*kmin;
G4double sside = s0*(kmax*kmax - kmin*kmin);
G4double ssurf[3] = { szmin, sside, szmax };
for (G4int i=1; i<3; ++i) { ssurf[i] += ssurf[i-1]; }
do // Loop checking, 13.08.2015, G.Cosmo
// Select surface
//
G4double select = ssurf[2]*G4UniformRand();
G4int k = 2;
if (select <= ssurf[1]) k = 1;
if (select <= ssurf[0]) k = 0;
// Pick random point on selected surface
//
G4ThreeVector p;
switch(k)
{
rRand1 = G4RandFlat::shoot(0.,1.) ;
rRand2 = G4RandFlat::shoot(0.,1.) ;
} while (( rRand2 >= rRand1 ) && (++it2 < 1000));
case 0: // base at -Z, uniform distribution, rejection sampling
{
G4double zh = zheight + zTopCut;
G4TwoVector rho = G4RandomPointInEllipse(zh*xSemiAxis,zh*ySemiAxis);
p.set(rho.x(),rho.y(),-zTopCut);
break;
}
case 1: // side surface, uniform distribution, rejection sampling
{
G4double zh = G4RandomRadiusInRing(zheight-zTopCut, zheight+zTopCut);
G4double a = x0;
G4double b = y0;
return G4ThreeVector(rRand1*xSemiAxis*(zheight-zTopCut)*cosphi,
rRand1*ySemiAxis*(zheight-zTopCut)*sinphi, zTopCut);
G4double hh = zheight*zheight;
G4double aa = a*a;
G4double bb = b*b;
G4double R = std::max(a,b);
G4double mu_max = R*std::sqrt(hh + R*R);
G4double x,y;
for (G4int i=0; i<1000; ++i)
{
G4double phi = CLHEP::twopi*G4UniformRand();
x = std::cos(phi);
y = std::sin(phi);
G4double xx = x*x;
G4double yy = y*y;
G4double E = hh + aa*xx + bb*yy;
G4double F = (aa-bb)*x*y;
G4double G = aa*yy + bb*xx;
G4double mu = std::sqrt(E*G - F*F);
if (mu_max*G4UniformRand() <= mu) break;
}
p.set(zh*xSemiAxis*x,zh*ySemiAxis*y,zheight-zh);
break;
}
case 2: // base at +Z, uniform distribution, rejection sampling
{
G4double zh = zheight - zTopCut;
G4TwoVector rho = G4RandomPointInEllipse(zh*xSemiAxis,zh*ySemiAxis);
p.set(rho.x(),rho.y(),zTopCut);
break;
}
}
return p;
}
/////////////////////////////////////////////////////////////////////////
//
// Get cubic volume
//
G4double G4EllipticalCone::GetCubicVolume()
{
if (fCubicVolume == 0)
@@ -1046,7 +938,7 @@ G4double G4EllipticalCone::GetCubicVolume()
/////////////////////////////////////////////////////////////////////////
//
// Get surface area
//
G4double G4EllipticalCone::GetSurfaceArea()
{
if (fSurfaceArea == 0)
@@ -1056,14 +948,15 @@ G4double G4EllipticalCone::GetSurfaceArea()
G4double s0 = G4GeomTools::EllipticConeLateralArea(x0,y0,zheight);
G4double kmin = (zTopCut >= zheight ) ? 0. : (zheight - zTopCut)/zheight;
G4double kmax = (zTopCut >= zheight ) ? 2. : (zheight + zTopCut)/zheight;
fSurfaceArea = (kmax - kmin)*(kmax + kmin)*s0 + CLHEP::pi*x0*y0*(kmin*kmin + kmax*kmax);
fSurfaceArea = (kmax - kmin)*(kmax + kmin)*s0
+ CLHEP::pi*x0*y0*(kmin*kmin + kmax*kmax);
}
return fSurfaceArea;
}
/////////////////////////////////////////////////////////////////////////
//
// Methods for visualisation
//
void G4EllipticalCone::DescribeYourselfTo (G4VGraphicsScene& scene) const
{
@@ -24,7 +24,7 @@
// ********************************************************************
//
//
// $Id: G4ExtrudedSolid.cc 104316 2017-05-24 13:04:23Z gcosmo $
// $Id: G4ExtrudedSolid.cc 107558 2017-11-22 15:29:33Z gcosmo $
//
//
// --------------------------------------------------------------------
@@ -37,16 +37,20 @@
// CHANGE HISTORY
// --------------
//
// 31.10.2017 E.Tcherniaev: added implementation for a non-convex
// right prism
// 08.09.2017 E.Tcherniaev: added implementation for a convex
// right prism
// 21.10.2016 E.Tcherniaev: reimplemented CalculateExtent(),
// used G4GeomTools::PolygonArea() to calculate area,
// replaced IsConvex() with G4GeomTools::IsConvex()
// 02.03.2016 E.Tcherniaev: added CheckPolygon() to remove
// 02.03.2016 E.Tcherniaev: added CheckPolygon() to remove
// collinear and coincident points from polygon
// --------------------------------------------------------------------
#include "G4ExtrudedSolid.hh"
#if !defined(G4GEOM_USE_UEXTRUDEDSOLID)
//#if !defined(G4GEOM_USE_UEXTRUDEDSOLID)
#include <set>
#include <algorithm>
@@ -77,10 +81,10 @@ G4ExtrudedSolid::G4ExtrudedSolid( const G4String& pName,
fZSections(),
fTriangles(),
fIsConvex(false),
fGeometryType("G4ExtrudedSolid")
fGeometryType("G4ExtrudedSolid"),
fSolidType(0)
{
// General constructor
// General constructor
// First check input parameters
@@ -178,6 +182,17 @@ G4ExtrudedSolid::G4ExtrudedSolid( const G4String& pName,
fIsConvex = G4GeomTools::IsConvex(fPolygon);
ComputeProjectionParameters();
// Check if the solid is a right prism, if so then set lateral planes
//
if ((fNz == 2)
&& (fZSections[0].fScale == 1) && (fZSections[1].fScale == 1)
&& (fZSections[0].fOffset == G4TwoVector(0,0))
&& (fZSections[1].fOffset == G4TwoVector(0,0)))
{
fSolidType = (fIsConvex) ? 1 : 2; // 1 - convex, 2 - non-convex right prism
ComputeLateralPlanes();
}
}
//_____________________________________________________________________________
@@ -194,8 +209,8 @@ G4ExtrudedSolid::G4ExtrudedSolid( const G4String& pName,
fZSections(),
fTriangles(),
fIsConvex(false),
fGeometryType("G4ExtrudedSolid")
fGeometryType("G4ExtrudedSolid"),
fSolidType(0)
{
// Special constructor for solid with 2 z-sections
@@ -268,13 +283,23 @@ G4ExtrudedSolid::G4ExtrudedSolid( const G4String& pName,
fIsConvex = G4GeomTools::IsConvex(fPolygon);
ComputeProjectionParameters();
// Check if the solid is a right prism, if so then set lateral planes
//
if ((scale1 == 1) && (scale2 == 1)
&& (off1 == G4TwoVector(0,0)) && (off2 == G4TwoVector(0,0)))
{
fSolidType = (fIsConvex) ? 1 : 2; // 1 - convex, 2 - non-convex right prism
ComputeLateralPlanes();
}
}
//_____________________________________________________________________________
G4ExtrudedSolid::G4ExtrudedSolid( __void__& a )
: G4TessellatedSolid(a), fNv(0), fNz(0), fPolygon(), fZSections(),
fTriangles(), fIsConvex(false), fGeometryType("G4ExtrudedSolid")
fTriangles(), fIsConvex(false), fGeometryType("G4ExtrudedSolid"),
fSolidType(0)
{
// Fake default constructor - sets only member data and allocates memory
// for usage restricted to object persistency.
@@ -286,15 +311,16 @@ G4ExtrudedSolid::G4ExtrudedSolid(const G4ExtrudedSolid& rhs)
: G4TessellatedSolid(rhs), fNv(rhs.fNv), fNz(rhs.fNz),
fPolygon(rhs.fPolygon), fZSections(rhs.fZSections),
fTriangles(rhs.fTriangles), fIsConvex(rhs.fIsConvex),
fGeometryType(rhs.fGeometryType), fKScales(rhs.fKScales),
fScale0s(rhs.fScale0s), fKOffsets(rhs.fKOffsets), fOffset0s(rhs.fOffset0s)
fGeometryType(rhs.fGeometryType),
fSolidType(rhs.fSolidType), fPlanes(rhs.fPlanes),
fKScales(rhs.fKScales), fScale0s(rhs.fScale0s),
fKOffsets(rhs.fKOffsets), fOffset0s(rhs.fOffset0s)
{
}
//_____________________________________________________________________________
G4ExtrudedSolid& G4ExtrudedSolid::operator = (const G4ExtrudedSolid& rhs)
G4ExtrudedSolid& G4ExtrudedSolid::operator = (const G4ExtrudedSolid& rhs)
{
// Check assignment to self
//
@@ -309,9 +335,10 @@ G4ExtrudedSolid& G4ExtrudedSolid::operator = (const G4ExtrudedSolid& rhs)
fNv = rhs.fNv; fNz = rhs.fNz;
fPolygon = rhs.fPolygon; fZSections = rhs.fZSections;
fTriangles = rhs.fTriangles; fIsConvex = rhs.fIsConvex;
fGeometryType = rhs.fGeometryType; fKScales = rhs.fKScales;
fScale0s = rhs.fScale0s; fKOffsets = rhs.fKOffsets;
fOffset0s = rhs.fOffset0s;
fGeometryType = rhs.fGeometryType;
fSolidType = rhs.fSolidType; fPlanes = rhs.fPlanes;
fKScales = rhs.fKScales; fScale0s = rhs.fScale0s;
fKOffsets = rhs.fKOffsets; fOffset0s = rhs.fOffset0s;
return *this;
}
@@ -327,15 +354,15 @@ G4ExtrudedSolid::~G4ExtrudedSolid()
void G4ExtrudedSolid::ComputeProjectionParameters()
{
// Compute parameters for point projections p(z)
// Compute parameters for point projections p(z)
// to the polygon scale & offset:
// scale(z) = k*z + scale0
// offset(z) = l*z + offset0
// p(z) = scale(z)*p0 + offset(z)
// p(z) = scale(z)*p0 + offset(z)
// p0 = (p(z) - offset(z))/scale(z);
//
//
for ( G4int iz=0; iz<fNz-1; ++iz)
for ( G4int iz=0; iz<fNz-1; ++iz)
{
G4double z1 = fZSections[iz].fZ;
G4double z2 = fZSections[iz+1].fZ;
@@ -343,19 +370,57 @@ void G4ExtrudedSolid::ComputeProjectionParameters()
G4double scale2 = fZSections[iz+1].fScale;
G4TwoVector off1 = fZSections[iz].fOffset;
G4TwoVector off2 = fZSections[iz+1].fOffset;
G4double kscale = (scale2 - scale1)/(z2 - z1);
G4double scale0 = scale2 - kscale*(z2 - z1)/2.0;
G4double scale0 = scale2 - kscale*(z2 - z1)/2.0;
G4TwoVector koff = (off2 - off1)/(z2 - z1);
G4TwoVector off0 = off2 - koff*(z2 - z1)/2.0;
G4TwoVector off0 = off2 - koff*(z2 - z1)/2.0;
fKScales.push_back(kscale);
fScale0s.push_back(scale0);
fKOffsets.push_back(koff);
fOffset0s.push_back(off0);
}
}
}
//_____________________________________________________________________________
void G4ExtrudedSolid::ComputeLateralPlanes()
{
// Compute lateral planes: a*x + b*y + c*z + d = 0
//
G4int Nv = fPolygon.size();
fPlanes.resize(Nv);
for (G4int i=0, k=Nv-1; i<Nv; k=i++)
{
G4TwoVector norm = (fPolygon[i] - fPolygon[k]).unit();
fPlanes[i].a = -norm.y();
fPlanes[i].b = norm.x();
fPlanes[i].c = 0;
fPlanes[i].d = norm.y()*fPolygon[i].x() - norm.x()*fPolygon[i].y();
}
// Compute edge equations: x = k*y + m
// and edge lengths
//
fLines.resize(Nv);
fLengths.resize(Nv);
for (G4int i=0, k=Nv-1; i<Nv; k=i++)
{
if (fPolygon[k].y() == fPolygon[i].y())
{
fLines[i].k = 0;
fLines[i].m = fPolygon[i].x();
}
else
{
G4double ctg = (fPolygon[k].x()-fPolygon[i].x())/(fPolygon[k].y()-fPolygon[i].y());
fLines[i].k = ctg;
fLines[i].m = fPolygon[i].x() - ctg*fPolygon[i].y();
}
fLengths[i] = (fPolygon[i] - fPolygon[k]).mag();
}
}
//_____________________________________________________________________________
@@ -371,7 +436,6 @@ G4ThreeVector G4ExtrudedSolid::GetVertex(G4int iz, G4int ind) const
//_____________________________________________________________________________
G4TwoVector G4ExtrudedSolid::ProjectPoint(const G4ThreeVector& point) const
{
// Project point in the polygon scale
@@ -805,8 +869,44 @@ G4VSolid* G4ExtrudedSolid::Clone() const
//_____________________________________________________________________________
EInside G4ExtrudedSolid::Inside (const G4ThreeVector &p) const
EInside G4ExtrudedSolid::Inside(const G4ThreeVector &p) const
{
switch (fSolidType)
{
case 1: // convex right prism
{
G4double dist = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
if (dist > kCarToleranceHalf) { return kOutside; }
G4int np = fPlanes.size();
for (G4int i=0; i<np; ++i)
{
G4double dd = fPlanes[i].a*p.x() + fPlanes[i].b*p.y() + fPlanes[i].d;
if (dd > dist) { dist = dd; }
}
if (dist > kCarToleranceHalf) { return kOutside; }
return (dist > -kCarToleranceHalf) ? kSurface : kInside;
}
case 2: // non-convex right prism
{
G4double distz = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
if (distz > kCarToleranceHalf) { return kOutside; }
G4bool in = PointInPolygon(p);
if (distz > -kCarToleranceHalf && in) { return kSurface; }
G4double dd = DistanceToPolygonSqr(p) - kCarToleranceHalf*kCarToleranceHalf;
if (in)
{
return (dd >= 0) ? kInside : kSurface;
}
else
{
return (dd > 0) ? kOutside : kSurface;
}
}
}
// Override the base class function as it fails in case of concave polygon.
// Project the point in the original polygon scale and check if it is inside
// for each triangle.
@@ -822,7 +922,7 @@ EInside G4ExtrudedSolid::Inside (const G4ThreeVector &p) const
{
// G4cout << "G4ExtrudedSolid::Outside extent: " << p << G4endl;
return kOutside;
}
}
// Project point p(z) to the polygon scale p0
//
@@ -839,8 +939,8 @@ EInside G4ExtrudedSolid::Inside (const G4ThreeVector &p) const
// << G4endl;
return kSurface;
}
}
}
}
// Now check if inside triangles
//
@@ -852,7 +952,7 @@ EInside G4ExtrudedSolid::Inside (const G4ThreeVector &p) const
fPolygon[(*it)[2]], pscaled) ) { inside = true; }
++it;
} while ( (inside == false) && (it != fTriangles.end()) );
if ( inside )
{
// Check if on surface of z sides
@@ -864,17 +964,297 @@ EInside G4ExtrudedSolid::Inside (const G4ThreeVector &p) const
// << G4endl;
return kSurface;
}
}
// G4cout << "G4ExtrudedSolid::Inside return Inside" << G4endl;
return kInside;
}
}
// G4cout << "G4ExtrudedSolid::Inside return Outside " << G4endl;
return kOutside;
}
return kOutside;
}
//_____________________________________________________________________________
G4ThreeVector G4ExtrudedSolid::SurfaceNormal(const G4ThreeVector& p) const
{
G4int nsurf = 0;
G4double nx = 0, ny = 0, nz = 0;
switch (fSolidType)
{
case 1: // convex right prism
{
if (std::abs(p.z() - fZSections[0].fZ) <= kCarToleranceHalf) { nz = -1; ++nsurf; }
if (std::abs(p.z() - fZSections[1].fZ) <= kCarToleranceHalf) { nz = 1; ++nsurf; }
for (G4int i=0; i<fNv; ++i)
{
G4double dd = fPlanes[i].a*p.x() + fPlanes[i].b*p.y() + fPlanes[i].d;
if (std::abs(dd) > kCarToleranceHalf) continue;
nx += fPlanes[i].a;
ny += fPlanes[i].b;
++nsurf;
}
break;
}
case 2: // non-convex right prism
{
if (std::abs(p.z() - fZSections[0].fZ) <= kCarToleranceHalf) { nz = -1; ++nsurf; }
if (std::abs(p.z() - fZSections[1].fZ) <= kCarToleranceHalf) { nz = 1; ++nsurf; }
G4double sqrCarToleranceHalf = kCarToleranceHalf*kCarToleranceHalf;
for (G4int i=0, k=fNv-1; i<fNv; k=i++)
{
G4double ix = p.x() - fPolygon[i].x();
G4double iy = p.y() - fPolygon[i].y();
G4double u = fPlanes[i].a*iy - fPlanes[i].b*ix;
if (u < 0)
{
if (ix*ix + iy*iy > sqrCarToleranceHalf) continue;
}
else if (u > fLengths[i])
{
G4double kx = p.x() - fPolygon[k].x();
G4double ky = p.y() - fPolygon[k].y();
if (kx*kx + ky*ky > sqrCarToleranceHalf) continue;
}
else
{
G4double dd = fPlanes[i].a*p.x() + fPlanes[i].b*p.y() + fPlanes[i].d;
if (dd*dd > sqrCarToleranceHalf) continue;
}
nx += fPlanes[i].a;
ny += fPlanes[i].b;
++nsurf;
}
break;
}
default:
{
return G4TessellatedSolid::SurfaceNormal(p);
}
}
// Return normal (right prism)
//
if (nsurf == 1)
{
return G4ThreeVector(nx,ny,nz);
}
else if (nsurf != 0) // edge or corner
{
return G4ThreeVector(nx,ny,nz).unit();
}
else
{
// Point is not on the surface, compute approximate normal
//
#ifdef G4CSGDEBUG
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("G4TesselatedSolid::SurfaceNormal(p)", "GeomSolids1002",
JustWarning, message );
DumpInfo();
#endif
return ApproxSurfaceNormal(p);
}
}
//_____________________________________________________________________________
G4ThreeVector G4ExtrudedSolid::ApproxSurfaceNormal(const G4ThreeVector& p) const
{
// This method is valid only for right prisms and
// normally should not be called
if (fSolidType == 1 || fSolidType == 2)
{
// Find distances to z-planes
//
G4double dz0 = fZSections[0].fZ - p.z();
G4double dz1 = p.z() - fZSections[1].fZ;
G4double ddz0 = dz0*dz0;
G4double ddz1 = dz1*dz1;
// Find nearest lateral side and distance to it
//
G4int iside = 0;
G4double dd = DBL_MAX;
for (G4int i=0, k=fNv-1; i<fNv; k=i++)
{
G4double ix = p.x() - fPolygon[i].x();
G4double iy = p.y() - fPolygon[i].y();
G4double u = fPlanes[i].a*iy - fPlanes[i].b*ix;
if (u < 0)
{
G4double tmp = ix*ix + iy*iy;
if (tmp < dd) { dd = tmp; iside = i; }
}
else if (u > fLengths[i])
{
G4double kx = p.x() - fPolygon[k].x();
G4double ky = p.y() - fPolygon[k].y();
G4double tmp = kx*kx + ky*ky;
if (tmp < dd) { dd = tmp; iside = i; }
}
else
{
G4double tmp = fPlanes[i].a*p.x() + fPlanes[i].b*p.y() + fPlanes[i].d;
tmp *= tmp;
if (tmp < dd) { dd = tmp; iside = i; }
}
}
// Find region
//
// 3 | 1 | 3
// ----+-------+----
// 2 | 0 | 2
// ----+-------+----
// 3 | 1 | 3
//
G4int iregion = 0;
if (std::max(dz0,dz1) > 0) iregion = 1;
G4bool in = PointInPolygon(p);
if (!in) iregion += 2;
// Return normal
//
switch (iregion)
{
case 0:
{
if (ddz0 <= ddz1 && ddz0 <= dd) return G4ThreeVector(0, 0,-1);
if (ddz1 <= ddz0 && ddz1 <= dd) return G4ThreeVector(0, 0, 1);
return G4ThreeVector(fPlanes[iside].a,fPlanes[iside].b, 0);
}
case 1:
{
return G4ThreeVector(0, 0, (dz0 > dz1) ? -1 : 1);
}
case 2:
{
return G4ThreeVector(fPlanes[iside].a,fPlanes[iside].b, 0);
}
case 3:
{
G4double dzmax = std::max(dz0,dz1);
if (dzmax*dzmax > dd) return G4ThreeVector(0,0,(dz0 > dz1) ? -1 : 1);
return G4ThreeVector(fPlanes[iside].a,fPlanes[iside].b, 0);
}
}
}
return G4ThreeVector(0,0,0);
}
//_____________________________________________________________________________
G4double G4ExtrudedSolid::DistanceToIn(const G4ThreeVector& p,
const G4ThreeVector& v) const
{
G4double z0 = fZSections[0].fZ;
G4double z1 = fZSections[fNz-1].fZ;
if ((p.z() <= z0 + kCarToleranceHalf) && v.z() <= 0) return kInfinity;
if ((p.z() >= z1 - kCarToleranceHalf) && v.z() >= 0) return kInfinity;
switch (fSolidType)
{
case 1: // convex right prism
{
// Intersection with Z planes
//
G4double dz = (z1 - z0)*0.5;
G4double pz = p.z() - dz - z0;
G4double invz = (v.z() == 0) ? DBL_MAX : -1./v.z();
G4double ddz = (invz < 0) ? dz : -dz;
G4double tzmin = (pz + ddz)*invz;
G4double tzmax = (pz - ddz)*invz;
// Intersection with lateral planes
//
G4int np = fPlanes.size();
G4double txmin = tzmin, txmax = tzmax;
for (G4int i=0; i<np; ++i)
{
G4double cosa = fPlanes[i].a*v.x()+fPlanes[i].b*v.y();
G4double dist = fPlanes[i].a*p.x()+fPlanes[i].b*p.y()+fPlanes[i].d;
if (dist >= -kCarToleranceHalf)
{
if (cosa >= 0) { return kInfinity; }
G4double tmp = -dist/cosa;
if (txmin < tmp) { txmin = tmp; }
}
else if (cosa > 0)
{
G4double tmp = -dist/cosa;
if (txmax > tmp) { txmax = tmp; }
}
}
// Find distance
//
G4double tmin = txmin, tmax = txmax;
if (tmax <= tmin + kCarToleranceHalf) // touch or no hit
{
return kInfinity;
}
return (tmin < kCarToleranceHalf) ? 0. : tmin;
}
case 2: // non-convex right prism
{
}
}
return G4TessellatedSolid::DistanceToIn(p,v);
}
//_____________________________________________________________________________
G4double G4ExtrudedSolid::DistanceToIn (const G4ThreeVector& p) const
{
switch (fSolidType)
{
case 1: // convex right prism
{
G4double dist = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
G4int np = fPlanes.size();
for (G4int i=0; i<np; ++i)
{
G4double dd = fPlanes[i].a*p.x() + fPlanes[i].b*p.y() + fPlanes[i].d;
if (dd > dist) dist = dd;
}
return (dist > 0) ? dist : 0.;
}
case 2: // non-convex right prism
{
G4bool in = PointInPolygon(p);
if (in)
{
G4double distz = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
return (distz > 0) ? distz : 0;
}
else
{
G4double distz = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
G4double dd = DistanceToPolygonSqr(p);
if (distz > 0) dd += distz*distz;
return std::sqrt(dd);
}
}
}
// General case: use tessellated solid
return G4TessellatedSolid::DistanceToIn(p);
}
//_____________________________________________________________________________
@@ -884,8 +1264,72 @@ G4double G4ExtrudedSolid::DistanceToOut (const G4ThreeVector &p,
G4bool *validNorm,
G4ThreeVector *n) const
{
G4bool getnorm = calcNorm;
if (getnorm) *validNorm = true;
G4double z0 = fZSections[0].fZ;
G4double z1 = fZSections[fNz-1].fZ;
if ((p.z() <= z0 + kCarToleranceHalf) && v.z() < 0)
{
if (getnorm) n->set(0,0,-1);
return 0;
}
if ((p.z() >= z1 - kCarToleranceHalf) && v.z() > 0)
{
if (getnorm) n->set(0,0,1);
return 0;
}
switch (fSolidType)
{
case 1: // convex right prism
{
// Intersection with Z planes
//
G4double dz = (z1 - z0)*0.5;
G4double pz = p.z() - z1 - z0;
G4double vz = v.z();
G4double tmax = (vz == 0) ? DBL_MAX : (std::copysign(dz,vz) - pz)/vz;
G4int iside = (vz < 0) ? -4 : -2; // little trick: (-4+3)=-1, (-2+3)=+1
// Intersection with lateral planes
//
G4int np = fPlanes.size();
for (G4int i=0; i<np; ++i)
{
G4double cosa = fPlanes[i].a*v.x()+fPlanes[i].b*v.y();
if (cosa > 0)
{
G4double dist = fPlanes[i].a*p.x()+fPlanes[i].b*p.y()+fPlanes[i].d;
if (dist >= -kCarToleranceHalf)
{
if (getnorm) n->set(fPlanes[i].a, fPlanes[i].b, fPlanes[i].c);
return 0;
}
G4double tmp = -dist/cosa;
if (tmax > tmp) { tmax = tmp; iside = i; }
}
}
// Set normal, if required, and return distance
//
if (getnorm)
{
if (iside < 0)
{ n->set(0, 0, iside + 3); } // (-4+3)=-1, (-2+3)=+1
else
{ n->set(fPlanes[iside].a, fPlanes[iside].b, fPlanes[iside].c); }
}
return tmax;
}
case 2: // non-convex right prism
{
}
}
// Override the base class function to redefine validNorm
// (the solid can be concave)
// (the solid can be concave)
G4double distOut =
G4TessellatedSolid::DistanceToOut(p, v, calcNorm, validNorm, n);
@@ -894,18 +1338,37 @@ G4double G4ExtrudedSolid::DistanceToOut (const G4ThreeVector &p,
return distOut;
}
//_____________________________________________________________________________
G4double G4ExtrudedSolid::DistanceToOut (const G4ThreeVector &p) const
G4double G4ExtrudedSolid::DistanceToOut(const G4ThreeVector &p) const
{
// Override the overloaded base class function
switch (fSolidType)
{
case 1: // convex right prism
{
G4double dist = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
G4int np = fPlanes.size();
for (G4int i=0; i<np; ++i)
{
G4double dd = fPlanes[i].a*p.x() + fPlanes[i].b*p.y() + fPlanes[i].d;
if (dd > dist) dist = dd;
}
return (dist < 0) ? -dist : 0.;
}
case 2: // non-convex right prism
{
G4double distz = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
G4bool in = PointInPolygon(p);
if (distz >= 0 || (!in)) return 0; // point is outside
return std::min(-distz,std::sqrt(DistanceToPolygonSqr(p)));
}
}
// General case: use tessellated solid
return G4TessellatedSolid::DistanceToOut(p);
}
///////////////////////////////////////////////////////////////////////////////
//
//_____________________________________________________________________________
// Get bounding box
void G4ExtrudedSolid::BoundingLimits(G4ThreeVector& pMin,
@@ -961,8 +1424,7 @@ void G4ExtrudedSolid::BoundingLimits(G4ThreeVector& pMin,
}
}
//////////////////////////////////////////////////////////////////////////////
//
//_____________________________________________________________________________
// Calculate extent under transform and specified limit
G4bool
@@ -1107,4 +1569,4 @@ std::ostream& G4ExtrudedSolid::StreamInfo(std::ostream &os) const
return os;
}
#endif
//#endif
@@ -39,7 +39,7 @@
#include "G4GenericPolycone.hh"
#if !defined(G4GEOM_USE_UGENERICPOLYCONE)
//#if !defined(G4GEOM_USE_UGENERICPOLYCONE)
#include "G4PolyconeSide.hh"
#include "G4PolyPhiFace.hh"
@@ -946,4 +946,4 @@ G4Polyhedron* G4GenericPolycone::CreatePolyhedron() const
}
}
#endif
//#endif
@@ -24,7 +24,7 @@
// ********************************************************************
//
//
// $Id: G4Hype.cc 104316 2017-05-24 13:04:23Z gcosmo $
// $Id: G4Hype.cc 106627 2017-10-17 06:23:58Z gcosmo $
// $Original: G4Hype.cc,v 1.0 1998/06/09 16:57:50 safai Exp $
//
//
@@ -45,6 +45,8 @@
#include "G4Hype.hh"
//#if !(defined(G4GEOM_USE_UHYPE) && defined(G4GEOM_USE_SYS_USOLIDS))
#include "G4VoxelLimits.hh"
#include "G4AffineTransform.hh"
#include "G4BoundingEnvelope.hh"
@@ -1338,3 +1340,5 @@ G4double G4Hype::asinh(G4double arg)
{
return std::log(arg+std::sqrt(sqr(arg)+1));
}
//#endif // !defined(G4GEOM_USE_UHYPE) || !defined(G4GEOM_USE_SYS_USOLIDS)
@@ -24,7 +24,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4TessellatedSolid.cc 104316 2017-05-24 13:04:23Z gcosmo $
// $Id: G4TessellatedSolid.cc 106710 2017-10-20 09:22:51Z gcosmo $
//
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//
@@ -1605,6 +1605,7 @@ G4GeometryType G4TessellatedSolid::GetEntityType () const
std::ostream &G4TessellatedSolid::StreamInfo(std::ostream &os) const
{
os << G4endl;
os << "Solid name = " << GetName() << G4endl;
os << "Geometry Type = " << fGeometryType << G4endl;
os << "Number of facets = " << fFacets.size() << G4endl;
+4 -4
View File
@@ -27,7 +27,7 @@
// * *
// ********************************************************************
//
// $Id: G4Tet.cc 104316 2017-05-24 13:04:23Z gcosmo $
// $Id: G4Tet.cc 106603 2017-10-16 09:17:44Z gcosmo $
//
// class G4Tet
//
@@ -57,9 +57,9 @@
#include "G4Tet.hh"
#if !defined(G4GEOM_USE_UTET)
//#if !defined(G4GEOM_USE_UTET)
const char G4Tet::CVSVers[]="$Id: G4Tet.cc 104316 2017-05-24 13:04:23Z gcosmo $";
const char G4Tet::CVSVers[]="$Id: G4Tet.cc 106603 2017-10-16 09:17:44Z gcosmo $";
#include "G4VoxelLimits.hh"
#include "G4AffineTransform.hh"
@@ -817,4 +817,4 @@ G4Polyhedron* G4Tet::GetPolyhedron () const
return fpPolyhedron;
}
#endif
//#endif
@@ -24,7 +24,7 @@
// ********************************************************************
//
//
// $Id: G4TwistedTubs.cc 104316 2017-05-24 13:04:23Z gcosmo $
// $Id: G4TwistedTubs.cc 105776 2017-08-17 08:09:09Z gcosmo $
//
//
// --------------------------------------------------------------------
@@ -906,11 +906,12 @@ G4Polyhedron* G4TwistedTubs::CreatePolyhedron () const
{
// number of meshes
//
G4double dA = std::max(fDPhi,fPhiTwist);
G4double absPhiTwist = std::abs(fPhiTwist);
G4double dA = std::max(fDPhi,absPhiTwist);
const G4int k =
G4int(G4Polyhedron::GetNumberOfRotationSteps() * dA / twopi) + 2;
const G4int n =
G4int(G4Polyhedron::GetNumberOfRotationSteps() * fPhiTwist / twopi) + 2;
G4int(G4Polyhedron::GetNumberOfRotationSteps() * absPhiTwist / twopi) + 2;
const G4int nnodes = 4*(k-1)*(n-2) + 2*k*k ;
const G4int nfaces = 4*(k-1)*(n-1) + 2*(k-1)*(k-1) ;
@@ -31,6 +31,7 @@
// --------------------------------------------------------------------
#include "G4ExtrudedSolid.hh"
#if 0
#include "G4UExtrudedSolid.hh"
#if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
@@ -396,3 +397,4 @@ G4Polyhedron* G4UExtrudedSolid::CreatePolyhedron () const
}
#endif // G4GEOM_USE_USOLIDS
#endif
@@ -31,6 +31,7 @@
// --------------------------------------------------------------------
#include "G4GenericPolycone.hh"
#if 0
#include "G4UGenericPolycone.hh"
#if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
@@ -629,3 +630,4 @@ G4Polyhedron* G4UGenericPolycone::CreatePolyhedron() const
}
#endif // G4GEOM_USE_USOLIDS
#endif
@@ -0,0 +1,244 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
// $Id:$
//
// Implementation for G4UHype wrapper class
//
// 16-10-2017 G.Cosmo, CERN
//
// --------------------------------------------------------------------
#include "G4Hype.hh"
#if 0
#include "G4UHype.hh"
#if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
#include "G4AffineTransform.hh"
#include "G4VPVParameterisation.hh"
#include "G4BoundingEnvelope.hh"
#include "G4Polyhedron.hh"
////////////////////////////////////////////////////////////////////////
//
// Constructor
G4UHype::G4UHype(const G4String& pName,
G4double newInnerRadius,
G4double newOuterRadius,
G4double newInnerStereo,
G4double newOuterStereo,
G4double newHalfLenZ)
: Base_t(pName, newInnerRadius, newOuterRadius,
newInnerStereo, newOuterStereo, newHalfLenZ)
{ }
//////////////////////////////////////////////////////////////////////////
//
// Fake default constructor - sets only member data and allocates memory
// for usage restricted to object persistency.
G4UHype::G4UHype( __void__& a )
: Base_t(a)
{ }
//////////////////////////////////////////////////////////////////////////
//
// Destructor
G4UHype::~G4UHype() { }
//////////////////////////////////////////////////////////////////////////
//
// Copy constructor
G4UHype::G4UHype(const G4UHype& rhs)
: Base_t(rhs)
{ }
//////////////////////////////////////////////////////////////////////////
//
// Assignment operator
G4UHype& G4UHype::operator = (const G4UHype& rhs)
{
// Check assignment to self
//
if (this == &rhs) { return *this; }
// Copy base class data
//
Base_t::operator=(rhs);
return *this;
}
//////////////////////////////////////////////////////////////////////////
//
// Accessors
G4double G4UHype::GetInnerRadius () const
{
return GetRmin();
}
G4double G4UHype::GetOuterRadius () const
{
return GetRmax();
}
G4double G4UHype::GetZHalfLength () const
{
return GetDz();
}
G4double G4UHype::GetInnerStereo () const
{
return GetStIn();
}
G4double G4UHype::GetOuterStereo () const
{
return GetStOut();
}
//////////////////////////////////////////////////////////////////////////
//
// Modifiers
void G4UHype::SetInnerRadius (G4double newIRad)
{
SetParameters(newIRad, GetRmax(), GetStIn(), GetStOut(), GetDz());
fRebuildPolyhedron = true;
}
void G4UHype::SetOuterRadius (G4double newORad)
{
SetParameters(GetRmin(), newORad, GetStIn(), GetStOut(), GetDz());
fRebuildPolyhedron = true;
}
void G4UHype::SetZHalfLength (G4double newHLZ)
{
SetParameters(GetRmin(), GetRmax(), GetStIn(), GetStOut(), newHLZ);
fRebuildPolyhedron = true;
}
void G4UHype::SetInnerStereo (G4double newISte)
{
SetParameters(GetRmin(), GetRmax(), newISte, GetStOut(), GetDz());
fRebuildPolyhedron = true;
}
void G4UHype::SetOuterStereo (G4double newOSte)
{
SetParameters(GetRmin(), GetRmax(), GetStIn(), newOSte, GetDz());
fRebuildPolyhedron = true;
}
////////////////////////////////////////////////////////////////////////
//
// Dispatch to parameterisation for replication mechanism dimension
// computation & modification.
void G4UHype::ComputeDimensions(G4VPVParameterisation* p,
const G4int n,
const G4VPhysicalVolume* pRep)
{
p->ComputeDimensions(*(G4Hype*)this,n,pRep);
}
//////////////////////////////////////////////////////////////////////////
//
// Make a clone of the object
G4VSolid* G4UHype::Clone() const
{
return new G4UHype(*this);
}
//////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4UHype::BoundingLimits(G4ThreeVector& pMin,
G4ThreeVector& pMax) const
{
G4double endORadius = GetEndInnerRadius();
pMin.set(-endORadius,-endORadius,-GetDz());
pMax.set( endORadius, endORadius, GetDz());
// Check correctness of the bounding box
//
if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
{
std::ostringstream message;
message << "Bad bounding box (min >= max) for solid: "
<< GetName() << " !"
<< "\npMin = " << pMin
<< "\npMax = " << pMax;
G4Exception("G4UHype::BoundingLimits()", "GeomMgt0001",
JustWarning, message);
StreamInfo(G4cout);
}
}
//////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
G4bool
G4UHype::CalculateExtent(const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax) const
{
G4ThreeVector bmin, bmax;
// Get bounding box
BoundingLimits(bmin,bmax);
// Find extent
G4BoundingEnvelope bbox(bmin,bmax);
return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
}
////////////////////////////////////////////////////////////////////////
//
// CreatePolyhedron
//
G4Polyhedron* G4UHype::CreatePolyhedron() const
{
return new G4PolyhedronHype(GetRmin(), GetRmax(),
GetTIn2(), GetTOut2(), GetDz());
}
#endif // G4GEOM_USE_USOLIDS
#endif
@@ -102,7 +102,7 @@ G4UPolyhedra::G4UPolyhedra(const G4String& name,
G4int numRZ,
const G4double r[],
const G4double z[] )
: Base_t(name, phiStart, phiTotal, numSide, numRZ/2, r, z)
: Base_t(name, phiStart, phiTotal, numSide, numRZ, r, z)
{
fGenericPgon = true;
SetOriginalParameters();
@@ -34,6 +34,7 @@
// --------------------------------------------------------------------
#include "G4Tet.hh"
#if 0
#include "G4UTet.hh"
#if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
@@ -224,3 +225,4 @@ G4Polyhedron* G4UTet::CreatePolyhedron() const
}
#endif // G4GEOM_USE_USOLIDS
#endif
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4VTwistedFaceted.cc 104316 2017-05-24 13:04:23Z gcosmo $
// $Id: G4VTwistedFaceted.cc 105776 2017-08-17 08:09:09Z gcosmo $
//
//
// --------------------------------------------------------------------
@@ -1152,7 +1152,8 @@ G4Polyhedron* G4VTwistedFaceted::CreatePolyhedron () const
{
// number of meshes
const G4int k =
G4int(G4Polyhedron::GetNumberOfRotationSteps() * fPhiTwist / twopi) + 2;
G4int(G4Polyhedron::GetNumberOfRotationSteps() *
std::abs(fPhiTwist) / twopi) + 2;
const G4int n = k;
const G4int nnodes = 4*(k-1)*(n-2) + 2*k*k ;
@@ -487,8 +487,9 @@ void G4Voxelizer::BuildBoundingBox(G4ThreeVector& amin,
fBoundingBoxSize[i] = (max - min) / 2 + tolerance * 0.5;
fBoundingBoxCenter[i] = min + fBoundingBoxSize[i];
}
fBoundingBox = G4Box("VoxBBox", fBoundingBoxSize.x(),
fBoundingBoxSize.y(), fBoundingBoxSize.z());
fBoundingBox.SetXHalfLength(fBoundingBoxSize.x());
fBoundingBox.SetYHalfLength(fBoundingBoxSize.y());
fBoundingBox.SetZHalfLength(fBoundingBoxSize.z());
}
// algorithm -