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