Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4ExtrudedSolid Class Reference

G4ExtrudedSolid is a is a solid which represents the extrusion of an arbitrary polygon with fixed outline in the defined Z sections. The z-sides of the solid are the scaled versions of the same polygon. The solid is implemented as a specification of a G4TessellatedSolid. More...

#include <G4ExtrudedSolid.hh>

Inheritance diagram for G4ExtrudedSolid:

Classes

struct  ZSection

Public Member Functions

 G4ExtrudedSolid (const G4String &pName, const std::vector< G4TwoVector > &polygon, const std::vector< ZSection > &zsections)
 G4ExtrudedSolid (const G4String &pName, const std::vector< G4TwoVector > &polygon, G4double halfZ, const G4TwoVector &off1=G4TwoVector(0., 0.), G4double scale1=1., const G4TwoVector &off2=G4TwoVector(0., 0.), G4double scale2=1.)
 ~G4ExtrudedSolid () override=default
G4int GetNofVertices () const
G4TwoVector GetVertex (G4int index) const
std::vector< G4TwoVectorGetPolygon () const
G4int GetNofZSections () const
ZSection GetZSection (G4int index) const
std::vector< ZSectionGetZSections () const
EInside Inside (const G4ThreeVector &p) const override
G4ThreeVector SurfaceNormal (const G4ThreeVector &p) const override
G4double DistanceToIn (const G4ThreeVector &p, const G4ThreeVector &v) const override
G4double DistanceToIn (const G4ThreeVector &p) const override
G4double DistanceToOut (const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const override
G4double DistanceToOut (const G4ThreeVector &p) const override
void BoundingLimits (G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4bool CalculateExtent (const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const override
G4GeometryType GetEntityType () const override
G4bool IsFaceted () const override
G4VSolidClone () const override
std::ostream & StreamInfo (std::ostream &os) const override
 G4ExtrudedSolid (__void__ &)
 G4ExtrudedSolid (const G4ExtrudedSolid &rhs)=default
G4ExtrudedSolidoperator= (const G4ExtrudedSolid &rhs)
Public Member Functions inherited from G4TessellatedSolid
 G4TessellatedSolid ()
 G4TessellatedSolid (const G4String &name)
 ~G4TessellatedSolid () override
 G4TessellatedSolid (__void__ &)
 G4TessellatedSolid (const G4TessellatedSolid &ts)
G4TessellatedSolidoperator= (const G4TessellatedSolid &right)
G4TessellatedSolidoperator+= (const G4TessellatedSolid &right)
G4bool AddFacet (G4VFacet *aFacet)
G4VFacetGetFacet (G4int i) const
G4int GetNumberOfFacets () const
G4int GetFacetIndex (const G4ThreeVector &p) const
G4double GetMinXExtent () const
G4double GetMaxXExtent () const
G4double GetMinYExtent () const
G4double GetMaxYExtent () const
G4double GetMinZExtent () const
G4double GetMaxZExtent () const
EInside Inside (const G4ThreeVector &p) const override
G4ThreeVector SurfaceNormal (const G4ThreeVector &p) const override
G4double DistanceToIn (const G4ThreeVector &p, const G4ThreeVector &v) const override
G4double DistanceToIn (const G4ThreeVector &p) const override
G4double DistanceToOut (const G4ThreeVector &p) const override
G4double DistanceToOut (const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm, G4bool *validNorm, G4ThreeVector *norm) const override
virtual G4bool Normal (const G4ThreeVector &p, G4ThreeVector &n) const
virtual G4double SafetyFromOutside (const G4ThreeVector &p, G4bool aAccurate=false) const
virtual G4double SafetyFromInside (const G4ThreeVector &p, G4bool aAccurate=false) const
G4GeometryType GetEntityType () const override
G4bool IsFaceted () const override
std::ostream & StreamInfo (std::ostream &os) const override
G4VSolidClone () const override
G4ThreeVector GetPointOnSurface () const override
G4double GetSurfaceArea () override
G4double GetCubicVolume () override
void SetSolidClosed (const G4bool t)
G4bool GetSolidClosed () const
G4int CheckStructure () const
void SetMaxVoxels (G4int max)
G4VoxelizerGetVoxels ()
G4bool CalculateExtent (const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const override
void BoundingLimits (G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4PolyhedronCreatePolyhedron () const override
G4PolyhedronGetPolyhedron () const override
void DescribeYourselfTo (G4VGraphicsScene &scene) const override
G4VisExtent GetExtent () const override
G4int AllocatedMemoryWithoutVoxels ()
G4int AllocatedMemory ()
void DisplayAllocatedMemory ()
Public Member Functions inherited from G4VSolid
 G4VSolid (const G4String &name)
virtual ~G4VSolid ()
 G4VSolid (const G4VSolid &rhs)
G4VSolidoperator= (const G4VSolid &rhs)
G4bool operator== (const G4VSolid &s) const
G4String GetName () const
void SetName (const G4String &name)
G4double GetTolerance () const
virtual void ComputeDimensions (G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
virtual G4int GetNumOfConstituents () const
void DumpInfo () const
virtual const G4VSolidGetConstituentSolid (G4int no) const
virtual G4VSolidGetConstituentSolid (G4int no)
virtual const G4DisplacedSolidGetDisplacedSolidPtr () const
virtual G4DisplacedSolidGetDisplacedSolidPtr ()
 G4VSolid (__void__ &)
G4double EstimateCubicVolume (G4int nStat, G4double epsilon) const
G4double EstimateSurfaceArea (G4int nStat, G4double epsilon) const

Additional Inherited Members

Protected Member Functions inherited from G4VSolid
void CalculateClippedPolygonExtent (G4ThreeVectorList &pPolygon, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
void ClipCrossSection (G4ThreeVectorList *pVertices, const G4int pSectionIndex, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
void ClipBetweenSections (G4ThreeVectorList *pVertices, const G4int pSectionIndex, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
void ClipPolygon (G4ThreeVectorList &pPolygon, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis) const
Protected Attributes inherited from G4TessellatedSolid
G4double kCarToleranceHalf
Protected Attributes inherited from G4VSolid
G4double kCarTolerance

Detailed Description

G4ExtrudedSolid is a is a solid which represents the extrusion of an arbitrary polygon with fixed outline in the defined Z sections. The z-sides of the solid are the scaled versions of the same polygon. The solid is implemented as a specification of a G4TessellatedSolid.

Definition at line 78 of file G4ExtrudedSolid.hh.

Constructor & Destructor Documentation

◆ G4ExtrudedSolid() [1/4]

G4ExtrudedSolid::G4ExtrudedSolid ( const G4String & pName,
const std::vector< G4TwoVector > & polygon,
const std::vector< ZSection > & zsections )

General constructor for an extruded polygon, through contour and polyline.

Parameters
[in]pNameThe solid name.
[in]polygonThe 2D polygonal contour, i.e. the vertices of the outlined polygon defined in clock-wise order.
[in]zsectionsThe 3D polyline with scale factors, i.e. the Z-sections defined by Z position in increasing order.

Definition at line 66 of file G4ExtrudedSolid.cc.

69 : G4TessellatedSolid(pName),
70 fNv(polygon.size()),
71 fNz(zsections.size()),
72 fGeometryType("G4ExtrudedSolid")
73{
74 // General constructor
75
76 // First check input parameters
77
78 if (fNv < 3)
79 {
80 std::ostringstream message;
81 message << "Number of vertices in polygon < 3 - " << pName;
82 G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids0002",
83 FatalErrorInArgument, message);
84 }
85
86 if (fNz < 2)
87 {
88 std::ostringstream message;
89 message << "Number of z-sides < 2 - " << pName;
90 G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids0002",
91 FatalErrorInArgument, message);
92 }
93
94 for ( std::size_t i=0; i<fNz-1; ++i )
95 {
96 if ( zsections[i].fZ > zsections[i+1].fZ )
97 {
98 std::ostringstream message;
99 message << "Z-sections have to be ordered by z value (z0 < z1 < z2...) - "
100 << pName;
101 G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids0002",
102 FatalErrorInArgument, message);
103 }
104 if ( std::fabs( zsections[i+1].fZ - zsections[i].fZ ) < kCarToleranceHalf )
105 {
106 std::ostringstream message;
107 message << "Z-sections with the same z position are not supported - "
108 << pName;
109 G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids0001",
110 FatalException, message);
111 }
112 }
113
114 // Copy polygon
115 //
116 fPolygon = polygon;
117
118 // Remove collinear and coincident vertices, if any
119 //
120 std::vector<G4int> removedVertices;
121 G4GeomTools::RemoveRedundantVertices(fPolygon,removedVertices,
122 2*kCarTolerance);
123 if (!removedVertices.empty())
124 {
125 std::size_t nremoved = removedVertices.size();
126 std::ostringstream message;
127 message << "The following "<< nremoved
128 << " vertices have been removed from polygon in " << pName
129 << "\nas collinear or coincident with other vertices: "
130 << removedVertices[0];
131 for (std::size_t i=1; i<nremoved; ++i)
132 {
133 message << ", " << removedVertices[i];
134 }
135 G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids1001",
136 JustWarning, message);
137 }
138
139 fNv = fPolygon.size();
140 if (fNv < 3)
141 {
142 std::ostringstream message;
143 message << "Number of vertices in polygon after removal < 3 - " << pName;
144 G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids0002",
145 FatalErrorInArgument, message);
146 }
147
148 // Check if polygon vertices are defined clockwise
149 // (the area is positive if polygon vertices are defined anti-clockwise)
150 //
151 if (G4GeomTools::PolygonArea(fPolygon) > 0.)
152 {
153 // Polygon vertices are defined anti-clockwise, we revert them
154 // G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids1001",
155 // JustWarning,
156 // "Polygon vertices defined anti-clockwise, reverting polygon");
157 std::reverse(fPolygon.begin(),fPolygon.end());
158 }
159
160 // Copy z-sections
161 //
162 fZSections = zsections;
163
164 G4bool result = MakeFacets();
165 if (!result)
166 {
167 std::ostringstream message;
168 message << "Making facets failed - " << pName;
169 G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids0003",
170 FatalException, message);
171 }
172 fIsConvex = G4GeomTools::IsConvex(fPolygon);
173
174 ComputeProjectionParameters();
175
176 // Check if the solid is a right prism, if so then set lateral planes
177 //
178 if ((fNz == 2)
179 && (fZSections[0].fScale == 1) && (fZSections[1].fScale == 1)
180 && (fZSections[0].fOffset == G4TwoVector(0,0))
181 && (fZSections[1].fOffset == G4TwoVector(0,0)))
182 {
183 fSolidType = (fIsConvex) ? 1 : 2; // 1 - convex, 2 - non-convex right prism
184 ComputeLateralPlanes();
185 }
186}
@ JustWarning
@ FatalException
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
CLHEP::Hep2Vector G4TwoVector
bool G4bool
Definition G4Types.hh:86
static void RemoveRedundantVertices(G4TwoVectorList &polygon, std::vector< G4int > &iout, G4double tolerance=0.0)
static G4double PolygonArea(const G4TwoVectorList &polygon)
static G4bool IsConvex(const G4TwoVectorList &polygon)
G4double kCarTolerance
Definition G4VSolid.hh:418

Referenced by Clone(), G4ExtrudedSolid(), and operator=().

◆ G4ExtrudedSolid() [2/4]

G4ExtrudedSolid::G4ExtrudedSolid ( const G4String & pName,
const std::vector< G4TwoVector > & polygon,
G4double halfZ,
const G4TwoVector & off1 = G4TwoVector(0.,0.),
G4double scale1 = 1.,
const G4TwoVector & off2 = G4TwoVector(0.,0.),
G4double scale2 = 1. )

Special constructor for an extruded polygon with 2 Z-sections.

Parameters
[in]pNameThe solid name.
[in]polygonThe 2D polygonal contour, i.e. the vertices of the outlined polygon defined in clock-wise order.
[in]halfZHalf length in Z, i.e. the distance from the origin to the sections.
[in]off1(X, Y) position of the first polygon in -halfZ.
[in]scale1Scale factor at -halfZ.
[in]off2(X, Y) position of the second polygon in +halfZ.
[in]scale2Scale factor at +halfZ.

Definition at line 190 of file G4ExtrudedSolid.cc.

195 : G4TessellatedSolid(pName),
196 fNv(polygon.size()),
197 fNz(2),
198 fGeometryType("G4ExtrudedSolid")
199{
200 // Special constructor for solid with 2 z-sections
201
202 // First check input parameters
203 //
204 if (fNv < 3)
205 {
206 std::ostringstream message;
207 message << "Number of vertices in polygon < 3 - " << pName;
208 G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids0002",
209 FatalErrorInArgument, message);
210 }
211
212 // Copy polygon
213 //
214 fPolygon = polygon;
215
216 // Remove collinear and coincident vertices, if any
217 //
218 std::vector<G4int> removedVertices;
219 G4GeomTools::RemoveRedundantVertices(fPolygon,removedVertices,
220 2*kCarTolerance);
221 if (!removedVertices.empty())
222 {
223 std::size_t nremoved = removedVertices.size();
224 std::ostringstream message;
225 message << "The following "<< nremoved
226 << " vertices have been removed from polygon in " << pName
227 << "\nas collinear or coincident with other vertices: "
228 << removedVertices[0];
229 for (std::size_t i=1; i<nremoved; ++i)
230 {
231 message << ", " << removedVertices[i];
232 }
233 G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids1001",
234 JustWarning, message);
235 }
236
237 fNv = fPolygon.size();
238 if (fNv < 3)
239 {
240 std::ostringstream message;
241 message << "Number of vertices in polygon after removal < 3 - " << pName;
242 G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids0002",
243 FatalErrorInArgument, message);
244 }
245
246 // Check if polygon vertices are defined clockwise
247 // (the area is positive if polygon vertices are defined anti-clockwise)
248 //
249 if (G4GeomTools::PolygonArea(fPolygon) > 0.)
250 {
251 // Polygon vertices are defined anti-clockwise, we revert them
252 // G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids1001",
253 // JustWarning,
254 // "Polygon vertices defined anti-clockwise, reverting polygon");
255 std::reverse(fPolygon.begin(),fPolygon.end());
256 }
257
258 // Copy z-sections
259 //
260 fZSections.emplace_back(-dz, off1, scale1);
261 fZSections.emplace_back( dz, off2, scale2);
262
263 G4bool result = MakeFacets();
264 if (!result)
265 {
266 std::ostringstream message;
267 message << "Making facets failed - " << pName;
268 G4Exception("G4ExtrudedSolid::G4ExtrudedSolid()", "GeomSolids0003",
269 FatalException, message);
270 }
271 fIsConvex = G4GeomTools::IsConvex(fPolygon);
272
273 ComputeProjectionParameters();
274
275 // Check if the solid is a right prism, if so then set lateral planes
276 //
277 if ((scale1 == 1) && (scale2 == 1)
278 && (off1 == G4TwoVector(0,0)) && (off2 == G4TwoVector(0,0)))
279 {
280 fSolidType = (fIsConvex) ? 1 : 2; // 1 - convex, 2 - non-convex right prism
281 ComputeLateralPlanes();
282 }
283}

◆ ~G4ExtrudedSolid()

G4ExtrudedSolid::~G4ExtrudedSolid ( )
overridedefault

Default Destructor.

◆ G4ExtrudedSolid() [3/4]

G4ExtrudedSolid::G4ExtrudedSolid ( __void__ & a)

Fake default constructor for usage restricted to direct object persistency for clients requiring preallocation of memory for persistifiable objects.

Definition at line 287 of file G4ExtrudedSolid.cc.

288 : G4TessellatedSolid(a), fGeometryType("G4ExtrudedSolid")
289{
290 // Fake default constructor - sets only member data and allocates memory
291 // for usage restricted to object persistency.
292}

◆ G4ExtrudedSolid() [4/4]

G4ExtrudedSolid::G4ExtrudedSolid ( const G4ExtrudedSolid & rhs)
default

Copy constructor and assignment operator.

Member Function Documentation

◆ BoundingLimits()

void G4ExtrudedSolid::BoundingLimits ( G4ThreeVector & pMin,
G4ThreeVector & pMax ) const
overridevirtual

Computes the bounding limits of the solid.

Parameters
[out]pMinThe minimum bounding limit point.
[out]pMaxThe maximum bounding limit point.

Reimplemented from G4VSolid.

Definition at line 1323 of file G4ExtrudedSolid.cc.

1325{
1326 G4double xmin0 = kInfinity, xmax0 = -kInfinity;
1327 G4double ymin0 = kInfinity, ymax0 = -kInfinity;
1328
1329 for (G4int i=0; i<GetNofVertices(); ++i)
1330 {
1331 G4double x = fPolygon[i].x();
1332 if (x < xmin0) { xmin0 = x; }
1333 if (x > xmax0) { xmax0 = x; }
1334 G4double y = fPolygon[i].y();
1335 if (y < ymin0) { ymin0 = y; }
1336 if (y > ymax0) { ymax0 = y; }
1337 }
1338
1339 G4double xmin = kInfinity, xmax = -kInfinity;
1340 G4double ymin = kInfinity, ymax = -kInfinity;
1341
1342 G4int nsect = GetNofZSections();
1343 for (G4int i=0; i<nsect; ++i)
1344 {
1345 ZSection zsect = GetZSection(i);
1346 G4double dx = zsect.fOffset.x();
1347 G4double dy = zsect.fOffset.y();
1348 G4double scale = zsect.fScale;
1349 xmin = std::min(xmin,xmin0*scale+dx);
1350 xmax = std::max(xmax,xmax0*scale+dx);
1351 ymin = std::min(ymin,ymin0*scale+dy);
1352 ymax = std::max(ymax,ymax0*scale+dy);
1353 }
1354
1355 G4double zmin = GetZSection(0).fZ;
1356 G4double zmax = GetZSection(nsect-1).fZ;
1357
1358 pMin.set(xmin,ymin,zmin);
1359 pMax.set(xmax,ymax,zmax);
1360
1361 // Check correctness of the bounding box
1362 //
1363 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
1364 {
1365 std::ostringstream message;
1366 message << "Bad bounding box (min >= max) for solid: "
1367 << GetName() << " !"
1368 << "\npMin = " << pMin
1369 << "\npMax = " << pMax;
1370 G4Exception("G4ExtrudedSolid::BoundingLimits()",
1371 "GeomMgt0001", JustWarning, message);
1372 DumpInfo();
1373 }
1374}
double G4double
Definition G4Types.hh:83
int G4int
Definition G4Types.hh:85
double z() const
double x() const
double y() const
void set(double x, double y, double z)
ZSection GetZSection(G4int index) const
G4int GetNofZSections() const
G4int GetNofVertices() const
G4String GetName() const
void DumpInfo() const

Referenced by CalculateExtent().

◆ CalculateExtent()

G4bool G4ExtrudedSolid::CalculateExtent ( const EAxis pAxis,
const G4VoxelLimits & pVoxelLimit,
const G4AffineTransform & pTransform,
G4double & pMin,
G4double & pMax ) const
overridevirtual

Calculates the minimum and maximum extent of the solid, when under the specified transform, and within the specified limits.

Parameters
[in]pAxisThe axis along which compute the extent.
[in]pVoxelLimitThe limiting space dictated by voxels.
[in]pTransformThe internal transformation applied to the solid.
[out]pMinThe minimum extent value.
[out]pMaxThe maximum extent value.
Returns
True if the solid is intersected by the extent region.

Implements G4VSolid.

Definition at line 1380 of file G4ExtrudedSolid.cc.

1384{
1385 G4ThreeVector bmin, bmax;
1386 G4bool exist;
1387
1388 // Check bounding box (bbox)
1389 //
1390 BoundingLimits(bmin,bmax);
1391 G4BoundingEnvelope bbox(bmin,bmax);
1392#ifdef G4BBOX_EXTENT
1393 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
1394#endif
1395 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
1396 {
1397 return exist = pMin < pMax;
1398 }
1399
1400 // To find the extent, the base polygon is subdivided in triangles.
1401 // The extent is calculated as cumulative extent of the parts
1402 // formed by extrusion of the triangles
1403 //
1404 G4TwoVectorList triangles;
1405 G4double eminlim = pVoxelLimit.GetMinExtent(pAxis);
1406 G4double emaxlim = pVoxelLimit.GetMaxExtent(pAxis);
1407
1408 // triangulate the base polygon
1409 if (!G4GeomTools::TriangulatePolygon(fPolygon,triangles))
1410 {
1411 std::ostringstream message;
1412 message << "Triangulation of the base polygon has failed for solid: "
1413 << GetName() << " !"
1414 << "\nExtent has been calculated using boundary box";
1415 G4Exception("G4ExtrudedSolid::CalculateExtent()",
1416 "GeomMgt1002",JustWarning,message);
1417 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
1418 }
1419
1420 // allocate vector lists
1421 G4int nsect = GetNofZSections();
1422 std::vector<const G4ThreeVectorList *> polygons;
1423 polygons.resize(nsect);
1424 for (G4int k=0; k<nsect; ++k)
1425 {
1426 polygons[k] = new G4ThreeVectorList(3);
1427 }
1428
1429 // main loop along triangles
1430 pMin = kInfinity;
1431 pMax = -kInfinity;
1432 G4int ntria = (G4int)triangles.size()/3;
1433 for (G4int i=0; i<ntria; ++i)
1434 {
1435 G4int i3 = i*3;
1436 for (G4int k=0; k<nsect; ++k) // extrude triangle
1437 {
1438 ZSection zsect = GetZSection(k);
1439 G4double z = zsect.fZ;
1440 G4double dx = zsect.fOffset.x();
1441 G4double dy = zsect.fOffset.y();
1442 G4double scale = zsect.fScale;
1443
1444 auto ptr = const_cast<G4ThreeVectorList*>(polygons[k]);
1445 auto iter = ptr->begin();
1446 G4double x0 = triangles[i3+0].x()*scale+dx;
1447 G4double y0 = triangles[i3+0].y()*scale+dy;
1448 iter->set(x0,y0,z);
1449 iter++;
1450 G4double x1 = triangles[i3+1].x()*scale+dx;
1451 G4double y1 = triangles[i3+1].y()*scale+dy;
1452 iter->set(x1,y1,z);
1453 iter++;
1454 G4double x2 = triangles[i3+2].x()*scale+dx;
1455 G4double y2 = triangles[i3+2].y()*scale+dy;
1456 iter->set(x2,y2,z);
1457 }
1458
1459 // set sub-envelope and adjust extent
1460 G4double emin,emax;
1461 G4BoundingEnvelope benv(polygons);
1462 if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax))
1463 {
1464 continue;
1465 }
1466 if (emin < pMin) { pMin = emin; }
1467 if (emax > pMax) { pMax = emax; }
1468 if (eminlim > pMin && emaxlim < pMax) { break; } // max possible extent
1469 }
1470 // free memory
1471 for (G4int k=0; k<nsect; ++k)
1472 {
1473 delete polygons[k];
1474 polygons[k]=nullptr;
1475 }
1476 return (pMin < pMax);
1477}
std::vector< G4ThreeVector > G4ThreeVectorList
std::vector< G4TwoVector > G4TwoVectorList
CLHEP::Hep3Vector G4ThreeVector
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
static G4bool TriangulatePolygon(const G4TwoVectorList &polygon, std::vector< G4int > &result)
G4double GetMinExtent(const EAxis pAxis) const
G4double GetMaxExtent(const EAxis pAxis) const

◆ Clone()

G4VSolid * G4ExtrudedSolid::Clone ( ) const
overridevirtual

Makes a clone of the object for use in multi-treading.

Returns
A pointer to the new cloned allocated solid.

Reimplemented from G4VSolid.

Definition at line 806 of file G4ExtrudedSolid.cc.

807{
808 return new G4ExtrudedSolid(*this);
809}
G4ExtrudedSolid(const G4String &pName, const std::vector< G4TwoVector > &polygon, const std::vector< ZSection > &zsections)

◆ DistanceToIn() [1/2]

G4double G4ExtrudedSolid::DistanceToIn ( const G4ThreeVector & p) const
overridevirtual

Calculates the distance to the nearest surface of a shape from an outside point. The distance can be an underestimate.

Parameters
[in]pThe point at offset p.
Returns
The safety distance to enter the shape.

Implements G4VSolid.

Definition at line 1173 of file G4ExtrudedSolid.cc.

1174{
1175 switch (fSolidType)
1176 {
1177 case 1: // convex right prism
1178 {
1179 G4double dist = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
1180 std::size_t np = fPlanes.size();
1181 for (std::size_t i=0; i<np; ++i)
1182 {
1183 G4double dd = fPlanes[i].a*p.x() + fPlanes[i].b*p.y() + fPlanes[i].d;
1184 if (dd > dist) { dist = dd; }
1185 }
1186 return (dist > 0) ? dist : 0.;
1187 }
1188 case 2: // non-convex right prism
1189 {
1190 G4bool in = PointInPolygon(p);
1191 if (in)
1192 {
1193 G4double distz= std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
1194 return (distz > 0) ? distz : 0;
1195 }
1196
1197 G4double distz= std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
1198 G4double dd = DistanceToPolygonSqr(p);
1199 if (distz > 0) { dd += distz*distz; }
1200 return std::sqrt(dd);
1201 }
1202 }
1203
1204 // General case: use tessellated solid
1206}
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override

◆ DistanceToIn() [2/2]

G4double G4ExtrudedSolid::DistanceToIn ( const G4ThreeVector & p,
const G4ThreeVector & v ) const
overridevirtual

Returns the distance along the normalised vector 'v' to the shape, from the point at offset 'p'. If there is no intersection, returns kInfinity. The first intersection resulting from 'leaving' a surface/volume is discarded. Hence, it is tolerant of points on the surface of the shape.

Parameters
[in]pThe point at offset p.
[in]vThe normalised direction vector.
Returns
The distance to enter the shape.

Implements G4VSolid.

Definition at line 1112 of file G4ExtrudedSolid.cc.

1114{
1115 G4double z0 = fZSections[0].fZ;
1116 G4double z1 = fZSections[fNz-1].fZ;
1117 if ((p.z() <= z0 + kCarToleranceHalf) && v.z() <= 0) { return kInfinity; }
1118 if ((p.z() >= z1 - kCarToleranceHalf) && v.z() >= 0) { return kInfinity; }
1119
1120 switch (fSolidType)
1121 {
1122 case 1: // convex right prism
1123 {
1124 // Intersection with Z planes
1125 //
1126 G4double dz = (z1 - z0)*0.5;
1127 G4double pz = p.z() - dz - z0;
1128
1129 G4double invz = (v.z() == 0) ? DBL_MAX : -1./v.z();
1130 G4double ddz = (invz < 0) ? dz : -dz;
1131 G4double tzmin = (pz + ddz)*invz;
1132 G4double tzmax = (pz - ddz)*invz;
1133
1134 // Intersection with lateral planes
1135 //
1136 std::size_t np = fPlanes.size();
1137 G4double txmin = tzmin, txmax = tzmax;
1138 for (std::size_t i=0; i<np; ++i)
1139 {
1140 G4double cosa = fPlanes[i].a*v.x()+fPlanes[i].b*v.y();
1141 G4double dist = fPlanes[i].a*p.x()+fPlanes[i].b*p.y()+fPlanes[i].d;
1142 if (dist >= -kCarToleranceHalf)
1143 {
1144 if (cosa >= 0) { return kInfinity; }
1145 G4double tmp = -dist/cosa;
1146 if (txmin < tmp) { txmin = tmp; }
1147 }
1148 else if (cosa > 0)
1149 {
1150 G4double tmp = -dist/cosa;
1151 if (txmax > tmp) { txmax = tmp; }
1152 }
1153 }
1154
1155 // Find distance
1156 //
1157 G4double tmin = txmin, tmax = txmax;
1158 if (tmax <= tmin + kCarToleranceHalf) // touch or no hit
1159 {
1160 return kInfinity;
1161 }
1162 return (tmin < kCarToleranceHalf) ? 0. : tmin;
1163 }
1164 case 2: // non-convex right prism
1165 {
1166 }
1167 }
1169}
#define DBL_MAX
Definition templates.hh:62

◆ DistanceToOut() [1/2]

G4double G4ExtrudedSolid::DistanceToOut ( const G4ThreeVector & p) const
overridevirtual

Calculates the distance to the nearest surface of a shape from an inside point 'p'. The distance can be an underestimate.

Parameters
[in]pThe point at offset p.
Returns
The safety distance to exit the shape.

Implements G4VSolid.

Definition at line 1292 of file G4ExtrudedSolid.cc.

1293{
1294 switch (fSolidType)
1295 {
1296 case 1: // convex right prism
1297 {
1298 G4double dist = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
1299 std::size_t np = fPlanes.size();
1300 for (std::size_t i=0; i<np; ++i)
1301 {
1302 G4double dd = fPlanes[i].a*p.x() + fPlanes[i].b*p.y() + fPlanes[i].d;
1303 if (dd > dist) { dist = dd; }
1304 }
1305 return (dist < 0) ? -dist : 0.;
1306 }
1307 case 2: // non-convex right prism
1308 {
1309 G4double distz = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
1310 G4bool in = PointInPolygon(p);
1311 if (distz >= 0 || (!in)) { return 0; } // point is outside
1312 return std::min(-distz,std::sqrt(DistanceToPolygonSqr(p)));
1313 }
1314 }
1315
1316 // General case: use tessellated solid
1318}
G4double DistanceToOut(const G4ThreeVector &p) const override

◆ DistanceToOut() [2/2]

G4double G4ExtrudedSolid::DistanceToOut ( const G4ThreeVector & p,
const G4ThreeVector & v,
const G4bool calcNorm = false,
G4bool * validNorm = nullptr,
G4ThreeVector * n = nullptr ) const
overridevirtual

Returns the distance along the normalised vector 'v' to the shape, from a point at an offset 'p' inside or on the surface of the shape. Intersections with surfaces, when the point is less than Tolerance/2 from a surface must be ignored.

Parameters
[in]pThe point at offset p.
[in]vThe normalised direction vector.
[in]calcNormFlag to indicate if to calculate the normal or not.
[out]validNormFlag set to true if the solid lies entirely behind or on the exiting surface. It is set false if the solid does not lie entirely behind or on the exiting surface. 'calcNorm' must be true, otherwise it is unused.
[out]nThe exiting outwards normal vector (undefined Magnitude). 'calcNorm' must be true, otherwise it is unused.
Returns
The distance to exit the shape.

Implements G4VSolid.

Definition at line 1210 of file G4ExtrudedSolid.cc.

1215{
1216 G4bool getnorm = calcNorm;
1217 if (getnorm) { *validNorm = true; }
1218
1219 G4double z0 = fZSections[0].fZ;
1220 G4double z1 = fZSections[fNz-1].fZ;
1221 if ((p.z() <= z0 + kCarToleranceHalf) && v.z() < 0)
1222 {
1223 if (getnorm) { n->set(0,0,-1); }
1224 return 0;
1225 }
1226 if ((p.z() >= z1 - kCarToleranceHalf) && v.z() > 0)
1227 {
1228 if (getnorm) { n->set(0,0,1); }
1229 return 0;
1230 }
1231
1232 switch (fSolidType)
1233 {
1234 case 1: // convex right prism
1235 {
1236 // Intersection with Z planes
1237 //
1238 G4double dz = (z1 - z0)*0.5;
1239 G4double pz = p.z() - 0.5 * (z0 + z1);
1240
1241 G4double vz = v.z();
1242 G4double tmax = (vz == 0) ? DBL_MAX : (std::copysign(dz,vz) - pz)/vz;
1243 G4int iside = (vz < 0) ? -4 : -2; // little trick: (-4+3)=-1, (-2+3)=+1
1244
1245 // Intersection with lateral planes
1246 //
1247 std::size_t np = fPlanes.size();
1248 for (std::size_t i=0; i<np; ++i)
1249 {
1250 G4double cosa = fPlanes[i].a*v.x()+fPlanes[i].b*v.y();
1251 if (cosa > 0)
1252 {
1253 G4double dist = fPlanes[i].a*p.x()+fPlanes[i].b*p.y()+fPlanes[i].d;
1254 if (dist >= -kCarToleranceHalf)
1255 {
1256 if (getnorm) { n->set(fPlanes[i].a, fPlanes[i].b, fPlanes[i].c); }
1257 return 0;
1258 }
1259 G4double tmp = -dist/cosa;
1260 if (tmax > tmp) { tmax = tmp; iside = (G4int)i; }
1261 }
1262 }
1263
1264 // Set normal, if required, and return distance
1265 //
1266 if (getnorm)
1267 {
1268 if (iside < 0)
1269 { n->set(0, 0, iside + 3); } // (-4+3)=-1, (-2+3)=+1
1270 else
1271 { n->set(fPlanes[iside].a, fPlanes[iside].b, fPlanes[iside].c); }
1272 }
1273 return tmax;
1274 }
1275 case 2: // non-convex right prism
1276 {
1277 }
1278 }
1279
1280 // Override the base class function to redefine validNorm
1281 // (the solid can be concave)
1282
1283 G4double distOut =
1284 G4TessellatedSolid::DistanceToOut(p, v, calcNorm, validNorm, n);
1285 if (validNorm != nullptr) { *validNorm = fIsConvex; }
1286
1287 return distOut;
1288}

◆ GetEntityType()

G4GeometryType G4ExtrudedSolid::GetEntityType ( ) const
overridevirtual

Returns the type ID, "G4ExtrudedSolid" of the solid.

Implements G4VSolid.

Definition at line 790 of file G4ExtrudedSolid.cc.

791{
792 // Return entity type
793
794 return fGeometryType;
795}

◆ GetNofVertices()

G4int G4ExtrudedSolid::GetNofVertices ( ) const
inline

Accessors.

Referenced by BoundingLimits(), and G4GDMLWriteSolids::XtruWrite().

◆ GetNofZSections()

G4int G4ExtrudedSolid::GetNofZSections ( ) const
inline

◆ GetPolygon()

std::vector< G4TwoVector > G4ExtrudedSolid::GetPolygon ( ) const
inline

◆ GetVertex()

G4TwoVector G4ExtrudedSolid::GetVertex ( G4int index) const
inline

◆ GetZSection()

ZSection G4ExtrudedSolid::GetZSection ( G4int index) const
inline

◆ GetZSections()

std::vector< ZSection > G4ExtrudedSolid::GetZSections ( ) const
inline

◆ Inside()

EInside G4ExtrudedSolid::Inside ( const G4ThreeVector & p) const
overridevirtual

Concrete implementations of the expected query interfaces for solids, as defined in the base class G4VSolid.

Implements G4VSolid.

Definition at line 813 of file G4ExtrudedSolid.cc.

814{
815 switch (fSolidType)
816 {
817 case 1: // convex right prism
818 {
819 G4double dist = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
820 if (dist > kCarToleranceHalf) { return kOutside; }
821
822 std::size_t np = fPlanes.size();
823 for (std::size_t i=0; i<np; ++i)
824 {
825 G4double dd = fPlanes[i].a*p.x() + fPlanes[i].b*p.y() + fPlanes[i].d;
826 if (dd > dist) { dist = dd; }
827 }
828 if (dist > kCarToleranceHalf) { return kOutside; }
829 return (dist > -kCarToleranceHalf) ? kSurface : kInside;
830 }
831 case 2: // non-convex right prism
832 {
833 G4double distz = std::max(fZSections[0].fZ-p.z(),p.z()-fZSections[1].fZ);
834 if (distz > kCarToleranceHalf) { return kOutside; }
835
836 G4bool in = PointInPolygon(p);
837 if (distz > -kCarToleranceHalf && in) { return kSurface; }
838
839 G4double dd = DistanceToPolygonSqr(p) - kCarToleranceHalf*kCarToleranceHalf;
840 if (in)
841 {
842 return (dd >= 0) ? kInside : kSurface;
843 }
844 return (dd > 0) ? kOutside : kSurface;
845 }
846 }
847
848 // Override the base class function as it fails in case of concave polygon.
849 // Project the point in the original polygon scale and check if it is inside
850 // for each triangle.
851
852 // Check first if outside extent
853 //
854 if ( p.x() < GetMinXExtent() - kCarToleranceHalf ||
860 {
861 // G4cout << "G4ExtrudedSolid::Outside extent: " << p << G4endl;
862 return kOutside;
863 }
864
865 // Project point p(z) to the polygon scale p0
866 //
867 G4TwoVector pscaled = ProjectPoint(p);
868
869 // Check if on surface of polygon
870 //
871 for ( G4int i=0; i<(G4int)fNv; ++i )
872 {
873 G4int j = (i+1) % fNv;
874 if ( IsSameLineSegment(pscaled, fPolygon[i], fPolygon[j]) )
875 {
876 // G4cout << "G4ExtrudedSolid::Inside return Surface (on polygon) "
877 // << G4endl;
878
879 return kSurface;
880 }
881 }
882
883 // Now check if inside triangles
884 //
885 auto it = fTriangles.cbegin();
886 G4bool inside = false;
887 do // Loop checking, 13.08.2015, G.Cosmo
888 {
889 if ( IsPointInside(fPolygon[(*it)[0]], fPolygon[(*it)[1]],
890 fPolygon[(*it)[2]], pscaled) ) { inside = true; }
891 ++it;
892 } while ( (!inside) && (it != fTriangles.cend()) );
893
894 if ( inside )
895 {
896 // Check if on surface of z sides
897 //
898 if ( std::fabs( p.z() - fZSections[0].fZ ) < kCarToleranceHalf ||
899 std::fabs( p.z() - fZSections[fNz-1].fZ ) < kCarToleranceHalf )
900 {
901 // G4cout << "G4ExtrudedSolid::Inside return Surface (on z side)"
902 // << G4endl;
903
904 return kSurface;
905 }
906
907 // G4cout << "G4ExtrudedSolid::Inside return Inside" << G4endl;
908
909 return kInside;
910 }
911
912 // G4cout << "G4ExtrudedSolid::Inside return Outside " << G4endl;
913
914 return kOutside;
915}
G4double GetMinYExtent() const
G4double GetMinZExtent() const
G4double GetMaxYExtent() const
G4double GetMaxZExtent() const
G4double GetMaxXExtent() const
G4double GetMinXExtent() const
@ kInside
Definition geomdefs.hh:70
@ kOutside
Definition geomdefs.hh:68
@ kSurface
Definition geomdefs.hh:69

◆ IsFaceted()

G4bool G4ExtrudedSolid::IsFaceted ( ) const
overridevirtual

Returns true as the solid has only planar faces.

Reimplemented from G4VSolid.

Definition at line 799 of file G4ExtrudedSolid.cc.

800{
801 return true;
802}

◆ operator=()

G4ExtrudedSolid & G4ExtrudedSolid::operator= ( const G4ExtrudedSolid & rhs)

Definition at line 296 of file G4ExtrudedSolid.cc.

297{
298 // Check assignment to self
299 //
300 if (this == &rhs) { return *this; }
301
302 // Copy base class data
303 //
305
306 // Copy data
307 //
308 fNv = rhs.fNv; fNz = rhs.fNz;
309 fPolygon = rhs.fPolygon; fZSections = rhs.fZSections;
310 fTriangles = rhs.fTriangles; fIsConvex = rhs.fIsConvex;
311 fGeometryType = rhs.fGeometryType;
312 fSolidType = rhs.fSolidType; fPlanes = rhs.fPlanes;
313 fLines = rhs.fLines; fLengths = rhs.fLengths;
314 fKScales = rhs.fKScales; fScale0s = rhs.fScale0s;
315 fKOffsets = rhs.fKOffsets; fOffset0s = rhs.fOffset0s;
316
317 return *this;
318}
G4TessellatedSolid & operator=(const G4TessellatedSolid &right)

◆ StreamInfo()

std::ostream & G4ExtrudedSolid::StreamInfo ( std::ostream & os) const
overridevirtual

Streams the object contents to an output stream.

Implements G4VSolid.

Definition at line 1481 of file G4ExtrudedSolid.cc.

1482{
1483 G4long oldprc = os.precision(16);
1484 os << "-----------------------------------------------------------\n"
1485 << " *** Dump for solid - " << GetName() << " ***\n"
1486 << " ===================================================\n"
1487 << " Solid geometry type: " << fGeometryType << G4endl;
1488
1489 if ( fIsConvex)
1490 { os << " Convex polygon; list of vertices:" << G4endl; }
1491 else
1492 { os << " Concave polygon; list of vertices:" << G4endl; }
1493
1494 for ( std::size_t i=0; i<fNv; ++i )
1495 {
1496 os << std::setw(5) << "#" << i
1497 << " vx = " << fPolygon[i].x()/mm << " mm"
1498 << " vy = " << fPolygon[i].y()/mm << " mm" << G4endl;
1499 }
1500
1501 os << " Sections:" << G4endl;
1502 for ( std::size_t iz=0; iz<fNz; ++iz )
1503 {
1504 os << " z = " << fZSections[iz].fZ/mm << " mm "
1505 << " x0= " << fZSections[iz].fOffset.x()/mm << " mm "
1506 << " y0= " << fZSections[iz].fOffset.y()/mm << " mm "
1507 << " scale= " << fZSections[iz].fScale << G4endl;
1508 }
1509
1510/*
1511 // Triangles (for debugging)
1512 os << G4endl;
1513 os << " Triangles:" << G4endl;
1514 os << " Triangle # vertex1 vertex2 vertex3" << G4endl;
1515
1516 G4int counter = 0;
1517 std::vector< std::vector<G4int> >::const_iterator it;
1518 for ( it = fTriangles.begin(); it != fTriangles.end(); it++ ) {
1519 std::vector<G4int> triangle = *it;
1520 os << std::setw(10) << counter++
1521 << std::setw(10) << triangle[0] << std::setw(10) << triangle[1]
1522 << std::setw(10) << triangle[2]
1523 << G4endl;
1524 }
1525*/
1526 os.precision(oldprc);
1527
1528 return os;
1529}
long G4long
Definition G4Types.hh:87
#define G4endl
Definition G4ios.hh:67

◆ SurfaceNormal()

G4ThreeVector G4ExtrudedSolid::SurfaceNormal ( const G4ThreeVector & p) const
overridevirtual

Returns the outwards pointing unit normal of the shape for the surface closest to the point at offset 'p'.

Parameters
[in]pThe point at offset p.
Returns
The outwards pointing unit normal.

Implements G4VSolid.

Definition at line 919 of file G4ExtrudedSolid.cc.

920{
921 G4int nsurf = 0;
922 G4double nx = 0., ny = 0., nz = 0.;
923 switch (fSolidType)
924 {
925 case 1: // convex right prism
926 {
927 if (std::abs(p.z() - fZSections[0].fZ) <= kCarToleranceHalf)
928 {
929 nz = -1; ++nsurf;
930 }
931 if (std::abs(p.z() - fZSections[1].fZ) <= kCarToleranceHalf)
932 {
933 nz = 1; ++nsurf;
934 }
935 for (std::size_t i=0; i<fNv; ++i)
936 {
937 G4double dd = fPlanes[i].a*p.x() + fPlanes[i].b*p.y() + fPlanes[i].d;
938 if (std::abs(dd) > kCarToleranceHalf) { continue; }
939 nx += fPlanes[i].a;
940 ny += fPlanes[i].b;
941 ++nsurf;
942 }
943 break;
944 }
945 case 2: // non-convex right prism
946 {
947 if (std::abs(p.z() - fZSections[0].fZ) <= kCarToleranceHalf)
948 {
949 nz = -1; ++nsurf;
950 }
951 if (std::abs(p.z() - fZSections[1].fZ) <= kCarToleranceHalf)
952 {
953 nz = 1; ++nsurf;
954 }
955
956 G4double sqrCarToleranceHalf = kCarToleranceHalf*kCarToleranceHalf;
957 for (std::size_t i=0, k=fNv-1; i<fNv; k=i++)
958 {
959 G4double ix = p.x() - fPolygon[i].x();
960 G4double iy = p.y() - fPolygon[i].y();
961 G4double u = fPlanes[i].a*iy - fPlanes[i].b*ix;
962 if (u < 0)
963 {
964 if (ix*ix + iy*iy > sqrCarToleranceHalf) { continue; }
965 }
966 else if (u > fLengths[i])
967 {
968 G4double kx = p.x() - fPolygon[k].x();
969 G4double ky = p.y() - fPolygon[k].y();
970 if (kx*kx + ky*ky > sqrCarToleranceHalf) { continue; }
971 }
972 else
973 {
974 G4double dd = fPlanes[i].a*p.x() + fPlanes[i].b*p.y() + fPlanes[i].d;
975 if (dd*dd > sqrCarToleranceHalf) { continue; }
976 }
977 nx += fPlanes[i].a;
978 ny += fPlanes[i].b;
979 ++nsurf;
980 }
981 break;
982 }
983 default:
984 {
986 }
987 }
988
989 // Return normal (right prism)
990 //
991 if (nsurf == 1)
992 {
993 return { nx,ny,nz };
994 }
995 if (nsurf != 0) // edge or corner
996 {
997 return G4ThreeVector(nx,ny,nz).unit();
998 }
999
1000 // Point is not on the surface, compute approximate normal
1001 //
1002#ifdef G4CSGDEBUG
1003 std::ostringstream message;
1004 G4long oldprc = message.precision(16);
1005 message << "Point p is not on surface (!?) of solid: "
1006 << GetName() << G4endl;
1007 message << "Position:\n";
1008 message << " p.x() = " << p.x()/mm << " mm\n";
1009 message << " p.y() = " << p.y()/mm << " mm\n";
1010 message << " p.z() = " << p.z()/mm << " mm";
1011 G4cout.precision(oldprc) ;
1012 G4Exception("G4TesselatedSolid::SurfaceNormal(p)", "GeomSolids1002",
1013 JustWarning, message );
1014 DumpInfo();
1015#endif
1016 return ApproxSurfaceNormal(p);
1017}
G4GLOB_DLL std::ostream G4cout
Hep3Vector unit() const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const override

The documentation for this class was generated from the following files: