G4TwistTubsSide Class Reference

#include <G4TwistTubsSide.hh>

Inheritance diagram for G4TwistTubsSide:

G4VTwistSurface

Public Member Functions

 G4TwistTubsSide (const G4String &name, const G4RotationMatrix &rot, const G4ThreeVector &tlate, G4int handedness, const G4double kappa, const EAxis axis0=kXAxis, const EAxis axis1=kZAxis, G4double axis0min=-kInfinity, G4double axis1min=-kInfinity, G4double axis0max=kInfinity, G4double axis1max=kInfinity)
 G4TwistTubsSide (const G4String &name, G4double EndInnerRadius[2], G4double EndOuterRadius[2], G4double DPhi, G4double EndPhi[2], G4double EndZ[2], G4double InnerRadius, G4double OuterRadius, G4double Kappa, G4int handedness)
virtual ~G4TwistTubsSide ()
virtual G4ThreeVector GetNormal (const G4ThreeVector &xx, G4bool isGlobal=false)
virtual G4int DistanceToSurface (const G4ThreeVector &gp, const G4ThreeVector &gv, G4ThreeVector gxx[], G4double distance[], G4int areacode[], G4bool isvalid[], EValidate validate=kValidateWithTol)
virtual G4int DistanceToSurface (const G4ThreeVector &gp, G4ThreeVector gxx[], G4double distance[], G4int areacode[])
G4ThreeVector ProjectAtPXPZ (const G4ThreeVector &p, G4bool isglobal=false) const
virtual G4ThreeVector SurfacePoint (G4double, G4double, G4bool isGlobal=false)
virtual G4double GetBoundaryMin (G4double phi)
virtual G4double GetBoundaryMax (G4double phi)
virtual G4double GetSurfaceArea ()
virtual void GetFacets (G4int m, G4int n, G4double xyz[][3], G4int faces[][4], G4int iside)
 G4TwistTubsSide (__void__ &)

Detailed Description

Definition at line 52 of file G4TwistTubsSide.hh.


Constructor & Destructor Documentation

G4TwistTubsSide::G4TwistTubsSide ( const G4String name,
const G4RotationMatrix rot,
const G4ThreeVector tlate,
G4int  handedness,
const G4double  kappa,
const EAxis  axis0 = kXAxis,
const EAxis  axis1 = kZAxis,
G4double  axis0min = -kInfinity,
G4double  axis1min = -kInfinity,
G4double  axis0max = kInfinity,
G4double  axis1max = kInfinity 
)

Definition at line 50 of file G4TwistTubsSide.cc.

References FatalErrorInArgument, G4VTwistSurface::fIsValidNorm, G4Exception(), kXAxis, and kZAxis.

00061    : G4VTwistSurface(name, rot, tlate, handedness, axis0, axis1,
00062                 axis0min, axis1min, axis0max, axis1max),
00063      fKappa(kappa)
00064 {
00065    if (axis0 == kZAxis && axis1 == kXAxis) {
00066       G4Exception("G4TwistTubsSide::G4TwistTubsSide()", "GeomSolids0002",
00067                   FatalErrorInArgument, "Should swap axis0 and axis1!");
00068    }
00069    fIsValidNorm = false;
00070    SetCorners();
00071    SetBoundaries();
00072 }

G4TwistTubsSide::G4TwistTubsSide ( const G4String name,
G4double  EndInnerRadius[2],
G4double  EndOuterRadius[2],
G4double  DPhi,
G4double  EndPhi[2],
G4double  EndZ[2],
G4double  InnerRadius,
G4double  OuterRadius,
G4double  Kappa,
G4int  handedness 
)

Definition at line 74 of file G4TwistTubsSide.cc.

References G4VTwistSurface::fAxis, G4VTwistSurface::fAxisMax, G4VTwistSurface::fAxisMin, G4VTwistSurface::fHandedness, G4VTwistSurface::fIsValidNorm, G4VTwistSurface::fRot, G4VTwistSurface::fTrans, kXAxis, and kZAxis.

00084   : G4VTwistSurface(name)
00085 {  
00086    fHandedness = handedness;   // +z = +ve, -z = -ve
00087    fAxis[0]    = kXAxis; // in local coordinate system
00088    fAxis[1]    = kZAxis;
00089    fAxisMin[0] = InnerRadius;  // Inner-hype radius at z=0
00090    fAxisMax[0] = OuterRadius;  // Outer-hype radius at z=0
00091    fAxisMin[1] = EndZ[0];
00092    fAxisMax[1] = EndZ[1];
00093 
00094    fKappa = Kappa;
00095    fRot.rotateZ( fHandedness > 0
00096                  ? -0.5*DPhi
00097                  :  0.5*DPhi );
00098    fTrans.set(0, 0, 0);
00099    fIsValidNorm = false;
00100    
00101    SetCorners( EndInnerRadius, EndOuterRadius, EndPhi, EndZ) ;
00102    SetBoundaries();
00103 }

G4TwistTubsSide::~G4TwistTubsSide (  )  [virtual]

Definition at line 118 of file G4TwistTubsSide.cc.

00119 {
00120 }

G4TwistTubsSide::G4TwistTubsSide ( __void__ &   ) 

Definition at line 109 of file G4TwistTubsSide.cc.

00110   : G4VTwistSurface(a), fKappa(0.)
00111 {
00112 }


Member Function Documentation

G4int G4TwistTubsSide::DistanceToSurface ( const G4ThreeVector gp,
G4ThreeVector  gxx[],
G4double  distance[],
G4int  areacode[] 
) [virtual]

Implements G4VTwistSurface.

Definition at line 454 of file G4TwistTubsSide.cc.

References G4VTwistSurface::AmIOnLeftSide(), G4VTwistSurface::ComputeGlobalPoint(), G4VTwistSurface::ComputeLocalPoint(), G4VTwistSurface::DistanceToBoundary(), G4VTwistSurface::DistanceToLine(), G4VTwistSurface::DistanceToPlane(), G4VTwistSurface::fAxis, G4VTwistSurface::fCurStat, G4VTwistSurface::fCurStatWithV, G4VTwistSurface::GetBoundaryAtPZ(), G4VTwistSurface::GetBoundaryParameters(), G4VTwistSurface::kCarTolerance, G4VTwistSurface::kDontValidate, kXAxis, kZAxis, G4VTwistSurface::sAxis0, G4VTwistSurface::sAxisMax, G4VTwistSurface::sAxisMin, G4VTwistSurface::sInside, and G4VTwistSurface::sOutside.

00458 {  
00459    fCurStat.ResetfDone(kDontValidate, &gp);
00460    G4int i = 0;
00461    if (fCurStat.IsDone()) {
00462       for (i=0; i<fCurStat.GetNXX(); i++) {
00463          gxx[i] = fCurStat.GetXX(i);
00464          distance[i] = fCurStat.GetDistance(i);
00465          areacode[i] = fCurStat.GetAreacode(i);
00466       }
00467       return fCurStat.GetNXX();
00468    } else {
00469       // initialize
00470       for (i=0; i<2; i++) {
00471          distance[i] = kInfinity;
00472          areacode[i] = sOutside;
00473          gxx[i].set(kInfinity, kInfinity, kInfinity);
00474       }
00475    }
00476    
00477    static const G4double halftol = 0.5 * kCarTolerance; 
00478 
00479    G4ThreeVector  p       = ComputeLocalPoint(gp);
00480    G4ThreeVector  xx;
00481    G4int          parity  = (fKappa >= 0 ? 1 : -1);
00482  
00483    // 
00484    // special case! 
00485    // If p is on surface, or
00486    // p is on z-axis, 
00487    // return here immediatery.
00488    //
00489    
00490    G4ThreeVector  lastgxx[2];
00491    for (i=0; i<2; i++) {
00492       lastgxx[i] = fCurStatWithV.GetXX(i);
00493    } 
00494 
00495    if  ((gp - lastgxx[0]).mag() < halftol
00496      || (gp - lastgxx[1]).mag() < halftol) { 
00497       // last winner, or last poststep point is on the surface.
00498       xx = p;
00499       distance[0] = 0;
00500       gxx[0] = gp;
00501 
00502       G4bool isvalid = true;
00503       fCurStat.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
00504                              isvalid, 1, kDontValidate, &gp);
00505       return 1;
00506    }
00507           
00508    if (p.getRho() == 0) { 
00509       // p is on z-axis. Namely, p is on twisted surface (invalid area).
00510       // We must return here, however, returning distance to x-minimum
00511       // boundary is better than return 0-distance.
00512       //
00513       G4bool isvalid = true;
00514       if (fAxis[0] == kXAxis && fAxis[1] == kZAxis) {
00515          distance[0] = DistanceToBoundary(sAxis0 & sAxisMin, xx, p);
00516          areacode[0] = sInside;
00517       } else {
00518          distance[0] = 0;
00519          xx.set(0., 0., 0.);
00520       }
00521       gxx[0] = ComputeGlobalPoint(xx);
00522       fCurStat.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
00523                                 isvalid, 0, kDontValidate, &gp);
00524       return 1;
00525    } 
00526 
00527    // 
00528    // special case end
00529    //
00530 
00531    // set corner points of quadrangle try area ...
00532 
00533    G4ThreeVector A;  // foot of normal from p to boundary of sAxis0 & sAxisMin
00534    G4ThreeVector C;  // foot of normal from p to boundary of sAxis0 & sAxisMax
00535    G4ThreeVector B;       // point on boundary sAxis0 & sAxisMax at z = A.z()
00536    G4ThreeVector D;       // point on boundary sAxis0 & sAxisMin at z = C.z()
00537 
00538    // G4double      distToA; // distance from p to A
00539    DistanceToBoundary(sAxis0 & sAxisMin, A, p);
00540    // G4double      distToC; // distance from p to C 
00541    DistanceToBoundary(sAxis0 & sAxisMax, C, p);
00542    
00543    // is p.z between a.z and c.z?
00544    // p.z must be bracketed a.z and c.z.
00545    if (A.z() > C.z()) {
00546       if (p.z() > A.z()) {
00547          A = GetBoundaryAtPZ(sAxis0 & sAxisMin, p);
00548       } else if (p.z() < C.z()) {
00549          C = GetBoundaryAtPZ(sAxis0 & sAxisMax, p);
00550       }
00551    } else {
00552       if (p.z() > C.z()) {
00553          C = GetBoundaryAtPZ(sAxis0 & sAxisMax, p);
00554       } else if (p.z() < A.z()) {
00555          A = GetBoundaryAtPZ(sAxis0 & sAxisMin, p);
00556       }
00557    }
00558 
00559    G4ThreeVector  d[2];     // direction vectors of boundary
00560    G4ThreeVector  x0[2];    // foot of normal from line to p 
00561    G4int          btype[2]; // boundary type
00562 
00563    for (i=0; i<2; i++) {
00564       if (i == 0) {
00565          GetBoundaryParameters((sAxis0 & sAxisMax), d[i], x0[i], btype[i]);
00566          B = x0[i] + ((A.z() - x0[i].z()) / d[i].z()) * d[i]; 
00567          // x0 + t*d , d is direction unit vector.
00568       } else {
00569          GetBoundaryParameters((sAxis0 & sAxisMin), d[i], x0[i], btype[i]);
00570          D = x0[i] + ((C.z() - x0[i].z()) / d[i].z()) * d[i]; 
00571       }
00572    }
00573 
00574    // In order to set correct diagonal, swap A and D, C and B if needed.  
00575    G4ThreeVector pt(p.x(), p.y(), 0.);
00576    G4double      rc = std::fabs(p.x());
00577    G4ThreeVector surfacevector(rc, rc * fKappa * p.z(), 0.); 
00578    G4int         pside = AmIOnLeftSide(pt, surfacevector); 
00579    G4double      test  = (A.z() - C.z()) * parity * pside;  
00580 
00581    if (test == 0) {
00582       if (pside == 0) {
00583          // p is on surface.
00584          xx = p;
00585          distance[0] = 0;
00586          gxx[0] = gp;
00587 
00588          G4bool isvalid = true;
00589          fCurStat.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
00590                                 isvalid, 1, kDontValidate, &gp);
00591          return 1;
00592       } else {
00593          // A.z = C.z(). return distance to line.
00594          d[0] = C - A;
00595          distance[0] = DistanceToLine(p, A, d[0], xx);
00596          areacode[0] = sInside;
00597          gxx[0] = ComputeGlobalPoint(xx);
00598          G4bool isvalid = true;
00599          fCurStat.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
00600                                 isvalid, 1, kDontValidate, &gp);
00601          return 1;
00602       } 
00603 
00604    } else if (test < 0) {
00605 
00606       // wrong diagonal. vector AC is crossing the surface!  
00607       // swap A and D, C and B
00608       G4ThreeVector tmp;
00609       tmp = A;
00610       A = D;
00611       D = tmp;
00612       tmp = C;
00613       C = B;
00614       B = tmp; 
00615 
00616    } else {
00617       // correct diagonal. nothing to do.  
00618    }
00619 
00620    // Now, we chose correct diaglnal.
00621    // First try. divide quadrangle into double triangle by diagonal and 
00622    // calculate distance to both surfaces.
00623 
00624    G4ThreeVector xxacb;   // foot of normal from plane ACB to p
00625    G4ThreeVector nacb;    // normal of plane ACD
00626    G4ThreeVector xxcad;   // foot of normal from plane CAD to p
00627    G4ThreeVector ncad;    // normal of plane CAD
00628    G4ThreeVector AB(A.x(), A.y(), 0);
00629    G4ThreeVector DC(C.x(), C.y(), 0);
00630 
00631    G4double distToACB = G4VTwistSurface::DistanceToPlane(p, A, C-A, AB, xxacb, nacb) * parity;
00632    G4double distToCAD = G4VTwistSurface::DistanceToPlane(p, C, C-A, DC, xxcad, ncad) * parity;
00633 
00634    // if calculated distance = 0, return  
00635 
00636    if (std::fabs(distToACB) <= halftol || std::fabs(distToCAD) <= halftol) {
00637       xx = (std::fabs(distToACB) < std::fabs(distToCAD) ? xxacb : xxcad); 
00638       areacode[0] = sInside;
00639       gxx[0] = ComputeGlobalPoint(xx);
00640       distance[0] = 0;
00641       G4bool isvalid = true;
00642       fCurStat.SetCurrentStatus(0, gxx[0], distance[0] , areacode[0],
00643                                 isvalid, 1, kDontValidate, &gp);
00644       return 1;
00645    }
00646    
00647    if (distToACB * distToCAD > 0 && distToACB < 0) {
00648       // both distToACB and distToCAD are negative.
00649       // divide quadrangle into double triangle by diagonal
00650       G4ThreeVector normal;
00651       distance[0] = DistanceToPlane(p, A, B, C, D, parity, xx, normal);
00652    } else {
00653       if (distToACB * distToCAD > 0) {
00654          // both distToACB and distToCAD are positive.
00655          // Take smaller one.
00656          if (distToACB <= distToCAD) {
00657             distance[0] = distToACB;
00658             xx   = xxacb;
00659          } else {
00660             distance[0] = distToCAD;
00661             xx   = xxcad;
00662          }
00663       } else {
00664          // distToACB * distToCAD is negative.
00665          // take positive one
00666          if (distToACB > 0) {
00667             distance[0] = distToACB;
00668             xx   = xxacb;
00669          } else {
00670             distance[0] = distToCAD;
00671             xx   = xxcad;
00672          }
00673       }
00674       
00675    }
00676    areacode[0] = sInside;
00677    gxx[0]      = ComputeGlobalPoint(xx);
00678    G4bool isvalid = true;
00679    fCurStat.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
00680                              isvalid, 1, kDontValidate, &gp);
00681    return 1;
00682 }

G4int G4TwistTubsSide::DistanceToSurface ( const G4ThreeVector gp,
const G4ThreeVector gv,
G4ThreeVector  gxx[],
G4double  distance[],
G4int  areacode[],
G4bool  isvalid[],
EValidate  validate = kValidateWithTol 
) [virtual]

Definition at line 160 of file G4TwistTubsSide.cc.

References G4VTwistSurface::ComputeGlobalPoint(), G4VTwistSurface::ComputeLocalDirection(), G4VTwistSurface::ComputeLocalPoint(), DBL_MIN, G4VTwistSurface::DistanceToPlaneWithV(), FatalException, G4VTwistSurface::fCurStat, G4VTwistSurface::fCurStatWithV, G4endl, G4Exception(), GetNormal(), G4VTwistSurface::IsInside(), G4VTwistSurface::IsOutside(), G4VTwistSurface::kCarTolerance, G4VTwistSurface::kValidateWithoutTol, G4VTwistSurface::kValidateWithTol, G4VTwistSurface::sInside, and G4VTwistSurface::sOutside.

00167 {
00168    // Coordinate system:
00169    //
00170    //    The coordinate system is so chosen that the intersection of
00171    //    the twisted surface with the z=0 plane coincides with the
00172    //    x-axis. 
00173    //    Rotation matrix from this coordinate system (local system)
00174    //    to global system is saved in fRot field.
00175    //    So the (global) particle position and (global) velocity vectors, 
00176    //    p and v, should be rotated fRot.inverse() in order to convert
00177    //    to local vectors.
00178    //
00179    // Equation of a twisted surface:
00180    //
00181    //    x(rho(z=0), z) = rho(z=0)
00182    //    y(rho(z=0), z) = rho(z=0)*K*z
00183    //    z(rho(z=0), z) = z
00184    //    with
00185    //       K = std::tan(fPhiTwist/2)/fZHalfLen
00186    //
00187    // Equation of a line:
00188    //
00189    //    gxx = p + t*v
00190    //    with
00191    //       p = fRot.inverse()*gp  
00192    //       v = fRot.inverse()*gv
00193    //
00194    // Solution for intersection:
00195    //
00196    //    Required time for crossing is given by solving the
00197    //    following quadratic equation:
00198    //
00199    //       a*t^2 + b*t + c = 0
00200    //
00201    //    where
00202    //
00203    //       a = K*v_x*v_z
00204    //       b = K*(v_x*p_z + v_z*p_x) - v_y
00205    //       c = K*p_x*p_z - p_y
00206    //
00207    //    Out of the possible two solutions you must choose
00208    //    the one that gives a positive rho(z=0).
00209    //
00210    //
00211       
00212    fCurStatWithV.ResetfDone(validate, &gp, &gv);
00213 
00214    if (fCurStatWithV.IsDone()) {
00215       G4int i;
00216       for (i=0; i<fCurStatWithV.GetNXX(); i++) {
00217          gxx[i] = fCurStatWithV.GetXX(i);
00218          distance[i] = fCurStatWithV.GetDistance(i);
00219          areacode[i] = fCurStatWithV.GetAreacode(i);
00220          isvalid[i]  = fCurStatWithV.IsValid(i);
00221       }
00222       return fCurStatWithV.GetNXX();
00223    } else {
00224       // initialize
00225       G4int i;
00226       for (i=0; i<2; i++) {
00227          distance[i] = kInfinity;
00228          areacode[i] = sOutside;
00229          isvalid[i]  = false;
00230          gxx[i].set(kInfinity, kInfinity, kInfinity);
00231       }
00232    }
00233 
00234    G4ThreeVector p = ComputeLocalPoint(gp);
00235    G4ThreeVector v = ComputeLocalDirection(gv);
00236    G4ThreeVector xx[2]; 
00237 
00238 
00239    // 
00240    // special case! 
00241    // p is origin or
00242    //
00243 
00244    G4double absvz = std::fabs(v.z());
00245 
00246    if ((absvz < DBL_MIN) && (std::fabs(p.x() * v.y() - p.y() * v.x()) < DBL_MIN)) {
00247       // no intersection
00248 
00249       isvalid[0] = false;
00250       fCurStat.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
00251                                 isvalid[0], 0, validate, &gp, &gv);
00252       return 0;
00253    } 
00254    
00255    // 
00256    // special case end
00257    //
00258 
00259    
00260    G4double a = fKappa * v.x() * v.z();
00261    G4double b = fKappa * (v.x() * p.z() + v.z() * p.x()) - v.y();
00262    G4double c = fKappa * p.x() * p.z() - p.y();
00263    G4double D = b * b - 4 * a * c;             // discriminant
00264    G4int vout = 0;
00265 
00266    if (std::fabs(a) < DBL_MIN) {
00267       if (std::fabs(b) > DBL_MIN) { 
00268 
00269          // single solution
00270 
00271          distance[0] = - c / b;
00272          xx[0]       = p + distance[0]*v;
00273          gxx[0]      = ComputeGlobalPoint(xx[0]);
00274 
00275          if (validate == kValidateWithTol) {
00276             areacode[0] = GetAreaCode(xx[0]);
00277             if (!IsOutside(areacode[0])) {
00278                if (distance[0] >= 0) isvalid[0] = true;
00279             }
00280          } else if (validate == kValidateWithoutTol) {
00281             areacode[0] = GetAreaCode(xx[0], false);
00282             if (IsInside(areacode[0])) {
00283                if (distance[0] >= 0) isvalid[0] = true;
00284             }
00285          } else { // kDontValidate                       
00286             // we must omit x(rho,z) = rho(z=0) < 0
00287             if (xx[0].x() > 0) {
00288                areacode[0] = sInside;
00289                if (distance[0] >= 0) isvalid[0] = true;
00290             } else {
00291                distance[0] = kInfinity;
00292                fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0],
00293                                               areacode[0], isvalid[0],
00294                                               0, validate, &gp, &gv);
00295                return vout;
00296             } 
00297          }
00298                  
00299          fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
00300                                         isvalid[0], 1, validate, &gp, &gv);
00301          vout = 1;
00302 
00303       } else {
00304          // if a=b=0 , v.y=0 and (v.x=0 && p.x=0) or (v.z=0 && p.z=0) .
00305          //    if v.x=0 && p.x=0, no intersection unless p is on z-axis
00306          //    (in that case, v is paralell to surface). 
00307          //    if v.z=0 && p.z=0, no intersection unless p is on x-axis
00308          //    (in that case, v is paralell to surface). 
00309          // return distance = infinity.
00310 
00311          fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
00312                                         isvalid[0], 0, validate, &gp, &gv);
00313       }
00314       
00315    } else if (D > DBL_MIN) {   
00316 
00317       // double solutions
00318 
00319       D = std::sqrt(D);
00320       G4double      factor = 0.5/a;
00321       G4double      tmpdist[2] = {kInfinity, kInfinity};
00322       G4ThreeVector tmpxx[2];
00323       G4int         tmpareacode[2] = {sOutside, sOutside};
00324       G4bool        tmpisvalid[2]  = {false, false};
00325       G4int i;
00326 
00327       for (i=0; i<2; i++) {
00328          G4double bminusD = - b - D;
00329 
00330          // protection against round off error  
00331          //G4double protection = 1.0e-6;
00332          G4double protection = 0;
00333          if ( b * D < 0 && std::fabs(bminusD / D) < protection ) {
00334             G4double acovbb = (a*c)/(b*b);
00335             tmpdist[i] = - c/b * ( 1 - acovbb * (1 + 2*acovbb));
00336          } else { 
00337             tmpdist[i] = factor * bminusD;
00338          }
00339 
00340          D = -D;
00341          tmpxx[i] = p + tmpdist[i]*v;
00342          
00343          if (validate == kValidateWithTol) {
00344             tmpareacode[i] = GetAreaCode(tmpxx[i]);
00345             if (!IsOutside(tmpareacode[i])) {
00346                if (tmpdist[i] >= 0) tmpisvalid[i] = true;
00347                continue;
00348             }
00349          } else if (validate == kValidateWithoutTol) {
00350             tmpareacode[i] = GetAreaCode(tmpxx[i], false);
00351             if (IsInside(tmpareacode[i])) {
00352                if (tmpdist[i] >= 0) tmpisvalid[i] = true;
00353                continue;
00354             }
00355          } else { // kDontValidate
00356             // we must choose x(rho,z) = rho(z=0) > 0
00357             if (tmpxx[i].x() > 0) {
00358                tmpareacode[i] = sInside;
00359                if (tmpdist[i] >= 0) tmpisvalid[i] = true;
00360                continue;
00361             } else {
00362                tmpdist[i] = kInfinity;
00363                continue;
00364             }                     
00365          }
00366       }
00367       
00368       if (tmpdist[0] <= tmpdist[1]) {
00369          distance[0] = tmpdist[0];
00370          distance[1] = tmpdist[1];
00371          xx[0]       = tmpxx[0];
00372          xx[1]       = tmpxx[1];
00373          gxx[0]      = ComputeGlobalPoint(tmpxx[0]);
00374          gxx[1]      = ComputeGlobalPoint(tmpxx[1]);
00375          areacode[0] = tmpareacode[0];
00376          areacode[1] = tmpareacode[1];
00377          isvalid[0]  = tmpisvalid[0];
00378          isvalid[1]  = tmpisvalid[1];
00379       } else {
00380          distance[0] = tmpdist[1];
00381          distance[1] = tmpdist[0];
00382          xx[0]       = tmpxx[1];
00383          xx[1]       = tmpxx[0];
00384          gxx[0]      = ComputeGlobalPoint(tmpxx[1]);
00385          gxx[1]      = ComputeGlobalPoint(tmpxx[0]);
00386          areacode[0] = tmpareacode[1];
00387          areacode[1] = tmpareacode[0];
00388          isvalid[0]  = tmpisvalid[1];
00389          isvalid[1]  = tmpisvalid[0];
00390       }
00391          
00392       fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
00393                                      isvalid[0], 2, validate, &gp, &gv);
00394       fCurStatWithV.SetCurrentStatus(1, gxx[1], distance[1], areacode[1],
00395                                      isvalid[1], 2, validate, &gp, &gv);
00396 
00397       // protection against roundoff error
00398 
00399       for (G4int k=0; k<2; k++) {
00400          if (!isvalid[k]) continue;
00401 
00402          G4ThreeVector xxonsurface(xx[k].x(), fKappa * std::fabs(xx[k].x())
00403                                               * xx[k].z() , xx[k].z());
00404          G4double      deltaY  =  (xx[k] - xxonsurface).mag();
00405 
00406          if ( deltaY > 0.5*kCarTolerance ) {
00407 
00408            G4int maxcount = 10;
00409            G4int l;
00410            G4double      lastdeltaY = deltaY; 
00411            for (l=0; l<maxcount; l++) {
00412              G4ThreeVector surfacenormal = GetNormal(xxonsurface); 
00413              distance[k] = DistanceToPlaneWithV(p, v, xxonsurface,
00414                                                 surfacenormal, xx[k]);
00415              deltaY      = (xx[k] - xxonsurface).mag();
00416              if (deltaY > lastdeltaY) {
00417                
00418              }
00419              gxx[k]      = ComputeGlobalPoint(xx[k]);
00420 
00421                if (deltaY <= 0.5*kCarTolerance) {
00422             
00423                  break;
00424                }
00425                xxonsurface.set(xx[k].x(),
00426                                fKappa * std::fabs(xx[k].x()) * xx[k].z(),
00427                                xx[k].z());
00428             }
00429             if (l == maxcount) {
00430                std::ostringstream message;
00431                message << "Exceeded maxloop count!" << G4endl
00432                       << "        maxloop count " << maxcount;
00433                G4Exception("G4TwistTubsFlatSide::DistanceToSurface(p,v)",
00434                            "GeomSolids0003",  FatalException, message);
00435             }
00436          }
00437 
00438       }
00439       vout = 2;
00440    } else {
00441       // if D<0, no solution
00442       // if D=0, just grazing the surfaces, return kInfinity
00443 
00444       fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
00445                                      isvalid[0], 0, validate, &gp, &gv);
00446    }
00447 
00448    return vout;
00449 }

G4double G4TwistTubsSide::GetBoundaryMax ( G4double  phi  )  [inline, virtual]

Implements G4VTwistSurface.

Definition at line 181 of file G4TwistTubsSide.hh.

References G4VTwistSurface::fAxisMax.

Referenced by GetFacets().

00182 {
00183   return  fAxisMax[0] ;  // outer radius at z = 0
00184 }

G4double G4TwistTubsSide::GetBoundaryMin ( G4double  phi  )  [inline, virtual]

Implements G4VTwistSurface.

Definition at line 175 of file G4TwistTubsSide.hh.

References G4VTwistSurface::fAxisMin.

Referenced by GetFacets().

00176 {
00177   return  fAxisMin[0] ;  // inner radius at z = 0
00178 }

void G4TwistTubsSide::GetFacets ( G4int  m,
G4int  n,
G4double  xyz[][3],
G4int  faces[][4],
G4int  iside 
) [virtual]

Implements G4VTwistSurface.

Definition at line 953 of file G4TwistTubsSide.cc.

References G4VTwistSurface::fAxisMax, G4VTwistSurface::fAxisMin, G4VTwistSurface::fHandedness, GetBoundaryMax(), GetBoundaryMin(), G4VTwistSurface::GetEdgeVisibility(), G4VTwistSurface::GetFace(), G4VTwistSurface::GetNode(), and SurfacePoint().

00955 {
00956 
00957   G4double z ;     // the two parameters for the surface equation
00958   G4double x,xmin,xmax ;
00959 
00960   G4ThreeVector p ;  // a point on the surface, given by (z,u)
00961 
00962   G4int nnode ;
00963   G4int nface ;
00964 
00965   // calculate the (n-1)*(k-1) vertices
00966 
00967   G4int i,j ;
00968 
00969   for ( i = 0 ; i<n ; i++ )
00970   {
00971 
00972     z = fAxisMin[1] + i*(fAxisMax[1]-fAxisMin[1])/(n-1) ;
00973 
00974     for ( j = 0 ; j<k ; j++ ) {
00975 
00976       nnode = GetNode(i,j,k,n,iside) ;
00977 
00978       xmin = GetBoundaryMin(z) ; 
00979       xmax = GetBoundaryMax(z) ;
00980 
00981       if (fHandedness < 0) { 
00982         x = xmin + j*(xmax-xmin)/(k-1) ;
00983       } else {               
00984         x = xmax - j*(xmax-xmin)/(k-1) ;
00985       }
00986 
00987       p = SurfacePoint(x,z,true) ;  // surface point in global coord.system
00988 
00989       xyz[nnode][0] = p.x() ;
00990       xyz[nnode][1] = p.y() ;
00991       xyz[nnode][2] = p.z() ;
00992 
00993       if ( i<n-1 && j<k-1 ) {   // clock wise filling
00994         
00995         nface = GetFace(i,j,k,n,iside) ;
00996 
00997         faces[nface][0] = GetEdgeVisibility(i,j,k,n,0,1) * ( GetNode(i  ,j  ,k,n,iside)+1) ;  
00998         faces[nface][1] = GetEdgeVisibility(i,j,k,n,1,1) * ( GetNode(i+1,j  ,k,n,iside)+1) ;
00999         faces[nface][2] = GetEdgeVisibility(i,j,k,n,2,1) * ( GetNode(i+1,j+1,k,n,iside)+1) ;
01000         faces[nface][3] = GetEdgeVisibility(i,j,k,n,3,1) * ( GetNode(i  ,j+1,k,n,iside)+1) ;
01001 
01002       }
01003     }
01004   }
01005 }

G4ThreeVector G4TwistTubsSide::GetNormal ( const G4ThreeVector xx,
G4bool  isGlobal = false 
) [virtual]

Implements G4VTwistSurface.

Definition at line 125 of file G4TwistTubsSide.cc.

References G4VTwistSurface::ComputeGlobalDirection(), G4VTwistSurface::ComputeLocalPoint(), G4VTwistSurface::fCurrentNormal, G4VTwistSurface::fHandedness, and G4VTwistSurface::kCarTolerance.

Referenced by DistanceToSurface().

00127 {
00128    // GetNormal returns a normal vector at a surface (or very close
00129    // to surface) point at tmpxx.
00130    // If isGlobal=true, it returns the normal in global coordinate.
00131    //
00132    G4ThreeVector xx;
00133    if (isGlobal) {
00134       xx = ComputeLocalPoint(tmpxx);
00135       if ((xx - fCurrentNormal.p).mag() < 0.5 * kCarTolerance) {
00136          return ComputeGlobalDirection(fCurrentNormal.normal);
00137       }
00138    } else {
00139       xx = tmpxx;
00140       if (xx == fCurrentNormal.p) {
00141          return fCurrentNormal.normal;
00142       }
00143    }
00144    
00145    G4ThreeVector er(1, fKappa * xx.z(), 0);
00146    G4ThreeVector ez(0, fKappa * xx.x(), 1);
00147    G4ThreeVector normal = fHandedness*(er.cross(ez));
00148 
00149    if (isGlobal) {
00150       fCurrentNormal.normal = ComputeGlobalDirection(normal.unit());
00151    } else {
00152       fCurrentNormal.normal = normal.unit();
00153    }
00154    return fCurrentNormal.normal;
00155 }

G4double G4TwistTubsSide::GetSurfaceArea (  )  [inline, virtual]

Implements G4VTwistSurface.

Definition at line 187 of file G4TwistTubsSide.hh.

References G4VTwistSurface::fAxisMax, and G4VTwistSurface::fAxisMin.

00188 {
00189   // approximation only
00190   return ( fAxisMax[0] - fAxisMin[0] ) * ( fAxisMax[1] - fAxisMin[1] ) ;
00191 }

G4ThreeVector G4TwistTubsSide::ProjectAtPXPZ ( const G4ThreeVector p,
G4bool  isglobal = false 
) const [inline]

Definition at line 149 of file G4TwistTubsSide.hh.

References G4VTwistSurface::fRot, and G4VTwistSurface::fTrans.

00151 {
00152   // Get Rho at p.z() on Hyperbolic Surface.
00153   G4ThreeVector tmpp;
00154   if (isglobal) {
00155      tmpp = fRot.inverse()*p - fTrans;
00156   } else {
00157      tmpp = p;
00158   }
00159   G4ThreeVector xx(p.x(), p.x() * fKappa * p.z(), p.z());
00160   if (isglobal) { return (fRot * xx + fTrans); }
00161   return xx;
00162 }

G4ThreeVector G4TwistTubsSide::SurfacePoint ( G4double  ,
G4double  ,
G4bool  isGlobal = false 
) [inline, virtual]

Implements G4VTwistSurface.

Definition at line 166 of file G4TwistTubsSide.hh.

References G4VTwistSurface::fRot, and G4VTwistSurface::fTrans.

Referenced by GetFacets().

00167 {
00168   G4ThreeVector SurfPoint( x , x * fKappa * z , z ) ;
00169 
00170   if (isGlobal) { return (fRot * SurfPoint + fTrans); }
00171   return SurfPoint;
00172 }


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