source: trunk/source/geometry/solids/specific/src/G4Tet.cc @ 1202

Last change on this file since 1202 was 1058, checked in by garnier, 15 years ago

file release beta

File size: 23.9 KB
Line 
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  intellectual property  of the *
19// * Vanderbilt University Free Electron Laser Center                 *
20// * Vanderbilt University, Nashville, TN, USA                        *
21// * Development supported by:                                        *
22// * United States MFEL program  under grant FA9550-04-1-0045         *
23// * and NASA under contract number NNG04CT05P                        *
24// * Written by Marcus H. Mendenhall and Robert A. Weller.            *
25// *                                                                  *
26// * Contributed to the Geant4 Core, January, 2005.                   *
27// *                                                                  *
28// ********************************************************************
29//
30// $Id: G4Tet.cc,v 1.11 2006/11/13 08:58:03 gcosmo Exp $
31// GEANT4 tag $Name: geant4-09-02-ref-02 $
32//
33// class G4Tet
34//
35// Implementation for G4Tet class
36//
37// History:
38//
39//  20040903 - Marcus Mendenhall, created G4Tet
40//  20041101 - Marcus Mendenhall, optimized constant dot products with
41//             fCdotNijk values
42//  20041101 - MHM removed tracking error by clipping DistanceToOut to 0
43//             for surface cases
44//  20041101 - MHM many speed optimizations in if statements
45//  20041101 - MHM changed vdotn comparisons to 1e-12 instead of 0.0 to
46//             avoid nearly-parallel problems
47//  20041102 - MHM Added extra distance into solid to DistanceToIn(p,v)
48//             hit testing
49//  20041102 - MHM added ability to check for degeneracy without throwing
50//             G4Exception
51//  20041103 - MHM removed many unused variables from class
52//  20040803 - Dionysios Anninos, added GetPointOnSurface() method
53//  20061112 - MHM added code for G4VSolid GetSurfaceArea()
54//
55// --------------------------------------------------------------------
56
57#include "G4Tet.hh"
58
59const char G4Tet::CVSVers[]="$Id: G4Tet.cc,v 1.11 2006/11/13 08:58:03 gcosmo Exp $";
60
61#include "G4VoxelLimits.hh"
62#include "G4AffineTransform.hh"
63
64#include "G4VPVParameterisation.hh"
65
66#include "Randomize.hh"
67
68#include "G4VGraphicsScene.hh"
69#include "G4Polyhedron.hh"
70#include "G4NURBS.hh"
71#include "G4NURBSbox.hh"
72#include "G4VisExtent.hh"
73
74#include "G4ThreeVector.hh"
75
76#include <cmath>
77
78using namespace CLHEP;
79
80////////////////////////////////////////////////////////////////////////
81//
82// Constructor - create a tetrahedron
83// This class is implemented separately from general polyhedra,
84// because the simplex geometry can be computed very quickly,
85// which may become important in situations imported from mesh generators,
86// in which a very large number of G4Tets are created.
87// A Tet has all of its geometrical information precomputed
88
89G4Tet::G4Tet(const G4String& pName,
90                   G4ThreeVector anchor,
91                   G4ThreeVector p2,
92                   G4ThreeVector p3,
93                   G4ThreeVector p4, G4bool *degeneracyFlag)
94  : G4VSolid(pName), fpPolyhedron(0), warningFlag(0)
95{
96  // fV<x><y> is vector from vertex <y> to vertex <x>
97  //
98  G4ThreeVector fV21=p2-anchor;
99  G4ThreeVector fV31=p3-anchor;
100  G4ThreeVector fV41=p4-anchor;
101
102  // make sure this is a correctly oriented set of points for the tetrahedron
103  //
104  G4double signed_vol=fV21.cross(fV31).dot(fV41);
105  if(signed_vol<0.0)
106  {
107    G4ThreeVector temp(p4);
108    p4=p3;
109    p3=temp;
110    temp=fV41;
111    fV41=fV31;
112    fV31=temp; 
113  }
114  fCubicVolume = std::abs(signed_vol) / 6.;
115
116  G4ThreeVector fV24=p2-p4;
117  G4ThreeVector fV43=p4-p3;
118  G4ThreeVector fV32=p3-p2;
119
120  fXMin=std::min(std::min(std::min(anchor.x(), p2.x()),p3.x()),p4.x());
121  fXMax=std::max(std::max(std::max(anchor.x(), p2.x()),p3.x()),p4.x());
122  fYMin=std::min(std::min(std::min(anchor.y(), p2.y()),p3.y()),p4.y());
123  fYMax=std::max(std::max(std::max(anchor.y(), p2.y()),p3.y()),p4.y());
124  fZMin=std::min(std::min(std::min(anchor.z(), p2.z()),p3.z()),p4.z());
125  fZMax=std::max(std::max(std::max(anchor.z(), p2.z()),p3.z()),p4.z());
126
127  fDx=(fXMax-fXMin)*0.5; fDy=(fYMax-fYMin)*0.5; fDz=(fZMax-fZMin)*0.5;
128
129  fMiddle=G4ThreeVector(fXMax+fXMin, fYMax+fYMin, fZMax+fZMin)*0.5;
130  fMaxSize=std::max(std::max(std::max((anchor-fMiddle).mag(),
131                                      (p2-fMiddle).mag()),
132                             (p3-fMiddle).mag()),
133                    (p4-fMiddle).mag());
134
135  G4bool degenerate=std::abs(signed_vol) < 1e-9*fMaxSize*fMaxSize*fMaxSize;
136
137  if(degeneracyFlag) *degeneracyFlag=degenerate;
138  else if (degenerate)
139  {
140    G4Exception("G4Tet::G4Tet()", "InvalidSetup", FatalException,
141                "Degenerate tetrahedron not allowed.");
142  }
143
144  fTol=1e-9*(std::abs(fXMin)+std::abs(fXMax)+std::abs(fYMin)
145            +std::abs(fYMax)+std::abs(fZMin)+std::abs(fZMax));
146  //fTol=kCarTolerance;
147
148  fAnchor=anchor;
149  fP2=p2;
150  fP3=p3;
151  fP4=p4;
152
153  G4ThreeVector fCenter123=(anchor+p2+p3)*(1.0/3.0); // face center
154  G4ThreeVector fCenter134=(anchor+p4+p3)*(1.0/3.0);
155  G4ThreeVector fCenter142=(anchor+p4+p2)*(1.0/3.0);
156  G4ThreeVector fCenter234=(p2+p3+p4)*(1.0/3.0);
157
158  // compute area of each triangular face by cross product
159  // and sum for total surface area
160
161  G4ThreeVector normal123=fV31.cross(fV21);
162  G4ThreeVector normal134=fV41.cross(fV31);
163  G4ThreeVector normal142=fV21.cross(fV41);
164  G4ThreeVector normal234=fV32.cross(fV43);
165
166  fSurfaceArea=(
167      normal123.mag()+
168      normal134.mag()+
169      normal142.mag()+
170      normal234.mag()
171  )/2.0;
172
173  fNormal123=normal123.unit();
174  fNormal134=normal134.unit();
175  fNormal142=normal142.unit();
176  fNormal234=normal234.unit();
177
178  fCdotN123=fCenter123.dot(fNormal123);
179  fCdotN134=fCenter134.dot(fNormal134);
180  fCdotN142=fCenter142.dot(fNormal142);
181  fCdotN234=fCenter234.dot(fNormal234);
182}
183
184//////////////////////////////////////////////////////////////////////////
185//
186// Fake default constructor - sets only member data and allocates memory
187//                            for usage restricted to object persistency.
188//
189G4Tet::G4Tet( __void__& a )
190  : G4VSolid(a), fCubicVolume(0.), fSurfaceArea(0.), fpPolyhedron(0),
191    fAnchor(0,0,0), fP2(0,0,0), fP3(0,0,0), fP4(0,0,0), fMiddle(0,0,0),
192    fNormal123(0,0,0), fNormal142(0,0,0), fNormal134(0,0,0),
193    fNormal234(0,0,0), warningFlag(0),
194    fCdotN123(0.), fCdotN142(0.), fCdotN134(0.), fCdotN234(0.),
195    fXMin(0.), fXMax(0.), fYMin(0.), fYMax(0.), fZMin(0.), fZMax(0.),
196    fDx(0.), fDy(0.), fDz(0.), fTol(0.), fMaxSize(0.)
197{
198}
199
200//////////////////////////////////////////////////////////////////////////
201//
202// Destructor
203
204G4Tet::~G4Tet()
205{
206  delete fpPolyhedron;
207}
208
209//////////////////////////////////////////////////////////////////////////
210//
211// CheckDegeneracy
212
213G4bool G4Tet::CheckDegeneracy( G4ThreeVector anchor,
214                               G4ThreeVector p2,
215                               G4ThreeVector p3,
216                               G4ThreeVector p4 )
217{
218  G4bool result;
219  G4Tet *object=new G4Tet("temp",anchor,p2,p3,p4,&result);
220  delete object;
221  return result;
222}
223
224//////////////////////////////////////////////////////////////////////////
225//
226// Dispatch to parameterisation for replication mechanism dimension
227// computation & modification.
228
229void G4Tet::ComputeDimensions(G4VPVParameterisation* ,
230                              const G4int ,
231                              const G4VPhysicalVolume* )
232{
233}
234
235//////////////////////////////////////////////////////////////////////////
236//
237// Calculate extent under transform and specified limit
238
239G4bool G4Tet::CalculateExtent(const EAxis pAxis,
240                              const G4VoxelLimits& pVoxelLimit,
241                              const G4AffineTransform& pTransform,
242                                    G4double& pMin, G4double& pMax) const
243{
244  G4double xMin,xMax;
245  G4double yMin,yMax;
246  G4double zMin,zMax;
247
248  if (pTransform.IsRotated())
249  {
250    G4ThreeVector pp0=pTransform.TransformPoint(fAnchor);
251    G4ThreeVector pp1=pTransform.TransformPoint(fP2);
252    G4ThreeVector pp2=pTransform.TransformPoint(fP3);
253    G4ThreeVector pp3=pTransform.TransformPoint(fP4);
254
255    xMin    = std::min(std::min(std::min(pp0.x(), pp1.x()),pp2.x()),pp3.x());
256    xMax    = std::max(std::max(std::max(pp0.x(), pp1.x()),pp2.x()),pp3.x());
257    yMin    = std::min(std::min(std::min(pp0.y(), pp1.y()),pp2.y()),pp3.y());
258    yMax    = std::max(std::max(std::max(pp0.y(), pp1.y()),pp2.y()),pp3.y());
259    zMin    = std::min(std::min(std::min(pp0.z(), pp1.z()),pp2.z()),pp3.z());
260    zMax    = std::max(std::max(std::max(pp0.z(), pp1.z()),pp2.z()),pp3.z());
261
262  }
263  else
264  {
265    G4double xoffset = pTransform.NetTranslation().x() ;
266    xMin    = xoffset + fXMin;
267    xMax    = xoffset + fXMax;
268    G4double yoffset = pTransform.NetTranslation().y() ;
269    yMin    = yoffset + fYMin;
270    yMax    = yoffset + fYMax;
271    G4double zoffset = pTransform.NetTranslation().z() ;
272    zMin    = zoffset + fZMin;
273    zMax    = zoffset + fZMax;
274  }
275
276  if (pVoxelLimit.IsXLimited())
277  {
278    if ( (xMin > pVoxelLimit.GetMaxXExtent()+fTol) || 
279         (xMax < pVoxelLimit.GetMinXExtent()-fTol)  )  { return false; }
280    else
281    {
282      xMin = std::max(xMin, pVoxelLimit.GetMinXExtent());
283      xMax = std::min(xMax, pVoxelLimit.GetMaxXExtent());
284    }
285  }
286
287  if (pVoxelLimit.IsYLimited())
288  {
289    if ( (yMin > pVoxelLimit.GetMaxYExtent()+fTol) ||
290         (yMax < pVoxelLimit.GetMinYExtent()-fTol)  )  { return false; }
291    else
292    {
293      yMin = std::max(yMin, pVoxelLimit.GetMinYExtent());
294      yMax = std::min(yMax, pVoxelLimit.GetMaxYExtent());
295    }
296    }
297
298    if (pVoxelLimit.IsZLimited())
299    {
300      if ( (zMin > pVoxelLimit.GetMaxZExtent()+fTol) ||
301           (zMax < pVoxelLimit.GetMinZExtent()-fTol)  )  { return false; }
302    else
303    {
304      zMin = std::max(zMin, pVoxelLimit.GetMinZExtent());
305      zMax = std::min(zMax, pVoxelLimit.GetMaxZExtent());
306    }
307  }
308
309  switch (pAxis)
310  {
311    case kXAxis:
312      pMin=xMin;
313      pMax=xMax;
314      break;
315    case kYAxis:
316      pMin=yMin;
317      pMax=yMax;
318      break;
319    case kZAxis:
320      pMin=zMin;
321      pMax=zMax;
322      break;
323    default:
324      break;
325  }
326
327  return true;
328} 
329
330/////////////////////////////////////////////////////////////////////////
331//
332// Return whether point inside/outside/on surface, using tolerance
333
334EInside G4Tet::Inside(const G4ThreeVector& p) const
335{
336  G4double r123, r134, r142, r234;
337
338  // this is written to allow if-statement truncation so the outside test
339  // (where most of the world is) can fail very quickly and efficiently
340
341  if ( (r123=p.dot(fNormal123)-fCdotN123) > fTol ||
342       (r134=p.dot(fNormal134)-fCdotN134) > fTol ||
343       (r142=p.dot(fNormal142)-fCdotN142) > fTol ||
344       (r234=p.dot(fNormal234)-fCdotN234) > fTol )
345  {
346    return kOutside; // at least one is out!
347  }
348  else if( (r123 < -fTol)&&(r134 < -fTol)&&(r142 < -fTol)&&(r234 < -fTol) )
349  {
350    return kInside; // all are definitively inside
351  }
352  else
353  {
354    return kSurface; // too close to tell
355  }
356}
357
358///////////////////////////////////////////////////////////////////////
359//
360// Calculate side nearest to p, and return normal
361// If two sides are equidistant, normal of first side (x/y/z)
362// encountered returned.
363// This assumes that we are looking from the inside!
364
365G4ThreeVector G4Tet::SurfaceNormal( const G4ThreeVector& p) const
366{
367  G4double r123=std::abs(p.dot(fNormal123)-fCdotN123);
368  G4double r134=std::abs(p.dot(fNormal134)-fCdotN134);
369  G4double r142=std::abs(p.dot(fNormal142)-fCdotN142);
370  G4double r234=std::abs(p.dot(fNormal234)-fCdotN234);
371
372  if( (r123<=r134) && (r123<=r142) && (r123<=r234) )  { return fNormal123; }
373  else if ( (r134<=r142) && (r134<=r234) )  { return fNormal134; }
374  else if (r142 <= r234)  { return fNormal142; }
375  return fNormal234;
376}
377
378///////////////////////////////////////////////////////////////////////////
379//
380// Calculate distance to box from an outside point
381// - return kInfinity if no intersection.
382// All this is very unrolled, for speed.
383
384G4double G4Tet::DistanceToIn(const G4ThreeVector& p,
385                             const G4ThreeVector& v) const
386{
387    G4ThreeVector vu(v.unit()), hp;
388    G4double vdotn, t, tmin=kInfinity;
389
390    G4double extraDistance=10.0*fTol; // a little ways into the solid
391
392    vdotn=-vu.dot(fNormal123);
393    if(vdotn > 1e-12)
394    { // this is a candidate face, since it is pointing at us
395      t=(p.dot(fNormal123)-fCdotN123)/vdotn; // #  distance to intersection
396      if( (t>=-fTol) && (t<tmin) )
397      { // if not true, we're going away from this face or it's not close
398        hp=p+vu*(t+extraDistance); // a little beyond point of intersection
399        if ( ( hp.dot(fNormal134)-fCdotN134 < 0.0 ) &&
400             ( hp.dot(fNormal142)-fCdotN142 < 0.0 ) &&
401             ( hp.dot(fNormal234)-fCdotN234 < 0.0 ) )
402        {
403          tmin=t;
404        }
405      }
406    }
407
408    vdotn=-vu.dot(fNormal134);
409    if(vdotn > 1e-12)
410    { // # this is a candidate face, since it is pointing at us
411      t=(p.dot(fNormal134)-fCdotN134)/vdotn; // #  distance to intersection
412      if( (t>=-fTol) && (t<tmin) )
413      { // if not true, we're going away from this face
414        hp=p+vu*(t+extraDistance); // a little beyond point of intersection
415        if ( ( hp.dot(fNormal123)-fCdotN123 < 0.0 ) && 
416             ( hp.dot(fNormal142)-fCdotN142 < 0.0 ) &&
417             ( hp.dot(fNormal234)-fCdotN234 < 0.0 ) )
418        {
419          tmin=t;
420        }
421      }
422    }
423
424    vdotn=-vu.dot(fNormal142);
425    if(vdotn > 1e-12)
426    { // # this is a candidate face, since it is pointing at us
427      t=(p.dot(fNormal142)-fCdotN142)/vdotn; // #  distance to intersection
428      if( (t>=-fTol) && (t<tmin) )
429      { // if not true, we're going away from this face
430        hp=p+vu*(t+extraDistance); // a little beyond point of intersection
431        if ( ( hp.dot(fNormal123)-fCdotN123 < 0.0 ) &&
432             ( hp.dot(fNormal134)-fCdotN134 < 0.0 ) &&
433             ( hp.dot(fNormal234)-fCdotN234 < 0.0 ) )
434        {
435          tmin=t;
436        }
437      }
438    }
439
440    vdotn=-vu.dot(fNormal234);
441    if(vdotn > 1e-12)
442    { // # this is a candidate face, since it is pointing at us
443      t=(p.dot(fNormal234)-fCdotN234)/vdotn; // #  distance to intersection
444      if( (t>=-fTol) && (t<tmin) )
445      { // if not true, we're going away from this face
446        hp=p+vu*(t+extraDistance); // a little beyond point of intersection
447        if ( ( hp.dot(fNormal123)-fCdotN123 < 0.0 ) &&
448             ( hp.dot(fNormal134)-fCdotN134 < 0.0 ) &&
449             ( hp.dot(fNormal142)-fCdotN142 < 0.0 ) )
450        {
451          tmin=t;
452        }
453      }
454    }
455
456  return std::max(0.0,tmin);
457}
458
459//////////////////////////////////////////////////////////////////////////
460//
461// Approximate distance to tet.
462// returns distance to sphere centered on bounding box
463// - If inside return 0
464
465G4double G4Tet::DistanceToIn(const G4ThreeVector& p) const
466{
467  G4double dd=(p-fMiddle).mag() - fMaxSize - fTol;
468  return std::max(0.0, dd);
469}
470
471/////////////////////////////////////////////////////////////////////////
472//
473// Calcluate distance to surface of box from inside
474// by calculating distances to box's x/y/z planes.
475// Smallest distance is exact distance to exiting.
476
477G4double G4Tet::DistanceToOut( const G4ThreeVector& p,const G4ThreeVector& v,
478                               const G4bool calcNorm,
479                                     G4bool *validNorm, G4ThreeVector *n) const
480{
481    G4ThreeVector vu(v.unit());
482    G4double t1=kInfinity,t2=kInfinity,t3=kInfinity,t4=kInfinity, vdotn, tt;
483
484    vdotn=vu.dot(fNormal123);
485    if(vdotn > 1e-12)  // #we're heading towards this face, so it is a candidate
486    {
487      t1=(fCdotN123-p.dot(fNormal123))/vdotn; // #  distance to intersection
488    }
489
490    vdotn=vu.dot(fNormal134);
491    if(vdotn > 1e-12) // #we're heading towards this face, so it is a candidate
492    {
493      t2=(fCdotN134-p.dot(fNormal134))/vdotn; // #  distance to intersection
494    }
495
496    vdotn=vu.dot(fNormal142);
497    if(vdotn > 1e-12) // #we're heading towards this face, so it is a candidate
498    {
499      t3=(fCdotN142-p.dot(fNormal142))/vdotn; // #  distance to intersection
500    }
501
502    vdotn=vu.dot(fNormal234);
503    if(vdotn > 1e-12) // #we're heading towards this face, so it is a candidate
504    {
505      t4=(fCdotN234-p.dot(fNormal234))/vdotn; // #  distance to intersection
506    }
507
508    tt=std::min(std::min(std::min(t1,t2),t3),t4);
509
510    if (warningFlag && (tt == kInfinity || tt < -fTol))
511    {
512      DumpInfo();
513      G4cout << "p = " << p / mm << "mm" << G4endl;
514      G4cout << "v = " << v  << G4endl;
515      G4cout << "t1, t2, t3, t4 (mm) "
516             << t1/mm << ", " << t2/mm << ", " << t3/mm << ", " << t4/mm
517             << G4endl << G4endl;
518      G4Exception("G4Tet::DistanceToOut(p,v,...)", "Notification", JustWarning,
519                  "No good intersection found or already outside!?" );
520      if(validNorm)
521      {
522        *validNorm=false; // flag normal as meaningless
523      }
524    }
525    else if(calcNorm && n)
526    {
527      static G4ThreeVector normal;
528      if(tt==t1)        { normal=fNormal123; }
529      else if (tt==t2)  { normal=fNormal134; }
530      else if (tt==t3)  { normal=fNormal142; }
531      else if (tt==t4)  { normal=fNormal234; }
532      n=&normal;
533      if(validNorm) { *validNorm=true; }
534    }
535
536    return std::max(tt,0.0); // avoid tt<0.0 by a tiny bit
537                             // if we are right on a face
538}
539
540////////////////////////////////////////////////////////////////////////////
541//
542// Calculate exact shortest distance to any boundary from inside
543// - If outside return 0
544
545G4double G4Tet::DistanceToOut(const G4ThreeVector& p) const
546{
547  G4double t1,t2,t3,t4;
548  t1=fCdotN123-p.dot(fNormal123); //  distance to plane, positive if inside
549  t2=fCdotN134-p.dot(fNormal134); //  distance to plane
550  t3=fCdotN142-p.dot(fNormal142); //  distance to plane
551  t4=fCdotN234-p.dot(fNormal234); //  distance to plane
552
553  // if any one of these is negative, we are outside,
554  // so return zero in that case
555
556  G4double tmin=std::min(std::min(std::min(t1,t2),t3),t4);
557  return (tmin < fTol)? 0:tmin;
558}
559
560////////////////////////////////////////////////////////////////////////
561//
562// Create a List containing the transformed vertices
563// Note: Caller has deletion responsibility
564
565G4ThreeVectorList*
566G4Tet::CreateRotatedVertices(const G4AffineTransform& pTransform) const
567{
568  G4ThreeVectorList* vertices = new G4ThreeVectorList();
569  vertices->reserve(4);
570
571  if (vertices)
572  {
573    G4ThreeVector vertex0(fAnchor);
574    G4ThreeVector vertex1(fP2);
575    G4ThreeVector vertex2(fP3);
576    G4ThreeVector vertex3(fP4);
577
578    vertices->push_back(pTransform.TransformPoint(vertex0));
579    vertices->push_back(pTransform.TransformPoint(vertex1));
580    vertices->push_back(pTransform.TransformPoint(vertex2));
581    vertices->push_back(pTransform.TransformPoint(vertex3));
582  }
583  else
584  {
585    DumpInfo();
586    G4Exception("G4Tet::CreateRotatedVertices()",
587          "FatalError", FatalException,
588          "Error in allocation of vertices. Out of memory !");
589  }
590  return vertices;
591}
592
593//////////////////////////////////////////////////////////////////////////
594//
595// GetEntityType
596
597G4GeometryType G4Tet::GetEntityType() const
598{
599  return G4String("G4Tet");
600}
601
602//////////////////////////////////////////////////////////////////////////
603//
604// Stream object contents to an output stream
605
606std::ostream& G4Tet::StreamInfo(std::ostream& os) const
607{
608  os << "-----------------------------------------------------------\n"
609  << "    *** Dump for solid - " << GetName() << " ***\n"
610  << "    ===================================================\n"
611  << " Solid type: G4Tet\n"
612  << " Parameters: \n"
613  << "    anchor: " << fAnchor/mm << " mm \n"
614  << "    p2: " << fP2/mm << " mm \n"
615  << "    p3: " << fP3/mm << " mm \n"
616  << "    p4: " << fP4/mm << " mm \n"
617  << "    normal123: " << fNormal123 << " \n"
618  << "    normal134: " << fNormal134 << " \n"
619  << "    normal142: " << fNormal142 << " \n"
620  << "    normal234: " << fNormal234 << " \n"
621  << "-----------------------------------------------------------\n";
622
623  return os;
624}
625
626
627////////////////////////////////////////////////////////////////////////
628//
629// GetPointOnFace
630//
631// Auxiliary method for get point on surface
632
633G4ThreeVector G4Tet::GetPointOnFace(G4ThreeVector p1, G4ThreeVector p2,
634                                    G4ThreeVector p3, G4double& area) const
635{
636  G4double lambda1,lambda2;
637  G4ThreeVector v, w;
638
639  v = p3 - p1;
640  w = p1 - p2;
641
642  lambda1 = RandFlat::shoot(0.,1.);
643  lambda2 = RandFlat::shoot(0.,lambda1);
644
645  area = 0.5*(v.cross(w)).mag();
646
647  return (p2 + lambda1*w + lambda2*v);
648}
649
650////////////////////////////////////////////////////////////////////////////
651//
652// GetPointOnSurface
653
654G4ThreeVector G4Tet::GetPointOnSurface() const
655{
656  G4double chose,aOne,aTwo,aThree,aFour;
657  G4ThreeVector p1, p2, p3, p4;
658 
659  p1 = GetPointOnFace(fAnchor,fP2,fP3,aOne);
660  p2 = GetPointOnFace(fAnchor,fP4,fP3,aTwo);
661  p3 = GetPointOnFace(fAnchor,fP4,fP2,aThree);
662  p4 = GetPointOnFace(fP4,fP3,fP2,aFour);
663 
664  chose = RandFlat::shoot(0.,aOne+aTwo+aThree+aFour);
665  if( (chose>=0.) && (chose <aOne) ) {return p1;}
666  else if( (chose>=aOne) && (chose < aOne+aTwo) ) {return p2;}
667  else if( (chose>=aOne+aTwo) && (chose<aOne+aTwo+aThree) ) {return p3;}
668  return p4;
669}
670
671////////////////////////////////////////////////////////////////////////
672//
673// GetVertices
674
675std::vector<G4ThreeVector> G4Tet::GetVertices() const 
676{
677  std::vector<G4ThreeVector> vertices(4);
678  vertices[0] = fAnchor;
679  vertices[1] = fP2;
680  vertices[2] = fP3;
681  vertices[3] = fP4;
682
683  return vertices;
684}
685
686////////////////////////////////////////////////////////////////////////
687//
688// GetCubicVolume
689
690G4double G4Tet::GetCubicVolume()
691{
692  return fCubicVolume;
693}
694
695////////////////////////////////////////////////////////////////////////
696//
697// GetSurfaceArea
698
699G4double G4Tet::GetSurfaceArea()
700{
701  return fSurfaceArea;
702}
703
704// Methods for visualisation
705
706////////////////////////////////////////////////////////////////////////
707//
708// DescribeYourselfTo
709
710void G4Tet::DescribeYourselfTo (G4VGraphicsScene& scene) const 
711{
712  scene.AddSolid (*this);
713}
714
715////////////////////////////////////////////////////////////////////////
716//
717// GetExtent
718
719G4VisExtent G4Tet::GetExtent() const 
720{
721  return G4VisExtent (fXMin, fXMax, fYMin, fYMax, fZMin, fZMax);
722}
723
724////////////////////////////////////////////////////////////////////////
725//
726// CreatePolyhedron
727
728G4Polyhedron* G4Tet::CreatePolyhedron () const 
729{
730  G4Polyhedron *ph=new G4Polyhedron;
731  G4double xyz[4][3];
732  static G4int faces[4][4]={{1,3,2,0},{1,4,3,0},{1,2,4,0},{2,3,4,0}};
733  xyz[0][0]=fAnchor.x(); xyz[0][1]=fAnchor.y(); xyz[0][2]=fAnchor.z();
734  xyz[1][0]=fP2.x(); xyz[1][1]=fP2.y(); xyz[1][2]=fP2.z();
735  xyz[2][0]=fP3.x(); xyz[2][1]=fP3.y(); xyz[2][2]=fP3.z();
736  xyz[3][0]=fP4.x(); xyz[3][1]=fP4.y(); xyz[3][2]=fP4.z();
737
738  ph->createPolyhedron(4,4,xyz,faces);
739
740  return ph;
741}
742
743////////////////////////////////////////////////////////////////////////
744//
745// CreateNURBS
746
747G4NURBS* G4Tet::CreateNURBS () const 
748{
749  return new G4NURBSbox (fDx, fDy, fDz);
750}
751
752////////////////////////////////////////////////////////////////////////
753//
754// GetPolyhedron
755
756G4Polyhedron* G4Tet::GetPolyhedron () const
757{
758  if (!fpPolyhedron ||
759      fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
760      fpPolyhedron->GetNumberOfRotationSteps())
761    {
762      delete fpPolyhedron;
763      fpPolyhedron = CreatePolyhedron();
764    }
765  return fpPolyhedron;
766}
Note: See TracBrowser for help on using the repository browser.