#include <G4TwistTubsSide.hh>
Inheritance diagram for G4TwistTubsSide:
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__ &) |
Definition at line 52 of file G4TwistTubsSide.hh.
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] |
G4TwistTubsSide::G4TwistTubsSide | ( | __void__ & | ) |
Definition at line 109 of file G4TwistTubsSide.cc.
00110 : G4VTwistSurface(a), fKappa(0.) 00111 { 00112 }
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 }
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 }
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 }