Geant4  10.03.p01
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4BooleanSolid.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 //
27 // $Id: G4BooleanSolid.cc 97300 2016-06-01 09:27:19Z gcosmo $
28 //
29 // Implementation for the abstract base class for solids created by boolean
30 // operations between other solids
31 //
32 // History:
33 //
34 // 2016.03.16 E.Tcherniaev - added GetListOfPrimitives(),
35 // reimplemented GetPointOnSurface()
36 //
37 // 1998.09.10 V.Grichine - created
38 //
39 // --------------------------------------------------------------------
40 
41 #include "G4BooleanSolid.hh"
42 #include "G4VSolid.hh"
43 #include "G4DisplacedSolid.hh"
44 #include "G4ReflectedSolid.hh"
45 #include "G4ScaledSolid.hh"
46 #include "G4Polyhedron.hh"
47 #include "HepPolyhedronProcessor.h"
48 #include "Randomize.hh"
49 
50 #include "G4AutoLock.hh"
51 
52 namespace
53 {
54  G4Mutex polyhedronMutex = G4MUTEX_INITIALIZER;
55 }
56 
58 //
59 // Constructor
60 
62  G4VSolid* pSolidA ,
63  G4VSolid* pSolidB ) :
64  G4VSolid(pName), fStatistics(1000000), fCubVolEpsilon(0.001),
65  fAreaAccuracy(-1.), fCubicVolume(0.), fSurfaceArea(0.),
66  fRebuildPolyhedron(false), fpPolyhedron(0), fPrimitivesSurfaceArea(0.),
67  createdDisplacedSolid(false)
68 {
69  fPtrSolidA = pSolidA ;
70  fPtrSolidB = pSolidB ;
71 }
72 
74 //
75 // Constructor
76 
78  G4VSolid* pSolidA ,
79  G4VSolid* pSolidB ,
80  G4RotationMatrix* rotMatrix,
81  const G4ThreeVector& transVector ) :
82  G4VSolid(pName), fStatistics(1000000), fCubVolEpsilon(0.001),
83  fAreaAccuracy(-1.), fCubicVolume(0.), fSurfaceArea(0.),
84  fRebuildPolyhedron(false), fpPolyhedron(0), fPrimitivesSurfaceArea(0.),
85  createdDisplacedSolid(true)
86 {
87  fPtrSolidA = pSolidA ;
88  fPtrSolidB = new G4DisplacedSolid("placedB",pSolidB,rotMatrix,transVector) ;
89 }
90 
92 //
93 // Constructor
94 
96  G4VSolid* pSolidA ,
97  G4VSolid* pSolidB ,
98  const G4Transform3D& transform ) :
99  G4VSolid(pName), fStatistics(1000000), fCubVolEpsilon(0.001),
100  fAreaAccuracy(-1.), fCubicVolume(0.), fSurfaceArea(0.),
101  fRebuildPolyhedron(false), fpPolyhedron(0), fPrimitivesSurfaceArea(0.),
102  createdDisplacedSolid(true)
103 {
104  fPtrSolidA = pSolidA ;
105  fPtrSolidB = new G4DisplacedSolid("placedB",pSolidB,transform) ;
106 }
107 
109 //
110 // Fake default constructor - sets only member data and allocates memory
111 // for usage restricted to object persistency.
112 
114  : G4VSolid(a), fPtrSolidA(0), fPtrSolidB(0),
115  fStatistics(1000000), fCubVolEpsilon(0.001),
116  fAreaAccuracy(-1.), fCubicVolume(0.), fSurfaceArea(0.),
117  fRebuildPolyhedron(false), fpPolyhedron(0), fPrimitivesSurfaceArea(0.),
118  createdDisplacedSolid(false)
119 {
120 }
121 
123 //
124 // Destructor deletes transformation contents of the created displaced solid
125 
127 {
128  if(createdDisplacedSolid)
129  {
130  ((G4DisplacedSolid*)fPtrSolidB)->CleanTransformations();
131  }
132  delete fpPolyhedron; fpPolyhedron = 0;
133 }
134 
136 //
137 // Copy constructor
138 
140  : G4VSolid (rhs), fPtrSolidA(rhs.fPtrSolidA), fPtrSolidB(rhs.fPtrSolidB),
141  fStatistics(rhs.fStatistics), fCubVolEpsilon(rhs.fCubVolEpsilon),
142  fAreaAccuracy(rhs.fAreaAccuracy), fCubicVolume(rhs.fCubicVolume),
143  fSurfaceArea(rhs.fSurfaceArea), fRebuildPolyhedron(false), fpPolyhedron(0),
144  createdDisplacedSolid(rhs.createdDisplacedSolid)
145 {
146  fPrimitives.resize(0); fPrimitivesSurfaceArea = 0.;
147 }
148 
150 //
151 // Assignment operator
152 
154 {
155  // Check assignment to self
156  //
157  if (this == &rhs) { return *this; }
158 
159  // Copy base class data
160  //
161  G4VSolid::operator=(rhs);
162 
163  // Copy data
164  //
166  fStatistics= rhs.fStatistics; fCubVolEpsilon= rhs.fCubVolEpsilon;
167  fAreaAccuracy= rhs.fAreaAccuracy; fCubicVolume= rhs.fCubicVolume;
168  fSurfaceArea= rhs.fSurfaceArea;
169  createdDisplacedSolid= rhs.createdDisplacedSolid;
170  fRebuildPolyhedron = false;
171  delete fpPolyhedron; fpPolyhedron = 0;
172  fPrimitives.resize(0); fPrimitivesSurfaceArea = 0.;
173 
174  return *this;
175 }
176 
178 //
179 // If solid is made up from a Boolean operation of two solids,
180 // return the corresponding solid (for no=0 and 1)
181 // If the solid is not a "Boolean", return 0
182 
184 {
185  const G4VSolid* subSolid=0;
186  if( no == 0 )
187  subSolid = fPtrSolidA;
188  else if( no == 1 )
189  subSolid = fPtrSolidB;
190  else
191  {
192  DumpInfo();
193  G4Exception("G4BooleanSolid::GetConstituentSolid()",
194  "GeomSolids0002", FatalException, "Invalid solid index.");
195  }
196 
197  return subSolid;
198 }
199 
201 //
202 // If solid is made up from a Boolean operation of two solids,
203 // return the corresponding solid (for no=0 and 1)
204 // If the solid is not a "Boolean", return 0
205 
207 {
208  G4VSolid* subSolid=0;
209  if( no == 0 )
210  subSolid = fPtrSolidA;
211  else if( no == 1 )
212  subSolid = fPtrSolidB;
213  else
214  {
215  DumpInfo();
216  G4Exception("G4BooleanSolid::GetConstituentSolid()",
217  "GeomSolids0002", FatalException, "Invalid solid index.");
218  }
219 
220  return subSolid;
221 }
222 
224 //
225 // Returns entity type
226 
228 {
229  return G4String("G4BooleanSolid");
230 }
231 
233 //
234 // Stream object contents to an output stream
235 
236 std::ostream& G4BooleanSolid::StreamInfo(std::ostream& os) const
237 {
238  os << "-----------------------------------------------------------\n"
239  << " *** Dump for Boolean solid - " << GetName() << " ***\n"
240  << " ===================================================\n"
241  << " Solid type: " << GetEntityType() << "\n"
242  << " Parameters of constituent solids: \n"
243  << "===========================================================\n";
244  fPtrSolidA->StreamInfo(os);
245  fPtrSolidB->StreamInfo(os);
246  os << "===========================================================\n";
247 
248  return os;
249 }
250 
252 //
253 // Creates list of constituent primitives of and their placements
254 
256  std::vector<std::pair<G4VSolid *,G4Transform3D>>& primitives,
257  const G4Transform3D& curPlacement) const
258 {
259  G4Transform3D transform;
260  G4VSolid* solid;
261  G4String type;
262 
263  // Repeat two times, first time for fPtrSolidA and then for fPtrSolidB
264  //
265  for (G4int i=0; i<2; i++)
266  {
267  transform = curPlacement;
268  solid = (i == 0) ? fPtrSolidA : fPtrSolidB;
269  type = solid->GetEntityType();
270 
271  // While current solid is a trasformed solid just modify transform
272  //
273  while (type == "G4DisplacedSolid" ||
274  type == "G4ReflectedSolid" ||
275  type == "G4ScaledSolid")
276  {
277  if (type == "G4DisplacedSolid")
278  {
279  transform = transform * G4Transform3D(
280  ((G4DisplacedSolid*)solid)->GetObjectRotation(),
281  ((G4DisplacedSolid*)solid)->GetObjectTranslation());
282  solid = ((G4DisplacedSolid*)solid)->GetConstituentMovedSolid();
283  }
284  else if (type == "G4ReflectedSolid")
285  {
286  transform= transform*((G4ReflectedSolid*)solid)->GetDirectTransform3D();
287  solid = ((G4ReflectedSolid*)solid)->GetConstituentMovedSolid();
288  }
289  else if (type == "G4ScaledSolid")
290  {
291  transform = transform * ((G4ScaledSolid*)solid)->GetScaleTransform();
292  solid = ((G4ScaledSolid*)solid)->GetUnscaledSolid();
293  }
294  type = solid->GetEntityType();
295  }
296 
297  // If current solid is a Boolean solid then continue recursion,
298  // otherwise add it to the list of primitives
299  //
300  if (type == "G4UnionSolid" ||
301  type == "G4SubtractionSolid" ||
302  type == "G4IntersectionSolid" ||
303  type == "G4BooleanSolid")
304  {
305  ((G4BooleanSolid *)solid)->GetListOfPrimitives(primitives,transform);
306  }
307  else
308  {
309  primitives.push_back(std::pair<G4VSolid*,G4Transform3D>(solid,transform));
310  }
311  }
312 }
313 
315 //
316 // Returns a point (G4ThreeVector) randomly and uniformly selected
317 // on the surface of the solid
318 
320 {
321  G4int nprims = fPrimitives.size();
322  std::pair<G4VSolid *, G4Transform3D> prim;
323 
324  // Get list of primitives and find the total area of their surfaces
325  //
326  if (nprims == 0)
327  {
328  GetListOfPrimitives(fPrimitives, G4Transform3D());
329  nprims = fPrimitives.size();
330  fPrimitivesSurfaceArea = 0.;
331  for (G4int i=0; i<nprims; i++)
332  {
333  fPrimitivesSurfaceArea += fPrimitives[i].first->GetSurfaceArea();
334  }
335  }
336 
337  // Select random primitive, get random point on its surface and
338  // check that the point belongs to the surface of the solid
339  //
341  for (G4int k=0; k<1000000; k++) // try 1000000 times
342  {
343  G4double rand = fPrimitivesSurfaceArea * G4UniformRand();
344  G4double area = 0.;
345  for (G4int i=0; i<nprims; i++)
346  {
347  prim = fPrimitives[i];
348  area += prim.first->GetSurfaceArea();
349  if (rand < area) break;
350  }
351  p = prim.first->GetPointOnSurface();
352  p = prim.second * G4Point3D(p);
353  if (Inside(p) == kSurface) return p;
354  }
355  std::ostringstream message;
356  message << "Solid - " << GetName() << "\n"
357  << "All attempts to generate a point on the surface have failed.\n"
358  << "Returning point from the last unsuccessful attempt!";
359  G4Exception("G4BooleanSolid::GetPointOnSurface()",
360  "GeomSolids1001", JustWarning, message);
361  return p;
362 }
363 
365 //
366 // Returns polyhedron for visualization
367 
369 {
370  if (!fpPolyhedron ||
371  fRebuildPolyhedron ||
373  fpPolyhedron->GetNumberOfRotationSteps())
374  {
375  G4AutoLock l(&polyhedronMutex);
376  delete fpPolyhedron;
377  fpPolyhedron = CreatePolyhedron();
378  fRebuildPolyhedron = false;
379  l.unlock();
380  }
381  return fpPolyhedron;
382 }
383 
385 //
386 // Stacks polyhedra for processing. Returns top polyhedron.
387 
390  const G4VSolid* solid) const
391 {
393  const G4String& type = solid->GetEntityType();
394  if (type == "G4UnionSolid")
395  { operation = HepPolyhedronProcessor::UNION; }
396  else if (type == "G4IntersectionSolid")
397  { operation = HepPolyhedronProcessor::INTERSECTION; }
398  else if (type == "G4SubtractionSolid")
399  { operation = HepPolyhedronProcessor::SUBTRACTION; }
400  else
401  {
402  std::ostringstream message;
403  message << "Solid - " << solid->GetName()
404  << " - Unrecognised composite solid" << G4endl
405  << " Returning NULL !";
406  G4Exception("StackPolyhedron()", "GeomSolids1001", JustWarning, message);
407  return 0;
408  }
409 
410  G4Polyhedron* top = 0;
411  const G4VSolid* solidA = solid->GetConstituentSolid(0);
412  const G4VSolid* solidB = solid->GetConstituentSolid(1);
413 
414  if (solidA->GetConstituentSolid(0))
415  {
416  top = StackPolyhedron(processor, solidA);
417  }
418  else
419  {
420  top = solidA->GetPolyhedron();
421  }
422  G4Polyhedron* operand = solidB->GetPolyhedron();
423  processor.push_back (operation, *operand);
424 
425  return top;
426 }
virtual G4Polyhedron * GetPolyhedron() const
Definition: G4VSolid.cc:665
G4String GetName() const
G4VSolid * fPtrSolidB
virtual G4Polyhedron * GetPolyhedron() const
G4BooleanSolid(const G4String &pName, G4VSolid *pSolidA, G4VSolid *pSolidB)
virtual G4GeometryType GetEntityType() const
const char * p
Definition: xmltok.h:285
HepGeom::Point3D< G4double > G4Point3D
Definition: G4Point3D.hh:35
virtual G4GeometryType GetEntityType() const =0
int G4int
Definition: G4Types.hh:78
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:175
void DumpInfo() const
static int operand(pchar begin, pchar end, double &result, pchar &endp, const dic_type &dictionary)
Definition: Evaluator.cc:162
void push_back(Operation, const HepPolyhedron &)
virtual std::ostream & StreamInfo(std::ostream &os) const =0
#define G4UniformRand()
Definition: Randomize.hh:97
virtual EInside Inside(const G4ThreeVector &p) const =0
void GetListOfPrimitives(std::vector< std::pair< G4VSolid *, G4Transform3D >> &, const G4Transform3D &) const
std::ostream & StreamInfo(std::ostream &os) const
HepGeom::Transform3D G4Transform3D
virtual G4Polyhedron * CreatePolyhedron() const
Definition: G4VSolid.cc:660
virtual ~G4BooleanSolid()
virtual const G4VSolid * GetConstituentSolid(G4int no) const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
#define processor
Definition: xmlparse.cc:617
G4int G4Mutex
Definition: G4Threading.hh:173
static G4int GetNumberOfRotationSteps()
virtual const G4VSolid * GetConstituentSolid(G4int no) const
Definition: G4VSolid.cc:168
G4VSolid * fPtrSolidA
G4ThreeVector GetPointOnSurface() const
#define G4endl
Definition: G4ios.hh:61
G4VSolid & operator=(const G4VSolid &rhs)
Definition: G4VSolid.cc:111
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
G4BooleanSolid & operator=(const G4BooleanSolid &rhs)
double G4double
Definition: G4Types.hh:76
G4Polyhedron * StackPolyhedron(HepPolyhedronProcessor &, const G4VSolid *) const