Import Geant4 10.3.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-12-09 12:35:28 +01:00
parent 4ec577e5c4
commit a3452e42ac
3514 changed files with 210500 additions and 89628 deletions
+33 -197
View File
@@ -24,7 +24,7 @@
// ********************************************************************
//
//
// $Id: G4Box.cc 83572 2014-09-01 15:23:27Z gcosmo $
// $Id: G4Box.cc 99469 2016-09-22 15:04:36Z gcosmo $
//
//
//
@@ -37,6 +37,8 @@
// and information before exception in DistanceToOut(p,v,...)
// 15.11.00 - D.Williams, V.Grichine: bug fixed in CalculateExtent - change
// algorithm for rotated vertices
// 23.08.16 - E.Tcherniaev: use G4BoundingEnvelope for CalculateExtent()
// 20.09.16 - E.Tcherniaev: added Extent(pmin,pmax)
// --------------------------------------------------------------------
#include "G4Box.hh"
@@ -46,6 +48,7 @@
#include "G4SystemOfUnits.hh"
#include "G4VoxelLimits.hh"
#include "G4AffineTransform.hh"
#include "G4BoundingEnvelope.hh"
#include "Randomize.hh"
#include "G4VPVParameterisation.hh"
@@ -200,6 +203,29 @@ void G4Box::ComputeDimensions(G4VPVParameterisation* p,
p->ComputeDimensions(*this,n,pRep);
}
//////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4Box::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
pMin.set(-fDx,-fDy,-fDz);
pMax.set( fDx, fDy, fDz);
// 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("G4Box::Extent()", "GeomMgt0001", JustWarning, message);
DumpInfo();
}
}
//////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
@@ -209,159 +235,14 @@ G4bool G4Box::CalculateExtent(const EAxis pAxis,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax) const
{
if (!pTransform.IsRotated())
{
// Special case handling for unrotated boxes
// Compute x/y/z mins and maxs respecting limits, with early returns
// if outside limits. Then switch() on pAxis
G4ThreeVector bmin, bmax;
G4double xoffset,xMin,xMax;
G4double yoffset,yMin,yMax;
G4double zoffset,zMin,zMax;
// Get bounding box
Extent(bmin,bmax);
xoffset = pTransform.NetTranslation().x() ;
xMin = xoffset - fDx ;
xMax = xoffset + fDx ;
if (pVoxelLimit.IsXLimited())
{
if ((xMin > pVoxelLimit.GetMaxXExtent()+kCarTolerance) ||
(xMax < pVoxelLimit.GetMinXExtent()-kCarTolerance)) { return false ; }
else
{
xMin = std::max(xMin, pVoxelLimit.GetMinXExtent());
xMax = std::min(xMax, pVoxelLimit.GetMaxXExtent());
}
}
yoffset = pTransform.NetTranslation().y() ;
yMin = yoffset - fDy ;
yMax = yoffset + fDy ;
if (pVoxelLimit.IsYLimited())
{
if ((yMin > pVoxelLimit.GetMaxYExtent()+kCarTolerance) ||
(yMax < pVoxelLimit.GetMinYExtent()-kCarTolerance)) { return false ; }
else
{
yMin = std::max(yMin, pVoxelLimit.GetMinYExtent());
yMax = std::min(yMax, pVoxelLimit.GetMaxYExtent());
}
}
zoffset = pTransform.NetTranslation().z() ;
zMin = zoffset - fDz ;
zMax = zoffset + fDz ;
if (pVoxelLimit.IsZLimited())
{
if ((zMin > pVoxelLimit.GetMaxZExtent()+kCarTolerance) ||
(zMax < pVoxelLimit.GetMinZExtent()-kCarTolerance)) { return false ; }
else
{
zMin = std::max(zMin, pVoxelLimit.GetMinZExtent());
zMax = std::min(zMax, pVoxelLimit.GetMaxZExtent());
}
}
switch (pAxis)
{
case kXAxis:
pMin = xMin ;
pMax = xMax ;
break ;
case kYAxis:
pMin=yMin;
pMax=yMax;
break;
case kZAxis:
pMin=zMin;
pMax=zMax;
break;
default:
break;
}
pMin -= kCarTolerance ;
pMax += kCarTolerance ;
return true;
}
else // General rotated case - create and clip mesh to boundaries
{
G4bool existsAfterClip = false ;
G4ThreeVectorList* vertices ;
pMin = +kInfinity ;
pMax = -kInfinity ;
// Calculate rotated vertex coordinates
vertices = CreateRotatedVertices(pTransform) ;
ClipCrossSection(vertices,0,pVoxelLimit,pAxis,pMin,pMax) ;
ClipCrossSection(vertices,4,pVoxelLimit,pAxis,pMin,pMax) ;
ClipBetweenSections(vertices,0,pVoxelLimit,pAxis,pMin,pMax) ;
if (pVoxelLimit.IsLimited(pAxis) == false)
{
if ( (pMin != kInfinity) || (pMax != -kInfinity) )
{
existsAfterClip = true ;
// Add 2*tolerance to avoid precision troubles
pMin -= kCarTolerance;
pMax += kCarTolerance;
}
}
else
{
G4ThreeVector clipCentre(
( pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
( pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
( pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5);
if ( (pMin != kInfinity) || (pMax != -kInfinity) )
{
existsAfterClip = true ;
// Check to see if endpoints are in the solid
clipCentre(pAxis) = pVoxelLimit.GetMinExtent(pAxis);
if (Inside(pTransform.Inverse().TransformPoint(clipCentre)) != kOutside)
{
pMin = pVoxelLimit.GetMinExtent(pAxis);
}
else
{
pMin -= kCarTolerance;
}
clipCentre(pAxis) = pVoxelLimit.GetMaxExtent(pAxis);
if (Inside(pTransform.Inverse().TransformPoint(clipCentre)) != kOutside)
{
pMax = pVoxelLimit.GetMaxExtent(pAxis);
}
else
{
pMax += kCarTolerance;
}
}
// Check for case where completely enveloping clipping volume
// If point inside then we are confident that the solid completely
// envelopes the clipping volume. Hence set min/max extents according
// to clipping volume extents along the specified axis.
else if (Inside(pTransform.Inverse().TransformPoint(clipCentre))
!= kOutside)
{
existsAfterClip = true ;
pMin = pVoxelLimit.GetMinExtent(pAxis) ;
pMax = pVoxelLimit.GetMaxExtent(pAxis) ;
}
}
delete vertices;
return existsAfterClip;
}
// Find extent
G4BoundingEnvelope bbox(bmin,bmax);
return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
}
/////////////////////////////////////////////////////////////////////////
@@ -904,51 +785,6 @@ G4double G4Box::DistanceToOut(const G4ThreeVector& p) const
return safe ;
}
////////////////////////////////////////////////////////////////////////
//
// Create a List containing the transformed vertices
// Ordering [0-3] -fDz cross section
// [4-7] +fDz cross section such that [0] is below [4],
// [1] below [5] etc.
// Note:
// Caller has deletion resposibility
G4ThreeVectorList*
G4Box::CreateRotatedVertices(const G4AffineTransform& pTransform) const
{
G4ThreeVectorList* vertices = new G4ThreeVectorList();
if (vertices)
{
vertices->reserve(8);
G4ThreeVector vertex0(-fDx,-fDy,-fDz) ;
G4ThreeVector vertex1(fDx,-fDy,-fDz) ;
G4ThreeVector vertex2(fDx,fDy,-fDz) ;
G4ThreeVector vertex3(-fDx,fDy,-fDz) ;
G4ThreeVector vertex4(-fDx,-fDy,fDz) ;
G4ThreeVector vertex5(fDx,-fDy,fDz) ;
G4ThreeVector vertex6(fDx,fDy,fDz) ;
G4ThreeVector vertex7(-fDx,fDy,fDz) ;
vertices->push_back(pTransform.TransformPoint(vertex0));
vertices->push_back(pTransform.TransformPoint(vertex1));
vertices->push_back(pTransform.TransformPoint(vertex2));
vertices->push_back(pTransform.TransformPoint(vertex3));
vertices->push_back(pTransform.TransformPoint(vertex4));
vertices->push_back(pTransform.TransformPoint(vertex5));
vertices->push_back(pTransform.TransformPoint(vertex6));
vertices->push_back(pTransform.TransformPoint(vertex7));
}
else
{
DumpInfo();
G4Exception("G4Box::CreateRotatedVertices()",
"GeomSolids0003", FatalException,
"Error in allocation of vertices. Out of memory !");
}
return vertices;
}
//////////////////////////////////////////////////////////////////////////
//
// GetEntityType
+159 -310
View File
@@ -24,7 +24,7 @@
// ********************************************************************
//
//
// $Id: G4Cons.cc 90248 2015-05-21 14:18:50Z gcosmo $
// $Id: G4Cons.cc 101121 2016-11-07 09:18:01Z gcosmo $
// GEANT4 tag $Name: $
//
//
@@ -34,6 +34,9 @@
//
// History:
//
// 03.10.16 E.Tcherniaev: added Extent(pmin,pmax),
// use G4BoundingEnvelope for CalculateExtent(),
// removed CreateRotatedVertices()
// 04.09.14 T.Nikitina: Fix typo error in GetPointOnSurface() when
// GetRadiusInRing() was introduced
// Fix DistanceToIn(p,v) for points on the Surface,
@@ -50,8 +53,10 @@
#if !defined(G4GEOM_USE_UCONS)
#include "G4GeomTools.hh"
#include "G4VoxelLimits.hh"
#include "G4AffineTransform.hh"
#include "G4BoundingEnvelope.hh"
#include "G4GeometryTolerance.hh"
#include "G4VPVParameterisation.hh"
@@ -264,221 +269,159 @@ void G4Cons::ComputeDimensions( G4VPVParameterisation* p,
p->ComputeDimensions(*this,n,pRep) ;
}
///////////////////////////////////////////////////////////////////////
//
// Get bounding box
///////////////////////////////////////////////////////////////////////////
void G4Cons::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
G4double rmin = std::min(GetInnerRadiusMinusZ(),GetInnerRadiusPlusZ());
G4double rmax = std::max(GetOuterRadiusMinusZ(),GetOuterRadiusPlusZ());
G4double dz = GetZHalfLength();
// Find bounding box
//
if (GetDeltaPhiAngle() < twopi)
{
G4TwoVector vmin,vmax;
G4GeomTools::DiskExtent(rmin,rmax,
GetSinStartPhi(),GetCosStartPhi(),
GetSinEndPhi(),GetCosEndPhi(),
vmin,vmax);
pMin.set(vmin.x(),vmin.y(),-dz);
pMax.set(vmax.x(),vmax.y(), dz);
}
else
{
pMin.set(-rmax,-rmax,-dz);
pMax.set( rmax, rmax, dz);
}
// 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("G4Cons::Extent()", "GeomMgt0001", JustWarning, message);
DumpInfo();
}
}
///////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
G4bool G4Cons::CalculateExtent( const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin,
G4double& pMax ) const
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin,
G4double& pMax ) const
{
if ( !pTransform.IsRotated() && (fDPhi == twopi)
&& (fRmin1 == 0) && (fRmin2 == 0) )
G4ThreeVector bmin, bmax;
G4bool exist;
// Get bounding box
Extent(bmin,bmax);
// Check bounding box
G4BoundingEnvelope bbox(bmin,bmax);
#ifdef G4BBOX_EXTENT
if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
#endif
if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
{
// Special case handling for unrotated solid cones
// Compute z/x/y mins and maxs for bounding box respecting limits,
// with early returns if outside limits. Then switch() on pAxis,
// and compute exact x and y limit for x/y case
G4double xoffset, xMin, xMax ;
G4double yoffset, yMin, yMax ;
G4double zoffset, zMin, zMax ;
G4double diff1, diff2, delta, maxDiff, newMin, newMax, RMax ;
G4double xoff1, xoff2, yoff1, yoff2 ;
zoffset = pTransform.NetTranslation().z();
zMin = zoffset - fDz ;
zMax = zoffset + fDz ;
if (pVoxelLimit.IsZLimited())
{
if( (zMin > pVoxelLimit.GetMaxZExtent() + kCarTolerance) ||
(zMax < pVoxelLimit.GetMinZExtent() - kCarTolerance) )
{
return false ;
}
else
{
if ( zMin < pVoxelLimit.GetMinZExtent() )
{
zMin = pVoxelLimit.GetMinZExtent() ;
}
if ( zMax > pVoxelLimit.GetMaxZExtent() )
{
zMax = pVoxelLimit.GetMaxZExtent() ;
}
}
}
xoffset = pTransform.NetTranslation().x() ;
RMax = (fRmax2 >= fRmax1) ? zMax : zMin ;
xMax = xoffset + (fRmax1 + fRmax2)*0.5 +
(RMax - zoffset)*(fRmax2 - fRmax1)/(2*fDz) ;
xMin = 2*xoffset-xMax ;
if (pVoxelLimit.IsXLimited())
{
if ( (xMin > pVoxelLimit.GetMaxXExtent() + kCarTolerance) ||
(xMax < pVoxelLimit.GetMinXExtent() - kCarTolerance) )
{
return false ;
}
else
{
if ( xMin < pVoxelLimit.GetMinXExtent() )
{
xMin = pVoxelLimit.GetMinXExtent() ;
}
if ( xMax > pVoxelLimit.GetMaxXExtent() )
{
xMax=pVoxelLimit.GetMaxXExtent() ;
}
}
}
yoffset = pTransform.NetTranslation().y() ;
yMax = yoffset + (fRmax1 + fRmax2)*0.5 +
(RMax - zoffset)*(fRmax2 - fRmax1)/(2*fDz) ;
yMin = 2*yoffset-yMax ;
RMax = yMax - yoffset ; // = max radius due to Zmax/Zmin cuttings
if (pVoxelLimit.IsYLimited())
{
if ( (yMin > pVoxelLimit.GetMaxYExtent() + kCarTolerance) ||
(yMax < pVoxelLimit.GetMinYExtent() - kCarTolerance) )
{
return false ;
}
else
{
if ( yMin < pVoxelLimit.GetMinYExtent() )
{
yMin = pVoxelLimit.GetMinYExtent() ;
}
if ( yMax > pVoxelLimit.GetMaxYExtent() )
{
yMax = pVoxelLimit.GetMaxYExtent() ;
}
}
}
switch (pAxis) // Known to cut cones
{
case kXAxis:
yoff1 = yoffset - yMin ;
yoff2 = yMax - yoffset ;
if ((yoff1 >= 0) && (yoff2 >= 0)) // Y limits cross max/min x
{ // => no change
pMin = xMin ;
pMax = xMax ;
}
else
{
// Y limits don't cross max/min x => compute max delta x,
// hence new mins/maxs
delta=RMax*RMax-yoff1*yoff1;
diff1=(delta>0.) ? std::sqrt(delta) : 0.;
delta=RMax*RMax-yoff2*yoff2;
diff2=(delta>0.) ? std::sqrt(delta) : 0.;
maxDiff = (diff1>diff2) ? diff1:diff2 ;
newMin = xoffset - maxDiff ;
newMax = xoffset + maxDiff ;
pMin = ( newMin < xMin ) ? xMin : newMin ;
pMax = ( newMax > xMax) ? xMax : newMax ;
}
break ;
case kYAxis:
xoff1 = xoffset - xMin ;
xoff2 = xMax - xoffset ;
if ((xoff1 >= 0) && (xoff2 >= 0) ) // X limits cross max/min y
{ // => no change
pMin = yMin ;
pMax = yMax ;
}
else
{
// X limits don't cross max/min y => compute max delta y,
// hence new mins/maxs
delta=RMax*RMax-xoff1*xoff1;
diff1=(delta>0.) ? std::sqrt(delta) : 0.;
delta=RMax*RMax-xoff2*xoff2;
diff2=(delta>0.) ? std::sqrt(delta) : 0.;
maxDiff = (diff1 > diff2) ? diff1:diff2 ;
newMin = yoffset - maxDiff ;
newMax = yoffset + maxDiff ;
pMin = (newMin < yMin) ? yMin : newMin ;
pMax = (newMax > yMax) ? yMax : newMax ;
}
break ;
case kZAxis:
pMin = zMin ;
pMax = zMax ;
break ;
default:
break ;
}
pMin -= kCarTolerance ;
pMax += kCarTolerance ;
return true ;
return exist = (pMin < pMax) ? true : false;
}
else // Calculate rotated vertex coordinates
// Get parameters of the solid
G4double rmin1 = GetInnerRadiusMinusZ();
G4double rmax1 = GetOuterRadiusMinusZ();
G4double rmin2 = GetInnerRadiusPlusZ();
G4double rmax2 = GetOuterRadiusPlusZ();
G4double dz = GetZHalfLength();
G4double dphi = GetDeltaPhiAngle();
// Find bounding envelope and calculate extent
//
const G4int NSTEPS = 24; // number of steps for whole circle
G4double astep = (360/NSTEPS)*deg; // max angle for one step
G4int ksteps = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1;
G4double ang = dphi/ksteps;
G4double sinHalf = std::sin(0.5*ang);
G4double cosHalf = std::cos(0.5*ang);
G4double sinStep = 2.*sinHalf*cosHalf;
G4double cosStep = 1. - 2.*sinHalf*sinHalf;
G4double rext1 = rmax1/cosHalf;
G4double rext2 = rmax2/cosHalf;
// bounding envelope for full cone without hole consists of two polygons,
// in other cases it is a sequence of quadrilaterals
if (rmin1 == 0 && rmin2 == 0 && dphi == twopi)
{
G4int i, noEntries, noBetweenSections4 ;
G4bool existsAfterClip = false ;
G4ThreeVectorList* vertices = CreateRotatedVertices(pTransform) ;
G4double sinCur = sinHalf;
G4double cosCur = cosHalf;
pMin = +kInfinity ;
pMax = -kInfinity ;
G4ThreeVectorList baseA(NSTEPS),baseB(NSTEPS);
for (G4int k=0; k<NSTEPS; ++k)
{
baseA[k].set(rext1*cosCur,rext1*sinCur,-dz);
baseB[k].set(rext2*cosCur,rext2*sinCur, dz);
noEntries = vertices->size() ;
noBetweenSections4 = noEntries-4 ;
for ( i = 0 ; i < noEntries ; i += 4 )
{
ClipCrossSection(vertices, i, pVoxelLimit, pAxis, pMin, pMax) ;
G4double sinTmp = sinCur;
sinCur = sinCur*cosStep + cosCur*sinStep;
cosCur = cosCur*cosStep - sinTmp*sinStep;
}
for ( i = 0 ; i < noBetweenSections4 ; i += 4 )
{
ClipBetweenSections(vertices, i, pVoxelLimit, pAxis, pMin, pMax) ;
}
if ( (pMin != kInfinity) || (pMax != -kInfinity) )
{
existsAfterClip = true ;
// Add 2*tolerance to avoid precision troubles
pMin -= kCarTolerance ;
pMax += kCarTolerance ;
}
else
{
// Check for case where completely enveloping clipping volume
// If point inside then we are confident that the solid completely
// envelopes the clipping volume. Hence set min/max extents according
// to clipping volume extents along the specified axis.
G4ThreeVector clipCentre(
(pVoxelLimit.GetMinXExtent() + pVoxelLimit.GetMaxXExtent())*0.5,
(pVoxelLimit.GetMinYExtent() + pVoxelLimit.GetMaxYExtent())*0.5,
(pVoxelLimit.GetMinZExtent() + pVoxelLimit.GetMaxZExtent())*0.5 ) ;
if (Inside(pTransform.Inverse().TransformPoint(clipCentre)) != kOutside)
{
existsAfterClip = true ;
pMin = pVoxelLimit.GetMinExtent(pAxis) ;
pMax = pVoxelLimit.GetMaxExtent(pAxis) ;
}
}
delete vertices ;
return existsAfterClip ;
std::vector<const G4ThreeVectorList *> polygons(2);
polygons[0] = &baseA;
polygons[1] = &baseB;
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
}
else
{
G4double sinStart = GetSinStartPhi();
G4double cosStart = GetCosStartPhi();
G4double sinEnd = GetSinEndPhi();
G4double cosEnd = GetCosEndPhi();
G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
// set quadrilaterals
G4ThreeVectorList pols[NSTEPS+2];
for (G4int k=0; k<ksteps+2; ++k) pols[k].resize(4);
pols[0][0].set(rmin2*cosStart,rmin2*sinStart, dz);
pols[0][1].set(rmin1*cosStart,rmin1*sinStart,-dz);
pols[0][2].set(rmax1*cosStart,rmax1*sinStart,-dz);
pols[0][3].set(rmax2*cosStart,rmax2*sinStart, dz);
for (G4int k=1; k<ksteps+1; ++k)
{
pols[k][0].set(rmin2*cosCur,rmin2*sinCur, dz);
pols[k][1].set(rmin1*cosCur,rmin1*sinCur,-dz);
pols[k][2].set(rext1*cosCur,rext1*sinCur,-dz);
pols[k][3].set(rext2*cosCur,rext2*sinCur, dz);
G4double sinTmp = sinCur;
sinCur = sinCur*cosStep + cosCur*sinStep;
cosCur = cosCur*cosStep - sinTmp*sinStep;
}
pols[ksteps+1][0].set(rmin2*cosEnd,rmin2*sinEnd, dz);
pols[ksteps+1][1].set(rmin1*cosEnd,rmin1*sinEnd,-dz);
pols[ksteps+1][2].set(rmax1*cosEnd,rmax1*sinEnd,-dz);
pols[ksteps+1][3].set(rmax2*cosEnd,rmax2*sinEnd, dz);
// set envelope and calculate extent
std::vector<const G4ThreeVectorList *> polygons;
polygons.resize(ksteps+2);
for (G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k];
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
}
return exist;
}
////////////////////////////////////////////////////////////////////////
@@ -1137,7 +1080,7 @@ G4double G4Cons::DistanceToIn( const G4ThreeVector& p,
}
else
{
if (b>0) { sd = -b - std::sqrt(d); }
if (b>0) { sd = -b - std::sqrt(d); }
else { sd = c/(-b+std::sqrt(d)); }
zi = p.z() + sd*v.z() ;
ri = rMinAv + zi*tanRMin ;
@@ -2146,100 +2089,6 @@ G4double G4Cons::DistanceToOut(const G4ThreeVector& p) const
return safe ;
}
////////////////////////////////////////////////////////////////////////////
//
// Create a List containing the transformed vertices
// Ordering [0-3] -fDz cross section
// [4-7] +fDz cross section such that [0] is below [4],
// [1] below [5] etc.
// Note:
// Caller has deletion resposibility
// Potential improvement: For last slice, use actual ending angle
// to avoid rounding error problems.
G4ThreeVectorList*
G4Cons::CreateRotatedVertices(const G4AffineTransform& pTransform) const
{
G4ThreeVectorList* vertices ;
G4ThreeVector vertex0, vertex1, vertex2, vertex3 ;
G4double meshAngle, meshRMax1, meshRMax2, crossAngle;
G4double cosCrossAngle, sinCrossAngle, sAngle ;
G4double rMaxX1, rMaxX2, rMaxY1, rMaxY2, rMinX1, rMinX2, rMinY1, rMinY2 ;
G4int crossSection, noCrossSections ;
// Compute no of cross-sections necessary to mesh cone
noCrossSections = G4int(fDPhi/kMeshAngleDefault) + 1 ;
if (noCrossSections < kMinMeshSections)
{
noCrossSections = kMinMeshSections ;
}
else if (noCrossSections > kMaxMeshSections)
{
noCrossSections = kMaxMeshSections ;
}
meshAngle = fDPhi/(noCrossSections - 1) ;
meshRMax1 = fRmax1/std::cos(meshAngle*0.5) ;
meshRMax2 = fRmax2/std::cos(meshAngle*0.5) ;
// If complete in phi, set start angle such that mesh will be at RMax
// on the x axis. Will give better extent calculations when not rotated.
if ( fPhiFullCone && (fSPhi == 0.0) )
{
sAngle = -meshAngle*0.5 ;
}
else
{
sAngle = fSPhi ;
}
vertices = new G4ThreeVectorList();
if (vertices)
{
vertices->reserve(noCrossSections*4) ;
for (crossSection = 0 ; crossSection < noCrossSections ; crossSection++)
{
// Compute coordinates of cross section at section crossSection
crossAngle = sAngle + crossSection*meshAngle ;
cosCrossAngle = std::cos(crossAngle) ;
sinCrossAngle = std::sin(crossAngle) ;
rMaxX1 = meshRMax1*cosCrossAngle ;
rMaxY1 = meshRMax1*sinCrossAngle ;
rMaxX2 = meshRMax2*cosCrossAngle ;
rMaxY2 = meshRMax2*sinCrossAngle ;
rMinX1 = fRmin1*cosCrossAngle ;
rMinY1 = fRmin1*sinCrossAngle ;
rMinX2 = fRmin2*cosCrossAngle ;
rMinY2 = fRmin2*sinCrossAngle ;
vertex0 = G4ThreeVector(rMinX1,rMinY1,-fDz) ;
vertex1 = G4ThreeVector(rMaxX1,rMaxY1,-fDz) ;
vertex2 = G4ThreeVector(rMaxX2,rMaxY2,+fDz) ;
vertex3 = G4ThreeVector(rMinX2,rMinY2,+fDz) ;
vertices->push_back(pTransform.TransformPoint(vertex0)) ;
vertices->push_back(pTransform.TransformPoint(vertex1)) ;
vertices->push_back(pTransform.TransformPoint(vertex2)) ;
vertices->push_back(pTransform.TransformPoint(vertex3)) ;
}
}
else
{
DumpInfo();
G4Exception("G4Cons::CreateRotatedVertices()",
"GeomSolids0003", FatalException,
"Error in allocation of vertices. Out of memory !");
}
return vertices ;
}
//////////////////////////////////////////////////////////////////////////
//
// GetEntityType
@@ -2308,40 +2157,40 @@ G4ThreeVector G4Cons::GetPointOnSurface() const
Afour = 0.5*fDPhi*(fRmax2*fRmax2-fRmin2*fRmin2);
Afive = fDz*(fRmax1-fRmin1+fRmax2-fRmin2);
phi = RandFlat::shoot(fSPhi,fSPhi+fDPhi);
phi = G4RandFlat::shoot(fSPhi,fSPhi+fDPhi);
cosu = std::cos(phi); sinu = std::sin(phi);
rRand1 = GetRadiusInRing(fRmin1, fRmax1);
rRand2 = GetRadiusInRing(fRmin2, fRmax2);
if ( (fSPhi == 0.) && fPhiFullCone ) { Afive = 0.; }
chose = RandFlat::shoot(0.,Aone+Atwo+Athree+Afour+2.*Afive);
chose = G4RandFlat::shoot(0.,Aone+Atwo+Athree+Afour+2.*Afive);
if( (chose >= 0.) && (chose < Aone) )
{
if(fRmin1 != fRmin2)
{
zRand = RandFlat::shoot(-1.*fDz,fDz);
zRand = G4RandFlat::shoot(-1.*fDz,fDz);
return G4ThreeVector (rtwo*cosu*(qtwo-zRand),
rtwo*sinu*(qtwo-zRand), zRand);
}
else
{
return G4ThreeVector(fRmin1*cosu, fRmin2*sinu,
RandFlat::shoot(-1.*fDz,fDz));
G4RandFlat::shoot(-1.*fDz,fDz));
}
}
else if( (chose >= Aone) && (chose <= Aone + Atwo) )
{
if(fRmax1 != fRmax2)
{
zRand = RandFlat::shoot(-1.*fDz,fDz);
zRand = G4RandFlat::shoot(-1.*fDz,fDz);
return G4ThreeVector (rone*cosu*(qone-zRand),
rone*sinu*(qone-zRand), zRand);
}
else
{
return G4ThreeVector(fRmax1*cosu, fRmax2*sinu,
RandFlat::shoot(-1.*fDz,fDz));
G4RandFlat::shoot(-1.*fDz,fDz));
}
}
else if( (chose >= Aone + Atwo) && (chose < Aone + Atwo + Athree) )
@@ -2356,17 +2205,17 @@ G4ThreeVector G4Cons::GetPointOnSurface() const
else if( (chose >= Aone + Atwo + Athree + Afour)
&& (chose < Aone + Atwo + Athree + Afour + Afive) )
{
zRand = RandFlat::shoot(-1.*fDz,fDz);
rRand1 = RandFlat::shoot(fRmin2-((zRand-fDz)/(2.*fDz))*(fRmin1-fRmin2),
fRmax2-((zRand-fDz)/(2.*fDz))*(fRmax1-fRmax2));
zRand = G4RandFlat::shoot(-1.*fDz,fDz);
rRand1 = G4RandFlat::shoot(fRmin2-((zRand-fDz)/(2.*fDz))*(fRmin1-fRmin2),
fRmax2-((zRand-fDz)/(2.*fDz))*(fRmax1-fRmax2));
return G4ThreeVector (rRand1*std::cos(fSPhi),
rRand1*std::sin(fSPhi), zRand);
}
else
{
zRand = RandFlat::shoot(-1.*fDz,fDz);
rRand1 = RandFlat::shoot(fRmin2-((zRand-fDz)/(2.*fDz))*(fRmin1-fRmin2),
fRmax2-((zRand-fDz)/(2.*fDz))*(fRmax1-fRmax2));
zRand = G4RandFlat::shoot(-1.*fDz,fDz);
rRand1 = G4RandFlat::shoot(fRmin2-((zRand-fDz)/(2.*fDz))*(fRmin1-fRmin2),
fRmax2-((zRand-fDz)/(2.*fDz))*(fRmax1-fRmax2));
return G4ThreeVector (rRand1*std::cos(fSPhi+fDPhi),
rRand1*std::sin(fSPhi+fDPhi), zRand);
}
+180 -310
View File
@@ -24,13 +24,15 @@
// ********************************************************************
//
//
// $Id: G4CutTubs.cc 93494 2015-10-23 10:05:09Z gcosmo $
// $Id: G4CutTubs.cc 101121 2016-11-07 09:18:01Z gcosmo $
//
//
// class G4CutTubs
//
// History:
//
// 30.10.16 E.Tcherniaev - reimplemented CalculateExtent(),
// added Extent, removed CreateRotatedVetices()
// 05.04.12 M.Kelsey - GetPointOnSurface() throw flat in sqrt(r)
// 01.06.11 T.Nikitina - Derived from G4Tubs
//
@@ -38,8 +40,10 @@
#include "G4CutTubs.hh"
#include "G4GeomTools.hh"
#include "G4VoxelLimits.hh"
#include "G4AffineTransform.hh"
#include "G4BoundingEnvelope.hh"
#include "G4GeometryTolerance.hh"
#include "G4VPVParameterisation.hh"
@@ -119,18 +123,21 @@ G4CutTubs::G4CutTubs( const G4String &pName,
fLowNorm = pLowNorm;
fHighNorm = pHighNorm;
// Check Intersection of Cutted planes. They MUST NOT Intersect
// Check Intersection of cut planes. They MUST NOT Intersect
//
if(IsCrossingCutPlanes())
{
std::ostringstream message;
message << "Invalid Low or High Normal to Z plane; "
<< "Crossing Cutted Planes." << G4endl
<< "Invalid Norm to Z plane (" << pLowNorm << " and "
<< pHighNorm << ") in solid: " << GetName();
G4Exception("G4CutTubs::G4CutTubs()", "GeomSolids0002",
FatalException, message);
}
// This check has been disabled as too strict.
// See problem report #1887
//
// if(IsCrossingCutPlanes())
// {
// std::ostringstream message;
// message << "Invalid Low or High Normal to Z plane; "
// << "Crossing Cutted Planes." << G4endl
// << "Invalid Norm to Z plane (" << pLowNorm << " and "
// << pHighNorm << ") in solid: " << GetName();
// G4Exception("G4CutTubs::G4CutTubs()", "GeomSolids0002",
// FatalException, message);
// }
}
///////////////////////////////////////////////////////////////////////
@@ -191,7 +198,64 @@ G4CutTubs& G4CutTubs::operator = (const G4CutTubs& rhs)
return *this;
}
////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4CutTubs::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
G4double rmin = GetInnerRadius();
G4double rmax = GetOuterRadius();
G4double dz = GetZHalfLength();
G4ThreeVector norm;
G4double xynorm, znorm;
// get zmin
norm = GetLowNorm();
xynorm = std::sqrt(norm.x()*norm.x()+norm.y()*norm.y());
znorm = std::abs(norm.z());
G4double zmin = -(dz + rmax*xynorm/znorm);
// get zmax
norm = GetHighNorm();
xynorm = std::sqrt(norm.x()*norm.x()+norm.y()*norm.y());
znorm = std::abs(norm.z());
G4double zmax = dz + rmax*xynorm/znorm;
// Find bounding box
//
if (GetDeltaPhiAngle() < twopi)
{
G4TwoVector vmin,vmax;
G4GeomTools::DiskExtent(rmin,rmax,
GetSinStartPhi(),GetCosStartPhi(),
GetSinEndPhi(),GetCosEndPhi(),
vmin,vmax);
pMin.set(vmin.x(),vmin.y(), zmin);
pMax.set(vmax.x(),vmax.y(), zmax);
}
else
{
pMin.set(-rmax,-rmax, zmin);
pMax.set( rmax, rmax, zmax);
}
// 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("G4CutTubs::Extent()", "GeomMgt0001", JustWarning, message);
DumpInfo();
}
}
//////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
@@ -201,210 +265,108 @@ G4bool G4CutTubs::CalculateExtent( const EAxis pAxis,
G4double& pMin,
G4double& pMax ) const
{
if ( (!pTransform.IsRotated()) && (fDPhi == twopi) && (fRMin == 0) )
G4ThreeVector bmin, bmax;
G4bool exist;
// Get bounding box
Extent(bmin,bmax);
// Check bounding box
G4BoundingEnvelope bbox(bmin,bmax);
#ifdef G4BBOX_EXTENT
if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
#endif
if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
{
// Special case handling for unrotated solid tubes
// Compute x/y/z mins and maxs fro bounding box respecting limits,
// with early returns if outside limits. Then switch() on pAxis,
// and compute exact x and y limit for x/y case
G4double xoffset, xMin, xMax;
G4double yoffset, yMin, yMax;
G4double zoffset, zMin, zMax;
G4double diff1, diff2, maxDiff, newMin, newMax;
G4double xoff1, xoff2, yoff1, yoff2, delta;
xoffset = pTransform.NetTranslation().x();
xMin = xoffset - fRMax;
xMax = xoffset + fRMax;
if (pVoxelLimit.IsXLimited())
{
if ( (xMin > pVoxelLimit.GetMaxXExtent())
|| (xMax < pVoxelLimit.GetMinXExtent()) )
{
return false;
}
else
{
if (xMin < pVoxelLimit.GetMinXExtent())
{
xMin = pVoxelLimit.GetMinXExtent();
}
if (xMax > pVoxelLimit.GetMaxXExtent())
{
xMax = pVoxelLimit.GetMaxXExtent();
}
}
}
yoffset = pTransform.NetTranslation().y();
yMin = yoffset - fRMax;
yMax = yoffset + fRMax;
if ( pVoxelLimit.IsYLimited() )
{
if ( (yMin > pVoxelLimit.GetMaxYExtent())
|| (yMax < pVoxelLimit.GetMinYExtent()) )
{
return false;
}
else
{
if (yMin < pVoxelLimit.GetMinYExtent())
{
yMin = pVoxelLimit.GetMinYExtent();
}
if (yMax > pVoxelLimit.GetMaxYExtent())
{
yMax=pVoxelLimit.GetMaxYExtent();
}
}
}
zoffset = pTransform.NetTranslation().z();
GetMaxMinZ(zMin,zMax);
zMin += zoffset;
zMax += zoffset;
if ( pVoxelLimit.IsZLimited() )
{
if ( (zMin > pVoxelLimit.GetMaxZExtent())
|| (zMax < pVoxelLimit.GetMinZExtent()) )
{
return false;
}
else
{
if (zMin < pVoxelLimit.GetMinZExtent())
{
zMin = pVoxelLimit.GetMinZExtent();
}
if (zMax > pVoxelLimit.GetMaxZExtent())
{
zMax = pVoxelLimit.GetMaxZExtent();
}
}
}
switch ( pAxis ) // Known to cut cylinder
{
case kXAxis :
{
yoff1 = yoffset - yMin;
yoff2 = yMax - yoffset;
if ( (yoff1 >= 0) && (yoff2 >= 0) ) // Y limits cross max/min x
{ // => no change
pMin = xMin;
pMax = xMax;
}
else
{
// Y limits don't cross max/min x => compute max delta x,
// hence new mins/maxs
delta = fRMax*fRMax - yoff1*yoff1;
diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
delta = fRMax*fRMax - yoff2*yoff2;
diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
maxDiff = (diff1 > diff2) ? diff1:diff2;
newMin = xoffset - maxDiff;
newMax = xoffset + maxDiff;
pMin = (newMin < xMin) ? xMin : newMin;
pMax = (newMax > xMax) ? xMax : newMax;
}
break;
}
case kYAxis :
{
xoff1 = xoffset - xMin;
xoff2 = xMax - xoffset;
if ( (xoff1 >= 0) && (xoff2 >= 0) ) // X limits cross max/min y
{ // => no change
pMin = yMin;
pMax = yMax;
}
else
{
// X limits don't cross max/min y => compute max delta y,
// hence new mins/maxs
delta = fRMax*fRMax - xoff1*xoff1;
diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
delta = fRMax*fRMax - xoff2*xoff2;
diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
maxDiff = (diff1 > diff2) ? diff1 : diff2;
newMin = yoffset - maxDiff;
newMax = yoffset + maxDiff;
pMin = (newMin < yMin) ? yMin : newMin;
pMax = (newMax > yMax) ? yMax : newMax;
}
break;
}
case kZAxis:
{
pMin = zMin;
pMax = zMax;
break;
}
default:
break;
}
pMin -= kCarTolerance;
pMax += kCarTolerance;
return true;
return exist = (pMin < pMax) ? true : false;
}
else // Calculate rotated vertex coordinates
// Get parameters of the solid
G4double rmin = GetInnerRadius();
G4double rmax = GetOuterRadius();
G4double dphi = GetDeltaPhiAngle();
G4double zmin = bmin.z();
G4double zmax = bmax.z();
// Find bounding envelope and calculate extent
//
const G4int NSTEPS = 24; // number of steps for whole circle
G4double astep = (360/NSTEPS)*deg; // max angle for one step
G4int ksteps = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1;
G4double ang = dphi/ksteps;
G4double sinHalf = std::sin(0.5*ang);
G4double cosHalf = std::cos(0.5*ang);
G4double sinStep = 2.*sinHalf*cosHalf;
G4double cosStep = 1. - 2.*sinHalf*sinHalf;
G4double rext = rmax/cosHalf;
// bounding envelope for full cylinder consists of two polygons,
// in other cases it is a sequence of quadrilaterals
if (rmin == 0 && dphi == twopi)
{
G4int i, noEntries, noBetweenSections4;
G4bool existsAfterClip = false;
G4ThreeVectorList* vertices = CreateRotatedVertices(pTransform);
G4double sinCur = sinHalf;
G4double cosCur = cosHalf;
pMin = kInfinity;
pMax = -kInfinity;
G4ThreeVectorList baseA(NSTEPS),baseB(NSTEPS);
for (G4int k=0; k<NSTEPS; ++k)
{
baseA[k].set(rext*cosCur,rext*sinCur,zmin);
baseB[k].set(rext*cosCur,rext*sinCur,zmax);
noEntries = vertices->size();
noBetweenSections4 = noEntries - 4;
for ( i = 0 ; i < noEntries ; i += 4 )
{
ClipCrossSection(vertices, i, pVoxelLimit, pAxis, pMin, pMax);
G4double sinTmp = sinCur;
sinCur = sinCur*cosStep + cosCur*sinStep;
cosCur = cosCur*cosStep - sinTmp*sinStep;
}
for ( i = 0 ; i < noBetweenSections4 ; i += 4 )
{
ClipBetweenSections(vertices, i, pVoxelLimit, pAxis, pMin, pMax);
}
if ( (pMin != kInfinity) || (pMax != -kInfinity) )
{
existsAfterClip = true;
pMin -= kCarTolerance; // Add 2*tolerance to avoid precision troubles
pMax += kCarTolerance;
}
else
{
// Check for case where completely enveloping clipping volume
// If point inside then we are confident that the solid completely
// envelopes the clipping volume. Hence set min/max extents according
// to clipping volume extents along the specified axis.
G4ThreeVector clipCentre(
(pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
(pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
(pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5 );
if ( Inside(pTransform.Inverse().TransformPoint(clipCentre)) != kOutside )
{
existsAfterClip = true;
pMin = pVoxelLimit.GetMinExtent(pAxis);
pMax = pVoxelLimit.GetMaxExtent(pAxis);
}
}
delete vertices;
return existsAfterClip;
std::vector<const G4ThreeVectorList *> polygons(2);
polygons[0] = &baseA;
polygons[1] = &baseB;
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
}
else
{
G4double sinStart = GetSinStartPhi();
G4double cosStart = GetCosStartPhi();
G4double sinEnd = GetSinEndPhi();
G4double cosEnd = GetCosEndPhi();
G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
// set quadrilaterals
G4ThreeVectorList pols[NSTEPS+2];
for (G4int k=0; k<ksteps+2; ++k) pols[k].resize(4);
pols[0][0].set(rmin*cosStart,rmin*sinStart,zmax);
pols[0][1].set(rmin*cosStart,rmin*sinStart,zmin);
pols[0][2].set(rmax*cosStart,rmax*sinStart,zmin);
pols[0][3].set(rmax*cosStart,rmax*sinStart,zmax);
for (G4int k=1; k<ksteps+1; ++k)
{
pols[k][0].set(rmin*cosCur,rmin*sinCur,zmax);
pols[k][1].set(rmin*cosCur,rmin*sinCur,zmin);
pols[k][2].set(rext*cosCur,rext*sinCur,zmin);
pols[k][3].set(rext*cosCur,rext*sinCur,zmax);
G4double sinTmp = sinCur;
sinCur = sinCur*cosStep + cosCur*sinStep;
cosCur = cosCur*cosStep - sinTmp*sinStep;
}
pols[ksteps+1][0].set(rmin*cosEnd,rmin*sinEnd,zmax);
pols[ksteps+1][1].set(rmin*cosEnd,rmin*sinEnd,zmin);
pols[ksteps+1][2].set(rmax*cosEnd,rmax*sinEnd,zmin);
pols[ksteps+1][3].set(rmax*cosEnd,rmax*sinEnd,zmax);
// set envelope and calculate extent
std::vector<const G4ThreeVectorList *> polygons;
polygons.resize(ksteps+2);
for (G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k];
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
}
return exist;
}
///////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Return whether point inside/outside/on surface
@@ -1747,98 +1709,6 @@ G4double G4CutTubs::DistanceToOut( const G4ThreeVector& p ) const
return safe ;
}
/////////////////////////////////////////////////////////////////////////
//
// Create a List containing the transformed vertices
// Ordering [0-3] -fDz cross section
// [4-7] +fDz cross section such that [0] is below [4],
// [1] below [5] etc.
// Note:
// Caller has deletion resposibility
G4ThreeVectorList*
G4CutTubs::CreateRotatedVertices( const G4AffineTransform& pTransform ) const
{
G4ThreeVectorList* vertices ;
G4ThreeVector vertex0, vertex1, vertex2, vertex3 ;
G4double meshAngle, meshRMax, crossAngle,
cosCrossAngle, sinCrossAngle, sAngle;
G4double rMaxX, rMaxY, rMinX, rMinY, meshRMin ;
G4int crossSection, noCrossSections;
// Compute no of cross-sections necessary to mesh tube
//
noCrossSections = G4int(fDPhi/kMeshAngleDefault) + 1 ;
if ( noCrossSections < kMinMeshSections )
{
noCrossSections = kMinMeshSections ;
}
else if (noCrossSections>kMaxMeshSections)
{
noCrossSections = kMaxMeshSections ;
}
// noCrossSections = 4 ;
meshAngle = fDPhi/(noCrossSections - 1) ;
// meshAngle = fDPhi/(noCrossSections) ;
meshRMax = (fRMax+100*kCarTolerance)/std::cos(meshAngle*0.5) ;
meshRMin = fRMin - 100*kCarTolerance ;
// If complete in phi, set start angle such that mesh will be at fRMax
// on the x axis. Will give better extent calculations when not rotated.
if (fPhiFullCutTube && (fSPhi == 0) ) { sAngle = -meshAngle*0.5 ; }
else { sAngle = fSPhi ; }
vertices = new G4ThreeVectorList();
if ( vertices )
{
vertices->reserve(noCrossSections*4);
for (crossSection = 0 ; crossSection < noCrossSections ; crossSection++ )
{
// Compute coordinates of cross section at section crossSection
crossAngle = sAngle + crossSection*meshAngle ;
cosCrossAngle = std::cos(crossAngle) ;
sinCrossAngle = std::sin(crossAngle) ;
rMaxX = meshRMax*cosCrossAngle ;
rMaxY = meshRMax*sinCrossAngle ;
if(meshRMin <= 0.0)
{
rMinX = 0.0 ;
rMinY = 0.0 ;
}
else
{
rMinX = meshRMin*cosCrossAngle ;
rMinY = meshRMin*sinCrossAngle ;
}
vertex0 = G4ThreeVector(rMinX,rMinY,GetCutZ(G4ThreeVector(rMinX,rMinY,-fDz))) ;
vertex1 = G4ThreeVector(rMaxX,rMaxY,GetCutZ(G4ThreeVector(rMaxX,rMaxY,-fDz))) ;
vertex2 = G4ThreeVector(rMaxX,rMaxY,GetCutZ(G4ThreeVector(rMaxX,rMaxY,+fDz))) ;
vertex3 = G4ThreeVector(rMinX,rMinY,GetCutZ(G4ThreeVector(rMinX,rMinY,+fDz))) ;
vertices->push_back(pTransform.TransformPoint(vertex0)) ;
vertices->push_back(pTransform.TransformPoint(vertex1)) ;
vertices->push_back(pTransform.TransformPoint(vertex2)) ;
vertices->push_back(pTransform.TransformPoint(vertex3)) ;
}
}
else
{
DumpInfo();
G4Exception("G4CutTubs::CreateRotatedVertices()",
"GeomSolids0003", FatalException,
"Error in allocation of vertices. Out of memory !");
}
return vertices ;
}
//////////////////////////////////////////////////////////////////////////
//
// Stream object contents to an output stream
@@ -1897,7 +1767,7 @@ G4ThreeVector G4CutTubs::GetPointOnSurface() const
aThr = 0.5*fDPhi*(fRMax*fRMax-fRMin*fRMin);
aFou = 2.*fDz*(fRMax-fRMin);
phi = RandFlat::shoot(fSPhi, fSPhi+fDPhi);
phi = G4RandFlat::shoot(fSPhi, fSPhi+fDPhi);
cosphi = std::cos(phi);
sinphi = std::sin(phi);
@@ -1905,22 +1775,22 @@ G4ThreeVector G4CutTubs::GetPointOnSurface() const
if( (fSPhi == 0) && (fDPhi == twopi) ) { aFou = 0; }
chose = RandFlat::shoot(0.,aOne+aTwo+2.*aThr+2.*aFou);
chose = G4RandFlat::shoot(0.,aOne+aTwo+2.*aThr+2.*aFou);
if( (chose >=0) && (chose < aOne) )
{
xRand = fRMax*cosphi;
yRand = fRMax*sinphi;
zRand = RandFlat::shoot(GetCutZ(G4ThreeVector(xRand,yRand,-fDz)),
GetCutZ(G4ThreeVector(xRand,yRand,fDz)));
zRand = G4RandFlat::shoot(GetCutZ(G4ThreeVector(xRand,yRand,-fDz)),
GetCutZ(G4ThreeVector(xRand,yRand,fDz)));
return G4ThreeVector (xRand, yRand, zRand);
}
else if( (chose >= aOne) && (chose < aOne + aTwo) )
{
xRand = fRMin*cosphi;
yRand = fRMin*sinphi;
zRand = RandFlat::shoot(GetCutZ(G4ThreeVector(xRand,yRand,-fDz)),
GetCutZ(G4ThreeVector(xRand,yRand,fDz)));
zRand = G4RandFlat::shoot(GetCutZ(G4ThreeVector(xRand,yRand,-fDz)),
GetCutZ(G4ThreeVector(xRand,yRand,fDz)));
return G4ThreeVector (xRand, yRand, zRand);
}
else if( (chose >= aOne + aTwo) && (chose < aOne + aTwo + aThr) )
@@ -1942,16 +1812,16 @@ G4ThreeVector G4CutTubs::GetPointOnSurface() const
{
xRand = rRand*std::cos(fSPhi);
yRand = rRand*std::sin(fSPhi);
zRand = RandFlat::shoot(GetCutZ(G4ThreeVector(xRand,yRand,-fDz)),
GetCutZ(G4ThreeVector(xRand,yRand,fDz)));
zRand = G4RandFlat::shoot(GetCutZ(G4ThreeVector(xRand,yRand,-fDz)),
GetCutZ(G4ThreeVector(xRand,yRand,fDz)));
return G4ThreeVector (xRand, yRand, zRand);
}
else
{
xRand = rRand*std::cos(fSPhi+fDPhi);
yRand = rRand*std::sin(fSPhi+fDPhi);
zRand = RandFlat::shoot(GetCutZ(G4ThreeVector(xRand,yRand,-fDz)),
GetCutZ(G4ThreeVector(xRand,yRand,fDz)));
zRand = G4RandFlat::shoot(GetCutZ(G4ThreeVector(xRand,yRand,-fDz)),
GetCutZ(G4ThreeVector(xRand,yRand,fDz)));
return G4ThreeVector (xRand, yRand, zRand);
}
}
+144 -296
View File
@@ -35,9 +35,11 @@
#include "G4OTubs.hh"
#include "G4GeomTools.hh"
#include "G4VoxelLimits.hh"
#include "G4AffineTransform.hh"
#include "G4GeometryTolerance.hh"
#include "G4BoundingEnvelope.hh"
#include "G4VPVParameterisation.hh"
@@ -162,6 +164,48 @@ G4OTubs& G4OTubs::operator = (const G4OTubs& rhs)
return *this;
}
/////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4OTubs::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
G4double rmin = GetInnerRadius();
G4double rmax = GetOuterRadius();
G4double dz = GetZHalfLength();
// Find bounding box
//
if (GetDeltaPhiAngle() < twopi)
{
G4TwoVector vmin,vmax;
G4GeomTools::DiskExtent(rmin,rmax,
GetSinStartPhi(),GetCosStartPhi(),
GetSinEndPhi(),GetCosEndPhi(),
vmin,vmax);
pMin.set(vmin.x(),vmin.y(),-dz);
pMax.set(vmax.x(),vmax.y(), dz);
}
else
{
pMin.set(-rmax,-rmax,-dz);
pMax.set( rmax, rmax, dz);
}
// 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("G4OTubs::Extent()", "GeomMgt0001", JustWarning, message);
DumpInfo();
}
}
////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
@@ -172,210 +216,106 @@ G4bool G4OTubs::CalculateExtent( const EAxis pAxis,
G4double& pMin,
G4double& pMax ) const
{
G4ThreeVector bmin, bmax;
G4bool exist;
if ( (!pTransform.IsRotated()) && (fDPhi == twopi) && (fRMin == 0) )
// Get bounding box
Extent(bmin,bmax);
// Check bounding box
G4BoundingEnvelope bbox(bmin,bmax);
#ifdef G4BBOX_EXTENT
if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
#endif
if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
{
// Special case handling for unrotated solid tubes
// Compute x/y/z mins and maxs fro bounding box respecting limits,
// with early returns if outside limits. Then switch() on pAxis,
// and compute exact x and y limit for x/y case
G4double xoffset, xMin, xMax;
G4double yoffset, yMin, yMax;
G4double zoffset, zMin, zMax;
G4double diff1, diff2, maxDiff, newMin, newMax;
G4double xoff1, xoff2, yoff1, yoff2, delta;
xoffset = pTransform.NetTranslation().x();
xMin = xoffset - fRMax;
xMax = xoffset + fRMax;
if (pVoxelLimit.IsXLimited())
{
if ( (xMin > pVoxelLimit.GetMaxXExtent())
|| (xMax < pVoxelLimit.GetMinXExtent()) )
{
return false;
}
else
{
if (xMin < pVoxelLimit.GetMinXExtent())
{
xMin = pVoxelLimit.GetMinXExtent();
}
if (xMax > pVoxelLimit.GetMaxXExtent())
{
xMax = pVoxelLimit.GetMaxXExtent();
}
}
}
yoffset = pTransform.NetTranslation().y();
yMin = yoffset - fRMax;
yMax = yoffset + fRMax;
if ( pVoxelLimit.IsYLimited() )
{
if ( (yMin > pVoxelLimit.GetMaxYExtent())
|| (yMax < pVoxelLimit.GetMinYExtent()) )
{
return false;
}
else
{
if (yMin < pVoxelLimit.GetMinYExtent())
{
yMin = pVoxelLimit.GetMinYExtent();
}
if (yMax > pVoxelLimit.GetMaxYExtent())
{
yMax=pVoxelLimit.GetMaxYExtent();
}
}
}
zoffset = pTransform.NetTranslation().z();
zMin = zoffset - fDz;
zMax = zoffset + fDz;
if ( pVoxelLimit.IsZLimited() )
{
if ( (zMin > pVoxelLimit.GetMaxZExtent())
|| (zMax < pVoxelLimit.GetMinZExtent()) )
{
return false;
}
else
{
if (zMin < pVoxelLimit.GetMinZExtent())
{
zMin = pVoxelLimit.GetMinZExtent();
}
if (zMax > pVoxelLimit.GetMaxZExtent())
{
zMax = pVoxelLimit.GetMaxZExtent();
}
}
}
switch ( pAxis ) // Known to cut cylinder
{
case kXAxis :
{
yoff1 = yoffset - yMin;
yoff2 = yMax - yoffset;
if ( (yoff1 >= 0) && (yoff2 >= 0) ) // Y limits cross max/min x
{ // => no change
pMin = xMin;
pMax = xMax;
}
else
{
// Y limits don't cross max/min x => compute max delta x,
// hence new mins/maxs
delta = fRMax*fRMax - yoff1*yoff1;
diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
delta = fRMax*fRMax - yoff2*yoff2;
diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
maxDiff = (diff1 > diff2) ? diff1:diff2;
newMin = xoffset - maxDiff;
newMax = xoffset + maxDiff;
pMin = (newMin < xMin) ? xMin : newMin;
pMax = (newMax > xMax) ? xMax : newMax;
}
break;
}
case kYAxis :
{
xoff1 = xoffset - xMin;
xoff2 = xMax - xoffset;
if ( (xoff1 >= 0) && (xoff2 >= 0) ) // X limits cross max/min y
{ // => no change
pMin = yMin;
pMax = yMax;
}
else
{
// X limits don't cross max/min y => compute max delta y,
// hence new mins/maxs
delta = fRMax*fRMax - xoff1*xoff1;
diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
delta = fRMax*fRMax - xoff2*xoff2;
diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
maxDiff = (diff1 > diff2) ? diff1 : diff2;
newMin = yoffset - maxDiff;
newMax = yoffset + maxDiff;
pMin = (newMin < yMin) ? yMin : newMin;
pMax = (newMax > yMax) ? yMax : newMax;
}
break;
}
case kZAxis:
{
pMin = zMin;
pMax = zMax;
break;
}
default:
break;
}
pMin -= kCarTolerance;
pMax += kCarTolerance;
return true;
return exist = (pMin < pMax) ? true : false;
}
else // Calculate rotated vertex coordinates
// Get parameters of the solid
G4double rmin = GetInnerRadius();
G4double rmax = GetOuterRadius();
G4double dz = GetZHalfLength();
G4double dphi = GetDeltaPhiAngle();
// Find bounding envelope and calculate extent
//
const G4int NSTEPS = 24; // number of steps for whole circle
G4double astep = (360/NSTEPS)*deg; // max angle for one step
G4int ksteps = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1;
G4double ang = dphi/ksteps;
G4double sinHalf = std::sin(0.5*ang);
G4double cosHalf = std::cos(0.5*ang);
G4double sinStep = 2.*sinHalf*cosHalf;
G4double cosStep = 1. - 2.*sinHalf*sinHalf;
G4double rext = rmax/cosHalf;
// bounding envelope for full cylinder consists of two polygons,
// in other cases it is a sequence of quadrilaterals
if (rmin == 0 && dphi == twopi)
{
G4int i, noEntries, noBetweenSections4;
G4bool existsAfterClip = false;
G4ThreeVectorList* vertices = CreateRotatedVertices(pTransform);
G4double sinCur = sinHalf;
G4double cosCur = cosHalf;
pMin = kInfinity;
pMax = -kInfinity;
G4ThreeVectorList baseA(NSTEPS),baseB(NSTEPS);
for (G4int k=0; k<NSTEPS; ++k)
{
baseA[k].set(rext*cosCur,rext*sinCur,-dz);
baseB[k].set(rext*cosCur,rext*sinCur, dz);
noEntries = vertices->size();
noBetweenSections4 = noEntries - 4;
for ( i = 0 ; i < noEntries ; i += 4 )
{
ClipCrossSection(vertices, i, pVoxelLimit, pAxis, pMin, pMax);
G4double sinTmp = sinCur;
sinCur = sinCur*cosStep + cosCur*sinStep;
cosCur = cosCur*cosStep - sinTmp*sinStep;
}
for ( i = 0 ; i < noBetweenSections4 ; i += 4 )
{
ClipBetweenSections(vertices, i, pVoxelLimit, pAxis, pMin, pMax);
}
if ( (pMin != kInfinity) || (pMax != -kInfinity) )
{
existsAfterClip = true;
pMin -= kCarTolerance; // Add 2*tolerance to avoid precision troubles
pMax += kCarTolerance;
}
else
{
// Check for case where completely enveloping clipping volume
// If point inside then we are confident that the solid completely
// envelopes the clipping volume. Hence set min/max extents according
// to clipping volume extents along the specified axis.
G4ThreeVector clipCentre(
(pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
(pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
(pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5 );
if ( Inside(pTransform.Inverse().TransformPoint(clipCentre)) != kOutside )
{
existsAfterClip = true;
pMin = pVoxelLimit.GetMinExtent(pAxis);
pMax = pVoxelLimit.GetMaxExtent(pAxis);
}
}
delete vertices;
return existsAfterClip;
std::vector<const G4ThreeVectorList *> polygons(2);
polygons[0] = &baseA;
polygons[1] = &baseB;
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
}
else
{
G4double sinStart = GetSinStartPhi();
G4double cosStart = GetCosStartPhi();
G4double sinEnd = GetSinEndPhi();
G4double cosEnd = GetCosEndPhi();
G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
// set quadrilaterals
G4ThreeVectorList pols[NSTEPS+2];
for (G4int k=0; k<ksteps+2; ++k) pols[k].resize(4);
pols[0][0].set(rmin*cosStart,rmin*sinStart, dz);
pols[0][1].set(rmin*cosStart,rmin*sinStart,-dz);
pols[0][2].set(rmax*cosStart,rmax*sinStart,-dz);
pols[0][3].set(rmax*cosStart,rmax*sinStart, dz);
for (G4int k=1; k<ksteps+1; ++k)
{
pols[k][0].set(rmin*cosCur,rmin*sinCur, dz);
pols[k][1].set(rmin*cosCur,rmin*sinCur,-dz);
pols[k][2].set(rext*cosCur,rext*sinCur,-dz);
pols[k][3].set(rext*cosCur,rext*sinCur, dz);
G4double sinTmp = sinCur;
sinCur = sinCur*cosStep + cosCur*sinStep;
cosCur = cosCur*cosStep - sinTmp*sinStep;
}
pols[ksteps+1][0].set(rmin*cosEnd,rmin*sinEnd, dz);
pols[ksteps+1][1].set(rmin*cosEnd,rmin*sinEnd,-dz);
pols[ksteps+1][2].set(rmax*cosEnd,rmax*sinEnd,-dz);
pols[ksteps+1][3].set(rmax*cosEnd,rmax*sinEnd, dz);
// set envelope and calculate extent
std::vector<const G4ThreeVectorList *> polygons;
polygons.resize(ksteps+2);
for (G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k];
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
}
return exist;
}
///////////////////////////////////////////////////////////////////////////
//
// Return whether point inside/outside/on surface
@@ -1422,7 +1362,8 @@ G4double G4OTubs::DistanceToOut( const G4ThreeVector& p,
// Check intersecting with correct half-plane
// (if not -> no intersect)
//
if( (std::fabs(xi)<=kCarTolerance)&&(std::fabs(yi)<=kCarTolerance) )
if( (std::fabs(xi)<=kCarTolerance)
&& (std::fabs(yi)<=kCarTolerance) )
{
sidephi = kSPhi;
if (((fSPhi-halfAngTolerance)<=vphi)
@@ -1465,7 +1406,8 @@ G4double G4OTubs::DistanceToOut( const G4ThreeVector& p,
xi = p.x() + sphi2*v.x() ;
yi = p.y() + sphi2*v.y() ;
if ((std::fabs(xi)<=kCarTolerance)&&(std::fabs(yi)<=kCarTolerance))
if ( (std::fabs(xi)<=kCarTolerance)
&& (std::fabs(yi)<=kCarTolerance))
{
// Leaving via ending phi
//
@@ -1663,100 +1605,6 @@ G4double G4OTubs::DistanceToOut( const G4ThreeVector& p ) const
return safe ;
}
/////////////////////////////////////////////////////////////////////////
//
// Create a List containing the transformed vertices
// Ordering [0-3] -fDz cross section
// [4-7] +fDz cross section such that [0] is below [4],
// [1] below [5] etc.
// Note:
// Caller has deletion resposibility
// Potential improvement: For last slice, use actual ending angle
// to avoid rounding error problems.
G4ThreeVectorList*
G4OTubs::CreateRotatedVertices( const G4AffineTransform& pTransform ) const
{
G4ThreeVectorList* vertices ;
G4ThreeVector vertex0, vertex1, vertex2, vertex3 ;
G4double meshAngle, meshRMax, crossAngle,
cosCrossAngle, sinCrossAngle, sAngle;
G4double rMaxX, rMaxY, rMinX, rMinY, meshRMin ;
G4int crossSection, noCrossSections;
// Compute no of cross-sections necessary to mesh tube
//
noCrossSections = G4int(fDPhi/kMeshAngleDefault) + 1 ;
if ( noCrossSections < kMinMeshSections )
{
noCrossSections = kMinMeshSections ;
}
else if (noCrossSections>kMaxMeshSections)
{
noCrossSections = kMaxMeshSections ;
}
// noCrossSections = 4 ;
meshAngle = fDPhi/(noCrossSections - 1) ;
// meshAngle = fDPhi/(noCrossSections) ;
meshRMax = (fRMax+100*kCarTolerance)/std::cos(meshAngle*0.5) ;
meshRMin = fRMin - 100*kCarTolerance ;
// If complete in phi, set start angle such that mesh will be at fRMax
// on the x axis. Will give better extent calculations when not rotated.
if (fPhiFullTube && (fSPhi == 0) ) { sAngle = -meshAngle*0.5 ; }
else { sAngle = fSPhi ; }
vertices = new G4ThreeVectorList();
if ( vertices )
{
vertices->reserve(noCrossSections*4);
for (crossSection = 0 ; crossSection < noCrossSections ; crossSection++ )
{
// Compute coordinates of cross section at section crossSection
crossAngle = sAngle + crossSection*meshAngle ;
cosCrossAngle = std::cos(crossAngle) ;
sinCrossAngle = std::sin(crossAngle) ;
rMaxX = meshRMax*cosCrossAngle ;
rMaxY = meshRMax*sinCrossAngle ;
if(meshRMin <= 0.0)
{
rMinX = 0.0 ;
rMinY = 0.0 ;
}
else
{
rMinX = meshRMin*cosCrossAngle ;
rMinY = meshRMin*sinCrossAngle ;
}
vertex0 = G4ThreeVector(rMinX,rMinY,-fDz) ;
vertex1 = G4ThreeVector(rMaxX,rMaxY,-fDz) ;
vertex2 = G4ThreeVector(rMaxX,rMaxY,+fDz) ;
vertex3 = G4ThreeVector(rMinX,rMinY,+fDz) ;
vertices->push_back(pTransform.TransformPoint(vertex0)) ;
vertices->push_back(pTransform.TransformPoint(vertex1)) ;
vertices->push_back(pTransform.TransformPoint(vertex2)) ;
vertices->push_back(pTransform.TransformPoint(vertex3)) ;
}
}
else
{
DumpInfo();
G4Exception("G4Tubs::CreateRotatedVertices()",
"GeomSolids0003", FatalException,
"Error in allocation of vertices. Out of memory !");
}
return vertices ;
}
//////////////////////////////////////////////////////////////////////////
//
// Stream object contents to an output stream
@@ -1813,7 +1661,7 @@ G4ThreeVector G4OTubs::GetPointOnSurface() const
aThr = 0.5*fDPhi*(fRMax*fRMax-fRMin*fRMin);
aFou = 2.*fDz*(fRMax-fRMin);
phi = RandFlat::shoot(fSPhi, fSPhi+fDPhi);
phi = G4RandFlat::shoot(fSPhi, fSPhi+fDPhi);
cosphi = std::cos(phi);
sinphi = std::sin(phi);
@@ -1821,20 +1669,20 @@ G4ThreeVector G4OTubs::GetPointOnSurface() const
if( (fSPhi == 0) && (fDPhi == twopi) ) { aFou = 0; }
chose = RandFlat::shoot(0.,aOne+aTwo+2.*aThr+2.*aFou);
chose = G4RandFlat::shoot(0.,aOne+aTwo+2.*aThr+2.*aFou);
if( (chose >=0) && (chose < aOne) )
{
xRand = fRMax*cosphi;
yRand = fRMax*sinphi;
zRand = RandFlat::shoot(-1.*fDz,fDz);
zRand = G4RandFlat::shoot(-1.*fDz,fDz);
return G4ThreeVector (xRand, yRand, zRand);
}
else if( (chose >= aOne) && (chose < aOne + aTwo) )
{
xRand = fRMin*cosphi;
yRand = fRMin*sinphi;
zRand = RandFlat::shoot(-1.*fDz,fDz);
zRand = G4RandFlat::shoot(-1.*fDz,fDz);
return G4ThreeVector (xRand, yRand, zRand);
}
else if( (chose >= aOne + aTwo) && (chose < aOne + aTwo + aThr) )
@@ -1856,14 +1704,14 @@ G4ThreeVector G4OTubs::GetPointOnSurface() const
{
xRand = rRand*std::cos(fSPhi);
yRand = rRand*std::sin(fSPhi);
zRand = RandFlat::shoot(-1.*fDz,fDz);
zRand = G4RandFlat::shoot(-1.*fDz,fDz);
return G4ThreeVector (xRand, yRand, zRand);
}
else
{
xRand = rRand*std::cos(fSPhi+fDPhi);
yRand = rRand*std::sin(fSPhi+fDPhi);
zRand = RandFlat::shoot(-1.*fDz,fDz);
zRand = G4RandFlat::shoot(-1.*fDz,fDz);
return G4ThreeVector (xRand, yRand, zRand);
}
}
+101 -152
View File
@@ -23,7 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4Orb.cc 96318 2016-04-06 07:26:42Z gcosmo $
// $Id: G4Orb.cc 101121 2016-11-07 09:18:01Z gcosmo $
//
// class G4Orb
//
@@ -31,6 +31,7 @@
//
// History:
//
// 27.10.16 E.Tcherniaev - added Extent(), reimplemented CalculateExtent()
// 05.04.12 M.Kelsey - GetPointOnSurface() throw flat in cos(theta)
// 30.06.04 V.Grichine - bug fixed in DistanceToIn(p,v) on Rmax surface
// 20.08.03 V.Grichine - created
@@ -41,9 +42,11 @@
#if !defined(G4GEOM_USE_UORB)
#include "G4TwoVector.hh"
#include "G4VoxelLimits.hh"
#include "G4AffineTransform.hh"
#include "G4GeometryTolerance.hh"
#include "G4BoundingEnvelope.hh"
#include "G4VPVParameterisation.hh"
@@ -150,165 +153,111 @@ void G4Orb::ComputeDimensions( G4VPVParameterisation* p,
p->ComputeDimensions(*this,n,pRep);
}
////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4Orb::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
G4double radius = GetRadius();
pMin.set(-radius,-radius,-radius);
pMax.set( radius, radius, radius);
// 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("G4Orb::Extent()", "GeomMgt0001", JustWarning, message);
DumpInfo();
}
}
//////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
G4bool G4Orb::CalculateExtent( const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax ) const
G4bool G4Orb::CalculateExtent(const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax) const
{
// Compute x/y/z mins and maxs for bounding box respecting limits,
// with early returns if outside limits. Then switch() on pAxis,
// and compute exact x and y limit for x/y case
G4double xoffset,xMin,xMax;
G4double yoffset,yMin,yMax;
G4double zoffset,zMin,zMax;
G4ThreeVector bmin, bmax;
G4bool exist;
G4double diff1,diff2,delta,maxDiff,newMin,newMax;
G4double xoff1,xoff2,yoff1,yoff2;
// Get bounding box
Extent(bmin,bmax);
xoffset=pTransform.NetTranslation().x();
xMin=xoffset-fRmax;
xMax=xoffset+fRmax;
// Check bounding box
G4BoundingEnvelope bbox(bmin,bmax);
#ifdef G4BBOX_EXTENT
if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
#endif
if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
{
return exist = (pMin < pMax) ? true : false;
}
if (pVoxelLimit.IsXLimited())
{
if ( (xMin>pVoxelLimit.GetMaxXExtent()+kCarTolerance)
|| (xMax<pVoxelLimit.GetMinXExtent()-kCarTolerance) )
{
return false;
}
else
{
if (xMin<pVoxelLimit.GetMinXExtent())
{
xMin=pVoxelLimit.GetMinXExtent();
}
if (xMax>pVoxelLimit.GetMaxXExtent())
{
xMax=pVoxelLimit.GetMaxXExtent();
}
}
}
yoffset=pTransform.NetTranslation().y();
yMin=yoffset-fRmax;
yMax=yoffset+fRmax;
// Find bounding envelope and calculate extent
//
static const G4int NTHETA = 8; // number of steps along Theta
static const G4int NPHI = 16; // number of steps along Phi
static const G4double sinHalfTheta = std::sin(halfpi/NTHETA);
static const G4double cosHalfTheta = std::cos(halfpi/NTHETA);
static const G4double sinHalfPhi = std::sin(pi/NPHI);
static const G4double cosHalfPhi = std::cos(pi/NPHI);
static const G4double sinStepTheta = 2.*sinHalfTheta*cosHalfTheta;
static const G4double cosStepTheta = 1. - 2.*sinHalfTheta*sinHalfTheta;
static const G4double sinStepPhi = 2.*sinHalfPhi*cosHalfPhi;
static const G4double cosStepPhi = 1. - 2.*sinHalfPhi*sinHalfPhi;
if (pVoxelLimit.IsYLimited())
{
if ( (yMin>pVoxelLimit.GetMaxYExtent()+kCarTolerance)
|| (yMax<pVoxelLimit.GetMinYExtent()-kCarTolerance) )
{
return false;
}
else
{
if (yMin<pVoxelLimit.GetMinYExtent())
{
yMin=pVoxelLimit.GetMinYExtent();
}
if (yMax>pVoxelLimit.GetMaxYExtent())
{
yMax=pVoxelLimit.GetMaxYExtent();
}
}
}
zoffset=pTransform.NetTranslation().z();
zMin=zoffset-fRmax;
zMax=zoffset+fRmax;
G4double radius = GetRadius();
G4double rtheta = radius/cosHalfTheta;
G4double rphi = rtheta/cosHalfPhi;
if (pVoxelLimit.IsZLimited())
{
if ( (zMin>pVoxelLimit.GetMaxZExtent()+kCarTolerance)
|| (zMax<pVoxelLimit.GetMinZExtent()-kCarTolerance) )
{
return false;
}
else
{
if (zMin<pVoxelLimit.GetMinZExtent())
{
zMin=pVoxelLimit.GetMinZExtent();
}
if (zMax>pVoxelLimit.GetMaxZExtent())
{
zMax=pVoxelLimit.GetMaxZExtent();
}
}
}
// Known to cut sphere
switch (pAxis)
{
case kXAxis:
yoff1=yoffset-yMin;
yoff2=yMax-yoffset;
if ( yoff1 >= 0 && yoff2 >= 0 )
{
// Y limits cross max/min x => no change
//
pMin=xMin;
pMax=xMax;
}
else
{
// Y limits don't cross max/min x => compute max delta x,
// hence new mins/maxs
//
delta=fRmax*fRmax-yoff1*yoff1;
diff1=(delta>0.) ? std::sqrt(delta) : 0.;
delta=fRmax*fRmax-yoff2*yoff2;
diff2=(delta>0.) ? std::sqrt(delta) : 0.;
maxDiff=(diff1>diff2) ? diff1:diff2;
newMin=xoffset-maxDiff;
newMax=xoffset+maxDiff;
pMin=(newMin<xMin) ? xMin : newMin;
pMax=(newMax>xMax) ? xMax : newMax;
}
break;
case kYAxis:
xoff1=xoffset-xMin;
xoff2=xMax-xoffset;
if (xoff1>=0&&xoff2>=0)
{
// X limits cross max/min y => no change
//
pMin=yMin;
pMax=yMax;
}
else
{
// X limits don't cross max/min y => compute max delta y,
// hence new mins/maxs
//
delta=fRmax*fRmax-xoff1*xoff1;
diff1=(delta>0.) ? std::sqrt(delta) : 0.;
delta=fRmax*fRmax-xoff2*xoff2;
diff2=(delta>0.) ? std::sqrt(delta) : 0.;
maxDiff=(diff1>diff2) ? diff1:diff2;
newMin=yoffset-maxDiff;
newMax=yoffset+maxDiff;
pMin=(newMin<yMin) ? yMin : newMin;
pMax=(newMax>yMax) ? yMax : newMax;
}
break;
case kZAxis:
pMin=zMin;
pMax=zMax;
break;
default:
break;
}
pMin -= fRmaxTolerance;
pMax += fRmaxTolerance;
return true;
// set reference circle
G4TwoVector xy[NPHI];
G4double sinCurPhi = sinHalfPhi;
G4double cosCurPhi = cosHalfPhi;
for (G4int k=0; k<NPHI; ++k)
{
xy[k].set(cosCurPhi,sinCurPhi);
G4double sinTmpPhi = sinCurPhi;
sinCurPhi = sinCurPhi*cosStepPhi + cosCurPhi*sinStepPhi;
cosCurPhi = cosCurPhi*cosStepPhi - sinTmpPhi*sinStepPhi;
}
// set bounding circles
G4ThreeVectorList circles[NTHETA];
for (G4int i=0; i<NTHETA; ++i) circles[i].resize(NPHI);
G4double sinCurTheta = sinHalfTheta;
G4double cosCurTheta = cosHalfTheta;
for (G4int i=0; i<NTHETA; ++i)
{
G4double z = rtheta*cosCurTheta;
G4double rho = rphi*sinCurTheta;
for (G4int k=0; k<NPHI; ++k)
{
circles[i][k].set(rho*xy[k].x(),rho*xy[k].y(),z);
}
G4double sinTmpTheta = sinCurTheta;
sinCurTheta = sinCurTheta*cosStepTheta + cosCurTheta*sinStepTheta;
cosCurTheta = cosCurTheta*cosStepTheta - sinTmpTheta*sinStepTheta;
}
// set envelope and calculate extent
std::vector<const G4ThreeVectorList *> polygons;
polygons.resize(NTHETA);
for (G4int i=0; i<NTHETA; ++i) polygons[i] = &circles[i];
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
return exist;
}
///////////////////////////////////////////////////////////////////////////
@@ -694,12 +643,12 @@ G4ThreeVector G4Orb::GetPointOnSurface() const
{
// generate a random number from zero to 2pi...
//
G4double phi = RandFlat::shoot(0.,2.*pi);
G4double phi = G4RandFlat::shoot(0.,2.*pi);
G4double cosphi = std::cos(phi);
G4double sinphi = std::sin(phi);
// generate a random point uniform in area
G4double costheta = RandFlat::shoot(-1.,1.);
G4double costheta = G4RandFlat::shoot(-1.,1.);
G4double sintheta = std::sqrt(1.-sqr(costheta));
return G4ThreeVector (fRmax*sintheta*cosphi,
+92 -266
View File
@@ -24,7 +24,7 @@
// ********************************************************************
//
//
// $Id: G4Para.cc 89721 2015-04-28 10:42:51Z gcosmo $
// $Id: G4Para.cc 101121 2016-11-07 09:18:01Z gcosmo $
//
// class G4Para
//
@@ -32,6 +32,9 @@
//
// History:
//
// 23.09.16 E.Tcherniaev: added Extent(pmin,pmax),
// use G4BoundingEnvelope for CalculateExtent(),
// removed CreateRotatedVertices()
// 23.10.05 V.Grichine: bug fixed in DistanceToOut(p,v,...) for the v.x()<0 case
// 28.04.05 V.Grichine: new SurfaceNormal according to J. Apostolakis proposal
// 30.11.04 V.Grichine: modifications in SurfaceNormal for edges/vertices and
@@ -47,6 +50,7 @@
#include "G4VoxelLimits.hh"
#include "G4AffineTransform.hh"
#include "G4BoundingEnvelope.hh"
#include "Randomize.hh"
#include "G4VPVParameterisation.hh"
@@ -210,6 +214,47 @@ void G4Para::ComputeDimensions( G4VPVParameterisation* p,
p->ComputeDimensions(*this,n,pRep);
}
////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4Para::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
G4double dz = GetZHalfLength();
G4double dx = GetXHalfLength();
G4double dy = GetYHalfLength();
G4double x0 = dz*fTthetaCphi;
G4double x1 = dy*GetTanAlpha();
G4double xmin =
std::min(
std::min(
std::min(-x0-x1-dx,-x0+x1-dx),x0-x1-dx),x0+x1-dx);
G4double xmax =
std::max(
std::max(
std::max(-x0-x1+dx,-x0+x1+dx),x0-x1+dx),x0+x1+dx);
G4double y0 = dz*fTthetaSphi;
G4double ymin = std::min(-y0-dy,y0-dy);
G4double ymax = std::max(-y0+dy,y0+dy);
pMin.set(xmin,ymin,-dz);
pMax.set(xmax,ymax, dz);
// 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("G4Para::Extent()", "GeomMgt0001", JustWarning, message);
DumpInfo();
}
}
//////////////////////////////////////////////////////////////
//
@@ -220,215 +265,49 @@ G4bool G4Para::CalculateExtent( const EAxis pAxis,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax ) const
{
G4bool flag;
G4ThreeVector bmin, bmax;
G4bool exist;
if (!pTransform.IsRotated())
{
// Special case handling for unrotated trapezoids
// Compute z/x/y/ mins and maxs respecting limits, with early returns
// if outside limits. Then switch() on pAxis
G4int i ;
G4double xoffset,xMin,xMax;
G4double yoffset,yMin,yMax;
G4double zoffset,zMin,zMax;
G4double temp[8] ; // some points for intersection with zMin/zMax
xoffset=pTransform.NetTranslation().x();
yoffset=pTransform.NetTranslation().y();
zoffset=pTransform.NetTranslation().z();
G4ThreeVector pt[8]; // vertices after translation
pt[0]=G4ThreeVector(xoffset-fDz*fTthetaCphi-fDy*fTalpha-fDx,
yoffset-fDz*fTthetaSphi-fDy,zoffset-fDz);
pt[1]=G4ThreeVector(xoffset-fDz*fTthetaCphi-fDy*fTalpha+fDx,
yoffset-fDz*fTthetaSphi-fDy,zoffset-fDz);
pt[2]=G4ThreeVector(xoffset-fDz*fTthetaCphi+fDy*fTalpha-fDx,
yoffset-fDz*fTthetaSphi+fDy,zoffset-fDz);
pt[3]=G4ThreeVector(xoffset-fDz*fTthetaCphi+fDy*fTalpha+fDx,
yoffset-fDz*fTthetaSphi+fDy,zoffset-fDz);
pt[4]=G4ThreeVector(xoffset+fDz*fTthetaCphi-fDy*fTalpha-fDx,
yoffset+fDz*fTthetaSphi-fDy,zoffset+fDz);
pt[5]=G4ThreeVector(xoffset+fDz*fTthetaCphi-fDy*fTalpha+fDx,
yoffset+fDz*fTthetaSphi-fDy,zoffset+fDz);
pt[6]=G4ThreeVector(xoffset+fDz*fTthetaCphi+fDy*fTalpha-fDx,
yoffset+fDz*fTthetaSphi+fDy,zoffset+fDz);
pt[7]=G4ThreeVector(xoffset+fDz*fTthetaCphi+fDy*fTalpha+fDx,
yoffset+fDz*fTthetaSphi+fDy,zoffset+fDz);
zMin=zoffset-fDz;
zMax=zoffset+fDz;
if ( pVoxelLimit.IsZLimited() )
{
if ( (zMin>pVoxelLimit.GetMaxZExtent()+kCarTolerance)
|| (zMax<pVoxelLimit.GetMinZExtent()-kCarTolerance) )
{
return false;
}
else
{
if (zMin<pVoxelLimit.GetMinZExtent())
{
zMin=pVoxelLimit.GetMinZExtent();
}
if (zMax>pVoxelLimit.GetMaxZExtent())
{
zMax=pVoxelLimit.GetMaxZExtent();
}
}
}
temp[0] = pt[0].y()+(pt[4].y()-pt[0].y())
*(zMin-pt[0].z())/(pt[4].z()-pt[0].z()) ;
temp[1] = pt[0].y()+(pt[4].y()-pt[0].y())
*(zMax-pt[0].z())/(pt[4].z()-pt[0].z()) ;
temp[2] = pt[2].y()+(pt[6].y()-pt[2].y())
*(zMin-pt[2].z())/(pt[6].z()-pt[2].z()) ;
temp[3] = pt[2].y()+(pt[6].y()-pt[2].y())
*(zMax-pt[2].z())/(pt[6].z()-pt[2].z()) ;
yMax = yoffset - std::fabs(fDz*fTthetaSphi) - fDy - fDy ;
yMin = -yMax ;
for(i=0;i<4;i++)
{
if(temp[i] > yMax) yMax = temp[i] ;
if(temp[i] < yMin) yMin = temp[i] ;
}
if (pVoxelLimit.IsYLimited())
{
if ( (yMin>pVoxelLimit.GetMaxYExtent()+kCarTolerance)
|| (yMax<pVoxelLimit.GetMinYExtent()-kCarTolerance) )
{
return false;
}
else
{
if (yMin<pVoxelLimit.GetMinYExtent())
{
yMin=pVoxelLimit.GetMinYExtent();
}
if (yMax>pVoxelLimit.GetMaxYExtent())
{
yMax=pVoxelLimit.GetMaxYExtent();
}
}
}
temp[0] = pt[0].x()+(pt[4].x()-pt[0].x())
*(zMin-pt[0].z())/(pt[4].z()-pt[0].z()) ;
temp[1] = pt[0].x()+(pt[4].x()-pt[0].x())
*(zMax-pt[0].z())/(pt[4].z()-pt[0].z()) ;
temp[2] = pt[2].x()+(pt[6].x()-pt[2].x())
*(zMin-pt[2].z())/(pt[6].z()-pt[2].z()) ;
temp[3] = pt[2].x()+(pt[6].x()-pt[2].x())
*(zMax-pt[2].z())/(pt[6].z()-pt[2].z()) ;
temp[4] = pt[3].x()+(pt[7].x()-pt[3].x())
*(zMin-pt[3].z())/(pt[7].z()-pt[3].z()) ;
temp[5] = pt[3].x()+(pt[7].x()-pt[3].x())
*(zMax-pt[3].z())/(pt[7].z()-pt[3].z()) ;
temp[6] = pt[1].x()+(pt[5].x()-pt[1].x())
*(zMin-pt[1].z())/(pt[5].z()-pt[1].z()) ;
temp[7] = pt[1].x()+(pt[5].x()-pt[1].x())
*(zMax-pt[1].z())/(pt[5].z()-pt[1].z()) ;
xMax = xoffset - std::fabs(fDz*fTthetaCphi) - fDx - fDx -fDx - fDx;
xMin = -xMax ;
for(i=0;i<8;i++)
{
if(temp[i] > xMax) xMax = temp[i] ;
if(temp[i] < xMin) xMin = temp[i] ;
}
// xMax/Min = f(yMax/Min) ?
if (pVoxelLimit.IsXLimited())
{
if ( (xMin>pVoxelLimit.GetMaxXExtent()+kCarTolerance)
|| (xMax<pVoxelLimit.GetMinXExtent()-kCarTolerance) )
{
return false;
}
else
{
if (xMin<pVoxelLimit.GetMinXExtent())
{
xMin=pVoxelLimit.GetMinXExtent();
}
if (xMax>pVoxelLimit.GetMaxXExtent())
{
xMax=pVoxelLimit.GetMaxXExtent();
}
}
}
switch (pAxis)
{
case kXAxis:
pMin=xMin;
pMax=xMax;
break;
case kYAxis:
pMin=yMin;
pMax=yMax;
break;
case kZAxis:
pMin=zMin;
pMax=zMax;
break;
default:
break;
}
pMin-=kCarTolerance;
pMax+=kCarTolerance;
flag = true;
}
else
// Check bounding box (bbox)
//
Extent(bmin,bmax);
G4BoundingEnvelope bbox(bmin,bmax);
#ifdef G4BBOX_EXTENT
if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
#endif
if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
{
// General rotated case - create and clip mesh to boundaries
G4bool existsAfterClip=false;
G4ThreeVectorList *vertices;
pMin=+kInfinity;
pMax=-kInfinity;
// Calculate rotated vertex coordinates
vertices=CreateRotatedVertices(pTransform);
ClipCrossSection(vertices,0,pVoxelLimit,pAxis,pMin,pMax);
ClipCrossSection(vertices,4,pVoxelLimit,pAxis,pMin,pMax);
ClipBetweenSections(vertices,0,pVoxelLimit,pAxis,pMin,pMax);
if (pMin!=kInfinity||pMax!=-kInfinity)
{
existsAfterClip=true;
// Add 2*tolerance to avoid precision troubles
//
pMin-=kCarTolerance;
pMax+=kCarTolerance;
}
else
{
// Check for case where completely enveloping clipping volume
// If point inside then we are confident that the solid completely
// envelopes the clipping volume. Hence set min/max extents according
// to clipping volume extents along the specified axis.
G4ThreeVector clipCentre(
(pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
(pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
(pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5);
if (Inside(pTransform.Inverse().TransformPoint(clipCentre))!=kOutside)
{
existsAfterClip=true;
pMin=pVoxelLimit.GetMinExtent(pAxis);
pMax=pVoxelLimit.GetMaxExtent(pAxis);
}
}
delete vertices ; // 'new' in the function called
flag = existsAfterClip ;
return exist = (pMin < pMax) ? true : false;
}
return flag;
// Set bounding envelope (benv) and calculate extent
//
G4double dz = GetZHalfLength();
G4double dx = GetXHalfLength();
G4double dy = GetYHalfLength();
G4double x0 = dz*fTthetaCphi;
G4double x1 = dy*GetTanAlpha();
G4double y0 = dz*fTthetaSphi;
G4ThreeVectorList baseA(4), baseB(4);
baseA[0].set(-x0-x1-dx,-y0-dy,-dz);
baseA[1].set(-x0-x1+dx,-y0-dy,-dz);
baseA[2].set(-x0+x1+dx,-y0+dy,-dz);
baseA[3].set(-x0+x1-dx,-y0+dy,-dz);
baseB[0].set(+x0-x1-dx, y0-dy, dz);
baseB[1].set(+x0-x1+dx, y0-dy, dz);
baseB[2].set(+x0+x1+dx, y0+dy, dz);
baseB[3].set(+x0+x1-dx, y0+dy, dz);
std::vector<const G4ThreeVectorList *> polygons(2);
polygons[0] = &baseA;
polygons[1] = &baseB;
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
return exist;
}
/////////////////////////////////////////////////////////////////////////////
@@ -1134,59 +1013,6 @@ G4double G4Para::DistanceToOut( const G4ThreeVector& p ) const
return safe;
}
////////////////////////////////////////////////////////////////////////////////
//
// Create a List containing the transformed vertices
// Ordering [0-3] -fDz cross section
// [4-7] +fDz cross section such that [0] is below [4],
// [1] below [5] etc.
// Note:
// Caller has deletion resposibility
G4ThreeVectorList*
G4Para::CreateRotatedVertices( const G4AffineTransform& pTransform ) const
{
G4ThreeVectorList *vertices;
vertices=new G4ThreeVectorList();
if (vertices)
{
vertices->reserve(8);
G4ThreeVector vertex0(-fDz*fTthetaCphi-fDy*fTalpha-fDx,
-fDz*fTthetaSphi-fDy, -fDz);
G4ThreeVector vertex1(-fDz*fTthetaCphi-fDy*fTalpha+fDx,
-fDz*fTthetaSphi-fDy, -fDz);
G4ThreeVector vertex2(-fDz*fTthetaCphi+fDy*fTalpha-fDx,
-fDz*fTthetaSphi+fDy, -fDz);
G4ThreeVector vertex3(-fDz*fTthetaCphi+fDy*fTalpha+fDx,
-fDz*fTthetaSphi+fDy, -fDz);
G4ThreeVector vertex4(+fDz*fTthetaCphi-fDy*fTalpha-fDx,
+fDz*fTthetaSphi-fDy, +fDz);
G4ThreeVector vertex5(+fDz*fTthetaCphi-fDy*fTalpha+fDx,
+fDz*fTthetaSphi-fDy, +fDz);
G4ThreeVector vertex6(+fDz*fTthetaCphi+fDy*fTalpha-fDx,
+fDz*fTthetaSphi+fDy, +fDz);
G4ThreeVector vertex7(+fDz*fTthetaCphi+fDy*fTalpha+fDx,
+fDz*fTthetaSphi+fDy, +fDz);
vertices->push_back(pTransform.TransformPoint(vertex0));
vertices->push_back(pTransform.TransformPoint(vertex1));
vertices->push_back(pTransform.TransformPoint(vertex2));
vertices->push_back(pTransform.TransformPoint(vertex3));
vertices->push_back(pTransform.TransformPoint(vertex4));
vertices->push_back(pTransform.TransformPoint(vertex5));
vertices->push_back(pTransform.TransformPoint(vertex6));
vertices->push_back(pTransform.TransformPoint(vertex7));
}
else
{
DumpInfo();
G4Exception("G4Para::CreateRotatedVertices()",
"GeomSolids0003", FatalException,
"Error in allocation of vertices. Out of memory !");
}
return vertices;
}
//////////////////////////////////////////////////////////////////////////
//
// GetEntityType
@@ -1263,19 +1089,19 @@ G4ThreeVector G4Para::GetPointOnPlane(G4ThreeVector p0, G4ThreeVector p1,
area = aOne + aTwo;
chose = RandFlat::shoot(0.,aOne+aTwo);
chose = G4RandFlat::shoot(0.,aOne+aTwo);
if( (chose>=0.) && (chose < aOne) )
{
lambda1 = RandFlat::shoot(0.,1.);
lambda2 = RandFlat::shoot(0.,lambda1);
lambda1 = G4RandFlat::shoot(0.,1.);
lambda2 = G4RandFlat::shoot(0.,lambda1);
return (p2+lambda1*v+lambda2*w);
}
// else
lambda1 = RandFlat::shoot(0.,1.);
lambda2 = RandFlat::shoot(0.,lambda1);
lambda1 = G4RandFlat::shoot(0.,1.);
lambda2 = G4RandFlat::shoot(0.,lambda1);
return (p0+lambda1*t+lambda2*u);
}
@@ -1318,7 +1144,7 @@ G4ThreeVector G4Para::GetPointOnSurface() const
Five = GetPointOnPlane(pt[0],pt[2],pt[6],pt[4], aFive);
Six = GetPointOnPlane(pt[1],pt[3],pt[7],pt[5], aSix);
chose = RandFlat::shoot(0.,aOne+aTwo+aThree+aFour+aFive+aSix);
chose = G4RandFlat::shoot(0.,aOne+aTwo+aThree+aFour+aFive+aSix);
if( (chose>=0.) && (chose<aOne) )
{ return One; }
+94 -384
View File
@@ -24,7 +24,7 @@
// ********************************************************************
//
//
// $Id: G4Sphere.cc 93421 2015-10-22 09:26:27Z gcosmo $
// $Id: G4Sphere.cc 100820 2016-11-02 15:18:48Z gcosmo $
//
// class G4Sphere
//
@@ -32,8 +32,12 @@
//
// History:
//
// 26.10.16 E.Tcherniaev: added Extent(pmin,pmax), re-implemented
// CalculateExtent() using G4BoundingEnvelope,
// removed CreateRotatedVertices()
// 05.04.12 M.Kelsey: GetPointOnSurface() throw flat in cos(theta), sqrt(r)
// 14.09.09 T.Nikitina: fix for phi section in DistanceToOut(p,v,..),as for G4Tubs,G4Cons
// 14.09.09 T.Nikitina: fix for phi section in DistanceToOut(p,v,..),as for
// G4Tubs,G4Cons
// 26.03.09 G.Cosmo : optimisations and uniform use of local radial tolerance
// 12.06.08 V.Grichine: fix for theta intersections in DistanceToOut(p,v,...)
// 22.07.05 O.Link : Added check for intersection with double cone
@@ -58,9 +62,11 @@
#if !defined(G4GEOM_USE_USPHERE)
#include "G4GeomTools.hh"
#include "G4VoxelLimits.hh"
#include "G4AffineTransform.hh"
#include "G4GeometryTolerance.hh"
#include "G4BoundingEnvelope.hh"
#include "G4VPVParameterisation.hh"
@@ -220,6 +226,62 @@ void G4Sphere::ComputeDimensions( G4VPVParameterisation* p,
p->ComputeDimensions(*this,n,pRep);
}
//////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4Sphere::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
G4double rmin = GetInnerRadius();
G4double rmax = GetOuterRadius();
// Find bounding box
//
if (GetDeltaThetaAngle() >= pi && GetDeltaPhiAngle() >= twopi)
{
pMin.set(-rmax,-rmax,-rmax);
pMax.set( rmax, rmax, rmax);
}
else
{
G4double sinStart = GetSinStartTheta();
G4double cosStart = GetCosStartTheta();
G4double sinEnd = GetSinEndTheta();
G4double cosEnd = GetCosEndTheta();
G4double stheta = GetStartThetaAngle();
G4double etheta = stheta + GetDeltaThetaAngle();
G4double rhomin = rmin*std::min(sinStart,sinEnd);
G4double rhomax = rmax;
if (stheta > halfpi) rhomax = rmax*sinStart;
if (etheta < halfpi) rhomax = rmax*sinEnd;
G4TwoVector xymin,xymax;
G4GeomTools::DiskExtent(rhomin,rhomax,
GetSinStartPhi(),GetCosStartPhi(),
GetSinEndPhi(),GetCosEndPhi(),
xymin,xymax);
G4double zmin = std::min(rmin*cosEnd,rmax*cosEnd);
G4double zmax = std::max(rmin*cosStart,rmax*cosStart);
pMin.set(xymin.x(),xymin.y(),zmin);
pMax.set(xymax.x(),xymax.y(),zmax);
}
// 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("G4Sphere::Extent()", "GeomMgt0001", JustWarning, message);
DumpInfo();
}
}
////////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
@@ -229,238 +291,14 @@ G4bool G4Sphere::CalculateExtent( const EAxis pAxis,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax ) const
{
if ( fFullSphere )
{
// Special case handling for solid spheres-shells
// (rotation doesn't influence).
// Compute x/y/z mins and maxs for bounding box respecting limits,
// with early returns if outside limits. Then switch() on pAxis,
// and compute exact x and y limit for x/y case
G4double xoffset,xMin,xMax;
G4double yoffset,yMin,yMax;
G4double zoffset,zMin,zMax;
G4ThreeVector bmin, bmax;
G4double diff1,diff2,delta,maxDiff,newMin,newMax;
G4double xoff1,xoff2,yoff1,yoff2;
// Get bounding box
Extent(bmin,bmax);
xoffset=pTransform.NetTranslation().x();
xMin=xoffset-fRmax;
xMax=xoffset+fRmax;
if (pVoxelLimit.IsXLimited())
{
if ( (xMin>pVoxelLimit.GetMaxXExtent()+kCarTolerance)
|| (xMax<pVoxelLimit.GetMinXExtent()-kCarTolerance) )
{
return false;
}
else
{
if (xMin<pVoxelLimit.GetMinXExtent())
{
xMin=pVoxelLimit.GetMinXExtent();
}
if (xMax>pVoxelLimit.GetMaxXExtent())
{
xMax=pVoxelLimit.GetMaxXExtent();
}
}
}
yoffset=pTransform.NetTranslation().y();
yMin=yoffset-fRmax;
yMax=yoffset+fRmax;
if (pVoxelLimit.IsYLimited())
{
if ( (yMin>pVoxelLimit.GetMaxYExtent()+kCarTolerance)
|| (yMax<pVoxelLimit.GetMinYExtent()-kCarTolerance) )
{
return false;
}
else
{
if (yMin<pVoxelLimit.GetMinYExtent())
{
yMin=pVoxelLimit.GetMinYExtent();
}
if (yMax>pVoxelLimit.GetMaxYExtent())
{
yMax=pVoxelLimit.GetMaxYExtent();
}
}
}
zoffset=pTransform.NetTranslation().z();
zMin=zoffset-fRmax;
zMax=zoffset+fRmax;
if (pVoxelLimit.IsZLimited())
{
if ( (zMin>pVoxelLimit.GetMaxZExtent()+kCarTolerance)
|| (zMax<pVoxelLimit.GetMinZExtent()-kCarTolerance) )
{
return false;
}
else
{
if (zMin<pVoxelLimit.GetMinZExtent())
{
zMin=pVoxelLimit.GetMinZExtent();
}
if (zMax>pVoxelLimit.GetMaxZExtent())
{
zMax=pVoxelLimit.GetMaxZExtent();
}
}
}
// Known to cut sphere
switch (pAxis)
{
case kXAxis:
yoff1=yoffset-yMin;
yoff2=yMax-yoffset;
if ((yoff1>=0) && (yoff2>=0))
{
// Y limits cross max/min x => no change
//
pMin=xMin;
pMax=xMax;
}
else
{
// Y limits don't cross max/min x => compute max delta x,
// hence new mins/maxs
//
delta=fRmax*fRmax-yoff1*yoff1;
diff1=(delta>0.) ? std::sqrt(delta) : 0.;
delta=fRmax*fRmax-yoff2*yoff2;
diff2=(delta>0.) ? std::sqrt(delta) : 0.;
maxDiff=(diff1>diff2) ? diff1:diff2;
newMin=xoffset-maxDiff;
newMax=xoffset+maxDiff;
pMin=(newMin<xMin) ? xMin : newMin;
pMax=(newMax>xMax) ? xMax : newMax;
}
break;
case kYAxis:
xoff1=xoffset-xMin;
xoff2=xMax-xoffset;
if ((xoff1>=0) && (xoff2>=0))
{
// X limits cross max/min y => no change
//
pMin=yMin;
pMax=yMax;
}
else
{
// X limits don't cross max/min y => compute max delta y,
// hence new mins/maxs
//
delta=fRmax*fRmax-xoff1*xoff1;
diff1=(delta>0.) ? std::sqrt(delta) : 0.;
delta=fRmax*fRmax-xoff2*xoff2;
diff2=(delta>0.) ? std::sqrt(delta) : 0.;
maxDiff=(diff1>diff2) ? diff1:diff2;
newMin=yoffset-maxDiff;
newMax=yoffset+maxDiff;
pMin=(newMin<yMin) ? yMin : newMin;
pMax=(newMax>yMax) ? yMax : newMax;
}
break;
case kZAxis:
pMin=zMin;
pMax=zMax;
break;
default:
break;
}
pMin-=kCarTolerance;
pMax+=kCarTolerance;
return true;
}
else // Transformed cutted sphere
{
G4int i,j,noEntries,noBetweenSections;
G4bool existsAfterClip=false;
// Calculate rotated vertex coordinates
G4ThreeVectorList* vertices;
G4int noPolygonVertices ;
vertices=CreateRotatedVertices(pTransform,noPolygonVertices);
pMin=+kInfinity;
pMax=-kInfinity;
noEntries=vertices->size(); // noPolygonVertices*noPhiCrossSections
noBetweenSections=noEntries-noPolygonVertices;
G4ThreeVectorList ThetaPolygon ;
for (i=0;i<noEntries;i+=noPolygonVertices)
{
for(j=0;j<(noPolygonVertices/2)-1;j++)
{
ThetaPolygon.push_back((*vertices)[i+j]) ;
ThetaPolygon.push_back((*vertices)[i+j+1]) ;
ThetaPolygon.push_back((*vertices)[i+noPolygonVertices-2-j]) ;
ThetaPolygon.push_back((*vertices)[i+noPolygonVertices-1-j]) ;
CalculateClippedPolygonExtent(ThetaPolygon,pVoxelLimit,pAxis,pMin,pMax);
ThetaPolygon.clear() ;
}
}
for (i=0;i<noBetweenSections;i+=noPolygonVertices)
{
for(j=0;j<noPolygonVertices-1;j++)
{
ThetaPolygon.push_back((*vertices)[i+j]) ;
ThetaPolygon.push_back((*vertices)[i+j+1]) ;
ThetaPolygon.push_back((*vertices)[i+noPolygonVertices+j+1]) ;
ThetaPolygon.push_back((*vertices)[i+noPolygonVertices+j]) ;
CalculateClippedPolygonExtent(ThetaPolygon,pVoxelLimit,pAxis,pMin,pMax);
ThetaPolygon.clear() ;
}
ThetaPolygon.push_back((*vertices)[i+noPolygonVertices-1]) ;
ThetaPolygon.push_back((*vertices)[i]) ;
ThetaPolygon.push_back((*vertices)[i+noPolygonVertices]) ;
ThetaPolygon.push_back((*vertices)[i+2*noPolygonVertices-1]) ;
CalculateClippedPolygonExtent(ThetaPolygon,pVoxelLimit,pAxis,pMin,pMax);
ThetaPolygon.clear() ;
}
if ((pMin!=kInfinity) || (pMax!=-kInfinity))
{
existsAfterClip=true;
// Add 2*tolerance to avoid precision troubles
//
pMin-=kCarTolerance;
pMax+=kCarTolerance;
}
else
{
// Check for case where completely enveloping clipping volume
// If point inside then we are confident that the solid completely
// envelopes the clipping volume. Hence set min/max extents according
// to clipping volume extents along the specified axis.
G4ThreeVector clipCentre(
(pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
(pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
(pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5);
if (Inside(pTransform.Inverse().TransformPoint(clipCentre))!=kOutside)
{
existsAfterClip=true;
pMin=pVoxelLimit.GetMinExtent(pAxis);
pMax=pVoxelLimit.GetMaxExtent(pAxis);
}
}
delete vertices;
return existsAfterClip;
}
// Find extent
G4BoundingEnvelope bbox(bmin,bmax);
return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
}
///////////////////////////////////////////////////////////////////////////
@@ -551,9 +389,9 @@ EInside G4Sphere::Inside( const G4ThreeVector& p ) const
if ( in == kInside )
{
if ( ((fSTheta > 0.0) && (pTheta < fSTheta + halfAngTolerance))
|| ((eTheta < pi) && (pTheta > eTheta - halfAngTolerance)) )
|| ((eTheta < pi) && (pTheta > eTheta - halfAngTolerance)) )
{
if ( (( (fSTheta>0.0)&&(pTheta>=fSTheta-halfAngTolerance) )
if ( (( (fSTheta>0.0)&&(pTheta>=fSTheta-halfAngTolerance) )
|| (fSTheta == 0.0) )
&& ((eTheta==pi)||(pTheta <= eTheta + halfAngTolerance) ) )
{
@@ -568,7 +406,7 @@ EInside G4Sphere::Inside( const G4ThreeVector& p ) const
else
{
if ( ((fSTheta > 0.0)&&(pTheta < fSTheta - halfAngTolerance))
||((eTheta < pi )&&(pTheta > eTheta + halfAngTolerance)) )
||((eTheta < pi )&&(pTheta > eTheta + halfAngTolerance)) )
{
in = kOutside;
}
@@ -707,7 +545,7 @@ G4ThreeVector G4Sphere::SurfaceNormal( const G4ThreeVector& p ) const
}
/////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
//
// Algorithm for SurfaceNormal() following the original specification
// for points not on the surface
@@ -1373,7 +1211,8 @@ G4double G4Sphere::DistanceToIn( const G4ThreeVector& p,
// => (px^2+py^2-pz^2tan^2(t))+2sd(pxvx+pyvy-pzvztan^2(t))
// + sd^2(vx^2+vy^2-vz^2tan^2(t)) = 0
//
// => sd^2(1-vz^2(1+tan^2(t))+2sd(pdotv2d-pzvztan^2(t))+(rho2-pz^2tan^2(t))=0
// => sd^2(1-vz^2(1+tan^2(t))+2sd(pdotv2d-pzvztan^2(t))
// + (rho2-pz^2tan^2(t)) = 0
if (fSTheta)
{
@@ -2033,7 +1872,7 @@ G4double G4Sphere::DistanceToOut( const G4ThreeVector& p,
if ( (c < fRminTolerance*fRmin) // leaving from Rmin
&& (d2 >= fRminTolerance*fRmin) && (pDotV3d < 0) )
{
if(calcNorm) { *validNorm = false; } // Rmin surface is concave
if(calcNorm) { *validNorm = false; } // Rmin surface is concave
return snxt = 0 ;
}
else
@@ -2076,7 +1915,8 @@ G4double G4Sphere::DistanceToOut( const G4ThreeVector& p,
// => (px^2+py^2-pz^2tan^2(t))+2sd(pxvx+pyvy-pzvztan^2(t))
// + sd^2(vx^2+vy^2-vz^2tan^2(t)) = 0
//
// => sd^2(1-vz^2(1+tan^2(t))+2sd(pdotv2d-pzvztan^2(t))+(rho2-pz^2tan^2(t))=0
// => sd^2(1-vz^2(1+tan^2(t))+2sd(pdotv2d-pzvztan^2(t))
// + (rho2-pz^2tan^2(t)) = 0
//
if(fSTheta) // intersection with first cons
@@ -2338,11 +2178,13 @@ G4double G4Sphere::DistanceToOut( const G4ThreeVector& p,
sd = -b - d; // First root
if ( ((std::fabs(sd) < halfRmaxTolerance) && (t2 >= 0.))
|| (sd < 0.) || ( (sd > 0.) && (p.z() + sd*v.z() > halfRmaxTolerance) ) )
|| (sd < 0.)
|| ( (sd > 0.) && (p.z() + sd*v.z() > halfRmaxTolerance) ) )
{
sd = -b + d ; // 2nd root
}
if( (sd > halfRmaxTolerance) && (p.z() + sd*v.z() <= halfRmaxTolerance) )
if ( ( sd>halfRmaxTolerance )
&& ( p.z()+sd*v.z() <= halfRmaxTolerance ) )
{
if( sd < stheta )
{
@@ -2419,7 +2261,8 @@ G4double G4Sphere::DistanceToOut( const G4ThreeVector& p,
// Check intersection with correct half-plane
//
if ((std::fabs(xi)<=kCarTolerance) && (std::fabs(yi)<=kCarTolerance))
if ( (std::fabs(xi)<=kCarTolerance)
&& (std::fabs(yi)<=kCarTolerance))
{
// Leaving via ending phi
//
@@ -2525,7 +2368,8 @@ G4double G4Sphere::DistanceToOut( const G4ThreeVector& p,
// Check intersection in correct half-plane
// (if not -> remain in extent)
//
if( (std::fabs(xi)<=kCarTolerance)&&(std::fabs(yi)<=kCarTolerance) )
if( (std::fabs(xi)<=kCarTolerance)
&& (std::fabs(yi)<=kCarTolerance) )
{
vphi = std::atan2(v.y(),v.x());
sidephi = kSPhi;
@@ -2607,7 +2451,8 @@ G4double G4Sphere::DistanceToOut( const G4ThreeVector& p,
// Check intersection in correct half-plane
// (if not -> remain in extent)
//
if((std::fabs(xi)<=kCarTolerance) && (std::fabs(yi)<=kCarTolerance))
if( (std::fabs(xi)<=kCarTolerance)
&& (std::fabs(yi)<=kCarTolerance))
{
vphi = std::atan2(v.y(),v.x()) ;
sidephi = kSPhi;
@@ -2903,141 +2748,6 @@ G4double G4Sphere::DistanceToOut( const G4ThreeVector& p ) const
return safe;
}
//////////////////////////////////////////////////////////////////////////
//
// Create a List containing the transformed vertices
// Ordering [0-3] -fDz cross section
// [4-7] +fDz cross section such that [0] is below [4],
// [1] below [5] etc.
// Note:
// Caller has deletion resposibility
// Potential improvement: For last slice, use actual ending angle
// to avoid rounding error problems.
G4ThreeVectorList*
G4Sphere::CreateRotatedVertices( const G4AffineTransform& pTransform,
G4int& noPolygonVertices ) const
{
G4ThreeVectorList *vertices;
G4ThreeVector vertex;
G4double meshAnglePhi,meshRMax,crossAnglePhi,
coscrossAnglePhi,sincrossAnglePhi,sAnglePhi;
G4double meshTheta,crossTheta,startTheta;
G4double rMaxX,rMaxY,rMinX,rMinY,rMinZ,rMaxZ;
G4int crossSectionPhi,noPhiCrossSections,crossSectionTheta,noThetaSections;
// Phi cross sections
noPhiCrossSections = G4int(fDPhi/kMeshAngleDefault)+1;
if (noPhiCrossSections<kMinMeshSections)
{
noPhiCrossSections=kMinMeshSections;
}
else if (noPhiCrossSections>kMaxMeshSections)
{
noPhiCrossSections=kMaxMeshSections;
}
meshAnglePhi=fDPhi/(noPhiCrossSections-1);
// If complete in phi, set start angle such that mesh will be at fRMax
// on the x axis. Will give better extent calculations when not rotated.
if (fFullPhiSphere)
{
sAnglePhi = -meshAnglePhi*0.5;
}
else
{
sAnglePhi=fSPhi;
}
// Theta cross sections
noThetaSections = G4int(fDTheta/kMeshAngleDefault)+1;
if (noThetaSections<kMinMeshSections)
{
noThetaSections=kMinMeshSections;
}
else if (noThetaSections>kMaxMeshSections)
{
noThetaSections=kMaxMeshSections;
}
meshTheta=fDTheta/(noThetaSections-1);
// If complete in Theta, set start angle such that mesh will be at fRMax
// on the z axis. Will give better extent calculations when not rotated.
if (fFullThetaSphere)
{
startTheta = -meshTheta*0.5;
}
else
{
startTheta=fSTheta;
}
meshRMax = (meshAnglePhi >= meshTheta) ?
fRmax/std::cos(meshAnglePhi*0.5) : fRmax/std::cos(meshTheta*0.5);
G4double* cosCrossTheta = new G4double[noThetaSections];
G4double* sinCrossTheta = new G4double[noThetaSections];
vertices=new G4ThreeVectorList();
if (vertices && cosCrossTheta && sinCrossTheta)
{
vertices->reserve(noPhiCrossSections*(noThetaSections*2));
for (crossSectionPhi=0;
crossSectionPhi<noPhiCrossSections; crossSectionPhi++)
{
crossAnglePhi=sAnglePhi+crossSectionPhi*meshAnglePhi;
coscrossAnglePhi=std::cos(crossAnglePhi);
sincrossAnglePhi=std::sin(crossAnglePhi);
for (crossSectionTheta=0;
crossSectionTheta<noThetaSections;crossSectionTheta++)
{
// Compute coordinates of cross section at section crossSectionPhi
//
crossTheta=startTheta+crossSectionTheta*meshTheta;
cosCrossTheta[crossSectionTheta]=std::cos(crossTheta);
sinCrossTheta[crossSectionTheta]=std::sin(crossTheta);
rMinX=fRmin*sinCrossTheta[crossSectionTheta]*coscrossAnglePhi;
rMinY=fRmin*sinCrossTheta[crossSectionTheta]*sincrossAnglePhi;
rMinZ=fRmin*cosCrossTheta[crossSectionTheta];
vertex=G4ThreeVector(rMinX,rMinY,rMinZ);
vertices->push_back(pTransform.TransformPoint(vertex));
} // Theta forward
for (crossSectionTheta=noThetaSections-1;
crossSectionTheta>=0; crossSectionTheta--)
{
rMaxX=meshRMax*sinCrossTheta[crossSectionTheta]*coscrossAnglePhi;
rMaxY=meshRMax*sinCrossTheta[crossSectionTheta]*sincrossAnglePhi;
rMaxZ=meshRMax*cosCrossTheta[crossSectionTheta];
vertex=G4ThreeVector(rMaxX,rMaxY,rMaxZ);
vertices->push_back(pTransform.TransformPoint(vertex));
} // Theta back
} // Phi
noPolygonVertices = noThetaSections*2 ;
}
else
{
DumpInfo();
G4Exception("G4Sphere::CreateRotatedVertices()",
"GeomSolids0003", FatalException,
"Error in allocation of vertices. Out of memory !");
}
delete [] cosCrossTheta;
delete [] sinCrossTheta;
return vertices;
}
//////////////////////////////////////////////////////////////////////////
//
// G4EntityType
@@ -3101,10 +2811,10 @@ G4ThreeVector G4Sphere::GetPointOnSurface() const
aFou = fDPhi*((fRmax + fRmin)*sinETheta)*slant2;
aFiv = 0.5*fDTheta*(fRmax*fRmax-fRmin*fRmin);
phi = RandFlat::shoot(fSPhi, ePhi);
phi = G4RandFlat::shoot(fSPhi, ePhi);
cosphi = std::cos(phi);
sinphi = std::sin(phi);
costheta = RandFlat::shoot(cosETheta,cosSTheta);
costheta = G4RandFlat::shoot(cosETheta,cosSTheta);
sintheta = std::sqrt(1.-sqr(costheta));
if(fFullPhiSphere) { aFiv = 0; }
@@ -3113,7 +2823,7 @@ G4ThreeVector G4Sphere::GetPointOnSurface() const
if(fSTheta == halfpi) { aThr = pi*(fRmax*fRmax-fRmin*fRmin); }
if(eTheta == halfpi) { aFou = pi*(fRmax*fRmax-fRmin*fRmin); }
chose = RandFlat::shoot(0.,aOne+aTwo+aThr+aFou+2.*aFiv);
chose = G4RandFlat::shoot(0.,aOne+aTwo+aThr+aFou+2.*aFiv);
if( (chose>=0.) && (chose<aOne) )
{
return G4ThreeVector(fRmax*sintheta*cosphi,
@@ -3128,7 +2838,7 @@ G4ThreeVector G4Sphere::GetPointOnSurface() const
{
if (fSTheta != halfpi)
{
zRand = RandFlat::shoot(fRmin*cosSTheta,fRmax*cosSTheta);
zRand = G4RandFlat::shoot(fRmin*cosSTheta,fRmax*cosSTheta);
return G4ThreeVector(tanSTheta*zRand*cosphi,
tanSTheta*zRand*sinphi,zRand);
}
@@ -3141,7 +2851,7 @@ G4ThreeVector G4Sphere::GetPointOnSurface() const
{
if(eTheta != halfpi)
{
zRand = RandFlat::shoot(fRmin*cosETheta, fRmax*cosETheta);
zRand = G4RandFlat::shoot(fRmin*cosETheta, fRmax*cosETheta);
return G4ThreeVector (tanETheta*zRand*cosphi,
tanETheta*zRand*sinphi,zRand);
}
+168 -290
View File
@@ -24,13 +24,15 @@
// ********************************************************************
//
//
// $Id: G4Torus.cc 92393 2015-08-31 14:07:30Z gcosmo $
// $Id: G4Torus.cc 101121 2016-11-07 09:18:01Z gcosmo $
//
//
// class G4Torus
//
// Implementation
//
// 28.10.16 E.Tcherniaev: reimplemented CalculateExtent(),
// added Extent(), removed CreateRotatedVertices()
// 05.04.12 M.Kelsey: Use sqrt(r) in GetPointOnSurface() for uniform points
// 02.10.07 T.Nikitina: Bug fixed in SolveNumericJT(), b.969:segmentation fault.
// rootsrefined is used only if the number of refined roots
@@ -58,8 +60,10 @@
#if !(defined(G4GEOM_USE_UTORUS) && defined(G4GEOM_USE_SYS_USOLIDS))
#include "G4GeomTools.hh"
#include "G4VoxelLimits.hh"
#include "G4AffineTransform.hh"
#include "G4BoundingEnvelope.hh"
#include "G4GeometryTolerance.hh"
#include "G4JTPolynomialSolver.hh"
@@ -409,6 +413,50 @@ G4double G4Torus::SolveNumericJT( const G4ThreeVector& p,
return tmin;
}
/////////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4Torus::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
G4double rmax = GetRmax();
G4double rtor = GetRtor();
G4double rint = rtor - rmax;
G4double rext = rtor + rmax;
G4double dz = rmax;
// Find bounding box
//
if (GetDPhi() >= twopi)
{
pMin.set(-rext,-rext,-dz);
pMax.set( rext, rext, dz);
}
else
{
G4TwoVector vmin,vmax;
G4GeomTools::DiskExtent(rint,rext,
GetSinStartPhi(),GetCosStartPhi(),
GetSinEndPhi(),GetCosEndPhi(),
vmin,vmax);
pMin.set(vmin.x(),vmin.y(),-dz);
pMax.set(vmax.x(),vmax.y(), dz);
}
// 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("G4Torus::Extent()", "GeomMgt0001", JustWarning, message);
DumpInfo();
}
}
/////////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
@@ -418,215 +466,133 @@ G4bool G4Torus::CalculateExtent( const EAxis pAxis,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax) const
{
if ((!pTransform.IsRotated()) && (fDPhi==twopi) && (fRmin==0))
G4ThreeVector bmin, bmax;
G4bool exist;
// Get bounding box
Extent(bmin,bmax);
// Check bounding box
G4BoundingEnvelope bbox(bmin,bmax);
#ifdef G4BBOX_EXTENT
if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
#endif
if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
{
// Special case handling for unrotated solid torus
// Compute x/y/z mins and maxs for bounding box respecting limits,
// with early returns if outside limits. Then switch() on pAxis,
// and compute exact x and y limit for x/y case
G4double xoffset,xMin,xMax;
G4double yoffset,yMin,yMax;
G4double zoffset,zMin,zMax;
G4double RTorus,delta,diff1,diff2,maxDiff,newMin,newMax;
G4double xoff1,xoff2,yoff1,yoff2;
xoffset = pTransform.NetTranslation().x();
xMin = xoffset - fRmax - fRtor ;
xMax = xoffset + fRmax + fRtor ;
if (pVoxelLimit.IsXLimited())
{
if ( (xMin > pVoxelLimit.GetMaxXExtent()+kCarTolerance)
|| (xMax < pVoxelLimit.GetMinXExtent()-kCarTolerance) )
return false ;
else
{
if (xMin < pVoxelLimit.GetMinXExtent())
{
xMin = pVoxelLimit.GetMinXExtent() ;
}
if (xMax > pVoxelLimit.GetMaxXExtent())
{
xMax = pVoxelLimit.GetMaxXExtent() ;
}
}
}
yoffset = pTransform.NetTranslation().y();
yMin = yoffset - fRmax - fRtor ;
yMax = yoffset + fRmax + fRtor ;
if (pVoxelLimit.IsYLimited())
{
if ( (yMin > pVoxelLimit.GetMaxYExtent()+kCarTolerance)
|| (yMax < pVoxelLimit.GetMinYExtent()-kCarTolerance) )
{
return false ;
}
else
{
if (yMin < pVoxelLimit.GetMinYExtent() )
{
yMin = pVoxelLimit.GetMinYExtent() ;
}
if (yMax > pVoxelLimit.GetMaxYExtent() )
{
yMax = pVoxelLimit.GetMaxYExtent() ;
}
}
}
zoffset = pTransform.NetTranslation().z() ;
zMin = zoffset - fRmax ;
zMax = zoffset + fRmax ;
if (pVoxelLimit.IsZLimited())
{
if ( (zMin > pVoxelLimit.GetMaxZExtent()+kCarTolerance)
|| (zMax < pVoxelLimit.GetMinZExtent()-kCarTolerance) )
{
return false ;
}
else
{
if (zMin < pVoxelLimit.GetMinZExtent() )
{
zMin = pVoxelLimit.GetMinZExtent() ;
}
if (zMax > pVoxelLimit.GetMaxZExtent() )
{
zMax = pVoxelLimit.GetMaxZExtent() ;
}
}
}
// Known to cut cylinder
switch (pAxis)
{
case kXAxis:
yoff1=yoffset-yMin;
yoff2=yMax-yoffset;
if ( yoff1 >= 0 && yoff2 >= 0 )
{
// Y limits cross max/min x => no change
//
pMin = xMin ;
pMax = xMax ;
}
else
{
// Y limits don't cross max/min x => compute max delta x,
// hence new mins/maxs
//
RTorus=fRmax+fRtor;
delta = RTorus*RTorus - yoff1*yoff1;
diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
delta = RTorus*RTorus - yoff2*yoff2;
diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
maxDiff = (diff1 > diff2) ? diff1:diff2 ;
newMin = xoffset - maxDiff ;
newMax = xoffset + maxDiff ;
pMin = (newMin < xMin) ? xMin : newMin ;
pMax = (newMax > xMax) ? xMax : newMax ;
}
break;
case kYAxis:
xoff1 = xoffset - xMin ;
xoff2 = xMax - xoffset ;
if (xoff1 >= 0 && xoff2 >= 0 )
{
// X limits cross max/min y => no change
//
pMin = yMin ;
pMax = yMax ;
}
else
{
// X limits don't cross max/min y => compute max delta y,
// hence new mins/maxs
//
RTorus=fRmax+fRtor;
delta = RTorus*RTorus - xoff1*xoff1;
diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
delta = RTorus*RTorus - xoff2*xoff2;
diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
maxDiff = (diff1 > diff2) ? diff1 : diff2 ;
newMin = yoffset - maxDiff ;
newMax = yoffset + maxDiff ;
pMin = (newMin < yMin) ? yMin : newMin ;
pMax = (newMax > yMax) ? yMax : newMax ;
}
break;
case kZAxis:
pMin=zMin;
pMax=zMax;
break;
default:
break;
}
pMin -= kCarTolerance ;
pMax += kCarTolerance ;
return true;
return exist = (pMin < pMax) ? true : false;
}
else
// Get parameters of the solid
G4double rmin = GetRmin();
G4double rmax = GetRmax();
G4double rtor = GetRtor();
G4double dphi = GetDPhi();
G4double sinStart = GetSinStartPhi();
G4double cosStart = GetCosStartPhi();
G4double sinEnd = GetSinEndPhi();
G4double cosEnd = GetCosEndPhi();
G4double rint = rtor - rmax;
G4double rext = rtor + rmax;
// Find bounding envelope and calculate extent
//
static const G4int NPHI = 24; // number of steps for whole torus
static const G4int NDISK = 16; // number of steps for disk
static const G4double sinHalfDisk = std::sin(pi/NDISK);
static const G4double cosHalfDisk = std::cos(pi/NDISK);
static const G4double sinStepDisk = 2.*sinHalfDisk*cosHalfDisk;
static const G4double cosStepDisk = 1. - 2.*sinHalfDisk*sinHalfDisk;
G4double astep = (360/NPHI)*deg; // max angle for one slice in phi
G4int kphi = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1;
G4double ang = dphi/kphi;
G4double sinHalf = std::sin(0.5*ang);
G4double cosHalf = std::cos(0.5*ang);
G4double sinStep = 2.*sinHalf*cosHalf;
G4double cosStep = 1. - 2.*sinHalf*sinHalf;
// define vectors for bounding envelope
G4ThreeVectorList pols[NDISK+1];
for (G4int k=0; k<NDISK+1; ++k) pols[k].resize(4);
std::vector<const G4ThreeVectorList *> polygons;
polygons.resize(NDISK+1);
for (G4int k=0; k<NDISK+1; ++k) polygons[k] = &pols[k];
// set internal and external reference circles
G4TwoVector rzmin[NDISK];
G4TwoVector rzmax[NDISK];
if ((rtor-rmin*sinHalfDisk)/cosHalf > (rtor+rmin*sinHalfDisk)) rmin = 0;
rmax /= cosHalfDisk;
G4double sinCurDisk = sinHalfDisk;
G4double cosCurDisk = cosHalfDisk;
for (G4int k=0; k<NDISK; ++k)
{
G4int i, noEntries, noBetweenSections4 ;
G4bool existsAfterClip = false ;
G4double rmincur = rtor + rmin*cosCurDisk;
if (cosCurDisk < 0 && rmin > 0) rmincur /= cosHalf;
rzmin[k].set(rmincur,rmin*sinCurDisk);
// Calculate rotated vertex coordinates
G4double rmaxcur = rtor + rmax*cosCurDisk;
if (cosCurDisk > 0) rmaxcur /= cosHalf;
rzmax[k].set(rmaxcur,rmax*sinCurDisk);
G4ThreeVectorList *vertices ;
G4int noPolygonVertices ; // will be 4
vertices = CreateRotatedVertices(pTransform,noPolygonVertices) ;
G4double sinTmpDisk = sinCurDisk;
sinCurDisk = sinCurDisk*cosStepDisk + cosCurDisk*sinStepDisk;
cosCurDisk = cosCurDisk*cosStepDisk - sinTmpDisk*sinStepDisk;
}
pMin = +kInfinity ;
pMax = -kInfinity ;
noEntries = vertices->size() ;
noBetweenSections4 = noEntries - noPolygonVertices ;
for (i=0;i<noEntries;i+=noPolygonVertices)
// Loop along slices in Phi. The extent is calculated as cumulative
// extent of the slices
pMin = kInfinity;
pMax = -kInfinity;
G4double eminlim = pVoxelLimit.GetMinExtent(pAxis);
G4double emaxlim = pVoxelLimit.GetMaxExtent(pAxis);
G4double sinCur1 = 0, cosCur1 = 0, sinCur2 = 0, cosCur2 = 0;
for (G4int i=0; i<kphi+1; ++i)
{
if (i == 0)
{
ClipCrossSection(vertices,i,pVoxelLimit,pAxis,pMin,pMax);
}
for (i=0;i<noBetweenSections4;i+=noPolygonVertices)
{
ClipBetweenSections(vertices,i,pVoxelLimit,pAxis,pMin,pMax);
}
if (pMin!=kInfinity||pMax!=-kInfinity)
{
existsAfterClip = true ; // Add 2*tolerance to avoid precision troubles
pMin -= kCarTolerance ;
pMax += kCarTolerance ;
sinCur1 = sinStart;
cosCur1 = cosStart;
sinCur2 = sinCur1*cosHalf + cosCur1*sinHalf;
cosCur2 = cosCur1*cosHalf - sinCur1*sinHalf;
}
else
{
// Check for case where completely enveloping clipping volume
// If point inside then we are confident that the solid completely
// envelopes the clipping volume. Hence set min/max extents according
// to clipping volume extents along the specified axis.
G4ThreeVector clipCentre(
(pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
(pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
(pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5 ) ;
if (Inside(pTransform.Inverse().TransformPoint(clipCentre)) != kOutside )
{
existsAfterClip = true ;
pMin = pVoxelLimit.GetMinExtent(pAxis) ;
pMax = pVoxelLimit.GetMaxExtent(pAxis) ;
}
sinCur1 = sinCur2;
cosCur1 = cosCur2;
sinCur2 = (i == kphi) ? sinEnd : sinCur1*cosStep + cosCur1*sinStep;
cosCur2 = (i == kphi) ? cosEnd : cosCur1*cosStep - sinCur1*sinStep;
}
delete vertices;
return existsAfterClip;
for (G4int k=0; k<NDISK; ++k)
{
G4double r1 = rzmin[k].x(), r2 = rzmax[k].x();
G4double z1 = rzmin[k].y(), z2 = rzmax[k].y();
pols[k][0].set(r1*cosCur1,r1*sinCur1,z1);
pols[k][1].set(r2*cosCur1,r2*sinCur1,z2);
pols[k][2].set(r2*cosCur2,r2*sinCur2,z2);
pols[k][3].set(r1*cosCur2,r1*sinCur2,z1);
}
pols[NDISK] = pols[0];
// get bounding box of current slice
G4TwoVector vmin,vmax;
G4GeomTools::
DiskExtent(rint,rext,sinCur1,cosCur1,sinCur2,cosCur2,vmin,vmax);
bmin.setX(vmin.x()); bmin.setY(vmin.y());
bmax.setX(vmax.x()); bmax.setY(vmax.y());
// set bounding envelope for current slice and adjust extent
G4double emin,emax;
G4BoundingEnvelope benv(bmin,bmax,polygons);
if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax)) continue;
if (emin < pMin) pMin = emin;
if (emax > pMax) pMax = emax;
if (eminlim > pMin && emaxlim < pMax) break; // max possible extent
}
return (pMin < pMax);
}
//////////////////////////////////////////////////////////////////////////////
@@ -854,7 +820,7 @@ G4ThreeVector G4Torus::SurfaceNormal( const G4ThreeVector& p ) const
{
G4Exception("G4Torus::SurfaceNormal(p)", "GeomSolids1002",
JustWarning, ed,
"Failing to find normal, even though point is on surface!" );
"Failing to find normal, even though point is on surface!");
}
else
{
@@ -869,8 +835,6 @@ G4ThreeVector G4Torus::SurfaceNormal( const G4ThreeVector& p ) const
else if ( noSurfaces == 1 ) { norm = sumnorm; }
else { norm = sumnorm.unit(); }
// G4cout << "G4Torus::SurfaceNormal p= " << p << " returns norm= " << norm << G4endl;
return norm ;
}
@@ -1600,92 +1564,6 @@ G4double G4Torus::DistanceToOut( const G4ThreeVector& p ) const
return safe ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Create a List containing the transformed vertices
// Ordering [0-3] -fRtor cross section
// [4-7] +fRtor cross section such that [0] is below [4],
// [1] below [5] etc.
// Note:
// Caller has deletion resposibility
// Potential improvement: For last slice, use actual ending angle
// to avoid rounding error problems.
G4ThreeVectorList*
G4Torus::CreateRotatedVertices( const G4AffineTransform& pTransform,
G4int& noPolygonVertices ) const
{
G4ThreeVectorList *vertices;
G4ThreeVector vertex0,vertex1,vertex2,vertex3;
G4double meshAngle,meshRMax,crossAngle,cosCrossAngle,sinCrossAngle,sAngle;
G4double rMaxX,rMaxY,rMinX,rMinY;
G4int crossSection,noCrossSections;
// Compute no of cross-sections necessary to mesh tube
//
noCrossSections = G4int (fDPhi/kMeshAngleDefault) + 1 ;
if (noCrossSections < kMinMeshSections)
{
noCrossSections = kMinMeshSections ;
}
else if (noCrossSections>kMaxMeshSections)
{
noCrossSections=kMaxMeshSections;
}
meshAngle = fDPhi/(noCrossSections - 1) ;
meshRMax = (fRtor + fRmax)/std::cos(meshAngle*0.5) ;
// If complete in phi, set start angle such that mesh will be at fRmax
// on the x axis. Will give better extent calculations when not rotated
if ( (fDPhi == twopi) && (fSPhi == 0) )
{
sAngle = -meshAngle*0.5 ;
}
else
{
sAngle = fSPhi ;
}
vertices = new G4ThreeVectorList();
if (vertices)
{
vertices->reserve(noCrossSections*4) ;
for (crossSection=0;crossSection<noCrossSections;crossSection++)
{
// Compute coordinates of cross section at section crossSection
crossAngle=sAngle+crossSection*meshAngle;
cosCrossAngle=std::cos(crossAngle);
sinCrossAngle=std::sin(crossAngle);
rMaxX=meshRMax*cosCrossAngle;
rMaxY=meshRMax*sinCrossAngle;
rMinX=(fRtor-fRmax)*cosCrossAngle;
rMinY=(fRtor-fRmax)*sinCrossAngle;
vertex0=G4ThreeVector(rMinX,rMinY,-fRmax);
vertex1=G4ThreeVector(rMaxX,rMaxY,-fRmax);
vertex2=G4ThreeVector(rMaxX,rMaxY,+fRmax);
vertex3=G4ThreeVector(rMinX,rMinY,+fRmax);
vertices->push_back(pTransform.TransformPoint(vertex0));
vertices->push_back(pTransform.TransformPoint(vertex1));
vertices->push_back(pTransform.TransformPoint(vertex2));
vertices->push_back(pTransform.TransformPoint(vertex3));
}
noPolygonVertices = 4 ;
}
else
{
DumpInfo();
G4Exception("G4Torus::CreateRotatedVertices()",
"GeomSolids0003", FatalException,
"Error in allocation of vertices. Out of memory !");
}
return vertices;
}
//////////////////////////////////////////////////////////////////////////
//
// Stream object contents to an output stream
@@ -1735,8 +1613,8 @@ G4ThreeVector G4Torus::GetPointOnSurface() const
{
G4double cosu, sinu,cosv, sinv, aOut, aIn, aSide, chose, phi, theta, rRand;
phi = RandFlat::shoot(fSPhi,fSPhi+fDPhi);
theta = RandFlat::shoot(0.,twopi);
phi = G4RandFlat::shoot(fSPhi,fSPhi+fDPhi);
theta = G4RandFlat::shoot(0.,twopi);
cosu = std::cos(phi); sinu = std::sin(phi);
cosv = std::cos(theta); sinv = std::sin(theta);
@@ -1748,7 +1626,7 @@ G4ThreeVector G4Torus::GetPointOnSurface() const
aSide = pi*(fRmax*fRmax-fRmin*fRmin);
if ((fSPhi == 0) && (fDPhi == twopi)){ aSide = 0; }
chose = RandFlat::shoot(0.,aOut + aIn + 2.*aSide);
chose = G4RandFlat::shoot(0.,aOut + aIn + 2.*aSide);
if(chose < aOut)
{
+102 -338
View File
@@ -24,7 +24,7 @@
// ********************************************************************
//
//
// $Id: G4Trap.cc 83851 2014-09-19 10:12:12Z gcosmo $
// $Id: G4Trap.cc 101121 2016-11-07 09:18:01Z gcosmo $
//
// class G4Trap
//
@@ -32,6 +32,9 @@
//
// History:
//
// 23.09.16 E.Tcherniaev: added Extent(pmin,pmax),
// use G4BoundingEnvelope for CalculateExtent(),
// removed CreateRotatedVertices()
// 28.04.05 V.Grichine: new SurfaceNormal according to J. Apostolakis proposal
// 26.04.05 V.Grichine: new SurfaceNormal is default
// 19.04.05 V.Grichine: bug fixed in G4Trap("name",G4ThreeVector[8] vp)
@@ -55,6 +58,7 @@
#include "G4VoxelLimits.hh"
#include "G4AffineTransform.hh"
#include "G4BoundingEnvelope.hh"
#include "G4VPVParameterisation.hh"
@@ -809,6 +813,52 @@ void G4Trap::ComputeDimensions( G4VPVParameterisation* p,
p->ComputeDimensions(*this,n,pRep);
}
////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4Trap::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
G4double dz = GetZHalfLength();
G4double dx1 = GetXHalfLength1();
G4double dx2 = GetXHalfLength2();
G4double dx3 = GetXHalfLength3();
G4double dx4 = GetXHalfLength4();
G4double dy1 = GetYHalfLength1();
G4double dy2 = GetYHalfLength2();
G4double x0 = dz*fTthetaCphi;
G4double x1 = dy1*GetTanAlpha1();
G4double x2 = dy2*GetTanAlpha2();
G4double xmin =
std::min(
std::min(
std::min(-x0-x1-dx1,-x0+x1-dx2),x0-x2-dx3),x0+x2-dx4);
G4double xmax =
std::max(
std::max(
std::max(-x0-x1+dx1,-x0+x1+dx2),x0-x2+dx3),x0+x2+dx4);
G4double y0 = dz*fTthetaSphi;
G4double ymin = std::min(-y0-dy1,y0-dy2);
G4double ymax = std::max(-y0+dy1,y0+dy2);
pMin.set(xmin,ymin,-dz);
pMax.set(xmax,ymax, dz);
// 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("G4Trap::Extent()", "GeomMgt0001", JustWarning, message);
DumpInfo();
}
}
////////////////////////////////////////////////////////////////////////
//
@@ -819,288 +869,55 @@ G4bool G4Trap::CalculateExtent( const EAxis pAxis,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax) const
{
G4double xMin, xMax, yMin, yMax, zMin, zMax;
G4bool flag;
G4ThreeVector bmin, bmax;
G4bool exist;
if (!pTransform.IsRotated())
{
// Special case handling for unrotated trapezoids
// Compute z/x/y/ mins and maxs respecting limits, with early returns
// if outside limits. Then switch() on pAxis
G4int i ;
G4double xoffset;
G4double yoffset;
G4double zoffset;
G4double temp[8] ; // some points for intersection with zMin/zMax
G4ThreeVector pt[8]; // vertices after translation
xoffset=pTransform.NetTranslation().x();
yoffset=pTransform.NetTranslation().y();
zoffset=pTransform.NetTranslation().z();
pt[0]=G4ThreeVector(xoffset-fDz*fTthetaCphi-fDy1*fTalpha1-fDx1,
yoffset-fDz*fTthetaSphi-fDy1,zoffset-fDz);
pt[1]=G4ThreeVector(xoffset-fDz*fTthetaCphi-fDy1*fTalpha1+fDx1,
yoffset-fDz*fTthetaSphi-fDy1,zoffset-fDz);
pt[2]=G4ThreeVector(xoffset-fDz*fTthetaCphi+fDy1*fTalpha1-fDx2,
yoffset-fDz*fTthetaSphi+fDy1,zoffset-fDz);
pt[3]=G4ThreeVector(xoffset-fDz*fTthetaCphi+fDy1*fTalpha1+fDx2,
yoffset-fDz*fTthetaSphi+fDy1,zoffset-fDz);
pt[4]=G4ThreeVector(xoffset+fDz*fTthetaCphi-fDy2*fTalpha2-fDx3,
yoffset+fDz*fTthetaSphi-fDy2,zoffset+fDz);
pt[5]=G4ThreeVector(xoffset+fDz*fTthetaCphi-fDy2*fTalpha2+fDx3,
yoffset+fDz*fTthetaSphi-fDy2,zoffset+fDz);
pt[6]=G4ThreeVector(xoffset+fDz*fTthetaCphi+fDy2*fTalpha2-fDx4,
yoffset+fDz*fTthetaSphi+fDy2,zoffset+fDz);
pt[7]=G4ThreeVector(xoffset+fDz*fTthetaCphi+fDy2*fTalpha2+fDx4,
yoffset+fDz*fTthetaSphi+fDy2,zoffset+fDz);
zMin=zoffset-fDz;
zMax=zoffset+fDz;
if ( pVoxelLimit.IsZLimited() )
{
if ( (zMin > pVoxelLimit.GetMaxZExtent() + kCarTolerance)
|| (zMax < pVoxelLimit.GetMinZExtent() - kCarTolerance) )
{
return false;
}
else
{
if ( zMin < pVoxelLimit.GetMinZExtent() )
{
zMin = pVoxelLimit.GetMinZExtent() ;
}
if ( zMax > pVoxelLimit.GetMaxZExtent() )
{
zMax = pVoxelLimit.GetMaxZExtent() ;
}
}
}
temp[0] = pt[0].y()+(pt[4].y()-pt[0].y())*(zMin-pt[0].z())
/(pt[4].z()-pt[0].z()) ;
temp[1] = pt[0].y()+(pt[4].y()-pt[0].y())*(zMax-pt[0].z())
/(pt[4].z()-pt[0].z()) ;
temp[2] = pt[2].y()+(pt[6].y()-pt[2].y())*(zMin-pt[2].z())
/(pt[6].z()-pt[2].z()) ;
temp[3] = pt[2].y()+(pt[6].y()-pt[2].y())*(zMax-pt[2].z())
/(pt[6].z()-pt[2].z()) ;
yMax = yoffset - std::fabs(fDz*fTthetaSphi) - fDy1 - fDy2 ;
yMin = -yMax ;
for( i = 0 ; i < 4 ; i++ )
{
if( temp[i] > yMax ) yMax = temp[i] ;
if( temp[i] < yMin ) yMin = temp[i] ;
}
if ( pVoxelLimit.IsYLimited() )
{
if ( (yMin > pVoxelLimit.GetMaxYExtent() + kCarTolerance)
|| (yMax < pVoxelLimit.GetMinYExtent() - kCarTolerance) )
{
return false;
}
else
{
if ( yMin < pVoxelLimit.GetMinYExtent() )
{
yMin = pVoxelLimit.GetMinYExtent() ;
}
if ( yMax > pVoxelLimit.GetMaxYExtent() )
{
yMax = pVoxelLimit.GetMaxYExtent() ;
}
}
}
temp[0] = pt[0].x()+(pt[4].x()-pt[0].x())
*(zMin-pt[0].z())/(pt[4].z()-pt[0].z()) ;
temp[1] = pt[0].x()+(pt[4].x()-pt[0].x())
*(zMax-pt[0].z())/(pt[4].z()-pt[0].z()) ;
temp[2] = pt[2].x()+(pt[6].x()-pt[2].x())
*(zMin-pt[2].z())/(pt[6].z()-pt[2].z()) ;
temp[3] = pt[2].x()+(pt[6].x()-pt[2].x())
*(zMax-pt[2].z())/(pt[6].z()-pt[2].z()) ;
temp[4] = pt[3].x()+(pt[7].x()-pt[3].x())
*(zMin-pt[3].z())/(pt[7].z()-pt[3].z()) ;
temp[5] = pt[3].x()+(pt[7].x()-pt[3].x())
*(zMax-pt[3].z())/(pt[7].z()-pt[3].z()) ;
temp[6] = pt[1].x()+(pt[5].x()-pt[1].x())
*(zMin-pt[1].z())/(pt[5].z()-pt[1].z()) ;
temp[7] = pt[1].x()+(pt[5].x()-pt[1].x())
*(zMax-pt[1].z())/(pt[5].z()-pt[1].z()) ;
xMax = xoffset - std::fabs(fDz*fTthetaCphi) - fDx1 - fDx2 -fDx3 - fDx4 ;
xMin = -xMax ;
for( i = 0 ; i < 8 ; i++ )
{
if( temp[i] > xMax) xMax = temp[i] ;
if( temp[i] < xMin) xMin = temp[i] ;
}
if (pVoxelLimit.IsXLimited()) // xMax/Min = f(yMax/Min) ?
{
if ( (xMin > pVoxelLimit.GetMaxXExtent() + kCarTolerance)
|| (xMax < pVoxelLimit.GetMinXExtent() - kCarTolerance) )
{
return false;
}
else
{
if ( xMin < pVoxelLimit.GetMinXExtent() )
{
xMin = pVoxelLimit.GetMinXExtent() ;
}
if ( xMax > pVoxelLimit.GetMaxXExtent() )
{
xMax = pVoxelLimit.GetMaxXExtent() ;
}
}
}
switch (pAxis)
{
case kXAxis:
pMin=xMin;
pMax=xMax;
break;
case kYAxis:
pMin=yMin;
pMax=yMax;
break;
case kZAxis:
pMin=zMin;
pMax=zMax;
break;
default:
break;
}
pMin -= kCarTolerance;
pMax += kCarTolerance;
flag = true;
}
else // General rotated case -
// Check bounding box (bbox)
//
Extent(bmin,bmax);
G4BoundingEnvelope bbox(bmin,bmax);
#ifdef G4BBOX_EXTENT
if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
#endif
if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
{
G4bool existsAfterClip = false ;
G4ThreeVectorList* vertices;
pMin = +kInfinity;
pMax = -kInfinity;
// Calculate rotated vertex coordinates. Operator 'new' is called
vertices = CreateRotatedVertices(pTransform);
xMin = +kInfinity; yMin = +kInfinity; zMin = +kInfinity;
xMax = -kInfinity; yMax = -kInfinity; zMax = -kInfinity;
for( G4int nv = 0 ; nv < 8 ; nv++ )
{
if( (*vertices)[nv].x() > xMax ) xMax = (*vertices)[nv].x();
if( (*vertices)[nv].y() > yMax ) yMax = (*vertices)[nv].y();
if( (*vertices)[nv].z() > zMax ) zMax = (*vertices)[nv].z();
if( (*vertices)[nv].x() < xMin ) xMin = (*vertices)[nv].x();
if( (*vertices)[nv].y() < yMin ) yMin = (*vertices)[nv].y();
if( (*vertices)[nv].z() < zMin ) zMin = (*vertices)[nv].z();
}
if ( pVoxelLimit.IsZLimited() )
{
if ( (zMin > pVoxelLimit.GetMaxZExtent() + kCarTolerance)
|| (zMax < pVoxelLimit.GetMinZExtent() - kCarTolerance) )
{
delete vertices ; // 'new' in the function called
return false;
}
else
{
if ( zMin < pVoxelLimit.GetMinZExtent() )
{
zMin = pVoxelLimit.GetMinZExtent() ;
}
if ( zMax > pVoxelLimit.GetMaxZExtent() )
{
zMax = pVoxelLimit.GetMaxZExtent() ;
}
}
}
if ( pVoxelLimit.IsYLimited() )
{
if ( (yMin > pVoxelLimit.GetMaxYExtent() + kCarTolerance)
|| (yMax < pVoxelLimit.GetMinYExtent() - kCarTolerance) )
{
delete vertices ; // 'new' in the function called
return false;
}
else
{
if ( yMin < pVoxelLimit.GetMinYExtent() )
{
yMin = pVoxelLimit.GetMinYExtent() ;
}
if ( yMax > pVoxelLimit.GetMaxYExtent() )
{
yMax = pVoxelLimit.GetMaxYExtent() ;
}
}
}
if ( pVoxelLimit.IsXLimited() )
{
if ( (xMin > pVoxelLimit.GetMaxXExtent() + kCarTolerance)
|| (xMax < pVoxelLimit.GetMinXExtent() - kCarTolerance) )
{
delete vertices ; // 'new' in the function called
return false ;
}
else
{
if ( xMin < pVoxelLimit.GetMinXExtent() )
{
xMin = pVoxelLimit.GetMinXExtent() ;
}
if ( xMax > pVoxelLimit.GetMaxXExtent() )
{
xMax = pVoxelLimit.GetMaxXExtent() ;
}
}
}
switch (pAxis)
{
case kXAxis:
pMin=xMin;
pMax=xMax;
break;
case kYAxis:
pMin=yMin;
pMax=yMax;
break;
case kZAxis:
pMin=zMin;
pMax=zMax;
break;
default:
break;
}
if ( (pMin != kInfinity) || (pMax != -kInfinity) )
{
existsAfterClip=true;
// Add tolerance to avoid precision troubles
//
pMin -= kCarTolerance ;
pMax += kCarTolerance ;
}
delete vertices ; // 'new' in the function called
flag = existsAfterClip ;
return exist = (pMin < pMax) ? true : false;
}
return flag;
}
// Set bounding envelope (benv) and calculate extent
//
G4double dz = GetZHalfLength();
G4double dx1 = GetXHalfLength1();
G4double dx2 = GetXHalfLength2();
G4double dx3 = GetXHalfLength3();
G4double dx4 = GetXHalfLength4();
G4double dy1 = GetYHalfLength1();
G4double dy2 = GetYHalfLength2();
G4double x0 = dz*fTthetaCphi;
G4double x1 = dy1*GetTanAlpha1();
G4double x2 = dy2*GetTanAlpha2();
G4double y0 = dz*fTthetaSphi;
G4ThreeVectorList baseA(4), baseB(4);
baseA[0].set(-x0-x1-dx1,-y0-dy1,-dz);
baseA[1].set(-x0-x1+dx1,-y0-dy1,-dz);
baseA[2].set(-x0+x1+dx2,-y0+dy1,-dz);
baseA[3].set(-x0+x1-dx2,-y0+dy1,-dz);
baseB[0].set( x0-x2-dx3, y0-dy2, dz);
baseB[1].set( x0-x2+dx3, y0-dy2, dz);
baseB[2].set( x0+x2+dx4, y0+dy2, dz);
baseB[3].set( x0+x2-dx4, y0+dy2, dz);
std::vector<const G4ThreeVectorList *> polygons(2);
polygons[0] = &baseA;
polygons[1] = &baseB;
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
return exist;
}
////////////////////////////////////////////////////////////////////////
//
@@ -1740,59 +1557,6 @@ G4double G4Trap::DistanceToOut( const G4ThreeVector& p ) const
return safe;
}
//////////////////////////////////////////////////////////////////////////
//
// Create a List containing the transformed vertices
// Ordering [0-3] -fDz cross section
// [4-7] +fDz cross section such that [0] is below [4],
// [1] below [5] etc.
// Note:
// Caller has deletion resposibility
G4ThreeVectorList*
G4Trap::CreateRotatedVertices( const G4AffineTransform& pTransform ) const
{
G4ThreeVectorList *vertices;
vertices=new G4ThreeVectorList();
if (vertices)
{
vertices->reserve(8);
G4ThreeVector vertex0(-fDz*fTthetaCphi-fDy1*fTalpha1-fDx1,
-fDz*fTthetaSphi-fDy1,-fDz);
G4ThreeVector vertex1(-fDz*fTthetaCphi-fDy1*fTalpha1+fDx1,
-fDz*fTthetaSphi-fDy1,-fDz);
G4ThreeVector vertex2(-fDz*fTthetaCphi+fDy1*fTalpha1-fDx2,
-fDz*fTthetaSphi+fDy1,-fDz);
G4ThreeVector vertex3(-fDz*fTthetaCphi+fDy1*fTalpha1+fDx2,
-fDz*fTthetaSphi+fDy1,-fDz);
G4ThreeVector vertex4(+fDz*fTthetaCphi-fDy2*fTalpha2-fDx3,
+fDz*fTthetaSphi-fDy2,+fDz);
G4ThreeVector vertex5(+fDz*fTthetaCphi-fDy2*fTalpha2+fDx3,
+fDz*fTthetaSphi-fDy2,+fDz);
G4ThreeVector vertex6(+fDz*fTthetaCphi+fDy2*fTalpha2-fDx4,
+fDz*fTthetaSphi+fDy2,+fDz);
G4ThreeVector vertex7(+fDz*fTthetaCphi+fDy2*fTalpha2+fDx4,
+fDz*fTthetaSphi+fDy2,+fDz);
vertices->push_back(pTransform.TransformPoint(vertex0));
vertices->push_back(pTransform.TransformPoint(vertex1));
vertices->push_back(pTransform.TransformPoint(vertex2));
vertices->push_back(pTransform.TransformPoint(vertex3));
vertices->push_back(pTransform.TransformPoint(vertex4));
vertices->push_back(pTransform.TransformPoint(vertex5));
vertices->push_back(pTransform.TransformPoint(vertex6));
vertices->push_back(pTransform.TransformPoint(vertex7));
}
else
{
DumpInfo();
G4Exception("G4Trap::CreateRotatedVertices()",
"GeomSolids0003", FatalException,
"Error in allocation of vertices. Out of memory !");
}
return vertices;
}
//////////////////////////////////////////////////////////////////////////
//
// GetEntityType
@@ -1881,19 +1645,19 @@ G4ThreeVector G4Trap::GetPointOnPlane(G4ThreeVector p0, G4ThreeVector p1,
area = aOne + aTwo;
chose = RandFlat::shoot(0.,aOne+aTwo);
chose = G4RandFlat::shoot(0.,aOne+aTwo);
if( (chose>=0.) && (chose < aOne) )
{
lambda1 = RandFlat::shoot(0.,1.);
lambda2 = RandFlat::shoot(0.,lambda1);
lambda1 = G4RandFlat::shoot(0.,1.);
lambda2 = G4RandFlat::shoot(0.,lambda1);
return (p2+lambda1*v+lambda2*w);
}
// else
lambda1 = RandFlat::shoot(0.,1.);
lambda2 = RandFlat::shoot(0.,lambda1);
lambda1 = G4RandFlat::shoot(0.,1.);
lambda2 = G4RandFlat::shoot(0.,lambda1);
return (p0+lambda1*t+lambda2*u);
}
@@ -1934,7 +1698,7 @@ G4ThreeVector G4Trap::GetPointOnSurface() const
Five = GetPointOnPlane(pt[0],pt[2],pt[6],pt[4], aFive);
Six = GetPointOnPlane(pt[1],pt[3],pt[7],pt[5], aSix);
chose = RandFlat::shoot(0.,aOne+aTwo+aThree+aFour+aFive+aSix);
chose = G4RandFlat::shoot(0.,aOne+aTwo+aThree+aFour+aFive+aSix);
if( (chose>=0.) && (chose<aOne) )
{ return One; }
else if( (chose>=aOne) && (chose<aOne+aTwo) )
+71 -208
View File
@@ -24,13 +24,16 @@
// ********************************************************************
//
//
// $Id: G4Trd.cc 83572 2014-09-01 15:23:27Z gcosmo $
// $Id: G4Trd.cc 101121 2016-11-07 09:18:01Z gcosmo $
//
//
// Implementation for G4Trd class
//
// History:
//
// 23.09.16 E.Tcherniaev: added Extent(pmin,pmax),
// use G4BoundingEnvelope for CalculateExtent(),
// removed CreateRotatedVertices()
// 28.04.05 V.Grichine: new SurfaceNormal according to J. Apostolakis proposal
// 26.04.05, V.Grichine, new SurfaceNoramal is default
// 07.12.04, V.Grichine, SurfaceNoramal with edges/vertices.
@@ -43,11 +46,13 @@
#if !defined(G4GEOM_USE_UTRD)
#include "G4VPVParameterisation.hh"
#include "G4VoxelLimits.hh"
#include "G4AffineTransform.hh"
#include "G4BoundingEnvelope.hh"
#include "Randomize.hh"
#include "G4VPVParameterisation.hh"
#include "G4VGraphicsScene.hh"
using namespace CLHEP;
@@ -184,6 +189,36 @@ void G4Trd::ComputeDimensions( G4VPVParameterisation* p,
p->ComputeDimensions(*this,n,pRep);
}
////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4Trd::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
G4double dx1 = GetXHalfLength1();
G4double dx2 = GetXHalfLength2();
G4double dy1 = GetYHalfLength1();
G4double dy2 = GetYHalfLength2();
G4double dz = GetZHalfLength();
G4double xmax = std::max(dx1,dx2);
G4double ymax = std::max(dy1,dy2);
pMin.set(-xmax,-ymax,-dz);
pMax.set( xmax, ymax, dz);
// 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("G4Trd::Extent()", "GeomMgt0001", JustWarning, message);
DumpInfo();
}
}
///////////////////////////////////////////////////////////////////////////
//
@@ -194,173 +229,46 @@ G4bool G4Trd::CalculateExtent( const EAxis pAxis,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax ) const
{
if (!pTransform.IsRotated())
G4ThreeVector bmin, bmax;
G4bool exist;
// Check bounding box (bbox)
//
Extent(bmin,bmax);
G4BoundingEnvelope bbox(bmin,bmax);
#ifdef G4BBOX_EXTENT
if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
#endif
if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
{
// Special case handling for unrotated solids
// Compute x/y/z mins and maxs respecting limits, with early returns
// if outside limits. Then switch() on pAxis
G4double xoffset,xMin,xMax;
G4double yoffset,yMin,yMax;
G4double zoffset,zMin,zMax;
zoffset=pTransform.NetTranslation().z();
zMin=zoffset-fDz;
zMax=zoffset+fDz;
if (pVoxelLimit.IsZLimited())
{
if ( (zMin>pVoxelLimit.GetMaxZExtent()+kCarTolerance)
|| (zMax<pVoxelLimit.GetMinZExtent()-kCarTolerance) )
{
return false;
}
else
{
if (zMin<pVoxelLimit.GetMinZExtent())
{
zMin=pVoxelLimit.GetMinZExtent();
}
if (zMax>pVoxelLimit.GetMaxZExtent())
{
zMax=pVoxelLimit.GetMaxZExtent();
}
}
}
xoffset=pTransform.NetTranslation().x();
if (fDx2 >= fDx1)
{
xMax = xoffset+(fDx1+fDx2)/2+(zMax-zoffset)*(fDx2-fDx1)/(2*fDz) ;
xMin = 2*xoffset - xMax ;
}
else
{
xMax = xoffset+(fDx1+fDx2)/2+(zMin-zoffset)*(fDx2-fDx1)/(2*fDz) ;
xMin = 2*xoffset - xMax ;
}
if (pVoxelLimit.IsXLimited())
{
if ( (xMin>pVoxelLimit.GetMaxXExtent()+kCarTolerance)
|| (xMax<pVoxelLimit.GetMinXExtent()-kCarTolerance) )
{
return false;
}
else
{
if (xMin<pVoxelLimit.GetMinXExtent())
{
xMin=pVoxelLimit.GetMinXExtent();
}
if (xMax>pVoxelLimit.GetMaxXExtent())
{
xMax=pVoxelLimit.GetMaxXExtent();
}
}
}
yoffset= pTransform.NetTranslation().y() ;
if(fDy2 >= fDy1)
{
yMax = yoffset+(fDy2+fDy1)/2+(zMax-zoffset)*(fDy2-fDy1)/(2*fDz) ;
yMin = 2*yoffset - yMax ;
}
else
{
yMax = yoffset+(fDy2+fDy1)/2+(zMin-zoffset)*(fDy2-fDy1)/(2*fDz) ;
yMin = 2*yoffset - yMax ;
}
if (pVoxelLimit.IsYLimited())
{
if ( (yMin>pVoxelLimit.GetMaxYExtent()+kCarTolerance)
|| (yMax<pVoxelLimit.GetMinYExtent()-kCarTolerance) )
{
return false;
}
else
{
if (yMin<pVoxelLimit.GetMinYExtent())
{
yMin=pVoxelLimit.GetMinYExtent();
}
if (yMax>pVoxelLimit.GetMaxYExtent())
{
yMax=pVoxelLimit.GetMaxYExtent();
}
}
}
switch (pAxis)
{
case kXAxis:
pMin=xMin;
pMax=xMax;
break;
case kYAxis:
pMin=yMin;
pMax=yMax;
break;
case kZAxis:
pMin=zMin;
pMax=zMax;
break;
default:
break;
}
// Add 2*Tolerance to avoid precision troubles ?
//
pMin-=kCarTolerance;
pMax+=kCarTolerance;
return true;
return exist = (pMin < pMax) ? true : false;
}
else
{
// General rotated case - create and clip mesh to boundaries
G4bool existsAfterClip=false;
G4ThreeVectorList *vertices;
// Set bounding envelope (benv) and calculate extent
//
G4double dx1 = GetXHalfLength1();
G4double dx2 = GetXHalfLength2();
G4double dy1 = GetYHalfLength1();
G4double dy2 = GetYHalfLength2();
G4double dz = GetZHalfLength();
pMin=+kInfinity;
pMax=-kInfinity;
G4ThreeVectorList baseA(4), baseB(4);
baseA[0].set(-dx1,-dy1,-dz);
baseA[1].set( dx1,-dy1,-dz);
baseA[2].set( dx1, dy1,-dz);
baseA[3].set(-dx1, dy1,-dz);
baseB[0].set(-dx2,-dy2, dz);
baseB[1].set( dx2,-dy2, dz);
baseB[2].set( dx2, dy2, dz);
baseB[3].set(-dx2, dy2, dz);
// Calculate rotated vertex coordinates
//
vertices=CreateRotatedVertices(pTransform);
ClipCrossSection(vertices,0,pVoxelLimit,pAxis,pMin,pMax);
ClipCrossSection(vertices,4,pVoxelLimit,pAxis,pMin,pMax);
ClipBetweenSections(vertices,0,pVoxelLimit,pAxis,pMin,pMax);
if (pMin!=kInfinity||pMax!=-kInfinity)
{
existsAfterClip=true;
std::vector<const G4ThreeVectorList *> polygons(2);
polygons[0] = &baseA;
polygons[1] = &baseB;
// Add 2*tolerance to avoid precision troubles
//
pMin-=kCarTolerance;
pMax+=kCarTolerance;
}
else
{
// Check for case where completely enveloping clipping volume
// If point inside then we are confident that the solid completely
// envelopes the clipping volume. Hence set min/max extents according
// to clipping volume extents along the specified axis.
G4ThreeVector clipCentre(
(pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
(pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
(pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5);
if (Inside(pTransform.Inverse().TransformPoint(clipCentre))!=kOutside)
{
existsAfterClip=true;
pMin=pVoxelLimit.GetMinExtent(pAxis);
pMax=pVoxelLimit.GetMaxExtent(pAxis);
}
}
delete vertices;
return existsAfterClip;
}
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
return exist;
}
///////////////////////////////////////////////////////////////////
@@ -1305,51 +1213,6 @@ G4double G4Trd::DistanceToOut( const G4ThreeVector& p ) const
return safe;
}
////////////////////////////////////////////////////////////////////////////
//
// Create a List containing the transformed vertices
// Ordering [0-3] -fDz cross section
// [4-7] +fDz cross section such that [0] is below [4],
// [1] below [5] etc.
// Note:
// Caller has deletion resposibility
G4ThreeVectorList*
G4Trd::CreateRotatedVertices( const G4AffineTransform& pTransform ) const
{
G4ThreeVectorList *vertices;
vertices=new G4ThreeVectorList();
if (vertices)
{
vertices->reserve(8);
G4ThreeVector vertex0(-fDx1,-fDy1,-fDz);
G4ThreeVector vertex1(fDx1,-fDy1,-fDz);
G4ThreeVector vertex2(fDx1,fDy1,-fDz);
G4ThreeVector vertex3(-fDx1,fDy1,-fDz);
G4ThreeVector vertex4(-fDx2,-fDy2,fDz);
G4ThreeVector vertex5(fDx2,-fDy2,fDz);
G4ThreeVector vertex6(fDx2,fDy2,fDz);
G4ThreeVector vertex7(-fDx2,fDy2,fDz);
vertices->push_back(pTransform.TransformPoint(vertex0));
vertices->push_back(pTransform.TransformPoint(vertex1));
vertices->push_back(pTransform.TransformPoint(vertex2));
vertices->push_back(pTransform.TransformPoint(vertex3));
vertices->push_back(pTransform.TransformPoint(vertex4));
vertices->push_back(pTransform.TransformPoint(vertex5));
vertices->push_back(pTransform.TransformPoint(vertex6));
vertices->push_back(pTransform.TransformPoint(vertex7));
}
else
{
DumpInfo();
G4Exception("G4Trd::CreateRotatedVertices()",
"GeomSolids0003", FatalException,
"Error in allocation of vertices. Out of memory !");
}
return vertices;
}
//////////////////////////////////////////////////////////////////////////
//
// GetEntityType
+146 -298
View File
@@ -24,13 +24,15 @@
// ********************************************************************
//
//
// $Id: G4Tubs.cc 88373 2015-02-16 09:45:10Z gcosmo $
// $Id: G4Tubs.cc 101121 2016-11-07 09:18:01Z gcosmo $
//
//
// class G4Tubs
//
// History:
//
// 24.08.16 E.Tcherniaev: reimplemented CalculateExtent() to make use
// of G4BoundingEnvelope
// 05.04.12 M.Kelsey: Use sqrt(r) in GetPointOnSurface() for uniform points
// 02.08.07 T.Nikitina: bug fixed in DistanceToOut(p,v,..) for negative value under sqrt
// for the case: p on the surface and v is tangent to the surface
@@ -63,9 +65,11 @@
#if !defined(G4GEOM_USE_UTUBS)
#include "G4GeomTools.hh"
#include "G4VoxelLimits.hh"
#include "G4AffineTransform.hh"
#include "G4GeometryTolerance.hh"
#include "G4BoundingEnvelope.hh"
#include "G4VPVParameterisation.hh"
@@ -201,7 +205,49 @@ void G4Tubs::ComputeDimensions( G4VPVParameterisation* p,
p->ComputeDimensions(*this,n,pRep) ;
}
////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4Tubs::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
G4double rmin = GetInnerRadius();
G4double rmax = GetOuterRadius();
G4double dz = GetZHalfLength();
// Find bounding box
//
if (GetDeltaPhiAngle() < twopi)
{
G4TwoVector vmin,vmax;
G4GeomTools::DiskExtent(rmin,rmax,
GetSinStartPhi(),GetCosStartPhi(),
GetSinEndPhi(),GetCosEndPhi(),
vmin,vmax);
pMin.set(vmin.x(),vmin.y(),-dz);
pMax.set(vmax.x(),vmax.y(), dz);
}
else
{
pMin.set(-rmax,-rmax,-dz);
pMax.set( rmax, rmax, dz);
}
// 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("G4Tubs::Extent()", "GeomMgt0001", JustWarning, message);
DumpInfo();
}
}
/////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
@@ -211,210 +257,106 @@ G4bool G4Tubs::CalculateExtent( const EAxis pAxis,
G4double& pMin,
G4double& pMax ) const
{
G4ThreeVector bmin, bmax;
G4bool exist;
if ( (!pTransform.IsRotated()) && (fDPhi == twopi) && (fRMin == 0) )
// Get bounding box
Extent(bmin,bmax);
// Check bounding box
G4BoundingEnvelope bbox(bmin,bmax);
#ifdef G4BBOX_EXTENT
if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
#endif
if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
{
// Special case handling for unrotated solid tubes
// Compute x/y/z mins and maxs fro bounding box respecting limits,
// with early returns if outside limits. Then switch() on pAxis,
// and compute exact x and y limit for x/y case
G4double xoffset, xMin, xMax;
G4double yoffset, yMin, yMax;
G4double zoffset, zMin, zMax;
G4double diff1, diff2, maxDiff, newMin, newMax;
G4double xoff1, xoff2, yoff1, yoff2, delta;
xoffset = pTransform.NetTranslation().x();
xMin = xoffset - fRMax;
xMax = xoffset + fRMax;
if (pVoxelLimit.IsXLimited())
{
if ( (xMin > pVoxelLimit.GetMaxXExtent())
|| (xMax < pVoxelLimit.GetMinXExtent()) )
{
return false;
}
else
{
if (xMin < pVoxelLimit.GetMinXExtent())
{
xMin = pVoxelLimit.GetMinXExtent();
}
if (xMax > pVoxelLimit.GetMaxXExtent())
{
xMax = pVoxelLimit.GetMaxXExtent();
}
}
}
yoffset = pTransform.NetTranslation().y();
yMin = yoffset - fRMax;
yMax = yoffset + fRMax;
if ( pVoxelLimit.IsYLimited() )
{
if ( (yMin > pVoxelLimit.GetMaxYExtent())
|| (yMax < pVoxelLimit.GetMinYExtent()) )
{
return false;
}
else
{
if (yMin < pVoxelLimit.GetMinYExtent())
{
yMin = pVoxelLimit.GetMinYExtent();
}
if (yMax > pVoxelLimit.GetMaxYExtent())
{
yMax=pVoxelLimit.GetMaxYExtent();
}
}
}
zoffset = pTransform.NetTranslation().z();
zMin = zoffset - fDz;
zMax = zoffset + fDz;
if ( pVoxelLimit.IsZLimited() )
{
if ( (zMin > pVoxelLimit.GetMaxZExtent())
|| (zMax < pVoxelLimit.GetMinZExtent()) )
{
return false;
}
else
{
if (zMin < pVoxelLimit.GetMinZExtent())
{
zMin = pVoxelLimit.GetMinZExtent();
}
if (zMax > pVoxelLimit.GetMaxZExtent())
{
zMax = pVoxelLimit.GetMaxZExtent();
}
}
}
switch ( pAxis ) // Known to cut cylinder
{
case kXAxis :
{
yoff1 = yoffset - yMin;
yoff2 = yMax - yoffset;
if ( (yoff1 >= 0) && (yoff2 >= 0) ) // Y limits cross max/min x
{ // => no change
pMin = xMin;
pMax = xMax;
}
else
{
// Y limits don't cross max/min x => compute max delta x,
// hence new mins/maxs
delta = fRMax*fRMax - yoff1*yoff1;
diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
delta = fRMax*fRMax - yoff2*yoff2;
diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
maxDiff = (diff1 > diff2) ? diff1:diff2;
newMin = xoffset - maxDiff;
newMax = xoffset + maxDiff;
pMin = (newMin < xMin) ? xMin : newMin;
pMax = (newMax > xMax) ? xMax : newMax;
}
break;
}
case kYAxis :
{
xoff1 = xoffset - xMin;
xoff2 = xMax - xoffset;
if ( (xoff1 >= 0) && (xoff2 >= 0) ) // X limits cross max/min y
{ // => no change
pMin = yMin;
pMax = yMax;
}
else
{
// X limits don't cross max/min y => compute max delta y,
// hence new mins/maxs
delta = fRMax*fRMax - xoff1*xoff1;
diff1 = (delta>0.) ? std::sqrt(delta) : 0.;
delta = fRMax*fRMax - xoff2*xoff2;
diff2 = (delta>0.) ? std::sqrt(delta) : 0.;
maxDiff = (diff1 > diff2) ? diff1 : diff2;
newMin = yoffset - maxDiff;
newMax = yoffset + maxDiff;
pMin = (newMin < yMin) ? yMin : newMin;
pMax = (newMax > yMax) ? yMax : newMax;
}
break;
}
case kZAxis:
{
pMin = zMin;
pMax = zMax;
break;
}
default:
break;
}
pMin -= kCarTolerance;
pMax += kCarTolerance;
return true;
return exist = (pMin < pMax) ? true : false;
}
else // Calculate rotated vertex coordinates
// Get parameters of the solid
G4double rmin = GetInnerRadius();
G4double rmax = GetOuterRadius();
G4double dz = GetZHalfLength();
G4double dphi = GetDeltaPhiAngle();
// Find bounding envelope and calculate extent
//
const G4int NSTEPS = 24; // number of steps for whole circle
G4double astep = (360/NSTEPS)*deg; // max angle for one step
G4int ksteps = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1;
G4double ang = dphi/ksteps;
G4double sinHalf = std::sin(0.5*ang);
G4double cosHalf = std::cos(0.5*ang);
G4double sinStep = 2.*sinHalf*cosHalf;
G4double cosStep = 1. - 2.*sinHalf*sinHalf;
G4double rext = rmax/cosHalf;
// bounding envelope for full cylinder consists of two polygons,
// in other cases it is a sequence of quadrilaterals
if (rmin == 0 && dphi == twopi)
{
G4int i, noEntries, noBetweenSections4;
G4bool existsAfterClip = false;
G4ThreeVectorList* vertices = CreateRotatedVertices(pTransform);
G4double sinCur = sinHalf;
G4double cosCur = cosHalf;
pMin = kInfinity;
pMax = -kInfinity;
G4ThreeVectorList baseA(NSTEPS),baseB(NSTEPS);
for (G4int k=0; k<NSTEPS; ++k)
{
baseA[k].set(rext*cosCur,rext*sinCur,-dz);
baseB[k].set(rext*cosCur,rext*sinCur, dz);
noEntries = vertices->size();
noBetweenSections4 = noEntries - 4;
for ( i = 0 ; i < noEntries ; i += 4 )
{
ClipCrossSection(vertices, i, pVoxelLimit, pAxis, pMin, pMax);
G4double sinTmp = sinCur;
sinCur = sinCur*cosStep + cosCur*sinStep;
cosCur = cosCur*cosStep - sinTmp*sinStep;
}
for ( i = 0 ; i < noBetweenSections4 ; i += 4 )
{
ClipBetweenSections(vertices, i, pVoxelLimit, pAxis, pMin, pMax);
}
if ( (pMin != kInfinity) || (pMax != -kInfinity) )
{
existsAfterClip = true;
pMin -= kCarTolerance; // Add 2*tolerance to avoid precision troubles
pMax += kCarTolerance;
}
else
{
// Check for case where completely enveloping clipping volume
// If point inside then we are confident that the solid completely
// envelopes the clipping volume. Hence set min/max extents according
// to clipping volume extents along the specified axis.
G4ThreeVector clipCentre(
(pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
(pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
(pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5 );
if ( Inside(pTransform.Inverse().TransformPoint(clipCentre)) != kOutside )
{
existsAfterClip = true;
pMin = pVoxelLimit.GetMinExtent(pAxis);
pMax = pVoxelLimit.GetMaxExtent(pAxis);
}
}
delete vertices;
return existsAfterClip;
std::vector<const G4ThreeVectorList *> polygons(2);
polygons[0] = &baseA;
polygons[1] = &baseB;
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
}
else
{
G4double sinStart = GetSinStartPhi();
G4double cosStart = GetCosStartPhi();
G4double sinEnd = GetSinEndPhi();
G4double cosEnd = GetCosEndPhi();
G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
// set quadrilaterals
G4ThreeVectorList pols[NSTEPS+2];
for (G4int k=0; k<ksteps+2; ++k) pols[k].resize(4);
pols[0][0].set(rmin*cosStart,rmin*sinStart, dz);
pols[0][1].set(rmin*cosStart,rmin*sinStart,-dz);
pols[0][2].set(rmax*cosStart,rmax*sinStart,-dz);
pols[0][3].set(rmax*cosStart,rmax*sinStart, dz);
for (G4int k=1; k<ksteps+1; ++k)
{
pols[k][0].set(rmin*cosCur,rmin*sinCur, dz);
pols[k][1].set(rmin*cosCur,rmin*sinCur,-dz);
pols[k][2].set(rext*cosCur,rext*sinCur,-dz);
pols[k][3].set(rext*cosCur,rext*sinCur, dz);
G4double sinTmp = sinCur;
sinCur = sinCur*cosStep + cosCur*sinStep;
cosCur = cosCur*cosStep - sinTmp*sinStep;
}
pols[ksteps+1][0].set(rmin*cosEnd,rmin*sinEnd, dz);
pols[ksteps+1][1].set(rmin*cosEnd,rmin*sinEnd,-dz);
pols[ksteps+1][2].set(rmax*cosEnd,rmax*sinEnd,-dz);
pols[ksteps+1][3].set(rmax*cosEnd,rmax*sinEnd, dz);
// set envelope and calculate extent
std::vector<const G4ThreeVectorList *> polygons;
polygons.resize(ksteps+2);
for (G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k];
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
}
return exist;
}
///////////////////////////////////////////////////////////////////////////
//
// Return whether point inside/outside/on surface
@@ -1461,7 +1403,7 @@ G4double G4Tubs::DistanceToOut( const G4ThreeVector& p,
// Check intersecting with correct half-plane
// (if not -> no intersect)
//
if( (std::fabs(xi)<=kCarTolerance)&&(std::fabs(yi)<=kCarTolerance) )
if((std::fabs(xi)<=kCarTolerance)&&(std::fabs(yi)<=kCarTolerance))
{
sidephi = kSPhi;
if (((fSPhi-halfAngTolerance)<=vphi)
@@ -1504,7 +1446,7 @@ G4double G4Tubs::DistanceToOut( const G4ThreeVector& p,
xi = p.x() + sphi2*v.x() ;
yi = p.y() + sphi2*v.y() ;
if ((std::fabs(xi)<=kCarTolerance)&&(std::fabs(yi)<=kCarTolerance))
if((std::fabs(xi)<=kCarTolerance)&&(std::fabs(yi)<=kCarTolerance))
{
// Leaving via ending phi
//
@@ -1702,100 +1644,6 @@ G4double G4Tubs::DistanceToOut( const G4ThreeVector& p ) const
return safe ;
}
/////////////////////////////////////////////////////////////////////////
//
// Create a List containing the transformed vertices
// Ordering [0-3] -fDz cross section
// [4-7] +fDz cross section such that [0] is below [4],
// [1] below [5] etc.
// Note:
// Caller has deletion resposibility
// Potential improvement: For last slice, use actual ending angle
// to avoid rounding error problems.
G4ThreeVectorList*
G4Tubs::CreateRotatedVertices( const G4AffineTransform& pTransform ) const
{
G4ThreeVectorList* vertices ;
G4ThreeVector vertex0, vertex1, vertex2, vertex3 ;
G4double meshAngle, meshRMax, crossAngle,
cosCrossAngle, sinCrossAngle, sAngle;
G4double rMaxX, rMaxY, rMinX, rMinY, meshRMin ;
G4int crossSection, noCrossSections;
// Compute no of cross-sections necessary to mesh tube
//
noCrossSections = G4int(fDPhi/kMeshAngleDefault) + 1 ;
if ( noCrossSections < kMinMeshSections )
{
noCrossSections = kMinMeshSections ;
}
else if (noCrossSections>kMaxMeshSections)
{
noCrossSections = kMaxMeshSections ;
}
// noCrossSections = 4 ;
meshAngle = fDPhi/(noCrossSections - 1) ;
// meshAngle = fDPhi/(noCrossSections) ;
meshRMax = (fRMax+100*kCarTolerance)/std::cos(meshAngle*0.5) ;
meshRMin = fRMin - 100*kCarTolerance ;
// If complete in phi, set start angle such that mesh will be at fRMax
// on the x axis. Will give better extent calculations when not rotated.
if (fPhiFullTube && (fSPhi == 0) ) { sAngle = -meshAngle*0.5 ; }
else { sAngle = fSPhi ; }
vertices = new G4ThreeVectorList();
if ( vertices )
{
vertices->reserve(noCrossSections*4);
for (crossSection = 0 ; crossSection < noCrossSections ; crossSection++ )
{
// Compute coordinates of cross section at section crossSection
crossAngle = sAngle + crossSection*meshAngle ;
cosCrossAngle = std::cos(crossAngle) ;
sinCrossAngle = std::sin(crossAngle) ;
rMaxX = meshRMax*cosCrossAngle ;
rMaxY = meshRMax*sinCrossAngle ;
if(meshRMin <= 0.0)
{
rMinX = 0.0 ;
rMinY = 0.0 ;
}
else
{
rMinX = meshRMin*cosCrossAngle ;
rMinY = meshRMin*sinCrossAngle ;
}
vertex0 = G4ThreeVector(rMinX,rMinY,-fDz) ;
vertex1 = G4ThreeVector(rMaxX,rMaxY,-fDz) ;
vertex2 = G4ThreeVector(rMaxX,rMaxY,+fDz) ;
vertex3 = G4ThreeVector(rMinX,rMinY,+fDz) ;
vertices->push_back(pTransform.TransformPoint(vertex0)) ;
vertices->push_back(pTransform.TransformPoint(vertex1)) ;
vertices->push_back(pTransform.TransformPoint(vertex2)) ;
vertices->push_back(pTransform.TransformPoint(vertex3)) ;
}
}
else
{
DumpInfo();
G4Exception("G4Tubs::CreateRotatedVertices()",
"GeomSolids0003", FatalException,
"Error in allocation of vertices. Out of memory !");
}
return vertices ;
}
//////////////////////////////////////////////////////////////////////////
//
// Stream object contents to an output stream
@@ -1852,7 +1700,7 @@ G4ThreeVector G4Tubs::GetPointOnSurface() const
aThr = 0.5*fDPhi*(fRMax*fRMax-fRMin*fRMin);
aFou = 2.*fDz*(fRMax-fRMin);
phi = RandFlat::shoot(fSPhi, fSPhi+fDPhi);
phi = G4RandFlat::shoot(fSPhi, fSPhi+fDPhi);
cosphi = std::cos(phi);
sinphi = std::sin(phi);
@@ -1860,20 +1708,20 @@ G4ThreeVector G4Tubs::GetPointOnSurface() const
if( (fSPhi == 0) && (fDPhi == twopi) ) { aFou = 0; }
chose = RandFlat::shoot(0.,aOne+aTwo+2.*aThr+2.*aFou);
chose = G4RandFlat::shoot(0.,aOne+aTwo+2.*aThr+2.*aFou);
if( (chose >=0) && (chose < aOne) )
{
xRand = fRMax*cosphi;
yRand = fRMax*sinphi;
zRand = RandFlat::shoot(-1.*fDz,fDz);
zRand = G4RandFlat::shoot(-1.*fDz,fDz);
return G4ThreeVector (xRand, yRand, zRand);
}
else if( (chose >= aOne) && (chose < aOne + aTwo) )
{
xRand = fRMin*cosphi;
yRand = fRMin*sinphi;
zRand = RandFlat::shoot(-1.*fDz,fDz);
zRand = G4RandFlat::shoot(-1.*fDz,fDz);
return G4ThreeVector (xRand, yRand, zRand);
}
else if( (chose >= aOne + aTwo) && (chose < aOne + aTwo + aThr) )
@@ -1895,14 +1743,14 @@ G4ThreeVector G4Tubs::GetPointOnSurface() const
{
xRand = rRand*std::cos(fSPhi);
yRand = rRand*std::sin(fSPhi);
zRand = RandFlat::shoot(-1.*fDz,fDz);
zRand = G4RandFlat::shoot(-1.*fDz,fDz);
return G4ThreeVector (xRand, yRand, zRand);
}
else
{
xRand = rRand*std::cos(fSPhi+fDPhi);
yRand = rRand*std::sin(fSPhi+fDPhi);
zRand = RandFlat::shoot(-1.*fDz,fDz);
zRand = G4RandFlat::shoot(-1.*fDz,fDz);
return G4ThreeVector (xRand, yRand, zRand);
}
}
+51
View File
@@ -35,7 +35,11 @@
#if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
#include "G4AffineTransform.hh"
#include "G4VPVParameterisation.hh"
#include "G4BoundingEnvelope.hh"
using namespace CLHEP;
////////////////////////////////////////////////////////////////////////
//
@@ -148,6 +152,53 @@ G4VSolid* G4UBox::Clone() const
return new G4UBox(*this);
}
//////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4UBox::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
G4double dx = GetXHalfLength();
G4double dy = GetYHalfLength();
G4double dz = GetZHalfLength();
pMin.set(-dx,-dy,-dz);
pMax.set( dx, dy, dz);
// 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("G4UBox::Extent()", "GeomMgt0001", JustWarning, message);
StreamInfo(G4cout);
}
}
//////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
G4bool
G4UBox::CalculateExtent(const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax) const
{
G4ThreeVector bmin, bmax;
// Get bounding box
Extent(bmin,bmax);
// Find extent
G4BoundingEnvelope bbox(bmin,bmax);
return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
}
//////////////////////////////////////////////////////////////////////////
//
// Create polyhedron for visualization
+207
View File
@@ -35,7 +35,12 @@
#if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
#include "G4GeomTools.hh"
#include "G4AffineTransform.hh"
#include "G4VPVParameterisation.hh"
#include "G4BoundingEnvelope.hh"
using namespace CLHEP;
//////////////////////////////////////////////////////////////////////////
//
@@ -128,6 +133,28 @@ G4double G4UCons::GetDeltaPhiAngle() const
{
return GetShape()->GetDeltaPhiAngle();
}
G4double G4UCons::GetSinStartPhi() const
{
G4double phi = GetShape()->GetStartPhiAngle();
return std::sin(phi);
}
G4double G4UCons::GetCosStartPhi() const
{
G4double phi = GetShape()->GetStartPhiAngle();
return std::cos(phi);
}
G4double G4UCons::GetSinEndPhi() const
{
G4double phi = GetShape()->GetStartPhiAngle() +
GetShape()->GetDeltaPhiAngle();
return std::sin(phi);
}
G4double G4UCons::GetCosEndPhi() const
{
G4double phi = GetShape()->GetStartPhiAngle() +
GetShape()->GetDeltaPhiAngle();
return std::cos(phi);
}
void G4UCons::SetInnerRadiusMinusZ(G4double Rmin1)
{
@@ -186,6 +213,186 @@ G4VSolid* G4UCons::Clone() const
return new G4UCons(*this);
}
//////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4UCons::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
static G4bool checkBBox = true;
G4double rmin = std::min(GetInnerRadiusMinusZ(),GetInnerRadiusPlusZ());
G4double rmax = std::max(GetOuterRadiusMinusZ(),GetOuterRadiusPlusZ());
G4double dz = GetZHalfLength();
// Find bounding box
//
if (GetDeltaPhiAngle() < twopi)
{
G4TwoVector vmin,vmax;
G4GeomTools::DiskExtent(rmin,rmax,
GetSinStartPhi(),GetCosStartPhi(),
GetSinEndPhi(),GetCosEndPhi(),
vmin,vmax);
pMin.set(vmin.x(),vmin.y(),-dz);
pMax.set(vmax.x(),vmax.y(), dz);
}
else
{
pMin.set(-rmax,-rmax,-dz);
pMax.set( rmax, rmax, dz);
}
// 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("G4UCons::Extent()", "GeomMgt0001", JustWarning, message);
StreamInfo(G4cout);
}
// Check consistency of bounding boxes
//
if (checkBBox)
{
UVector3 vmin, vmax;
GetShape()->Extent(vmin,vmax);
if (std::abs(pMin.x()-vmin.x()) > kCarTolerance ||
std::abs(pMin.y()-vmin.y()) > kCarTolerance ||
std::abs(pMin.z()-vmin.z()) > kCarTolerance ||
std::abs(pMax.x()-vmax.x()) > kCarTolerance ||
std::abs(pMax.y()-vmax.y()) > kCarTolerance ||
std::abs(pMax.z()-vmax.z()) > kCarTolerance)
{
std::ostringstream message;
message << "Inconsistency in bounding boxes for solid: "
<< GetName() << " !"
<< "\nBBox min: wrapper = " << pMin << " solid = " << vmin
<< "\nBBox max: wrapper = " << pMax << " solid = " << vmax;
G4Exception("G4UCons::Extent()", "GeomMgt0001", JustWarning, message);
checkBBox = false;
}
}
}
/////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
G4bool
G4UCons::CalculateExtent(const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax) const
{
G4ThreeVector bmin, bmax;
G4bool exist;
// Get bounding box
Extent(bmin,bmax);
// Check bounding box
G4BoundingEnvelope bbox(bmin,bmax);
#ifdef G4BBOX_EXTENT
if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
#endif
if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
{
return exist = (pMin < pMax) ? true : false;
}
// Get parameters of the solid
G4double rmin1 = GetInnerRadiusMinusZ();
G4double rmax1 = GetOuterRadiusMinusZ();
G4double rmin2 = GetInnerRadiusPlusZ();
G4double rmax2 = GetOuterRadiusPlusZ();
G4double dz = GetZHalfLength();
G4double dphi = GetDeltaPhiAngle();
// Find bounding envelope and calculate extent
//
const G4int NSTEPS = 24; // number of steps for whole circle
G4double astep = (360/NSTEPS)*deg; // max angle for one step
G4int ksteps = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1;
G4double ang = dphi/ksteps;
G4double sinHalf = std::sin(0.5*ang);
G4double cosHalf = std::cos(0.5*ang);
G4double sinStep = 2.*sinHalf*cosHalf;
G4double cosStep = 1. - 2.*sinHalf*sinHalf;
G4double rext1 = rmax1/cosHalf;
G4double rext2 = rmax2/cosHalf;
// bounding envelope for full cone without hole consists of two polygons,
// in other cases it is a sequence of quadrilaterals
if (rmin1 == 0 && rmin2 == 0 && dphi == twopi)
{
G4double sinCur = sinHalf;
G4double cosCur = cosHalf;
G4ThreeVectorList baseA(NSTEPS),baseB(NSTEPS);
for (G4int k=0; k<NSTEPS; ++k)
{
baseA[k].set(rext1*cosCur,rext1*sinCur,-dz);
baseB[k].set(rext2*cosCur,rext2*sinCur, dz);
G4double sinTmp = sinCur;
sinCur = sinCur*cosStep + cosCur*sinStep;
cosCur = cosCur*cosStep - sinTmp*sinStep;
}
std::vector<const G4ThreeVectorList *> polygons(2);
polygons[0] = &baseA;
polygons[1] = &baseB;
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
}
else
{
G4double sinStart = GetSinStartPhi();
G4double cosStart = GetCosStartPhi();
G4double sinEnd = GetSinEndPhi();
G4double cosEnd = GetCosEndPhi();
G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
// set quadrilaterals
G4ThreeVectorList pols[NSTEPS+2];
for (G4int k=0; k<ksteps+2; ++k) pols[k].resize(4);
pols[0][0].set(rmin2*cosStart,rmin2*sinStart, dz);
pols[0][1].set(rmin1*cosStart,rmin1*sinStart,-dz);
pols[0][2].set(rmax1*cosStart,rmax1*sinStart,-dz);
pols[0][3].set(rmax2*cosStart,rmax2*sinStart, dz);
for (G4int k=1; k<ksteps+1; ++k)
{
pols[k][0].set(rmin2*cosCur,rmin2*sinCur, dz);
pols[k][1].set(rmin1*cosCur,rmin1*sinCur,-dz);
pols[k][2].set(rext1*cosCur,rext1*sinCur,-dz);
pols[k][3].set(rext2*cosCur,rext2*sinCur, dz);
G4double sinTmp = sinCur;
sinCur = sinCur*cosStep + cosCur*sinStep;
cosCur = cosCur*cosStep - sinTmp*sinStep;
}
pols[ksteps+1][0].set(rmin2*cosEnd,rmin2*sinEnd, dz);
pols[ksteps+1][1].set(rmin1*cosEnd,rmin1*sinEnd,-dz);
pols[ksteps+1][2].set(rmax1*cosEnd,rmax1*sinEnd,-dz);
pols[ksteps+1][3].set(rmax2*cosEnd,rmax2*sinEnd, dz);
// set envelope and calculate extent
std::vector<const G4ThreeVectorList *> polygons;
polygons.resize(ksteps+2);
for (G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k];
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
}
return exist;
}
//////////////////////////////////////////////////////////////////////////
//
// Create polyhedron for visualization
+115
View File
@@ -34,9 +34,16 @@
#if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
#include "G4TwoVector.hh"
#include "G4AffineTransform.hh"
#include "G4GeometryTolerance.hh"
#include "G4BoundingEnvelope.hh"
#include "G4VPVParameterisation.hh"
#include "G4PhysicalConstants.hh"
using namespace CLHEP;
////////////////////////////////////////////////////////////////////////
//
// constructor - check positive radius
@@ -127,6 +134,114 @@ G4VSolid* G4UOrb::Clone() const
return new G4UOrb(*this);
}
//////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4UOrb::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
G4double radius = GetRadius();
pMin.set(-radius,-radius,-radius);
pMax.set( radius, radius, radius);
// 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("G4UOrb::Extent()", "GeomMgt0001", JustWarning, message);
StreamInfo(G4cout);
}
}
//////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
G4bool
G4UOrb::CalculateExtent(const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax) const
{
G4ThreeVector bmin, bmax;
G4bool exist;
// Get bounding box
Extent(bmin,bmax);
// Check bounding box
G4BoundingEnvelope bbox(bmin,bmax);
#ifdef G4BBOX_EXTENT
if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
#endif
if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
{
return exist = (pMin < pMax) ? true : false;
}
// Find bounding envelope and calculate extent
//
static const G4int NTHETA = 8; // number of steps along Theta
static const G4int NPHI = 16; // number of steps along Phi
static const G4double sinHalfTheta = std::sin(halfpi/NTHETA);
static const G4double cosHalfTheta = std::cos(halfpi/NTHETA);
static const G4double sinHalfPhi = std::sin(pi/NPHI);
static const G4double cosHalfPhi = std::cos(pi/NPHI);
static const G4double sinStepTheta = 2.*sinHalfTheta*cosHalfTheta;
static const G4double cosStepTheta = 1. - 2.*sinHalfTheta*sinHalfTheta;
static const G4double sinStepPhi = 2.*sinHalfPhi*cosHalfPhi;
static const G4double cosStepPhi = 1. - 2.*sinHalfPhi*sinHalfPhi;
G4double radius = GetRadius();
G4double rtheta = radius/cosHalfTheta;
G4double rphi = rtheta/cosHalfPhi;
// set reference circle
G4TwoVector xy[NPHI];
G4double sinCurPhi = sinHalfPhi;
G4double cosCurPhi = cosHalfPhi;
for (G4int k=0; k<NPHI; ++k)
{
xy[k].set(cosCurPhi,sinCurPhi);
G4double sinTmpPhi = sinCurPhi;
sinCurPhi = sinCurPhi*cosStepPhi + cosCurPhi*sinStepPhi;
cosCurPhi = cosCurPhi*cosStepPhi - sinTmpPhi*sinStepPhi;
}
// set bounding circles
G4ThreeVectorList circles[NTHETA];
for (G4int i=0; i<NTHETA; ++i) circles[i].resize(NPHI);
G4double sinCurTheta = sinHalfTheta;
G4double cosCurTheta = cosHalfTheta;
for (G4int i=0; i<NTHETA; ++i)
{
G4double z = rtheta*cosCurTheta;
G4double rho = rphi*sinCurTheta;
for (G4int k=0; k<NPHI; ++k)
{
circles[i][k].set(rho*xy[k].x(),rho*xy[k].y(),z);
}
G4double sinTmpTheta = sinCurTheta;
sinCurTheta = sinCurTheta*cosStepTheta + cosCurTheta*sinStepTheta;
cosCurTheta = cosCurTheta*cosStepTheta - sinTmpTheta*sinStepTheta;
}
// set envelope and calculate extent
std::vector<const G4ThreeVectorList *> polygons;
polygons.resize(NTHETA);
for (G4int i=0; i<NTHETA; ++i) polygons[i] = &circles[i];
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
return exist;
}
//////////////////////////////////////////////////////////////////////////
//
// Create polyhedron for visualization
+149
View File
@@ -35,7 +35,12 @@
#if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
#include "G4GeomTools.hh"
#include "G4AffineTransform.hh"
#include "G4VPVParameterisation.hh"
#include "G4BoundingEnvelope.hh"
using namespace CLHEP;
////////////////////////////////////////////////////////////////////////
//
@@ -123,6 +128,50 @@ G4double G4USphere::GetDeltaThetaAngle() const
{
return GetShape()->GetDeltaThetaAngle();
}
G4double G4USphere::GetSinStartPhi() const
{
G4double phi = GetShape()->GetStartPhiAngle();
return std::sin(phi);
}
G4double G4USphere::GetCosStartPhi() const
{
G4double phi = GetShape()->GetStartPhiAngle();
return std::cos(phi);
}
G4double G4USphere::GetSinEndPhi() const
{
G4double phi = GetShape()->GetStartPhiAngle() +
GetShape()->GetDeltaPhiAngle();
return std::sin(phi);
}
G4double G4USphere::GetCosEndPhi() const
{
G4double phi = GetShape()->GetStartPhiAngle() +
GetShape()->GetDeltaPhiAngle();
return std::cos(phi);
}
G4double G4USphere::GetSinStartTheta() const
{
G4double theta = GetShape()->GetStartThetaAngle();
return std::sin(theta);
}
G4double G4USphere::GetCosStartTheta() const
{
G4double theta = GetShape()->GetStartThetaAngle();
return std::cos(theta);
}
G4double G4USphere::GetSinEndTheta() const
{
G4double theta = GetShape()->GetStartThetaAngle() +
GetShape()->GetDeltaThetaAngle();
return std::sin(theta);
}
G4double G4USphere::GetCosEndTheta() const
{
G4double theta = GetShape()->GetStartThetaAngle() +
GetShape()->GetDeltaThetaAngle();
return std::cos(theta);
}
void G4USphere::SetInnerRadius(G4double newRMin)
{
@@ -176,6 +225,106 @@ G4VSolid* G4USphere::Clone() const
return new G4USphere(*this);
}
//////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4USphere::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
static G4bool checkBBox = true;
G4double rmin = GetInnerRadius();
G4double rmax = GetOuterRadius();
// Find bounding box
//
if (GetDeltaThetaAngle() >= pi && GetDeltaPhiAngle() >= twopi)
{
pMin.set(-rmax,-rmax,-rmax);
pMax.set( rmax, rmax, rmax);
}
else
{
G4double sinStart = GetSinStartTheta();
G4double cosStart = GetCosStartTheta();
G4double sinEnd = GetSinEndTheta();
G4double cosEnd = GetCosEndTheta();
G4double stheta = GetStartThetaAngle();
G4double etheta = stheta + GetDeltaThetaAngle();
G4double rhomin = rmin*std::min(sinStart,sinEnd);
G4double rhomax = rmax;
if (stheta > halfpi) rhomax = rmax*sinStart;
if (etheta < halfpi) rhomax = rmax*sinEnd;
G4TwoVector xymin,xymax;
G4GeomTools::DiskExtent(rhomin,rhomax,
GetSinStartPhi(),GetCosStartPhi(),
GetSinEndPhi(),GetCosEndPhi(),
xymin,xymax);
G4double zmin = std::min(rmin*cosEnd,rmax*cosEnd);
G4double zmax = std::max(rmin*cosStart,rmax*cosStart);
pMin.set(xymin.x(),xymin.y(),zmin);
pMax.set(xymax.x(),xymax.y(),zmax);
}
// 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("G4USphere::Extent()", "GeomMgt0001", JustWarning, message);
StreamInfo(G4cout);
}
// Check consistency of bounding boxes
//
if (checkBBox)
{
UVector3 vmin, vmax;
GetShape()->Extent(vmin,vmax);
if (std::abs(pMin.x()-vmin.x()) > kCarTolerance ||
std::abs(pMin.y()-vmin.y()) > kCarTolerance ||
std::abs(pMin.z()-vmin.z()) > kCarTolerance ||
std::abs(pMax.x()-vmax.x()) > kCarTolerance ||
std::abs(pMax.y()-vmax.y()) > kCarTolerance ||
std::abs(pMax.z()-vmax.z()) > kCarTolerance)
{
std::ostringstream message;
message << "Inconsistency in bounding boxes for solid: "
<< GetName() << " !"
<< "\nBBox min: wrapper = " << pMin << " solid = " << vmin
<< "\nBBox max: wrapper = " << pMax << " solid = " << vmax;
G4Exception("G4USphere::Extent()", "GeomMgt0001", JustWarning, message);
checkBBox = false;
}
}
}
//////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
G4bool G4USphere::CalculateExtent(const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax) const
{
G4ThreeVector bmin, bmax;
// Get bounding box
Extent(bmin,bmax);
// Find extent
G4BoundingEnvelope bbox(bmin,bmax);
return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
}
//////////////////////////////////////////////////////////////////////////
//
// Create polyhedron for visualization
+241
View File
@@ -37,8 +37,15 @@
#if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
#include "G4TwoVector.hh"
#include "G4GeomTools.hh"
#include "G4AffineTransform.hh"
#include "G4BoundingEnvelope.hh"
#include "G4VPVParameterisation.hh"
using namespace CLHEP;
////////////////////////////////////////////////////////////////////////
//
// Constructor - check & set half widths
@@ -119,6 +126,32 @@ G4double G4UTorus::GetDPhi() const
return GetShape()->GetDPhi();
}
G4double G4UTorus::GetSinStartPhi() const
{
G4double phi = GetShape()->GetSPhi();
return std::sin(phi);
}
G4double G4UTorus::GetCosStartPhi() const
{
G4double phi = GetShape()->GetSPhi();
return std::cos(phi);
}
G4double G4UTorus::GetSinEndPhi() const
{
G4double phi = GetShape()->GetSPhi() +
GetShape()->GetDPhi();
return std::sin(phi);
}
G4double G4UTorus::GetCosEndPhi() const
{
G4double phi = GetShape()->GetSPhi() +
GetShape()->GetDPhi();
return std::cos(phi);
}
void G4UTorus::SetRmin(G4double arg)
{
GetShape()->SetRmin(arg);
@@ -181,6 +214,214 @@ G4VSolid* G4UTorus::Clone() const
return new G4UTorus(*this);
}
//////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4UTorus::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
static G4bool checkBBox = true;
G4double rmax = GetRmax();
G4double rtor = GetRtor();
G4double rint = rtor - rmax;
G4double rext = rtor + rmax;
G4double dz = rmax;
// Find bounding box
//
if (GetDPhi() >= twopi)
{
pMin.set(-rext,-rext,-dz);
pMax.set( rext, rext, dz);
}
else
{
G4TwoVector vmin,vmax;
G4GeomTools::DiskExtent(rint,rext,
GetSinStartPhi(),GetCosStartPhi(),
GetSinEndPhi(),GetCosEndPhi(),
vmin,vmax);
pMin.set(vmin.x(),vmin.y(),-dz);
pMax.set(vmax.x(),vmax.y(), dz);
}
// 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("G4UTorus::Extent()", "GeomMgt0001", JustWarning, message);
StreamInfo(G4cout);
}
// Check consistency of bounding boxes
//
if (checkBBox)
{
UVector3 vmin, vmax;
GetShape()->Extent(vmin,vmax);
if (std::abs(pMin.x()-vmin.x()) > kCarTolerance ||
std::abs(pMin.y()-vmin.y()) > kCarTolerance ||
std::abs(pMin.z()-vmin.z()) > kCarTolerance ||
std::abs(pMax.x()-vmax.x()) > kCarTolerance ||
std::abs(pMax.y()-vmax.y()) > kCarTolerance ||
std::abs(pMax.z()-vmax.z()) > kCarTolerance)
{
std::ostringstream message;
message << "Inconsistency in bounding boxes for solid: "
<< GetName() << " !"
<< "\nBBox min: wrapper = " << pMin << " solid = " << vmin
<< "\nBBox max: wrapper = " << pMax << " solid = " << vmax;
G4Exception("G4UTorus::Extent()", "GeomMgt0001", JustWarning, message);
checkBBox = false;
}
}
}
//////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
G4bool
G4UTorus::CalculateExtent(const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax) const
{
G4ThreeVector bmin, bmax;
G4bool exist;
// Get bounding box
Extent(bmin,bmax);
// Check bounding box
G4BoundingEnvelope bbox(bmin,bmax);
#ifdef G4BBOX_EXTENT
if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
#endif
if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
{
return exist = (pMin < pMax) ? true : false;
}
// Get parameters of the solid
G4double rmin = GetRmin();
G4double rmax = GetRmax();
G4double rtor = GetRtor();
G4double dphi = GetDPhi();
G4double sinStart = GetSinStartPhi();
G4double cosStart = GetCosStartPhi();
G4double sinEnd = GetSinEndPhi();
G4double cosEnd = GetCosEndPhi();
G4double rint = rtor - rmax;
G4double rext = rtor + rmax;
// Find bounding envelope and calculate extent
//
static const G4int NPHI = 24; // number of steps for whole torus
static const G4int NDISK = 16; // number of steps for disk
static const G4double sinHalfDisk = std::sin(pi/NDISK);
static const G4double cosHalfDisk = std::cos(pi/NDISK);
static const G4double sinStepDisk = 2.*sinHalfDisk*cosHalfDisk;
static const G4double cosStepDisk = 1. - 2.*sinHalfDisk*sinHalfDisk;
G4double astep = (360/NPHI)*deg; // max angle for one slice in phi
G4int kphi = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1;
G4double ang = dphi/kphi;
G4double sinHalf = std::sin(0.5*ang);
G4double cosHalf = std::cos(0.5*ang);
G4double sinStep = 2.*sinHalf*cosHalf;
G4double cosStep = 1. - 2.*sinHalf*sinHalf;
// define vectors for bounding envelope
G4ThreeVectorList pols[NDISK+1];
for (G4int k=0; k<NDISK+1; ++k) pols[k].resize(4);
std::vector<const G4ThreeVectorList *> polygons;
polygons.resize(NDISK+1);
for (G4int k=0; k<NDISK+1; ++k) polygons[k] = &pols[k];
// set internal and external reference circles
G4TwoVector rzmin[NDISK];
G4TwoVector rzmax[NDISK];
if ((rtor-rmin*sinHalfDisk)/cosHalf > (rtor+rmin*sinHalfDisk)) rmin = 0;
rmax /= cosHalfDisk;
G4double sinCurDisk = sinHalfDisk;
G4double cosCurDisk = cosHalfDisk;
for (G4int k=0; k<NDISK; ++k)
{
G4double rmincur = rtor + rmin*cosCurDisk;
if (cosCurDisk < 0 && rmin > 0) rmincur /= cosHalf;
rzmin[k].set(rmincur,rmin*sinCurDisk);
G4double rmaxcur = rtor + rmax*cosCurDisk;
if (cosCurDisk > 0) rmaxcur /= cosHalf;
rzmax[k].set(rmaxcur,rmax*sinCurDisk);
G4double sinTmpDisk = sinCurDisk;
sinCurDisk = sinCurDisk*cosStepDisk + cosCurDisk*sinStepDisk;
cosCurDisk = cosCurDisk*cosStepDisk - sinTmpDisk*sinStepDisk;
}
// Loop along slices in Phi. The extent is calculated as cumulative
// extent of the slices
pMin = kInfinity;
pMax = -kInfinity;
G4double eminlim = pVoxelLimit.GetMinExtent(pAxis);
G4double emaxlim = pVoxelLimit.GetMaxExtent(pAxis);
G4double sinCur1 = 0, cosCur1 = 0, sinCur2 = 0, cosCur2 = 0;
for (G4int i=0; i<kphi+1; ++i)
{
if (i == 0)
{
sinCur1 = sinStart;
cosCur1 = cosStart;
sinCur2 = sinCur1*cosHalf + cosCur1*sinHalf;
cosCur2 = cosCur1*cosHalf - sinCur1*sinHalf;
}
else
{
sinCur1 = sinCur2;
cosCur1 = cosCur2;
sinCur2 = (i == kphi) ? sinEnd : sinCur1*cosStep + cosCur1*sinStep;
cosCur2 = (i == kphi) ? cosEnd : cosCur1*cosStep - sinCur1*sinStep;
}
for (G4int k=0; k<NDISK; ++k)
{
G4double r1 = rzmin[k].x(), r2 = rzmax[k].x();
G4double z1 = rzmin[k].y(), z2 = rzmax[k].y();
pols[k][0].set(r1*cosCur1,r1*sinCur1,z1);
pols[k][1].set(r2*cosCur1,r2*sinCur1,z2);
pols[k][2].set(r2*cosCur2,r2*sinCur2,z2);
pols[k][3].set(r1*cosCur2,r1*sinCur2,z1);
}
pols[NDISK] = pols[0];
// get bounding box of current slice
G4TwoVector vmin,vmax;
G4GeomTools::
DiskExtent(rint,rext,sinCur1,cosCur1,sinCur2,cosCur2,vmin,vmax);
bmin.setX(vmin.x()); bmin.setY(vmin.y());
bmax.setX(vmax.x()); bmax.setY(vmax.y());
// set bounding envelope for current slice and adjust extent
G4double emin,emax;
G4BoundingEnvelope benv(bmin,bmax,polygons);
if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax)) continue;
if (emin < pMin) pMin = emin;
if (emax > pMax) pMax = emax;
if (eminlim > pMin && emaxlim < pMax) break; // max possible extent
}
return (pMin < pMax);
}
//////////////////////////////////////////////////////////////////////////
//
// Create polyhedron for visualization
+140
View File
@@ -35,7 +35,11 @@
#if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
#include "G4AffineTransform.hh"
#include "G4VPVParameterisation.hh"
#include "G4BoundingEnvelope.hh"
using namespace CLHEP;
/////////////////////////////////////////////////////////////////////////
//
@@ -228,6 +232,142 @@ G4VSolid* G4UTrap::Clone() const
return new G4UTrap(*this);
}
//////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4UTrap::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
static G4bool checkBBox = true;
G4double dz = GetZHalfLength();
G4double dx1 = GetXHalfLength1();
G4double dx2 = GetXHalfLength2();
G4double dx3 = GetXHalfLength3();
G4double dx4 = GetXHalfLength4();
G4double dy1 = GetYHalfLength1();
G4double dy2 = GetYHalfLength2();
G4double fTthetaSphi = GetShape()->GetThetaSphi();
G4double fTthetaCphi = GetShape()->GetThetaCphi();
G4double x0 = dz*fTthetaCphi;
G4double x1 = dy1*GetTanAlpha1();
G4double x2 = dy2*GetTanAlpha2();
G4double xmin =
std::min(
std::min(
std::min(-x0-x1-dx1,-x0+x1-dx2),x0-x2-dx3),x0+x2-dx4);
G4double xmax =
std::max(
std::max(
std::max(-x0-x1+dx1,-x0+x1+dx2),x0-x2+dx3),x0+x2+dx4);
G4double y0 = dz*fTthetaSphi;
G4double ymin = std::min(-y0-dy1,y0-dy2);
G4double ymax = std::max(-y0+dy1,y0+dy2);
pMin.set(xmin,ymin,-dz);
pMax.set(xmax,ymax, dz);
// 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("G4UTrap::Extent()", "GeomMgt0001", JustWarning, message);
StreamInfo(G4cout);
}
// Check consistency of bounding boxes
//
if (checkBBox)
{
UVector3 vmin, vmax;
GetShape()->Extent(vmin,vmax);
if (std::abs(pMin.x()-vmin.x()) > kCarTolerance ||
std::abs(pMin.y()-vmin.y()) > kCarTolerance ||
std::abs(pMin.z()-vmin.z()) > kCarTolerance ||
std::abs(pMax.x()-vmax.x()) > kCarTolerance ||
std::abs(pMax.y()-vmax.y()) > kCarTolerance ||
std::abs(pMax.z()-vmax.z()) > kCarTolerance)
{
std::ostringstream message;
message << "Inconsistency in bounding boxes for solid: "
<< GetName() << " !"
<< "\nBBox min: wrapper = " << pMin << " solid = " << vmin
<< "\nBBox max: wrapper = " << pMax << " solid = " << vmax;
G4Exception("G4UTrap::Extent()", "GeomMgt0001", JustWarning, message);
checkBBox = false;
}
}
}
//////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
G4bool
G4UTrap::CalculateExtent(const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax) const
{
G4ThreeVector bmin, bmax;
G4bool exist;
// Check bounding box (bbox)
//
Extent(bmin,bmax);
G4BoundingEnvelope bbox(bmin,bmax);
#ifdef G4BBOX_EXTENT
if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
#endif
if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
{
return exist = (pMin < pMax) ? true : false;
}
// Set bounding envelope (benv) and calculate extent
//
G4double dz = GetZHalfLength();
G4double dx1 = GetXHalfLength1();
G4double dx2 = GetXHalfLength2();
G4double dx3 = GetXHalfLength3();
G4double dx4 = GetXHalfLength4();
G4double dy1 = GetYHalfLength1();
G4double dy2 = GetYHalfLength2();
G4double fTthetaSphi = GetShape()->GetThetaSphi();
G4double fTthetaCphi = GetShape()->GetThetaCphi();
G4double x0 = dz*fTthetaCphi;
G4double x1 = dy1*GetTanAlpha1();
G4double x2 = dy2*GetTanAlpha2();
G4double y0 = dz*fTthetaSphi;
G4ThreeVectorList baseA(4), baseB(4);
baseA[0].set(-x0-x1-dx1,-y0-dy1,-dz);
baseA[1].set(-x0-x1+dx1,-y0-dy1,-dz);
baseA[2].set(-x0+x1+dx2,-y0+dy1,-dz);
baseA[3].set(-x0+x1-dx2,-y0+dy1,-dz);
baseB[0].set( x0-x2-dx3, y0-dy2, dz);
baseB[1].set( x0-x2+dx3, y0-dy2, dz);
baseB[2].set( x0+x2+dx4, y0+dy2, dz);
baseB[3].set( x0+x2-dx4, y0+dy2, dz);
std::vector<const G4ThreeVectorList *> polygons(2);
polygons[0] = &baseA;
polygons[1] = &baseB;
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
return exist;
}
//////////////////////////////////////////////////////////////////////////
//
// Create polyhedron for visualization
+112
View File
@@ -35,7 +35,11 @@
#if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
#include "G4AffineTransform.hh"
#include "G4VPVParameterisation.hh"
#include "G4BoundingEnvelope.hh"
using namespace CLHEP;
/////////////////////////////////////////////////////////////////////////
//
@@ -171,6 +175,114 @@ G4VSolid* G4UTrd::Clone() const
return new G4UTrd(*this);
}
//////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4UTrd::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
static G4bool checkBBox = true;
G4double dx1 = GetXHalfLength1();
G4double dx2 = GetXHalfLength2();
G4double dy1 = GetYHalfLength1();
G4double dy2 = GetYHalfLength2();
G4double dz = GetZHalfLength();
G4double xmax = std::max(dx1,dx2);
G4double ymax = std::max(dy1,dy2);
pMin.set(-xmax,-ymax,-dz);
pMax.set( xmax, ymax, dz);
// 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("G4UTrd::Extent()", "GeomMgt0001", JustWarning, message);
StreamInfo(G4cout);
}
// Check consistency of bounding boxes
//
if (checkBBox)
{
UVector3 vmin, vmax;
GetShape()->Extent(vmin,vmax);
if (std::abs(pMin.x()-vmin.x()) > kCarTolerance ||
std::abs(pMin.y()-vmin.y()) > kCarTolerance ||
std::abs(pMin.z()-vmin.z()) > kCarTolerance ||
std::abs(pMax.x()-vmax.x()) > kCarTolerance ||
std::abs(pMax.y()-vmax.y()) > kCarTolerance ||
std::abs(pMax.z()-vmax.z()) > kCarTolerance)
{
std::ostringstream message;
message << "Inconsistency in bounding boxes for solid: "
<< GetName() << " !"
<< "\nBBox min: wrapper = " << pMin << " solid = " << vmin
<< "\nBBox max: wrapper = " << pMax << " solid = " << vmax;
G4Exception("G4UTrd::Extent()", "GeomMgt0001", JustWarning, message);
checkBBox = false;
}
}
}
//////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
G4bool
G4UTrd::CalculateExtent(const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax) const
{
G4ThreeVector bmin, bmax;
G4bool exist;
// Check bounding box (bbox)
//
Extent(bmin,bmax);
G4BoundingEnvelope bbox(bmin,bmax);
#ifdef G4BBOX_EXTENT
if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
#endif
if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
{
return exist = (pMin < pMax) ? true : false;
}
// Set bounding envelope (benv) and calculate extent
//
G4double dx1 = GetXHalfLength1();
G4double dx2 = GetXHalfLength2();
G4double dy1 = GetYHalfLength1();
G4double dy2 = GetYHalfLength2();
G4double dz = GetZHalfLength();
G4ThreeVectorList baseA(4), baseB(4);
baseA[0].set(-dx1,-dy1,-dz);
baseA[1].set( dx1,-dy1,-dz);
baseA[2].set( dx1, dy1,-dz);
baseA[3].set(-dx1, dy1,-dz);
baseB[0].set(-dx2,-dy2, dz);
baseB[1].set( dx2,-dy2, dz);
baseB[2].set( dx2, dy2, dz);
baseB[3].set(-dx2, dy2, dz);
std::vector<const G4ThreeVectorList *> polygons(2);
polygons[0] = &baseA;
polygons[1] = &baseB;
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
return exist;
}
//////////////////////////////////////////////////////////////////////////
//
// Create polyhedron for visualization
+205 -1
View File
@@ -35,7 +35,12 @@
#if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
#include "G4GeomTools.hh"
#include "G4AffineTransform.hh"
#include "G4VPVParameterisation.hh"
#include "G4BoundingEnvelope.hh"
using namespace CLHEP;
/////////////////////////////////////////////////////////////////////////
//
@@ -118,6 +123,28 @@ G4double G4UTubs::GetDeltaPhiAngle() const
{
return GetShape()->GetDeltaPhiAngle();
}
G4double G4UTubs::GetSinStartPhi() const
{
G4double phi = GetShape()->GetStartPhiAngle();
return std::sin(phi);
}
G4double G4UTubs::GetCosStartPhi() const
{
G4double phi = GetShape()->GetStartPhiAngle();
return std::cos(phi);
}
G4double G4UTubs::GetSinEndPhi() const
{
G4double phi = GetShape()->GetStartPhiAngle() +
GetShape()->GetDeltaPhiAngle();
return std::sin(phi);
}
G4double G4UTubs::GetCosEndPhi() const
{
G4double phi = GetShape()->GetStartPhiAngle() +
GetShape()->GetDeltaPhiAngle();
return std::cos(phi);
}
void G4UTubs::SetInnerRadius(G4double newRMin)
{
@@ -157,7 +184,7 @@ void G4UTubs::ComputeDimensions( G4VPVParameterisation* p,
p->ComputeDimensions(*(G4Tubs*)this,n,pRep) ;
}
//////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
//
// Make a clone of the object
@@ -166,6 +193,183 @@ G4VSolid* G4UTubs::Clone() const
return new G4UTubs(*this);
}
//////////////////////////////////////////////////////////////////////////
//
// Get bounding box
void G4UTubs::Extent(G4ThreeVector& pMin, G4ThreeVector& pMax) const
{
static G4bool checkBBox = true;
G4double rmin = GetInnerRadius();
G4double rmax = GetOuterRadius();
G4double dz = GetZHalfLength();
// Find bounding box
//
if (GetDeltaPhiAngle() < twopi)
{
G4TwoVector vmin,vmax;
G4GeomTools::DiskExtent(rmin,rmax,
GetSinStartPhi(),GetCosStartPhi(),
GetSinEndPhi(),GetCosEndPhi(),
vmin,vmax);
pMin.set(vmin.x(),vmin.y(),-dz);
pMax.set(vmax.x(),vmax.y(), dz);
}
else
{
pMin.set(-rmax,-rmax,-dz);
pMax.set( rmax, rmax, dz);
}
// 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("G4UTubs::Extent()", "GeomMgt0001", JustWarning, message);
StreamInfo(G4cout);
}
// Check consistency of bounding boxes
//
if (checkBBox)
{
UVector3 vmin, vmax;
GetShape()->Extent(vmin,vmax);
if (std::abs(pMin.x()-vmin.x()) > kCarTolerance ||
std::abs(pMin.y()-vmin.y()) > kCarTolerance ||
std::abs(pMin.z()-vmin.z()) > kCarTolerance ||
std::abs(pMax.x()-vmax.x()) > kCarTolerance ||
std::abs(pMax.y()-vmax.y()) > kCarTolerance ||
std::abs(pMax.z()-vmax.z()) > kCarTolerance)
{
std::ostringstream message;
message << "Inconsistency in bounding boxes for solid: "
<< GetName() << " !"
<< "\nBBox min: wrapper = " << pMin << " solid = " << vmin
<< "\nBBox max: wrapper = " << pMax << " solid = " << vmax;
G4Exception("G4UTubs::Extent()", "GeomMgt0001", JustWarning, message);
checkBBox = false;
}
}
}
//////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
G4bool
G4UTubs::CalculateExtent(const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax) const
{
G4ThreeVector bmin, bmax;
G4bool exist;
// Get bounding box
Extent(bmin,bmax);
// Check bounding box
G4BoundingEnvelope bbox(bmin,bmax);
#ifdef G4BBOX_EXTENT
if (true) return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
#endif
if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
{
return exist = (pMin < pMax) ? true : false;
}
// Get parameters of the solid
G4double rmin = GetInnerRadius();
G4double rmax = GetOuterRadius();
G4double dz = GetZHalfLength();
G4double dphi = GetDeltaPhiAngle();
// Find bounding envelope and calculate extent
//
const G4int NSTEPS = 24; // number of steps for whole circle
G4double astep = (360/NSTEPS)*deg; // max angle for one step
G4int ksteps = (dphi <= astep) ? 1 : (G4int)((dphi-deg)/astep) + 1;
G4double ang = dphi/ksteps;
G4double sinHalf = std::sin(0.5*ang);
G4double cosHalf = std::cos(0.5*ang);
G4double sinStep = 2.*sinHalf*cosHalf;
G4double cosStep = 1. - 2.*sinHalf*sinHalf;
G4double rext = rmax/cosHalf;
// bounding envelope for full cylinder consists of two polygons,
// in other cases it is a sequence of quadrilaterals
if (rmin == 0 && dphi == twopi)
{
G4double sinCur = sinHalf;
G4double cosCur = cosHalf;
G4ThreeVectorList baseA(NSTEPS),baseB(NSTEPS);
for (G4int k=0; k<NSTEPS; ++k)
{
baseA[k].set(rext*cosCur,rext*sinCur,-dz);
baseB[k].set(rext*cosCur,rext*sinCur, dz);
G4double sinTmp = sinCur;
sinCur = sinCur*cosStep + cosCur*sinStep;
cosCur = cosCur*cosStep - sinTmp*sinStep;
}
std::vector<const G4ThreeVectorList *> polygons(2);
polygons[0] = &baseA;
polygons[1] = &baseB;
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
}
else
{
G4double sinStart = GetSinStartPhi();
G4double cosStart = GetCosStartPhi();
G4double sinEnd = GetSinEndPhi();
G4double cosEnd = GetCosEndPhi();
G4double sinCur = sinStart*cosHalf + cosStart*sinHalf;
G4double cosCur = cosStart*cosHalf - sinStart*sinHalf;
// set quadrilaterals
G4ThreeVectorList pols[NSTEPS+2];
for (G4int k=0; k<ksteps+2; ++k) pols[k].resize(4);
pols[0][0].set(rmin*cosStart,rmin*sinStart, dz);
pols[0][1].set(rmin*cosStart,rmin*sinStart,-dz);
pols[0][2].set(rmax*cosStart,rmax*sinStart,-dz);
pols[0][3].set(rmax*cosStart,rmax*sinStart, dz);
for (G4int k=1; k<ksteps+1; ++k)
{
pols[k][0].set(rmin*cosCur,rmin*sinCur, dz);
pols[k][1].set(rmin*cosCur,rmin*sinCur,-dz);
pols[k][2].set(rext*cosCur,rext*sinCur,-dz);
pols[k][3].set(rext*cosCur,rext*sinCur, dz);
G4double sinTmp = sinCur;
sinCur = sinCur*cosStep + cosCur*sinStep;
cosCur = cosCur*cosStep - sinTmp*sinStep;
}
pols[ksteps+1][0].set(rmin*cosEnd,rmin*sinEnd, dz);
pols[ksteps+1][1].set(rmin*cosEnd,rmin*sinEnd,-dz);
pols[ksteps+1][2].set(rmax*cosEnd,rmax*sinEnd,-dz);
pols[ksteps+1][3].set(rmax*cosEnd,rmax*sinEnd, dz);
// set envelope and calculate extent
std::vector<const G4ThreeVectorList *> polygons;
polygons.resize(ksteps+2);
for (G4int k=0; k<ksteps+2; ++k) polygons[k] = &pols[k];
G4BoundingEnvelope benv(bmin,bmax,polygons);
exist = benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
}
return exist;
}
//////////////////////////////////////////////////////////////////////////
//
// Create polyhedron for visualization