ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4UTessellatedSolid.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4UTessellatedSolid.cc
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"
32 #include "G4UTessellatedSolid.hh"
33 
34 #if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
35 
36 #include "G4TriangularFacet.hh"
37 #include "G4QuadrangularFacet.hh"
38 
39 #include "G4GeomTools.hh"
40 #include "G4AffineTransform.hh"
41 #include "G4BoundingEnvelope.hh"
42 
43 #include "G4PolyhedronArbitrary.hh"
44 
46 //
47 // Constructors
48 //
49 G4UTessellatedSolid::G4UTessellatedSolid()
50  : Base_t("")
51 {
52 }
53 
54 G4UTessellatedSolid::G4UTessellatedSolid(const G4String& name)
55  : Base_t(name)
56 {
57 }
58 
60 //
61 // Fake default constructor - sets only member data and allocates memory
62 // for usage restricted to object persistency.
63 //
64 G4UTessellatedSolid::G4UTessellatedSolid(__void__& a)
65  : Base_t(a)
66 {
67 }
68 
70 //
71 // Destructor
72 //
73 G4UTessellatedSolid::~G4UTessellatedSolid()
74 {
75  G4int size = fFacets.size();
76  for (G4int i = 0; i < size; ++i) { delete fFacets[i]; }
77  fFacets.clear();
78 }
79 
81 //
82 // Copy constructor
83 //
84 G4UTessellatedSolid::G4UTessellatedSolid(const G4UTessellatedSolid& source)
85  : Base_t(source)
86 {
87 }
88 
90 //
91 // Assignment operator
92 //
93 G4UTessellatedSolid&
94 G4UTessellatedSolid::operator=(const G4UTessellatedSolid& source)
95 {
96  if (this == &source) return *this;
97 
98  Base_t::operator=( source );
99 
100  return *this;
101 }
102 
104 //
105 // Accessors
106 
107 G4bool G4UTessellatedSolid::AddFacet(G4VFacet* aFacet)
108 {
109  // Add a facet to the structure, checking validity.
110  //
111  if (GetSolidClosed())
112  {
113  G4Exception("G4UTessellatedSolid::AddFacet()", "GeomSolids1002",
114  JustWarning, "Attempt to add facets when solid is closed.");
115  return false;
116  }
117  if (!aFacet->IsDefined())
118  {
119  G4Exception("G4UTessellatedSolid::AddFacet()", "GeomSolids1002",
120  JustWarning, "Attempt to add facet not properly defined.");
121  aFacet->StreamInfo(G4cout);
122  return false;
123  }
124  if (aFacet->GetNumberOfVertices() == 3)
125  {
126  G4TriangularFacet* a3Facet = dynamic_cast<G4TriangularFacet*>(aFacet);
127  return Base_t::AddTriangularFacet(U3Vector(a3Facet->GetVertex(0).x(),
128  a3Facet->GetVertex(0).y(),
129  a3Facet->GetVertex(0).z()),
130  U3Vector(a3Facet->GetVertex(1).x(),
131  a3Facet->GetVertex(1).y(),
132  a3Facet->GetVertex(1).z()),
133  U3Vector(a3Facet->GetVertex(2).x(),
134  a3Facet->GetVertex(2).y(),
135  a3Facet->GetVertex(2).z()),
136  true);
137  }
138  else if (aFacet->GetNumberOfVertices() == 4)
139  {
140  G4QuadrangularFacet* a4Facet = dynamic_cast<G4QuadrangularFacet*>(aFacet);
141  return Base_t::AddQuadrilateralFacet(U3Vector(a4Facet->GetVertex(0).x(),
142  a4Facet->GetVertex(0).y(),
143  a4Facet->GetVertex(0).z()),
144  U3Vector(a4Facet->GetVertex(1).x(),
145  a4Facet->GetVertex(1).y(),
146  a4Facet->GetVertex(1).z()),
147  U3Vector(a4Facet->GetVertex(2).x(),
148  a4Facet->GetVertex(2).y(),
149  a4Facet->GetVertex(2).z()),
150  U3Vector(a4Facet->GetVertex(3).x(),
151  a4Facet->GetVertex(3).y(),
152  a4Facet->GetVertex(3).z()),
153  true);
154  }
155  else
156  {
157  G4Exception("G4UTessellatedSolid::AddFacet()", "GeomSolids1002",
158  JustWarning, "Attempt to add facet not properly defined.");
159  aFacet->StreamInfo(G4cout);
160  return false;
161  }
162 }
163 
164 G4VFacet* G4UTessellatedSolid::GetFacet(G4int i) const
165 {
166  return fFacets[i];
167 }
168 
169 G4int G4UTessellatedSolid::GetNumberOfFacets() const
170 {
171  return GetNFacets();
172 }
173 
174 void G4UTessellatedSolid::SetSolidClosed(const G4bool t)
175 {
176  if (t && !Base_t::IsClosed())
177  {
178  Base_t::Close();
179  G4int nVertices = fTessellated.fVertices.size();
180  G4int nFacets = fTessellated.fFacets.size();
181  for (G4int j = 0; j < nVertices; ++j)
182  {
183  U3Vector vt = fTessellated.fVertices[j];
184  fVertexList.push_back(G4ThreeVector(vt.x(), vt.y(), vt.z()));
185  }
186  for (G4int i = 0; i < nFacets; ++i)
187  {
188  vecgeom::TriangleFacet<G4double>* afacet = Base_t::GetFacet(i);
189  std::vector<G4ThreeVector> v;
190  for (G4int k=0; k<3; ++k)
191  {
192  v.push_back(G4ThreeVector(afacet->fVertices[k].x(),
193  afacet->fVertices[k].y(),
194  afacet->fVertices[k].z()));
195  }
196  G4VFacet* facet = new G4TriangularFacet(v[0], v[1], v[2],
198  facet->SetVertices(&fVertexList);
199  for (G4int k=0; k<3; ++k)
200  {
201  facet->SetVertexIndex(k, afacet->fIndices[k]);
202  }
203  fFacets.push_back(facet);
204  }
205  }
206 }
207 
208 G4bool G4UTessellatedSolid::GetSolidClosed() const
209 {
210  return Base_t::IsClosed();
211 }
212 
213 void G4UTessellatedSolid::SetMaxVoxels(G4int)
214 {
215  // Not yet implemented !
216 }
217 
218 G4double G4UTessellatedSolid::GetMinXExtent() const
219 {
220  U3Vector aMin, aMax;
221  Base_t::Extent(aMin, aMax);
222  return aMin.x();
223 }
224 G4double G4UTessellatedSolid::GetMaxXExtent() const
225 {
226  U3Vector aMin, aMax;
227  Base_t::Extent(aMin, aMax);
228  return aMax.x();
229 }
230 G4double G4UTessellatedSolid::GetMinYExtent() const
231 {
232  U3Vector aMin, aMax;
233  Base_t::Extent(aMin, aMax);
234  return aMin.y();
235 }
236 G4double G4UTessellatedSolid::GetMaxYExtent() const
237 {
238  U3Vector aMin, aMax;
239  Base_t::Extent(aMin, aMax);
240  return aMax.y();
241 }
242 G4double G4UTessellatedSolid::GetMinZExtent() const
243 {
244  U3Vector aMin, aMax;
245  Base_t::Extent(aMin, aMax);
246  return aMin.z();
247 }
248 G4double G4UTessellatedSolid::GetMaxZExtent() const
249 {
250  U3Vector aMin, aMax;
251  Base_t::Extent(aMin, aMax);
252  return aMax.z();
253 }
254 
255 G4int G4UTessellatedSolid::AllocatedMemoryWithoutVoxels()
256 {
257  G4int base = sizeof(*this);
258  base += fVertexList.capacity() * sizeof(G4ThreeVector);
259 
260  G4int limit = fFacets.size();
261  for (G4int i = 0; i < limit; ++i)
262  {
263  G4VFacet &facet = *fFacets[i];
264  base += facet.AllocatedMemory();
265  }
266  return base;
267 }
268 G4int G4UTessellatedSolid::AllocatedMemory()
269 {
270  return AllocatedMemoryWithoutVoxels();
271 }
272 void G4UTessellatedSolid::DisplayAllocatedMemory()
273 {
274  G4int without = AllocatedMemoryWithoutVoxels();
275  // G4int with = AllocatedMemory();
276  // G4double ratio = (G4double) with / without;
277  // G4cout << "G4TessellatedSolid - Allocated memory without voxel overhead "
278  // << without << "; with " << with << "; ratio: " << ratio << G4endl;
279  G4cout << "G4TessellatedSolid - Allocated memory without voxel overhead "
280  << without << G4endl;
281 }
282 
283 
285 //
286 // Get bounding box
287 
288 void G4UTessellatedSolid::BoundingLimits(G4ThreeVector& pMin,
289  G4ThreeVector& pMax) const
290 {
291  U3Vector aMin, aMax;
292  Base_t::Extent(aMin, aMax);
293  pMin = G4ThreeVector(aMin.x(), aMin.y(), aMin.z());
294  pMax = G4ThreeVector(aMax.x(), aMax.y(), aMax.z());
295 
296  // Check correctness of the bounding box
297  //
298  if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
299  {
300  std::ostringstream message;
301  message << "Bad bounding box (min >= max) for solid: "
302  << GetName() << " !"
303  << "\npMin = " << pMin
304  << "\npMax = " << pMax;
305  G4Exception("G4UTessellatedSolid::BoundingLimits()",
306  "GeomMgt0001", JustWarning, message);
307  StreamInfo(G4cout);
308  }
309 }
310 
311 
313 //
314 // Calculate extent under transform and specified limit
315 
316 G4bool
317 G4UTessellatedSolid::CalculateExtent(const EAxis pAxis,
318  const G4VoxelLimits& pVoxelLimit,
319  const G4AffineTransform& pTransform,
320  G4double& pMin, G4double& pMax) const
321 {
322  G4ThreeVector bmin, bmax;
323 
324  // Check bounding box (bbox)
325  //
326  BoundingLimits(bmin,bmax);
327  G4BoundingEnvelope bbox(bmin,bmax);
328 
329  // Use simple bounding-box to help in the case of complex meshes
330  //
331  return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
332 
333 #if 0
334  // Precise extent computation (disabled by default for this shape)
335  //
336  G4double kCarToleranceHalf = 0.5*kCarTolerance;
337  if (bbox.BoundingBoxVsVoxelLimits(pAxis,pVoxelLimit,pTransform,pMin,pMax))
338  {
339  return (pMin < pMax) ? true : false;
340  }
341 
342  // The extent is calculated as cumulative extent of the pyramids
343  // formed by facets and the center of the bounding box.
344  //
345  G4double eminlim = pVoxelLimit.GetMinExtent(pAxis);
346  G4double emaxlim = pVoxelLimit.GetMaxExtent(pAxis);
347 
349  G4ThreeVectorList apex(1);
350  std::vector<const G4ThreeVectorList *> pyramid(2);
351  pyramid[0] = &base;
352  pyramid[1] = &apex;
353  apex[0] = (bmin+bmax)*0.5;
354 
355  // main loop along facets
356  pMin = kInfinity;
357  pMax = -kInfinity;
358  for (G4int i=0; i<GetNumberOfFacets(); ++i)
359  {
360  G4VFacet* facet = GetFacet(i);
361  if (std::abs((facet->GetSurfaceNormal()).dot(facet->GetVertex(0)-apex[0]))
362  < kCarToleranceHalf) continue;
363 
364  base.resize(3);
365  for (G4int k=0; k<3; ++k) { base[k] = facet->GetVertex(k); }
367  G4BoundingEnvelope benv(pyramid);
368  if (!benv.CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax)) continue;
369  if (emin < pMin) pMin = emin;
370  if (emax > pMax) pMax = emax;
371  if (eminlim > pMin && emaxlim < pMax) break; // max possible extent
372  }
373  return (pMin < pMax);
374 #endif
375 }
376 
377 
379 //
380 // CreatePolyhedron()
381 //
382 G4Polyhedron* G4UTessellatedSolid::CreatePolyhedron () const
383 {
384  G4int nVertices = fVertexList.size();
385  G4int nFacets = fFacets.size();
386  G4PolyhedronArbitrary *polyhedron = new G4PolyhedronArbitrary (nVertices,
387  nFacets);
388  for (G4int j = 0; j < nVertices; ++j)
389  {
390  polyhedron->AddVertex(fVertexList[j]);
391  }
392 
393  for (G4int i = 0; i < nFacets; ++i)
394  {
395  G4int v[3]; // Only facets with 3 vertices are defined in VecGeom
396  G4VFacet* facet = GetFacet(i);
397  for (G4int j=0; j<3; ++j) // Retrieve indexing directly from VecGeom
398  {
399  v[j] = facet->GetVertexIndex(j) + 1;
400  }
401  polyhedron->AddFacet(v[0],v[1],v[2]);
402  }
403  polyhedron->SetReferences();
404 
405  return (G4Polyhedron*) polyhedron;
406 }
407 
408 #endif // G4GEOM_USE_USOLIDS