G4EllipticalTube Class Reference

#include <G4EllipticalTube.hh>

Inheritance diagram for G4EllipticalTube:

G4VSolid

Public Member Functions

 G4EllipticalTube (const G4String &name, G4double theDx, G4double theDy, G4double theDz)
virtual ~G4EllipticalTube ()
G4bool CalculateExtent (const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
EInside Inside (const G4ThreeVector &p) const
G4ThreeVector SurfaceNormal (const G4ThreeVector &p) const
G4double DistanceToIn (const G4ThreeVector &p, const G4ThreeVector &v) const
G4double DistanceToIn (const G4ThreeVector &p) const
G4double DistanceToOut (const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const
G4double DistanceToOut (const G4ThreeVector &p) const
G4GeometryType GetEntityType () const
G4VSolidClone () const
std::ostream & StreamInfo (std::ostream &os) const
G4double GetCubicVolume ()
G4double GetSurfaceArea ()
G4ThreeVector GetPointOnSurface () const
G4PolyhedronCreatePolyhedron () const
G4PolyhedronGetPolyhedron () const
void DescribeYourselfTo (G4VGraphicsScene &scene) const
G4VisExtent GetExtent () const
G4double GetDx () const
G4double GetDy () const
G4double GetDz () const
void SetDx (const G4double newDx)
void SetDy (const G4double newDy)
void SetDz (const G4double newDz)
 G4EllipticalTube (__void__ &)
 G4EllipticalTube (const G4EllipticalTube &rhs)
G4EllipticalTubeoperator= (const G4EllipticalTube &rhs)

Protected Member Functions

G4double CheckXY (const G4double x, const G4double y, const G4double toler) const
G4double CheckXY (const G4double x, const G4double y) const
G4int IntersectXY (const G4ThreeVector &p, const G4ThreeVector &v, G4double s[2]) const

Protected Attributes

G4double dx
G4double dy
G4double dz

Detailed Description

Definition at line 55 of file G4EllipticalTube.hh.


Constructor & Destructor Documentation

G4EllipticalTube::G4EllipticalTube ( const G4String name,
G4double  theDx,
G4double  theDy,
G4double  theDz 
)

Definition at line 60 of file G4EllipticalTube.cc.

References dx, dy, and dz.

Referenced by Clone().

00064   : G4VSolid( name ), fCubicVolume(0.), fSurfaceArea(0.), fpPolyhedron(0)
00065 {
00066   dx = theDx;
00067   dy = theDy;
00068   dz = theDz;
00069 }

G4EllipticalTube::~G4EllipticalTube (  )  [virtual]

Definition at line 86 of file G4EllipticalTube.cc.

00087 {
00088   delete fpPolyhedron;
00089 }

G4EllipticalTube::G4EllipticalTube ( __void__ &   ) 

Definition at line 76 of file G4EllipticalTube.cc.

00077   : G4VSolid(a), dx(0.), dy(0.), dz(0.),
00078     fCubicVolume(0.), fSurfaceArea(0.), fpPolyhedron(0)
00079 {
00080 }

G4EllipticalTube::G4EllipticalTube ( const G4EllipticalTube rhs  ) 

Definition at line 95 of file G4EllipticalTube.cc.

00096   : G4VSolid(rhs), dx(rhs.dx), dy(rhs.dy), dz(rhs.dz),
00097     fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
00098     fpPolyhedron(0)
00099 {
00100 }


Member Function Documentation

G4bool G4EllipticalTube::CalculateExtent ( const EAxis  pAxis,
const G4VoxelLimits pVoxelLimit,
const G4AffineTransform pTransform,
G4double pmin,
G4double pmax 
) const [virtual]

Implements G4VSolid.

Definition at line 130 of file G4EllipticalTube.cc.

References G4SolidExtentList::AddSurface(), G4ClippablePolygon::AddVertexInOrder(), G4AffineTransform::ApplyPointTransform(), G4ClippablePolygon::ClearAllVertices(), dx, dy, dz, G4SolidExtentList::GetExtent(), kMaxMeshSections, G4ClippablePolygon::PartialClip(), G4ClippablePolygon::SetNormal(), and G4AffineTransform::TransformAxis().

00134 {
00135   G4SolidExtentList  extentList( axis, voxelLimit );
00136   
00137   //
00138   // We are going to divide up our elliptical face into small
00139   // pieces
00140   //
00141   
00142   //
00143   // Choose phi size of our segment(s) based on constants as
00144   // defined in meshdefs.hh
00145   //
00146   G4int numPhi = kMaxMeshSections;
00147   G4double sigPhi = twopi/numPhi;
00148   
00149   //
00150   // We have to be careful to keep our segments completely outside
00151   // of the elliptical surface. To do so we imagine we have
00152   // a simple (unit radius) circular cross section (as in G4Tubs) 
00153   // and then "stretch" the dimensions as necessary to fit the ellipse.
00154   //
00155   G4double rFudge = 1.0/std::cos(0.5*sigPhi);
00156   G4double dxFudge = dx*rFudge,
00157            dyFudge = dy*rFudge;
00158   
00159   //
00160   // As we work around the elliptical surface, we build
00161   // a "phi" segment on the way, and keep track of two
00162   // additional polygons for the two ends.
00163   //
00164   G4ClippablePolygon endPoly1, endPoly2, phiPoly;
00165   
00166   G4double phi = 0, 
00167            cosPhi = std::cos(phi),
00168            sinPhi = std::sin(phi);
00169   G4ThreeVector v0( dxFudge*cosPhi, dyFudge*sinPhi, +dz ),
00170                 v1( dxFudge*cosPhi, dyFudge*sinPhi, -dz ),
00171                 w0, w1;
00172   transform.ApplyPointTransform( v0 );
00173   transform.ApplyPointTransform( v1 );
00174   do
00175   {
00176     phi += sigPhi;
00177     if (numPhi == 1) phi = 0;  // Try to avoid roundoff
00178     cosPhi = std::cos(phi), 
00179     sinPhi = std::sin(phi);
00180     
00181     w0 = G4ThreeVector( dxFudge*cosPhi, dyFudge*sinPhi, +dz );
00182     w1 = G4ThreeVector( dxFudge*cosPhi, dyFudge*sinPhi, -dz );
00183     transform.ApplyPointTransform( w0 );
00184     transform.ApplyPointTransform( w1 );
00185     
00186     //
00187     // Add a point to our z ends
00188     //
00189     endPoly1.AddVertexInOrder( v0 );
00190     endPoly2.AddVertexInOrder( v1 );
00191     
00192     //
00193     // Build phi polygon
00194     //
00195     phiPoly.ClearAllVertices();
00196     
00197     phiPoly.AddVertexInOrder( v0 );
00198     phiPoly.AddVertexInOrder( v1 );
00199     phiPoly.AddVertexInOrder( w1 );
00200     phiPoly.AddVertexInOrder( w0 );
00201     
00202     if (phiPoly.PartialClip( voxelLimit, axis ))
00203     {
00204       //
00205       // Get unit normal
00206       //
00207       phiPoly.SetNormal( (v1-v0).cross(w0-v0).unit() );
00208       
00209       extentList.AddSurface( phiPoly );
00210     }
00211 
00212     //
00213     // Next vertex
00214     //    
00215     v0 = w0;
00216     v1 = w1;
00217   } while( --numPhi > 0 );
00218 
00219   //
00220   // Process the end pieces
00221   //
00222   if (endPoly1.PartialClip( voxelLimit, axis ))
00223   {
00224     static const G4ThreeVector normal(0,0,+1);
00225     endPoly1.SetNormal( transform.TransformAxis(normal) );
00226     extentList.AddSurface( endPoly1 );
00227   }
00228   
00229   if (endPoly2.PartialClip( voxelLimit, axis ))
00230   {
00231     static const G4ThreeVector normal(0,0,-1);
00232     endPoly2.SetNormal( transform.TransformAxis(normal) );
00233     extentList.AddSurface( endPoly2 );
00234   }
00235   
00236   //
00237   // Return min/max value
00238   //
00239   return extentList.GetExtent( min, max );
00240 }

G4double G4EllipticalTube::CheckXY ( const G4double  x,
const G4double  y 
) const [inline, protected]

Definition at line 89 of file G4EllipticalTube.icc.

References dx, and dy.

00090 {
00091   G4double rx = x/dx, ry = y/dy;
00092   return rx*rx + ry*ry;
00093 }

G4double G4EllipticalTube::CheckXY ( const G4double  x,
const G4double  y,
const G4double  toler 
) const [inline, protected]

Definition at line 80 of file G4EllipticalTube.icc.

References dx, and dy.

Referenced by DistanceToIn(), DistanceToOut(), Inside(), and SurfaceNormal().

00083 {
00084   G4double rx = x/(dx+toler), ry = y/(dy+toler);
00085   return rx*rx + ry*ry;
00086 }

G4VSolid * G4EllipticalTube::Clone (  )  const [virtual]

Reimplemented from G4VSolid.

Definition at line 858 of file G4EllipticalTube.cc.

References G4EllipticalTube().

00859 {
00860   return new G4EllipticalTube(*this);
00861 }

G4Polyhedron * G4EllipticalTube::CreatePolyhedron (  )  const [virtual]

Reimplemented from G4VSolid.

Definition at line 961 of file G4EllipticalTube.cc.

References dx, and dz.

Referenced by GetPolyhedron().

00962 {
00963   // create cylinder with radius=1...
00964   //
00965   G4Polyhedron* eTube = new G4PolyhedronTube(0.,1.,dz);
00966 
00967   // apply non-uniform scaling...
00968   //
00969   eTube->Transform(G4Scale3D(dx,dy,1.));
00970   return  eTube;
00971 }

void G4EllipticalTube::DescribeYourselfTo ( G4VGraphicsScene scene  )  const [virtual]

Implements G4VSolid.

Definition at line 993 of file G4EllipticalTube.cc.

References G4VGraphicsScene::AddSolid().

00994 {
00995   scene.AddSolid (*this);
00996 }

G4double G4EllipticalTube::DistanceToIn ( const G4ThreeVector p  )  const [virtual]

Implements G4VSolid.

Definition at line 525 of file G4EllipticalTube.cc.

References CheckXY(), DBL_MIN, dx, dz, and G4VSolid::kCarTolerance.

00526 {
00527   static const G4double halfTol = 0.5*kCarTolerance;
00528   
00529   if (CheckXY( p.x(), p.y(), +halfTol ) < 1.0)
00530   {
00531     //
00532     // We are inside or on the surface of the
00533     // elliptical cross section in x/y. Check z
00534     //
00535     if (p.z() < -dz-halfTol) 
00536       return -p.z()-dz;
00537     else if (p.z() > dz+halfTol)
00538       return p.z()-dz;
00539     else
00540       return 0;    // On any surface here (or inside)
00541   }
00542   
00543   //
00544   // Find point on ellipse
00545   //
00546   G4double qnorm = CheckXY( p.x(), p.y() );
00547   if (qnorm < DBL_MIN) return 0;  // This should never happen
00548   
00549   G4double q = 1.0/std::sqrt(qnorm);
00550   
00551   G4double xe = q*p.x(), ye = q*p.y();
00552      
00553   //
00554   // Get tangent to ellipse
00555   //
00556   G4double tx = -ye*dx*dx, ty = +xe*dy*dy;
00557   G4double tnorm = std::sqrt( tx*tx + ty*ty );
00558   
00559   //
00560   // Calculate distance
00561   //
00562   G4double distR = ( (p.x()-xe)*ty - (p.y()-ye)*tx )/tnorm;
00563   
00564   //
00565   // Add the result in quadrature if we are, in addition,
00566   // outside the z bounds of the shape
00567   //
00568   // We could save some time by returning the maximum rather
00569   // than the quadrature sum
00570   //
00571   if (p.z() < -dz) 
00572     return std::sqrt( (p.z()+dz)*(p.z()+dz) + distR*distR );
00573   else if (p.z() > dz)
00574     return std::sqrt( (p.z()-dz)*(p.z()-dz) + distR*distR );
00575 
00576   return distR;
00577 }

G4double G4EllipticalTube::DistanceToIn ( const G4ThreeVector p,
const G4ThreeVector v 
) const [virtual]

Implements G4VSolid.

Definition at line 367 of file G4EllipticalTube.cc.

References CheckXY(), dx, dz, IntersectXY(), G4VSolid::kCarTolerance, and CLHEP::detail::n.

00369 {
00370   static const G4double halfTol = 0.5*kCarTolerance;
00371     
00372   //
00373   // Check z = -dz planer surface
00374   //
00375   G4double sigz = p.z()+dz;
00376 
00377   if (sigz < halfTol)
00378   {
00379     //
00380     // We are "behind" the shape in z, and so can
00381     // potentially hit the rear face. Correct direction?
00382     //
00383     if (v.z() <= 0)
00384     {
00385       //
00386       // As long as we are far enough away, we know we
00387       // can't intersect
00388       //
00389       if (sigz < 0) return kInfinity;
00390       
00391       //
00392       // Otherwise, we don't intersect unless we are
00393       // on the surface of the ellipse
00394       //
00395       if (CheckXY(p.x(),p.y(),-halfTol) <= 1.0) return kInfinity;
00396     }
00397     else
00398     {
00399       //
00400       // How far?
00401       //
00402       G4double q = -sigz/v.z();
00403       
00404       //
00405       // Where does that place us?
00406       //
00407       G4double xi = p.x() + q*v.x(),
00408                yi = p.y() + q*v.y();
00409       
00410       //
00411       // Is this on the surface (within ellipse)?
00412       //
00413       if (CheckXY(xi,yi) <= 1.0)
00414       {
00415         //
00416         // Yup. Return q, unless we are on the surface
00417         //
00418         return (sigz < -halfTol) ? q : 0;
00419       }
00420       else if (xi*dy*dy*v.x() + yi*dx*dx*v.y() >= 0)
00421       {
00422         //
00423         // Else, if we are traveling outwards, we know
00424         // we must miss
00425         //
00426         return kInfinity;
00427       }
00428     }
00429   }
00430 
00431   //
00432   // Check z = +dz planer surface
00433   //
00434   sigz = p.z() - dz;
00435   
00436   if (sigz > -halfTol)
00437   {
00438     if (v.z() >= 0)
00439     {
00440       if (sigz > 0) return kInfinity;
00441       if (CheckXY(p.x(),p.y(),-halfTol) <= 1.0) return kInfinity;
00442     }
00443     else {
00444       G4double q = -sigz/v.z();
00445 
00446       G4double xi = p.x() + q*v.x(),
00447                yi = p.y() + q*v.y();
00448       
00449       if (CheckXY(xi,yi) <= 1.0)
00450       {
00451         return (sigz > -halfTol) ? q : 0;
00452       }
00453       else if (xi*dy*dy*v.x() + yi*dx*dx*v.y() >= 0)
00454       {
00455         return kInfinity;
00456       }
00457     }
00458   }
00459   
00460   //
00461   // Check intersection with the elliptical tube
00462   //
00463   G4double q[2];
00464   G4int n = IntersectXY( p, v, q );
00465   
00466   if (n==0) return kInfinity;
00467   
00468   //
00469   // Is the original point on the surface?
00470   //
00471   if (std::fabs(p.z()) < dz+halfTol) {
00472     if (CheckXY( p.x(), p.y(), halfTol ) < 1.0)
00473     {
00474       //
00475       // Well, yes, but are we traveling inwards at this point?
00476       //
00477       if (p.x()*dy*dy*v.x() + p.y()*dx*dx*v.y() < 0) return 0;
00478     }
00479   }
00480   
00481   //
00482   // We are now certain that point p is not on the surface of 
00483   // the solid (and thus std::fabs(q[0]) > halfTol). 
00484   // Return kInfinity if the intersection is "behind" the point.
00485   //
00486   if (q[0] < 0) return kInfinity;
00487   
00488   //
00489   // Check to see if we intersect the tube within
00490   // dz, but only when we know it might miss
00491   //
00492   G4double zi = p.z() + q[0]*v.z();
00493 
00494   if (v.z() < 0)
00495   {
00496     if (zi < -dz) return kInfinity;
00497   }
00498   else if (v.z() > 0)
00499   {
00500     if (zi > +dz) return kInfinity;
00501   }
00502 
00503   return q[0];
00504 }

G4double G4EllipticalTube::DistanceToOut ( const G4ThreeVector p  )  const [virtual]

Implements G4VSolid.

Definition at line 729 of file G4EllipticalTube.cc.

References DBL_MIN, dx, dz, and G4VSolid::kCarTolerance.

00730 {
00731   static const G4double halfTol = 0.5*kCarTolerance;
00732   
00733   //
00734   // We need to calculate the distances to all surfaces,
00735   // and then return the smallest
00736   //
00737   // Check -dz and +dz surface
00738   //
00739   G4double sBest = dz - std::fabs(p.z());
00740   if (sBest < halfTol) return 0;
00741   
00742   //
00743   // Check elliptical surface: find intersection of
00744   // line through p and parallel to x axis
00745   //
00746   G4double radical = 1.0 - p.y()*p.y()/dy/dy;
00747   if (radical < +DBL_MIN) return 0;
00748   
00749   G4double xi = dx*std::sqrt( radical );
00750   if (p.x() < 0) xi = -xi;
00751   
00752   //
00753   // Do the same with y axis
00754   //
00755   radical = 1.0 - p.x()*p.x()/dx/dx;
00756   if (radical < +DBL_MIN) return 0;
00757   
00758   G4double yi = dy*std::sqrt( radical );
00759   if (p.y() < 0) yi = -yi;
00760   
00761   //
00762   // Get distance from p to the line connecting
00763   // these two points
00764   //
00765   G4double xdi = p.x() - xi,
00766      ydi = yi - p.y();
00767 
00768   G4double normi = std::sqrt( xdi*xdi + ydi*ydi );
00769   if (normi < halfTol) return 0;
00770   xdi /= normi;
00771   ydi /= normi;
00772   
00773   G4double q = 0.5*(xdi*(p.y()-yi) - ydi*(p.x()-xi));
00774   if (xi*yi < 0) q = -q;
00775   
00776   if (q < sBest) sBest = q;
00777   
00778   //
00779   // Return best answer
00780   //
00781   return sBest < halfTol ? 0 : sBest;
00782 }

G4double G4EllipticalTube::DistanceToOut ( const G4ThreeVector p,
const G4ThreeVector v,
const G4bool  calcNorm = false,
G4bool validNorm = 0,
G4ThreeVector n = 0 
) const [virtual]

Implements G4VSolid.

Definition at line 588 of file G4EllipticalTube.cc.

References CheckXY(), G4VSolid::DumpInfo(), dx, dz, G4endl, G4Exception(), IntersectXY(), JustWarning, G4VSolid::kCarTolerance, and CLHEP::detail::n.

00593 {
00594   static const G4double halfTol = 0.5*kCarTolerance;
00595   
00596   //
00597   // Our normal is always valid
00598   //
00599   if (calcNorm)  { *validNorm = true; }
00600   
00601   G4double sBest = kInfinity;
00602   G4ThreeVector nBest(0,0,0);
00603   
00604   //
00605   // Might we intersect the -dz surface?
00606   //
00607   if (v.z() < 0)
00608   {
00609     static const G4ThreeVector normHere(0.0,0.0,-1.0);
00610     //
00611     // Yup. What distance?
00612     //
00613     sBest = -(p.z()+dz)/v.z();
00614     
00615     //
00616     // Are we on the surface? If so, return zero
00617     //
00618     if (p.z() < -dz+halfTol)
00619     {
00620       if (calcNorm)  { *norm = normHere; }
00621       return 0;
00622     }
00623     else
00624     {
00625       nBest = normHere;
00626     }
00627   }
00628   
00629   //
00630   // How about the +dz surface?
00631   //
00632   if (v.z() > 0)
00633   {
00634     static const G4ThreeVector normHere(0.0,0.0,+1.0);
00635     //
00636     // Yup. What distance?
00637     //
00638     G4double q = (dz-p.z())/v.z();
00639     
00640     //
00641     // Are we on the surface? If so, return zero
00642     //
00643     if (p.z() > +dz-halfTol)
00644     {
00645       if (calcNorm)  { *norm = normHere; }
00646       return 0;
00647     }
00648     
00649     //
00650     // Best so far?
00651     //
00652     if (q < sBest) { sBest = q; nBest = normHere; }
00653   }
00654   
00655   //
00656   // Check furthest intersection with ellipse 
00657   //
00658   G4double q[2];
00659   G4int n = IntersectXY( p, v, q );
00660 
00661   if (n == 0)
00662   {
00663     if (sBest == kInfinity)
00664     {
00665       DumpInfo();
00666       std::ostringstream message;
00667       G4int oldprc = message.precision(16) ;
00668       message << "Point p is outside !?" << G4endl
00669               << "Position:"  << G4endl
00670               << "   p.x() = "   << p.x()/mm << " mm" << G4endl
00671               << "   p.y() = "   << p.y()/mm << " mm" << G4endl
00672               << "   p.z() = "   << p.z()/mm << " mm" << G4endl
00673               << "Direction:" << G4endl << G4endl
00674               << "   v.x() = "   << v.x() << G4endl
00675               << "   v.y() = "   << v.y() << G4endl
00676               << "   v.z() = "   << v.z() << G4endl
00677               << "Proposed distance :" << G4endl
00678               << "   snxt = "    << sBest/mm << " mm";
00679       message.precision(oldprc) ;
00680       G4Exception( "G4EllipticalTube::DistanceToOut(p,v,...)",
00681                    "GeomSolids1002", JustWarning, message);
00682     }
00683     if (calcNorm)  { *norm = nBest; }
00684     return sBest;
00685   }
00686   else if (q[n-1] > sBest)
00687   {
00688     if (calcNorm)  { *norm = nBest; }
00689     return sBest;
00690   }  
00691   sBest = q[n-1];
00692       
00693   //
00694   // Intersection with ellipse. Get normal at intersection point.
00695   //
00696   if (calcNorm)
00697   {
00698     G4ThreeVector ip = p + sBest*v;
00699     *norm = G4ThreeVector( ip.x()*dy*dy, ip.y()*dx*dx, 0.0 ).unit();
00700   }
00701   
00702   //
00703   // Do we start on the surface?
00704   //
00705   if (CheckXY( p.x(), p.y(), -halfTol ) > 1.0)
00706   {
00707     //
00708     // Well, yes, but are we traveling outwards at this point?
00709     //
00710     if (p.x()*dy*dy*v.x() + p.y()*dx*dx*v.y() > 0) return 0;
00711   }
00712   
00713   return sBest;
00714 }

G4double G4EllipticalTube::GetCubicVolume (  )  [virtual]

Reimplemented from G4VSolid.

Definition at line 867 of file G4EllipticalTube.cc.

References G4VSolid::GetCubicVolume().

00868 {
00869   if(fCubicVolume != 0.) {;}
00870     else { fCubicVolume = G4VSolid::GetCubicVolume(); }
00871   return fCubicVolume;
00872 }

G4double G4EllipticalTube::GetDx (  )  const [inline]

Definition at line 38 of file G4EllipticalTube.icc.

References dx.

Referenced by G4GDMLWriteSolids::EltubeWrite(), and G4tgbGeometryDumper::GetSolidParams().

00039 {
00040   return dx;
00041 }

G4double G4EllipticalTube::GetDy (  )  const [inline]

Definition at line 44 of file G4EllipticalTube.icc.

References dy.

Referenced by G4GDMLWriteSolids::EltubeWrite(), and G4tgbGeometryDumper::GetSolidParams().

00045 {
00046   return dy;
00047 }

G4double G4EllipticalTube::GetDz (  )  const [inline]

Definition at line 50 of file G4EllipticalTube.icc.

References dz.

Referenced by G4GDMLWriteSolids::EltubeWrite(), and G4tgbGeometryDumper::GetSolidParams().

00051 {
00052   return dz;
00053 }

G4GeometryType G4EllipticalTube::GetEntityType (  )  const [virtual]

Implements G4VSolid.

Definition at line 849 of file G4EllipticalTube.cc.

00850 {
00851   return G4String("G4EllipticalTube");
00852 }

G4VisExtent G4EllipticalTube::GetExtent (  )  const [virtual]

Reimplemented from G4VSolid.

Definition at line 1002 of file G4EllipticalTube.cc.

References dx, and dz.

01003 {
01004   return G4VisExtent( -dx, dx, -dy, dy, -dz, dz );
01005 }

G4ThreeVector G4EllipticalTube::GetPointOnSurface (  )  const [virtual]

Reimplemented from G4VSolid.

Definition at line 911 of file G4EllipticalTube.cc.

References dx, dz, G4INCL::Math::pi, and sqr().

00912 {
00913   G4double xRand, yRand, zRand, phi, cosphi, sinphi, zArea, cArea,p, chose;
00914 
00915   phi    = RandFlat::shoot(0., 2.*pi);
00916   cosphi = std::cos(phi);
00917   sinphi = std::sin(phi);
00918   
00919   // the ellipse perimeter from: "http://mathworld.wolfram.com/Ellipse.html"
00920   //   m = (dx - dy)/(dx + dy);
00921   //   k = 1.+1./4.*m*m+1./64.*sqr(m)*sqr(m)+1./256.*sqr(m)*sqr(m)*sqr(m);
00922   //   p = pi*(a+b)*k;
00923 
00924   // perimeter below from "http://www.efunda.com/math/areas/EllipseGen.cfm"
00925 
00926   p = 2.*pi*std::sqrt(0.5*(dx*dx+dy*dy));
00927 
00928   cArea = 2.*dz*p;
00929   zArea = pi*dx*dy;
00930 
00931   xRand = dx*cosphi;
00932   yRand = dy*sinphi;
00933   zRand = RandFlat::shoot(dz, -1.*dz);
00934     
00935   chose = RandFlat::shoot(0.,2.*zArea+cArea);
00936   
00937   if( (chose>=0) && (chose < cArea) )
00938   {
00939     return G4ThreeVector (xRand,yRand,zRand);
00940   }
00941   else if( (chose >= cArea) && (chose < cArea + zArea) )
00942   {
00943     xRand = RandFlat::shoot(-1.*dx,dx);
00944     yRand = std::sqrt(1.-sqr(xRand/dx));
00945     yRand = RandFlat::shoot(-1.*yRand, yRand);
00946     return G4ThreeVector (xRand,yRand,dz); 
00947   }
00948   else
00949   { 
00950     xRand = RandFlat::shoot(-1.*dx,dx);
00951     yRand = std::sqrt(1.-sqr(xRand/dx));
00952     yRand = RandFlat::shoot(-1.*yRand, yRand);
00953     return G4ThreeVector (xRand,yRand,-1.*dz);
00954   }
00955 }

G4Polyhedron * G4EllipticalTube::GetPolyhedron (  )  const [virtual]

Reimplemented from G4VSolid.

Definition at line 977 of file G4EllipticalTube.cc.

References CreatePolyhedron(), and G4Polyhedron::GetNumberOfRotationStepsAtTimeOfCreation().

00978 {
00979   if (!fpPolyhedron ||
00980       fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
00981       fpPolyhedron->GetNumberOfRotationSteps())
00982     {
00983       delete fpPolyhedron;
00984       fpPolyhedron = CreatePolyhedron();
00985     }
00986   return fpPolyhedron;
00987 }

G4double G4EllipticalTube::GetSurfaceArea (  )  [virtual]

Reimplemented from G4VSolid.

Definition at line 877 of file G4EllipticalTube.cc.

References G4VSolid::GetSurfaceArea().

00878 {
00879   if(fSurfaceArea != 0.) {;}
00880   else   { fSurfaceArea = G4VSolid::GetSurfaceArea(); }
00881   return fSurfaceArea;
00882 }

EInside G4EllipticalTube::Inside ( const G4ThreeVector p  )  const [virtual]

Implements G4VSolid.

Definition at line 250 of file G4EllipticalTube.cc.

References CheckXY(), dz, G4VSolid::kCarTolerance, kInside, kOutside, and kSurface.

00251 {
00252   static const G4double halfTol = 0.5*kCarTolerance;
00253   
00254   //
00255   // Check z extents: are we outside?
00256   //
00257   G4double absZ = std::fabs(p.z());
00258   if (absZ > dz+halfTol) return kOutside;
00259   
00260   //
00261   // Check x,y: are we outside?
00262   //
00263   // G4double x = p.x(), y = p.y();
00264   
00265   if (CheckXY(p.x(), p.y(), +halfTol) > 1.0) return kOutside;
00266   
00267   //
00268   // We are either inside or on the surface: recheck z extents
00269   //
00270   if (absZ > dz-halfTol) return kSurface;
00271   
00272   //
00273   // Recheck x,y
00274   //
00275   if (CheckXY(p.x(), p.y(), -halfTol) > 1.0) return kSurface;
00276   
00277   return kInside;
00278 }

G4int G4EllipticalTube::IntersectXY ( const G4ThreeVector p,
const G4ThreeVector v,
G4double  s[2] 
) const [protected]

Definition at line 810 of file G4EllipticalTube.cc.

References DBL_MIN, and dx.

Referenced by DistanceToIn(), and DistanceToOut().

00813 {
00814   G4double px = p.x(), py = p.y();
00815   G4double vx = v.x(), vy = v.y();
00816   
00817   G4double a = (vx/dx)*(vx/dx) + (vy/dy)*(vy/dy);
00818   G4double b = 2.0*( px*vx/dx/dx + py*vy/dy/dy );
00819   G4double c = (px/dx)*(px/dx) + (py/dy)*(py/dy) - 1.0;
00820   
00821   if (a < DBL_MIN) return 0;      // Trajectory parallel to z axis
00822   
00823   G4double radical = b*b - 4*a*c;
00824   
00825   if (radical < -DBL_MIN) return 0;    // No solution
00826   
00827   if (radical < DBL_MIN)
00828   {
00829     //
00830     // Grazes surface
00831     //
00832     ss[0] = -b/a/2.0;
00833     return 1;
00834   }
00835   
00836   radical = std::sqrt(radical);
00837   
00838   G4double q = -0.5*( b + (b < 0 ? -radical : +radical) );
00839   G4double sa = q/a;
00840   G4double sb = c/q;    
00841   if (sa < sb) { ss[0] = sa; ss[1] = sb; } else { ss[0] = sb; ss[1] = sa; }
00842   return 2;
00843 }

G4EllipticalTube & G4EllipticalTube::operator= ( const G4EllipticalTube rhs  ) 

Definition at line 106 of file G4EllipticalTube.cc.

References dx, dy, dz, fCubicVolume, fSurfaceArea, and G4VSolid::operator=().

00107 {
00108    // Check assignment to self
00109    //
00110    if (this == &rhs)  { return *this; }
00111 
00112    // Copy base class data
00113    //
00114    G4VSolid::operator=(rhs);
00115 
00116    // Copy data
00117    //
00118    dx = rhs.dx; dy = rhs.dy; dz = rhs.dz;
00119    fCubicVolume = rhs.fCubicVolume; fSurfaceArea = rhs.fSurfaceArea;
00120    fpPolyhedron = 0;
00121 
00122    return *this;
00123 }

void G4EllipticalTube::SetDx ( const G4double  newDx  )  [inline]

Definition at line 56 of file G4EllipticalTube.icc.

References dx.

00057 {
00058   dx = newDx;
00059   fCubicVolume = 0.;
00060   fpPolyhedron = 0;
00061 }

void G4EllipticalTube::SetDy ( const G4double  newDy  )  [inline]

Definition at line 64 of file G4EllipticalTube.icc.

References dy.

00065 {
00066   dy = newDy;
00067   fCubicVolume = 0.;
00068   fpPolyhedron = 0;
00069 }

void G4EllipticalTube::SetDz ( const G4double  newDz  )  [inline]

Definition at line 72 of file G4EllipticalTube.icc.

References dz.

00073 {
00074   dz = newDz;
00075   fCubicVolume = 0.;
00076   fpPolyhedron = 0;
00077 }

std::ostream & G4EllipticalTube::StreamInfo ( std::ostream &  os  )  const [virtual]

Implements G4VSolid.

Definition at line 887 of file G4EllipticalTube.cc.

References dx, dz, and G4VSolid::GetName().

00888 {
00889   G4int oldprc = os.precision(16);
00890   os << "-----------------------------------------------------------\n"
00891      << "    *** Dump for solid - " << GetName() << " ***\n"
00892      << "    ===================================================\n"
00893      << " Solid type: G4EllipticalTube\n"
00894      << " Parameters: \n"
00895      << "    length Z: " << dz/mm << " mm \n"
00896      << "    surface equation in X and Y: \n"
00897      << "       (X / " << dx << ")^2 + (Y / " << dy << ")^2 = 1 \n"
00898      << "-----------------------------------------------------------\n";
00899   os.precision(oldprc);
00900 
00901   return os;
00902 }

G4ThreeVector G4EllipticalTube::SurfaceNormal ( const G4ThreeVector p  )  const [virtual]

Implements G4VSolid.

Definition at line 284 of file G4EllipticalTube.cc.

References CheckXY(), dx, dy, dz, G4Exception(), JustWarning, and G4VSolid::kCarTolerance.

00285 {
00286   //
00287   // SurfaceNormal for the point On the Surface, sum the normals on the Corners
00288   //
00289   static const G4double halfTol = 0.5*kCarTolerance;
00290 
00291   G4int noSurfaces=0;
00292   G4ThreeVector norm, sumnorm(0.,0.,0.);
00293 
00294   G4double distZ = std::fabs(std::fabs(p.z()) - dz);
00295   
00296   G4double distR1 = CheckXY( p.x(), p.y(),+ halfTol );
00297   G4double distR2 = CheckXY( p.x(), p.y(),- halfTol );
00298  
00299   if (  (distZ  < halfTol ) && ( distR1 <= 1 ) )
00300   {
00301     noSurfaces++;
00302     sumnorm=G4ThreeVector( 0.0, 0.0, p.z() < 0 ? -1.0 : 1.0 );
00303   }
00304   if( (distR1 <= 1 ) && ( distR2 >= 1 ) )
00305   {
00306     noSurfaces++;
00307     norm= G4ThreeVector( p.x()*dy*dy, p.y()*dx*dx, 0.0 ).unit();
00308     sumnorm+=norm;
00309   }
00310   if ( noSurfaces == 0 )
00311   {
00312 #ifdef G4SPECSDEBUG
00313     G4Exception("G4EllipticalTube::SurfaceNormal(p)", "GeomSolids1002",
00314                 JustWarning, "Point p is not on surface !?" );
00315 #endif 
00316     norm = ApproxSurfaceNormal(p);
00317   }
00318   else if ( noSurfaces == 1 )  { norm = sumnorm; }
00319   else                         { norm = sumnorm.unit(); }
00320  
00321   return norm;
00322 }


Field Documentation

G4double G4EllipticalTube::dx [protected]

Definition at line 128 of file G4EllipticalTube.hh.

Referenced by CalculateExtent(), CheckXY(), CreatePolyhedron(), DistanceToIn(), DistanceToOut(), G4EllipticalTube(), GetDx(), GetExtent(), GetPointOnSurface(), IntersectXY(), operator=(), SetDx(), StreamInfo(), and SurfaceNormal().

G4double G4EllipticalTube::dy [protected]

Definition at line 128 of file G4EllipticalTube.hh.

Referenced by CalculateExtent(), CheckXY(), G4EllipticalTube(), GetDy(), operator=(), SetDy(), and SurfaceNormal().

G4double G4EllipticalTube::dz [protected]

Definition at line 128 of file G4EllipticalTube.hh.

Referenced by CalculateExtent(), CreatePolyhedron(), DistanceToIn(), DistanceToOut(), G4EllipticalTube(), GetDz(), GetExtent(), GetPointOnSurface(), Inside(), operator=(), SetDz(), StreamInfo(), and SurfaceNormal().


The documentation for this class was generated from the following files:
Generated on Mon May 27 17:51:52 2013 for Geant4 by  doxygen 1.4.7