Import Geant4 11.0.0 source tree
This commit is contained in:
committed by
Ben Morgan
parent
6399a014b6
commit
80e2389dd8
@@ -38,7 +38,7 @@
|
||||
// 12.10.2012, M Gayer, CERN, complete rewrite reducing memory
|
||||
// requirements more than 50% and speedup by a factor of
|
||||
// tens or more depending on the number of facets, thanks
|
||||
// to voxelization of surface and improvements.
|
||||
// to voxelization of surface and improvements.
|
||||
// Speedup factor of thousands for solids with number of
|
||||
// facets in hundreds of thousands.
|
||||
// 23.10.2016, E Tcherniaev, reimplemented CalculateExtent() to make
|
||||
@@ -56,6 +56,7 @@
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <random>
|
||||
|
||||
#include "geomdefs.hh"
|
||||
#include "Randomize.hh"
|
||||
@@ -248,7 +249,7 @@ G4bool G4TessellatedSolid::AddFacet (G4VFacet* aFacet)
|
||||
{
|
||||
--it;
|
||||
G4int id = (*it).id;
|
||||
G4VFacet *facet = fFacets[id];
|
||||
G4VFacet *facet = fFacets[id];
|
||||
G4ThreeVector q = facet->GetCircumcentre();
|
||||
found = (facet == aFacet);
|
||||
if (found) break;
|
||||
@@ -268,7 +269,7 @@ G4bool G4TessellatedSolid::AddFacet (G4VFacet* aFacet)
|
||||
else
|
||||
{
|
||||
G4Exception("G4TessellatedSolid::AddFacet()", "GeomSolids1002",
|
||||
JustWarning, "Attempt to add facet not properly defined.");
|
||||
JustWarning, "Attempt to add facet not properly defined.");
|
||||
aFacet->StreamInfo(G4cout);
|
||||
return false;
|
||||
}
|
||||
@@ -392,21 +393,52 @@ void G4TessellatedSolid::Voxelize ()
|
||||
// returns true. So will this work?? Need non-equality
|
||||
// "G4bool inside = displacement < 0.0;"
|
||||
// or
|
||||
// "G4bool inside = displacement <= -0.5*kCarTolerance"
|
||||
// "G4bool inside = displacement <= -0.5*kCarTolerance"
|
||||
// (Notes from PT 13/08/2007).
|
||||
//
|
||||
void G4TessellatedSolid::SetExtremeFacets()
|
||||
{
|
||||
// Copy vertices to local array
|
||||
G4int vsize = fVertexList.size();
|
||||
std::vector<G4ThreeVector> vertices(vsize);
|
||||
for (G4int i = 0; i < vsize; ++i) { vertices[i] = fVertexList[i]; }
|
||||
|
||||
// Shuffle vertices
|
||||
std::mt19937 gen(12345678);
|
||||
std::shuffle(vertices.begin(), vertices.end(), gen);
|
||||
|
||||
// Select six extreme vertices in different directions
|
||||
G4ThreeVector points[6];
|
||||
for (G4int i=0; i < 6; ++i) { points[i] = vertices[0]; }
|
||||
for (G4int i=1; i < vsize; ++i)
|
||||
{
|
||||
if (vertices[i].x() < points[0].x()) points[0] = vertices[i];
|
||||
if (vertices[i].x() > points[1].x()) points[1] = vertices[i];
|
||||
if (vertices[i].y() < points[2].y()) points[2] = vertices[i];
|
||||
if (vertices[i].y() > points[3].y()) points[3] = vertices[i];
|
||||
if (vertices[i].z() < points[4].z()) points[4] = vertices[i];
|
||||
if (vertices[i].z() > points[5].z()) points[5] = vertices[i];
|
||||
}
|
||||
|
||||
// Find extreme facets
|
||||
G4int size = fFacets.size();
|
||||
for (G4int j = 0; j < size; ++j)
|
||||
{
|
||||
G4VFacet &facet = *fFacets[j];
|
||||
|
||||
// Check extreme vertices
|
||||
if (!facet.IsInside(points[0])) continue;
|
||||
if (!facet.IsInside(points[1])) continue;
|
||||
if (!facet.IsInside(points[2])) continue;
|
||||
if (!facet.IsInside(points[3])) continue;
|
||||
if (!facet.IsInside(points[4])) continue;
|
||||
if (!facet.IsInside(points[5])) continue;
|
||||
|
||||
// Check vertices
|
||||
G4bool isExtreme = true;
|
||||
G4int vsize = fVertexList.size();
|
||||
for (G4int i=0; i < vsize; ++i)
|
||||
{
|
||||
if (!facet.IsInside(fVertexList[i]))
|
||||
if (!facet.IsInside(vertices[i]))
|
||||
{
|
||||
isExtreme = false;
|
||||
break;
|
||||
@@ -442,7 +474,7 @@ void G4TessellatedSolid::CreateVertexList()
|
||||
G4double kCarTolerance24 = kCarTolerance * kCarTolerance / 4.0;
|
||||
G4double kCarTolerance3 = 3 * kCarTolerance;
|
||||
vector<G4int> newIndex(100);
|
||||
|
||||
|
||||
for (G4int k = 0; k < size; ++k)
|
||||
{
|
||||
G4VFacet &facet = *fFacets[k];
|
||||
@@ -505,7 +537,7 @@ void G4TessellatedSolid::CreateVertexList()
|
||||
//
|
||||
// Now update the maximum x, y and z limits of the volume.
|
||||
//
|
||||
if (value.id == 0) fMinExtent = fMaxExtent = p;
|
||||
if (value.id == 0) fMinExtent = fMaxExtent = p;
|
||||
else
|
||||
{
|
||||
if (p.x() > fMaxExtent.x()) fMaxExtent.setX(p.x());
|
||||
@@ -534,7 +566,7 @@ void G4TessellatedSolid::CreateVertexList()
|
||||
facet.SetVertexIndex(i,newIndex[i]);
|
||||
}
|
||||
vector<G4ThreeVector>(fVertexList).swap(fVertexList);
|
||||
|
||||
|
||||
#ifdef G4SPECSDEBUG
|
||||
G4double previousValue = 0.;
|
||||
for (auto res=vertexListSorted.cbegin(); res!=vertexListSorted.cend(); ++res)
|
||||
@@ -543,7 +575,7 @@ void G4TessellatedSolid::CreateVertexList()
|
||||
G4ThreeVector vec = fVertexList[id];
|
||||
G4double mvalue = vec.x() + vec.y() + vec.z();
|
||||
if (previousValue && (previousValue - 1e-9 > mvalue))
|
||||
G4cout << "Error in CreateVertexList: previousValue " << previousValue
|
||||
G4cout << "Error in CreateVertexList: previousValue " << previousValue
|
||||
<< " is smaller than mvalue " << mvalue << G4endl;
|
||||
previousValue = mvalue;
|
||||
}
|
||||
@@ -558,7 +590,7 @@ void G4TessellatedSolid::DisplayAllocatedMemory()
|
||||
G4int with = AllocatedMemory();
|
||||
G4double ratio = (G4double) with / without;
|
||||
G4cout << "G4TessellatedSolid - Allocated memory without voxel overhead "
|
||||
<< without << "; with " << with << "; ratio: " << ratio << G4endl;
|
||||
<< without << "; with " << with << "; ratio: " << ratio << G4endl;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -567,17 +599,17 @@ void G4TessellatedSolid::SetSolidClosed (const G4bool t)
|
||||
{
|
||||
if (t)
|
||||
{
|
||||
#ifdef G4SPECSDEBUG
|
||||
#ifdef G4SPECSDEBUG
|
||||
G4cout << "Creating vertex list..." << G4endl;
|
||||
#endif
|
||||
CreateVertexList();
|
||||
|
||||
#ifdef G4SPECSDEBUG
|
||||
#ifdef G4SPECSDEBUG
|
||||
G4cout << "Setting extreme facets..." << G4endl;
|
||||
#endif
|
||||
SetExtremeFacets();
|
||||
|
||||
#ifdef G4SPECSDEBUG
|
||||
|
||||
#ifdef G4SPECSDEBUG
|
||||
G4cout << "Voxelizing..." << G4endl;
|
||||
#endif
|
||||
Voxelize();
|
||||
@@ -586,7 +618,38 @@ void G4TessellatedSolid::SetSolidClosed (const G4bool t)
|
||||
DisplayAllocatedMemory();
|
||||
#endif
|
||||
|
||||
}
|
||||
#ifdef G4SPECSDEBUG
|
||||
G4cout << "Checking Structure..." << G4endl;
|
||||
#endif
|
||||
G4int irep = CheckStructure();
|
||||
if (irep != 0)
|
||||
{
|
||||
if (irep & 1)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Defects in solid: " << GetName()
|
||||
<< " - negative cubic volume, please check orientation of facets!";
|
||||
G4Exception("G4TessellatedSolid::SetSolidClosed()",
|
||||
"GeomSolids1001", JustWarning, message);
|
||||
}
|
||||
if (irep & 2)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Defects in solid: " << GetName()
|
||||
<< " - some facets have wrong orientation!";
|
||||
G4Exception("G4TessellatedSolid::SetSolidClosed()",
|
||||
"GeomSolids1001", JustWarning, message);
|
||||
}
|
||||
if (irep & 4)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Defects in solid: " << GetName()
|
||||
<< " - there are holes in the surface!";
|
||||
G4Exception("G4TessellatedSolid::SetSolidClosed()",
|
||||
"GeomSolids1001", JustWarning, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
fSolidClosed = t;
|
||||
}
|
||||
|
||||
@@ -601,6 +664,77 @@ G4bool G4TessellatedSolid::GetSolidClosed () const
|
||||
return fSolidClosed;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CheckStructure
|
||||
//
|
||||
// Checks structure of the solid. Return value is a sum of the following
|
||||
// defect indicators, if any (0 means no defects):
|
||||
// 1 - cubic volume is negative, wrong orientation of facets
|
||||
// 2 - some facets have wrong orientation
|
||||
// 4 - holes in the surface
|
||||
//
|
||||
G4int G4TessellatedSolid::CheckStructure() const
|
||||
{
|
||||
G4int nedge = 0;
|
||||
G4int nface = fFacets.size();
|
||||
|
||||
// Calculate volume
|
||||
//
|
||||
G4double volume = 0.;
|
||||
for (G4int i = 0; i < nface; ++i)
|
||||
{
|
||||
G4VFacet& facet = *fFacets[i];
|
||||
nedge += facet.GetNumberOfVertices();
|
||||
volume += facet.GetArea()*(facet.GetVertex(0).dot(facet.GetSurfaceNormal()));
|
||||
}
|
||||
G4int ivolume = (volume <= 0.);
|
||||
|
||||
// Create sorted vector of edges
|
||||
//
|
||||
std::vector<int64_t> iedge(nedge);
|
||||
G4int kk = 0;
|
||||
for (G4int i = 0; i < nface; ++i)
|
||||
{
|
||||
G4VFacet& facet = *fFacets[i];
|
||||
G4int nnode = facet.GetNumberOfVertices();
|
||||
for (G4int k = 0; k < nnode; ++k)
|
||||
{
|
||||
int64_t i1 = facet.GetVertexIndex((k == 0) ? nnode - 1 : k - 1);
|
||||
int64_t i2 = facet.GetVertexIndex(k);
|
||||
int64_t inverse = (i2 > i1);
|
||||
if (inverse) std::swap(i1, i2);
|
||||
iedge[kk++] = i1*1000000000 + i2*2 + inverse;
|
||||
}
|
||||
}
|
||||
std::sort(iedge.begin(), iedge.end());
|
||||
|
||||
// Check edges, correct structure should consist of paired edges
|
||||
// with different orientation
|
||||
//
|
||||
G4int iorder = 0;
|
||||
G4int ihole = 0;
|
||||
G4int i = 0;
|
||||
while (i < nedge - 1)
|
||||
{
|
||||
if (iedge[i + 1] - iedge[i] == 1) // paired edges with different orientation
|
||||
{
|
||||
i += 2;
|
||||
}
|
||||
else if (iedge[i + 1] == iedge[i]) // paired edges with the same orientation
|
||||
{
|
||||
iorder = 2;
|
||||
i += 2;
|
||||
}
|
||||
else // unpaired edge
|
||||
{
|
||||
ihole = 4;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return ivolume + iorder + ihole;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// operator+=
|
||||
@@ -722,7 +856,7 @@ EInside G4TessellatedSolid::InsideVoxels(const G4ThreeVector& p) const
|
||||
started ? startingCandidates : fVoxels.GetCandidates(curVoxel);
|
||||
started = false;
|
||||
if (G4int candidatesCount = candidates.size())
|
||||
{
|
||||
{
|
||||
for (G4int i = 0 ; i < candidatesCount; ++i)
|
||||
{
|
||||
G4int candidate = candidates[i];
|
||||
@@ -741,9 +875,9 @@ EInside G4TessellatedSolid::InsideVoxels(const G4ThreeVector& p) const
|
||||
|| (crossingI && std::fabs(normalI.dot(v))<dirTolerance);
|
||||
if (!nearParallel)
|
||||
{
|
||||
if (crossingO && distO > 0.0 && distO < distOut)
|
||||
if (crossingO && distO > 0.0 && distO < distOut)
|
||||
distOut = distO;
|
||||
if (crossingI && distI > 0.0 && distI < distIn)
|
||||
if (crossingI && distI > 0.0 && distI < distIn)
|
||||
distIn = distI;
|
||||
}
|
||||
else break;
|
||||
@@ -819,7 +953,7 @@ EInside G4TessellatedSolid::InsideVoxels(const G4ThreeVector& p) const
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
EInside G4TessellatedSolid::InsideNoVoxels (const G4ThreeVector &p) const
|
||||
@@ -963,6 +1097,55 @@ EInside G4TessellatedSolid::InsideNoVoxels (const G4ThreeVector &p) const
|
||||
return location;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Return index of the facet closest to the point p, normally the point should
|
||||
// be located on the surface. Return -1 if no facet selected.
|
||||
//
|
||||
G4int G4TessellatedSolid::GetFacetIndex (const G4ThreeVector& p) const
|
||||
{
|
||||
G4int index = -1;
|
||||
|
||||
if (fVoxels.GetCountOfVoxels() > 1)
|
||||
{
|
||||
vector<G4int> curVoxel(3);
|
||||
fVoxels.GetVoxel(curVoxel, p);
|
||||
const vector<G4int> &candidates = fVoxels.GetCandidates(curVoxel);
|
||||
if (G4int limit = candidates.size())
|
||||
{
|
||||
G4double minDist = kInfinity;
|
||||
for(G4int i = 0 ; i < limit ; ++i)
|
||||
{
|
||||
G4int candidate = candidates[i];
|
||||
G4VFacet& facet = *fFacets[candidate];
|
||||
G4double dist = facet.Distance(p, minDist);
|
||||
if (dist <= kCarToleranceHalf) return index = candidate;
|
||||
if (dist < minDist)
|
||||
{
|
||||
minDist = dist;
|
||||
index = candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
G4double minDist = kInfinity;
|
||||
G4int size = fFacets.size();
|
||||
for (G4int i = 0; i < size; ++i)
|
||||
{
|
||||
G4VFacet& facet = *fFacets[i];
|
||||
G4double dist = facet.Distance(p, minDist);
|
||||
if (dist < minDist)
|
||||
{
|
||||
minDist = dist;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Return the outwards pointing unit normal of the shape for the
|
||||
@@ -985,7 +1168,7 @@ G4bool G4TessellatedSolid::Normal (const G4ThreeVector& p,
|
||||
{
|
||||
minDist = kInfinity;
|
||||
for(G4int i = 0 ; i < limit ; ++i)
|
||||
{
|
||||
{
|
||||
G4int candidate = candidates[i];
|
||||
G4VFacet &fct = *fFacets[candidate];
|
||||
G4double dist = fct.Distance(p,minDist);
|
||||
@@ -1257,8 +1440,8 @@ G4TessellatedSolid::DistanceToOutCore(const G4ThreeVector& aPoint,
|
||||
if (old != &candidates && candidates.size())
|
||||
{
|
||||
DistanceToOutCandidates(candidates, aPoint, direction, minDistance,
|
||||
aNormalVector, minCandidate);
|
||||
if (minDistance <= totalShift) break;
|
||||
aNormalVector, minCandidate);
|
||||
if (minDistance <= totalShift) break;
|
||||
}
|
||||
|
||||
G4double shift=fVoxels.DistanceToNext(currentPoint, direction, curVoxel);
|
||||
@@ -1306,7 +1489,7 @@ DistanceToInCandidates(const std::vector<G4int>& candidates,
|
||||
G4double distFromSurface = 0.0;
|
||||
G4ThreeVector normal;
|
||||
|
||||
G4double minDistance = kInfinity;
|
||||
G4double minDistance = kInfinity;
|
||||
for (G4int i = 0 ; i < candidatesCount; ++i)
|
||||
{
|
||||
G4int candidate = candidates[i];
|
||||
@@ -1334,7 +1517,7 @@ DistanceToInCandidates(const std::vector<G4int>& candidates,
|
||||
else if (distFromSurface > -kCarToleranceHalf
|
||||
&& distFromSurface < kCarToleranceHalf)
|
||||
{
|
||||
minDistance = dist;
|
||||
minDistance = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1359,7 +1542,7 @@ G4TessellatedSolid::DistanceToInCore(const G4ThreeVector& aPoint,
|
||||
G4double shift = fVoxels.DistanceToFirst(currentPoint, direction);
|
||||
if (shift == kInfinity) return shift;
|
||||
G4double shiftBonus = kCarTolerance;
|
||||
if (shift)
|
||||
if (shift)
|
||||
currentPoint += direction * (shift + shiftBonus);
|
||||
// if (!fVoxels.Contains(currentPoint)) return minDistance;
|
||||
G4double totalShift = shift;
|
||||
@@ -1416,7 +1599,7 @@ G4TessellatedSolid::MinDistanceFacet(const G4ThreeVector& p,
|
||||
|
||||
G4int size = fVoxels.GetVoxelBoxesSize();
|
||||
vector<pair<G4int, G4double> > voxelsSorted(size);
|
||||
|
||||
|
||||
pair<G4int, G4double> info;
|
||||
|
||||
for (G4int i = 0; i < size; ++i)
|
||||
@@ -1519,7 +1702,7 @@ G4double G4TessellatedSolid::SafetyFromOutside (const G4ThreeVector& p,
|
||||
//
|
||||
G4double
|
||||
G4TessellatedSolid::SafetyFromInside (const G4ThreeVector& p, G4bool) const
|
||||
{
|
||||
{
|
||||
#if G4SPECSDEBUG
|
||||
if ( Inside(p) == kOutside )
|
||||
{
|
||||
@@ -1767,7 +1950,7 @@ G4Polyhedron *G4TessellatedSolid::CreatePolyhedron () const
|
||||
}
|
||||
polyhedron->AddFacet(v[0],v[1],v[2],v[3]);
|
||||
}
|
||||
polyhedron->SetReferences();
|
||||
polyhedron->SetReferences();
|
||||
|
||||
return (G4Polyhedron*) polyhedron;
|
||||
}
|
||||
|
||||
@@ -250,11 +250,15 @@ void G4Tet::Initialize(const G4ThreeVector& p0,
|
||||
void G4Tet::SetVertices(const G4ThreeVector& p0,
|
||||
const G4ThreeVector& p1,
|
||||
const G4ThreeVector& p2,
|
||||
const G4ThreeVector& p3)
|
||||
const G4ThreeVector& p3, G4bool* degeneracyFlag)
|
||||
{
|
||||
// Check for degeneracy
|
||||
G4bool degenerate = CheckDegeneracy(p0, p1, p2, p3);
|
||||
if (degenerate)
|
||||
if (degeneracyFlag)
|
||||
{
|
||||
*degeneracyFlag = degenerate;
|
||||
}
|
||||
else if (degenerate)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Degenerate tetrahedron is not permitted: " << GetName() << " !\n"
|
||||
@@ -264,7 +268,7 @@ void G4Tet::SetVertices(const G4ThreeVector& p0,
|
||||
<< " p3 : " << p3 << "\n"
|
||||
<< " volume: "
|
||||
<< std::abs((p1 - p0).cross(p2 - p0).dot(p3 - p0))/6.;
|
||||
G4Exception("G4Tet::G4SetVertices()", "GeomSolids0002",
|
||||
G4Exception("G4Tet::SetVertices()", "GeomSolids0002",
|
||||
FatalException, message);
|
||||
}
|
||||
|
||||
@@ -312,6 +316,43 @@ void G4Tet::ComputeDimensions(G4VPVParameterisation* ,
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set bounding box
|
||||
//
|
||||
void G4Tet::SetBoundingLimits(const G4ThreeVector& pMin,
|
||||
const G4ThreeVector& pMax)
|
||||
{
|
||||
G4int iout[4] = { 0, 0, 0, 0 };
|
||||
for (G4int i = 0; i < 4; ++i)
|
||||
{
|
||||
iout[i] = (fVertex[i].x() < pMin.x() ||
|
||||
fVertex[i].y() < pMin.y() ||
|
||||
fVertex[i].z() < pMin.z() ||
|
||||
fVertex[i].x() > pMax.x() ||
|
||||
fVertex[i].y() > pMax.y() ||
|
||||
fVertex[i].z() > pMax.z());
|
||||
}
|
||||
if (iout[0] + iout[1] + iout[2] + iout[3] != 0)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Attempt to set bounding box that does not encapsulate solid: "
|
||||
<< GetName() << " !\n"
|
||||
<< " Specified bounding box limits:\n"
|
||||
<< " pmin: " << pMin << "\n"
|
||||
<< " pmax: " << pMax << "\n"
|
||||
<< " Tetrahedron vertices:\n"
|
||||
<< " anchor " << fVertex[0] << ((iout[0]) ? " is outside\n" : "\n")
|
||||
<< " p1 " << fVertex[1] << ((iout[1]) ? " is outside\n" : "\n")
|
||||
<< " p2 " << fVertex[2] << ((iout[2]) ? " is outside\n" : "\n")
|
||||
<< " p3 " << fVertex[3] << ((iout[3]) ? " is outside" : "");
|
||||
G4Exception("G4Tet::SetBoundingLimits()", "GeomSolids0002",
|
||||
FatalException, message);
|
||||
}
|
||||
fBmin = pMin;
|
||||
fBmax = pMax;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Return bounding box
|
||||
|
||||
@@ -346,9 +346,9 @@ G4ThreeVector G4TriangularFacet::Distance (const G4ThreeVector& p)
|
||||
//
|
||||
// We are in region 0.
|
||||
//
|
||||
q = q / fDet;
|
||||
t = t / fDet;
|
||||
fSqrDist = q*(fA*q + fB*t + 2.0*d) + t*(fB*q + fC*t + 2.0*e) + f;
|
||||
G4double dist = fSurfaceNormal.dot(D);
|
||||
fSqrDist = dist*dist;
|
||||
return fSurfaceNormal*dist;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "G4TwistedTubs.hh"
|
||||
|
||||
#include "G4GeomTools.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4GeometryTolerance.hh"
|
||||
@@ -308,10 +309,31 @@ void G4TwistedTubs::ComputeDimensions(G4VPVParameterisation* /* p */ ,
|
||||
void G4TwistedTubs::BoundingLimits(G4ThreeVector& pMin,
|
||||
G4ThreeVector& pMax) const
|
||||
{
|
||||
G4double maxEndOuterRad = (fEndOuterRadius[0] > fEndOuterRadius[1] ?
|
||||
fEndOuterRadius[0] : fEndOuterRadius[1]);
|
||||
pMin.set(-maxEndOuterRad,-maxEndOuterRad,-fZHalfLength);
|
||||
pMax.set( maxEndOuterRad, maxEndOuterRad, fZHalfLength);
|
||||
// Find bounding tube
|
||||
G4double rmin = GetInnerRadius();
|
||||
G4double rmax = GetEndOuterRadius();
|
||||
|
||||
G4double zmin = std::min(GetEndZ(0), GetEndZ(1));
|
||||
G4double zmax = std::max(GetEndZ(0), GetEndZ(1));
|
||||
|
||||
G4double dphi = 0.5*GetDPhi();
|
||||
G4double sphi = std::min(GetEndPhi(0), GetEndPhi(1)) - dphi;
|
||||
G4double ephi = std::max(GetEndPhi(0), GetEndPhi(1)) + dphi;
|
||||
G4double totalphi = ephi - sphi;
|
||||
|
||||
// Find bounding box
|
||||
if (dphi <= 0 || totalphi >= CLHEP::twopi)
|
||||
{
|
||||
pMin.set(-rmax,-rmax, zmin);
|
||||
pMax.set( rmax, rmax, zmax);
|
||||
}
|
||||
else
|
||||
{
|
||||
G4TwoVector vmin,vmax;
|
||||
G4GeomTools::DiskExtent(rmin, rmax, sphi, totalphi, vmin, vmax);
|
||||
pMin.set(vmin.x(), vmin.y(), zmin);
|
||||
pMax.set(vmax.x(), vmax.y(), zmax);
|
||||
}
|
||||
|
||||
// Check correctness of the bounding box
|
||||
//
|
||||
@@ -859,15 +881,15 @@ void G4TwistedTubs::DescribeYourselfTo (G4VGraphicsScene& scene) const
|
||||
//=====================================================================
|
||||
//* GetExtent ---------------------------------------------------------
|
||||
|
||||
G4VisExtent G4TwistedTubs::GetExtent() const
|
||||
G4VisExtent G4TwistedTubs::GetExtent() const
|
||||
{
|
||||
// Define the sides of the box into which the G4Tubs instance would fit.
|
||||
|
||||
G4double maxEndOuterRad = (fEndOuterRadius[0] > fEndOuterRadius[1] ?
|
||||
fEndOuterRadius[0] : fEndOuterRadius[1]);
|
||||
return G4VisExtent( -maxEndOuterRad, maxEndOuterRad,
|
||||
-maxEndOuterRad, maxEndOuterRad,
|
||||
-fZHalfLength, fZHalfLength );
|
||||
//
|
||||
G4ThreeVector pmin,pmax;
|
||||
BoundingLimits(pmin,pmax);
|
||||
return G4VisExtent(pmin.x(),pmax.x(),
|
||||
pmin.y(),pmax.y(),
|
||||
pmin.z(),pmax.z());
|
||||
}
|
||||
|
||||
//=====================================================================
|
||||
@@ -1008,9 +1030,23 @@ G4VSolid* G4TwistedTubs::Clone() const
|
||||
|
||||
G4double G4TwistedTubs::GetCubicVolume()
|
||||
{
|
||||
if(fCubicVolume != 0.) {;}
|
||||
else { fCubicVolume = fDPhi*fZHalfLength*(fOuterRadius*fOuterRadius
|
||||
-fInnerRadius*fInnerRadius); }
|
||||
if (fCubicVolume == 0.)
|
||||
{
|
||||
G4double DPhi = GetDPhi();
|
||||
G4double Z0 = GetEndZ(0);
|
||||
G4double Z1 = GetEndZ(1);
|
||||
G4double Ain = GetInnerRadius();
|
||||
G4double Aout = GetOuterRadius();
|
||||
G4double R0in = GetEndInnerRadius(0);
|
||||
G4double R1in = GetEndInnerRadius(1);
|
||||
G4double R0out = GetEndOuterRadius(0);
|
||||
G4double R1out = GetEndOuterRadius(1);
|
||||
|
||||
// V_hyperboloid = pi*h*(2*a*a + R*R)/3
|
||||
fCubicVolume = (2.*(Z1 - Z0)*(Aout + Ain)*(Aout - Ain)
|
||||
+ Z1*(R1out + R1in)*(R1out - R1in)
|
||||
- Z0*(R0out + R0in)*(R0out - R0in))*DPhi/6.;
|
||||
}
|
||||
return fCubicVolume;
|
||||
}
|
||||
|
||||
@@ -1019,8 +1055,7 @@ G4double G4TwistedTubs::GetCubicVolume()
|
||||
|
||||
G4double G4TwistedTubs::GetSurfaceArea()
|
||||
{
|
||||
if(fSurfaceArea != 0.) {;}
|
||||
else { fSurfaceArea = G4VSolid::GetSurfaceArea(); }
|
||||
if (fSurfaceArea == 0.) fSurfaceArea = G4VSolid::GetSurfaceArea();
|
||||
return fSurfaceArea;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// Implementation for G4UTet wrapper class
|
||||
//
|
||||
// 1.11.13 G.Cosmo, CERN
|
||||
@@ -49,44 +49,30 @@ using namespace CLHEP;
|
||||
// A Tet has all of its geometrical information precomputed
|
||||
//
|
||||
G4UTet::G4UTet(const G4String& pName,
|
||||
G4ThreeVector anchor,
|
||||
G4ThreeVector p2,
|
||||
G4ThreeVector p3,
|
||||
G4ThreeVector p4, G4bool* degeneracyFlag)
|
||||
const G4ThreeVector& anchor,
|
||||
const G4ThreeVector& p1,
|
||||
const G4ThreeVector& p2,
|
||||
const G4ThreeVector& p3, G4bool* degeneracyFlag)
|
||||
: Base_t(pName, U3Vector(anchor.x(),anchor.y(),anchor.z()),
|
||||
U3Vector(p1.x(), p1.y(), p1.z()),
|
||||
U3Vector(p2.x(), p2.y(), p2.z()),
|
||||
U3Vector(p3.x(), p3.y(), p3.z()),
|
||||
U3Vector(p4.x(), p4.y(), p4.z()))
|
||||
U3Vector(p3.x(), p3.y(), p3.z()))
|
||||
{
|
||||
G4double fXMin=std::min(std::min(std::min(anchor.x(), p2.x()),p3.x()),p4.x());
|
||||
G4double fXMax=std::max(std::max(std::max(anchor.x(), p2.x()),p3.x()),p4.x());
|
||||
G4double fYMin=std::min(std::min(std::min(anchor.y(), p2.y()),p3.y()),p4.y());
|
||||
G4double fYMax=std::max(std::max(std::max(anchor.y(), p2.y()),p3.y()),p4.y());
|
||||
G4double fZMin=std::min(std::min(std::min(anchor.z(), p2.z()),p3.z()),p4.z());
|
||||
G4double fZMax=std::max(std::max(std::max(anchor.z(), p2.z()),p3.z()),p4.z());
|
||||
|
||||
G4ThreeVector fMiddle=G4ThreeVector(fXMax+fXMin,fYMax+fYMin,fZMax+fZMin)*0.5;
|
||||
G4double fMaxSize=std::max(std::max(std::max((anchor-fMiddle).mag(),
|
||||
(p2-fMiddle).mag()),
|
||||
(p3-fMiddle).mag()),
|
||||
(p4-fMiddle).mag());
|
||||
// fV<x><y> is vector from vertex <y> to vertex <x>
|
||||
//
|
||||
G4ThreeVector fV21=p2-anchor;
|
||||
G4ThreeVector fV31=p3-anchor;
|
||||
G4ThreeVector fV41=p4-anchor;
|
||||
|
||||
// make sure this is a correctly oriented set of points for the tetrahedron
|
||||
//
|
||||
G4double signed_vol=fV21.cross(fV31).dot(fV41);
|
||||
G4bool degenerate=std::fabs(signed_vol) < 1e-9*fMaxSize*fMaxSize*fMaxSize;
|
||||
|
||||
// Check for degeneracy
|
||||
G4bool degenerate = CheckDegeneracy(anchor, p1, p2, p3);
|
||||
if(degeneracyFlag) *degeneracyFlag = degenerate;
|
||||
else if (degenerate)
|
||||
{
|
||||
G4Exception("G4UTet::G4UTet()", "GeomSolids0002", FatalException,
|
||||
"Degenerate tetrahedron not allowed.");
|
||||
}
|
||||
|
||||
// Set bounding box
|
||||
for (G4int i = 0; i < 3; ++i)
|
||||
{
|
||||
fBmin[i] = std::min(std::min(std::min(anchor[i], p1[i]), p2[i]), p3[i]);
|
||||
fBmax[i] = std::max(std::max(std::max(anchor[i], p1[i]), p2[i]), p3[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -114,6 +100,8 @@ G4UTet::~G4UTet()
|
||||
G4UTet::G4UTet(const G4UTet& rhs)
|
||||
: Base_t(rhs)
|
||||
{
|
||||
fBmin = rhs.fBmin;
|
||||
fBmax = rhs.fBmax;
|
||||
}
|
||||
|
||||
|
||||
@@ -121,17 +109,50 @@ G4UTet::G4UTet(const G4UTet& rhs)
|
||||
//
|
||||
// Assignment operator
|
||||
//
|
||||
G4UTet& G4UTet::operator = (const G4UTet& rhs)
|
||||
G4UTet& G4UTet::operator = (const G4UTet& rhs)
|
||||
{
|
||||
// Check assignment to self
|
||||
//
|
||||
if (this == &rhs) { return *this; }
|
||||
// Check assignment to self
|
||||
if (this == &rhs) { return *this; }
|
||||
|
||||
// Copy base class data
|
||||
//
|
||||
Base_t::operator=(rhs);
|
||||
// Copy base class data
|
||||
Base_t::operator=(rhs);
|
||||
|
||||
return *this;
|
||||
// Copy bounding box
|
||||
fBmin = rhs.fBmin;
|
||||
fBmax = rhs.fBmax;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Return true if tetrahedron is degenerate
|
||||
// Tetrahedron is concidered as degenerate in case if its minimal
|
||||
// height is less than the degeneracy tolerance
|
||||
//
|
||||
G4bool G4UTet::CheckDegeneracy(const G4ThreeVector& p0,
|
||||
const G4ThreeVector& p1,
|
||||
const G4ThreeVector& p2,
|
||||
const G4ThreeVector& p3) const
|
||||
{
|
||||
G4double hmin = 4. * kCarTolerance; // degeneracy tolerance
|
||||
|
||||
// Calculate volume
|
||||
G4double vol = std::abs((p1 - p0).cross(p2 - p0).dot(p3 - p0));
|
||||
|
||||
// Calculate face areas squared
|
||||
G4double ss[4];
|
||||
ss[0] = ((p1 - p0).cross(p2 - p0)).mag2();
|
||||
ss[1] = ((p2 - p0).cross(p3 - p0)).mag2();
|
||||
ss[2] = ((p3 - p0).cross(p1 - p0)).mag2();
|
||||
ss[3] = ((p2 - p1).cross(p3 - p1)).mag2();
|
||||
|
||||
// Find face with max area
|
||||
G4int k = 0;
|
||||
for (G4int i = 1; i < 4; ++i) { if (ss[i] > ss[k]) k = i; }
|
||||
|
||||
// Check: vol^2 / s^2 <= hmin^2
|
||||
return (vol*vol <= ss[k]*hmin*hmin);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -154,6 +175,29 @@ G4VSolid* G4UTet::Clone() const
|
||||
return new G4UTet(*this);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Modifier
|
||||
//
|
||||
void G4UTet::SetVertices(const G4ThreeVector& anchor,
|
||||
const G4ThreeVector& p1,
|
||||
const G4ThreeVector& p2,
|
||||
const G4ThreeVector& p3,
|
||||
G4bool* degeneracyFlag)
|
||||
{
|
||||
// Check for degeneracy
|
||||
G4bool degenerate = CheckDegeneracy(anchor, p1, p2, p3);
|
||||
if(degeneracyFlag) *degeneracyFlag = degenerate;
|
||||
else if (degenerate)
|
||||
{
|
||||
G4Exception("G4UTet::SetVertices()", "GeomSolids0002", FatalException,
|
||||
"Degenerate tetrahedron not allowed.");
|
||||
}
|
||||
|
||||
// Change tetrahedron
|
||||
*this = G4UTet(GetName(), anchor, p1, p2, p3, °enerate);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Accessors
|
||||
@@ -184,30 +228,54 @@ std::vector<G4ThreeVector> G4UTet::GetVertices() const
|
||||
return vertices;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Set bounding box
|
||||
//
|
||||
void G4UTet::SetBoundingLimits(const G4ThreeVector& pMin,
|
||||
const G4ThreeVector& pMax)
|
||||
{
|
||||
G4ThreeVector fVertex[4];
|
||||
GetVertices(fVertex[0], fVertex[1], fVertex[2], fVertex[3]);
|
||||
|
||||
G4int iout[4] = { 0, 0, 0, 0 };
|
||||
for (G4int i = 0; i < 4; ++i)
|
||||
{
|
||||
iout[i] = (fVertex[i].x() < pMin.x() ||
|
||||
fVertex[i].y() < pMin.y() ||
|
||||
fVertex[i].z() < pMin.z() ||
|
||||
fVertex[i].x() > pMax.x() ||
|
||||
fVertex[i].y() > pMax.y() ||
|
||||
fVertex[i].z() > pMax.z());
|
||||
}
|
||||
if (iout[0] + iout[1] + iout[2] + iout[3] != 0)
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Attempt to set bounding box that does not encapsulate solid: "
|
||||
<< GetName() << " !\n"
|
||||
<< " Specified bounding box limits:\n"
|
||||
<< " pmin: " << pMin << "\n"
|
||||
<< " pmax: " << pMax << "\n"
|
||||
<< " Tetrahedron vertices:\n"
|
||||
<< " anchor " << fVertex[0] << ((iout[0]) ? " is outside\n" : "\n")
|
||||
<< " p1 " << fVertex[1] << ((iout[1]) ? " is outside\n" : "\n")
|
||||
<< " p2 " << fVertex[2] << ((iout[2]) ? " is outside\n" : "\n")
|
||||
<< " p3 " << fVertex[3] << ((iout[3]) ? " is outside" : "");
|
||||
G4Exception("G4UTet::SetBoundingLimits()", "GeomSolids0002",
|
||||
FatalException, message);
|
||||
}
|
||||
fBmin = pMin;
|
||||
fBmax = pMax;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Get bounding box
|
||||
|
||||
void G4UTet::BoundingLimits(G4ThreeVector& pMin, G4ThreeVector& pMax) const
|
||||
{
|
||||
U3Vector vmin, vmax;
|
||||
Base_t::Extent(vmin,vmax);
|
||||
pMin.set(vmin.x(),vmin.y(),vmin.z());
|
||||
pMax.set(vmax.x(),vmax.y(),vmax.z());
|
||||
|
||||
// Check correctness of the bounding box
|
||||
//
|
||||
if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
|
||||
{
|
||||
std::ostringstream message;
|
||||
message << "Bad bounding box (min >= max) for solid: "
|
||||
<< GetName() << " !"
|
||||
<< "\npMin = " << pMin
|
||||
<< "\npMax = " << pMax;
|
||||
G4Exception("G4UTet::BoundingLimits()", "GeomMgt0001",
|
||||
JustWarning, message);
|
||||
StreamInfo(G4cout);
|
||||
}
|
||||
pMin = fBmin;
|
||||
pMax = fBmax;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -181,7 +181,6 @@ G4VTwistedFaceted( const G4String& pname, // Name of instance
|
||||
"GeomSolids0002", FatalErrorInArgument, message);
|
||||
}
|
||||
CreateSurfaces();
|
||||
fCubicVolume = 2 * fDz * ( ( fDx1 + fDx2 ) * fDy1 + ( fDx3 + fDx4 ) * fDy2 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user