Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4UTessellatedSolid.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// Implementation of G4UTessellatedSolid wrapper class
27//
28// 11.01.18 G.Cosmo, CERN
29// --------------------------------------------------------------------
30
31#include "G4TessellatedSolid.hh"
33
34#if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
35
36#include "G4TriangularFacet.hh"
38
39#include "G4GeomTools.hh"
40#include "G4AffineTransform.hh"
41#include "G4BoundingEnvelope.hh"
42
43////////////////////////////////////////////////////////////////////////
44//
45// Constructors
46//
47G4UTessellatedSolid::G4UTessellatedSolid()
48 : Base_t("")
49{
50}
51
52G4UTessellatedSolid::G4UTessellatedSolid(const G4String& name)
53 : Base_t(name)
54{
55}
56
57////////////////////////////////////////////////////////////////////////
58//
59// Fake default constructor - sets only member data and allocates memory
60// for usage restricted to object persistency.
61//
62G4UTessellatedSolid::G4UTessellatedSolid(__void__& a)
63 : Base_t(a)
64{
65}
66
67//////////////////////////////////////////////////////////////////////////
68//
69// Destructor
70//
71G4UTessellatedSolid::~G4UTessellatedSolid()
72{
73 std::size_t size = fFacets.size();
74 for (std::size_t i = 0; i < size; ++i) { delete fFacets[i]; }
75 fFacets.clear();
76}
77
78//////////////////////////////////////////////////////////////////////////
79//
80// Copy constructor
81//
82G4UTessellatedSolid::G4UTessellatedSolid(const G4UTessellatedSolid& source)
83 : Base_t(source)
84{
85}
86
87//////////////////////////////////////////////////////////////////////////
88//
89// Assignment operator
90//
91G4UTessellatedSolid&
92G4UTessellatedSolid::operator=(const G4UTessellatedSolid& source)
93{
94 if (this == &source) return *this;
95
96 Base_t::operator=( source );
97
98 return *this;
99}
100
101//////////////////////////////////////////////////////////////////////////
102//
103// Accessors
104
105G4bool G4UTessellatedSolid::AddFacet(G4VFacet* aFacet)
106{
107 // Add a facet to the structure, checking validity.
108 //
109 if (GetSolidClosed())
110 {
111 G4Exception("G4UTessellatedSolid::AddFacet()", "GeomSolids1002",
112 JustWarning, "Attempt to add facets when solid is closed.");
113 return false;
114 }
115 if (!aFacet->IsDefined())
116 {
117 G4Exception("G4UTessellatedSolid::AddFacet()", "GeomSolids1002",
118 JustWarning, "Attempt to add facet not properly defined.");
119 aFacet->StreamInfo(G4cout);
120 return false;
121 }
122 if (aFacet->GetNumberOfVertices() == 3)
123 {
124 G4TriangularFacet* a3Facet = dynamic_cast<G4TriangularFacet*>(aFacet);
125 return Base_t::AddTriangularFacet(U3Vector(a3Facet->GetVertex(0).x(),
126 a3Facet->GetVertex(0).y(),
127 a3Facet->GetVertex(0).z()),
128 U3Vector(a3Facet->GetVertex(1).x(),
129 a3Facet->GetVertex(1).y(),
130 a3Facet->GetVertex(1).z()),
131 U3Vector(a3Facet->GetVertex(2).x(),
132 a3Facet->GetVertex(2).y(),
133 a3Facet->GetVertex(2).z()),
134 true);
135 }
136 else if (aFacet->GetNumberOfVertices() == 4)
137 {
138 G4QuadrangularFacet* a4Facet = dynamic_cast<G4QuadrangularFacet*>(aFacet);
139 return Base_t::AddQuadrilateralFacet(U3Vector(a4Facet->GetVertex(0).x(),
140 a4Facet->GetVertex(0).y(),
141 a4Facet->GetVertex(0).z()),
142 U3Vector(a4Facet->GetVertex(1).x(),
143 a4Facet->GetVertex(1).y(),
144 a4Facet->GetVertex(1).z()),
145 U3Vector(a4Facet->GetVertex(2).x(),
146 a4Facet->GetVertex(2).y(),
147 a4Facet->GetVertex(2).z()),
148 U3Vector(a4Facet->GetVertex(3).x(),
149 a4Facet->GetVertex(3).y(),
150 a4Facet->GetVertex(3).z()),
151 true);
152 }
153 else
154 {
155 G4Exception("G4UTessellatedSolid::AddFacet()", "GeomSolids1002",
156 JustWarning, "Attempt to add facet not properly defined.");
157 aFacet->StreamInfo(G4cout);
158 return false;
159 }
160}
161
162G4VFacet* G4UTessellatedSolid::GetFacet(G4int i) const
163{
164 return fFacets[i];
165}
166
167G4int G4UTessellatedSolid::GetNumberOfFacets() const
168{
169 return GetNFacets();
170}
171
172void G4UTessellatedSolid::SetSolidClosed(const G4bool t)
173{
174 if (t && !Base_t::IsClosed())
175 {
176 Base_t::Close();
177 std::size_t nVertices = fTessellated.fVertices.size();
178 std::size_t nFacets = fTessellated.fFacets.size();
179 for (std::size_t j = 0; j < nVertices; ++j)
180 {
181 U3Vector vt = fTessellated.fVertices[j];
182 fVertexList.push_back(G4ThreeVector(vt.x(), vt.y(), vt.z()));
183 }
184 for (std::size_t i = 0; i < nFacets; ++i)
185 {
186 vecgeom::TriangleFacet<G4double>* afacet = Base_t::GetFacet(i);
187 std::vector<G4ThreeVector> v;
188 for (G4int k=0; k<3; ++k)
189 {
190 v.push_back(G4ThreeVector(afacet->fVertices[k].x(),
191 afacet->fVertices[k].y(),
192 afacet->fVertices[k].z()));
193 }
194 G4VFacet* facet = new G4TriangularFacet(v[0], v[1], v[2],
196 facet->SetVertices(&fVertexList);
197 for (G4int k=0; k<3; ++k)
198 {
199 facet->SetVertexIndex(k, afacet->fIndices[k]);
200 }
201 fFacets.push_back(facet);
202 }
203 }
204}
205
206G4bool G4UTessellatedSolid::GetSolidClosed() const
207{
208 return Base_t::IsClosed();
209}
210
211void G4UTessellatedSolid::SetMaxVoxels(G4int)
212{
213 // Not yet implemented !
214}
215
216G4double G4UTessellatedSolid::GetMinXExtent() const
217{
218 U3Vector aMin, aMax;
219 Base_t::Extent(aMin, aMax);
220 return aMin.x();
221}
222G4double G4UTessellatedSolid::GetMaxXExtent() const
223{
224 U3Vector aMin, aMax;
225 Base_t::Extent(aMin, aMax);
226 return aMax.x();
227}
228G4double G4UTessellatedSolid::GetMinYExtent() const
229{
230 U3Vector aMin, aMax;
231 Base_t::Extent(aMin, aMax);
232 return aMin.y();
233}
234G4double G4UTessellatedSolid::GetMaxYExtent() const
235{
236 U3Vector aMin, aMax;
237 Base_t::Extent(aMin, aMax);
238 return aMax.y();
239}
240G4double G4UTessellatedSolid::GetMinZExtent() const
241{
242 U3Vector aMin, aMax;
243 Base_t::Extent(aMin, aMax);
244 return aMin.z();
245}
246G4double G4UTessellatedSolid::GetMaxZExtent() const
247{
248 U3Vector aMin, aMax;
249 Base_t::Extent(aMin, aMax);
250 return aMax.z();
251}
252
253G4int G4UTessellatedSolid::AllocatedMemoryWithoutVoxels()
254{
255 G4int base = sizeof(*this);
256 base += fVertexList.capacity() * sizeof(G4ThreeVector);
257
258 std::size_t limit = fFacets.size();
259 for (std::size_t i = 0; i < limit; ++i)
260 {
261 G4VFacet &facet = *fFacets[i];
262 base += facet.AllocatedMemory();
263 }
264 return base;
265}
266G4int G4UTessellatedSolid::AllocatedMemory()
267{
268 return AllocatedMemoryWithoutVoxels();
269}
270void G4UTessellatedSolid::DisplayAllocatedMemory()
271{
272 G4int without = AllocatedMemoryWithoutVoxels();
273 // G4int with = AllocatedMemory();
274 // G4double ratio = (G4double) with / without;
275 // G4cout << "G4TessellatedSolid - Allocated memory without voxel overhead "
276 // << without << "; with " << with << "; ratio: " << ratio << G4endl;
277 G4cout << "G4TessellatedSolid - Allocated memory without voxel overhead "
278 << without << G4endl;
279}
280
281
282///////////////////////////////////////////////////////////////////////////////
283//
284// Get bounding box
285
286void G4UTessellatedSolid::BoundingLimits(G4ThreeVector& pMin,
287 G4ThreeVector& pMax) const
288{
289 U3Vector aMin, aMax;
290 Base_t::Extent(aMin, aMax);
291 pMin = G4ThreeVector(aMin.x(), aMin.y(), aMin.z());
292 pMax = G4ThreeVector(aMax.x(), aMax.y(), aMax.z());
293
294 // Check correctness of the bounding box
295 //
296 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
297 {
298 std::ostringstream message;
299 message << "Bad bounding box (min >= max) for solid: "
300 << GetName() << " !"
301 << "\npMin = " << pMin
302 << "\npMax = " << pMax;
303 G4Exception("G4UTessellatedSolid::BoundingLimits()",
304 "GeomMgt0001", JustWarning, message);
305 StreamInfo(G4cout);
306 }
307}
308
309
310//////////////////////////////////////////////////////////////////////////////
311//
312// Calculate extent under transform and specified limit
313
314G4bool
315G4UTessellatedSolid::CalculateExtent(const EAxis pAxis,
316 const G4VoxelLimits& pVoxelLimit,
317 const G4AffineTransform& pTransform,
318 G4double& pMin, G4double& pMax) const
319{
320 G4ThreeVector bmin, bmax;
321
322 // Check bounding box (bbox)
323 //
324 BoundingLimits(bmin,bmax);
325 G4BoundingEnvelope bbox(bmin,bmax);
326
327 // Use simple bounding-box to help in the case of complex meshes
328 //
329 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
330
331#if 0
332 // Precise extent computation (disabled by default for this shape)
333 //
334 G4double kCarToleranceHalf = 0.5*kCarTolerance;
335 if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
336 {
337 return (pMin < pMax) ? true : false;
338 }
339
340 // The extent is calculated as cumulative extent of the pyramids
341 // formed by facets and the center of the bounding box.
342 //
343 G4double eminlim = pVoxelLimit.GetMinExtent(pAxis);
344 G4double emaxlim = pVoxelLimit.GetMaxExtent(pAxis);
345
347 G4ThreeVectorList apex(1);
348 std::vector<const G4ThreeVectorList *> pyramid(2);
349 pyramid[0] = &base;
350 pyramid[1] = &apex;
351 apex[0] = (bmin+bmax)*0.5;
352
353 // main loop along facets
354 pMin = kInfinity;
355 pMax = -kInfinity;
356 for (G4int i=0; i<GetNumberOfFacets(); ++i)
357 {
358 G4VFacet* facet = GetFacet(i);
359 if (std::abs((facet->GetSurfaceNormal()).dot(facet->GetVertex(0)-apex[0]))
360 < kCarToleranceHalf) continue;
361
362 base.resize(3);
363 for (G4int k=0; k<3; ++k) { base[k] = facet->GetVertex(k); }
364 G4double emin,emax;
365 G4BoundingEnvelope benv(pyramid);
366 if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax)) continue;
367 if (emin < pMin) pMin = emin;
368 if (emax > pMax) pMax = emax;
369 if (eminlim > pMin && emaxlim < pMax) break; // max possible extent
370 }
371 return (pMin < pMax);
372#endif
373}
374
375
376///////////////////////////////////////////////////////////////////////////////
377//
378// CreatePolyhedron()
379//
380G4Polyhedron* G4UTessellatedSolid::CreatePolyhedron () const
381{
382 G4int nVertices = (G4int)fVertexList.size();
383 G4int nFacets = (G4int)fFacets.size();
384 G4Polyhedron* polyhedron = new G4Polyhedron(nVertices, nFacets);
385 for (auto i = 0; i < nVertices; ++i)
386 {
387 polyhedron->SetVertex(i+1, fVertexList[i]);
388 }
389
390 for (auto i = 0; i < nFacets; ++i)
391 {
392 G4int v[3]; // Only facets with 3 vertices are defined in VecGeom
393 G4VFacet* facet = GetFacet(i);
394 for (auto j = 0; j < 3; ++j) // Retrieve indexing directly from VecGeom
395 {
396 v[j] = facet->GetVertexIndex(j) + 1;
397 }
398 polyhedron->SetFacet(i+1, v[0], v[1], v[2]);
399 }
400 polyhedron->SetReferences();
401
402 return polyhedron;
403}
404
405#endif // G4GEOM_USE_USOLIDS
const G4double kCarTolerance
std::vector< G4ThreeVector > G4ThreeVectorList
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
@ ABSOLUTE
Definition: G4VFacet.hh:48
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
double z() const
double x() const
double y() const
G4ThreeVector GetVertex(G4int i) const
G4ThreeVector GetVertex(G4int i) const
virtual void SetVertexIndex(G4int i, G4int j)=0
virtual G4int AllocatedMemory()=0
std::ostream & StreamInfo(std::ostream &os) const
Definition: G4VFacet.cc:96
virtual G4ThreeVector GetSurfaceNormal() const =0
virtual G4ThreeVector GetVertex(G4int i) const =0
virtual G4int GetNumberOfVertices() const =0
virtual G4int GetVertexIndex(G4int i) const =0
virtual void SetVertices(std::vector< G4ThreeVector > *vertices)=0
virtual G4bool IsDefined() const =0
G4double GetMinExtent(const EAxis pAxis) const
G4double GetMaxExtent(const EAxis pAxis) const
void SetVertex(G4int index, const G4Point3D &v)
void SetFacet(G4int index, G4int iv1, G4int iv2, G4int iv3, G4int iv4=0)
EAxis
Definition: geomdefs.hh:54
const char * name(G4int ptype)