Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/solids/specific/src/G4UTessellatedSolid.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 ////////////////////////////////////////////////////////////////////////
 44 //
 45 // Constructors
 46 //
 47 G4UTessellatedSolid::G4UTessellatedSolid()
 48  : Base_t("")
 49 {
 50 }
 51 
 52 G4UTessellatedSolid::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 //
 62 G4UTessellatedSolid::G4UTessellatedSolid(__void__& a)
 63   : Base_t(a)
 64 {
 65 }
 66 
 67 //////////////////////////////////////////////////////////////////////////
 68 //
 69 // Destructor
 70 //
 71 G4UTessellatedSolid::~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 //
 82 G4UTessellatedSolid::G4UTessellatedSolid(const G4UTessellatedSolid& source)
 83   : Base_t(source)
 84 {
 85 }
 86 
 87 //////////////////////////////////////////////////////////////////////////
 88 //
 89 // Assignment operator
 90 //
 91 G4UTessellatedSolid&
 92 G4UTessellatedSolid::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 
105 G4bool 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     auto 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     auto 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 
162 G4VFacet* G4UTessellatedSolid::GetFacet(G4int i) const
163 {
164   return fFacets[i];
165 }
166 
167 G4int G4UTessellatedSolid::GetNumberOfFacets() const
168 {
169   return GetNFacets();
170 }
171 
172 void 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.emplace_back(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 (const auto & vertex : afacet->fVertices)
189       {
190         v.emplace_back(vertex.x(),
191                                   vertex.y(),
192                                   vertex.z());
193       }
194       G4VFacet* facet = new G4TriangularFacet(v[0], v[1], v[2],
195                                               G4FacetVertexType::ABSOLUTE);
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 
206 G4bool G4UTessellatedSolid::GetSolidClosed() const
207 {
208   return Base_t::IsClosed();
209 }
210 
211 void G4UTessellatedSolid::SetMaxVoxels(G4int)
212 {
213   // Not yet implemented !
214 }
215 
216 G4double G4UTessellatedSolid::GetMinXExtent() const
217 {
218   U3Vector aMin, aMax;
219   Base_t::Extent(aMin, aMax);
220   return aMin.x();
221 }
222 G4double G4UTessellatedSolid::GetMaxXExtent() const
223 {
224   U3Vector aMin, aMax;
225   Base_t::Extent(aMin, aMax);
226   return aMax.x();
227 }
228 G4double G4UTessellatedSolid::GetMinYExtent() const
229 {
230   U3Vector aMin, aMax;
231   Base_t::Extent(aMin, aMax);
232   return aMin.y();
233 }
234 G4double G4UTessellatedSolid::GetMaxYExtent() const
235 {
236   U3Vector aMin, aMax;
237   Base_t::Extent(aMin, aMax);
238   return aMax.y();
239 }
240 G4double G4UTessellatedSolid::GetMinZExtent() const
241 {
242   U3Vector aMin, aMax;
243   Base_t::Extent(aMin, aMax);
244   return aMin.z();
245 }
246 G4double G4UTessellatedSolid::GetMaxZExtent() const
247 {
248   U3Vector aMin, aMax;
249   Base_t::Extent(aMin, aMax);
250   return aMax.z();
251 }
252 
253 G4int 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 }
266 G4int G4UTessellatedSolid::AllocatedMemory()
267 {
268   return AllocatedMemoryWithoutVoxels();
269 }
270 void 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 
286 void 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 
314 G4bool
315 G4UTessellatedSolid::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 
346   G4ThreeVectorList base;
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 //
380 G4Polyhedron* G4UTessellatedSolid::CreatePolyhedron () const
381 {
382   auto nVertices = (G4int)fVertexList.size();
383   auto nFacets = (G4int)fFacets.size();
384   auto 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
406