00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <cmath>
00043
00044 #include "G4TwistTrapAlphaSide.hh"
00045 #include "G4PhysicalConstants.hh"
00046 #include "G4JTPolynomialSolver.hh"
00047
00048
00049
00050
00051 G4TwistTrapAlphaSide::
00052 G4TwistTrapAlphaSide(const G4String &name,
00053 G4double PhiTwist,
00054 G4double pDz,
00055 G4double pTheta,
00056 G4double pPhi,
00057 G4double pDy1,
00058 G4double pDx1,
00059 G4double pDx2,
00060 G4double pDy2,
00061 G4double pDx3,
00062 G4double pDx4,
00063 G4double pAlph,
00064 G4double AngleSide
00065 )
00066 : G4VTwistSurface(name)
00067 {
00068 fAxis[0] = kYAxis;
00069 fAxis[1] = kZAxis;
00070 fAxisMin[0] = -kInfinity ;
00071 fAxisMax[0] = kInfinity ;
00072 fAxisMin[1] = -pDz ;
00073 fAxisMax[1] = pDz ;
00074
00075 fDx1 = pDx1 ;
00076 fDx2 = pDx2 ;
00077 fDx3 = pDx3 ;
00078 fDx4 = pDx4 ;
00079
00080 fDy1 = pDy1 ;
00081 fDy2 = pDy2 ;
00082
00083 fDz = pDz ;
00084
00085 fAlph = pAlph ;
00086 fTAlph = std::tan(fAlph) ;
00087
00088 fTheta = pTheta ;
00089 fPhi = pPhi ;
00090
00091
00092 fDx4plus2 = fDx4 + fDx2 ;
00093 fDx4minus2 = fDx4 - fDx2 ;
00094 fDx3plus1 = fDx3 + fDx1 ;
00095 fDx3minus1 = fDx3 - fDx1 ;
00096 fDy2plus1 = fDy2 + fDy1 ;
00097 fDy2minus1 = fDy2 - fDy1 ;
00098
00099 fa1md1 = 2*fDx2 - 2*fDx1 ;
00100 fa2md2 = 2*fDx4 - 2*fDx3 ;
00101
00102 fPhiTwist = PhiTwist ;
00103 fAngleSide = AngleSide ;
00104
00105 fdeltaX = 2 * fDz * std::tan(fTheta) * std::cos(fPhi);
00106
00107 fdeltaY = 2 * fDz * std::tan(fTheta) * std::sin(fPhi);
00108
00109
00110 fRot.rotateZ( AngleSide ) ;
00111
00112 fTrans.set(0, 0, 0);
00113 fIsValidNorm = false;
00114
00115 SetCorners() ;
00116 SetBoundaries() ;
00117
00118 }
00119
00120
00121
00122
00123
00124 G4TwistTrapAlphaSide::G4TwistTrapAlphaSide( __void__& a )
00125 : G4VTwistSurface(a), fTheta(0.), fPhi(0.), fDy1(0.), fDx1(0.), fDx2(0.),
00126 fDy2(0.), fDx3(0.), fDx4(0.), fDz(0.), fAlph(0.), fTAlph(0.), fPhiTwist(0.),
00127 fAngleSide(0.), fDx4plus2(0.), fDx4minus2(0.), fDx3plus1(0.), fDx3minus1(0.),
00128 fDy2plus1(0.), fDy2minus1(0.), fa1md1(0.), fa2md2(0.), fdeltaX(0.),
00129 fdeltaY(0.)
00130 {
00131 }
00132
00133
00134
00135
00136
00137 G4TwistTrapAlphaSide::~G4TwistTrapAlphaSide()
00138 {
00139 }
00140
00141
00142
00143
00144
00145 G4ThreeVector
00146 G4TwistTrapAlphaSide::GetNormal(const G4ThreeVector &tmpxx,
00147 G4bool isGlobal)
00148 {
00149
00150
00151
00152
00153
00154 G4ThreeVector xx;
00155 if (isGlobal)
00156 {
00157 xx = ComputeLocalPoint(tmpxx);
00158 if ((xx - fCurrentNormal.p).mag() < 0.5 * kCarTolerance)
00159 {
00160 return ComputeGlobalDirection(fCurrentNormal.normal);
00161 }
00162 }
00163 else
00164 {
00165 xx = tmpxx;
00166 if (xx == fCurrentNormal.p)
00167 {
00168 return fCurrentNormal.normal;
00169 }
00170 }
00171
00172 G4double phi ;
00173 G4double u ;
00174
00175 GetPhiUAtX(xx,phi,u) ;
00176
00177 G4ThreeVector normal = NormAng(phi,u) ;
00178
00179 #ifdef G4TWISTDEBUG
00180 G4cout << "normal vector = " << normal << G4endl ;
00181 G4cout << "phi = " << phi << " , u = " << u << G4endl ;
00182 #endif
00183
00184 if (isGlobal)
00185 {
00186 fCurrentNormal.normal = ComputeGlobalDirection(normal.unit());
00187 }
00188 else
00189 {
00190 fCurrentNormal.normal = normal.unit();
00191 }
00192
00193 return fCurrentNormal.normal;
00194 }
00195
00196
00197
00198
00199 G4int
00200 G4TwistTrapAlphaSide::DistanceToSurface(const G4ThreeVector &gp,
00201 const G4ThreeVector &gv,
00202 G4ThreeVector gxx[],
00203 G4double distance[],
00204 G4int areacode[],
00205 G4bool isvalid[],
00206 EValidate validate)
00207 {
00208 static const G4double ctol = 0.5 * kCarTolerance;
00209 static const G4double pihalf = pi/2 ;
00210
00211 G4bool IsParallel = false ;
00212 G4bool IsConverged = false ;
00213
00214 G4int nxx = 0 ;
00215
00216 fCurStatWithV.ResetfDone(validate, &gp, &gv);
00217
00218 if (fCurStatWithV.IsDone())
00219 {
00220 for (register int i=0; i<fCurStatWithV.GetNXX(); i++)
00221 {
00222 gxx[i] = fCurStatWithV.GetXX(i);
00223 distance[i] = fCurStatWithV.GetDistance(i);
00224 areacode[i] = fCurStatWithV.GetAreacode(i);
00225 isvalid[i] = fCurStatWithV.IsValid(i);
00226 }
00227 return fCurStatWithV.GetNXX();
00228 }
00229 else
00230 {
00231 for (register int j=0; j<G4VSURFACENXX ; j++)
00232 {
00233 distance[j] = kInfinity;
00234 areacode[j] = sOutside;
00235 isvalid[j] = false;
00236 gxx[j].set(kInfinity, kInfinity, kInfinity);
00237 }
00238 }
00239
00240 G4ThreeVector p = ComputeLocalPoint(gp);
00241 G4ThreeVector v = ComputeLocalDirection(gv);
00242
00243 #ifdef G4TWISTDEBUG
00244 G4cout << "Local point p = " << p << G4endl ;
00245 G4cout << "Local direction v = " << v << G4endl ;
00246 #endif
00247
00248 G4double phi,u ;
00249
00250
00251
00252 G4double tmpdist = kInfinity ;
00253 G4ThreeVector tmpxx;
00254 G4int tmpareacode = sOutside ;
00255 G4bool tmpisvalid = false ;
00256
00257 std::vector<Intersection> xbuf ;
00258 Intersection xbuftmp ;
00259
00260
00261
00262 G4double L = 2*fDz ;
00263
00264 G4double phixz = fPhiTwist * ( p.x() * v.z() - p.z() * v.x() ) ;
00265 G4double phiyz = fPhiTwist * ( p.y() * v.z() - p.z() * v.y() ) ;
00266
00267
00268
00269
00270 if ( v.z() == 0. )
00271 {
00272 if ( std::fabs(p.z()) <= L )
00273 {
00274 phi = p.z() * fPhiTwist / L ;
00275 u = (fDy1*(4*(-(fdeltaY*phi*v.x()) + fPhiTwist*p.y()*v.x()
00276 + fdeltaX*phi*v.y() - fPhiTwist*p.x()*v.y())
00277 + ((fDx3plus1 + fDx4plus2)*fPhiTwist
00278 + 2*(fDx3minus1 + fDx4minus2)*phi)
00279 *(v.y()*std::cos(phi) - v.x()*std::sin(phi))))
00280 /(fPhiTwist*(4*fDy1* v.x() - (fa1md1 + 4*fDy1*fTAlph)*v.y())
00281 *std::cos(phi) + fPhiTwist*(fa1md1*v.x()
00282 + 4*fDy1*(fTAlph*v.x() + v.y()))*std::sin(phi));
00283 xbuftmp.phi = phi ;
00284 xbuftmp.u = u ;
00285 xbuftmp.areacode = sOutside ;
00286 xbuftmp.distance = kInfinity ;
00287 xbuftmp.isvalid = false ;
00288
00289 xbuf.push_back(xbuftmp) ;
00290 }
00291 else
00292 {
00293 distance[0] = kInfinity;
00294 gxx[0].set(kInfinity,kInfinity,kInfinity);
00295 isvalid[0] = false ;
00296 areacode[0] = sOutside ;
00297 fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0],
00298 areacode[0], isvalid[0],
00299 0, validate, &gp, &gv);
00300 return 0;
00301 }
00302 }
00303 else
00304 {
00305
00306 G4double c[8],srd[7],si[7] ;
00307
00308 c[7] = 57600*
00309 fDy1*(fa1md1*phiyz +
00310 fDy1*(-4*phixz + 4*fTAlph*phiyz
00311 + (fDx3plus1 + fDx4plus2)*fPhiTwist*v.z())) ;
00312 c[6] = -57600*
00313 fDy1*(4*fDy1*(phiyz + 2*fDz*v.x() + fTAlph*(phixz - 2*fDz*v.y()))
00314 - 2*fDy1*(2*fdeltaX + fDx3minus1 + fDx4minus2
00315 - 2*fdeltaY*fTAlph)*v.z()
00316 + fa1md1*(phixz - 2*fDz*v.y() + fdeltaY*v.z()));
00317 c[5] = 4800*
00318 fDy1*(fa1md1*(-5*phiyz - 24*fDz*v.x() + 12*fdeltaX*v.z()) +
00319 fDy1*(20*phixz - 4*(5*fTAlph*phiyz + 24*fDz*fTAlph*v.x()
00320 + 24*fDz*v.y()) + (48*fdeltaY + (fDx3plus1 + fDx4plus2)
00321 *fPhiTwist + 48*fdeltaX*fTAlph)*v.z()));
00322 c[4] = 4800*
00323 fDy1*(fa1md1*(phixz - 10*fDz*v.y() + 5*fdeltaY*v.z())
00324 + 2*fDy1*(2*phiyz + 20*fDz*v.x()
00325 + (-10*fdeltaX + fDx3minus1 + fDx4minus2)*v.z()
00326 + 2*fTAlph*(phixz - 10*fDz*v.y() + 5*fdeltaY*v.z())));
00327 c[3] = -96*
00328 fDy1*(-(fa1md1*(phiyz + 100*fDz*v.x() - 50*fdeltaX*v.z()))
00329 + fDy1*(4*phixz - 400*fDz*v.y()
00330 + (200*fdeltaY - (fDx3plus1 + fDx4plus2)*fPhiTwist)*v.z()
00331 - 4*fTAlph*(phiyz + 100*fDz*v.x() - 50*fdeltaX*v.z())));
00332 c[2] = 32*
00333 fDy1*(4*fDy1*(7*fTAlph*phixz + 7*phiyz - 6*fDz*v.x() + 6*fDz*fTAlph*v.y())
00334 + 6*fDy1*(2*fdeltaX+fDx3minus1+fDx4minus2-2*fdeltaY*fTAlph)*v.z()
00335 + fa1md1*(7*phixz + 6*fDz*v.y() - 3*fdeltaY*v.z()));
00336 c[1] = -8*
00337 fDy1*(fa1md1*(-9*phiyz - 56*fDz*v.x() + 28*fdeltaX*v.z())
00338 + 4*fDy1*(9*phixz - 9*fTAlph*phiyz - 56*fDz*fTAlph*v.x()
00339 - 56*fDz*v.y() + 28*(fdeltaY + fdeltaX*fTAlph)*v.z()));
00340 c[0] = 72*
00341 fDy1*(fa1md1*(2*fDz*v.y() - fdeltaY*v.z())
00342 + fDy1*(-8*fDz*v.x() + 8*fDz*fTAlph*v.y()
00343 + 4*fdeltaX*v.z() - 4*fdeltaY*fTAlph*v.z()));
00344
00345 #ifdef G4TWISTDEBUG
00346 G4cout << "coef = " << c[0] << " "
00347 << c[1] << " "
00348 << c[2] << " "
00349 << c[3] << " "
00350 << c[4] << " "
00351 << c[5] << " "
00352 << c[6] << " "
00353 << c[7] << G4endl ;
00354 #endif
00355
00356 G4JTPolynomialSolver trapEq ;
00357 G4int num = trapEq.FindRoots(c,7,srd,si);
00358
00359 for (register int i = 0 ; i<num ; i++ )
00360 {
00361 if ( si[i]==0.0 )
00362 {
00363 #ifdef G4TWISTDEBUG
00364 G4cout << "Solution " << i << " : " << srd[i] << G4endl ;
00365 #endif
00366 phi = std::fmod(srd[i] , pihalf) ;
00367 u = (fDy1*(4*(phiyz + 2*fDz*phi*v.y() - fdeltaY*phi*v.z())
00368 - ((fDx3plus1 + fDx4plus2)*fPhiTwist
00369 + 2*(fDx3minus1 + fDx4minus2)*phi)*v.z()*std::sin(phi)))
00370 /(fPhiTwist*v.z()*(4*fDy1*std::cos(phi)
00371 + (fa1md1 + 4*fDy1*fTAlph)*std::sin(phi)));
00372 xbuftmp.phi = phi ;
00373 xbuftmp.u = u ;
00374 xbuftmp.areacode = sOutside ;
00375 xbuftmp.distance = kInfinity ;
00376 xbuftmp.isvalid = false ;
00377
00378 xbuf.push_back(xbuftmp) ;
00379
00380 #ifdef G4TWISTDEBUG
00381 G4cout << "solution " << i << " = " << phi << " , " << u << G4endl ;
00382 #endif
00383 }
00384 }
00385 }
00386
00387 nxx = xbuf.size() ;
00388
00389 G4ThreeVector xxonsurface ;
00390 G4ThreeVector surfacenormal ;
00391 G4double deltaX;
00392 G4double theta;
00393 G4double factor;
00394 G4int maxint=30;
00395
00396 for ( register size_t k = 0 ; k<xbuf.size() ; k++ )
00397 {
00398 #ifdef G4TWISTDEBUG
00399 G4cout << "Solution " << k << " : "
00400 << "reconstructed phiR = " << xbuf[k].phi
00401 << ", uR = " << xbuf[k].u << G4endl ;
00402 #endif
00403
00404 phi = xbuf[k].phi ;
00405 u = xbuf[k].u ;
00406
00407 IsConverged = false ;
00408
00409 for ( register int i = 1 ; i<maxint ; i++ )
00410 {
00411 xxonsurface = SurfacePoint(phi,u) ;
00412 surfacenormal = NormAng(phi,u) ;
00413
00414 tmpdist = DistanceToPlaneWithV(p, v, xxonsurface, surfacenormal, tmpxx);
00415 deltaX = ( tmpxx - xxonsurface ).mag() ;
00416 theta = std::fabs(std::acos(v*surfacenormal) - pihalf) ;
00417 if ( theta < 0.001 )
00418 {
00419 factor = 50 ;
00420 IsParallel = true ;
00421 }
00422 else
00423 {
00424 factor = 1 ;
00425 }
00426
00427 #ifdef G4TWISTDEBUG
00428 G4cout << "Step i = " << i << ", distance = " << tmpdist
00429 << ", " << deltaX << G4endl ;
00430 G4cout << "X = " << tmpxx << G4endl ;
00431 #endif
00432
00433 GetPhiUAtX(tmpxx, phi, u) ;
00434
00435
00436 #ifdef G4TWISTDEBUG
00437 G4cout << "approximated phi = " << phi << ", u = " << u << G4endl ;
00438 #endif
00439
00440 if ( deltaX <= factor*ctol ) { IsConverged = true ; break ; }
00441
00442 }
00443
00444 if ( std::fabs(tmpdist)<ctol ) { tmpdist = 0 ; }
00445
00446 #ifdef G4TWISTDEBUG
00447 G4cout << "refined solution " << phi << " , " << u << G4endl ;
00448 G4cout << "distance = " << tmpdist << G4endl ;
00449 G4cout << "local X = " << tmpxx << G4endl ;
00450 #endif
00451
00452 tmpisvalid = false ;
00453
00454 if ( IsConverged )
00455 {
00456 if (validate == kValidateWithTol)
00457 {
00458 tmpareacode = GetAreaCode(tmpxx);
00459 if (!IsOutside(tmpareacode))
00460 {
00461 if (tmpdist >= 0) tmpisvalid = true;
00462 }
00463 }
00464 else if (validate == kValidateWithoutTol)
00465 {
00466 tmpareacode = GetAreaCode(tmpxx, false);
00467 if (IsInside(tmpareacode))
00468 {
00469 if (tmpdist >= 0) { tmpisvalid = true; }
00470 }
00471 }
00472 else
00473 {
00474 G4Exception("G4TwistTrapAlphaSide::DistanceToSurface()",
00475 "GeomSolids0001", FatalException,
00476 "Feature NOT implemented !");
00477 }
00478 }
00479 else
00480 {
00481 tmpdist = kInfinity;
00482 tmpisvalid = false ;
00483 }
00484
00485
00486
00487 xbuf[k].xx = tmpxx ;
00488 xbuf[k].distance = tmpdist ;
00489 xbuf[k].areacode = tmpareacode ;
00490 xbuf[k].isvalid = tmpisvalid ;
00491
00492 }
00493
00494 std::sort(xbuf.begin() , xbuf.end(), DistanceSort ) ;
00495
00496 #ifdef G4TWISTDEBUG
00497 G4cout << G4endl << "list xbuf after sorting : " << G4endl ;
00498 G4cout << G4endl << G4endl ;
00499 #endif
00500
00501
00502
00503 xbuf.erase( std::unique(xbuf.begin(), xbuf.end() , EqualIntersection ),
00504 xbuf.end() );
00505
00506
00507
00508
00509 G4int nxxtmp = xbuf.size() ;
00510
00511 if ( nxxtmp<2 || IsParallel )
00512 {
00513
00514 #ifdef G4TWISTDEBUG
00515 G4cout << "add guess at +z/2 .. " << G4endl ;
00516 #endif
00517
00518 phi = fPhiTwist/2 ;
00519 u = 0 ;
00520
00521 xbuftmp.phi = phi ;
00522 xbuftmp.u = u ;
00523 xbuftmp.areacode = sOutside ;
00524 xbuftmp.distance = kInfinity ;
00525 xbuftmp.isvalid = false ;
00526
00527 xbuf.push_back(xbuftmp) ;
00528
00529 #ifdef G4TWISTDEBUG
00530 G4cout << "add guess at -z/2 .. " << G4endl ;
00531 #endif
00532
00533 phi = -fPhiTwist/2 ;
00534 u = 0 ;
00535
00536 xbuftmp.phi = phi ;
00537 xbuftmp.u = u ;
00538 xbuftmp.areacode = sOutside ;
00539 xbuftmp.distance = kInfinity ;
00540 xbuftmp.isvalid = false ;
00541
00542 xbuf.push_back(xbuftmp) ;
00543
00544 for ( register size_t k = nxxtmp ; k<xbuf.size() ; k++ )
00545 {
00546
00547 #ifdef G4TWISTDEBUG
00548 G4cout << "Solution " << k << " : "
00549 << "reconstructed phiR = " << xbuf[k].phi
00550 << ", uR = " << xbuf[k].u << G4endl ;
00551 #endif
00552
00553 phi = xbuf[k].phi ;
00554 u = xbuf[k].u ;
00555
00556 IsConverged = false ;
00557
00558 for ( register int i = 1 ; i<maxint ; i++ )
00559 {
00560 xxonsurface = SurfacePoint(phi,u) ;
00561 surfacenormal = NormAng(phi,u) ;
00562 tmpdist = DistanceToPlaneWithV(p, v, xxonsurface, surfacenormal, tmpxx);
00563 deltaX = ( tmpxx - xxonsurface ).mag();
00564 theta = std::fabs(std::acos(v*surfacenormal) - pihalf);
00565 if ( theta < 0.001 )
00566 {
00567 factor = 50 ;
00568 }
00569 else
00570 {
00571 factor = 1 ;
00572 }
00573
00574 #ifdef G4TWISTDEBUG
00575 G4cout << "Step i = " << i << ", distance = " << tmpdist
00576 << ", " << deltaX << G4endl
00577 << "X = " << tmpxx << G4endl ;
00578 #endif
00579
00580 GetPhiUAtX(tmpxx, phi, u) ;
00581
00582
00583 #ifdef G4TWISTDEBUG
00584 G4cout << "approximated phi = " << phi << ", u = " << u << G4endl ;
00585 #endif
00586
00587 if ( deltaX <= factor*ctol ) { IsConverged = true ; break ; }
00588
00589 }
00590
00591 if ( std::fabs(tmpdist)<ctol ) { tmpdist = 0; }
00592
00593 #ifdef G4TWISTDEBUG
00594 G4cout << "refined solution " << phi << " , " << u << G4endl ;
00595 G4cout << "distance = " << tmpdist << G4endl ;
00596 G4cout << "local X = " << tmpxx << G4endl ;
00597 #endif
00598
00599 tmpisvalid = false ;
00600
00601 if ( IsConverged )
00602 {
00603 if (validate == kValidateWithTol)
00604 {
00605 tmpareacode = GetAreaCode(tmpxx);
00606 if (!IsOutside(tmpareacode))
00607 {
00608 if (tmpdist >= 0) { tmpisvalid = true; }
00609 }
00610 }
00611 else if (validate == kValidateWithoutTol)
00612 {
00613 tmpareacode = GetAreaCode(tmpxx, false);
00614 if (IsInside(tmpareacode))
00615 {
00616 if (tmpdist >= 0) { tmpisvalid = true; }
00617 }
00618 }
00619 else
00620 {
00621 G4Exception("G4TwistedBoxSide::DistanceToSurface()",
00622 "GeomSolids0001", FatalException,
00623 "Feature NOT implemented !");
00624 }
00625 }
00626 else
00627 {
00628 tmpdist = kInfinity;
00629 tmpisvalid = false ;
00630 }
00631
00632
00633
00634 xbuf[k].xx = tmpxx ;
00635 xbuf[k].distance = tmpdist ;
00636 xbuf[k].areacode = tmpareacode ;
00637 xbuf[k].isvalid = tmpisvalid ;
00638
00639 }
00640 }
00641
00642
00643 std::sort(xbuf.begin() , xbuf.end(), DistanceSort ) ;
00644
00645
00646 xbuf.erase( std::unique(xbuf.begin(), xbuf.end() , EqualIntersection ) ,
00647 xbuf.end() );
00648
00649 #ifdef G4TWISTDEBUG
00650 G4cout << G4endl << "list xbuf after sorting : " << G4endl ;
00651 G4cout << G4endl << G4endl ;
00652 #endif
00653
00654 nxx = xbuf.size() ;
00655
00656 for ( register size_t i = 0 ; i<xbuf.size() ; i++ )
00657 {
00658 distance[i] = xbuf[i].distance;
00659 gxx[i] = ComputeGlobalPoint(xbuf[i].xx);
00660 areacode[i] = xbuf[i].areacode ;
00661 isvalid[i] = xbuf[i].isvalid ;
00662
00663 fCurStatWithV.SetCurrentStatus(i, gxx[i], distance[i], areacode[i],
00664 isvalid[i], nxx, validate, &gp, &gv);
00665 #ifdef G4TWISTDEBUG
00666 G4cout << "element Nr. " << i
00667 << ", local Intersection = " << xbuf[i].xx
00668 << ", distance = " << xbuf[i].distance
00669 << ", u = " << xbuf[i].u
00670 << ", phi = " << xbuf[i].phi
00671 << ", isvalid = " << xbuf[i].isvalid
00672 << G4endl ;
00673 #endif
00674
00675 }
00676
00677 #ifdef G4TWISTDEBUG
00678 G4cout << "G4TwistTrapAlphaSide finished " << G4endl ;
00679 G4cout << nxx << " possible physical solutions found" << G4endl ;
00680 for ( G4int k= 0 ; k< nxx ; k++ )
00681 {
00682 G4cout << "global intersection Point found: " << gxx[k] << G4endl ;
00683 G4cout << "distance = " << distance[k] << G4endl ;
00684 G4cout << "isvalid = " << isvalid[k] << G4endl ;
00685 }
00686 #endif
00687
00688 return nxx ;
00689 }
00690
00691
00692
00693
00694
00695 G4int
00696 G4TwistTrapAlphaSide::DistanceToSurface(const G4ThreeVector &gp,
00697 G4ThreeVector gxx[],
00698 G4double distance[],
00699 G4int areacode[])
00700 {
00701 static const G4double ctol = 0.5 * kCarTolerance;
00702
00703 fCurStat.ResetfDone(kDontValidate, &gp);
00704
00705 if (fCurStat.IsDone())
00706 {
00707 for (register int i=0; i<fCurStat.GetNXX(); i++)
00708 {
00709 gxx[i] = fCurStat.GetXX(i);
00710 distance[i] = fCurStat.GetDistance(i);
00711 areacode[i] = fCurStat.GetAreacode(i);
00712 }
00713 return fCurStat.GetNXX();
00714 }
00715 else
00716 {
00717 for (register int i=0; i<G4VSURFACENXX; i++)
00718 {
00719 distance[i] = kInfinity;
00720 areacode[i] = sOutside;
00721 gxx[i].set(kInfinity, kInfinity, kInfinity);
00722 }
00723 }
00724
00725 G4ThreeVector p = ComputeLocalPoint(gp);
00726 G4ThreeVector xx;
00727 G4ThreeVector xxonsurface ;
00728
00729
00730
00731 G4double phiR = 0 ;
00732 G4double uR = 0 ;
00733
00734 G4ThreeVector surfacenormal ;
00735 G4double deltaX, uMax ;
00736 G4double halfphi = 0.5*fPhiTwist ;
00737
00738 for ( register int i = 1 ; i<20 ; i++ )
00739 {
00740 xxonsurface = SurfacePoint(phiR,uR) ;
00741 surfacenormal = NormAng(phiR,uR) ;
00742 distance[0] = DistanceToPlane(p,xxonsurface,surfacenormal,xx);
00743 deltaX = ( xx - xxonsurface ).mag() ;
00744
00745 #ifdef G4TWISTDEBUG
00746 G4cout << "i = " << i << ", distance = " << distance[0]
00747 << ", " << deltaX << G4endl
00748 << "X = " << xx << G4endl ;
00749 #endif
00750
00751
00752
00753 GetPhiUAtX(xx, phiR, uR) ;
00754
00755 if ( deltaX <= ctol ) { break ; }
00756 }
00757
00758
00759
00760 uMax = GetBoundaryMax(phiR) ;
00761
00762 if ( phiR > halfphi ) { phiR = halfphi ; }
00763 if ( phiR < -halfphi ) { phiR = -halfphi ; }
00764 if ( uR > uMax ) { uR = uMax ; }
00765 if ( uR < -uMax ) { uR = -uMax ; }
00766
00767 xxonsurface = SurfacePoint(phiR,uR) ;
00768 distance[0] = ( p - xx ).mag() ;
00769 if ( distance[0] <= ctol ) { distance[0] = 0 ; }
00770
00771
00772
00773 #ifdef G4TWISTDEBUG
00774 G4cout << "refined solution " << phiR << " , " << uR << " , " << G4endl ;
00775 G4cout << "distance = " << distance[0] << G4endl ;
00776 G4cout << "X = " << xx << G4endl ;
00777 #endif
00778
00779 G4bool isvalid = true;
00780 gxx[0] = ComputeGlobalPoint(xx);
00781
00782 #ifdef G4TWISTDEBUG
00783 G4cout << "intersection Point found: " << gxx[0] << G4endl ;
00784 G4cout << "distance = " << distance[0] << G4endl ;
00785 #endif
00786
00787 fCurStat.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
00788 isvalid, 1, kDontValidate, &gp);
00789 return 1;
00790 }
00791
00792
00793
00794
00795
00796 G4int
00797 G4TwistTrapAlphaSide::GetAreaCode(const G4ThreeVector &xx, G4bool withTol)
00798 {
00799
00800
00801
00802 static const G4double ctol = 0.5 * kCarTolerance;
00803
00804 G4double phi ;
00805 G4double yprime ;
00806 GetPhiUAtX(xx, phi,yprime ) ;
00807
00808 G4double fYAxisMax = GetBoundaryMax(phi) ;
00809 G4double fYAxisMin = GetBoundaryMin(phi) ;
00810
00811 #ifdef G4TWISTDEBUG
00812 G4cout << "GetAreaCode: phi = " << phi << G4endl ;
00813 G4cout << "GetAreaCode: yprime = " << yprime << G4endl ;
00814 G4cout << "Intervall is " << fYAxisMin << " to " << fYAxisMax << G4endl ;
00815 #endif
00816
00817 G4int areacode = sInside;
00818
00819 if (fAxis[0] == kYAxis && fAxis[1] == kZAxis)
00820 {
00821 G4int zaxis = 1;
00822
00823 if (withTol)
00824 {
00825 G4bool isoutside = false;
00826
00827
00828
00829 if (yprime < fYAxisMin + ctol)
00830 {
00831 areacode |= (sAxis0 & (sAxisY | sAxisMin)) | sBoundary;
00832 if (yprime <= fYAxisMin - ctol) { isoutside = true; }
00833
00834 }
00835 else if (yprime > fYAxisMax - ctol)
00836 {
00837 areacode |= (sAxis0 & (sAxisY | sAxisMax)) | sBoundary;
00838 if (yprime >= fYAxisMax + ctol) { isoutside = true; }
00839 }
00840
00841
00842
00843 if (xx.z() < fAxisMin[zaxis] + ctol)
00844 {
00845 areacode |= (sAxis1 & (sAxisZ | sAxisMin));
00846
00847 if (areacode & sBoundary)
00848 { areacode |= sCorner; }
00849
00850 else
00851 { areacode |= sBoundary; }
00852 if (xx.z() <= fAxisMin[zaxis] - ctol) { isoutside = true; }
00853 }
00854 else if (xx.z() > fAxisMax[zaxis] - ctol)
00855 {
00856 areacode |= (sAxis1 & (sAxisZ | sAxisMax));
00857
00858 if (areacode & sBoundary)
00859 { areacode |= sCorner; }
00860 else
00861 { areacode |= sBoundary; }
00862 if (xx.z() >= fAxisMax[zaxis] + ctol) { isoutside = true; }
00863 }
00864
00865
00866
00867
00868 if (isoutside)
00869 {
00870 G4int tmpareacode = areacode & (~sInside);
00871 areacode = tmpareacode;
00872 }
00873 else if ((areacode & sBoundary) != sBoundary)
00874 {
00875 areacode |= (sAxis0 & sAxisY) | (sAxis1 & sAxisZ);
00876 }
00877
00878 }
00879 else
00880 {
00881
00882
00883 if (yprime < fYAxisMin )
00884 {
00885 areacode |= (sAxis0 & (sAxisY | sAxisMin)) | sBoundary;
00886 }
00887 else if (yprime > fYAxisMax)
00888 {
00889 areacode |= (sAxis0 & (sAxisY | sAxisMax)) | sBoundary;
00890 }
00891
00892
00893
00894 if (xx.z() < fAxisMin[zaxis])
00895 {
00896 areacode |= (sAxis1 & (sAxisZ | sAxisMin));
00897 if (areacode & sBoundary)
00898 { areacode |= sCorner; }
00899 else
00900 { areacode |= sBoundary; }
00901 }
00902 else if (xx.z() > fAxisMax[zaxis])
00903 {
00904 areacode |= (sAxis1 & (sAxisZ | sAxisMax)) ;
00905 if (areacode & sBoundary)
00906 { areacode |= sCorner; }
00907 else
00908 { areacode |= sBoundary; }
00909 }
00910
00911 if ((areacode & sBoundary) != sBoundary)
00912 {
00913 areacode |= (sAxis0 & sAxisY) | (sAxis1 & sAxisZ);
00914 }
00915 }
00916 return areacode;
00917 }
00918 else
00919 {
00920 G4Exception("G4TwistTrapAlphaSide::GetAreaCode()",
00921 "GeomSolids0001", FatalException,
00922 "Feature NOT implemented !");
00923 }
00924 return areacode;
00925 }
00926
00927
00928
00929
00930 void G4TwistTrapAlphaSide::SetCorners()
00931 {
00932
00933
00934
00935 if (fAxis[0] == kYAxis && fAxis[1] == kZAxis)
00936 {
00937
00938 G4double x, y, z;
00939
00940
00941
00942 x = -fdeltaX/2. + (fDx1 - fDy1*fTAlph)*std::cos(fPhiTwist/2.)
00943 - fDy1*std::sin(fPhiTwist/2.);
00944 y = -fdeltaY/2. - fDy1*std::cos(fPhiTwist/2.)
00945 + (-fDx1 + fDy1*fTAlph)*std::sin(fPhiTwist/2.);
00946 z = -fDz ;
00947
00948
00949
00950 SetCorner(sC0Min1Min, x, y, z);
00951
00952
00953
00954 x = -fdeltaX/2. + (fDx2 + fDy1*fTAlph)*std::cos(fPhiTwist/2.)
00955 + fDy1*std::sin(fPhiTwist/2.);
00956 y = -fdeltaY/2. + fDy1*std::cos(fPhiTwist/2.)
00957 - (fDx2 + fDy1*fTAlph)*std::sin(fPhiTwist/2.);
00958 z = -fDz ;
00959
00960
00961
00962 SetCorner(sC0Max1Min, x, y, z);
00963
00964
00965
00966 x = fdeltaX/2. + (fDx4 + fDy2*fTAlph)*std::cos(fPhiTwist/2.)
00967 - fDy2*std::sin(fPhiTwist/2.);
00968 y = fdeltaY/2. + fDy2*std::cos(fPhiTwist/2.)
00969 + (fDx4 + fDy2*fTAlph)*std::sin(fPhiTwist/2.);
00970 z = fDz ;
00971
00972
00973
00974 SetCorner(sC0Max1Max, x, y, z);
00975
00976
00977 x = fdeltaX/2. + (fDx3 - fDy2*fTAlph)*std::cos(fPhiTwist/2.)
00978 + fDy2*std::sin(fPhiTwist/2.) ;
00979 y = fdeltaY/2. - fDy2*std::cos(fPhiTwist/2.)
00980 + (fDx3 - fDy2*fTAlph)*std::sin(fPhiTwist/2.) ;
00981 z = fDz ;
00982
00983
00984
00985 SetCorner(sC0Min1Max, x, y, z);
00986
00987 }
00988 else
00989 {
00990 G4Exception("G4TwistTrapAlphaSide::SetCorners()",
00991 "GeomSolids0001", FatalException,
00992 "Method NOT implemented !");
00993 }
00994 }
00995
00996
00997
00998
00999 void G4TwistTrapAlphaSide::SetBoundaries()
01000 {
01001
01002
01003
01004 G4ThreeVector direction;
01005
01006 if (fAxis[0] == kYAxis && fAxis[1] == kZAxis)
01007 {
01008
01009 direction = GetCorner(sC0Min1Max) - GetCorner(sC0Min1Min);
01010 direction = direction.unit();
01011 SetBoundary(sAxis0 & (sAxisY | sAxisMin), direction,
01012 GetCorner(sC0Min1Min), sAxisZ) ;
01013
01014
01015 direction = GetCorner(sC0Max1Max) - GetCorner(sC0Max1Min);
01016 direction = direction.unit();
01017 SetBoundary(sAxis0 & (sAxisY | sAxisMax), direction,
01018 GetCorner(sC0Max1Min), sAxisZ);
01019
01020
01021 direction = GetCorner(sC0Max1Min) - GetCorner(sC0Min1Min);
01022 direction = direction.unit();
01023 SetBoundary(sAxis1 & (sAxisZ | sAxisMin), direction,
01024 GetCorner(sC0Min1Min), sAxisY);
01025
01026
01027 direction = GetCorner(sC0Max1Max) - GetCorner(sC0Min1Max);
01028 direction = direction.unit();
01029 SetBoundary(sAxis1 & (sAxisZ | sAxisMax), direction,
01030 GetCorner(sC0Min1Max), sAxisY);
01031
01032 }
01033 else
01034 {
01035 G4Exception("G4TwistTrapAlphaSide::SetCorners()",
01036 "GeomSolids0001", FatalException,
01037 "Feature NOT implemented !");
01038 }
01039 }
01040
01041
01042
01043
01044 void
01045 G4TwistTrapAlphaSide::GetPhiUAtX( G4ThreeVector p, G4double &phi, G4double &u )
01046 {
01047
01048
01049
01050
01051
01052
01053 phi = p.z()/(2*fDz)*fPhiTwist ;
01054 u = (fPhiTwist*(2*fDx1*fDx1 - 2*fDx2*fDx2 - fa1md1*(fDx3 + fDx4)
01055 - 4*(fDx3plus1 + fDx4plus2)*fDy1*fTAlph)
01056 - 2*(2*fDx1*fDx1 - 2*fDx2*fDx2 + fa1md1*(fDx3 + fDx4)
01057 + 4*(fDx3minus1 + fDx4minus2)*fDy1*fTAlph)*phi
01058 - 4*(fa1md1*(fdeltaX*phi - fPhiTwist*p.x())
01059 + 4*fDy1*(fdeltaY*phi + fdeltaX*fTAlph*phi
01060 - fPhiTwist*(fTAlph*p.x() + p.y())))*std::cos(phi)
01061 - 4*(fa1md1*fdeltaY*phi - 4*fdeltaX*fDy1*phi
01062 + 4*fdeltaY*fDy1*fTAlph*phi + 4*fDy1*fPhiTwist*p.x()
01063 - fPhiTwist*(fa1md1 + 4*fDy1*fTAlph)*p.y())*std::sin(phi))
01064 /(fDy1* fPhiTwist*((std::fabs(((fa1md1 + 4*fDy1*fTAlph)*std::cos(phi))
01065 /fDy1 - 4*std::sin(phi)))
01066 *(std::fabs(((fa1md1 + 4*fDy1*fTAlph)*std::cos(phi))
01067 /fDy1 - 4*std::sin(phi)))
01068 + (std::fabs(4*std::cos(phi)
01069 + ((fa1md1 + 4*fDy1*fTAlph)*std::sin(phi))/fDy1))
01070 * (std::fabs(4*std::cos(phi)
01071 + ((fa1md1 + 4*fDy1*fTAlph)*std::sin(phi))/fDy1)))) ;
01072 }
01073
01074
01075
01076
01077 G4ThreeVector
01078 G4TwistTrapAlphaSide::ProjectPoint(const G4ThreeVector &p, G4bool isglobal)
01079 {
01080
01081
01082 G4ThreeVector tmpp;
01083 if (isglobal)
01084 {
01085 tmpp = fRot.inverse()*p - fTrans;
01086 }
01087 else
01088 {
01089 tmpp = p;
01090 }
01091
01092 G4double phi ;
01093 G4double u ;
01094
01095 GetPhiUAtX( tmpp, phi, u ) ;
01096
01097
01098 G4ThreeVector xx = SurfacePoint(phi,u) ;
01099
01100
01101 if (isglobal)
01102 {
01103 return (fRot * xx + fTrans);
01104 }
01105 else
01106 {
01107 return xx;
01108 }
01109 }
01110
01111
01112
01113
01114 void
01115 G4TwistTrapAlphaSide::GetFacets( G4int k, G4int n, G4double xyz[][3],
01116 G4int faces[][4], G4int iside )
01117 {
01118
01119 G4double phi ;
01120 G4double b ;
01121
01122 G4double z, u ;
01123 G4ThreeVector p ;
01124
01125 G4int nnode ;
01126 G4int nface ;
01127
01128
01129
01130 for ( register int i = 0 ; i<n ; i++ )
01131 {
01132 z = -fDz+i*(2.*fDz)/(n-1) ;
01133 phi = z*fPhiTwist/(2*fDz) ;
01134 b = GetValueB(phi) ;
01135
01136 for ( register int j = 0 ; j<k ; j++ )
01137 {
01138 nnode = GetNode(i,j,k,n,iside) ;
01139 u = -b/2 +j*b/(k-1) ;
01140 p = SurfacePoint(phi,u,true) ;
01141
01142 xyz[nnode][0] = p.x() ;
01143 xyz[nnode][1] = p.y() ;
01144 xyz[nnode][2] = p.z() ;
01145
01146 if ( i<n-1 && j<k-1 )
01147 {
01148 nface = GetFace(i,j,k,n,iside) ;
01149 faces[nface][0] = GetEdgeVisibility(i,j,k,n,0,-1)
01150 * (GetNode(i ,j ,k,n,iside)+1) ;
01151 faces[nface][1] = GetEdgeVisibility(i,j,k,n,1,-1)
01152 * (GetNode(i ,j+1,k,n,iside)+1) ;
01153 faces[nface][2] = GetEdgeVisibility(i,j,k,n,2,-1)
01154 * (GetNode(i+1,j+1,k,n,iside)+1) ;
01155 faces[nface][3] = GetEdgeVisibility(i,j,k,n,3,-1)
01156 * (GetNode(i+1,j ,k,n,iside)+1) ;
01157 }
01158 }
01159 }
01160 }