Geant4  10.02.p02
G4USolid.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:$
28 // GEANT4 tag $Name:$
29 //
30 //
31 // G4USolid implementation
32 //
33 // --------------------------------------------------------------------
34 
35 #include "G4USolid.hh"
36 
37 #if ( defined(G4GEOM_USE_USOLIDS) || defined(G4GEOM_USE_PARTIAL_USOLIDS) )
38 
39 #include "G4AffineTransform.hh"
40 #include "G4VoxelLimits.hh"
41 #include "G4VGraphicsScene.hh"
42 #include "G4Polyhedron.hh"
43 #include "G4VisExtent.hh"
44 #include "G4PhysicalConstants.hh"
45 #include "G4GeometryTolerance.hh"
46 
47 #include "G4AutoLock.hh"
48 
49 namespace
50 {
51  G4Mutex polyhedronMutex = G4MUTEX_INITIALIZER;
52 }
53 
54 G4USolid::G4USolid(const G4String& name, VUSolid* s) :
55  G4VSolid(name), fShape(s), fRebuildPolyhedron(false), fPolyhedron(0)
56 {
57 }
58 
59 G4USolid::G4USolid(__void__& a)
60  : G4VSolid(a), fShape(0), fRebuildPolyhedron(false), fPolyhedron(0)
61 {
62 }
63 
64 G4USolid::~G4USolid()
65 {
66  delete fPolyhedron; fPolyhedron = 0;
67 }
68 
69 G4bool G4USolid::operator==(const G4USolid& s) const
70 {
71  return (this == &s) ? true : false;
72 }
73 
74 EInside G4USolid::Inside(const G4ThreeVector& p) const
75 {
76  UVector3 pt;
77  VUSolid::EnumInside in_temp;
78  EInside in = kOutside;
79  pt.x() = p.x();
80  pt.y() = p.y();
81  pt.z() = p.z(); // better assign at construction
82 
83  in_temp = fShape->Inside(pt);
84 
85  if (in_temp == VUSolid::EnumInside::eSurface) return kSurface;
86  if (in_temp == VUSolid::EnumInside::eInside) return kInside;
87 
88  return in;
89 }
90 
91 G4ThreeVector G4USolid::SurfaceNormal(const G4ThreeVector& pt) const
92 {
93  UVector3 p;
94  p.x() = pt.x();
95  p.y() = pt.y();
96  p.z() = pt.z();
97  UVector3 n;
98  fShape->Normal(p, n);
99  return G4ThreeVector(n.x(), n.y(), n.z());
100 }
101 
102 G4double G4USolid::DistanceToIn(const G4ThreeVector& pt,
103  const G4ThreeVector& d) const
104 {
105  UVector3 p;
106  p.x() = pt.x();
107  p.y() = pt.y();
108  p.z() = pt.z(); // better assign at construction
109  UVector3 v;
110  v.x() = d.x();
111  v.y() = d.y();
112  v.z() = d.z(); // better assign at construction
113  G4double dist = fShape->DistanceToIn(p, v);
114  if (dist > kInfinity) return kInfinity;
115 // return (dist > halfTolerance) ? dist : 0.0;
116  return dist;
117 }
118 
119 G4double G4USolid::DistanceToIn(const G4ThreeVector& pt) const
120 {
121  UVector3 p;
122  p.x() = pt.x();
123  p.y() = pt.y();
124  p.z() = pt.z(); // better assign at construction
125  G4double dist = fShape->SafetyFromOutside(p); // true?
126  if (dist > kInfinity) return kInfinity;
127 // return (dist > halfTolerance) ? dist : 0.0;
128  return dist;
129 }
130 
131 G4double G4USolid::DistanceToOut(const G4ThreeVector& pt,
132  const G4ThreeVector& d,
133  const G4bool calcNorm,
134  G4bool* validNorm,
135  G4ThreeVector* norm) const
136 {
137  UVector3 p;
138  p.x() = pt.x();
139  p.y() = pt.y();
140  p.z() = pt.z(); // better assign at construction
141  UVector3 v;
142  v.x() = d.x();
143  v.y() = d.y();
144  v.z() = d.z(); // better assign at construction
145  UVector3 n;
146  G4bool valid;
147  G4double dist = fShape->DistanceToOut(p, v, n, valid); // should use local variable
148  if(calcNorm)
149  {
150  if(valid){ *validNorm = true; }
151  else { *validNorm = false; }
152  if(*validNorm) // *norm = n, but only after calcNorm check
153  {
154  norm->setX(n.x());
155  norm->setY(n.y());
156  norm->setZ(n.z());
157  }
158  }
159  if (dist > kInfinity) return kInfinity;
160 // return (dist > halfTolerance) ? dist : 0.0;
161  return dist;
162 }
163 
164 G4double G4USolid::DistanceToOut(const G4ThreeVector& pt) const
165 {
166  UVector3 p;
167  p.x() = pt.x();
168  p.y() = pt.y();
169  p.z() = pt.z(); // better assign at construction
170  G4double dist = fShape->SafetyFromInside(p); // true?
171 // return (dist > halfTolerance) ? dist : 0.0;
172  return dist;
173 }
174 
175 G4double G4USolid::GetCubicVolume()
176 {
177  return fShape->Capacity();
178 }
179 
180 G4double G4USolid::GetSurfaceArea()
181 {
182  return fShape->SurfaceArea();
183 }
184 
185 G4ThreeVector G4USolid::GetPointOnSurface() const
186 {
187  UVector3 p;
188  p = fShape->GetPointOnSurface();
189  return G4ThreeVector(p.x(), p.y(), p.z());
190 }
191 
192 G4bool G4USolid::CalculateExtent(const EAxis pAxis,
193  const G4VoxelLimits& pVoxelLimit,
194  const G4AffineTransform& pTransform,
195  G4double& pMin, G4double& pMax) const
196 {
197  if (!pTransform.IsRotated())
198  {
199  VUSolid::EAxisType eAxis = VUSolid::eXaxis;
200  G4double offset = pTransform.NetTranslation().x();
201  if (pAxis == kYAxis)
202  {
203  eAxis = VUSolid::eYaxis;
204  offset = pTransform.NetTranslation().y();
205  }
206  if (pAxis == kZAxis)
207  {
208  eAxis = VUSolid::eZaxis;
209  offset = pTransform.NetTranslation().z();
210  }
211  fShape->ExtentAxis(eAxis, pMin, pMax);
212 
213  pMin += offset;
214  pMax += offset;
215 
216  if (pVoxelLimit.IsLimited())
217  {
218  switch (pAxis)
219  {
220  case kXAxis:
221  if ((pMin > pVoxelLimit.GetMaxXExtent() + kCarTolerance) ||
222  (pMax < pVoxelLimit.GetMinXExtent() - kCarTolerance))
223  {
224  return false;
225  }
226  else
227  {
228  pMin = std::max(pMin, pVoxelLimit.GetMinXExtent());
229  pMax = std::min(pMax, pVoxelLimit.GetMaxXExtent());
230  }
231  break;
232  case kYAxis:
233  if ((pMin > pVoxelLimit.GetMaxYExtent() + kCarTolerance) ||
234  (pMax < pVoxelLimit.GetMinYExtent() - kCarTolerance))
235  {
236  return false;
237  }
238  else
239  {
240  pMin = std::max(pMin, pVoxelLimit.GetMinYExtent());
241  pMax = std::min(pMax, pVoxelLimit.GetMaxYExtent());
242  }
243  break;
244  case kZAxis:
245  if ((pMin > pVoxelLimit.GetMaxZExtent() + kCarTolerance) ||
246  (pMax < pVoxelLimit.GetMinZExtent() - kCarTolerance))
247  {
248  return false;
249  }
250  else
251  {
252  pMin = std::max(pMin, pVoxelLimit.GetMinZExtent());
253  pMax = std::min(pMax, pVoxelLimit.GetMaxZExtent());
254  }
255  break;
256  default:
257  break;
258  }
259  pMin -= kCarTolerance ;
260  pMax += kCarTolerance ;
261  }
262  return true;
263  }
264  else // General rotated case - create and clip mesh to boundaries
265  {
266  // Rotate BoundingBox and Calculate Extent as for BREPS
267 
268  G4bool existsAfterClip = false ;
269  G4ThreeVectorList* vertices ;
270 
271  pMin = +kInfinity ;
272  pMax = -kInfinity ;
273 
274  // Calculate rotated vertex coordinates
275 
276  vertices = CreateRotatedVertices(pTransform) ;
277  ClipCrossSection(vertices, 0, pVoxelLimit, pAxis, pMin, pMax) ;
278  ClipCrossSection(vertices, 4, pVoxelLimit, pAxis, pMin, pMax) ;
279  ClipBetweenSections(vertices, 0, pVoxelLimit, pAxis, pMin, pMax) ;
280 
281  if (pVoxelLimit.IsLimited(pAxis) == false)
282  {
283  if ((pMin != kInfinity) || (pMax != -kInfinity))
284  {
285  existsAfterClip = true ;
286 
287  // Add 2*tolerance to avoid precision troubles
288 
289  pMin -= kCarTolerance;
290  pMax += kCarTolerance;
291  }
292  }
293  else
294  {
295  G4ThreeVector clipCentre(
296  (pVoxelLimit.GetMinXExtent() + pVoxelLimit.GetMaxXExtent()) * 0.5,
297  (pVoxelLimit.GetMinYExtent() + pVoxelLimit.GetMaxYExtent()) * 0.5,
298  (pVoxelLimit.GetMinZExtent() + pVoxelLimit.GetMaxZExtent()) * 0.5);
299 
300  if ((pMin != kInfinity) || (pMax != -kInfinity))
301  {
302  existsAfterClip = true ;
303 
304 
305  // Check to see if endpoints are in the solid
306 
307  clipCentre(pAxis) = pVoxelLimit.GetMinExtent(pAxis);
308 
309  if (Inside(pTransform.Inverse().TransformPoint(clipCentre)) != kOutside)
310  {
311  pMin = pVoxelLimit.GetMinExtent(pAxis);
312  }
313  else
314  {
315  pMin -= kCarTolerance;
316  }
317  clipCentre(pAxis) = pVoxelLimit.GetMaxExtent(pAxis);
318 
319  if (Inside(pTransform.Inverse().TransformPoint(clipCentre)) != kOutside)
320  {
321  pMax = pVoxelLimit.GetMaxExtent(pAxis);
322  }
323  else
324  {
325  pMax += kCarTolerance;
326  }
327  }
328 
329  // Check for case where completely enveloping clipping volume
330  // If point inside then we are confident that the solid completely
331  // envelopes the clipping volume. Hence set min/max extents according
332  // to clipping volume extents along the specified axis.
333 
334  else if (Inside(pTransform.Inverse().TransformPoint(clipCentre))
335  != kOutside)
336  {
337  existsAfterClip = true ;
338  pMin = pVoxelLimit.GetMinExtent(pAxis) ;
339  pMax = pVoxelLimit.GetMaxExtent(pAxis) ;
340  }
341  }
342  delete vertices;
343  return existsAfterClip;
344  }
345 }
346 
347 void G4USolid::ComputeDimensions(G4VPVParameterisation*,
348  const G4int,
349  const G4VPhysicalVolume*)
350 {
351  std::ostringstream message;
352  message << "Illegal call to G4USolid::ComputeDimensions()" << G4endl
353  << "Method not overloaded by derived class !";
354  G4Exception("G4USolid::ComputeDimensions()", "GeomSolids0003",
355  FatalException, message);
356 }
357 
358 void G4USolid::DescribeYourselfTo(G4VGraphicsScene& scene) const
359 {
360  scene.AddSolid(*this);
361 }
362 
363 G4GeometryType G4USolid::GetEntityType() const
364 {
365 
366  G4String string = fShape->GetEntityType();
367  return "G4" + string;
368 }
369 
370 std::ostream& G4USolid::StreamInfo(std::ostream& os) const
371 {
372  return fShape->StreamInfo(os);
373 }
374 
375 G4USolid::G4USolid(const G4USolid& rhs)
376  : G4VSolid(rhs), fRebuildPolyhedron(false), fPolyhedron(0)
377 {
378  fShape = rhs.fShape->Clone();
379 }
380 
381 G4USolid& G4USolid::operator=(const G4USolid& rhs)
382 {
383  // Check assignment to self
384  //
385  if (this == &rhs)
386  {
387  return *this;
388  }
389 
390  // Copy base class data
391  //
392  G4VSolid::operator=(rhs);
393 
394  // Copy data
395  //
396  fShape = rhs.fShape->Clone();
397  fRebuildPolyhedron = false;
398  delete fPolyhedron; fPolyhedron = 0;
399 
400  return *this;
401 }
402 
403 G4VSolid* G4USolid::Clone() const
404 {
405  std::ostringstream message;
406  message << "Clone() method not implemented for type: "
407  << GetEntityType() << "!" << G4endl
408  << "Returning NULL pointer!";
409  G4Exception("G4USolid::Clone()", "GeomSolids1001", JustWarning, message);
410  return 0;
411 }
412 
414 G4USolid::CreateRotatedVertices(const G4AffineTransform& pTransform) const
415 {
416  G4double xMin, xMax, yMin, yMax, zMin, zMax;
417 
418  fShape->ExtentAxis(VUSolid::eXaxis, xMin, xMax);
419  fShape->ExtentAxis(VUSolid::eYaxis, yMin, yMax);
420  fShape->ExtentAxis(VUSolid::eZaxis, zMin, zMax);
421 
422  G4ThreeVectorList* vertices;
423  vertices = new G4ThreeVectorList();
424 
425  if (vertices)
426  {
427  vertices->reserve(8);
428  G4ThreeVector vertex0(xMin, yMin, zMin);
429  G4ThreeVector vertex1(xMax, yMin, zMin);
430  G4ThreeVector vertex2(xMax, yMax, zMin);
431  G4ThreeVector vertex3(xMin, yMax, zMin);
432  G4ThreeVector vertex4(xMin, yMin, zMax);
433  G4ThreeVector vertex5(xMax, yMin, zMax);
434  G4ThreeVector vertex6(xMax, yMax, zMax);
435  G4ThreeVector vertex7(xMin, yMax, zMax);
436 
437  vertices->push_back(pTransform.TransformPoint(vertex0));
438  vertices->push_back(pTransform.TransformPoint(vertex1));
439  vertices->push_back(pTransform.TransformPoint(vertex2));
440  vertices->push_back(pTransform.TransformPoint(vertex3));
441  vertices->push_back(pTransform.TransformPoint(vertex4));
442  vertices->push_back(pTransform.TransformPoint(vertex5));
443  vertices->push_back(pTransform.TransformPoint(vertex6));
444  vertices->push_back(pTransform.TransformPoint(vertex7));
445  }
446  else
447  {
448  G4Exception("G4VUSolid::CreateRotatedVertices()", "FatalError",
449  FatalException, "Out of memory - Cannot allocate vertices!");
450  }
451  return vertices;
452 }
453 
454 G4Polyhedron* G4USolid::CreatePolyhedron() const
455 {
456  // Must be implemented in concrete wrappers...
457 
458  std::ostringstream message;
459  message << "Visualization not supported for USolid shape "
460  << GetEntityType() << "... Sorry!" << G4endl;
461  G4Exception("G4USolid::CreatePolyhedron()", "GeomSolids0003",
462  FatalException, message);
463  return 0;
464 }
465 
466 G4Polyhedron* G4USolid::GetPolyhedron() const
467 {
468  if (!fPolyhedron ||
469  fRebuildPolyhedron ||
470  fPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
471  fPolyhedron->GetNumberOfRotationSteps())
472  {
473  G4AutoLock l(&polyhedronMutex);
474  delete fPolyhedron;
475  fPolyhedron = CreatePolyhedron();
476  fRebuildPolyhedron = false;
477  l.unlock();
478  }
479  return fPolyhedron;
480 }
481 
482 G4VisExtent G4USolid:: GetExtent() const
483 {
484  G4VisExtent extent;
485  G4VoxelLimits voxelLimits; // Defaults to "infinite" limits.
486  G4AffineTransform affineTransform;
487  G4double vmin, vmax;
488  CalculateExtent(kXAxis, voxelLimits, affineTransform, vmin, vmax);
489  extent.SetXmin(vmin);
490  extent.SetXmax(vmax);
491  CalculateExtent(kYAxis, voxelLimits, affineTransform, vmin, vmax);
492  extent.SetYmin(vmin);
493  extent.SetYmax(vmax);
494  CalculateExtent(kZAxis, voxelLimits, affineTransform, vmin, vmax);
495  extent.SetZmin(vmin);
496  extent.SetZmax(vmax);
497  return extent;
498 }
499 
500 #endif // G4GEOM_USE_USOLIDS
static const G4double kInfinity
Definition: geomdefs.hh:42
G4double GetMinYExtent() const
CLHEP::Hep3Vector G4ThreeVector
G4AffineTransform Inverse() const
G4String name
Definition: TRTMaterials.hh:40
G4bool IsRotated() const
void SetXmax(G4double xmax)
Definition: G4VisExtent.hh:102
G4ThreeVector NetTranslation() const
G4double a
Definition: TRTMaterials.hh:39
virtual void AddSolid(const G4Box &)=0
int G4int
Definition: G4Types.hh:78
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:175
void SetYmax(G4double ymax)
Definition: G4VisExtent.hh:106
static const double s
Definition: G4SIunits.hh:168
G4double GetMaxXExtent() const
G4double GetMinZExtent() const
G4bool IsLimited() const
bool G4bool
Definition: G4Types.hh:79
std::vector< G4ThreeVector > G4ThreeVectorList
Definition: G4VSolid.hh:79
const G4int n
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
G4double GetMinXExtent() const
G4int G4Mutex
Definition: G4Threading.hh:173
G4ThreeVector TransformPoint(const G4ThreeVector &vec) const
G4double GetMaxZExtent() const
void SetZmin(G4double zmin)
Definition: G4VisExtent.hh:108
T max(const T t1, const T t2)
brief Return the largest of the two arguments
EInside
Definition: geomdefs.hh:58
EAxis
Definition: geomdefs.hh:54
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
G4bool operator==(const G4GeometryCell &k1, const G4GeometryCell &k2)
#define G4endl
Definition: G4ios.hh:61
G4double GetMaxYExtent() const
G4VSolid & operator=(const G4VSolid &rhs)
Definition: G4VSolid.cc:110
virtual G4VSolid * Clone() const
Definition: G4VSolid.cc:324
void SetZmax(G4double zmax)
Definition: G4VisExtent.hh:110
void SetXmin(G4double xmin)
Definition: G4VisExtent.hh:100
double G4double
Definition: G4Types.hh:76
G4double GetMaxExtent(const EAxis pAxis) const
void SetYmin(G4double ymin)
Definition: G4VisExtent.hh:104
G4double GetMinExtent(const EAxis pAxis) const