Import Geant4 10.7.0 source tree

This commit is contained in:
Gabriele Cosmo
2020-12-04 12:30:43 +01:00
parent 67ba86d073
commit dab42d2018
3770 changed files with 226369 additions and 286486 deletions
+22
View File
@@ -16,6 +16,28 @@ committal in the CVS repository !
* Reverse chronological order (last date on top), please *
----------------------------------------------------------
November 12, 2020 E.Tcherniaev geom-csg-V10-06-05
- G4Sphere::InitializeThetaTrigonometry(): tan() replaced with sin()/cos(),
it addresses problem report #2289
October 08, 2020 E.Tcherniaev geom-csg-V10-06-04
- G4Box: Migration to G4QuickRand in GetPointOnSurface();
- G4Trd: Added two precalculated values fHx, fHy for fast calculation
of lateral areas; Revision of GetPointOnSurface();
- G4Trap: Added array fAreas[6] with precalculated face areas;
Added SetCachedValues() method; Revision of GetPointOnSurface();
- G4Tubs: Revision of GetPointOnSurface();
- G4CSGSolid: Explicit implementation of G4RandomRadiusInRing(rmin,rmax)
based on G4QuickRand
October 06, 2020 E.Tcherniaev geom-csg-V10-06-03
- Improved G4CutTubs:
o Implemented GetCubicVolume(), GetSurfaceArea();
o Reimplemented GetPointOnSurface(), it's now faster and uniform;
o Reimplemented IsCrossingCutPlanes(), it now reports a problem
only in case if cut planes are crossing inside the lateral surface;
o Removed GetMaxMinZ() as obsolete;
April 30, 2020 G.Cosmo geom-csg-V10-06-02
- Adopt new convention for location of headers in VecGeom for all wrappers.
@@ -99,8 +99,8 @@ class G4CutTubs : public G4CSGSolid
// Methods for solid
inline G4double GetCubicVolume();
inline G4double GetSurfaceArea();
G4double GetCubicVolume();
G4double GetSurfaceArea();
void BoundingLimits(G4ThreeVector& pMin, G4ThreeVector& pMax) const;
@@ -182,17 +182,14 @@ class G4CutTubs : public G4CSGSolid
G4double GetCutZ(const G4ThreeVector& p) const;
// Get Z value of the point on Cutted Plane
void GetMaxMinZ(G4double& zmin,G4double& zmax)const;
// Get Max and Min values of Z on Cutted Plane,
// Used for Calculate BoundingLimits()
private:
G4double kRadTolerance, kAngTolerance;
//
// Radial and angular tolerances
G4double fRMin, fRMax, fDz, fSPhi, fDPhi;
G4double fRMin, fRMax, fDz, fSPhi, fDPhi;
mutable G4double fZMin, fZMax;
//
// Radial and angular dimensions
@@ -95,6 +95,8 @@ G4ThreeVector G4CutTubs::GetHighNorm () const
inline
void G4CutTubs::Initialize()
{
fZMin = 0.;
fZMax = 0.;
fCubicVolume = 0.;
fSurfaceArea = 0.;
fRebuildPolyhedron = true;
@@ -272,15 +274,3 @@ G4double G4CutTubs::GetDPhi () const
{
return GetDeltaPhiAngle();
}
inline G4double G4CutTubs::GetCubicVolume()
{
if (fCubicVolume == 0.) { fCubicVolume = G4VSolid::GetCubicVolume(); }
return fCubicVolume;
}
inline G4double G4CutTubs::GetSurfaceArea()
{
if (fSurfaceArea == 0.) { fSurfaceArea = G4VSolid::GetSurfaceArea(); }
return fSurfaceArea;
}
@@ -151,9 +151,9 @@ void G4Sphere::InitializeThetaTrigonometry()
sinETheta = std::sin(eTheta);
cosETheta = std::cos(eTheta);
tanSTheta = std::tan(fSTheta);
tanSTheta = sinSTheta/cosSTheta;
tanSTheta2 = tanSTheta*tanSTheta;
tanETheta = std::tan(eTheta);
tanETheta = sinETheta/cosETheta;
tanETheta2 = tanETheta*tanETheta;
}
@@ -252,6 +252,7 @@ class G4Trap : public G4CSGSolid
const G4ThreeVector& p3,
const G4ThreeVector& p4,
TrapSidePlane& plane ) ;
void SetCachedValues();
private:
@@ -272,6 +273,7 @@ class G4Trap : public G4CSGSolid
G4double fDy1,fDx1,fDx2,fTalpha1;
G4double fDy2,fDx3,fDx4,fTalpha2;
TrapSidePlane fPlanes[4];
G4double fAreas[6];
G4int fTrapType;
};
+1 -1
View File
@@ -166,7 +166,7 @@ class G4Trd : public G4CSGSolid
private:
G4double halfCarTolerance;
G4double fDx1,fDx2,fDy1,fDy2,fDz;
G4double fDx1,fDx2,fDy1,fDy2,fDz,fHx,fHy;
struct { G4double a,b,c,d; } fPlanes[4];
};
+31 -31
View File
@@ -38,7 +38,7 @@
#include "G4VoxelLimits.hh"
#include "G4AffineTransform.hh"
#include "G4BoundingEnvelope.hh"
#include "Randomize.hh"
#include "G4QuickRand.hh"
#include "G4VPVParameterisation.hh"
@@ -140,13 +140,13 @@ void G4Box::SetXHalfLength(G4double dx)
fCubicVolume = 0.;
fSurfaceArea = 0.;
fRebuildPolyhedron = true;
}
}
//////////////////////////////////////////////////////////////////////////
//
// Set Y dimension
void G4Box::SetYHalfLength(G4double dy)
void G4Box::SetYHalfLength(G4double dy)
{
if(dy > 2*kCarTolerance) // limit to thickness of surfaces
{
@@ -163,7 +163,7 @@ void G4Box::SetYHalfLength(G4double dy)
fCubicVolume = 0.;
fSurfaceArea = 0.;
fRebuildPolyhedron = true;
}
}
//////////////////////////////////////////////////////////////////////////
//
@@ -186,7 +186,7 @@ void G4Box::SetZHalfLength(G4double dz)
fCubicVolume = 0.;
fSurfaceArea = 0.;
fRebuildPolyhedron = true;
}
}
//////////////////////////////////////////////////////////////////////////
//
@@ -252,8 +252,8 @@ EInside G4Box::Inside(const G4ThreeVector& p) const
std::abs(p.x())-fDx,
std::abs(p.y())-fDy),
std::abs(p.z())-fDz);
if (dist > delta) return kOutside;
return (dist > -delta) ? kSurface : kInside;
return (dist > delta) ? kOutside :
((dist > -delta) ? kSurface : kInside);
}
//////////////////////////////////////////////////////////////////////////
@@ -278,7 +278,7 @@ G4ThreeVector G4Box::SurfaceNormal( const G4ThreeVector& p) const
else
{
// Point is not on the surface
//
//
#ifdef G4CSGDEBUG
std::ostringstream message;
G4int oldprc = message.precision(16);
@@ -353,7 +353,7 @@ G4double G4Box::DistanceToIn(const G4ThreeVector& p,
}
//////////////////////////////////////////////////////////////////////////
//
//
// Appoximate distance to box.
// Returns largest perpendicular distance to the closest x/y/z sides of
// the box, which is the most fast estimation of the shortest distance to box
@@ -361,9 +361,10 @@ G4double G4Box::DistanceToIn(const G4ThreeVector& p,
G4double G4Box::DistanceToIn(const G4ThreeVector& p) const
{
G4double dist = std::max(std::max(std::abs(p.x())-fDx,
std::abs(p.y())-fDy),
std::abs(p.z())-fDz);
G4double dist = std::max(std::max(
std::abs(p.x())-fDx,
std::abs(p.y())-fDy),
std::abs(p.z())-fDz);
return (dist > 0) ? dist : 0.;
}
@@ -456,9 +457,10 @@ G4double G4Box::DistanceToOut(const G4ThreeVector& p) const
DumpInfo();
}
#endif
G4double dist = std::min(std::min(fDx-std::abs(p.x()),
fDy-std::abs(p.y())),
fDz-std::abs(p.z()));
G4double dist = std::min(std::min(
fDx-std::abs(p.x()),
fDy-std::abs(p.y())),
fDz-std::abs(p.z()));
return (dist > 0) ? dist : 0.;
}
@@ -493,29 +495,27 @@ std::ostream& G4Box::StreamInfo(std::ostream& os) const
//////////////////////////////////////////////////////////////////////////
//
// GetPointOnSurface
//
// Return a point (G4ThreeVector) randomly and uniformly selected
// on the solid surface
// Return a point randomly and uniformly selected on the surface
G4ThreeVector G4Box::GetPointOnSurface() const
{
G4double sxy = fDx*fDy, sxz = fDx*fDz, syz = fDy*fDz;
G4double select = (sxy + sxz + syz)*G4UniformRand();
G4double select = (sxy + sxz + syz)*G4QuickRand();
G4double u = 2.*G4QuickRand() - 1.;
G4double v = 2.*G4QuickRand() - 1.;
if (select < sxy)
return G4ThreeVector((2.*G4UniformRand() - 1.)*fDx,
(2.*G4UniformRand() - 1.)*fDy,
(select < 0.5*sxy) ? -fDz : fDz);
if (select < sxy + sxz)
return G4ThreeVector((2.*G4UniformRand() - 1.)*fDx,
(select < sxy + 0.5*sxz) ? -fDy : fDy,
(2.*G4UniformRand() - 1.)*fDz);
return G4ThreeVector(u*fDx,
v*fDy,
((select < 0.5*sxy) ? -fDz : fDz));
else if (select < sxy + sxz)
return G4ThreeVector(u*fDx,
((select < sxy + 0.5*sxz) ? -fDy : fDy),
v*fDz);
else
return G4ThreeVector((select < sxy + sxz + 0.5*syz) ? -fDx : fDx,
(2.*G4UniformRand() - 1.)*fDy,
(2.*G4UniformRand() - 1.)*fDz);
return G4ThreeVector(((select < sxy + sxz + 0.5*syz) ? -fDx : fDx),
u*fDy,
v*fDz);
}
//////////////////////////////////////////////////////////////////////////
+8 -7
View File
@@ -31,8 +31,7 @@
#include <cmath>
#include "G4CSGSolid.hh"
#include "Randomize.hh"
#include "G4RandomTools.hh"
#include "G4QuickRand.hh"
#include "G4Polyhedron.hh"
#include "G4AutoLock.hh"
@@ -45,7 +44,7 @@ namespace
//////////////////////////////////////////////////////////////////////////
//
// Constructor
// - Base class constructor
// - Base class constructor
G4CSGSolid::G4CSGSolid(const G4String& name) :
G4VSolid(name)
@@ -67,7 +66,7 @@ G4CSGSolid::G4CSGSolid( __void__& a )
// Destructor
//
G4CSGSolid::~G4CSGSolid()
G4CSGSolid::~G4CSGSolid()
{
delete fpPolyhedron; fpPolyhedron = nullptr;
}
@@ -87,7 +86,7 @@ G4CSGSolid::G4CSGSolid(const G4CSGSolid& rhs)
//
// Assignment operator
G4CSGSolid& G4CSGSolid::operator = (const G4CSGSolid& rhs)
G4CSGSolid& G4CSGSolid::operator = (const G4CSGSolid& rhs)
{
// Check assignment to self
//
@@ -105,11 +104,13 @@ G4CSGSolid& G4CSGSolid::operator = (const G4CSGSolid& rhs)
delete fpPolyhedron; fpPolyhedron = nullptr;
return *this;
}
}
G4double G4CSGSolid::GetRadiusInRing(G4double rmin, G4double rmax) const
{
return G4RandomRadiusInRing(rmin, rmax);
G4double k = G4QuickRand();
return (rmin <= 0) ? rmax*std::sqrt(k)
: std::sqrt(k*rmax*rmax + (1. - k)*rmin*rmin);
}
std::ostream& G4CSGSolid::StreamInfo(std::ostream& os) const
File diff suppressed because it is too large Load Diff
+115 -95
View File
@@ -28,7 +28,7 @@
// 21.03.95 P.Kent: Modified for `tolerant' geometry
// 09.09.96 V.Grichine: Final modifications before to commit
// 08.12.97 J.Allison: Added "nominal" constructor and method SetAllParameters
// 28.04.05 V.Grichine: new SurfaceNormal according to J.Apostolakis proposal
// 28.04.05 V.Grichine: new SurfaceNormal according to J.Apostolakis proposal
// 18.04.17 E.Tcherniaev: complete revision, speed-up
// --------------------------------------------------------------------
@@ -45,7 +45,7 @@
#include "G4VPVParameterisation.hh"
#include "Randomize.hh"
#include "G4QuickRand.hh"
#include "G4VGraphicsScene.hh"
#include "G4Polyhedron.hh"
@@ -54,7 +54,7 @@ using namespace CLHEP;
//////////////////////////////////////////////////////////////////////////
//
// Constructor - check and set half-widths as well as angles:
// Constructor - check and set half-widths as well as angles:
// final check of coplanarity
G4Trap::G4Trap( const G4String& pName,
@@ -79,8 +79,8 @@ G4Trap::G4Trap( const G4String& pName,
//////////////////////////////////////////////////////////////////////////
//
// Constructor - Design of trapezoid based on 8 G4ThreeVector parameters,
// which are its vertices. Checking of planarity with preparation of
// Constructor - Design of trapezoid based on 8 G4ThreeVector parameters,
// which are its vertices. Checking of planarity with preparation of
// fPlanes[] and than calculation of other members
G4Trap::G4Trap( const G4String& pName,
@@ -116,11 +116,11 @@ G4Trap::G4Trap( const G4String& pName,
G4Exception("G4Trap::G4Trap()", "GeomSolids0002",
FatalException, message);
}
// Set parameters
//
fDz = (pt[7]).z();
fDy1 = ((pt[2]).y()-(pt[1]).y())*0.5;
fDx1 = ((pt[1]).x()-(pt[0]).x())*0.5;
fDx2 = ((pt[3]).x()-(pt[2]).x())*0.5;
@@ -244,6 +244,7 @@ G4Trap::G4Trap(const G4Trap& rhs)
fDy2(rhs.fDy2), fDx3(rhs.fDx3), fDx4(rhs.fDx4), fTalpha2(rhs.fTalpha2)
{
for (G4int i=0; i<4; ++i) { fPlanes[i] = rhs.fPlanes[i]; }
for (G4int i=0; i<6; ++i) { fAreas[i] = rhs.fAreas[i]; }
fTrapType = rhs.fTrapType;
}
@@ -251,7 +252,7 @@ G4Trap::G4Trap(const G4Trap& rhs)
//
// Assignment operator
G4Trap& G4Trap::operator = (const G4Trap& rhs)
G4Trap& G4Trap::operator = (const G4Trap& rhs)
{
// Check assignment to self
//
@@ -268,6 +269,7 @@ G4Trap& G4Trap::operator = (const G4Trap& rhs)
fDy1 = rhs.fDy1; fDx1 = rhs.fDx1; fDx2 = rhs.fDx2; fTalpha1 = rhs.fTalpha1;
fDy2 = rhs.fDy2; fDx3 = rhs.fDx3; fDx4 = rhs.fDx4; fTalpha2 = rhs.fTalpha2;
for (G4int i=0; i<4; ++i) { fPlanes[i] = rhs.fPlanes[i]; }
for (G4int i=0; i<6; ++i) { fAreas[i] = rhs.fAreas[i]; }
fTrapType = rhs.fTrapType;
return *this;
}
@@ -358,8 +360,8 @@ void G4Trap::MakePlanes()
void G4Trap::MakePlanes(const G4ThreeVector pt[8])
{
G4int iface[4][4] = { {0,4,5,1}, {2,3,7,6}, {0,2,6,4}, {1,5,7,3} };
G4String side[4] = { "~-Y", "~+Y", "~-X", "~+X" };
constexpr G4int iface[4][4] = { {0,4,5,1}, {2,3,7,6}, {0,2,6,4}, {1,5,7,3} };
const static G4String side[4] = { "~-Y", "~+Y", "~-X", "~+X" };
for (G4int i=0; i<4; ++i)
{
@@ -385,6 +387,70 @@ void G4Trap::MakePlanes(const G4ThreeVector pt[8])
FatalException, message);
}
// Re-compute parameters
SetCachedValues();
}
//////////////////////////////////////////////////////////////////////////
//
// Calculate the coef's of the plane p1->p2->p3->p4->p1
// where the ThreeVectors 1-4 are in anti-clockwise order when viewed
// from infront of the plane (i.e. from normal direction).
//
// Return true if the points are coplanar, false otherwise
G4bool G4Trap::MakePlane( const G4ThreeVector& p1,
const G4ThreeVector& p2,
const G4ThreeVector& p3,
const G4ThreeVector& p4,
TrapSidePlane& plane )
{
G4ThreeVector normal = ((p4 - p2).cross(p3 - p1)).unit();
if (std::abs(normal.x()) < DBL_EPSILON) normal.setX(0);
if (std::abs(normal.y()) < DBL_EPSILON) normal.setY(0);
if (std::abs(normal.z()) < DBL_EPSILON) normal.setZ(0);
normal = normal.unit();
G4ThreeVector centre = (p1 + p2 + p3 + p4)*0.25;
plane.a = normal.x();
plane.b = normal.y();
plane.c = normal.z();
plane.d = -normal.dot(centre);
// compute distances and check planarity
G4double d1 = std::abs(normal.dot(p1) + plane.d);
G4double d2 = std::abs(normal.dot(p2) + plane.d);
G4double d3 = std::abs(normal.dot(p3) + plane.d);
G4double d4 = std::abs(normal.dot(p4) + plane.d);
G4double dmax = std::max(std::max(std::max(d1,d2),d3),d4);
return (dmax > 1000 * kCarTolerance) ? false : true;
}
//////////////////////////////////////////////////////////////////////////
//
// Recompute parameters using planes
void G4Trap::SetCachedValues()
{
// Set indeces
constexpr G4int iface[6][4] =
{ {0,1,3,2}, {0,4,5,1}, {2,3,7,6}, {0,2,6,4}, {1,5,7,3}, {4,6,7,5} };
// Get vertices
G4ThreeVector pt[8];
GetVertices(pt);
// Set face areas
for (G4int i=0; i<6; ++i)
{
fAreas[i] = G4GeomTools::QuadAreaNormal(pt[iface[i][0]],
pt[iface[i][1]],
pt[iface[i][2]],
pt[iface[i][3]]).mag();
}
for (G4int i=1; i<6; ++i) { fAreas[i] += fAreas[i - 1]; }
// Define type of trapezoid
fTrapType = 0;
if (fPlanes[0].b == -1 && fPlanes[1].b == 1 &&
@@ -415,43 +481,7 @@ void G4Trap::MakePlanes(const G4ThreeVector pt[8])
}
}
///////////////////////////////////////////////////////////////////////
//
// Calculate the coef's of the plane p1->p2->p3->p4->p1
// where the ThreeVectors 1-4 are in anti-clockwise order when viewed
// from infront of the plane (i.e. from normal direction).
//
// Return true if the points are coplanar, false otherwise
G4bool G4Trap::MakePlane( const G4ThreeVector& p1,
const G4ThreeVector& p2,
const G4ThreeVector& p3,
const G4ThreeVector& p4,
TrapSidePlane& plane )
{
G4ThreeVector normal = ((p4 - p2).cross(p3 - p1)).unit();
if (std::abs(normal.x()) < DBL_EPSILON) normal.setX(0);
if (std::abs(normal.y()) < DBL_EPSILON) normal.setY(0);
if (std::abs(normal.z()) < DBL_EPSILON) normal.setZ(0);
normal = normal.unit();
G4ThreeVector centre = (p1 + p2 + p3 + p4)*0.25;
plane.a = normal.x();
plane.b = normal.y();
plane.c = normal.z();
plane.d = -normal.dot(centre);
// compute distances and check planarity
G4double d1 = std::abs(normal.dot(p1) + plane.d);
G4double d2 = std::abs(normal.dot(p2) + plane.d);
G4double d3 = std::abs(normal.dot(p3) + plane.d);
G4double d4 = std::abs(normal.dot(p4) + plane.d);
G4double dmax = std::max(std::max(std::max(d1,d2),d3),d4);
return (dmax > 1000 * kCarTolerance) ? false : true;
}
///////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Get volume
@@ -461,7 +491,7 @@ G4double G4Trap::GetCubicVolume()
{
G4ThreeVector pt[8];
GetVertices(pt);
G4double dz = pt[4].z() - pt[0].z();
G4double dy1 = pt[2].y() - pt[0].y();
G4double dx1 = pt[1].x() - pt[0].x();
@@ -476,7 +506,7 @@ G4double G4Trap::GetCubicVolume()
return fCubicVolume;
}
///////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Get surface area
@@ -500,7 +530,7 @@ G4double G4Trap::GetSurfaceArea()
return fSurfaceArea;
}
///////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Dispatch to parameterisation for replication mechanism dimension
// computation & modification.
@@ -512,7 +542,7 @@ void G4Trap::ComputeDimensions( G4VPVParameterisation* p,
p->ComputeDimensions(*this,n,pRep);
}
///////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Get bounding box
@@ -552,7 +582,7 @@ void G4Trap::BoundingLimits(G4ThreeVector& pMin, G4ThreeVector& pMax) const
}
}
///////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
@@ -601,7 +631,7 @@ G4bool G4Trap::CalculateExtent( const EAxis pAxis,
return exist;
}
///////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Return whether point is inside/outside/on_surface
@@ -661,10 +691,10 @@ EInside G4Trap::Inside( const G4ThreeVector& p ) const
((dist > -halfCarTolerance) ? kSurface : kInside);
}
}
return kOutside;
return kOutside;
}
///////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Determine side, and return corresponding normal
@@ -765,7 +795,7 @@ G4ThreeVector G4Trap::SurfaceNormal( const G4ThreeVector& p ) const
}
}
///////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Algorithm for SurfaceNormal() following the original specification
// for points not on the surface
@@ -789,7 +819,7 @@ G4ThreeVector G4Trap::ApproxSurfaceNormal( const G4ThreeVector& p ) const
return G4ThreeVector(0, 0, (p.z() < 0) ? -1 : 1);
}
///////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Calculate distance to shape from outside
// - return kInfinity if no intersection
@@ -802,7 +832,7 @@ G4double G4Trap::DistanceToIn(const G4ThreeVector& p,
if ((std::abs(p.z()) - fDz) >= -halfCarTolerance && p.z()*v.z() >= 0)
return kInfinity;
G4double invz = (-v.z() == 0) ? DBL_MAX : -1./v.z();
G4double dz = (invz < 0) ? fDz : -fDz;
G4double dz = (invz < 0) ? fDz : -fDz;
G4double tzmin = (p.z() + dz)*invz;
G4double tzmax = (p.z() - dz)*invz;
@@ -811,7 +841,7 @@ G4double G4Trap::DistanceToIn(const G4ThreeVector& p,
G4double tymin = 0, tymax = DBL_MAX;
G4int i = 0;
for ( ; i<2; ++i)
{
{
G4double cosa = fPlanes[i].b*v.y() + fPlanes[i].c*v.z();
G4double dist = fPlanes[i].b*p.y() + fPlanes[i].c*p.z() + fPlanes[i].d;
if (dist >= -halfCarTolerance)
@@ -824,14 +854,14 @@ G4double G4Trap::DistanceToIn(const G4ThreeVector& p,
{
G4double tmp = -dist/cosa;
if (tymax > tmp) tymax = tmp;
}
}
}
// Z intersections
//
G4double txmin = 0, txmax = DBL_MAX;
for ( ; i<4; ++i)
{
{
G4double cosa = fPlanes[i].a*v.x()+fPlanes[i].b*v.y()+fPlanes[i].c*v.z();
G4double dist = fPlanes[i].a*p.x()+fPlanes[i].b*p.y()+fPlanes[i].c*p.z() +
fPlanes[i].d;
@@ -845,19 +875,19 @@ G4double G4Trap::DistanceToIn(const G4ThreeVector& p,
{
G4double tmp = -dist/cosa;
if (txmax > tmp) txmax = tmp;
}
}
}
// Find distance
//
G4double tmin = std::max(std::max(txmin,tymin),tzmin);
G4double tmax = std::min(std::min(txmax,tymax),tzmax);
if (tmax <= tmin + halfCarTolerance) return kInfinity; // touch or no hit
return (tmin < halfCarTolerance ) ? 0. : tmin;
}
////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Calculate exact shortest distance to any boundary from outside
// This is the best fast estimation of the shortest distance to trap
@@ -914,7 +944,7 @@ G4double G4Trap::DistanceToIn( const G4ThreeVector& p ) const
return 0.;
}
////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Calculate distance to surface of shape from inside and
// find normal at exit point, if required
@@ -987,7 +1017,7 @@ G4double G4Trap::DistanceToOut(const G4ThreeVector& p, const G4ThreeVector& v,
// Set normal, if required, and return distance
//
if (calcNorm)
if (calcNorm)
{
*validNorm = true;
if (iside < 0)
@@ -998,7 +1028,7 @@ G4double G4Trap::DistanceToOut(const G4ThreeVector& p, const G4ThreeVector& v,
return tmax;
}
////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Calculate exact shortest distance to any boundary from inside
// - Returns 0 is ThreeVector outside
@@ -1015,7 +1045,7 @@ G4double G4Trap::DistanceToOut( const G4ThreeVector& p ) const
message << " p.x() = " << p.x()/mm << " mm\n";
message << " p.y() = " << p.y()/mm << " mm\n";
message << " p.z() = " << p.z()/mm << " mm";
G4cout.precision(oldprc) ;
G4cout.precision(oldprc);
G4Exception("G4Trap::DistanceToOut(p)", "GeomSolids1002",
JustWarning, message );
DumpInfo();
@@ -1070,7 +1100,7 @@ G4double G4Trap::DistanceToOut( const G4ThreeVector& p ) const
return 0.;
}
////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// GetEntityType
@@ -1099,7 +1129,7 @@ std::ostream& G4Trap::StreamInfo( std::ostream& os ) const
+fTthetaSphi*fTthetaSphi));
G4double alpha1 = std::atan(fTalpha1);
G4double alpha2 = std::atan(fTalpha2);
G4String signDegree = "\u00B0";
G4String signDegree = "\u00B0";
G4int oldprc = os.precision(16);
os << "-----------------------------------------------------------\n"
@@ -1142,38 +1172,29 @@ void G4Trap::GetVertices(G4ThreeVector pt[8]) const
}
}
/////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Generate random point on the surface
G4ThreeVector G4Trap::GetPointOnSurface() const
{
G4ThreeVector pt[8];
G4int iface [6][4] =
{ {0,1,3,2}, {0,4,5,1}, {2,3,7,6}, {0,2,6,4}, {1,5,7,3}, {4,6,7,5} };
G4double sface[6];
// Set indeces
constexpr G4int iface [6][4] =
{ {0,1,3,2}, {0,4,5,1}, {2,3,7,6}, {0,2,6,4}, {1,5,7,3}, {4,6,7,5} };
// Set vertices
G4ThreeVector pt[8];
GetVertices(pt);
G4double stotal = 0;
for (G4int i=0; i<6; ++i)
{
G4double ss = G4GeomTools::QuadAreaNormal(pt[iface[i][0]],
pt[iface[i][1]],
pt[iface[i][2]],
pt[iface[i][3]]).mag();
stotal += ss;
sface[i] = stotal;
}
// Select face
//
G4double select = stotal*G4UniformRand();
G4double select = fAreas[5]*G4QuickRand();
G4int k = 5;
if (select <= sface[4]) k = 4;
if (select <= sface[3]) k = 3;
if (select <= sface[2]) k = 2;
if (select <= sface[1]) k = 1;
if (select <= sface[0]) k = 0;
k -= (select <= fAreas[4]);
k -= (select <= fAreas[3]);
k -= (select <= fAreas[2]);
k -= (select <= fAreas[1]);
k -= (select <= fAreas[0]);
// Select sub-triangle
//
@@ -1181,14 +1202,13 @@ G4ThreeVector G4Trap::GetPointOnSurface() const
G4int i1 = iface[k][1];
G4int i2 = iface[k][2];
G4int i3 = iface[k][3];
G4double s1 = G4GeomTools::TriangleAreaNormal(pt[i0],pt[i1],pt[i3]).mag();
G4double s2 = G4GeomTools::TriangleAreaNormal(pt[i2],pt[i1],pt[i3]).mag();
if ((s1+s2)*G4UniformRand() > s1) i0 = i2;
if (select > fAreas[k] - s2) i0 = i2;
// Generate point
//
G4double u = G4UniformRand();
G4double v = G4UniformRand();
G4double u = G4QuickRand();
G4double v = G4QuickRand();
if (u + v > 1.) { u = 1. - u; v = 1. - v; }
return (1.-u-v)*pt[i0] + u*pt[i1] + v*pt[i3];
}
+87 -64
View File
@@ -26,7 +26,7 @@
// Implementation for G4Trd class
//
// 12.01.95 P.Kent: First version
// 28.04.05 V.Grichine: new SurfaceNormal according to J.Apostolakis proposal
// 28.04.05 V.Grichine: new SurfaceNormal according to J.Apostolakis proposal
// 25.05.17 E.Tcherniaev: complete revision, speed-up
// --------------------------------------------------------------------
@@ -39,7 +39,7 @@
#include "G4VoxelLimits.hh"
#include "G4AffineTransform.hh"
#include "G4BoundingEnvelope.hh"
#include "Randomize.hh"
#include "G4QuickRand.hh"
#include "G4VPVParameterisation.hh"
@@ -89,7 +89,8 @@ G4Trd::~G4Trd()
G4Trd::G4Trd(const G4Trd& rhs)
: G4CSGSolid(rhs), halfCarTolerance(rhs.halfCarTolerance),
fDx1(rhs.fDx1), fDx2(rhs.fDx2),
fDy1(rhs.fDy1), fDy2(rhs.fDy2), fDz(rhs.fDz)
fDy1(rhs.fDy1), fDy2(rhs.fDy2), fDz(rhs.fDz),
fHx(rhs.fHx), fHy(rhs.fHy)
{
for (G4int i=0; i<4; ++i) { fPlanes[i] = rhs.fPlanes[i]; }
}
@@ -114,6 +115,7 @@ G4Trd& G4Trd::operator = (const G4Trd& rhs)
fDx1 = rhs.fDx1; fDx2 = rhs.fDx2;
fDy1 = rhs.fDy1; fDy2 = rhs.fDy2;
fDz = rhs.fDz;
fHx = rhs.fHx; fHy = rhs.fHy;
for (G4int i=0; i<4; ++i) { fPlanes[i] = rhs.fPlanes[i]; }
return *this;
@@ -171,14 +173,14 @@ void G4Trd::MakePlanes()
G4double dx = fDx1 - fDx2;
G4double dy = fDy1 - fDy2;
G4double dz = 2*fDz;
G4double magx = std::sqrt(dx*dx + dz*dz);
G4double magy = std::sqrt(dy*dy + dz*dz);
fHx = std::sqrt(dy*dy + dz*dz);
fHy = std::sqrt(dx*dx + dz*dz);
// Set -Y & +Y planes
// Set X planes at -Y & +Y
//
fPlanes[0].a = 0.;
fPlanes[0].b = -dz/magy;
fPlanes[0].c = dy/magy;
fPlanes[0].b = -dz/fHx;
fPlanes[0].c = dy/fHx;
fPlanes[0].d = fPlanes[0].b*fDy1 + fPlanes[0].c*fDz;
fPlanes[1].a = fPlanes[0].a;
@@ -186,11 +188,11 @@ void G4Trd::MakePlanes()
fPlanes[1].c = fPlanes[0].c;
fPlanes[1].d = fPlanes[0].d;
// Set -X & +X planes
// Set Y planes at -X & +X
//
fPlanes[2].a = -dz/magx;
fPlanes[2].a = -dz/fHy;
fPlanes[2].b = 0.;
fPlanes[2].c = dx/magx;
fPlanes[2].c = dx/fHy;
fPlanes[2].d = fPlanes[2].a*fDx1 + fPlanes[2].c*fDz;
fPlanes[3].a = -fPlanes[2].a;
@@ -222,9 +224,7 @@ G4double G4Trd::GetSurfaceArea()
if (fSurfaceArea == 0.)
{
fSurfaceArea =
4*(fDx1*fDy1+fDx2*fDy2) +
2*(fDy1+fDy2)*std::hypot(fDx1-fDx2,2*fDz) +
2*(fDx1+fDx2)*std::hypot(fDy1-fDy2,2*fDz);
4*(fDx1*fDy1 + fDx2*fDy2) + 2*(fDx1+fDx2)*fHx + 2*(fDy1+fDy2)*fHy;
}
return fSurfaceArea;
}
@@ -328,7 +328,7 @@ G4bool G4Trd::CalculateExtent( const EAxis pAxis,
// Return whether point inside/outside/on surface, using tolerance
EInside G4Trd::Inside( const G4ThreeVector& p ) const
{
{
G4double dx = fPlanes[3].a*std::abs(p.x())+fPlanes[3].c*p.z()+fPlanes[3].d;
G4double dy = fPlanes[1].b*std::abs(p.y())+fPlanes[1].c*p.z()+fPlanes[1].d;
G4double dxy = std::max(dx,dy);
@@ -336,8 +336,8 @@ EInside G4Trd::Inside( const G4ThreeVector& p ) const
G4double dz = std::abs(p.z())-fDz;
G4double dist = std::max(dz,dxy);
if (dist > halfCarTolerance) return kOutside;
return (dist > -halfCarTolerance) ? kSurface : kInside;
return (dist > halfCarTolerance) ? kOutside :
((dist > -halfCarTolerance) ? kSurface : kInside);
}
//////////////////////////////////////////////////////////////////////////
@@ -457,7 +457,7 @@ G4double G4Trd::DistanceToIn(const G4ThreeVector& p,
if ((std::abs(p.z()) - fDz) >= -halfCarTolerance && p.z()*v.z() >= 0)
return kInfinity;
G4double invz = (-v.z() == 0) ? DBL_MAX : -1./v.z();
G4double dz = (invz < 0) ? fDz : -fDz;
G4double dz = (invz < 0) ? fDz : -fDz;
G4double tzmin = (p.z() + dz)*invz;
G4double tzmax = (p.z() - dz)*invz;
@@ -626,7 +626,7 @@ G4double G4Trd::DistanceToOut(const G4ThreeVector& p, const G4ThreeVector& v,
// Set normal, if required, and return distance
//
if (calcNorm)
if (calcNorm)
{
*validNorm = true;
if (iside < 0)
@@ -654,7 +654,7 @@ G4double G4Trd::DistanceToOut( const G4ThreeVector& p ) const
message << " p.x() = " << p.x()/mm << " mm\n";
message << " p.y() = " << p.y()/mm << " mm\n";
message << " p.z() = " << p.z()/mm << " mm";
G4cout.precision(oldprc) ;
G4cout.precision(oldprc);
G4Exception("G4Trd::DistanceToOut(p)", "GeomSolids1002",
JustWarning, message );
DumpInfo();
@@ -666,7 +666,7 @@ G4double G4Trd::DistanceToOut( const G4ThreeVector& p ) const
G4double dz = std::abs(p.z())-fDz;
G4double dist = std::max(dz,dxy);
return (dist < 0) ? -dist : 0.;
}
@@ -717,56 +717,79 @@ std::ostream& G4Trd::StreamInfo( std::ostream& os ) const
G4ThreeVector G4Trd::GetPointOnSurface() const
{
// Set vertices
//
G4ThreeVector pt[8];
pt[0].set(-fDx1,-fDy1,-fDz);
pt[1].set( fDx1,-fDy1,-fDz);
pt[2].set(-fDx1, fDy1,-fDz);
pt[3].set( fDx1, fDy1,-fDz);
pt[4].set(-fDx2,-fDy2, fDz);
pt[5].set( fDx2,-fDy2, fDz);
pt[6].set(-fDx2, fDy2, fDz);
pt[7].set( fDx2, fDy2, fDz);
// Set faces (-Z, -Y, +Y, -X, +X, +Z)
//
G4int iface [6][4] =
{ {0,1,3,2}, {0,4,5,1}, {2,3,7,6}, {0,2,6,4}, {1,5,7,3}, {4,6,7,5} };
// Set areas
//
G4double sxz = (fDy1 + fDy2)*std::hypot(fDx1 - fDx2, 2*fDz);
G4double syz = (fDx1 + fDx2)*std::hypot(fDy1 - fDy2, 2*fDz);
G4double sface[6] = { 4*fDx1*fDy1, syz, syz, sxz, sxz, 4*fDx2*fDy2 };
for (G4int i=1; i<6; ++i) { sface[i] += sface[i-1]; }
//
G4double sxz = (fDx1 + fDx2)*fHx;
G4double syz = (fDy1 + fDy2)*fHy;
G4double ssurf[6] = { 4.*fDx1*fDy1, sxz, sxz, syz, syz, 4.*fDx2*fDy2 };
ssurf[1] += ssurf[0];
ssurf[2] += ssurf[1];
ssurf[3] += ssurf[2];
ssurf[4] += ssurf[3];
ssurf[5] += ssurf[4];
// Select face
//
G4double select = sface[5]*G4UniformRand();
G4double select = ssurf[5]*G4QuickRand();
G4int k = 5;
if (select <= sface[4]) k = 4;
if (select <= sface[3]) k = 3;
if (select <= sface[2]) k = 2;
if (select <= sface[1]) k = 1;
if (select <= sface[0]) k = 0;
k -= (select <= ssurf[4]);
k -= (select <= ssurf[3]);
k -= (select <= ssurf[2]);
k -= (select <= ssurf[1]);
k -= (select <= ssurf[0]);
// Select sub-triangle
// Generate point on selected surface
//
G4int i0 = iface[k][0];
G4int i1 = iface[k][1];
G4int i2 = iface[k][2];
G4int i3 = iface[k][3];
G4double s1 = G4GeomTools::TriangleAreaNormal(pt[i0],pt[i1],pt[i3]).mag();
G4double s2 = G4GeomTools::TriangleAreaNormal(pt[i2],pt[i1],pt[i3]).mag();
if ((s1+s2)*G4UniformRand() > s1) i0 = i2;
// Generate point
//
G4double u = G4UniformRand();
G4double v = G4UniformRand();
if (u + v > 1.) { u = 1. - u; v = 1. - v; }
return (1.-u-v)*pt[i0] + u*pt[i1] + v*pt[i3];
G4double u = G4QuickRand();
G4double v = G4QuickRand();
switch(k)
{
case 0: // base at -Z
{
return G4ThreeVector((2.*u - 1.)*fDx1, (2.*v - 1.)*fDy1, -fDz);
}
case 1: // X face at -Y
{
if (u + v > 1.) { u = 1. - u; v = 1. - v; }
G4ThreeVector p0(-fDx1,-fDy1,-fDz);
G4ThreeVector p1( fDx2,-fDy2, fDz);
return (select <= ssurf[0] + fDx1*fHx) ?
(1. - u - v)*p0 + u*p1 + v*G4ThreeVector( fDx1,-fDy1,-fDz) :
(1. - u - v)*p0 + u*p1 + v*G4ThreeVector(-fDx2,-fDy2, fDz);
}
case 2: // X face at +Y
{
if (u + v > 1.) { u = 1. - u; v = 1. - v; }
G4ThreeVector p0( fDx1, fDy1,-fDz);
G4ThreeVector p1(-fDx2, fDy2, fDz);
return (select <= ssurf[1] + fDx1*fHx) ?
(1. - u - v)*p0 + u*p1 + v*G4ThreeVector(-fDx1, fDy1,-fDz) :
(1. - u - v)*p0 + u*p1 + v*G4ThreeVector( fDx2, fDy2, fDz);
}
case 3: // Y face at -X
{
if (u + v > 1.) { u = 1. - u; v = 1. - v; }
G4ThreeVector p0(-fDx1, fDy1,-fDz);
G4ThreeVector p1(-fDx2,-fDy2, fDz);
return (select <= ssurf[2] + fDy1*fHy) ?
(1. - u - v)*p0 + u*p1 + v*G4ThreeVector(-fDx1,-fDy1,-fDz) :
(1. - u - v)*p0 + u*p1 + v*G4ThreeVector(-fDx2, fDy2, fDz);
}
case 4: // Y face at +X
{
if (u + v > 1.) { u = 1. - u; v = 1. - v; }
G4ThreeVector p0( fDx1,-fDy1,-fDz);
G4ThreeVector p1( fDx2, fDy2, fDz);
return (select <= ssurf[3] + fDy1*fHy) ?
(1. - u - v)*p0 + u*p1 + v*G4ThreeVector( fDx1, fDy1,-fDz) :
(1. - u - v)*p0 + u*p1 + v*G4ThreeVector( fDx2,-fDy2, fDz);
}
case 5: // base at +Z
{
return G4ThreeVector((2.*u - 1.)*fDx2, (2.*v - 1.)*fDy2, fDz);
}
}
return G4ThreeVector(0., 0., 0.);
}
//////////////////////////////////////////////////////////////////////////
+153 -144
View File
@@ -43,12 +43,10 @@
#include "G4BoundingEnvelope.hh"
#include "G4VPVParameterisation.hh"
#include "Randomize.hh"
#include "meshdefs.hh"
#include "G4QuickRand.hh"
#include "G4VGraphicsScene.hh"
#include "G4Polyhedron.hh"
using namespace CLHEP;
@@ -103,7 +101,7 @@ G4Tubs::G4Tubs( __void__& a )
fRMin(0.), fRMax(0.), fDz(0.), fSPhi(0.), fDPhi(0.),
sinCPhi(0.), cosCPhi(0.), cosHDPhi(0.), cosHDPhiOT(0.), cosHDPhiIT(0.),
sinSPhi(0.), cosSPhi(0.), sinEPhi(0.), cosEPhi(0.),
fPhiFullTube(false), fInvRmax(0.), fInvRmin(0.),
fPhiFullTube(false), fInvRmax(0.), fInvRmin(0.),
halfCarTolerance(0.), halfRadTolerance(0.),
halfAngTolerance(0.)
{
@@ -141,7 +139,7 @@ G4Tubs::G4Tubs(const G4Tubs& rhs)
//
// Assignment operator
G4Tubs& G4Tubs::operator = (const G4Tubs& rhs)
G4Tubs& G4Tubs::operator = (const G4Tubs& rhs)
{
// Check assignment to self
//
@@ -232,7 +230,7 @@ void G4Tubs::BoundingLimits(G4ThreeVector& pMin, G4ThreeVector& pMax) const
G4bool G4Tubs::CalculateExtent( const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin,
G4double& pMin,
G4double& pMax ) const
{
G4ThreeVector bmin, bmax;
@@ -352,7 +350,7 @@ EInside G4Tubs::Inside( const G4ThreeVector& p ) const
else { tolRMin = 0 ; }
tolRMax = fRMax - halfRadTolerance ;
if ((r2 >= tolRMin*tolRMin) && (r2 <= tolRMax*tolRMax))
{
if ( fPhiFullTube )
@@ -378,7 +376,7 @@ EInside G4Tubs::Inside( const G4ThreeVector& p ) const
{
if ( (std::fabs(pPhi) < halfAngTolerance)
&& (std::fabs(fSPhi + fDPhi - twopi) < halfAngTolerance) )
{
{
pPhi += twopi ; // 0 <= pPhi < 2pi
}
if ( (pPhi >= fSPhi + halfAngTolerance)
@@ -406,7 +404,7 @@ EInside G4Tubs::Inside( const G4ThreeVector& p ) const
in = kInside ;
}
}
}
}
}
}
else // Try generous boundaries
@@ -431,7 +429,7 @@ EInside G4Tubs::Inside( const G4ThreeVector& p ) const
{
if ( (std::fabs(pPhi) < halfAngTolerance)
&& (std::fabs(fSPhi + fDPhi - twopi) < halfAngTolerance) )
{
{
pPhi += twopi ; // 0 <= pPhi < 2pi
}
if ( (pPhi >= fSPhi - halfAngTolerance)
@@ -476,7 +474,7 @@ EInside G4Tubs::Inside( const G4ThreeVector& p ) const
{
if ( (std::fabs(pPhi) < halfAngTolerance)
&& (std::fabs(fSPhi + fDPhi - twopi) < halfAngTolerance) )
{
{
pPhi += twopi ; // 0 <= pPhi < 2pi
}
if ( (pPhi >= fSPhi - halfAngTolerance)
@@ -493,7 +491,7 @@ EInside G4Tubs::Inside( const G4ThreeVector& p ) const
{
in = kSurface ;
}
}
}
}
}
}
@@ -523,22 +521,22 @@ G4ThreeVector G4Tubs::SurfaceNormal( const G4ThreeVector& p ) const
distRMax = std::fabs(rho - fRMax);
distZ = std::fabs(std::fabs(p.z()) - fDz);
if (!fPhiFullTube) // Protected against (0,0,z)
if (!fPhiFullTube) // Protected against (0,0,z)
{
if ( rho > halfCarTolerance )
{
pPhi = std::atan2(p.y(),p.x());
if (pPhi < fSPhi-halfCarTolerance) { pPhi += twopi; }
else if (pPhi > fSPhi+fDPhi+halfCarTolerance) { pPhi -= twopi; }
distSPhi = std::fabs( pPhi - fSPhi );
distEPhi = std::fabs( pPhi - fSPhi - fDPhi );
distSPhi = std::fabs( pPhi - fSPhi );
distEPhi = std::fabs( pPhi - fSPhi - fDPhi );
}
else if ( !fRMin )
{
distSPhi = 0.;
distEPhi = 0.;
distSPhi = 0.;
distEPhi = 0.;
}
nPs = G4ThreeVector( sinSPhi, -cosSPhi, 0 );
nPe = G4ThreeVector( -sinEPhi, cosEPhi, 0 );
@@ -555,20 +553,20 @@ G4ThreeVector G4Tubs::SurfaceNormal( const G4ThreeVector& p ) const
++noSurfaces;
sumnorm -= nR;
}
if( fDPhi < twopi )
if( fDPhi < twopi )
{
if (distSPhi <= halfAngTolerance)
if (distSPhi <= halfAngTolerance)
{
++noSurfaces;
sumnorm += nPs;
}
if (distEPhi <= halfAngTolerance)
if (distEPhi <= halfAngTolerance)
{
++noSurfaces;
sumnorm += nPe;
}
}
if (distZ <= halfCarTolerance)
if (distZ <= halfCarTolerance)
{
++noSurfaces;
if ( p.z() >= 0.) { sumnorm += nZ; }
@@ -583,7 +581,7 @@ G4ThreeVector G4Tubs::SurfaceNormal( const G4ThreeVector& p ) const
G4cout<< "G4Tubs::SN ( "<<p.x()<<", "<<p.y()<<", "<<p.z()<<" ); "
<< G4endl << G4endl;
G4cout.precision(oldprc) ;
#endif
#endif
norm = ApproxSurfaceNormal(p);
}
else if ( noSurfaces == 1 ) { norm = sumnorm; }
@@ -635,8 +633,8 @@ G4ThreeVector G4Tubs::ApproxSurfaceNormal( const G4ThreeVector& p ) const
distMin = distRMax ;
side = kNRMax ;
}
}
if (!fPhiFullTube && rho ) // Protected against (0,0,z)
}
if (!fPhiFullTube && rho ) // Protected against (0,0,z)
{
phi = std::atan2(p.y(),p.x()) ;
@@ -651,7 +649,7 @@ G4ThreeVector G4Tubs::ApproxSurfaceNormal( const G4ThreeVector& p ) const
distSPhi = std::fabs(phi - fSPhi)*rho ;
}
distEPhi = std::fabs(phi - fSPhi - fDPhi)*rho ;
if (distSPhi < distEPhi) // Find new minimum
{
if ( distSPhi < distMin )
@@ -666,21 +664,21 @@ G4ThreeVector G4Tubs::ApproxSurfaceNormal( const G4ThreeVector& p ) const
side = kNEPhi ;
}
}
}
}
switch ( side )
{
case kNRMin : // Inner radius
{
{
norm = G4ThreeVector(-p.x()/rho, -p.y()/rho, 0) ;
break ;
}
case kNRMax : // Outer radius
{
{
norm = G4ThreeVector(p.x()/rho, p.y()/rho, 0) ;
break ;
}
case kNZ : // + or - dz
{
{
if ( p.z() > 0 ) { norm = G4ThreeVector(0,0,1) ; }
else { norm = G4ThreeVector(0,0,-1); }
break ;
@@ -702,8 +700,8 @@ G4ThreeVector G4Tubs::ApproxSurfaceNormal( const G4ThreeVector& p ) const
"GeomSolids1002", JustWarning,
"Undefined side for valid surface normal to solid.");
break ;
}
}
}
}
return norm;
}
@@ -713,7 +711,7 @@ G4ThreeVector G4Tubs::ApproxSurfaceNormal( const G4ThreeVector& p ) const
// Calculate distance to shape from outside, along normalised vector
// - return kInfinity if no intersection, or intersection distance <= tolerance
//
// - Compute the intersection with the z planes
// - Compute the intersection with the z planes
// - if at valid r, phi, return
//
// -> If point is outer outer radius, compute intersection with rmax
@@ -740,8 +738,8 @@ G4double G4Tubs::DistanceToIn( const G4ThreeVector& p,
// Intersection point variables
//
G4double Dist, sd, xi, yi, zi, rho2, inum, iden, cosPsi, Comp ;
G4double t1, t2, t3, b, c, d ; // Quadratic solver variables
G4double t1, t2, t3, b, c, d ; // Quadratic solver variables
// Calculate tolerant rmin and rmax
if (fRMin > kRadTolerance)
@@ -837,7 +835,7 @@ G4double G4Tubs::DistanceToIn( const G4ThreeVector& p,
{ // 64 bits systems. Split long distances and recompute
G4double fTerm = sd-std::fmod(sd,dRmax);
sd = fTerm + DistanceToIn(p+fTerm*v,v);
}
}
// Check z intersection
//
zi = p.z() + sd*v.z() ;
@@ -860,7 +858,7 @@ G4double G4Tubs::DistanceToIn( const G4ThreeVector& p,
} // end if (sd>=0)
} // end if (d>=0)
} // end if (r>=fRMax)
else
else
{
// Inside outer radius :
// check not inside, and heading through tubs (-> 0 to in)
@@ -878,11 +876,11 @@ G4double G4Tubs::DistanceToIn( const G4ThreeVector& p,
{
// In the old version, the small negative tangent for the point
// on surface was not taken in account, and returning 0.0 ...
// New version: check the tangent for the point on surface and
// New version: check the tangent for the point on surface and
// if no intersection, return kInfinity, if intersection instead
// return sd.
//
c = t3-fRMax*fRMax;
c = t3-fRMax*fRMax;
if ( c<=0.0 )
{
return 0.0;
@@ -894,26 +892,26 @@ G4double G4Tubs::DistanceToIn( const G4ThreeVector& p,
if ( d>=0.0 )
{
snxt = c/(-b+std::sqrt(d)); // using safe solution
// for quadratic equation
// for quadratic equation
if ( snxt < halfCarTolerance ) { snxt=0; }
return snxt ;
}
}
else
{
return kInfinity;
}
}
}
}
}
else
{
{
// In the old version, the small negative tangent for the point
// on surface was not taken in account, and returning 0.0 ...
// New version: check the tangent for the point on surface and
// New version: check the tangent for the point on surface and
// if no intersection, return kInfinity, if intersection instead
// return sd.
//
c = t3 - fRMax*fRMax;
c = t3 - fRMax*fRMax;
if ( c<=0.0 )
{
return 0.0;
@@ -925,10 +923,10 @@ G4double G4Tubs::DistanceToIn( const G4ThreeVector& p,
if ( d>=0.0 )
{
snxt= c/(-b+std::sqrt(d)); // using safe solution
// for quadratic equation
// for quadratic equation
if ( snxt < halfCarTolerance ) { snxt=0; }
return snxt ;
}
}
else
{
return kInfinity;
@@ -936,7 +934,7 @@ G4double G4Tubs::DistanceToIn( const G4ThreeVector& p,
}
} // end if (!fPhiFullTube)
} // end if (t3>tolIRMin2)
} // end if (Inside Outer Radius)
} // end if (Inside Outer Radius)
if ( fRMin ) // Try inner cylinder intersection
{
c = (t3 - fRMin*fRMin)/t1 ;
@@ -956,7 +954,7 @@ G4double G4Tubs::DistanceToIn( const G4ThreeVector& p,
{ // 64 bits systems. Split long distances and recompute
G4double fTerm = sd-std::fmod(sd,dRmax);
sd = fTerm + DistanceToIn(p+fTerm*v,v);
}
}
zi = p.z() + sd*v.z() ;
if (std::fabs(zi) <= tolODz)
{
@@ -964,7 +962,7 @@ G4double G4Tubs::DistanceToIn( const G4ThreeVector& p,
//
if ( fPhiFullTube )
{
return sd ;
return sd ;
}
else
{
@@ -999,7 +997,7 @@ G4double G4Tubs::DistanceToIn( const G4ThreeVector& p,
// First phi surface (Starting phi)
//
Comp = v.x()*sinSPhi - v.y()*cosSPhi ;
if ( Comp < 0 ) // Component in outwards normal dirn
{
Dist = (p.y()*cosSPhi - p.x()*sinSPhi) ;
@@ -1033,13 +1031,13 @@ G4double G4Tubs::DistanceToIn( const G4ThreeVector& p,
}
}
}
}
}
}
// Second phi surface (Ending phi)
Comp = -(v.x()*sinEPhi - v.y()*cosEPhi) ;
if (Comp < 0 ) // Component in outwards normal dirn
{
Dist = -(p.y()*cosEPhi - p.x()*sinEPhi) ;
@@ -1074,17 +1072,17 @@ G4double G4Tubs::DistanceToIn( const G4ThreeVector& p,
}
}
} // Comp < 0
} // !fPhiFullTube
} // !fPhiFullTube
if ( snxt<halfCarTolerance ) { snxt=0; }
return snxt ;
}
//////////////////////////////////////////////////////////////////
//
// Calculate distance to shape from outside, along normalised vector
// - return kInfinity if no intersection, or intersection distance <= tolerance
//
// - Compute the intersection with the z planes
// - Compute the intersection with the z planes
// - if at valid r, phi, return
//
// -> If point is outer outer radius, compute intersection with rmax
@@ -1124,7 +1122,7 @@ G4double G4Tubs::DistanceToIn( const G4ThreeVector& p ) const
// Psi=angle from central phi to point
//
cosPsi = (p.x()*cosCPhi + p.y()*sinCPhi)/rho ;
if ( cosPsi < cosHDPhi )
{
// Point lies outside phi range
@@ -1158,11 +1156,11 @@ G4double G4Tubs::DistanceToOut( const G4ThreeVector& p,
ESide side=kNull , sider=kNull, sidephi=kNull ;
G4double snxt, srd=kInfinity, sphi=kInfinity, pdist ;
G4double deltaR, t1, t2, t3, b, c, d2, roMin2 ;
// Vars for phi intersection:
G4double pDistS, compS, pDistE, compE, sphi2, xi, yi, vphi, roi2 ;
// Z plane intersection
if (v.z() > 0 )
@@ -1229,7 +1227,7 @@ G4double G4Tubs::DistanceToOut( const G4ThreeVector& p,
if ( t1 > 0 ) // Check not parallel
{
// Calculate srd, r exit distance
if ( (t2 >= 0.0) && (roi2 > fRMax*(fRMax + kRadTolerance)) )
{
// Delta r not negative => leaving via rmax
@@ -1253,7 +1251,7 @@ G4double G4Tubs::DistanceToOut( const G4ThreeVector& p,
// On tolerant boundary & heading outwards (or perpendicular to)
// outer radial surface -> leaving immediately
if ( calcNorm )
if ( calcNorm )
{
G4double invRho = FastInverseRxy( p, fInvRmax, kNormTolerance );
*n = G4ThreeVector(p.x()*invRho,p.y()*invRho,0) ;
@@ -1261,10 +1259,10 @@ G4double G4Tubs::DistanceToOut( const G4ThreeVector& p,
}
return snxt = 0 ; // Leaving by rmax immediately
}
}
}
else if ( t2 < 0. ) // i.e. t2 < 0; Possible rmin intersection
{
roMin2 = t3 - t2*t2/t1 ; // min ro2 of the plane of movement
roMin2 = t3 - t2*t2/t1 ; // min ro2 of the plane of movement
if ( fRMin && (roMin2 < fRMin*(fRMin - kRadTolerance)) )
{
@@ -1280,7 +1278,7 @@ G4double G4Tubs::DistanceToOut( const G4ThreeVector& p,
if (deltaR > kRadTolerance*fRMin)
{
srd = c/(-b+std::sqrt(d2));
srd = c/(-b+std::sqrt(d2));
sider = kRMin ;
}
else
@@ -1307,7 +1305,7 @@ G4double G4Tubs::DistanceToOut( const G4ThreeVector& p,
if (calcNorm)
{
G4double invRho = FastInverseRxy( p, fInvRmax, kNormTolerance );
*n = G4ThreeVector(p.x()*invRho,p.y()*invRho,0) ;
*n = G4ThreeVector(p.x()*invRho,p.y()*invRho,0) ;
*validNorm = true ;
}
return snxt = 0.0;
@@ -1339,16 +1337,16 @@ G4double G4Tubs::DistanceToOut( const G4ThreeVector& p,
}
}
}
// Phi Intersection
if ( !fPhiFullTube )
{
// add angle calculation with correction
// add angle calculation with correction
// of the difference in domain of atan2 and Sphi
//
vphi = std::atan2(v.y(),v.x()) ;
if ( vphi < fSPhi - halfAngTolerance ) { vphi += twopi; }
else if ( vphi > fSPhi + fDPhi + halfAngTolerance ) { vphi -= twopi; }
@@ -1364,25 +1362,25 @@ G4double G4Tubs::DistanceToOut( const G4ThreeVector& p,
compS = -sinSPhi*v.x() + cosSPhi*v.y() ;
compE = sinEPhi*v.x() - cosEPhi*v.y() ;
sidephi = kNull;
if( ( (fDPhi <= pi) && ( (pDistS <= halfCarTolerance)
&& (pDistE <= halfCarTolerance) ) )
|| ( (fDPhi > pi) && !((pDistS > halfCarTolerance)
&& (pDistE > halfCarTolerance) ) ) )
{
// Inside both phi *full* planes
if ( compS < 0 )
{
sphi = pDistS/compS ;
if (sphi >= -halfCarTolerance)
{
xi = p.x() + sphi*v.x() ;
yi = p.y() + sphi*v.y() ;
// Check intersecting with correct half-plane
// (if not -> no intersect)
//
@@ -1405,8 +1403,8 @@ G4double G4Tubs::DistanceToOut( const G4ThreeVector& p,
if ( pDistS > -halfCarTolerance )
{
sphi = 0.0 ; // Leave by sphi immediately
}
}
}
}
}
else
{
@@ -1421,14 +1419,14 @@ G4double G4Tubs::DistanceToOut( const G4ThreeVector& p,
if ( compE < 0 )
{
sphi2 = pDistE/compE ;
// Only check further if < starting phi intersection
//
if ( (sphi2 > -halfCarTolerance) && (sphi2 < sphi) )
{
xi = p.x() + sphi2*v.x() ;
yi = p.y() + sphi2*v.y() ;
if((std::fabs(xi)<=kCarTolerance)&&(std::fabs(yi)<=kCarTolerance))
{
// Leaving via ending phi
@@ -1440,8 +1438,8 @@ G4double G4Tubs::DistanceToOut( const G4ThreeVector& p,
if ( pDistE <= -halfCarTolerance ) { sphi = sphi2 ; }
else { sphi = 0.0 ; }
}
}
else // Check intersecting with correct half-plane
}
else // Check intersecting with correct half-plane
if ( (yi*cosCPhi-xi*sinCPhi) >= 0)
{
@@ -1463,7 +1461,7 @@ G4double G4Tubs::DistanceToOut( const G4ThreeVector& p,
{
// On z axis + travel not || to z axis -> if phi of vector direction
// within phi of shape, Step limited by rmax, else Step =0
if ( (fSPhi - halfAngTolerance <= vphi)
&& (vphi <= fSPhi + fDPhi + halfAngTolerance ) )
{
@@ -1471,7 +1469,7 @@ G4double G4Tubs::DistanceToOut( const G4ThreeVector& p,
}
else
{
sidephi = kSPhi ; // arbitrary
sidephi = kSPhi ; // arbitrary
sphi = 0.0 ;
}
}
@@ -1596,7 +1594,7 @@ G4double G4Tubs::DistanceToOut( const G4ThreeVector& p ) const
{
safeR1 = rho - fRMin ;
safeR2 = fRMax - rho ;
if ( safeR1 < safeR2 ) { safe = safeR1 ; }
else { safe = safeR2 ; }
}
@@ -1624,7 +1622,7 @@ G4double G4Tubs::DistanceToOut( const G4ThreeVector& p ) const
}
if ( safe < 0 ) { safe = 0 ; }
return safe ;
return safe ;
}
//////////////////////////////////////////////////////////////////////////
@@ -1674,80 +1672,91 @@ std::ostream& G4Tubs::StreamInfo( std::ostream& os ) const
G4ThreeVector G4Tubs::GetPointOnSurface() const
{
G4double xRand, yRand, zRand, phi, cosphi, sinphi, chose,
aOne, aTwo, aThr, aFou;
G4double rRand;
G4double Rmax = fRMax;
G4double Rmin = fRMin;
G4double hz = 2.*fDz; // height
G4double lext = fDPhi*Rmax; // length of external circular arc
G4double lint = fDPhi*Rmin; // length of internal circular arc
aOne = 2.*fDz*fDPhi*fRMax;
aTwo = 2.*fDz*fDPhi*fRMin;
aThr = 0.5*fDPhi*(fRMax*fRMax-fRMin*fRMin);
aFou = 2.*fDz*(fRMax-fRMin);
// Set array of surface areas
//
G4double RRmax = Rmax * Rmax;
G4double RRmin = Rmin * Rmin;
G4double sbase = 0.5*fDPhi*(RRmax - RRmin);
G4double scut = (fDPhi == twopi) ? 0. : hz*(Rmax - Rmin);
G4double ssurf[6] = { scut, scut, sbase, sbase, hz*lext, hz*lint };
ssurf[1] += ssurf[0];
ssurf[2] += ssurf[1];
ssurf[3] += ssurf[2];
ssurf[4] += ssurf[3];
ssurf[5] += ssurf[4];
phi = G4RandFlat::shoot(fSPhi, fSPhi+fDPhi);
cosphi = std::cos(phi);
sinphi = std::sin(phi);
// Select surface
//
G4double select = ssurf[5]*G4QuickRand();
G4int k = 5;
k -= (select <= ssurf[4]);
k -= (select <= ssurf[3]);
k -= (select <= ssurf[2]);
k -= (select <= ssurf[1]);
k -= (select <= ssurf[0]);
rRand = GetRadiusInRing(fRMin,fRMax);
if( (fSPhi == 0) && (fDPhi == twopi) ) { aFou = 0; }
chose = G4RandFlat::shoot(0.,aOne+aTwo+2.*aThr+2.*aFou);
if( (chose >=0) && (chose < aOne) )
// Generate point on selected surface
//
switch(k)
{
xRand = fRMax*cosphi;
yRand = fRMax*sinphi;
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 = G4RandFlat::shoot(-1.*fDz,fDz);
return G4ThreeVector (xRand, yRand, zRand);
}
else if( (chose >= aOne + aTwo) && (chose < aOne + aTwo + aThr) )
{
xRand = rRand*cosphi;
yRand = rRand*sinphi;
zRand = fDz;
return G4ThreeVector (xRand, yRand, zRand);
}
else if( (chose >= aOne + aTwo + aThr) && (chose < aOne + aTwo + 2.*aThr) )
{
xRand = rRand*cosphi;
yRand = rRand*sinphi;
zRand = -1.*fDz;
return G4ThreeVector (xRand, yRand, zRand);
}
else if( (chose >= aOne + aTwo + 2.*aThr)
&& (chose < aOne + aTwo + 2.*aThr + aFou) )
{
xRand = rRand*cosSPhi;
yRand = rRand*sinSPhi;
zRand = G4RandFlat::shoot(-1.*fDz,fDz);
return G4ThreeVector (xRand, yRand, zRand);
}
else
{
xRand = rRand*cosEPhi;
yRand = rRand*sinEPhi;
zRand = G4RandFlat::shoot(-1.*fDz,fDz);
return G4ThreeVector (xRand, yRand, zRand);
case 0: // start phi cut
{
G4double r = Rmin + (Rmax - Rmin)*G4QuickRand();
return G4ThreeVector(r*cosSPhi, r*sinSPhi, hz*G4QuickRand() - fDz);
}
case 1: // end phi cut
{
G4double r = Rmin + (Rmax - Rmin)*G4QuickRand();
return G4ThreeVector(r*cosEPhi, r*sinEPhi, hz*G4QuickRand() - fDz);
}
case 2: // base at -dz
{
G4double r = std::sqrt(RRmin + (RRmax - RRmin)*G4QuickRand());
G4double phi = fSPhi + fDPhi*G4QuickRand();
return G4ThreeVector(r*std::cos(phi), r*std::sin(phi), -fDz);
}
case 3: // base at +dz
{
G4double r = std::sqrt(RRmin + (RRmax - RRmin)*G4QuickRand());
G4double phi = fSPhi + fDPhi*G4QuickRand();
return G4ThreeVector(r*std::cos(phi), r*std::sin(phi), fDz);
}
case 4: // external lateral surface
{
G4double phi = fSPhi + fDPhi*G4QuickRand();
G4double z = hz*G4QuickRand() - fDz;
G4double x = Rmax*std::cos(phi);
G4double y = Rmax*std::sin(phi);
return G4ThreeVector(x,y,z);
}
case 5: // internal lateral surface
{
G4double phi = fSPhi + fDPhi*G4QuickRand();
G4double z = hz*G4QuickRand() - fDz;
G4double x = Rmin*std::cos(phi);
G4double y = Rmin*std::sin(phi);
return G4ThreeVector(x,y,z);
}
}
return G4ThreeVector(0., 0., 0.);
}
///////////////////////////////////////////////////////////////////////////
//
// Methods for visualisation
void G4Tubs::DescribeYourselfTo ( G4VGraphicsScene& scene ) const
void G4Tubs::DescribeYourselfTo ( G4VGraphicsScene& scene ) const
{
scene.AddSolid (*this) ;
}
G4Polyhedron* G4Tubs::CreatePolyhedron () const
G4Polyhedron* G4Tubs::CreatePolyhedron () const
{
return new G4PolyhedronTubs (fRMin, fRMax, fDz, fSPhi, fDPhi) ;
}
+14
View File
@@ -16,6 +16,20 @@ committal in the source repository !
* Reverse chronological order (last date on top), please *
----------------------------------------------------------
30-October-2020 E.Tcherniaev (geom-specific-V10-06-10)
- G4Polycone: Revised GetPointOnSurface();
Added protected auxiliary method SetSurfaceElements();
Removed GetPointOnCone(), GetPointOnTubs(), GetPointOnCut(), GetPointOnRing();
- G4GenericPolycone: Revised GetPointOnSurface();
Added protected auxiliary method SetSurfaceElements();
- G4Polyhedra: Revised GetPointOnSurface();
Added protected auxiliary method SetSurfaceElements();
Removed GetPointOnPlane(), GetPointOnTriangle();
01-October-2020 E.Tcherniaev (geom-specific-V10-06-09)
- G4Polycone, G4GenericPolycone, G4Polyhedra:
implemented GetSurfaceArea(), GetCubicVolume().
May 21, 2020 Guilherme Lima (geom-specific-V10-06-08)
----------------------------
- Fix constructor signatures in G4UExtrudedSolid wrappers, to match those in G4 version.
@@ -88,6 +88,9 @@ class G4GenericPolycone : public G4VCSGfaceted
const G4AffineTransform& pTransform,
G4double& pmin, G4double& pmax) const;
G4double GetCubicVolume();
G4double GetSurfaceArea();
G4ThreeVector GetPointOnSurface() const;
G4GeometryType GetEntityType() const;
@@ -135,6 +138,8 @@ class G4GenericPolycone : public G4VCSGfaceted
// Methods for random point generation
void SetSurfaceElements() const;
protected: // without description
// Here are our parameters
@@ -145,9 +150,10 @@ class G4GenericPolycone : public G4VCSGfaceted
G4int numCorner; // number RZ points
G4PolyconeSideRZ* corners = nullptr; // corner r,z points
// Our quick test
G4EnclosingCylinder* enclosingCylinder = nullptr; // Our quick test
G4EnclosingCylinder* enclosingCylinder = nullptr;
struct surface_element { G4double area = 0.; G4int i0 = 0, i1 = 0, i2 = 0; };
mutable std::vector<surface_element>* fElements = nullptr;
};
#include "G4GenericPolycone.icc"
@@ -106,6 +106,9 @@ class G4Polycone : public G4VCSGfaceted
const G4AffineTransform& pTransform,
G4double& pmin, G4double& pmax) const;
G4double GetCubicVolume();
G4double GetSurfaceArea();
G4ThreeVector GetPointOnSurface() const;
void ComputeDimensions( G4VPVParameterisation* p,
@@ -161,23 +164,7 @@ class G4Polycone : public G4VCSGfaceted
// Methods for random point generation
G4ThreeVector GetPointOnCone(G4double fRmin1, G4double fRmax1,
G4double fRmin2, G4double fRmax2,
G4double zOne, G4double zTwo,
G4double& totArea) const;
G4ThreeVector GetPointOnTubs(G4double fRMin, G4double fRMax,
G4double zOne, G4double zTwo,
G4double& totArea) const;
G4ThreeVector GetPointOnCut(G4double fRMin1, G4double fRMax1,
G4double fRMin2, G4double fRMax2,
G4double zOne, G4double zTwo,
G4double& totArea) const;
G4ThreeVector GetPointOnRing(G4double fRMin, G4double fRMax,
G4double fRMin2, G4double fRMax2,
G4double zOne) const;
void SetSurfaceElements() const;
protected: // without description
@@ -190,10 +177,10 @@ class G4Polycone : public G4VCSGfaceted
G4PolyconeSideRZ* corners = nullptr; // Corner r,z points
G4PolyconeHistorical* original_parameters = nullptr; // Original input params
// Our quick test
G4EnclosingCylinder* enclosingCylinder = nullptr;
G4EnclosingCylinder* enclosingCylinder = nullptr; // Our quick test
struct surface_element { G4double area = 0.; G4int i0 = 0, i1 = 0, i2 = 0; };
mutable std::vector<surface_element>* fElements = nullptr;
};
#include "G4Polycone.icc"
@@ -115,6 +115,9 @@ class G4Polyhedra : public G4VCSGfaceted
G4VSolid* Clone() const;
G4double GetCubicVolume();
G4double GetSurfaceArea();
G4ThreeVector GetPointOnSurface() const;
std::ostream& StreamInfo( std::ostream& os ) const;
@@ -172,11 +175,7 @@ class G4Polyhedra : public G4VCSGfaceted
// Methods for generation of random points on surface
G4ThreeVector GetPointOnPlane(G4ThreeVector p0, G4ThreeVector p1,
G4ThreeVector p2, G4ThreeVector p3) const;
G4ThreeVector GetPointOnTriangle(G4ThreeVector p0, G4ThreeVector p1,
G4ThreeVector p2) const;
G4ThreeVector GetPointOnSurfaceCorners() const;
void SetSurfaceElements() const;
protected: // without description
@@ -190,6 +189,9 @@ class G4Polyhedra : public G4VCSGfaceted
G4PolyhedraHistorical* original_parameters = nullptr; // original input params
G4EnclosingCylinder* enclosingCylinder = nullptr;
struct surface_element { G4double area = 0.; G4int i0 = 0, i1 = 0, i2 = 0; };
mutable std::vector<surface_element>* fElements = nullptr;
};
#include "G4Polyhedra.icc"
@@ -40,30 +40,35 @@
#include "G4AffineTransform.hh"
#include "G4BoundingEnvelope.hh"
#include "Randomize.hh"
#include "G4QuickRand.hh"
#include "G4Polyhedron.hh"
#include "G4EnclosingCylinder.hh"
#include "G4ReduciblePolygon.hh"
#include "G4VPVParameterisation.hh"
namespace
{
G4Mutex surface_elementsMutex = G4MUTEX_INITIALIZER;
}
using namespace CLHEP;
// Constructor (generic parameters)
//
G4GenericPolycone::G4GenericPolycone( const G4String& name,
G4GenericPolycone::G4GenericPolycone( const G4String& name,
G4double phiStart,
G4double phiTotal,
G4int numRZ,
const G4double r[],
const G4double z[] )
: G4VCSGfaceted( name )
{
{
G4ReduciblePolygon *rz = new G4ReduciblePolygon( r, z, numRZ );
Create( phiStart, phiTotal, rz );
// Set original_parameters struct for consistency
//
//SetOriginalParameters(rz);
@@ -91,7 +96,7 @@ void G4GenericPolycone::Create( G4double phiStart,
G4Exception("G4GenericPolycone::Create()", "GeomSolids0002",
FatalErrorInArgument, message);
}
G4double rzArea = rz->Area();
if (rzArea < -kCarTolerance)
{
@@ -105,9 +110,9 @@ void G4GenericPolycone::Create( G4double phiStart,
G4Exception("G4GenericPolycone::Create()", "GeomSolids0002",
FatalErrorInArgument, message);
}
if ( (!rz->RemoveDuplicateVertices( kCarTolerance ))
|| (!rz->RemoveRedundantVertices( kCarTolerance )) )
|| (!rz->RemoveRedundantVertices( kCarTolerance )) )
{
std::ostringstream message;
message << "Illegal input parameters - " << GetName() << G4endl
@@ -116,7 +121,7 @@ void G4GenericPolycone::Create( G4double phiStart,
FatalErrorInArgument, message);
}
if (rz->CrossesItself(1/kInfinity))
if (rz->CrossesItself(1/kInfinity))
{
std::ostringstream message;
message << "Illegal input parameters - " << GetName() << G4endl
@@ -140,21 +145,21 @@ void G4GenericPolycone::Create( G4double phiStart,
else
{
phiIsOpen = true;
//
// Convert phi into our convention
//
startPhi = phiStart;
while( startPhi < 0 ) // Loop checking, 13.08.2015, G.Cosmo
startPhi += twopi;
endPhi = phiStart+phiTotal;
while( endPhi < startPhi ) // Loop checking, 13.08.2015, G.Cosmo
endPhi += twopi;
}
//
// Allocate corner array.
// Allocate corner array.
//
corners = new G4PolyconeSideRZ[numCorner];
@@ -162,7 +167,7 @@ void G4GenericPolycone::Create( G4double phiStart,
// Copy corners
//
G4ReduciblePolygonIterator iterRZ(rz);
G4PolyconeSideRZ* next = corners;
iterRZ.Begin();
do // Loop checking, 13.08.2015, G.Cosmo
@@ -170,13 +175,13 @@ void G4GenericPolycone::Create( G4double phiStart,
next->r = iterRZ.GetA();
next->z = iterRZ.GetB();
} while( ++next, iterRZ.Next() );
//
// Allocate face pointer array
//
numFace = phiIsOpen ? numCorner+2 : numCorner;
faces = new G4VCSGface*[numFace];
//
// Construct conical faces
//
@@ -192,9 +197,9 @@ void G4GenericPolycone::Create( G4double phiStart,
if (next >= corners+numCorner) next = corners;
nextNext = next+1;
if (nextNext >= corners+numCorner) nextNext = corners;
if (corner->r < 1/kInfinity && next->r < 1/kInfinity) continue;
//
// We must decide here if we can dare declare one of our faces
// as having a "valid" normal (i.e. allBehind = true). This
@@ -215,11 +220,11 @@ void G4GenericPolycone::Create( G4double phiStart,
allBehind = !rz->BisectedBy( corner->r, corner->z,
next->r, next->z, kCarTolerance );
}
*face++ = new G4PolyconeSide( prev, corner, next, nextNext,
startPhi, endPhi-startPhi, phiIsOpen, allBehind );
} while( prev=corner, corner=next, corner > corners );
if (phiIsOpen)
{
//
@@ -228,12 +233,12 @@ void G4GenericPolycone::Create( G4double phiStart,
*face++ = new G4PolyPhiFace( rz, startPhi, 0, endPhi );
*face++ = new G4PolyPhiFace( rz, endPhi, 0, startPhi );
}
//
// We might have dropped a face or two: recalculate numFace
//
numFace = face-faces;
//
// Make enclosingCylinder
//
@@ -255,6 +260,12 @@ G4GenericPolycone::~G4GenericPolycone()
{
delete [] corners;
delete enclosingCylinder;
delete fElements;
delete fpPolyhedron;
corners = nullptr;
enclosingCylinder = nullptr;
fElements = nullptr;
fpPolyhedron = nullptr;
}
// Copy constructor
@@ -271,16 +282,16 @@ G4GenericPolycone&
G4GenericPolycone::operator=( const G4GenericPolycone& source )
{
if (this == &source) return *this;
G4VCSGfaceted::operator=( source );
delete [] corners;
// if (original_parameters) delete original_parameters;
delete enclosingCylinder;
CopyStuff( source );
return *this;
}
@@ -300,20 +311,29 @@ void G4GenericPolycone::CopyStuff( const G4GenericPolycone& source )
// The corner array
//
corners = new G4PolyconeSideRZ[numCorner];
G4PolyconeSideRZ *corn = corners,
*sourceCorn = source.corners;
do // Loop checking, 13.08.2015, G.Cosmo
{
*corn = *sourceCorn;
} while( ++sourceCorn, ++corn < corners+numCorner );
//
// Enclosing cylinder
//
enclosingCylinder = new G4EnclosingCylinder( *source.enclosingCylinder );
//
// Surface elements
//
delete fElements;
fElements = nullptr;
// Polyhedron
//
fRebuildPolyhedron = false;
delete fpPolyhedron;
fpPolyhedron = nullptr;
}
@@ -360,7 +380,7 @@ G4double G4GenericPolycone::DistanceToIn( const G4ThreeVector& p,
//
if (enclosingCylinder->ShouldMiss(p,v))
return kInfinity;
//
// Long answer
//
@@ -595,7 +615,7 @@ std::ostream& G4GenericPolycone::StreamInfo( std::ostream& os ) const
<< " starting phi angle : " << startPhi/degree << " degrees \n"
<< " ending phi angle : " << endPhi/degree << " degrees \n";
G4int i=0;
os << " number of RZ points: " << numCorner << "\n"
<< " RZ values (corners): \n";
for (i=0; i<numCorner; i++)
@@ -609,18 +629,201 @@ std::ostream& G4GenericPolycone::StreamInfo( std::ostream& os ) const
return os;
}
// GetPointOnSurface
//////////////////////////////////////////////////////////////////////////
//
G4ThreeVector G4GenericPolycone::GetPointOnSurface() const
{
return GetPointOnSurfaceGeneric();
// Return volume
G4double G4GenericPolycone::GetCubicVolume()
{
if (fCubicVolume == 0.)
{
G4double total = 0.;
G4int nrz = GetNumRZCorner();
G4PolyconeSideRZ a = GetCorner(nrz - 1);
for (G4int i=0; i<nrz; ++i)
{
G4PolyconeSideRZ b = GetCorner(i);
total += (b.r*b.r + b.r*a.r + a.r*a.r)*(b.z - a.z);
a = b;
}
fCubicVolume = std::abs(total)*(GetEndPhi() - GetStartPhi())/6.;
}
return fCubicVolume;
}
// CreatePolyhedron
//////////////////////////////////////////////////////////////////////////
//
// Return surface area
G4double G4GenericPolycone::GetSurfaceArea()
{
if (fSurfaceArea == 0.)
{
// phi cut area
G4int nrz = GetNumRZCorner();
G4double scut = 0.;
if (IsOpen())
{
G4PolyconeSideRZ a = GetCorner(nrz - 1);
for (G4int i=0; i<nrz; ++i)
{
G4PolyconeSideRZ b = GetCorner(i);
scut += a.r*b.z - a.z*b.r;
a = b;
}
scut = std::abs(scut);
}
// lateral surface area
G4double slat = 0;
G4PolyconeSideRZ a = GetCorner(nrz - 1);
for (G4int i=0; i<nrz; ++i)
{
G4PolyconeSideRZ b = GetCorner(i);
G4double h = std::sqrt((b.r - a.r)*(b.r - a.r) + (b.z - a.z)*(b.z - a.z));
slat += (b.r + a.r)*h;
a = b;
}
slat *= (GetEndPhi() - GetStartPhi())/2.;
fSurfaceArea = scut + slat;
}
return fSurfaceArea;
}
//////////////////////////////////////////////////////////////////////////
//
// Set vector of surface elements, auxiliary method for sampling
// random points on surface
void G4GenericPolycone::SetSurfaceElements() const
{
fElements = new std::vector<G4GenericPolycone::surface_element>;
G4double sarea = 0.;
G4int nrz = GetNumRZCorner();
// set lateral surface elements
G4double dphi = GetEndPhi() - GetStartPhi();
G4int ia = nrz - 1;
for (G4int ib=0; ib<nrz; ++ib)
{
G4PolyconeSideRZ a = GetCorner(ia);
G4PolyconeSideRZ b = GetCorner(ib);
G4GenericPolycone::surface_element selem;
selem.i0 = ia;
selem.i1 = ib;
selem.i2 = -1;
ia = ib;
if (a.r == 0. && b.r == 0.) continue;
G4double h = std::sqrt((b.r - a.r)*(b.r - a.r) + (b.z - a.z)*(b.z - a.z));
sarea += 0.5*dphi*(b.r + a.r)*h;
selem.area = sarea;
fElements->push_back(selem);
}
// set elements for phi cuts
if (IsOpen())
{
G4TwoVectorList contourRZ;
std::vector<G4int> triangles;
for (G4int i=0; i<nrz; ++i)
{
G4PolyconeSideRZ corner = GetCorner(i);
contourRZ.push_back(G4TwoVector(corner.r, corner.z));
}
G4GeomTools::TriangulatePolygon(contourRZ, triangles);
G4int ntria = triangles.size();
for (G4int i=0; i<ntria; i+=3)
{
G4GenericPolycone::surface_element selem;
selem.i0 = triangles[i];
selem.i1 = triangles[i+1];
selem.i2 = triangles[i+2];
G4PolyconeSideRZ a = GetCorner(selem.i0);
G4PolyconeSideRZ b = GetCorner(selem.i1);
G4PolyconeSideRZ c = GetCorner(selem.i2);
G4double stria =
std::abs(G4GeomTools::TriangleArea(a.r, a.z, b.r, b.z, c.r, c.z));
sarea += stria;
selem.area = sarea;
fElements->push_back(selem); // start phi
sarea += stria;
selem.area = sarea;
selem.i0 += nrz;
fElements->push_back(selem); // end phi
}
}
}
//////////////////////////////////////////////////////////////////////////
//
// Generate random point on surface
G4ThreeVector G4GenericPolycone::GetPointOnSurface() const
{
// Set surface elements
if (!fElements)
{
G4AutoLock l(&surface_elementsMutex);
SetSurfaceElements();
l.unlock();
}
// Select surface element
G4GenericPolycone::surface_element selem;
selem = fElements->back();
G4double select = selem.area*G4QuickRand();
auto it = std::lower_bound(fElements->begin(), fElements->end(), select,
[](const G4GenericPolycone::surface_element& x, G4double val)
-> G4bool { return x.area < val; });
// Generate random point
G4double r = 0, z = 0, phi = 0;
G4double u = G4QuickRand();
G4double v = G4QuickRand();
G4int i0 = (*it).i0;
G4int i1 = (*it).i1;
G4int i2 = (*it).i2;
if (i2 < 0) // lateral surface
{
G4PolyconeSideRZ p0 = GetCorner(i0);
G4PolyconeSideRZ p1 = GetCorner(i1);
if (p1.r < p0.r)
{
p0 = GetCorner(i1);
p1 = GetCorner(i0);
}
if (p1.r - p0.r < kCarTolerance) // cylindrical surface
{
r = (p1.r - p0.r)*u + p0.r;
z = (p1.z - p0.z)*u + p0.z;
}
else // conical surface
{
r = std::sqrt(p1.r*p1.r*u + p0.r*p0.r*(1. - u));
z = p0.z + (p1.z - p0.z)*(r - p0.r)/(p1.r - p0.r);
}
phi = (GetEndPhi() - GetStartPhi())*v + GetStartPhi();
}
else // phi cut
{
G4int nrz = GetNumRZCorner();
phi = (i0 < nrz) ? GetStartPhi() : GetEndPhi();
if (i0 >= nrz) { i0 -= nrz; }
G4PolyconeSideRZ p0 = GetCorner(i0);
G4PolyconeSideRZ p1 = GetCorner(i1);
G4PolyconeSideRZ p2 = GetCorner(i2);
if (u + v > 1.) { u = 1. - u; v = 1. - v; }
r = (p1.r - p0.r)*u + (p2.r - p0.r)*v + p0.r;
z = (p1.z - p0.z)*u + (p2.z - p0.z)*v + p0.z;
}
return G4ThreeVector(r*std::cos(phi), r*std::sin(phi), z);
}
//////////////////////////////////////////////////////////////////////////
//
// CreatePolyhedron
G4Polyhedron* G4GenericPolycone::CreatePolyhedron() const
{
{
// The following code prepares for:
// HepPolyhedron::createPolyhedron(int Nnodes, int Nfaces,
// const double xyz[][3],
@@ -635,8 +838,8 @@ G4Polyhedron* G4GenericPolycone::CreatePolyhedron() const
* array starts from 1 (like in fortran). The indexes can be positive
* or negative. Negative sign means that the corresponding edge is
* invisible. The normal of the face should be directed to exterior
* of the polyhedron.
*
* of the polyhedron.
*
* @param Nnodes number of nodes
* @param Nfaces number of faces
* @param xyz nodes
+259 -339
View File
@@ -40,17 +40,22 @@
#include "G4AffineTransform.hh"
#include "G4BoundingEnvelope.hh"
#include "Randomize.hh"
#include "G4QuickRand.hh"
#include "G4EnclosingCylinder.hh"
#include "G4ReduciblePolygon.hh"
#include "G4VPVParameterisation.hh"
namespace
{
G4Mutex surface_elementsMutex = G4MUTEX_INITIALIZER;
}
using namespace CLHEP;
// Constructor (GEANT3 style parameters)
//
G4Polycone::G4Polycone( const G4String& name,
//
G4Polycone::G4Polycone( const G4String& name,
G4double phiStart,
G4double phiTotal,
G4int numZPlanes,
@@ -63,7 +68,7 @@ G4Polycone::G4Polycone( const G4String& name,
// Some historical ugliness
//
original_parameters = new G4PolyconeHistorical();
original_parameters->Start_angle = phiStart;
original_parameters->Opening_angle = phiTotal;
original_parameters->Num_z_planes = numZPlanes;
@@ -72,7 +77,7 @@ G4Polycone::G4Polycone( const G4String& name,
original_parameters->Rmax = new G4double[numZPlanes];
for (G4int i=0; i<numZPlanes; ++i)
{
{
if(rInner[i]>rOuter[i])
{
DumpInfo();
@@ -102,7 +107,7 @@ G4Polycone::G4Polycone( const G4String& name,
G4Exception("G4Polycone::G4Polycone()", "GeomSolids0002",
FatalErrorInArgument, message);
}
}
}
original_parameters->Z_values[i] = zPlane[i];
original_parameters->Rmin[i] = rInner[i];
original_parameters->Rmax[i] = rOuter[i];
@@ -113,33 +118,33 @@ G4Polycone::G4Polycone( const G4String& name,
//
G4ReduciblePolygon *rz =
new G4ReduciblePolygon( rInner, rOuter, zPlane, numZPlanes );
//
// Do the real work
//
Create( phiStart, phiTotal, rz );
delete rz;
}
// Constructor (generic parameters)
//
G4Polycone::G4Polycone( const G4String& name,
G4Polycone::G4Polycone( const G4String& name,
G4double phiStart,
G4double phiTotal,
G4int numRZ,
const G4double r[],
const G4double z[] )
: G4VCSGfaceted( name )
{
{
G4ReduciblePolygon* rz = new G4ReduciblePolygon( r, z, numRZ );
Create( phiStart, phiTotal, rz );
// Set original_parameters struct for consistency
//
G4bool convertible = SetOriginalParameters(rz);
if(!convertible)
@@ -179,7 +184,7 @@ void G4Polycone::Create( G4double phiStart,
G4Exception("G4Polycone::Create()", "GeomSolids0002",
FatalErrorInArgument, message);
}
G4double rzArea = rz->Area();
if (rzArea < -kCarTolerance)
{
@@ -193,9 +198,9 @@ void G4Polycone::Create( G4double phiStart,
G4Exception("G4Polycone::Create()", "GeomSolids0002",
FatalErrorInArgument, message);
}
if ( (!rz->RemoveDuplicateVertices( kCarTolerance ))
|| (!rz->RemoveRedundantVertices( kCarTolerance )) )
|| (!rz->RemoveRedundantVertices( kCarTolerance )) )
{
std::ostringstream message;
message << "Illegal input parameters - " << GetName() << G4endl
@@ -204,7 +209,7 @@ void G4Polycone::Create( G4double phiStart,
FatalErrorInArgument, message);
}
if (rz->CrossesItself(1/kInfinity))
if (rz->CrossesItself(1/kInfinity))
{
std::ostringstream message;
message << "Illegal input parameters - " << GetName() << G4endl
@@ -228,21 +233,21 @@ void G4Polycone::Create( G4double phiStart,
else
{
phiIsOpen = true;
//
// Convert phi into our convention
//
startPhi = phiStart;
while( startPhi < 0. ) // Loop checking, 13.08.2015, G.Cosmo
startPhi += twopi;
endPhi = phiStart+phiTotal;
while( endPhi < startPhi ) // Loop checking, 13.08.2015, G.Cosmo
endPhi += twopi;
}
//
// Allocate corner array.
// Allocate corner array.
//
corners = new G4PolyconeSideRZ[numCorner];
@@ -250,7 +255,7 @@ void G4Polycone::Create( G4double phiStart,
// Copy corners
//
G4ReduciblePolygonIterator iterRZ(rz);
G4PolyconeSideRZ *next = corners;
iterRZ.Begin();
do // Loop checking, 13.08.2015, G.Cosmo
@@ -258,13 +263,13 @@ void G4Polycone::Create( G4double phiStart,
next->r = iterRZ.GetA();
next->z = iterRZ.GetB();
} while( ++next, iterRZ.Next() );
//
// Allocate face pointer array
//
numFace = phiIsOpen ? numCorner+2 : numCorner;
faces = new G4VCSGface*[numFace];
//
// Construct conical faces
//
@@ -280,9 +285,9 @@ void G4Polycone::Create( G4double phiStart,
if (next >= corners+numCorner) next = corners;
nextNext = next+1;
if (nextNext >= corners+numCorner) nextNext = corners;
if (corner->r < 1/kInfinity && next->r < 1/kInfinity) continue;
//
// We must decide here if we can dare declare one of our faces
// as having a "valid" normal (i.e. allBehind = true). This
@@ -303,11 +308,11 @@ void G4Polycone::Create( G4double phiStart,
allBehind = !rz->BisectedBy( corner->r, corner->z,
next->r, next->z, kCarTolerance );
}
*face++ = new G4PolyconeSide( prev, corner, next, nextNext,
startPhi, endPhi-startPhi, phiIsOpen, allBehind );
} while( prev=corner, corner=next, corner > corners );
if (phiIsOpen)
{
//
@@ -316,12 +321,12 @@ void G4Polycone::Create( G4double phiStart,
*face++ = new G4PolyPhiFace( rz, startPhi, 0, endPhi );
*face++ = new G4PolyPhiFace( rz, endPhi, 0, startPhi );
}
//
// We might have dropped a face or two: recalculate numFace
//
numFace = face-faces;
//
// Make enclosingCylinder
//
@@ -346,6 +351,13 @@ G4Polycone::~G4Polycone()
delete [] corners;
delete original_parameters;
delete enclosingCylinder;
delete fElements;
delete fpPolyhedron;
corners = nullptr;
original_parameters = nullptr;
enclosingCylinder = nullptr;
fElements = nullptr;
fpPolyhedron = nullptr;
}
// Copy constructor
@@ -361,16 +373,16 @@ G4Polycone::G4Polycone( const G4Polycone& source )
G4Polycone &G4Polycone::operator=( const G4Polycone& source )
{
if (this == &source) return *this;
G4VCSGfaceted::operator=( source );
delete [] corners;
if (original_parameters) delete original_parameters;
delete enclosingCylinder;
CopyStuff( source );
return *this;
}
@@ -383,21 +395,21 @@ void G4Polycone::CopyStuff( const G4Polycone& source )
//
startPhi = source.startPhi;
endPhi = source.endPhi;
phiIsOpen = source.phiIsOpen;
numCorner = source.numCorner;
phiIsOpen = source.phiIsOpen;
numCorner = source.numCorner;
//
// The corner array
//
corners = new G4PolyconeSideRZ[numCorner];
G4PolyconeSideRZ* corn = corners,
* sourceCorn = source.corners;
do // Loop checking, 13.08.2015, G.Cosmo
{
*corn = *sourceCorn;
} while( ++sourceCorn, ++corn < corners+numCorner );
//
// Original parameters
//
@@ -406,13 +418,23 @@ void G4Polycone::CopyStuff( const G4Polycone& source )
original_parameters =
new G4PolyconeHistorical( *source.original_parameters );
}
//
// Enclosing cylinder
//
enclosingCylinder = new G4EnclosingCylinder( *source.enclosingCylinder );
//
// Surface elements
//
delete fElements;
fElements = nullptr;
//
// Polyhedron
//
fRebuildPolyhedron = false;
delete fpPolyhedron;
fpPolyhedron = nullptr;
}
@@ -426,6 +448,10 @@ G4bool G4Polycone::Reset()
G4VCSGfaceted::DeleteStuff();
delete [] corners;
delete enclosingCylinder;
delete fElements;
corners = nullptr;
fElements = nullptr;
enclosingCylinder = nullptr;
//
// Rebuild polycone
@@ -473,7 +499,7 @@ G4double G4Polycone::DistanceToIn( const G4ThreeVector& p,
//
if (enclosingCylinder->ShouldMiss(p,v))
return kInfinity;
//
// Long answer
//
@@ -701,7 +727,7 @@ std::ostream& G4Polycone::StreamInfo( std::ostream& os ) const
<< " starting phi angle : " << startPhi/degree << " degrees \n"
<< " ending phi angle : " << endPhi/degree << " degrees \n";
G4int i=0;
G4int numPlanes = original_parameters->Num_z_planes;
os << " number of Z planes: " << numPlanes << "\n"
<< " Z values: \n";
@@ -722,7 +748,7 @@ std::ostream& G4Polycone::StreamInfo( std::ostream& os ) const
os << " Z plane " << i << ": "
<< original_parameters->Rmax[i] << "\n";
}
os << " number of RZ points: " << numCorner << "\n"
<< " RZ values (corners): \n";
for (i=0; i<numCorner; ++i)
@@ -736,311 +762,205 @@ std::ostream& G4Polycone::StreamInfo( std::ostream& os ) const
return os;
}
// GetPointOnCone
//////////////////////////////////////////////////////////////////////////
//
// Auxiliary method for Get Point On Surface
//
G4ThreeVector G4Polycone::GetPointOnCone(G4double fRmin1, G4double fRmax1,
G4double fRmin2, G4double fRmax2,
G4double zOne, G4double zTwo,
G4double& totArea) const
{
// declare working variables
//
G4double Aone, Atwo, Afive, phi, zRand, fDPhi, cosu, sinu;
G4double rRand1, rmin, rmax, chose, rone, rtwo, qone, qtwo;
G4double fDz=(zTwo-zOne)/2., afDz=std::fabs(fDz);
G4ThreeVector point, offset=G4ThreeVector(0.,0.,0.5*(zTwo+zOne));
fDPhi = endPhi - startPhi;
rone = (fRmax1-fRmax2)/(2.*fDz);
rtwo = (fRmin1-fRmin2)/(2.*fDz);
if(fRmax1==fRmax2){qone=0.;}
else
{
qone = fDz*(fRmax1+fRmax2)/(fRmax1-fRmax2);
}
if(fRmin1==fRmin2){qtwo=0.;}
else
{
qtwo = fDz*(fRmin1+fRmin2)/(fRmin1-fRmin2);
}
Aone = 0.5*fDPhi*(fRmax2 + fRmax1)*(sqr(fRmin1-fRmin2)+sqr(zTwo-zOne));
Atwo = 0.5*fDPhi*(fRmin2 + fRmin1)*(sqr(fRmax1-fRmax2)+sqr(zTwo-zOne));
Afive = fDz*(fRmax1-fRmin1+fRmax2-fRmin2);
totArea = Aone+Atwo+2.*Afive;
phi = G4RandFlat::shoot(startPhi,endPhi);
cosu = std::cos(phi);
sinu = std::sin(phi);
// Return volume
if( (startPhi == 0.) && (endPhi == twopi) ) { Afive = 0.; }
chose = G4RandFlat::shoot(0.,Aone+Atwo+2.*Afive);
if( (chose >= 0.) && (chose < Aone) )
{
if(fRmax1 != fRmax2)
{
zRand = G4RandFlat::shoot(-1.*afDz,afDz);
point = G4ThreeVector (rone*cosu*(qone-zRand),
rone*sinu*(qone-zRand), zRand);
}
else
{
point = G4ThreeVector(fRmax1*cosu, fRmax1*sinu,
G4RandFlat::shoot(-1.*afDz,afDz));
}
}
else if(chose >= Aone && chose < Aone + Atwo)
{
if(fRmin1 != fRmin2)
{
zRand = G4RandFlat::shoot(-1.*afDz,afDz);
point = G4ThreeVector (rtwo*cosu*(qtwo-zRand),
rtwo*sinu*(qtwo-zRand), zRand);
}
else
{
point = G4ThreeVector(fRmin1*cosu, fRmin1*sinu,
G4RandFlat::shoot(-1.*afDz,afDz));
}
}
else if( (chose >= Aone + Atwo + Afive) && (chose < Aone + Atwo + 2.*Afive) )
{
zRand = G4RandFlat::shoot(-1.*afDz,afDz);
rmin = fRmin2-((zRand-fDz)/(2.*fDz))*(fRmin1-fRmin2);
rmax = fRmax2-((zRand-fDz)/(2.*fDz))*(fRmax1-fRmax2);
rRand1 = std::sqrt(G4RandFlat::shoot()*(sqr(rmax)-sqr(rmin))+sqr(rmin));
point = G4ThreeVector (rRand1*std::cos(startPhi),
rRand1*std::sin(startPhi), zRand);
}
else
{
zRand = G4RandFlat::shoot(-1.*afDz,afDz);
rmin = fRmin2-((zRand-fDz)/(2.*fDz))*(fRmin1-fRmin2);
rmax = fRmax2-((zRand-fDz)/(2.*fDz))*(fRmax1-fRmax2);
rRand1 = std::sqrt(G4RandFlat::shoot()*(sqr(rmax)-sqr(rmin))+sqr(rmin));
point = G4ThreeVector (rRand1*std::cos(endPhi),
rRand1*std::sin(endPhi), zRand);
}
return point+offset;
}
// GetPointOnTubs
//
// Auxiliary method for GetPoint On Surface
//
G4ThreeVector G4Polycone::GetPointOnTubs(G4double fRMin, G4double fRMax,
G4double zOne, G4double zTwo,
G4double& totArea) const
{
G4double xRand,yRand,zRand,phi,cosphi,sinphi,chose,
aOne,aTwo,aFou,rRand,fDz,fSPhi,fDPhi;
fDz = std::fabs(0.5*(zTwo-zOne));
fSPhi = startPhi;
fDPhi = endPhi-startPhi;
aOne = 2.*fDz*fDPhi*fRMax;
aTwo = 2.*fDz*fDPhi*fRMin;
aFou = 2.*fDz*(fRMax-fRMin);
totArea = aOne+aTwo+2.*aFou;
phi = G4RandFlat::shoot(startPhi,endPhi);
cosphi = std::cos(phi);
sinphi = std::sin(phi);
rRand = fRMin + (fRMax-fRMin)*std::sqrt(G4RandFlat::shoot());
if(startPhi == 0. && endPhi == twopi)
aFou = 0.;
chose = G4RandFlat::shoot(0.,aOne+aTwo+2.*aFou);
if( (chose >= 0.) && (chose < aOne) )
{
xRand = fRMax*cosphi;
yRand = fRMax*sinphi;
zRand = G4RandFlat::shoot(-1.*fDz,fDz);
return G4ThreeVector(xRand, yRand, zRand+0.5*(zTwo+zOne));
}
else if( (chose >= aOne) && (chose < aOne + aTwo) )
{
xRand = fRMin*cosphi;
yRand = fRMin*sinphi;
zRand = G4RandFlat::shoot(-1.*fDz,fDz);
return G4ThreeVector(xRand, yRand, zRand+0.5*(zTwo+zOne));
}
else if( (chose >= aOne+aTwo) && (chose <aOne+aTwo+aFou) )
{
xRand = rRand*std::cos(fSPhi+fDPhi);
yRand = rRand*std::sin(fSPhi+fDPhi);
zRand = G4RandFlat::shoot(-1.*fDz,fDz);
return G4ThreeVector(xRand, yRand, zRand+0.5*(zTwo+zOne));
}
// else
xRand = rRand*std::cos(fSPhi+fDPhi);
yRand = rRand*std::sin(fSPhi+fDPhi);
zRand = G4RandFlat::shoot(-1.*fDz,fDz);
return G4ThreeVector(xRand, yRand, zRand+0.5*(zTwo+zOne));
}
// GetPointOnRing
//
// Auxiliary method for GetPoint On Surface
//
G4ThreeVector G4Polycone::GetPointOnRing(G4double fRMin1, G4double fRMax1,
G4double fRMin2,G4double fRMax2,
G4double zOne) const
G4double G4Polycone::GetCubicVolume()
{
G4double xRand,yRand,phi,cosphi,sinphi,rRand1,rRand2,A1,Atot,rCh;
phi = G4RandFlat::shoot(startPhi,endPhi);
cosphi = std::cos(phi);
sinphi = std::sin(phi);
if(fRMin1==fRMin2)
if (fCubicVolume == 0.)
{
rRand1 = fRMin1; A1=0.;
G4double total = 0.;
G4int nrz = GetNumRZCorner();
G4PolyconeSideRZ a = GetCorner(nrz - 1);
for (G4int i=0; i<nrz; ++i)
{
G4PolyconeSideRZ b = GetCorner(i);
total += (b.r*b.r + b.r*a.r + a.r*a.r)*(b.z - a.z);
a = b;
}
fCubicVolume = std::abs(total)*(GetEndPhi() - GetStartPhi())/6.;
}
else
{
rRand1 = G4RandFlat::shoot(fRMin1,fRMin2);
A1=std::fabs(fRMin2*fRMin2-fRMin1*fRMin1);
}
if(fRMax1==fRMax2)
{
rRand2=fRMax1; Atot=A1;
}
else
{
rRand2 = G4RandFlat::shoot(fRMax1,fRMax2);
Atot = A1+std::fabs(fRMax2*fRMax2-fRMax1*fRMax1);
}
rCh = G4RandFlat::shoot(0.,Atot);
if(rCh>A1) { rRand1=rRand2; }
xRand = rRand1*cosphi;
yRand = rRand1*sinphi;
return G4ThreeVector(xRand, yRand, zOne);
return fCubicVolume;
}
// GetPointOnCut
//////////////////////////////////////////////////////////////////////////
//
// Auxiliary method for Get Point On Surface
//
G4ThreeVector G4Polycone::GetPointOnCut(G4double fRMin1, G4double fRMax1,
G4double fRMin2, G4double fRMax2,
G4double zOne, G4double zTwo,
G4double& totArea) const
{ if(zOne==zTwo)
// Return surface area
G4double G4Polycone::GetSurfaceArea()
{
if (fSurfaceArea == 0.)
{
// phi cut area
G4int nrz = GetNumRZCorner();
G4double scut = 0.;
if (IsOpen())
{
return GetPointOnRing(fRMin1, fRMax1,fRMin2,fRMax2,zOne);
G4PolyconeSideRZ a = GetCorner(nrz - 1);
for (G4int i=0; i<nrz; ++i)
{
G4PolyconeSideRZ b = GetCorner(i);
scut += a.r*b.z - a.z*b.r;
a = b;
}
scut = std::abs(scut);
}
if( (fRMin1 == fRMin2) && (fRMax1 == fRMax2) )
// lateral surface area
G4double slat = 0;
G4PolyconeSideRZ a = GetCorner(nrz - 1);
for (G4int i=0; i<nrz; ++i)
{
return GetPointOnTubs(fRMin1, fRMax1,zOne,zTwo,totArea);
G4PolyconeSideRZ b = GetCorner(i);
G4double h = std::sqrt((b.r - a.r)*(b.r - a.r) + (b.z - a.z)*(b.z - a.z));
slat += (b.r + a.r)*h;
a = b;
}
return GetPointOnCone(fRMin1,fRMax1,fRMin2,fRMax2,zOne,zTwo,totArea);
slat *= (GetEndPhi() - GetStartPhi())/2.;
fSurfaceArea = scut + slat;
}
return fSurfaceArea;
}
// GetPointOnSurface
//////////////////////////////////////////////////////////////////////////
//
// Set vector of surface elements, auxiliary method for sampling
// random points on surface
void G4Polycone::SetSurfaceElements() const
{
fElements = new std::vector<G4Polycone::surface_element>;
G4double total = 0.;
G4int nrz = GetNumRZCorner();
// set lateral surface elements
G4double dphi = GetEndPhi() - GetStartPhi();
G4int ia = nrz - 1;
for (G4int ib=0; ib<nrz; ++ib)
{
G4PolyconeSideRZ a = GetCorner(ia);
G4PolyconeSideRZ b = GetCorner(ib);
G4Polycone::surface_element selem;
selem.i0 = ia;
selem.i1 = ib;
selem.i2 = -1;
ia = ib;
if (a.r == 0. && b.r == 0.) continue;
G4double h = std::sqrt((b.r - a.r)*(b.r - a.r) + (b.z - a.z)*(b.z - a.z));
total += 0.5*dphi*(b.r + a.r)*h;
selem.area = total;
fElements->push_back(selem);
}
// set elements for phi cuts
if (IsOpen())
{
G4TwoVectorList contourRZ;
std::vector<G4int> triangles;
for (G4int i=0; i<nrz; ++i)
{
G4PolyconeSideRZ corner = GetCorner(i);
contourRZ.push_back(G4TwoVector(corner.r, corner.z));
}
G4GeomTools::TriangulatePolygon(contourRZ, triangles);
G4int ntria = triangles.size();
for (G4int i=0; i<ntria; i+=3)
{
G4Polycone::surface_element selem;
selem.i0 = triangles[i];
selem.i1 = triangles[i+1];
selem.i2 = triangles[i+2];
G4PolyconeSideRZ a = GetCorner(selem.i0);
G4PolyconeSideRZ b = GetCorner(selem.i1);
G4PolyconeSideRZ c = GetCorner(selem.i2);
G4double stria =
std::abs(G4GeomTools::TriangleArea(a.r, a.z, b.r, b.z, c.r, c.z));
total += stria;
selem.area = total;
fElements->push_back(selem); // start phi
total += stria;
selem.area = total;
selem.i0 += nrz;
fElements->push_back(selem); // end phi
}
}
}
//////////////////////////////////////////////////////////////////////////
//
// Generate random point on surface
G4ThreeVector G4Polycone::GetPointOnSurface() const
{
G4double Area=0.,totArea=0.,Achose1=0.,Achose2=0.,phi,cosphi,sinphi,rRand;
G4int i=0;
G4int numPlanes = original_parameters->Num_z_planes;
phi = G4RandFlat::shoot(startPhi,endPhi);
cosphi = std::cos(phi);
sinphi = std::sin(phi);
// Set surface elements
if (!fElements)
{
G4AutoLock l(&surface_elementsMutex);
SetSurfaceElements();
l.unlock();
}
rRand = original_parameters->Rmin[0] +
( (original_parameters->Rmax[0]-original_parameters->Rmin[0])
* std::sqrt(G4RandFlat::shoot()) );
// Select surface element
G4Polycone::surface_element selem;
selem = fElements->back();
G4double select = selem.area*G4QuickRand();
auto it = std::lower_bound(fElements->begin(), fElements->end(), select,
[](const G4Polycone::surface_element& x, G4double val)
-> G4bool { return x.area < val; });
std::vector<G4double> areas; // (numPlanes+1);
std::vector<G4ThreeVector> points; // (numPlanes-1);
areas.push_back(pi*(sqr(original_parameters->Rmax[0])
-sqr(original_parameters->Rmin[0])));
for(i=0; i<numPlanes-1; ++i)
// Generate random point
G4double r = 0, z = 0, phi = 0;
G4double u = G4QuickRand();
G4double v = G4QuickRand();
G4int i0 = (*it).i0;
G4int i1 = (*it).i1;
G4int i2 = (*it).i2;
if (i2 < 0) // lateral surface
{
G4PolyconeSideRZ p0 = GetCorner(i0);
G4PolyconeSideRZ p1 = GetCorner(i1);
if (p1.r < p0.r)
{
Area = (original_parameters->Rmin[i]+original_parameters->Rmin[i+1])
* std::sqrt(sqr(original_parameters->Rmin[i]
-original_parameters->Rmin[i+1])+
sqr(original_parameters->Z_values[i+1]
-original_parameters->Z_values[i]));
Area += (original_parameters->Rmax[i]+original_parameters->Rmax[i+1])
* std::sqrt(sqr(original_parameters->Rmax[i]
-original_parameters->Rmax[i+1])+
sqr(original_parameters->Z_values[i+1]
-original_parameters->Z_values[i]));
Area *= 0.5*(endPhi-startPhi);
if(startPhi==0.&& endPhi == twopi)
{
Area += std::fabs(original_parameters->Z_values[i+1]
-original_parameters->Z_values[i])*
(original_parameters->Rmax[i]
+original_parameters->Rmax[i+1]
-original_parameters->Rmin[i]
-original_parameters->Rmin[i+1]);
}
areas.push_back(Area);
totArea += Area;
p0 = GetCorner(i1);
p1 = GetCorner(i0);
}
areas.push_back(pi*(sqr(original_parameters->Rmax[numPlanes-1])-
sqr(original_parameters->Rmin[numPlanes-1])));
totArea += (areas[0]+areas[numPlanes]);
G4double chose = G4RandFlat::shoot(0.,totArea);
if( (chose>=0.) && (chose<areas[0]) )
if (p1.r - p0.r < kCarTolerance) // cylindrical surface
{
return G4ThreeVector(rRand*cosphi, rRand*sinphi,
original_parameters->Z_values[0]);
r = (p1.r - p0.r)*u + p0.r;
z = (p1.z - p0.z)*u + p0.z;
}
for (i=0; i<numPlanes-1; ++i)
else // conical surface
{
Achose1 += areas[i];
Achose2 = (Achose1+areas[i+1]);
if(chose>=Achose1 && chose<Achose2)
{
return GetPointOnCut(original_parameters->Rmin[i],
original_parameters->Rmax[i],
original_parameters->Rmin[i+1],
original_parameters->Rmax[i+1],
original_parameters->Z_values[i],
original_parameters->Z_values[i+1], Area);
}
r = std::sqrt(p1.r*p1.r*u + p0.r*p0.r*(1. - u));
z = p0.z + (p1.z - p0.z)*(r - p0.r)/(p1.r - p0.r);
}
rRand = original_parameters->Rmin[numPlanes-1] +
( (original_parameters->Rmax[numPlanes-1]-original_parameters->Rmin[numPlanes-1])
* std::sqrt(G4RandFlat::shoot()) );
return G4ThreeVector(rRand*cosphi,rRand*sinphi,
original_parameters->Z_values[numPlanes-1]);
phi = (GetEndPhi() - GetStartPhi())*v + GetStartPhi();
}
else // phi cut
{
G4int nrz = GetNumRZCorner();
phi = (i0 < nrz) ? GetStartPhi() : GetEndPhi();
if (i0 >= nrz) { i0 -= nrz; }
G4PolyconeSideRZ p0 = GetCorner(i0);
G4PolyconeSideRZ p1 = GetCorner(i1);
G4PolyconeSideRZ p2 = GetCorner(i2);
if (u + v > 1.) { u = 1. - u; v = 1. - v; }
r = (p1.r - p0.r)*u + (p2.r - p0.r)*v + p0.r;
z = (p1.z - p0.z)*u + (p2.z - p0.z)*v + p0.z;
}
return G4ThreeVector(r*std::cos(phi), r*std::sin(phi), z);
}
// CreatePolyhedron
//////////////////////////////////////////////////////////////////////////
//
// CreatePolyhedron
G4Polyhedron* G4Polycone::CreatePolyhedron() const
{
{
//
// This has to be fixed in visualization. Fake it for the moment.
//
//
return new G4PolyhedronPcon( original_parameters->Start_angle,
original_parameters->Opening_angle,
original_parameters->Num_z_planes,
@@ -1053,12 +973,12 @@ G4Polyhedron* G4Polycone::CreatePolyhedron() const
//
G4bool G4Polycone::SetOriginalParameters(G4ReduciblePolygon* rz)
{
G4int numPlanes = numCorner;
G4int numPlanes = numCorner;
G4bool isConvertible = true;
G4double Zmax=rz->Bmax();
rz->StartWithZMin();
// Prepare vectors for storage
// Prepare vectors for storage
//
std::vector<G4double> Z;
std::vector<G4double> Rmin;
@@ -1074,24 +994,24 @@ G4bool G4Polycone::SetOriginalParameters(G4ReduciblePolygon* rz)
G4double Zprev=Z[0];
if (Zprev == corners[1].z)
{
Rmin.push_back(corners[0].r);
Rmax.push_back (corners[1].r);icurr=1;
Rmin.push_back(corners[0].r);
Rmax.push_back (corners[1].r);icurr=1;
}
else if (Zprev == corners[numPlanes-1].z)
{
Rmin.push_back(corners[numPlanes-1].r);
Rmin.push_back(corners[numPlanes-1].r);
Rmax.push_back (corners[0].r);
icurl=numPlanes-1;
icurl=numPlanes-1;
}
else
{
Rmin.push_back(corners[0].r);
Rmin.push_back(corners[0].r);
Rmax.push_back (corners[0].r);
}
// next planes until last
//
G4int inextr=0, inextl=0;
G4int inextr=0, inextl=0;
for (G4int i=0; i < numPlanes-2; ++i)
{
inextr=1+icurr;
@@ -1103,7 +1023,7 @@ G4bool G4Polycone::SetOriginalParameters(G4ReduciblePolygon* rz)
G4double Zright = corners[inextr].z;
if(Zright > Zleft) // Next plane will be Zleft
{
Z.push_back(Zleft);
Z.push_back(Zleft);
countPlanes++;
G4double difZr=corners[inextr].z - corners[icurr].z;
G4double difZl=corners[inextl].z - corners[icurl].z;
@@ -1119,7 +1039,7 @@ G4bool G4Polycone::SetOriginalParameters(G4ReduciblePolygon* rz)
{
Rmin.push_back(corners[inextl].r);
Rmax.push_back(corners[icurr].r + (Zleft-corners[icurr].z)/difZr
*(corners[inextr].r - corners[icurr].r));
*(corners[inextr].r - corners[icurr].r));
}
}
else if (difZl >= kCarTolerance)
@@ -1144,18 +1064,18 @@ G4bool G4Polycone::SetOriginalParameters(G4ReduciblePolygon* rz)
}
else if(std::fabs(Zright-Zleft)<kCarTolerance) // Zright=Zleft
{
Z.push_back(Zleft);
Z.push_back(Zleft);
++countPlanes;
++icurr;
icurl=(icurl == 0)? numPlanes-1 : icurl-1;
Rmin.push_back(corners[inextl].r);
Rmin.push_back(corners[inextl].r);
Rmax.push_back(corners[inextr].r);
}
else // Zright<Zleft
{
Z.push_back(Zright);
Z.push_back(Zright);
++countPlanes;
G4double difZr=corners[inextr].z - corners[icurr].z;
@@ -1165,8 +1085,8 @@ G4bool G4Polycone::SetOriginalParameters(G4ReduciblePolygon* rz)
if(std::fabs(difZl) < kCarTolerance)
{
Rmax.push_back(corners[inextr].r);
Rmin.push_back(corners[icurr].r);
}
Rmin.push_back(corners[icurr].r);
}
else
{
Rmin.push_back(corners[icurl].r + (Zright-corners[icurl].z)/difZl
@@ -1180,8 +1100,8 @@ G4bool G4Polycone::SetOriginalParameters(G4ReduciblePolygon* rz)
if(std::fabs(difZl) < kCarTolerance)
{
Rmax.push_back(corners[inextr].r);
Rmin.push_back (corners[icurr].r);
}
Rmin.push_back (corners[icurr].r);
}
else
{
Rmax.push_back(corners[inextr].r);
@@ -1203,7 +1123,7 @@ G4bool G4Polycone::SetOriginalParameters(G4ReduciblePolygon* rz)
++countPlanes;
inextr=1+icurr;
inextl=(icurl <= 0)? numPlanes-1 : icurl-1;
Rmax.push_back(corners[inextr].r);
Rmin.push_back(corners[inextl].r);
@@ -1215,7 +1135,7 @@ G4bool G4Polycone::SetOriginalParameters(G4ReduciblePolygon* rz)
original_parameters->Z_values = new G4double[countPlanes];
original_parameters->Rmin = new G4double[countPlanes];
original_parameters->Rmax = new G4double[countPlanes];
for(G4int j=0; j < countPlanes; ++j)
{
original_parameters->Z_values[j] = Z[j];
@@ -1225,7 +1145,7 @@ G4bool G4Polycone::SetOriginalParameters(G4ReduciblePolygon* rz)
original_parameters->Start_angle = startPhi;
original_parameters->Opening_angle = endPhi-startPhi;
original_parameters->Num_z_planes = countPlanes;
}
else // Set parameters(r,z) with Rmin==0 as convention
{
@@ -1240,7 +1160,7 @@ G4bool G4Polycone::SetOriginalParameters(G4ReduciblePolygon* rz)
original_parameters->Z_values = new G4double[numPlanes];
original_parameters->Rmin = new G4double[numPlanes];
original_parameters->Rmax = new G4double[numPlanes];
for(G4int j=0; j < numPlanes; ++j)
{
original_parameters->Z_values[j] = corners[j].z;
+288 -303
View File
@@ -51,24 +51,27 @@
#include "G4AffineTransform.hh"
#include "G4BoundingEnvelope.hh"
#include "Randomize.hh"
#include "G4QuickRand.hh"
#include "G4EnclosingCylinder.hh"
#include "G4ReduciblePolygon.hh"
#include "G4VPVParameterisation.hh"
#include <sstream>
namespace
{
G4Mutex surface_elementsMutex = G4MUTEX_INITIALIZER;
}
using namespace CLHEP;
// Constructor (GEANT3 style parameters)
//
// GEANT3 PGON radii are specified in the distance to the norm of each face.
//
G4Polyhedra::G4Polyhedra( const G4String& name,
//
G4Polyhedra::G4Polyhedra( const G4String& name,
G4double phiStart,
G4double thePhiTotal,
G4int theNumSide,
G4int theNumSide,
G4int numZPlanes,
const G4double zPlane[],
const G4double rInner[],
@@ -96,7 +99,7 @@ G4Polyhedra::G4Polyhedra( const G4String& name,
// Some historical stuff
//
original_parameters = new G4PolyhedraHistorical;
original_parameters->numSide = theNumSide;
original_parameters->Start_angle = phiStart;
original_parameters->Opening_angle = phiTotal;
@@ -129,34 +132,34 @@ G4Polyhedra::G4Polyhedra( const G4String& name,
original_parameters->Rmin[i] = rInner[i]/convertRad;
original_parameters->Rmax[i] = rOuter[i]/convertRad;
}
//
// Build RZ polygon using special PCON/PGON GEANT3 constructor
//
G4ReduciblePolygon* rz =
new G4ReduciblePolygon( rInner, rOuter, zPlane, numZPlanes );
rz->ScaleA( 1/convertRad );
//
// Do the real work
//
Create( phiStart, phiTotal, theNumSide, rz );
delete rz;
}
// Constructor (generic parameters)
//
G4Polyhedra::G4Polyhedra( const G4String& name,
G4Polyhedra::G4Polyhedra( const G4String& name,
G4double phiStart,
G4double phiTotal,
G4int theNumSide,
G4int theNumSide,
G4int numRZ,
const G4double r[],
const G4double z[] )
: G4VCSGfaceted( name ), genericPgon(true)
{
{
if (theNumSide <= 0)
{
std::ostringstream message;
@@ -167,13 +170,13 @@ G4Polyhedra::G4Polyhedra( const G4String& name,
}
G4ReduciblePolygon* rz = new G4ReduciblePolygon( r, z, numRZ );
Create( phiStart, phiTotal, theNumSide, rz );
// Set original_parameters struct for consistency
//
SetOriginalParameters(rz);
delete rz;
}
@@ -184,7 +187,7 @@ G4Polyhedra::G4Polyhedra( const G4String& name,
//
void G4Polyhedra::Create( G4double phiStart,
G4double phiTotal,
G4int theNumSide,
G4int theNumSide,
G4ReduciblePolygon* rz )
{
//
@@ -212,9 +215,9 @@ void G4Polyhedra::Create( G4double phiStart,
G4Exception("G4Polyhedra::Create()", "GeomSolids0002",
FatalErrorInArgument, message);
}
if ( (!rz->RemoveDuplicateVertices( kCarTolerance ))
|| (!rz->RemoveRedundantVertices( kCarTolerance )) )
|| (!rz->RemoveRedundantVertices( kCarTolerance )) )
{
std::ostringstream message;
message << "Illegal input parameters - " << GetName() << G4endl
@@ -223,7 +226,7 @@ void G4Polyhedra::Create( G4double phiStart,
FatalErrorInArgument, message);
}
if (rz->CrossesItself( 1/kInfinity ))
if (rz->CrossesItself( 1/kInfinity ))
{
std::ostringstream message;
message << "Illegal input parameters - " << GetName() << G4endl
@@ -250,7 +253,7 @@ void G4Polyhedra::Create( G4double phiStart,
else
{
phiIsOpen = true;
//
// Convert phi into our convention
//
@@ -258,14 +261,14 @@ void G4Polyhedra::Create( G4double phiStart,
while( endPhi < startPhi ) // Loop checking, 13.08.2015, G.Cosmo
endPhi += twopi;
}
//
// Save number sides
//
numSide = theNumSide;
//
// Allocate corner array.
// Allocate corner array.
//
corners = new G4PolyhedraSideRZ[numCorner];
@@ -273,7 +276,7 @@ void G4Polyhedra::Create( G4double phiStart,
// Copy corners
//
G4ReduciblePolygonIterator iterRZ(rz);
G4PolyhedraSideRZ *next = corners;
iterRZ.Begin();
do // Loop checking, 13.08.2015, G.Cosmo
@@ -281,13 +284,13 @@ void G4Polyhedra::Create( G4double phiStart,
next->r = iterRZ.GetA();
next->z = iterRZ.GetB();
} while( ++next, iterRZ.Next() );
//
// Allocate face pointer array
//
numFace = phiIsOpen ? numCorner+2 : numCorner;
faces = new G4VCSGface*[numFace];
//
// Construct side faces
//
@@ -306,7 +309,7 @@ void G4Polyhedra::Create( G4double phiStart,
if (next >= corners+numCorner) next = corners;
nextNext = next+1;
if (nextNext >= corners+numCorner) nextNext = corners;
if (corner->r < 1/kInfinity && next->r < 1/kInfinity) continue;
/*
// We must decide here if we can dare declare one of our faces
@@ -333,7 +336,7 @@ void G4Polyhedra::Create( G4double phiStart,
*face++ = new G4PolyhedraSide( prev, corner, next, nextNext,
numSide, startPhi, endPhi-startPhi, phiIsOpen );
} while( prev=corner, corner=next, corner > corners );
if (phiIsOpen)
{
//
@@ -342,12 +345,12 @@ void G4Polyhedra::Create( G4double phiStart,
*face++ = new G4PolyPhiFace( rz, startPhi, phiTotal/numSide, endPhi );
*face++ = new G4PolyPhiFace( rz, endPhi, phiTotal/numSide, startPhi );
}
//
// We might have dropped a face or two: recalculate numFace
//
numFace = face-faces;
//
// Make enclosingCylinder
//
@@ -370,6 +373,13 @@ G4Polyhedra::~G4Polyhedra()
delete [] corners;
delete original_parameters;
delete enclosingCylinder;
delete fElements;
delete fpPolyhedron;
corners = nullptr;
original_parameters = nullptr;
enclosingCylinder = nullptr;
fElements = nullptr;
fpPolyhedron = nullptr;
}
// Copy constructor
@@ -387,13 +397,13 @@ G4Polyhedra &G4Polyhedra::operator=( const G4Polyhedra& source )
if (this == &source) return *this;
G4VCSGfaceted::operator=( source );
delete [] corners;
delete original_parameters;
delete enclosingCylinder;
CopyStuff( source );
return *this;
}
@@ -415,14 +425,14 @@ void G4Polyhedra::CopyStuff( const G4Polyhedra& source )
// The corner array
//
corners = new G4PolyhedraSideRZ[numCorner];
G4PolyhedraSideRZ* corn = corners,
* sourceCorn = source.corners;
do // Loop checking, 13.08.2015, G.Cosmo
{
*corn = *sourceCorn;
} while( ++sourceCorn, ++corn < corners+numCorner );
//
// Original parameters
//
@@ -431,13 +441,23 @@ void G4Polyhedra::CopyStuff( const G4Polyhedra& source )
original_parameters =
new G4PolyhedraHistorical( *source.original_parameters );
}
//
// Enclosing cylinder
//
enclosingCylinder = new G4EnclosingCylinder( *source.enclosingCylinder );
//
// Surface elements
//
delete fElements;
fElements = nullptr;
//
// Polyhedron
//
fRebuildPolyhedron = false;
delete fpPolyhedron;
fpPolyhedron = nullptr;
}
@@ -464,6 +484,10 @@ G4bool G4Polyhedra::Reset()
G4VCSGfaceted::DeleteStuff();
delete [] corners;
delete enclosingCylinder;
delete fElements;
corners = nullptr;
fElements = nullptr;
enclosingCylinder = nullptr;
//
// Rebuild polyhedra
@@ -512,7 +536,7 @@ G4double G4Polyhedra::DistanceToIn( const G4ThreeVector& p,
//
if (enclosingCylinder->ShouldMiss(p,v))
return kInfinity;
//
// Long answer
//
@@ -783,274 +807,235 @@ std::ostream& G4Polyhedra::StreamInfo( std::ostream& os ) const
return os;
}
// GetPointOnPlane
//////////////////////////////////////////////////////////////////////////
//
// Auxiliary method for get point on surface
//
G4ThreeVector
G4Polyhedra::GetPointOnPlane(G4ThreeVector p0, G4ThreeVector p1,
G4ThreeVector p2, G4ThreeVector p3) const
// Return volume
G4double G4Polyhedra::GetCubicVolume()
{
G4double lambda1, lambda2, chose,aOne,aTwo;
G4ThreeVector t, u, v, w, Area, normal;
aOne = 1.;
aTwo = 1.;
t = p1 - p0;
u = p2 - p1;
v = p3 - p2;
w = p0 - p3;
chose = G4RandFlat::shoot(0.,aOne+aTwo);
if( (chose>=0.) && (chose < aOne) )
if (fCubicVolume == 0.)
{
lambda1 = G4RandFlat::shoot(0.,1.);
lambda2 = G4RandFlat::shoot(0.,lambda1);
return (p2+lambda1*v+lambda2*w);
G4double total = 0.;
G4int nrz = GetNumRZCorner();
G4PolyhedraSideRZ a = GetCorner(nrz - 1);
for (G4int i=0; i<nrz; ++i)
{
G4PolyhedraSideRZ b = GetCorner(i);
total += (b.r*b.r + b.r*a.r + a.r*a.r)*(b.z - a.z);
a = b;
}
fCubicVolume = std::abs(total)*
std::sin((GetEndPhi() - GetStartPhi())/GetNumSide())*GetNumSide()/6.;
}
return fCubicVolume;
}
//////////////////////////////////////////////////////////////////////////
//
// Return surface area
G4double G4Polyhedra::GetSurfaceArea()
{
if (fSurfaceArea == 0.)
{
G4double total = 0.;
G4int nrz = GetNumRZCorner();
if (IsOpen())
{
G4PolyhedraSideRZ a = GetCorner(nrz - 1);
for (G4int i=0; i<nrz; ++i)
{
G4PolyhedraSideRZ b = GetCorner(i);
total += a.r*b.z - a.z*b.r;
a = b;
}
total = std::abs(total);
}
G4double alp = (GetEndPhi() - GetStartPhi())/GetNumSide();
G4double cosa = std::cos(alp);
G4double sina = std::sin(alp);
G4PolyhedraSideRZ a = GetCorner(nrz - 1);
for (G4int i=0; i<nrz; ++i)
{
G4PolyhedraSideRZ b = GetCorner(i);
G4ThreeVector p1(a.r, 0, a.z);
G4ThreeVector p2(a.r*cosa, a.r*sina, a.z);
G4ThreeVector p3(b.r*cosa, b.r*sina, b.z);
G4ThreeVector p4(b.r, 0, b.z);
total += GetNumSide()*(G4GeomTools::QuadAreaNormal(p1, p2, p3, p4)).mag();
a = b;
}
fSurfaceArea = total;
}
return fSurfaceArea;
}
//////////////////////////////////////////////////////////////////////////
//
// Set vector of surface elements, auxiliary method for sampling
// random points on surface
void G4Polyhedra::SetSurfaceElements() const
{
fElements = new std::vector<G4Polyhedra::surface_element>;
G4double total = 0.;
G4int nrz = GetNumRZCorner();
// set lateral surface elements
G4double dphi = (GetEndPhi() - GetStartPhi())/GetNumSide();
G4double cosa = std::cos(dphi);
G4double sina = std::sin(dphi);
G4int ia = nrz - 1;
for (G4int ib=0; ib<nrz; ++ib)
{
G4PolyhedraSideRZ a = GetCorner(ia);
G4PolyhedraSideRZ b = GetCorner(ib);
G4Polyhedra::surface_element selem;
selem.i0 = ia;
selem.i1 = ib;
ia = ib;
if (a.r == 0. && b.r == 0.) continue;
G4ThreeVector p1(a.r, 0, a.z);
G4ThreeVector p2(a.r*cosa, a.r*sina, a.z);
G4ThreeVector p3(b.r*cosa, b.r*sina, b.z);
G4ThreeVector p4(b.r, 0, b.z);
if (a.r > 0.)
{
selem.i2 = -1;
total += GetNumSide()*(G4GeomTools::TriangleAreaNormal(p1, p2, p3)).mag();
selem.area = total;
fElements->push_back(selem);
}
if (b.r > 0.)
{
selem.i2 = -2;
total += GetNumSide()*(G4GeomTools::TriangleAreaNormal(p1, p3, p4)).mag();
selem.area = total;
fElements->push_back(selem);
}
}
lambda1 = G4RandFlat::shoot(0.,1.);
lambda2 = G4RandFlat::shoot(0.,lambda1);
return (p0+lambda1*t+lambda2*u);
// set elements for phi cuts
if (IsOpen())
{
G4TwoVectorList contourRZ;
std::vector<G4int> triangles;
for (G4int i=0; i<nrz; ++i)
{
G4PolyhedraSideRZ corner = GetCorner(i);
contourRZ.push_back(G4TwoVector(corner.r, corner.z));
}
G4GeomTools::TriangulatePolygon(contourRZ, triangles);
G4int ntria = triangles.size();
for (G4int i=0; i<ntria; i+=3)
{
G4Polyhedra::surface_element selem;
selem.i0 = triangles[i];
selem.i1 = triangles[i+1];
selem.i2 = triangles[i+2];
G4PolyhedraSideRZ a = GetCorner(selem.i0);
G4PolyhedraSideRZ b = GetCorner(selem.i1);
G4PolyhedraSideRZ c = GetCorner(selem.i2);
G4double stria =
std::abs(G4GeomTools::TriangleArea(a.r, a.z, b.r, b.z, c.r, c.z));
total += stria;
selem.area = total;
fElements->push_back(selem); // start phi
total += stria;
selem.area = total;
selem.i0 += nrz;
fElements->push_back(selem); // end phi
}
}
}
// GetPointOnTriangle
//////////////////////////////////////////////////////////////////////////
//
// Auxiliary method for get point on surface
//
G4ThreeVector G4Polyhedra::GetPointOnTriangle(G4ThreeVector p1,
G4ThreeVector p2,
G4ThreeVector p3) const
{
G4double lambda1,lambda2;
G4ThreeVector v=p3-p1, w=p1-p2;
// Generate random point on surface
lambda1 = G4RandFlat::shoot(0.,1.);
lambda2 = G4RandFlat::shoot(0.,lambda1);
return (p2 + lambda1*w + lambda2*v);
}
// GetPointOnSurface
//
G4ThreeVector G4Polyhedra::GetPointOnSurface() const
{
if( !genericPgon ) // Polyhedra by faces
// Set surface elements
if (!fElements)
{
G4int j, numPlanes = original_parameters->Num_z_planes, Flag=0;
G4double chose, totArea=0., Achose1, Achose2,
rad1, rad2, sinphi1, sinphi2, cosphi1, cosphi2;
G4double a, b, l2, rang, totalPhi, ksi,
area, aTop=0., aBottom=0., zVal=0.;
G4AutoLock l(&surface_elementsMutex);
SetSurfaceElements();
l.unlock();
}
G4ThreeVector p0, p1, p2, p3;
std::vector<G4double> aVector1;
std::vector<G4double> aVector2;
std::vector<G4double> aVector3;
// Select surface element
G4Polyhedra::surface_element selem;
selem = fElements->back();
G4double select = selem.area*G4QuickRand();
auto it = std::lower_bound(fElements->begin(), fElements->end(), select,
[](const G4Polyhedra::surface_element& x, G4double val)
-> G4bool { return x.area < val; });
totalPhi= (phiIsOpen) ? (endPhi-startPhi) : twopi;
ksi = totalPhi/numSide;
G4double cosksi = std::cos(ksi/2.);
// Below we generate the areas relevant to our solid
//
for(j=0; j<numPlanes-1; ++j)
// Generate random point
G4double x = 0, y = 0, z = 0;
G4double u = G4QuickRand();
G4double v = G4QuickRand();
if (u + v > 1.) { u = 1. - u; v = 1. - v; }
G4int i0 = (*it).i0;
G4int i1 = (*it).i1;
G4int i2 = (*it).i2;
if (i2 < 0) // lateral surface
{
// sample point
G4int nside = GetNumSide();
G4double dphi = (GetEndPhi() - GetStartPhi())/nside;
G4double cosa = std::cos(dphi);
G4double sina = std::sin(dphi);
G4PolyhedraSideRZ a = GetCorner(i0);
G4PolyhedraSideRZ b = GetCorner(i1);
G4ThreeVector p0(a.r, 0, a.z);
G4ThreeVector p1(b.r, 0, b.z);
G4ThreeVector p2(b.r*cosa, b.r*sina, b.z);
if (i2 == -1) p1.set(a.r*cosa, a.r*sina, a.z);
p0 += (p1 - p0)*u + (p2 - p0)*v;
// find selected side and rotate point
G4double scurr = (*it).area;
G4double sprev = (it == fElements->begin()) ? 0. : (*(--it)).area;
G4int iside = nside*(select - sprev)/(scurr - sprev);
if (iside == 0 && GetStartPhi() == 0.)
{
a = original_parameters->Rmax[j+1];
b = original_parameters->Rmax[j];
l2 = sqr(original_parameters->Z_values[j]
-original_parameters->Z_values[j+1]) + sqr(b-a);
area = std::sqrt(l2-sqr((a-b)*cosksi))*(a+b)*cosksi;
aVector1.push_back(area);
}
for(j=0; j<numPlanes-1; ++j)
{
a = original_parameters->Rmin[j+1];//*cosksi;
b = original_parameters->Rmin[j];//*cosksi;
l2 = sqr(original_parameters->Z_values[j]
-original_parameters->Z_values[j+1]) + sqr(b-a);
area = std::sqrt(l2-sqr((a-b)*cosksi))*(a+b)*cosksi;
aVector2.push_back(area);
}
for(j=0; j<numPlanes-1; ++j)
{
if(phiIsOpen == true)
{
aVector3.push_back(0.5*(original_parameters->Rmax[j]
-original_parameters->Rmin[j]
+original_parameters->Rmax[j+1]
-original_parameters->Rmin[j+1])
*std::fabs(original_parameters->Z_values[j+1]
-original_parameters->Z_values[j]));
}
else { aVector3.push_back(0.); }
}
for(j=0; j<numPlanes-1; ++j)
{
totArea += numSide*(aVector1[j]+aVector2[j])+2.*aVector3[j];
}
// Must include top and bottom areas
//
if(original_parameters->Rmax[numPlanes-1] != 0.)
{
a = original_parameters->Rmax[numPlanes-1];
b = original_parameters->Rmin[numPlanes-1];
l2 = sqr(a-b);
aTop = std::sqrt(l2-sqr((a-b)*cosksi))*(a+b)*cosksi;
}
if(original_parameters->Rmax[0] != 0.)
{
a = original_parameters->Rmax[0];
b = original_parameters->Rmin[0];
l2 = sqr(a-b);
aBottom = std::sqrt(l2-sqr((a-b)*cosksi))*(a+b)*cosksi;
}
Achose1 = 0.;
Achose2 = numSide*(aVector1[0]+aVector2[0])+2.*aVector3[0];
chose = G4RandFlat::shoot(0.,totArea+aTop+aBottom);
if( (chose >= 0.) && (chose < aTop + aBottom) )
{
chose = G4RandFlat::shoot(startPhi,startPhi+totalPhi);
rang = std::floor((chose-startPhi)/ksi-0.01);
if(rang<0) { rang=0; }
rang = std::fabs(rang);
sinphi1 = std::sin(startPhi+rang*ksi);
sinphi2 = std::sin(startPhi+(rang+1)*ksi);
cosphi1 = std::cos(startPhi+rang*ksi);
cosphi2 = std::cos(startPhi+(rang+1)*ksi);
chose = G4RandFlat::shoot(0., aTop + aBottom);
if(chose>=0. && chose<aTop)
{
rad1 = original_parameters->Rmin[numPlanes-1];
rad2 = original_parameters->Rmax[numPlanes-1];
zVal = original_parameters->Z_values[numPlanes-1];
}
else
{
rad1 = original_parameters->Rmin[0];
rad2 = original_parameters->Rmax[0];
zVal = original_parameters->Z_values[0];
}
p0 = G4ThreeVector(rad1*cosphi1,rad1*sinphi1,zVal);
p1 = G4ThreeVector(rad2*cosphi1,rad2*sinphi1,zVal);
p2 = G4ThreeVector(rad2*cosphi2,rad2*sinphi2,zVal);
p3 = G4ThreeVector(rad1*cosphi2,rad1*sinphi2,zVal);
return GetPointOnPlane(p0,p1,p2,p3);
x = p0.x();
y = p0.y();
z = p0.z();
}
else
{
for (j=0; j<numPlanes-1; ++j)
{
if( ((chose >= Achose1) && (chose < Achose2)) || (j == numPlanes-2) )
{
Flag = j; break;
}
Achose1 += numSide*(aVector1[j]+aVector2[j])+2.*aVector3[j];
Achose2 = Achose1 + numSide*(aVector1[j+1]+aVector2[j+1])
+ 2.*aVector3[j+1];
}
if (iside == nside) --iside; // iside must be less then nside
G4double phi = iside*dphi + GetStartPhi();
G4double cosphi = std::cos(phi);
G4double sinphi = std::sin(phi);
x = p0.x()*cosphi - p0.y()*sinphi;
y = p0.x()*sinphi + p0.y()*cosphi;
z = p0.z();
}
// At this point we have chosen a subsection
// between to adjacent plane cuts...
j = Flag;
totArea = numSide*(aVector1[j]+aVector2[j])+2.*aVector3[j];
chose = G4RandFlat::shoot(0.,totArea);
if( (chose>=0.) && (chose<numSide*aVector1[j]) )
{
chose = G4RandFlat::shoot(startPhi,startPhi+totalPhi);
rang = std::floor((chose-startPhi)/ksi-0.01);
if(rang<0) { rang=0; }
rang = std::fabs(rang);
rad1 = original_parameters->Rmax[j];
rad2 = original_parameters->Rmax[j+1];
sinphi1 = std::sin(startPhi+rang*ksi);
sinphi2 = std::sin(startPhi+(rang+1)*ksi);
cosphi1 = std::cos(startPhi+rang*ksi);
cosphi2 = std::cos(startPhi+(rang+1)*ksi);
zVal = original_parameters->Z_values[j];
p0 = G4ThreeVector(rad1*cosphi1,rad1*sinphi1,zVal);
p1 = G4ThreeVector(rad1*cosphi2,rad1*sinphi2,zVal);
zVal = original_parameters->Z_values[j+1];
p2 = G4ThreeVector(rad2*cosphi2,rad2*sinphi2,zVal);
p3 = G4ThreeVector(rad2*cosphi1,rad2*sinphi1,zVal);
return GetPointOnPlane(p0,p1,p2,p3);
}
else if ( (chose >= numSide*aVector1[j])
&& (chose <= numSide*(aVector1[j]+aVector2[j])) )
{
chose = G4RandFlat::shoot(startPhi,startPhi+totalPhi);
rang = std::floor((chose-startPhi)/ksi-0.01);
if(rang<0) { rang=0; }
rang = std::fabs(rang);
rad1 = original_parameters->Rmin[j];
rad2 = original_parameters->Rmin[j+1];
sinphi1 = std::sin(startPhi+rang*ksi);
sinphi2 = std::sin(startPhi+(rang+1)*ksi);
cosphi1 = std::cos(startPhi+rang*ksi);
cosphi2 = std::cos(startPhi+(rang+1)*ksi);
zVal = original_parameters->Z_values[j];
p0 = G4ThreeVector(rad1*cosphi1,rad1*sinphi1,zVal);
p1 = G4ThreeVector(rad1*cosphi2,rad1*sinphi2,zVal);
zVal = original_parameters->Z_values[j+1];
p2 = G4ThreeVector(rad2*cosphi2,rad2*sinphi2,zVal);
p3 = G4ThreeVector(rad2*cosphi1,rad2*sinphi1,zVal);
return GetPointOnPlane(p0,p1,p2,p3);
}
chose = G4RandFlat::shoot(0.,2.2);
if( (chose>=0.) && (chose < 1.) )
{
rang = startPhi;
}
else
{
rang = endPhi;
}
cosphi1 = std::cos(rang); rad1 = original_parameters->Rmin[j];
sinphi1 = std::sin(rang); rad2 = original_parameters->Rmax[j];
p0 = G4ThreeVector(rad1*cosphi1,rad1*sinphi1,
original_parameters->Z_values[j]);
p1 = G4ThreeVector(rad2*cosphi1,rad2*sinphi1,
original_parameters->Z_values[j]);
rad1 = original_parameters->Rmax[j+1];
rad2 = original_parameters->Rmin[j+1];
p2 = G4ThreeVector(rad1*cosphi1,rad1*sinphi1,
original_parameters->Z_values[j+1]);
p3 = G4ThreeVector(rad2*cosphi1,rad2*sinphi1,
original_parameters->Z_values[j+1]);
return GetPointOnPlane(p0,p1,p2,p3);
}
else // Generic polyhedra
else // phi cut
{
return GetPointOnSurfaceGeneric();
G4int nrz = GetNumRZCorner();
G4double phi = (i0 < nrz) ? GetStartPhi() : GetEndPhi();
if (i0 >= nrz) { i0 -= nrz; }
G4PolyhedraSideRZ p0 = GetCorner(i0);
G4PolyhedraSideRZ p1 = GetCorner(i1);
G4PolyhedraSideRZ p2 = GetCorner(i2);
G4double r = (p1.r - p0.r)*u + (p2.r - p0.r)*v + p0.r;
x = r*std::cos(phi);
y = r*std::sin(phi);
z = (p1.z - p0.z)*u + (p2.z - p0.z)*v + p0.z;
}
return G4ThreeVector(x, y, z);
}
// CreatePolyhedron
//////////////////////////////////////////////////////////////////////////
//
// CreatePolyhedron
G4Polyhedron* G4Polyhedra::CreatePolyhedron() const
{
{
if (!genericPgon)
{
return new G4PolyhedronPgon( original_parameters->Start_angle,
@@ -1077,8 +1062,8 @@ G4Polyhedron* G4Polyhedra::CreatePolyhedron() const
* array starts from 1 (like in fortran). The indexes can be positive
* or negative. Negative sign means that the corresponding edge is
* invisible. The normal of the face should be directed to exterior
* of the polyhedron.
*
* of the polyhedron.
*
* @param Nnodes number of nodes
* @param Nfaces number of faces
* @param xyz nodes
@@ -1309,12 +1294,12 @@ G4Polyhedron* G4Polyhedra::CreatePolyhedron() const
//
void G4Polyhedra::SetOriginalParameters(G4ReduciblePolygon* rz)
{
G4int numPlanes = numCorner;
G4int numPlanes = numCorner;
G4bool isConvertible = true;
G4double Zmax=rz->Bmax();
rz->StartWithZMin();
// Prepare vectors for storage
// Prepare vectors for storage
//
std::vector<G4double> Z;
std::vector<G4double> Rmin;
@@ -1330,24 +1315,24 @@ void G4Polyhedra::SetOriginalParameters(G4ReduciblePolygon* rz)
G4double Zprev=Z[0];
if (Zprev == corners[1].z)
{
Rmin.push_back(corners[0].r);
Rmax.push_back (corners[1].r);icurr=1;
Rmin.push_back(corners[0].r);
Rmax.push_back (corners[1].r);icurr=1;
}
else if (Zprev == corners[numPlanes-1].z)
{
Rmin.push_back(corners[numPlanes-1].r);
Rmin.push_back(corners[numPlanes-1].r);
Rmax.push_back (corners[0].r);
icurl=numPlanes-1;
icurl=numPlanes-1;
}
else
{
Rmin.push_back(corners[0].r);
Rmin.push_back(corners[0].r);
Rmax.push_back (corners[0].r);
}
// next planes until last
//
G4int inextr=0, inextl=0;
G4int inextr=0, inextl=0;
for (G4int i=0; i < numPlanes-2; ++i)
{
inextr=1+icurr;
@@ -1359,7 +1344,7 @@ void G4Polyhedra::SetOriginalParameters(G4ReduciblePolygon* rz)
G4double Zright = corners[inextr].z;
if(Zright>Zleft)
{
Z.push_back(Zleft);
Z.push_back(Zleft);
countPlanes++;
G4double difZr=corners[inextr].z - corners[icurr].z;
G4double difZl=corners[inextl].z - corners[icurl].z;
@@ -1375,7 +1360,7 @@ void G4Polyhedra::SetOriginalParameters(G4ReduciblePolygon* rz)
{
Rmin.push_back(corners[inextl].r);
Rmax.push_back(corners[icurr].r + (Zleft-corners[icurr].z)/difZr
*(corners[inextr].r - corners[icurr].r));
*(corners[inextr].r - corners[icurr].r));
}
}
else if (difZl >= kCarTolerance)
@@ -1400,18 +1385,18 @@ void G4Polyhedra::SetOriginalParameters(G4ReduciblePolygon* rz)
}
else if(std::fabs(Zright-Zleft)<kCarTolerance) // Zright=Zleft
{
Z.push_back(Zleft);
Z.push_back(Zleft);
++countPlanes;
++icurr;
icurl=(icurl == 0)? numPlanes-1 : icurl-1;
Rmin.push_back(corners[inextl].r);
Rmin.push_back(corners[inextl].r);
Rmax.push_back (corners[inextr].r);
}
else // Zright<Zleft
{
Z.push_back(Zright);
Z.push_back(Zright);
++countPlanes;
G4double difZr=corners[inextr].z - corners[icurr].z;
@@ -1421,8 +1406,8 @@ void G4Polyhedra::SetOriginalParameters(G4ReduciblePolygon* rz)
if(std::fabs(difZl) < kCarTolerance)
{
Rmax.push_back(corners[inextr].r);
Rmin.push_back(corners[icurr].r);
}
Rmin.push_back(corners[icurr].r);
}
else
{
Rmin.push_back(corners[icurl].r + (Zright-corners[icurl].z)/difZl
@@ -1436,8 +1421,8 @@ void G4Polyhedra::SetOriginalParameters(G4ReduciblePolygon* rz)
if(std::fabs(difZl) < kCarTolerance)
{
Rmax.push_back(corners[inextr].r);
Rmin.push_back (corners[icurr].r);
}
Rmin.push_back (corners[icurr].r);
}
else
{
Rmax.push_back(corners[inextr].r);
@@ -1459,7 +1444,7 @@ void G4Polyhedra::SetOriginalParameters(G4ReduciblePolygon* rz)
++countPlanes;
inextr=1+icurr;
inextl=(icurl <= 0)? numPlanes-1 : icurl-1;
Rmax.push_back(corners[inextr].r);
Rmin.push_back(corners[inextl].r);
@@ -1472,7 +1457,7 @@ void G4Polyhedra::SetOriginalParameters(G4ReduciblePolygon* rz)
original_parameters->Z_values = new G4double[countPlanes];
original_parameters->Rmin = new G4double[countPlanes];
original_parameters->Rmax = new G4double[countPlanes];
for(G4int j=0; j < countPlanes; ++j)
{
original_parameters->Z_values[j] = Z[j];
@@ -1482,7 +1467,7 @@ void G4Polyhedra::SetOriginalParameters(G4ReduciblePolygon* rz)
original_parameters->Start_angle = startPhi;
original_parameters->Opening_angle = endPhi-startPhi;
original_parameters->Num_z_planes = countPlanes;
}
else // Set parameters(r,z) with Rmin==0 as convention
{
@@ -1498,7 +1483,7 @@ void G4Polyhedra::SetOriginalParameters(G4ReduciblePolygon* rz)
original_parameters->Z_values = new G4double[numPlanes];
original_parameters->Rmin = new G4double[numPlanes];
original_parameters->Rmax = new G4double[numPlanes];
for(G4int j=0; j < numPlanes; ++j)
{
original_parameters->Z_values[j] = corners[j].z;
@@ -383,7 +383,7 @@ G4Polyhedron* G4UGenericPolycone::CreatePolyhedron() const
// Here is an extract from the header file HepPolyhedron.h:
/**
* Creates user defined polyhedron.
* This function allows to the user to define arbitrary polyhedron.
* This function allows one to the user to define arbitrary polyhedron.
* The faces of the polyhedron should be either triangles or planar
* quadrilateral. Nodes of a face are defined by indexes pointing to
* the elements in the xyz array. Numeration of the elements in the
@@ -266,7 +266,7 @@ G4bool G4UPolycone::Reset()
message << "Solid " << GetName() << " built using generic construct."
<< G4endl << "Not applicable to the generic construct !";
G4Exception("G4UPolycone::Reset()", "GeomSolids1001",
JustWarning, message, "Parameters NOT resetted.");
JustWarning, message, "Parameters NOT reset.");
return true; // error code set
}
@@ -284,7 +284,7 @@ G4bool G4UPolyhedra::Reset()
message << "Solid " << GetName() << " built using generic construct."
<< G4endl << "Not applicable to the generic construct !";
G4Exception("G4UPolyhedra::Reset()", "GeomSolids1001",
JustWarning, message, "Parameters NOT resetted.");
JustWarning, message, "Parameters NOT reset.");
return true; // error code set
}
@@ -614,7 +614,7 @@ G4Polyhedron* G4UPolyhedra::CreatePolyhedron() const
// Here is an extract from the header file HepPolyhedron.h:
/**
* Creates user defined polyhedron.
* This function allows to the user to define arbitrary polyhedron.
* This function allows the user to define arbitrary polyhedron.
* The faces of the polyhedron should be either triangles or planar
* quadrilateral. Nodes of a face are defined by indexes pointing to
* the elements in the xyz array. Numeration of the elements in the