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