Geant4  10.01
G4TwistTrapParallelSide.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 // $Id: G4TwistTrapParallelSide.cc,v
28 //
29 //
30 // --------------------------------------------------------------------
31 // GEANT 4 class source file
32 //
33 //
34 // G4TwistTrapParallelSide.cc
35 //
36 // Author:
37 //
38 // Oliver Link (Oliver.Link@cern.ch)
39 //
40 // --------------------------------------------------------------------
41 
42 #include <cmath>
43 
45 #include "G4PhysicalConstants.hh"
46 #include "G4JTPolynomialSolver.hh"
47 
48 //=====================================================================
49 //* constructors ------------------------------------------------------
50 
52  G4double PhiTwist, // twist angle
53  G4double pDz, // half z lenght
54  G4double pTheta, // direction between end planes
55  G4double pPhi, // defined by polar and azimutal angles.
56  G4double pDy1, // half y length at -pDz
57  G4double pDx1, // half x length at -pDz,-pDy
58  G4double pDx2, // half x length at -pDz,+pDy
59  G4double pDy2, // half y length at +pDz
60  G4double pDx3, // half x length at +pDz,-pDy
61  G4double pDx4, // half x length at +pDz,+pDy
62  G4double pAlph, // tilt angle at +pDz
63  G4double AngleSide // parity
64  )
65  : G4VTwistSurface(name)
66 {
67 
68  fAxis[0] = kXAxis; // in local coordinate system
69  fAxis[1] = kZAxis;
70  fAxisMin[0] = -kInfinity ; // X Axis boundary
71  fAxisMax[0] = kInfinity ; // depends on z !!
72  fAxisMin[1] = -pDz ; // Z Axis boundary
73  fAxisMax[1] = pDz ;
74 
75  fDx1 = pDx1 ;
76  fDx2 = pDx2 ;
77  fDx3 = pDx3 ;
78  fDx4 = pDx4 ;
79 
80  fDy1 = pDy1 ;
81  fDy2 = pDy2 ;
82 
83  fDz = pDz ;
84 
85  fAlph = pAlph ;
86  fTAlph = std::tan(fAlph) ;
87 
88  fTheta = pTheta ;
89  fPhi = pPhi ;
90 
91  // precalculate frequently used parameters
92  fDx4plus2 = fDx4 + fDx2 ;
93  fDx4minus2 = fDx4 - fDx2 ;
94  fDx3plus1 = fDx3 + fDx1 ;
95  fDx3minus1 = fDx3 - fDx1 ;
96  fDy2plus1 = fDy2 + fDy1 ;
97  fDy2minus1 = fDy2 - fDy1 ;
98 
99  fa1md1 = 2*fDx2 - 2*fDx1 ;
100  fa2md2 = 2*fDx4 - 2*fDx3 ;
101 
102  fPhiTwist = PhiTwist ; // dphi
103  fAngleSide = AngleSide ; // 0,90,180,270 deg
104 
105  fdeltaX = 2 * fDz * std::tan(fTheta) * std::cos(fPhi) ; // dx in surface equation
106  fdeltaY = 2 * fDz * std::tan(fTheta) * std::sin(fPhi) ; // dy in surface equation
107 
108  fRot.rotateZ( AngleSide ) ;
109 
110  fTrans.set(0, 0, 0); // No Translation
111  fIsValidNorm = false;
112 
113  SetCorners() ;
114  SetBoundaries() ;
115 
116 }
117 
118 
119 //=====================================================================
120 //* Fake default constructor ------------------------------------------
121 
123  : G4VTwistSurface(a), fTheta(0.), fPhi(0.), fDy1(0.), fDx1(0.), fDx2(0.),
124  fDy2(0.), fDx3(0.), fDx4(0.), fDz(0.), fAlph(0.), fTAlph(0.), fPhiTwist(0.),
125  fAngleSide(0.), fdeltaX(0.), fdeltaY(0.), fDx4plus2(0.), fDx4minus2(0.),
126  fDx3plus1(0.), fDx3minus1(0.), fDy2plus1(0.), fDy2minus1(0.), fa1md1(0.),
127  fa2md2(0.)
128 {
129 }
130 
131 
132 //=====================================================================
133 //* destructor --------------------------------------------------------
134 
136 {
137 }
138 
139 //=====================================================================
140 //* GetNormal ---------------------------------------------------------
141 
143  G4bool isGlobal)
144 {
145  // GetNormal returns a normal vector at a surface (or very close
146  // to surface) point at tmpxx.
147  // If isGlobal=true, it returns the normal in global coordinate.
148  //
149 
150  G4ThreeVector xx;
151  if (isGlobal) {
152  xx = ComputeLocalPoint(tmpxx);
153  if ((xx - fCurrentNormal.p).mag() < 0.5 * kCarTolerance) {
155  }
156  } else {
157  xx = tmpxx;
158  if (xx == fCurrentNormal.p) {
159  return fCurrentNormal.normal;
160  }
161  }
162 
163  G4double phi ;
164  G4double u ;
165 
166  GetPhiUAtX(xx,phi,u) ; // phi,u for point xx close to surface
167 
168  G4ThreeVector normal = NormAng(phi,u) ; // the normal vector at phi,u
169 
170 #ifdef G4TWISTDEBUG
171  G4cout << "normal vector = " << normal << G4endl ;
172  G4cout << "phi = " << phi << " , u = " << u << G4endl ;
173 #endif
174 
175  // normal = normal/normal.mag() ;
176 
177  if (isGlobal) {
179  } else {
180  fCurrentNormal.normal = normal.unit();
181  }
182  return fCurrentNormal.normal;
183 }
184 
185 //=====================================================================
186 //* DistanceToSurface -------------------------------------------------
187 
189  const G4ThreeVector &gv,
190  G4ThreeVector gxx[],
191  G4double distance[],
192  G4int areacode[],
193  G4bool isvalid[],
194  EValidate validate)
195 {
196 
197  static const G4double pihalf = pi/2 ;
198  const G4double ctol = 0.5 * kCarTolerance;
199 
200  G4bool IsParallel = false ;
201  G4bool IsConverged = false ;
202 
203  G4int nxx = 0 ; // number of physical solutions
204 
205  fCurStatWithV.ResetfDone(validate, &gp, &gv);
206 
207  if (fCurStatWithV.IsDone()) {
208  G4int i;
209  for (i=0; i<fCurStatWithV.GetNXX(); i++) {
210  gxx[i] = fCurStatWithV.GetXX(i);
211  distance[i] = fCurStatWithV.GetDistance(i);
212  areacode[i] = fCurStatWithV.GetAreacode(i);
213  isvalid[i] = fCurStatWithV.IsValid(i);
214  }
215  return fCurStatWithV.GetNXX();
216  } else {
217 
218  // initialize
219  G4int i;
220  for (i=0; i<G4VSURFACENXX ; i++) {
221  distance[i] = kInfinity;
222  areacode[i] = sOutside;
223  isvalid[i] = false;
224  gxx[i].set(kInfinity, kInfinity, kInfinity);
225  }
226  }
227 
230 
231 #ifdef G4TWISTDEBUG
232  G4cout << "Local point p = " << p << G4endl ;
233  G4cout << "Local direction v = " << v << G4endl ;
234 #endif
235 
236  G4double phi,u ; // parameters
237 
238  // temporary variables
239 
240  G4double tmpdist = kInfinity ;
241  G4ThreeVector tmpxx;
242  G4int tmpareacode = sOutside ;
243  G4bool tmpisvalid = false ;
244 
245  std::vector<Intersection> xbuf ;
246  Intersection xbuftmp ;
247 
248  // prepare some variables for the intersection finder
249 
250  G4double L = 2*fDz ;
251 
252  G4double phixz = fPhiTwist * ( p.x() * v.z() - p.z() * v.x() ) ;
253  G4double phiyz = fPhiTwist * ( p.y() * v.z() - p.z() * v.y() ) ;
254 
255  // special case vz = 0
256 
257  if ( v.z() == 0. ) {
258 
259  if ( std::fabs(p.z()) <= L ) { // intersection possible in z
260 
261  phi = p.z() * fPhiTwist / L ; // phi is determined by the z-position
262 
263  u = (2*(fdeltaY*phi*v.x() - fPhiTwist*p.y()*v.x() - fdeltaX*phi*v.y()
264  + fPhiTwist*p.x()*v.y()) + (fDy2plus1*fPhiTwist
265  + 2*fDy2minus1*phi)*(v.x()*std::cos(phi) + v.y()*std::sin(phi)))
266  / (2.* fPhiTwist*(v.y()*std::cos(phi) - v.x()*std::sin(phi)));
267 
268  xbuftmp.phi = phi ;
269  xbuftmp.u = u ;
270  xbuftmp.areacode = sOutside ;
271  xbuftmp.distance = kInfinity ;
272  xbuftmp.isvalid = false ;
273 
274  xbuf.push_back(xbuftmp) ; // store it to xbuf
275 
276  }
277 
278  else { // no intersection possible
279 
280  distance[0] = kInfinity;
281  gxx[0].set(kInfinity,kInfinity,kInfinity);
282  isvalid[0] = false ;
283  areacode[0] = sOutside ;
284  fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0],
285  areacode[0], isvalid[0],
286  0, validate, &gp, &gv);
287 
288  return 0;
289 
290 
291  } // end std::fabs(p.z() <= L
292 
293  } // end v.z() == 0
294 
295 
296  // general solution for non-zero vz
297 
298  else {
299 
300  G4double c[9],srd[8],si[8] ;
301 
302  c[8] = -3600*(-2*phiyz + fDy2plus1*fPhiTwist*v.z()) ;
303  c[7] = -7200*(phixz - 2*fDz*v.y() + (fdeltaY + fDy2minus1)*v.z()) ;
304  c[6] = 120*(-52*phiyz - 120*fDz*v.x() + 60*fdeltaX*v.z() + 11*fDy2plus1*fPhiTwist*v.z()) ;
305  c[5] = 240*(16*phixz - 52*fDz*v.y() + 26*fdeltaY*v.z() + 11*fDy2minus1*v.z()) ;
306  c[4] = 12*(127*phiyz + 640*fDz*v.x() - 320*fdeltaX*v.z() + 4*fDy2plus1*fPhiTwist*v.z()) ;
307  c[3] = -404*phixz + 3048*fDz*v.y() - 1524*fdeltaY*v.z() + 96*fDy2minus1*v.z() ;
308  c[2] = -72*phiyz + 404*(-2*fDz*v.x() + fdeltaX*v.z()) ;
309  c[1] = 12*(phixz - 12*fDz*v.y() + 6*fdeltaY*v.z()) ;
310  c[0] = 24*fDz*v.x() - 12*fdeltaX*v.z() ;
311 
312 
313 #ifdef G4TWISTDEBUG
314  G4cout << "coef = " << c[0] << " "
315  << c[1] << " "
316  << c[2] << " "
317  << c[3] << " "
318  << c[4] << " "
319  << c[5] << " "
320  << c[6] << " "
321  << c[7] << " "
322  << c[8] << G4endl ;
323 #endif
324 
325  G4JTPolynomialSolver trapEq ;
326  G4int num = trapEq.FindRoots(c,8,srd,si);
327 
328 
329  for (G4int i = 0 ; i<num ; i++ ) { // loop over all mathematical solutions
330  if ( si[i]==0.0 ) { // only real solutions
331 #ifdef G4TWISTDEBUG
332  G4cout << "Solution " << i << " : " << srd[i] << G4endl ;
333 #endif
334  phi = std::fmod(srd[i] , pihalf) ;
335 
336  u = (1/std::cos(phi)*(2*phixz + 4*fDz*phi*v.x() - 2*fdeltaX*phi*v.z() + (fDy2plus1*fPhiTwist + 2*fDy2minus1*phi)*v.z()* std::sin(phi)))/(2.*fPhiTwist*v.z()) ;
337 
338  xbuftmp.phi = phi ;
339  xbuftmp.u = u ;
340  xbuftmp.areacode = sOutside ;
341  xbuftmp.distance = kInfinity ;
342  xbuftmp.isvalid = false ;
343 
344  xbuf.push_back(xbuftmp) ; // store it to xbuf
345 
346 #ifdef G4TWISTDEBUG
347  G4cout << "solution " << i << " = " << phi << " , " << u << G4endl ;
348 #endif
349 
350  } // end if real solution
351  } // end loop i
352 
353  } // end general case
354 
355 
356  nxx = xbuf.size() ; // save the number of solutions
357 
358  G4ThreeVector xxonsurface ; // point on surface
359  G4ThreeVector surfacenormal ; // normal vector
360  G4double deltaX ; // distance between intersection point and point on surface
361  G4double theta ; // angle between track and surfacenormal
362  G4double factor ; // a scaling factor
363  G4int maxint = 30 ; // number of iterations
364 
365 
366  for ( size_t k = 0 ; k<xbuf.size() ; k++ ) {
367 
368 #ifdef G4TWISTDEBUG
369  G4cout << "Solution " << k << " : "
370  << "reconstructed phiR = " << xbuf[k].phi
371  << ", uR = " << xbuf[k].u << G4endl ;
372 #endif
373 
374  phi = xbuf[k].phi ; // get the stored values for phi and u
375  u = xbuf[k].u ;
376 
377  IsConverged = false ; // no convergence at the beginning
378 
379  for ( G4int i = 1 ; i<maxint ; i++ ) {
380 
381  xxonsurface = SurfacePoint(phi,u) ;
382  surfacenormal = NormAng(phi,u) ;
383  tmpdist = DistanceToPlaneWithV(p, v, xxonsurface, surfacenormal, tmpxx);
384  deltaX = ( tmpxx - xxonsurface ).mag() ;
385  theta = std::fabs(std::acos(v*surfacenormal) - pihalf) ;
386  if ( theta < 0.001 ) {
387  factor = 50 ;
388  IsParallel = true ;
389  }
390  else {
391  factor = 1 ;
392  }
393 
394 #ifdef G4TWISTDEBUG
395  G4cout << "Step i = " << i << ", distance = " << tmpdist << ", " << deltaX << G4endl ;
396  G4cout << "X = " << tmpxx << G4endl ;
397 #endif
398 
399  GetPhiUAtX(tmpxx, phi, u) ; // the new point xx is accepted and phi/u replaced
400 
401 #ifdef G4TWISTDEBUG
402  G4cout << "approximated phi = " << phi << ", u = " << u << G4endl ;
403 #endif
404 
405  if ( deltaX <= factor*ctol ) { IsConverged = true ; break ; }
406 
407  } // end iterative loop (i)
408 
409 
410  // new code 21.09.05 O.Link
411  if ( std::fabs(tmpdist)<ctol ) tmpdist = 0 ;
412 
413 
414 #ifdef G4TWISTDEBUG
415  G4cout << "refined solution " << phi << " , " << u << G4endl ;
416  G4cout << "distance = " << tmpdist << G4endl ;
417  G4cout << "local X = " << tmpxx << G4endl ;
418 #endif
419 
420  tmpisvalid = false ; // init
421 
422  if ( IsConverged ) {
423 
424  if (validate == kValidateWithTol) {
425  tmpareacode = GetAreaCode(tmpxx);
426  if (!IsOutside(tmpareacode)) {
427  if (tmpdist >= 0) tmpisvalid = true;
428  }
429  } else if (validate == kValidateWithoutTol) {
430  tmpareacode = GetAreaCode(tmpxx, false);
431  if (IsInside(tmpareacode)) {
432  if (tmpdist >= 0) tmpisvalid = true;
433  }
434  } else { // kDontValidate
435  G4Exception("G4TwistTrapParallelSide::DistanceToSurface()",
436  "GeomSolids0001", FatalException,
437  "Feature NOT implemented !");
438  }
439 
440  }
441  else {
442  tmpdist = kInfinity; // no convergence after 10 steps
443  tmpisvalid = false ; // solution is not vaild
444  }
445 
446 
447  // store the found values
448  xbuf[k].xx = tmpxx ;
449  xbuf[k].distance = tmpdist ;
450  xbuf[k].areacode = tmpareacode ;
451  xbuf[k].isvalid = tmpisvalid ;
452 
453 
454  } // end loop over physical solutions (variable k)
455 
456 
457  std::sort(xbuf.begin() , xbuf.end(), DistanceSort ) ; // sorting
458 
459 #ifdef G4TWISTDEBUG
460  G4cout << G4endl << "list xbuf after sorting : " << G4endl ;
461  G4cout << G4endl << G4endl ;
462 #endif
463 
464 
465  // erase identical intersection (within kCarTolerance)
466  xbuf.erase( std::unique(xbuf.begin(), xbuf.end() , EqualIntersection ) , xbuf.end() ) ;
467 
468 
469  // add guesses
470 
471  G4int nxxtmp = xbuf.size() ;
472 
473  if ( nxxtmp<2 || IsParallel ) {
474 
475  // positive end
476 #ifdef G4TWISTDEBUG
477  G4cout << "add guess at +z/2 .. " << G4endl ;
478 #endif
479 
480  phi = fPhiTwist/2 ;
481  u = 0 ;
482 
483  xbuftmp.phi = phi ;
484  xbuftmp.u = u ;
485  xbuftmp.areacode = sOutside ;
486  xbuftmp.distance = kInfinity ;
487  xbuftmp.isvalid = false ;
488 
489  xbuf.push_back(xbuftmp) ; // store it to xbuf
490 
491 
492 #ifdef G4TWISTDEBUG
493  G4cout << "add guess at -z/2 .. " << G4endl ;
494 #endif
495 
496  phi = -fPhiTwist/2 ;
497  u = 0 ;
498 
499  xbuftmp.phi = phi ;
500  xbuftmp.u = u ;
501  xbuftmp.areacode = sOutside ;
502  xbuftmp.distance = kInfinity ;
503  xbuftmp.isvalid = false ;
504 
505  xbuf.push_back(xbuftmp) ; // store it to xbuf
506 
507  for ( size_t k = nxxtmp ; k<xbuf.size() ; k++ ) {
508 
509 #ifdef G4TWISTDEBUG
510  G4cout << "Solution " << k << " : "
511  << "reconstructed phiR = " << xbuf[k].phi
512  << ", uR = " << xbuf[k].u << G4endl ;
513 #endif
514 
515  phi = xbuf[k].phi ; // get the stored values for phi and u
516  u = xbuf[k].u ;
517 
518  IsConverged = false ; // no convergence at the beginning
519 
520  for ( G4int i = 1 ; i<maxint ; i++ ) {
521 
522  xxonsurface = SurfacePoint(phi,u) ;
523  surfacenormal = NormAng(phi,u) ;
524  tmpdist = DistanceToPlaneWithV(p, v, xxonsurface, surfacenormal, tmpxx);
525  deltaX = ( tmpxx - xxonsurface ).mag() ;
526  theta = std::fabs(std::acos(v*surfacenormal) - pihalf) ;
527  if ( theta < 0.001 ) {
528  factor = 50 ;
529  }
530  else {
531  factor = 1 ;
532  }
533 
534 #ifdef G4TWISTDEBUG
535  G4cout << "Step i = " << i << ", distance = " << tmpdist << ", " << deltaX << G4endl ;
536  G4cout << "X = " << tmpxx << G4endl ;
537 #endif
538 
539  GetPhiUAtX(tmpxx, phi, u) ; // the new point xx is accepted and phi/u replaced
540 
541 #ifdef G4TWISTDEBUG
542  G4cout << "approximated phi = " << phi << ", u = " << u << G4endl ;
543 #endif
544 
545  if ( deltaX <= factor*ctol ) { IsConverged = true ; break ; }
546 
547  } // end iterative loop (i)
548 
549 
550  // new code 21.09.05 O.Link
551  if ( std::fabs(tmpdist)<ctol ) tmpdist = 0 ;
552 
553 
554 #ifdef G4TWISTDEBUG
555  G4cout << "refined solution " << phi << " , " << u << G4endl ;
556  G4cout << "distance = " << tmpdist << G4endl ;
557  G4cout << "local X = " << tmpxx << G4endl ;
558 #endif
559 
560  tmpisvalid = false ; // init
561 
562  if ( IsConverged ) {
563 
564  if (validate == kValidateWithTol) {
565  tmpareacode = GetAreaCode(tmpxx);
566  if (!IsOutside(tmpareacode)) {
567  if (tmpdist >= 0) tmpisvalid = true;
568  }
569  } else if (validate == kValidateWithoutTol) {
570  tmpareacode = GetAreaCode(tmpxx, false);
571  if (IsInside(tmpareacode)) {
572  if (tmpdist >= 0) tmpisvalid = true;
573  }
574  } else { // kDontValidate
575  G4Exception("G4TwistedBoxSide::DistanceToSurface()",
576  "GeomSolids0001", FatalException,
577  "Feature NOT implemented !");
578  }
579 
580  }
581  else {
582  tmpdist = kInfinity; // no convergence after 10 steps
583  tmpisvalid = false ; // solution is not vaild
584  }
585 
586 
587  // store the found values
588  xbuf[k].xx = tmpxx ;
589  xbuf[k].distance = tmpdist ;
590  xbuf[k].areacode = tmpareacode ;
591  xbuf[k].isvalid = tmpisvalid ;
592 
593 
594  } // end loop over physical solutions
595 
596 
597  } // end less than 2 solutions
598 
599 
600  // sort again
601  std::sort(xbuf.begin() , xbuf.end(), DistanceSort ) ; // sorting
602 
603  // erase identical intersection (within kCarTolerance)
604  xbuf.erase( std::unique(xbuf.begin(), xbuf.end() , EqualIntersection ) , xbuf.end() ) ;
605 
606 #ifdef G4TWISTDEBUG
607  G4cout << G4endl << "list xbuf after sorting : " << G4endl ;
608  G4cout << G4endl << G4endl ;
609 #endif
610 
611  nxx = xbuf.size() ; // determine number of solutions again.
612 
613  for ( size_t i = 0 ; i<xbuf.size() ; i++ ) {
614 
615  distance[i] = xbuf[i].distance;
616  gxx[i] = ComputeGlobalPoint(xbuf[i].xx);
617  areacode[i] = xbuf[i].areacode ;
618  isvalid[i] = xbuf[i].isvalid ;
619 
620  fCurStatWithV.SetCurrentStatus(i, gxx[i], distance[i], areacode[i],
621  isvalid[i], nxx, validate, &gp, &gv);
622 
623 #ifdef G4TWISTDEBUG
624  G4cout << "element Nr. " << i
625  << ", local Intersection = " << xbuf[i].xx
626  << ", distance = " << xbuf[i].distance
627  << ", u = " << xbuf[i].u
628  << ", phi = " << xbuf[i].phi
629  << ", isvalid = " << xbuf[i].isvalid
630  << G4endl ;
631 #endif
632 
633  } // end for( i ) loop
634 
635 
636 #ifdef G4TWISTDEBUG
637  G4cout << "G4TwistTrapParallelSide finished " << G4endl ;
638  G4cout << nxx << " possible physical solutions found" << G4endl ;
639  for ( G4int k= 0 ; k< nxx ; k++ ) {
640  G4cout << "global intersection Point found: " << gxx[k] << G4endl ;
641  G4cout << "distance = " << distance[k] << G4endl ;
642  G4cout << "isvalid = " << isvalid[k] << G4endl ;
643  }
644 #endif
645 
646  return nxx ;
647 
648 }
649 
650 
651 
652 //=====================================================================
653 //* DistanceToSurface -------------------------------------------------
654 
656  G4ThreeVector gxx[],
657  G4double distance[],
658  G4int areacode[])
659 {
660  // to do
661 
662  const G4double ctol = 0.5 * kCarTolerance;
663 
665 
666  if (fCurStat.IsDone()) {
667  G4int i;
668  for (i=0; i<fCurStat.GetNXX(); i++) {
669  gxx[i] = fCurStat.GetXX(i);
670  distance[i] = fCurStat.GetDistance(i);
671  areacode[i] = fCurStat.GetAreacode(i);
672  }
673  return fCurStat.GetNXX();
674  } else {
675  // initialize
676  G4int i;
677  for (i=0; i<G4VSURFACENXX; i++) {
678  distance[i] = kInfinity;
679  areacode[i] = sOutside;
680  gxx[i].set(kInfinity, kInfinity, kInfinity);
681  }
682  }
683 
685  G4ThreeVector xx; // intersection point
686  G4ThreeVector xxonsurface ; // interpolated intersection point
687 
688  // the surfacenormal at that surface point
689  G4double phiR = 0 ; //
690  G4double uR = 0 ;
691 
692  G4ThreeVector surfacenormal ;
693  G4double deltaX ;
694 
695  G4int maxint = 20 ;
696 
697  for ( G4int i = 1 ; i<maxint ; i++ ) {
698 
699  xxonsurface = SurfacePoint(phiR,uR) ;
700  surfacenormal = NormAng(phiR,uR) ;
701  distance[0] = DistanceToPlane(p, xxonsurface, surfacenormal, xx); // new XX
702  deltaX = ( xx - xxonsurface ).mag() ;
703 
704 #ifdef G4TWISTDEBUG
705  G4cout << "i = " << i << ", distance = " << distance[0] << ", " << deltaX << G4endl ;
706  G4cout << "X = " << xx << G4endl ;
707 #endif
708 
709  // the new point xx is accepted and phi/psi replaced
710  GetPhiUAtX(xx, phiR, uR) ;
711 
712  if ( deltaX <= ctol ) { break ; }
713 
714  }
715 
716  // check validity of solution ( valid phi,psi )
717 
718  G4double halfphi = 0.5*fPhiTwist ;
719  G4double uMax = GetBoundaryMax(phiR) ;
720  G4double uMin = GetBoundaryMin(phiR) ;
721 
722  if ( phiR > halfphi ) phiR = halfphi ;
723  if ( phiR < -halfphi ) phiR = -halfphi ;
724  if ( uR > uMax ) uR = uMax ;
725  if ( uR < uMin ) uR = uMin ;
726 
727  xxonsurface = SurfacePoint(phiR,uR) ;
728  distance[0] = ( p - xx ).mag() ;
729  if ( distance[0] <= ctol ) { distance[0] = 0 ; }
730 
731  // end of validity
732 
733 #ifdef G4TWISTDEBUG
734  G4cout << "refined solution " << phiR << " , " << uR << " , " << G4endl ;
735  G4cout << "distance = " << distance[0] << G4endl ;
736  G4cout << "X = " << xx << G4endl ;
737 #endif
738 
739  G4bool isvalid = true;
740  gxx[0] = ComputeGlobalPoint(xx);
741 
742 #ifdef G4TWISTDEBUG
743  G4cout << "intersection Point found: " << gxx[0] << G4endl ;
744  G4cout << "distance = " << distance[0] << G4endl ;
745 #endif
746 
747  fCurStat.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
748  isvalid, 1, kDontValidate, &gp);
749  return 1;
750 }
751 
752 
753 //=====================================================================
754 //* GetAreaCode -------------------------------------------------------
755 
757  G4bool withTol)
758 {
759  // We must use the function in local coordinate system.
760  // See the description of DistanceToSurface(p,v).
761 
762  const G4double ctol = 0.5 * kCarTolerance;
763 
764  G4double phi ;
765  G4double yprime ;
766  GetPhiUAtX(xx, phi,yprime ) ;
767 
768  G4double fXAxisMax = GetBoundaryMax(phi) ;
769  G4double fXAxisMin = GetBoundaryMin(phi) ;
770 
771 #ifdef G4TWISTDEBUG
772  G4cout << "GetAreaCode: phi = " << phi << G4endl ;
773  G4cout << "GetAreaCode: yprime = " << yprime << G4endl ;
774  G4cout << "Intervall is " << fXAxisMin << " to " << fXAxisMax << G4endl ;
775 #endif
776 
777  G4int areacode = sInside;
778 
779  if (fAxis[0] == kXAxis && fAxis[1] == kZAxis) {
780 
781  G4int zaxis = 1;
782 
783  if (withTol) {
784 
785  G4bool isoutside = false;
786 
787  // test boundary of xaxis
788 
789  if (yprime < fXAxisMin + ctol) {
790  areacode |= (sAxis0 & (sAxisX | sAxisMin)) | sBoundary;
791  if (yprime <= fXAxisMin - ctol) isoutside = true;
792 
793  } else if (yprime > fXAxisMax - ctol) {
794  areacode |= (sAxis0 & (sAxisX | sAxisMax)) | sBoundary;
795  if (yprime >= fXAxisMax + ctol) isoutside = true;
796  }
797 
798  // test boundary of z-axis
799 
800  if (xx.z() < fAxisMin[zaxis] + ctol) {
801  areacode |= (sAxis1 & (sAxisZ | sAxisMin));
802 
803  if (areacode & sBoundary) areacode |= sCorner; // xx is on the corner.
804  else areacode |= sBoundary;
805  if (xx.z() <= fAxisMin[zaxis] - ctol) isoutside = true;
806 
807  } else if (xx.z() > fAxisMax[zaxis] - ctol) {
808  areacode |= (sAxis1 & (sAxisZ | sAxisMax));
809 
810  if (areacode & sBoundary) areacode |= sCorner; // xx is on the corner.
811  else areacode |= sBoundary;
812  if (xx.z() >= fAxisMax[zaxis] + ctol) isoutside = true;
813  }
814 
815  // if isoutside = true, clear inside bit.
816  // if not on boundary, add axis information.
817 
818  if (isoutside) {
819  G4int tmpareacode = areacode & (~sInside);
820  areacode = tmpareacode;
821  } else if ((areacode & sBoundary) != sBoundary) {
822  areacode |= (sAxis0 & sAxisX) | (sAxis1 & sAxisZ);
823  }
824 
825  } else {
826 
827  // boundary of y-axis
828 
829  if (yprime < fXAxisMin ) {
830  areacode |= (sAxis0 & (sAxisX | sAxisMin)) | sBoundary;
831  } else if (yprime > fXAxisMax) {
832  areacode |= (sAxis0 & (sAxisX | sAxisMax)) | sBoundary;
833  }
834 
835  // boundary of z-axis
836 
837  if (xx.z() < fAxisMin[zaxis]) {
838  areacode |= (sAxis1 & (sAxisZ | sAxisMin));
839  if (areacode & sBoundary) areacode |= sCorner; // xx is on the corner.
840  else areacode |= sBoundary;
841 
842  } else if (xx.z() > fAxisMax[zaxis]) {
843  areacode |= (sAxis1 & (sAxisZ | sAxisMax)) ;
844  if (areacode & sBoundary) areacode |= sCorner; // xx is on the corner.
845  else areacode |= sBoundary;
846  }
847 
848  if ((areacode & sBoundary) != sBoundary) {
849  areacode |= (sAxis0 & sAxisX) | (sAxis1 & sAxisZ);
850  }
851  }
852  return areacode;
853  } else {
854  G4Exception("G4TwistTrapParallelSide::GetAreaCode()",
855  "GeomSolids0001", FatalException,
856  "Feature NOT implemented !");
857  }
858  return areacode;
859 }
860 
861 //=====================================================================
862 //* SetCorners() ------------------------------------------------------
863 
865 {
866 
867  // Set Corner points in local coodinate.
868 
869  if (fAxis[0] == kXAxis && fAxis[1] == kZAxis) {
870 
871  G4double x, y, z;
872 
873  // corner of Axis0min and Axis1min
874 
875  x = -fdeltaX/2. + (-fDx2 + fDy1*fTAlph)*std::cos(fPhiTwist/2.) + fDy1*std::sin(fPhiTwist/2.) ;
876  y = -fdeltaY/2. + fDy1*std::cos(fPhiTwist/2.) + (fDx2 - fDy1*fTAlph)*std::sin(fPhiTwist/2.) ;
877  z = -fDz ;
878 
879  SetCorner(sC0Min1Min, x, y, z);
880 
881  // corner of Axis0max and Axis1min
882 
883  x = -fdeltaX/2. + (fDx2 + fDy1*fTAlph)*std::cos(fPhiTwist/2.) + fDy1*std::sin(fPhiTwist/2.) ;
884  y = -fdeltaY/2. + fDy1*std::cos(fPhiTwist/2.) - (fDx2 + fDy1*fTAlph)*std::sin(fPhiTwist/2.) ;
885  z = -fDz;
886 
887  SetCorner(sC0Max1Min, x, y, z);
888 
889  // corner of Axis0max and Axis1max
890  x = fdeltaX/2. + (fDx4 + fDy2*fTAlph)*std::cos(fPhiTwist/2.) - fDy2*std::sin(fPhiTwist/2.) ;
891  y = fdeltaY/2. + fDy2*std::cos(fPhiTwist/2.) + (fDx4 + fDy2*fTAlph)*std::sin(fPhiTwist/2.) ;
892  z = fDz ;
893 
894  SetCorner(sC0Max1Max, x, y, z);
895 
896  // corner of Axis0min and Axis1max
897  x = fdeltaX/2. + (-fDx4 + fDy2*fTAlph)*std::cos(fPhiTwist/2.) - fDy2*std::sin(fPhiTwist/2.) ;
898  y = fdeltaY/2. + fDy2*std::cos(fPhiTwist/2.) + (-fDx4 + fDy2*fTAlph)*std::sin(fPhiTwist/2.) ;
899  z = fDz ;
900 
901  SetCorner(sC0Min1Max, x, y, z);
902 
903  } else {
904 
905  G4Exception("G4TwistTrapParallelSide::SetCorners()",
906  "GeomSolids0001", FatalException,
907  "Method NOT implemented !");
908  }
909 }
910 
911 //=====================================================================
912 //* SetBoundaries() ---------------------------------------------------
913 
915 {
916  // Set direction-unit vector of boundary-lines in local coodinate.
917  //
918 
919  G4ThreeVector direction;
920 
921  if (fAxis[0] == kXAxis && fAxis[1] == kZAxis) {
922 
923  // sAxis0 & sAxisMin
924  direction = GetCorner(sC0Min1Max) - GetCorner(sC0Min1Min);
925  direction = direction.unit();
926  SetBoundary(sAxis0 & (sAxisX | sAxisMin), direction,
928 
929  // sAxis0 & sAxisMax
930  direction = GetCorner(sC0Max1Max) - GetCorner(sC0Max1Min);
931  direction = direction.unit();
932  SetBoundary(sAxis0 & (sAxisX | sAxisMax), direction,
934 
935  // sAxis1 & sAxisMin
936  direction = GetCorner(sC0Max1Min) - GetCorner(sC0Min1Min);
937  direction = direction.unit();
938  SetBoundary(sAxis1 & (sAxisZ | sAxisMin), direction,
940 
941  // sAxis1 & sAxisMax
942  direction = GetCorner(sC0Max1Max) - GetCorner(sC0Min1Max);
943  direction = direction.unit();
944  SetBoundary(sAxis1 & (sAxisZ | sAxisMax), direction,
946 
947  } else {
948 
949  G4Exception("G4TwistTrapParallelSide::SetCorners()",
950  "GeomSolids0001", FatalException,
951  "Feature NOT implemented !");
952  }
953 
954 }
955 
956 //=====================================================================
957 //* GetPhiUAtX() ------------------------------------------------------
958 
959 void
961 {
962  // find closest point XX on surface for a given point p
963  // X0 is a point on the surface, d is the direction ( both for a fixed z = pz)
964 
965  // phi is given by the z coordinate of p
966 
967  phi = p.z()/(2*fDz)*fPhiTwist ;
968 
969  u = ((-(fdeltaX*phi) + fPhiTwist*p.x())* std::cos(phi) + (-(fdeltaY*phi) + fPhiTwist*p.y())*std::sin(phi))/fPhiTwist ;
970 
971 }
972 
973 //=====================================================================
974 //* ProjectPoint() ----------------------------------------------------
975 
977  G4bool isglobal)
978 {
979  // Get Rho at p.z() on Hyperbolic Surface.
980  G4ThreeVector tmpp;
981  if (isglobal) {
982  tmpp = fRot.inverse()*p - fTrans;
983  } else {
984  tmpp = p;
985  }
986 
987  G4double phi ;
988  G4double u ;
989 
990  GetPhiUAtX( tmpp, phi, u ) ; // calculate (phi, u) for a point p close the surface
991 
992  G4ThreeVector xx = SurfacePoint(phi,u) ; // transform back to cartesian coordinates
993 
994  if (isglobal) {
995  return (fRot * xx + fTrans);
996  } else {
997  return xx;
998  }
999 }
1000 
1001 //=====================================================================
1002 //* GetFacets() -------------------------------------------------------
1003 
1005  G4int faces[][4], G4int iside )
1006 {
1007 
1008  G4double phi ;
1009  G4double z, u ; // the two parameters for the surface equation
1010  G4ThreeVector p ; // a point on the surface, given by (z,u)
1011 
1012  G4int nnode ;
1013  G4int nface ;
1014 
1015  G4double umin, umax ;
1016 
1017  // calculate the (n-1)*(k-1) vertices
1018 
1019  G4int i,j ;
1020 
1021  for ( i = 0 ; i<n ; i++ ) {
1022 
1023  z = -fDz+i*(2.*fDz)/(n-1) ;
1024  phi = z*fPhiTwist/(2*fDz) ;
1025  umin = GetBoundaryMin(phi) ;
1026  umax = GetBoundaryMax(phi) ;
1027 
1028  for ( j = 0 ; j<k ; j++ ) {
1029 
1030  nnode = GetNode(i,j,k,n,iside) ;
1031  u = umax - j*(umax-umin)/(k-1) ;
1032  p = SurfacePoint(phi,u,true) ; // surface point in global coordinate system
1033 
1034  xyz[nnode][0] = p.x() ;
1035  xyz[nnode][1] = p.y() ;
1036  xyz[nnode][2] = p.z() ;
1037 
1038  if ( i<n-1 && j<k-1 ) { // conterclock wise filling
1039 
1040  nface = GetFace(i,j,k,n,iside) ;
1041  faces[nface][0] = GetEdgeVisibility(i,j,k,n,0,-1) * (GetNode(i ,j ,k,n,iside)+1) ; // fortran numbering
1042  faces[nface][1] = GetEdgeVisibility(i,j,k,n,1,-1) * (GetNode(i ,j+1,k,n,iside)+1) ;
1043  faces[nface][2] = GetEdgeVisibility(i,j,k,n,2,-1) * (GetNode(i+1,j+1,k,n,iside)+1) ;
1044  faces[nface][3] = GetEdgeVisibility(i,j,k,n,3,-1) * (GetNode(i+1,j ,k,n,iside)+1) ;
1045 
1046  }
1047  }
1048  }
1049 }
static const G4int sAxisZ
G4int GetAreacode(G4int i) const
void SetCorner(G4int areacode, G4double x, G4double y, G4double z)
static const G4int sC0Min1Max
static const G4double kInfinity
Definition: geomdefs.hh:42
CLHEP::Hep3Vector G4ThreeVector
G4ThreeVector ComputeGlobalDirection(const G4ThreeVector &lp) const
G4ThreeVector ComputeLocalDirection(const G4ThreeVector &gp) const
G4SurfCurNormal fCurrentNormal
G4double z
Definition: TRTMaterials.hh:39
virtual G4int DistanceToSurface(const G4ThreeVector &gp, const G4ThreeVector &gv, G4ThreeVector gxx[], G4double distance[], G4int areacode[], G4bool isvalid[], EValidate validate=kValidateWithTol)
G4String name
Definition: TRTMaterials.hh:40
const G4double pi
G4double fAxisMax[2]
G4double DistanceToPlaneWithV(const G4ThreeVector &p, const G4ThreeVector &v, const G4ThreeVector &x0, const G4ThreeVector &n0, G4ThreeVector &xx)
virtual G4ThreeVector GetNormal(const G4ThreeVector &xx, G4bool isGlobal=false)
G4ThreeVector GetCorner(G4int areacode) const
static const G4int sOutside
virtual G4ThreeVector SurfacePoint(G4double phi, G4double u, G4bool isGlobal=false)
G4double a
Definition: TRTMaterials.hh:39
CurrentStatus fCurStat
virtual void GetFacets(G4int m, G4int n, G4double xyz[][3], G4int faces[][4], G4int iside)
G4ThreeVector ComputeGlobalPoint(const G4ThreeVector &lp) const
virtual G4double GetBoundaryMin(G4double phi)
int G4int
Definition: G4Types.hh:78
G4RotationMatrix fRot
static const G4int sAxisX
G4ThreeVector fTrans
G4double fAxisMin[2]
#define G4VSURFACENXX
static double normal(HepRandomEngine *eptr)
Definition: RandPoisson.cc:77
void GetPhiUAtX(G4ThreeVector p, G4double &phi, G4double &u)
static const G4int L[nN]
static const G4int sC0Min1Min
G4GLOB_DLL std::ostream G4cout
G4bool IsOutside(G4int areacode) const
G4double GetDistance(G4int i) const
static const G4int sAxis1
static const G4int sC0Max1Max
static const G4int sBoundary
bool G4bool
Definition: G4Types.hh:79
void SetCurrentStatus(G4int i, G4ThreeVector &xx, G4double &dist, G4int &areacode, G4bool &isvalid, G4int nxx, EValidate validate, const G4ThreeVector *p, const G4ThreeVector *v=0)
G4bool IsValid(G4int i) const
G4double DistanceToPlane(const G4ThreeVector &p, const G4ThreeVector &x0, const G4ThreeVector &n0, G4ThreeVector &xx)
static const G4int sAxis0
G4bool IsInside(G4int areacode, G4bool testbitmode=false) const
static const G4int sAxisMin
virtual G4double GetBoundaryMax(G4double phi)
G4TwistTrapParallelSide(const G4String &name, G4double PhiTwist, G4double pDz, G4double pTheta, G4double pPhi, G4double pDy1, G4double pDx1, G4double pDx2, G4double pDy2, G4double pDx3, G4double pDx4, G4double pAlph, G4double AngleSide)
const G4int n
static const G4int sInside
G4ThreeVector NormAng(G4double phi, G4double u)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
G4ThreeVector ProjectPoint(const G4ThreeVector &p, G4bool isglobal=false)
static const G4int sCorner
static const G4double factor
G4int GetNode(G4int i, G4int j, G4int m, G4int n, G4int iside)
static const G4int sAxisMax
G4ThreeVector GetXX(G4int i) const
virtual void SetBoundary(const G4int &axiscode, const G4ThreeVector &direction, const G4ThreeVector &x0, const G4int &boundarytype)
G4bool EqualIntersection(const Intersection &a, const Intersection &b)
#define G4endl
Definition: G4ios.hh:61
G4int GetFace(G4int i, G4int j, G4int m, G4int n, G4int iside)
G4ThreeVector ComputeLocalPoint(const G4ThreeVector &gp) const
double G4double
Definition: G4Types.hh:76
G4int GetEdgeVisibility(G4int i, G4int j, G4int m, G4int n, G4int number, G4int orientation)
G4bool DistanceSort(const Intersection &a, const Intersection &b)
static const G4int sC0Max1Min
G4int FindRoots(G4double *op, G4int degree, G4double *zeror, G4double *zeroi)
CurrentStatus fCurStatWithV
void ResetfDone(EValidate validate, const G4ThreeVector *p, const G4ThreeVector *v=0)
virtual G4int GetAreaCode(const G4ThreeVector &xx, G4bool withTol=true)