57 using namespace CLHEP;
 
   70   : 
G4VSolid(pName), fpPolyhedron(0), fCubicVolume(0.), fSurfaceArea(0.),
 
   71     zBottomCut(0.), zTopCut(0.)
 
   79   if ( (pxSemiAxis<=0.) || (pySemiAxis<=0.) || (pzSemiAxis<=0.) )
 
   81      std::ostringstream message;
 
   82      message << 
"Invalid semi-axis - " << 
GetName();
 
   83      G4Exception(
"G4Ellipsoid::G4Ellipsoid()", 
"GeomSolids0002",
 
   88   if ( pzBottomCut == 0 && pzTopCut == 0 )
 
   92   else if ( (pzBottomCut < pzSemiAxis) && (pzTopCut > -pzSemiAxis)
 
   93          && (pzBottomCut < pzTopCut) )
 
   99      std::ostringstream message;
 
  100      message << 
"Invalid z-coordinate for cutting plane - " << 
GetName();
 
  101      G4Exception(
"G4Ellipsoid::G4Ellipsoid()", 
"GeomSolids0002",
 
  112   : 
G4VSolid(a), fpPolyhedron(0), kRadTolerance(0.), fCubicVolume(0.),
 
  113     fSurfaceArea(0.), xSemiAxis(0.), ySemiAxis(0.), zSemiAxis(0.),
 
  114     semiAxisMax(0.), zBottomCut(0.), zTopCut(0.)
 
  132     fpPolyhedron(0), kRadTolerance(rhs.kRadTolerance),
 
  133     fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea),
 
  134     xSemiAxis(rhs.xSemiAxis), ySemiAxis(rhs.ySemiAxis),
 
  135     zSemiAxis(rhs.zSemiAxis), semiAxisMax(rhs.semiAxisMax),
 
  136     zBottomCut(rhs.zBottomCut), zTopCut(rhs.zTopCut)
 
  148    if (
this == &rhs)  { 
return *
this; }
 
  157    fCubicVolume = rhs.fCubicVolume; fSurfaceArea = rhs.fSurfaceArea;
 
  158    xSemiAxis = rhs.xSemiAxis; ySemiAxis = rhs.ySemiAxis;
 
  159    zSemiAxis = rhs.zSemiAxis; semiAxisMax = rhs.semiAxisMax;
 
  160    zBottomCut = rhs.zBottomCut; zTopCut = rhs.zTopCut;
 
  190     xMin=xoffset - xSemiAxis;
 
  191     xMax=xoffset + xSemiAxis;
 
  213     yMin=yoffset - ySemiAxis;
 
  214     yMax=yoffset + ySemiAxis;
 
  236     zMin=zoffset + (-zSemiAxis > zBottomCut ? -zSemiAxis : zBottomCut);
 
  237     zMax=zoffset + ( zSemiAxis < zTopCut ? zSemiAxis : zTopCut);
 
  260     xoff = (xoffset < xMin) ? (xMin-xoffset)
 
  261          : (xoffset > xMax) ? (xoffset-xMax) : 0.0;
 
  262     yoff = (yoffset < yMin) ? (yMin-yoffset)
 
  263          : (yoffset > yMax) ? (yoffset-yMax) : 0.0;
 
  285           maxDiff= 1.0-
sqr(yoff/ySemiAxis);
 
  286           if (maxDiff < 0.0) { 
return false; }
 
  287           maxDiff= xSemiAxis * std::sqrt(maxDiff);
 
  288           newMin=xoffset-maxDiff;
 
  289           newMax=xoffset+maxDiff;
 
  290           pMin=(newMin<xMin) ? xMin : newMin;
 
  291           pMax=(newMax>xMax) ? xMax : newMax;
 
  307           maxDiff= 1.0-
sqr(xoff/xSemiAxis);
 
  308           if (maxDiff < 0.0) { 
return false; }
 
  309           maxDiff= ySemiAxis * std::sqrt(maxDiff);
 
  310           newMin=yoffset-maxDiff;
 
  311           newMax=yoffset+maxDiff;
 
  312           pMin=(newMin<yMin) ? yMin : newMin;
 
  313           pMax=(newMax>yMax) ? yMax : newMax;
 
  330     G4int i,j,noEntries,noBetweenSections;
 
  331     G4bool existsAfterClip=
false;
 
  335     G4int noPolygonVertices=0;
 
  342     noEntries=vertices->size(); 
 
  343     noBetweenSections=noEntries-noPolygonVertices;
 
  346     for (i=0;i<noEntries;i+=noPolygonVertices)
 
  348       for(j=0;j<(noPolygonVertices/2)-1;j++)
 
  350         ThetaPolygon.push_back((*vertices)[i+j]);  
 
  351         ThetaPolygon.push_back((*vertices)[i+j+1]);  
 
  352         ThetaPolygon.push_back((*vertices)[i+noPolygonVertices-2-j]);
 
  353         ThetaPolygon.push_back((*vertices)[i+noPolygonVertices-1-j]);
 
  355         ThetaPolygon.clear();
 
  358     for (i=0;i<noBetweenSections;i+=noPolygonVertices)
 
  360       for(j=0;j<noPolygonVertices-1;j++)
 
  362         ThetaPolygon.push_back((*vertices)[i+j]);  
 
  363         ThetaPolygon.push_back((*vertices)[i+j+1]);  
 
  364         ThetaPolygon.push_back((*vertices)[i+noPolygonVertices+j+1]);
 
  365         ThetaPolygon.push_back((*vertices)[i+noPolygonVertices+j]);
 
  367         ThetaPolygon.clear();
 
  369       ThetaPolygon.push_back((*vertices)[i+noPolygonVertices-1]);
 
  370       ThetaPolygon.push_back((*vertices)[i]);
 
  371       ThetaPolygon.push_back((*vertices)[i+noPolygonVertices]);
 
  372       ThetaPolygon.push_back((*vertices)[i+2*noPolygonVertices-1]);
 
  374       ThetaPolygon.clear();
 
  376     if ( (pMin!=kInfinity) || (pMax!=-kInfinity) )
 
  378       existsAfterClip=
true;
 
  400         existsAfterClip=
true;
 
  406     return existsAfterClip;
 
  422   static const G4double halfRadTolerance=kRadTolerance*0.5;
 
  426   if (p.
z() < zBottomCut-halfRadTolerance) { 
return in=
kOutside; }
 
  427   if (p.
z() > zTopCut+halfRadTolerance)    { 
return in=
kOutside; }
 
  429   rad2oo= 
sqr(p.
x()/(xSemiAxis+halfRadTolerance))
 
  430         + 
sqr(p.
y()/(ySemiAxis+halfRadTolerance))
 
  431         + 
sqr(p.
z()/(zSemiAxis+halfRadTolerance));
 
  433   if (rad2oo > 1.0)  { 
return in=
kOutside; }
 
  435   rad2oi= 
sqr(p.
x()*(1.0+halfRadTolerance/xSemiAxis)/xSemiAxis)
 
  436       + 
sqr(p.
y()*(1.0+halfRadTolerance/ySemiAxis)/ySemiAxis)
 
  437       + 
sqr(p.
z()*(1.0+halfRadTolerance/zSemiAxis)/zSemiAxis);
 
  444     in = ( (p.
z() < zBottomCut+halfRadTolerance)
 
  446     if ( rad2oi > 1.0-halfRadTolerance )  { in=
kSurface; }
 
  462   G4double distR, distZBottom, distZTop;
 
  468                      p.
y()/(ySemiAxis*ySemiAxis),
 
  469                      p.
z()/(zSemiAxis*zSemiAxis));
 
  474   distR = std::fabs( (p*norm - 1.0) * radius ) / 2.0;
 
  478   distZBottom = std::fabs( p.
z() - zBottomCut );
 
  479   distZTop = std::fabs( p.
z() - zTopCut );
 
  481   if ( (distZBottom < distR) || (distZTop < distR) )
 
  483     return G4ThreeVector(0.,0.,(distZBottom < distZTop) ? -1.0 : 1.0);
 
  485   return ( norm *= radius );
 
  498   static const G4double halfRadTolerance=kRadTolerance*0.5;
 
  500   G4double distMin = std::min(xSemiAxis,ySemiAxis);
 
  501   const G4double dRmax = 100.*std::min(distMin,zSemiAxis);
 
  505   if (p.
z() <= zBottomCut+halfCarTolerance)
 
  507     if (v.
z() <= 0.0) { 
return distMin; }
 
  508     G4double distZ = (zBottomCut - p.
z()) / v.
z();
 
  510     if ( (distZ > -halfRadTolerance) && (
Inside(p+distZ*v) != 
kOutside) )
 
  513       if ( std::fabs(distZ) < halfRadTolerance ) { distZ=0.; }
 
  514       return distMin= distZ;
 
  517   if (p.
z() >= zTopCut-halfCarTolerance)
 
  519     if (v.
z() >= 0.0) { 
return distMin;}
 
  521     if ( (distZ > -halfRadTolerance) && (
Inside(p+distZ*v) != 
kOutside) )
 
  524       if ( std::fabs(distZ) < halfRadTolerance ) { distZ=0.; }
 
  525       return distMin= distZ;
 
  533   A= 
sqr(v.
x()/xSemiAxis) + 
sqr(v.
y()/ySemiAxis) + 
sqr(v.
z()/zSemiAxis);
 
  534   C= 
sqr(p.
x()/xSemiAxis) + 
sqr(p.
y()/ySemiAxis) + 
sqr(p.
z()/zSemiAxis) - 1.0;
 
  535   B= 2.0 * ( p.
x()*v.
x()/(xSemiAxis*xSemiAxis)
 
  536            + p.
y()*v.
y()/(ySemiAxis*ySemiAxis)
 
  537            + p.
z()*v.
z()/(zSemiAxis*zSemiAxis) );
 
  542     G4double distR= (-B - std::sqrt(C)) / (2.0*A);
 
  544     if ( (distR > halfRadTolerance)
 
  545       && (intZ >= zBottomCut-halfRadTolerance)
 
  546       && (intZ <= zTopCut+halfRadTolerance) )
 
  550     else if( (distR >- halfRadTolerance)
 
  551         && (intZ >= zBottomCut-halfRadTolerance)
 
  552         && (intZ <= zTopCut+halfRadTolerance) )
 
  558       distR = (-B + std::sqrt(C) ) / (2.0*A);
 
  559       if(distR>0.) { distMin=0.; }
 
  563       distR= (-B + std::sqrt(C)) / (2.0*A);
 
  564       intZ = p.
z()+distR*v.
z();
 
  565       if ( (distR > halfRadTolerance)
 
  566         && (intZ >= zBottomCut-halfRadTolerance)
 
  567         && (intZ <= zTopCut+halfRadTolerance) )
 
  570         if (norm.
dot(v)<0.) { distMin = distR; }
 
  573     if ( (distMin!=kInfinity) && (distMin>dRmax) ) 
 
  576       G4double fTerm = distMin-std::fmod(distMin,dRmax);
 
  581   if (std::fabs(distMin)<halfRadTolerance) { distMin=0.; }
 
  597                      p.
y()/(ySemiAxis*ySemiAxis),
 
  598                      p.
z()/(zSemiAxis*zSemiAxis));
 
  603   distR= (p*norm - 1.0) * radius / 2.0;
 
  607   distZ= zBottomCut - p.
z();
 
  610     distZ = p.
z() - zTopCut;
 
  617     return (distR < 0.0) ? 0.0 : distR;
 
  619   else if (distR < 0.0)
 
  625     return (distZ < distR) ? distZ : distR;
 
  640   enum surface_e {kPlaneSurf, kCurvedSurf, kNoSurf} surface;
 
  649     G4double distZ = (zBottomCut - p.
z()) / v.
z();
 
  653       if (!calcNorm) {
return 0.0;}
 
  664       if (!calcNorm) {
return 0.0;}
 
  673                          p.
y()/(ySemiAxis*ySemiAxis),
 
  674                          p.
z()/(zSemiAxis*zSemiAxis));
 
  680   A= 
sqr(v.
x()/xSemiAxis) + 
sqr(v.
y()/ySemiAxis) + 
sqr(v.
z()/zSemiAxis);
 
  681   C= (p * nearnorm) - 1.0;
 
  682   B= 2.0 * (v * nearnorm);
 
  687     G4double distR= (-B + std::sqrt(C) ) / (2.0*A);
 
  691       if (!calcNorm) {
return 0.0;}
 
  696       surface= kCurvedSurf;
 
  704     if (surface == kNoSurf)
 
  720                                  pexit.
y()/(ySemiAxis*ySemiAxis),
 
  721                                  pexit.
z()/(zSemiAxis*zSemiAxis));
 
  722           truenorm *= 1.0/truenorm.
mag();
 
  727           std::ostringstream message;
 
  728           G4int oldprc = message.precision(16);
 
  729           message << 
"Undefined side for valid surface normal to solid." 
  732                   << 
"   p.x() = "   << p.
x()/
mm << 
" mm" << 
G4endl 
  733                   << 
"   p.y() = "   << p.
y()/
mm << 
" mm" << 
G4endl 
  734                   << 
"   p.z() = "   << p.
z()/
mm << 
" mm" << 
G4endl 
  736                   << 
"   v.x() = "   << v.
x() << 
G4endl 
  737                   << 
"   v.y() = "   << v.
y() << 
G4endl 
  738                   << 
"   v.z() = "   << v.
z() << 
G4endl 
  739                   << 
"Proposed distance :" << 
G4endl 
  740                   << 
"   distMin = "    << distMin/
mm << 
" mm";
 
  741           message.precision(oldprc);
 
  764      std::ostringstream message;
 
  765      G4int oldprc = message.precision(16);
 
  766      message << 
"Point p is outside !?" << 
G4endl 
  768              << 
"   p.x() = "   << p.
x()/
mm << 
" mm" << 
G4endl 
  769              << 
"   p.y() = "   << p.
y()/
mm << 
" mm" << 
G4endl 
  770              << 
"   p.z() = "   << p.
z()/
mm << 
" mm";
 
  771      message.precision(oldprc) ;
 
  772      G4Exception(
"G4Ellipsoid::DistanceToOut(p)", 
"GeomSolids1002",
 
  780                      p.
y()/(ySemiAxis*ySemiAxis),
 
  781                      p.
z()/(zSemiAxis*zSemiAxis));
 
  787   if ( (tmp > 0.0) && (1.0 < radius*tmp) ) {radius = 1.0/
tmp;}
 
  791   distR = (1.0 - p*
norm) * radius / 2.0;
 
  795   distZ = p.
z() - zBottomCut;
 
  796   if (distZ < 0.0) {distZ= zTopCut - p.
z();}
 
  800   if ( (distZ < 0.0) || (distR < 0.0) )
 
  806     return (distZ < distR) ? distZ : distR;
 
  823                                          G4int& noPolygonVertices)
 const 
  827   G4double meshAnglePhi, meshRMaxFactor,
 
  828            crossAnglePhi, coscrossAnglePhi, sincrossAnglePhi, sAnglePhi;
 
  829   G4double meshTheta, crossTheta, startTheta;
 
  830   G4double rMaxX, rMaxY, rMaxZ, rMaxMax, rx, ry, rz;
 
  831   G4int crossSectionPhi, noPhiCrossSections, crossSectionTheta, noThetaSections;
 
  847   meshAnglePhi=
twopi/(noPhiCrossSections-1);
 
  852   sAnglePhi = -meshAnglePhi*0.5;
 
  868   meshTheta= 
pi/(noThetaSections-2);
 
  873   startTheta = -meshTheta*0.5;
 
  875   meshRMaxFactor =  1.0/std::cos(0.5*
 
  876                     std::sqrt(meshAnglePhi*meshAnglePhi+meshTheta*meshTheta));
 
  877   rMaxMax= (xSemiAxis > ySemiAxis ? xSemiAxis : ySemiAxis);
 
  878   if (zSemiAxis > rMaxMax) rMaxMax= zSemiAxis;
 
  879   rMaxX= xSemiAxis + rMaxMax*(meshRMaxFactor-1.0);
 
  880   rMaxY= ySemiAxis + rMaxMax*(meshRMaxFactor-1.0);
 
  881   rMaxZ= zSemiAxis + rMaxMax*(meshRMaxFactor-1.0);
 
  885   if (vertices && cosCrossTheta && sinCrossTheta)
 
  887     for (crossSectionTheta=0; crossSectionTheta<noThetaSections;
 
  892       crossTheta=startTheta+crossSectionTheta*meshTheta;
 
  893       cosCrossTheta[crossSectionTheta]=std::cos(crossTheta);
 
  894       sinCrossTheta[crossSectionTheta]=std::sin(crossTheta);
 
  896     for (crossSectionPhi=0; crossSectionPhi<noPhiCrossSections;
 
  899       crossAnglePhi=sAnglePhi+crossSectionPhi*meshAnglePhi;
 
  900       coscrossAnglePhi=std::cos(crossAnglePhi);
 
  901       sincrossAnglePhi=std::sin(crossAnglePhi);
 
  902       for (crossSectionTheta=0; crossSectionTheta<noThetaSections;
 
  907         rx= sinCrossTheta[crossSectionTheta]*coscrossAnglePhi*rMaxX;
 
  908         ry= sinCrossTheta[crossSectionTheta]*sincrossAnglePhi*rMaxY;
 
  909         rz= cosCrossTheta[crossSectionTheta]*rMaxZ;
 
  918     noPolygonVertices = noThetaSections ;
 
  923     G4Exception(
"G4Ellipsoid::CreateRotatedVertices()",
 
  925                 "Error in allocation of vertices. Out of memory !");
 
  928   delete[] cosCrossTheta;
 
  929   delete[] sinCrossTheta;
 
  958   G4int oldprc = os.precision(16);
 
  959   os << 
"-----------------------------------------------------------\n" 
  960      << 
"    *** Dump for solid - " << 
GetName() << 
" ***\n" 
  961      << 
"    ===================================================\n" 
  962      << 
" Solid type: G4Ellipsoid\n" 
  965      << 
"    semi-axis x: " << xSemiAxis/
mm << 
" mm \n" 
  966      << 
"    semi-axis y: " << ySemiAxis/
mm << 
" mm \n" 
  967      << 
"    semi-axis z: " << zSemiAxis/
mm << 
" mm \n" 
  968      << 
"    max semi-axis: " << semiAxisMax/
mm << 
" mm \n" 
  969      << 
"    lower cut plane level z: " << zBottomCut/
mm << 
" mm \n" 
  970      << 
"    upper cut plane level z: " << zTopCut/
mm << 
" mm \n" 
  971      << 
"-----------------------------------------------------------\n";
 
  972   os.precision(oldprc);
 
  983   G4double aTop, aBottom, aCurved, chose, xRand, yRand, zRand, phi;
 
  984   G4double cosphi, sinphi, costheta, sintheta, 
alpha, beta, max1, max2, max3;
 
  986   max1  = xSemiAxis > ySemiAxis ? xSemiAxis : ySemiAxis;
 
  987   max1  = max1 > zSemiAxis ? max1 : zSemiAxis;
 
  988   if (max1 == xSemiAxis)      { max2 = ySemiAxis; max3 = zSemiAxis; }
 
  989   else if (max1 == ySemiAxis) { max2 = xSemiAxis; max3 = zSemiAxis; }
 
  990   else                        { max2 = xSemiAxis; max3 = ySemiAxis; }
 
  992   phi   = RandFlat::shoot(0.,
twopi);
 
  994   cosphi = std::cos(phi);   sinphi = std::sin(phi);
 
  995   costheta = RandFlat::shoot(zBottomCut,zTopCut)/zSemiAxis;
 
  996   sintheta = std::sqrt(1.-
sqr(costheta));
 
  998   alpha = 1.-
sqr(max2/max1); beta  = 1.-
sqr(max3/max1);
 
 1000   aTop    = 
pi*xSemiAxis*ySemiAxis*(1 - 
sqr(zTopCut/zSemiAxis));
 
 1001   aBottom = 
pi*xSemiAxis*ySemiAxis*(1 - 
sqr(zBottomCut/zSemiAxis));
 
 1005   aCurved = 4.*
pi*max1*max2*(1.-1./6.*(alpha+beta)-
 
 1006                             1./120.*(3.*
sqr(alpha)+2.*alpha*beta+3.*
sqr(beta)));
 
 1008   aCurved *= 0.5*(1.2*zTopCut/zSemiAxis - 1.2*zBottomCut/zSemiAxis);
 
 1010   if( ( zTopCut >= zSemiAxis && zBottomCut <= -1.*zSemiAxis )
 
 1011    || ( zTopCut == 0 && zBottomCut ==0 ) )
 
 1013     aTop = 0; aBottom = 0;
 
 1016   chose = RandFlat::shoot(0.,aTop + aBottom + aCurved); 
 
 1020     xRand = xSemiAxis*sintheta*cosphi;
 
 1021     yRand = ySemiAxis*sintheta*sinphi;
 
 1022     zRand = zSemiAxis*costheta;
 
 1025   else if(chose >= aCurved && chose < aCurved + aTop)
 
 1027     xRand = RandFlat::shoot(-1.,1.)*xSemiAxis
 
 1028           * std::sqrt(1-
sqr(zTopCut/zSemiAxis));
 
 1029     yRand = RandFlat::shoot(-1.,1.)*ySemiAxis
 
 1030           * std::sqrt(1.-
sqr(zTopCut/zSemiAxis)-
sqr(xRand/xSemiAxis));
 
 1036     xRand = RandFlat::shoot(-1.,1.)*xSemiAxis
 
 1037           * std::sqrt(1-
sqr(zBottomCut/zSemiAxis));
 
 1038     yRand = RandFlat::shoot(-1.,1.)*ySemiAxis
 
 1039           * std::sqrt(1.-
sqr(zBottomCut/zSemiAxis)-
sqr(xRand/xSemiAxis)); 
 
 1059                       -semiAxisMax, semiAxisMax,
 
 1060                       -semiAxisMax, semiAxisMax);
 
 1067   return new G4NURBSbox(semiAxisMax, semiAxisMax, semiAxisMax);
 
 1073                                    zBottomCut, zTopCut);