62 using namespace CLHEP;
 
   73   : 
G4VSolid(pName), fpPolyhedron(0), fCubicVolume(0.), fSurfaceArea(0.),
 
   81   if ( (pxSemiAxis <= 0.) || (pySemiAxis <= 0.) || (pzMax <= 0.) )
 
   83      std::ostringstream message;
 
   84      message << 
"Invalid semi-axis or height - " << 
GetName();
 
   85      G4Exception(
"G4EllipticalCone::G4EllipticalCone()", 
"GeomSolids0002",
 
   90      std::ostringstream message;
 
   91      message << 
"Invalid z-coordinate for cutting plane - " << 
GetName();
 
   92      G4Exception(
"G4EllipticalCone::G4EllipticalCone()", 
"InvalidSetup",
 
  106   : 
G4VSolid(a), fpPolyhedron(0), kRadTolerance(0.), fCubicVolume(0.),
 
  107     fSurfaceArea(0.), xSemiAxis(0.), ySemiAxis(0.), zheight(0.),
 
  108     semiAxisMax(0.), zTopCut(0.)
 
  126     fpPolyhedron(0), kRadTolerance(rhs.kRadTolerance),
 
  127     fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
 
  128     xSemiAxis(rhs.xSemiAxis), ySemiAxis(rhs.ySemiAxis), zheight(rhs.zheight),
 
  129     semiAxisMax(rhs.semiAxisMax), zTopCut(rhs.zTopCut)
 
  141    if (
this == &rhs)  { 
return *
this; }
 
  150    fCubicVolume = rhs.fCubicVolume; fSurfaceArea = rhs.fSurfaceArea;
 
  151    xSemiAxis = rhs.xSemiAxis; ySemiAxis = rhs.ySemiAxis;
 
  152    zheight = rhs.zheight; semiAxisMax = rhs.semiAxisMax; zTopCut = rhs.zTopCut;
 
  186   G4double rFudge = 1.0/std::cos(0.5*sigPhi);
 
  187   G4double dxFudgeBot = xSemiAxis*2.*zheight*rFudge,
 
  188            dyFudgeBot = ySemiAxis*2.*zheight*rFudge;
 
  189   G4double dxFudgeTop = xSemiAxis*(zheight-zTopCut)*rFudge,
 
  190            dyFudgeTop = ySemiAxis*(zheight-zTopCut)*rFudge;
 
  200            cosPhi = std::cos(phi),
 
  201            sinPhi = std::sin(phi);
 
  202   G4ThreeVector v0( dxFudgeTop*cosPhi, dyFudgeTop*sinPhi, +zTopCut ),
 
  203                 v1( dxFudgeBot*cosPhi, dyFudgeBot*sinPhi, -zTopCut ),
 
  210     if (numPhi == 1) phi = 0;  
 
  211     cosPhi = std::cos(phi), 
 
  212     sinPhi = std::sin(phi);
 
  214     w0 = 
G4ThreeVector( dxFudgeTop*cosPhi, dyFudgeTop*sinPhi, +zTopCut );
 
  215     w1 = 
G4ThreeVector( dxFudgeBot*cosPhi, dyFudgeBot*sinPhi, -zTopCut );
 
  240       phiPoly.
SetNormal( (v1-v0).cross(w0-v0).unit() );
 
  250   } 
while( --numPhi > 0 );
 
  288   static const G4double halfRadTol = 0.5*kRadTolerance;
 
  294   if ( (p.
z() < -zTopCut - halfCarTol)
 
  295     || (p.
z() > zTopCut + halfCarTol ) )
 
  300   rad2oo= 
sqr(p.
x()/( xSemiAxis + halfRadTol ))
 
  301         + 
sqr(p.
y()/( ySemiAxis + halfRadTol ));
 
  303   if ( rad2oo > 
sqr( zheight-p.
z() ) )
 
  310   rad2oi = 
sqr(p.
x()/( xSemiAxis - halfRadTol ))
 
  311         + 
sqr(p.
y()/( ySemiAxis - halfRadTol ));
 
  313   if (rad2oi < 
sqr( zheight-p.
z() ) )
 
  315     in = ( ( p.
z() < -zTopCut + halfRadTol )
 
  334            ry = 
sqr(p.
y()/ySemiAxis);
 
  340   if( (p.
z() < -zTopCut) && ((rx+ry) < 
sqr(zTopCut + zheight)) )
 
  345   if( (p.
z() > (zheight > zTopCut ? zheight : zTopCut)) &&
 
  346       ((rx+ry) < 
sqr(zheight-zTopCut)) )
 
  351   if( p.
z() > rds + 2.*zTopCut - zheight ) 
 
  353     if ( p.
z() > zTopCut )
 
  358         return norm /= norm.
mag();
 
  363         return norm /= norm.
mag();
 
  376                             - ( zheight - zTopCut ) );
 
  379       return norm /= norm.
mag();      
 
  385   if( p.
z() < rds - 2.*zTopCut - zheight )
 
  390       return norm /= norm.
mag();
 
  395       return norm /= norm.
mag();
 
  408                           - ( zheight - zTopCut ) );
 
  411     return norm /= norm.
mag();      
 
  417   G4double c = -zTopCut - k*(zTopCut + zheight);
 
  419   if( p.
z() < -k*rds + 
c )
 
  422   return norm /= norm.
mag();
 
  457       if (sigz < 0) 
return kInfinity;
 
  464       if ( 
sqr(p.
x()/( xSemiAxis - halfTol ))
 
  465          + 
sqr(p.
y()/( ySemiAxis - halfTol )) <= 
sqr( zheight+zTopCut ) )
 
  480                yi = p.
y() + q*v.
y();
 
  485       if ( 
sqr(xi/xSemiAxis) + 
sqr(yi/ySemiAxis) <= 
sqr( zheight + zTopCut ) )
 
  490         return (sigz < -halfTol) ? q : 0;
 
  492       else if (xi/(xSemiAxis*xSemiAxis)*v.
x()
 
  493              + yi/(ySemiAxis*ySemiAxis)*v.
y() >= 0)
 
  507   sigz = p.
z() - zTopCut;
 
  514       if (sigz > 0) 
return kInfinity;
 
  516       if ( 
sqr(p.
x()/( xSemiAxis - halfTol ))
 
  517          + 
sqr(p.
y()/( ySemiAxis - halfTol )) <= 
sqr( zheight-zTopCut ) )
 
  525                yi = p.
y() + q*v.
y();
 
  527       if ( 
sqr(xi/xSemiAxis) + 
sqr(yi/ySemiAxis) <= 
sqr( zheight - zTopCut ) )
 
  529         return (sigz > -halfTol) ? q : 0;
 
  531       else if (xi/(xSemiAxis*xSemiAxis)*v.
x()
 
  532              + yi/(ySemiAxis*ySemiAxis)*v.
y() >= 0)
 
  551     if ( 
sqr((lambda*v.
x()+p.
x())/xSemiAxis) + 
 
  552          sqr((lambda*v.
y()+p.
y())/ySemiAxis) <=
 
  553          sqr(zTopCut + zheight + 0.5*kRadTolerance) ) 
 
  555       return distMin = std::fabs(lambda);    
 
  566     if ( 
sqr((lambda*v.
x() + p.
x())/xSemiAxis) + 
 
  567          sqr((lambda*v.
y() + p.
y())/ySemiAxis) <=
 
  568          sqr(zheight - zTopCut + 0.5*kRadTolerance) )
 
  570         return distMin = std::fabs(lambda);
 
  574   if (p.
z() > zTopCut - halfTol
 
  575    && p.
z() < zTopCut + halfTol )
 
  578       { 
return kInfinity; }
 
  583   if (p.
z() < -zTopCut + halfTol
 
  584    && p.
z() > -zTopCut - halfTol)
 
  587       { 
return distMin = kInfinity; }
 
  599                   v.
y()*p.
y()/
sqr(ySemiAxis) + v.
z()*(zheight-p.
z()));
 
  601                sqr(zheight - p.
z());
 
  607   if ( discr < -halfTol )
 
  612   if ( (discr >= - halfTol ) && (discr < halfTol ) )
 
  614     return distMin = std::fabs(-B/(2.*A)); 
 
  617   G4double plus  = (-B+std::sqrt(discr))/(2.*A);
 
  618   G4double minus = (-B-std::sqrt(discr))/(2.*A);
 
  622   if ( ( std::fabs(plus) < halfTol )||( std::fabs(minus) < halfTol ) )
 
  625                            p.
y()/(ySemiAxis*ySemiAxis),
 
  626                            -( p.
z() - zheight ));
 
  627     if ( truenorm*v >= 0)  
 
  640   if ( minus > halfTol && minus < distMin ) 
 
  648                              pin.
y()/(ySemiAxis*ySemiAxis),
 
  649                              - ( pin.
z() - zheight ));
 
  656   if ( plus > halfTol  && plus < distMin )
 
  664                              pin.
y()/(ySemiAxis*ySemiAxis),
 
  665                              - ( pin.
z() - zheight ) );
 
  672   if (distMin < halfTol) distMin=0.;
 
  683   G4double distR, distR2, distZ, maxDim;
 
  689   if( (p.
z() <= -zTopCut) && (
sqr(p.
x()/xSemiAxis) + 
sqr(p.
y()/ySemiAxis)
 
  693      return distZ = std::fabs(zTopCut + p.
z());
 
  696   if( (p.
z() >= zTopCut) && (
sqr(p.
x()/xSemiAxis)+
sqr(p.
y()/ySemiAxis)
 
  699     return distZ = std::fabs(p.
z() - zTopCut);
 
  706   maxDim = xSemiAxis >= ySemiAxis ? xSemiAxis:ySemiAxis;
 
  707   distRad = std::sqrt(p.
x()*p.
x()+p.
y()*p.
y());
 
  709   if( p.
z() > maxDim*distRad + zTopCut*(1.+maxDim)-
sqr(maxDim)*zheight )
 
  711     distR2 = 
sqr(p.
z() - zTopCut) + 
sqr(distRad - maxDim*(zheight - zTopCut));
 
  712     return std::sqrt( distR2 );
 
  715   if( distRad > maxDim*( zheight - p.
z() ) )
 
  717     if( p.
z() > maxDim*distRad - (zTopCut*(1.+maxDim)+
sqr(maxDim)*zheight) )
 
  719       G4double zVal = (p.
z()-maxDim*(distRad-maxDim*zheight))/(1.+
sqr(maxDim));
 
  720       G4double rVal = maxDim*(zheight - zVal);
 
  721       return distR  = std::sqrt(
sqr(p.
z() - zVal) + 
sqr(distRad - rVal));
 
  725   if( distRad <= maxDim*(zheight - p.
z()) )
 
  727     distR2 = 
sqr(distRad - maxDim*(zheight + zTopCut)) + 
sqr(p.
z() + zTopCut);
 
  728     return std::sqrt( distR2 );    
 
  746   enum surface_e {kPlaneSurf, kCurvedSurf, kNoSurf} surface;
 
  753     lambda = (-p.
z() - zTopCut)/v.
z();
 
  755     if ( (
sqr((p.
x() + lambda*v.
x())/xSemiAxis) + 
 
  756           sqr((p.
y() + lambda*v.
y())/ySemiAxis)) < 
 
  759       distMin = std::fabs(lambda);
 
  761       if (!calcNorm) { 
return distMin; }
 
  763     distMin = std::fabs(lambda);
 
  764     surface = kPlaneSurf;
 
  769     lambda = (zTopCut - p.
z()) / v.
z();
 
  771     if ( (
sqr((p.
x() + lambda*v.
x())/xSemiAxis)
 
  772         + 
sqr((p.
y() + lambda*v.
y())/ySemiAxis) )
 
  775       distMin = std::fabs(lambda);
 
  776       if (!calcNorm) { 
return distMin; }
 
  778     distMin = std::fabs(lambda);
 
  779     surface = kPlaneSurf;
 
  787                    v.
y()*p.
y()/
sqr(ySemiAxis) + v.
z()*(zheight-p.
z()));
 
  789              - 
sqr(zheight - p.
z());
 
  795     if(!calcNorm) { 
return distMin = std::fabs(-B/(2.*A)); }
 
  800     G4double plus  = (-B+std::sqrt(discr))/(2.*A);
 
  801     G4double minus = (-B-std::sqrt(discr))/(2.*A);
 
  807       lambda   = std::fabs(plus) < std::fabs(minus) ? plus : minus;
 
  817     if ( std::fabs(lambda) < distMin )
 
  821         distMin  = std::fabs(lambda);
 
  822         surface  = kCurvedSurf;
 
  827                                p.
y()/(ySemiAxis*ySemiAxis),
 
  828                                -( p.
z() - zheight ));
 
  829         if( truenorm.
dot(v) > 0 )
 
  832           surface  = kCurvedSurf;
 
  842     if (surface == kNoSurf)
 
  861                                   pexit.
y()/(ySemiAxis*ySemiAxis),
 
  862                                   -( pexit.
z() - zheight ) );
 
  863           truenorm /= truenorm.
mag();
 
  870           std::ostringstream message;
 
  871           G4int oldprc = message.precision(16);
 
  872           message << 
"Undefined side for valid surface normal to solid." 
  875                   << 
"   p.x() = "   << p.
x()/
mm << 
" mm" << 
G4endl 
  876                   << 
"   p.y() = "   << p.
y()/
mm << 
" mm" << 
G4endl 
  877                   << 
"   p.z() = "   << p.
z()/
mm << 
" mm" << 
G4endl 
  879                   << 
"   v.x() = "   << v.
x() << 
G4endl 
  880                   << 
"   v.y() = "   << v.
y() << 
G4endl 
  881                   << 
"   v.z() = "   << v.
z() << 
G4endl 
  882                   << 
"Proposed distance :" << 
G4endl 
  883                   << 
"   distMin = "    << distMin/
mm << 
" mm";
 
  884           message.precision(oldprc);
 
  885           G4Exception(
"G4EllipticalCone::DistanceToOut(p,v,..)",
 
  903   G4double rds,roo,roo1, distR, distZ, distMin=0.;
 
  904   G4double minAxis = xSemiAxis < ySemiAxis ? xSemiAxis : ySemiAxis;
 
  910      std::ostringstream message;
 
  911      G4int oldprc = message.precision(16);
 
  912      message << 
"Point p is outside !?" << 
G4endl 
  914              << 
"   p.x() = "   << p.
x()/
mm << 
" mm" << 
G4endl 
  915              << 
"   p.y() = "   << p.
y()/
mm << 
" mm" << 
G4endl 
  916              << 
"   p.z() = "   << p.
z()/
mm << 
" mm";
 
  917      message.precision(oldprc) ;
 
  918      G4Exception(
"G4Ellipsoid::DistanceToOut(p)", 
"GeomSolids1002",
 
  927   if( 
sqr(p.
x()/minAxis)+
sqr(p.
y()/minAxis) < 
sqr(zheight - p.
z()) )
 
  929     rds     = std::sqrt(
sqr(p.
x()) + 
sqr(p.
y()));
 
  930     roo     = minAxis*(zheight-p.
z()); 
 
  931     roo1    = minAxis*(zheight-zTopCut); 
 
  933     distZ=zTopCut - std::fabs(p.
z()) ;
 
  934     distR=(roo-rds)/(std::sqrt(1+
sqr(minAxis)));
 
  938       distMin=(zTopCut-p.
z())*(roo-rds)/(roo-roo1);
 
  939       distMin=std::min(distMin,distR);
 
  941     distMin=std::min(distR,distZ);
 
  953   return G4String(
"G4EllipticalCone");
 
  971   G4int oldprc = os.precision(16);
 
  972   os << 
"-----------------------------------------------------------\n" 
  973      << 
"    *** Dump for solid - " << 
GetName() << 
" ***\n" 
  974      << 
"    ===================================================\n" 
  975      << 
" Solid type: G4EllipticalCone\n" 
  978      << 
"    semi-axis x: " << xSemiAxis/
mm << 
" mm \n" 
  979      << 
"    semi-axis y: " << ySemiAxis/
mm << 
" mm \n" 
  980      << 
"    height    z: " << zheight/
mm << 
" mm \n" 
  981      << 
"    half length in  z: " << zTopCut/
mm << 
" mm \n" 
  982      << 
"-----------------------------------------------------------\n";
 
  983   os.precision(oldprc);
 
  997   G4double phi, sinphi, cosphi, aOne, aTwo, aThree,
 
  998            chose, zRand, rRand1, rRand2;
 
 1001                 + 
sqr(ySemiAxis))*(zheight - zTopCut);
 
 1003                 + 
sqr(ySemiAxis))*(zheight + zTopCut);
 
 1005   aOne   = 
pi*(rOne + rTwo)*std::sqrt(
sqr(rOne - rTwo)+
sqr(2.*zTopCut));
 
 1006   aTwo   = 
pi*xSemiAxis*ySemiAxis*
sqr(zheight+zTopCut);
 
 1007   aThree = 
pi*xSemiAxis*ySemiAxis*
sqr(zheight-zTopCut);  
 
 1009   phi = RandFlat::shoot(0.,
twopi);
 
 1010   cosphi = std::cos(phi);
 
 1011   sinphi = std::sin(phi);
 
 1013   if(zTopCut >= zheight) aThree = 0.;
 
 1015   chose = RandFlat::shoot(0.,aOne+aTwo+aThree);
 
 1016   if((chose>=0.) && (chose<aOne))
 
 1018     zRand = RandFlat::shoot(-zTopCut,zTopCut);
 
 1020                          ySemiAxis*(zheight-zRand)*sinphi,zRand);    
 
 1022   else if((chose>=aOne) && (chose<aOne+aTwo))
 
 1026       rRand1 = RandFlat::shoot(0.,1.) ;
 
 1027       rRand2 = RandFlat::shoot(0.,1.) ;
 
 1028     } 
while ( rRand2 >= rRand1  ) ;
 
 1031     return G4ThreeVector(rRand1*xSemiAxis*(zheight+zTopCut)*cosphi,
 
 1032                          rRand1*ySemiAxis*(zheight+zTopCut)*sinphi, -zTopCut);
 
 1040     rRand1 = RandFlat::shoot(0.,1.) ;
 
 1041     rRand2 = RandFlat::shoot(0.,1.) ;
 
 1042   } 
while ( rRand2 >= rRand1  ) ;
 
 1044   return G4ThreeVector(rRand1*xSemiAxis*(zheight-zTopCut)*cosphi,
 
 1045                        rRand1*ySemiAxis*(zheight-zTopCut)*sinphi, zTopCut);
 
 1062   maxDim = xSemiAxis > ySemiAxis ? xSemiAxis : ySemiAxis;
 
 1063   maxDim = maxDim > zTopCut ? maxDim : zTopCut;
 
 1074   return new G4NURBSbox(xSemiAxis, ySemiAxis,zheight);