Geant4  v4-10.4-release
 모두 클래스 네임스페이스들 파일들 함수 변수 타입정의 열거형 타입 열거형 멤버 Friends 매크로 그룹들 페이지들
G4Paraboloid.cc
이 파일의 문서화 페이지로 가기
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 // $Id: G4Paraboloid.cc 104316 2017-05-24 13:04:23Z gcosmo $
27 //
28 // class G4Paraboloid
29 //
30 // Implementation for G4Paraboloid class
31 //
32 // Author : Lukas Lindroos (CERN), July 2007
33 // Revised: Tatiana Nikitina (CERN)
34 // --------------------------------------------------------------------
35 
36 #include "globals.hh"
37 
38 #include "G4Paraboloid.hh"
39 
40 #if !(defined(G4GEOM_USE_UPARABOLOID) && defined(G4GEOM_USE_SYS_USOLIDS))
41 
42 #include "G4VoxelLimits.hh"
43 #include "G4AffineTransform.hh"
44 #include "G4BoundingEnvelope.hh"
45 
46 #include "meshdefs.hh"
47 
48 #include "Randomize.hh"
49 
50 #include "G4VGraphicsScene.hh"
51 #include "G4VisExtent.hh"
52 
53 #include "G4AutoLock.hh"
54 
55 namespace
56 {
57  G4Mutex polyhedronMutex = G4MUTEX_INITIALIZER;
58 }
59 
60 using namespace CLHEP;
61 
63 //
64 // constructor - check parameters
65 
67  G4double pDz,
68  G4double pR1,
69  G4double pR2)
70  : G4VSolid(pName), fRebuildPolyhedron(false), fpPolyhedron(0),
71  fSurfaceArea(0.), fCubicVolume(0.)
72 
73 {
74  if( (pDz <= 0.) || (pR2 <= pR1) || (pR1 < 0.) )
75  {
76  std::ostringstream message;
77  message << "Invalid dimensions. Negative Input Values or R1>=R2 - "
78  << GetName();
79  G4Exception("G4Paraboloid::G4Paraboloid()", "GeomSolids0002",
80  FatalErrorInArgument, message,
81  "Z half-length must be larger than zero or R1>=R2.");
82  }
83 
84  r1 = pR1;
85  r2 = pR2;
86  dz = pDz;
87 
88  // r1^2 = k1 * (-dz) + k2
89  // r2^2 = k1 * ( dz) + k2
90  // => r1^2 + r2^2 = k2 + k2 => k2 = (r2^2 + r1^2) / 2
91  // and r2^2 - r1^2 = k1 * dz - k1 * (-dz) => k1 = (r2^2 - r1^2) / 2 / dz
92 
93  k1 = (r2 * r2 - r1 * r1) / 2 / dz;
94  k2 = (r2 * r2 + r1 * r1) / 2;
95 }
96 
98 //
99 // Fake default constructor - sets only member data and allocates memory
100 // for usage restricted to object persistency.
101 //
103  : G4VSolid(a), fRebuildPolyhedron(false), fpPolyhedron(0),
104  fSurfaceArea(0.), fCubicVolume(0.),
105  dz(0.), r1(0.), r2(0.), k1(0.), k2(0.)
106 {
107 }
108 
110 //
111 // Destructor
112 
114 {
115  delete fpPolyhedron; fpPolyhedron = 0;
116 }
117 
119 //
120 // Copy constructor
121 
123  : G4VSolid(rhs), fRebuildPolyhedron(false), fpPolyhedron(0),
124  fSurfaceArea(rhs.fSurfaceArea), fCubicVolume(rhs.fCubicVolume),
125  dz(rhs.dz), r1(rhs.r1), r2(rhs.r2), k1(rhs.k1), k2(rhs.k2)
126 {
127 }
128 
129 
131 //
132 // Assignment operator
133 
135 {
136  // Check assignment to self
137  //
138  if (this == &rhs) { return *this; }
139 
140  // Copy base class data
141  //
142  G4VSolid::operator=(rhs);
143 
144  // Copy data
145  //
147  dz = rhs.dz; r1 = rhs.r1; r2 = rhs.r2; k1 = rhs.k1; k2 = rhs.k2;
148  fRebuildPolyhedron = false;
149  delete fpPolyhedron; fpPolyhedron = 0;
150 
151  return *this;
152 }
153 
155 //
156 // Dispatch to parameterisation for replication mechanism dimension
157 // computation & modification.
158 
159 //void ComputeDimensions( G4VPVParamerisation p,
160 // const G4Int n,
161 // const G4VPhysicalVolume* pRep )
162 //{
163 // p->ComputeDimensions(*this,n,pRep) ;
164 //}
165 
167 //
168 // Get bounding box
169 
171  G4ThreeVector& pMax) const
172 {
173  pMin.set(-r2,-r2,-dz);
174  pMax.set( r2, r2, dz);
175 
176  // Check correctness of the bounding box
177  //
178  if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
179  {
180  std::ostringstream message;
181  message << "Bad bounding box (min >= max) for solid: "
182  << GetName() << " !"
183  << "\npMin = " << pMin
184  << "\npMax = " << pMax;
185  G4Exception("G4Paraboloid::BoundingLimits()", "GeomMgt0001",
186  JustWarning, message);
187  DumpInfo();
188  }
189 }
190 
192 //
193 // Calculate extent under transform and specified limit
194 
195 G4bool
197  const G4VoxelLimits& pVoxelLimit,
198  const G4AffineTransform& pTransform,
199  G4double& pMin, G4double& pMax) const
200 {
201  G4ThreeVector bmin, bmax;
202 
203  // Get bounding box
204  BoundingLimits(bmin,bmax);
205 
206  // Find extent
207  G4BoundingEnvelope bbox(bmin,bmax);
208  return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
209 }
210 
212 //
213 // Return whether point inside/outside/on surface
214 
216 {
217  // First check is the point is above or below the solid.
218  //
219  if(std::fabs(p.z()) > dz + 0.5 * kCarTolerance) { return kOutside; }
220 
221  G4double rho2 = p.perp2(),
222  rhoSurfTimesTol2 = (k1 * p.z() + k2) * sqr(kCarTolerance),
223  A = rho2 - ((k1 *p.z() + k2) + 0.25 * kCarTolerance * kCarTolerance);
224 
225  if(A < 0 && sqr(A) > rhoSurfTimesTol2)
226  {
227  // Actually checking rho < radius of paraboloid at z = p.z().
228  // We're either inside or in lower/upper cutoff area.
229 
230  if(std::fabs(p.z()) > dz - 0.5 * kCarTolerance)
231  {
232  // We're in the upper/lower cutoff area, sides have a paraboloid shape
233  // maybe further checks should be made to make these nicer
234 
235  return kSurface;
236  }
237  else
238  {
239  return kInside;
240  }
241  }
242  else if(A <= 0 || sqr(A) < rhoSurfTimesTol2)
243  {
244  // We're in the parabolic surface.
245 
246  return kSurface;
247  }
248  else
249  {
250  return kOutside;
251  }
252 }
253 
255 //
256 
258 {
259  G4ThreeVector n(0, 0, 0);
260  if(std::fabs(p.z()) > dz + 0.5 * kCarTolerance)
261  {
262  // If above or below just return normal vector for the cutoff plane.
263 
264  n = G4ThreeVector(0, 0, p.z()/std::fabs(p.z()));
265  }
266  else if(std::fabs(p.z()) > dz - 0.5 * kCarTolerance)
267  {
268  // This means we're somewhere in the plane z = dz or z = -dz.
269  // (As far as the program is concerned anyway.
270 
271  if(p.z() < 0) // Are we in upper or lower plane?
272  {
273  if(p.perp2() > sqr(r1 + 0.5 * kCarTolerance))
274  {
275  n = G4ThreeVector(p.x(), p.y(), -k1 / 2).unit();
276  }
277  else if(r1 < 0.5 * kCarTolerance
278  || p.perp2() > sqr(r1 - 0.5 * kCarTolerance))
279  {
280  n = G4ThreeVector(p.x(), p.y(), 0.).unit()
281  + G4ThreeVector(0., 0., -1.).unit();
282  n = n.unit();
283  }
284  else
285  {
286  n = G4ThreeVector(0., 0., -1.);
287  }
288  }
289  else
290  {
291  if(p.perp2() > sqr(r2 + 0.5 * kCarTolerance))
292  {
293  n = G4ThreeVector(p.x(), p.y(), 0.).unit();
294  }
295  else if(r2 < 0.5 * kCarTolerance
296  || p.perp2() > sqr(r2 - 0.5 * kCarTolerance))
297  {
298  n = G4ThreeVector(p.x(), p.y(), 0.).unit()
299  + G4ThreeVector(0., 0., 1.).unit();
300  n = n.unit();
301  }
302  else
303  {
304  n = G4ThreeVector(0., 0., 1.);
305  }
306  }
307  }
308  else
309  {
310  G4double rho2 = p.perp2();
311  G4double rhoSurfTimesTol2 = (k1 * p.z() + k2) * sqr(kCarTolerance);
312  G4double A = rho2 - ((k1 *p.z() + k2)
313  + 0.25 * kCarTolerance * kCarTolerance);
314 
315  if(A < 0 && sqr(A) > rhoSurfTimesTol2)
316  {
317  // Actually checking rho < radius of paraboloid at z = p.z().
318  // We're inside.
319 
320  if(p.mag2() != 0) { n = p.unit(); }
321  }
322  else if(A <= 0 || sqr(A) < rhoSurfTimesTol2)
323  {
324  // We're in the parabolic surface.
325 
326  n = G4ThreeVector(p.x(), p.y(), - k1 / 2).unit();
327  }
328  else
329  {
330  n = G4ThreeVector(p.x(), p.y(), - k1 / 2).unit();
331  }
332  }
333 
334  if(n.mag2() == 0)
335  {
336  std::ostringstream message;
337  message << "No normal defined for this point p." << G4endl
338  << " p = " << 1 / mm * p << " mm";
339  G4Exception("G4Paraboloid::SurfaceNormal(p)", "GeomSolids1002",
340  JustWarning, message);
341  }
342  return n;
343 }
344 
346 //
347 // Calculate distance to shape from outside, along normalised vector
348 // - return kInfinity if no intersection
349 //
350 
352  const G4ThreeVector& v ) const
353 {
354  G4double rho2 = p.perp2(), paraRho2 = std::fabs(k1 * p.z() + k2);
356  G4double tolh = 0.5*kCarTolerance;
357 
358  if(r2 && p.z() > - tolh + dz)
359  {
360  // If the points is above check for intersection with upper edge.
361 
362  if(v.z() < 0)
363  {
364  G4double intersection = (dz - p.z()) / v.z(); // With plane z = dz.
365  if(sqr(p.x() + v.x()*intersection)
366  + sqr(p.y() + v.y()*intersection) < sqr(r2 + 0.5 * kCarTolerance))
367  {
368  if(p.z() < tolh + dz)
369  { return 0; }
370  else
371  { return intersection; }
372  }
373  }
374  else // Direction away, no possibility of intersection
375  {
376  return kInfinity;
377  }
378  }
379  else if(r1 && p.z() < tolh - dz)
380  {
381  // If the points is belove check for intersection with lower edge.
382 
383  if(v.z() > 0)
384  {
385  G4double intersection = (-dz - p.z()) / v.z(); // With plane z = -dz.
386  if(sqr(p.x() + v.x()*intersection)
387  + sqr(p.y() + v.y()*intersection) < sqr(r1 + 0.5 * kCarTolerance))
388  {
389  if(p.z() > -tolh - dz)
390  {
391  return 0;
392  }
393  else
394  {
395  return intersection;
396  }
397  }
398  }
399  else // Direction away, no possibility of intersection
400  {
401  return kInfinity;
402  }
403  }
404 
405  G4double A = k1 / 2 * v.z() - p.x() * v.x() - p.y() * v.y(),
406  vRho2 = v.perp2(), intersection,
407  B = (k1 * p.z() + k2 - rho2) * vRho2;
408 
409  if ( ( (rho2 > paraRho2) && (sqr(rho2-paraRho2-0.25*tol2) > tol2*paraRho2) )
410  || (p.z() < - dz+kCarTolerance)
411  || (p.z() > dz-kCarTolerance) ) // Make sure it's safely outside.
412  {
413  // Is there a problem with squaring rho twice?
414 
415  if(vRho2<tol2) // Needs to be treated seperately.
416  {
417  intersection = ((rho2 - k2)/k1 - p.z())/v.z();
418  if(intersection < 0) { return kInfinity; }
419  else if(std::fabs(p.z() + v.z() * intersection) <= dz)
420  {
421  return intersection;
422  }
423  else
424  {
425  return kInfinity;
426  }
427  }
428  else if(A*A + B < 0) // No real intersections.
429  {
430  return kInfinity;
431  }
432  else
433  {
434  intersection = (A - std::sqrt(B + sqr(A))) / vRho2;
435  if(intersection < 0)
436  {
437  return kInfinity;
438  }
439  else if(std::fabs(p.z() + intersection * v.z()) < dz + tolh)
440  {
441  return intersection;
442  }
443  else
444  {
445  return kInfinity;
446  }
447  }
448  }
449  else if(sqr(rho2 - paraRho2 - .25 * tol2) <= tol2 * paraRho2)
450  {
451  // If this is true we're somewhere in the border.
452 
453  G4ThreeVector normal(p.x(), p.y(), -k1/2);
454  if(normal.dot(v) <= 0)
455  { return 0; }
456  else
457  { return kInfinity; }
458  }
459  else
460  {
461  std::ostringstream message;
462  if(Inside(p) == kInside)
463  {
464  message << "Point p is inside! - " << GetName() << G4endl;
465  }
466  else
467  {
468  message << "Likely a problem in this function, for solid: " << GetName()
469  << G4endl;
470  }
471  message << " p = " << p * (1/mm) << " mm" << G4endl
472  << " v = " << v * (1/mm) << " mm";
473  G4Exception("G4Paraboloid::DistanceToIn(p,v)", "GeomSolids1002",
474  JustWarning, message);
475  return 0;
476  }
477 }
478 
480 //
481 // Calculate distance (<= actual) to closest surface of shape from outside
482 // - Return 0 if point inside
483 
485 {
486  G4double safz = -dz+std::fabs(p.z());
487  if(safz<0) { safz=0; }
488  G4double safr = kInfinity;
489 
490  G4double rho = p.x()*p.x()+p.y()*p.y();
491  G4double paraRho = (p.z()-k2)/k1;
492  G4double sqrho = std::sqrt(rho);
493 
494  if(paraRho<0)
495  {
496  safr=sqrho-r2;
497  if(safr>safz) { safz=safr; }
498  return safz;
499  }
500 
501  G4double sqprho = std::sqrt(paraRho);
502  G4double dRho = sqrho-sqprho;
503  if(dRho<0) { return safz; }
504 
505  G4double talf = -2.*k1*sqprho;
506  G4double tmp = 1+talf*talf;
507  if(tmp<0.) { return safz; }
508 
509  G4double salf = talf/std::sqrt(tmp);
510  safr = std::fabs(dRho*salf);
511  if(safr>safz) { safz=safr; }
512 
513  return safz;
514 }
515 
517 //
518 // Calculate distance to surface of shape from 'inside'
519 
521  const G4ThreeVector& v,
522  const G4bool calcNorm,
523  G4bool *validNorm,
524  G4ThreeVector *n ) const
525 {
526  G4double rho2 = p.perp2(), paraRho2 = std::fabs(k1 * p.z() + k2);
527  G4double vRho2 = v.perp2(), intersection;
529  G4double tolh = 0.5*kCarTolerance;
530 
531  if(calcNorm) { *validNorm = false; }
532 
533  // We have that the particle p follows the line x = p + s * v
534  // meaning x = p.x() + s * v.x(), y = p.y() + s * v.y() and
535  // z = p.z() + s * v.z()
536  // The equation for all points on the surface (surface expanded for
537  // to include all z) x^2 + y^2 = k1 * z + k2 => .. =>
538  // => s = (A +- std::sqrt(A^2 + B)) / vRho2
539  // where:
540  //
541  G4double A = k1 / 2 * v.z() - p.x() * v.x() - p.y() * v.y();
542  //
543  // and:
544  //
545  G4double B = (-rho2 + paraRho2) * vRho2;
546 
547  if ( rho2 < paraRho2 && sqr(rho2 - paraRho2 - 0.25 * tol2) > tol2 * paraRho2
548  && std::fabs(p.z()) < dz - kCarTolerance)
549  {
550  // Make sure it's safely inside.
551 
552  if(v.z() > 0)
553  {
554  // It's heading upwards, check where it colides with the plane z = dz.
555  // When it does, is that in the surface of the paraboloid.
556  // z = p.z() + variable * v.z() for all points the particle can go.
557  // => variable = (z - p.z()) / v.z() so intersection must be:
558 
559  intersection = (dz - p.z()) / v.z();
560  G4ThreeVector ip = p + intersection * v; // Point of intersection.
561 
562  if(ip.perp2() < sqr(r2 + kCarTolerance))
563  {
564  if(calcNorm)
565  {
566  *n = G4ThreeVector(0, 0, 1);
567  if(r2 < tolh || ip.perp2() > sqr(r2 - tolh))
568  {
569  *n += G4ThreeVector(ip.x(), ip.y(), - k1 / 2).unit();
570  *n = n->unit();
571  }
572  *validNorm = true;
573  }
574  return intersection;
575  }
576  }
577  else if(v.z() < 0)
578  {
579  // It's heading downwards, check were it colides with the plane z = -dz.
580  // When it does, is that in the surface of the paraboloid.
581  // z = p.z() + variable * v.z() for all points the particle can go.
582  // => variable = (z - p.z()) / v.z() so intersection must be:
583 
584  intersection = (-dz - p.z()) / v.z();
585  G4ThreeVector ip = p + intersection * v; // Point of intersection.
586 
587  if(ip.perp2() < sqr(r1 + tolh))
588  {
589  if(calcNorm)
590  {
591  *n = G4ThreeVector(0, 0, -1);
592  if(r1 < tolh || ip.perp2() > sqr(r1 - tolh))
593  {
594  *n += G4ThreeVector(ip.x(), ip.y(), - k1 / 2).unit();
595  *n = n->unit();
596  }
597  *validNorm = true;
598  }
599  return intersection;
600  }
601  }
602 
603  // Now check for collisions with paraboloid surface.
604 
605  if(vRho2 == 0) // Needs to be treated seperately.
606  {
607  intersection = ((rho2 - k2)/k1 - p.z())/v.z();
608  if(calcNorm)
609  {
610  G4ThreeVector intersectionP = p + v * intersection;
611  *n = G4ThreeVector(intersectionP.x(), intersectionP.y(), -k1/2);
612  *n = n->unit();
613 
614  *validNorm = true;
615  }
616  return intersection;
617  }
618  else if( ((A <= 0) && (B >= sqr(A) * (sqr(vRho2) - 1))) || (A >= 0))
619  {
620  // intersection = (A + std::sqrt(B + sqr(A))) / vRho2;
621  // The above calculation has a precision problem:
622  // known problem of solving quadratic equation with small A
623 
624  A = A/vRho2;
625  B = (k1 * p.z() + k2 - rho2)/vRho2;
626  intersection = B/(-A + std::sqrt(B + sqr(A)));
627  if(calcNorm)
628  {
629  G4ThreeVector intersectionP = p + v * intersection;
630  *n = G4ThreeVector(intersectionP.x(), intersectionP.y(), -k1/2);
631  *n = n->unit();
632  *validNorm = true;
633  }
634  return intersection;
635  }
636  std::ostringstream message;
637  message << "There is no intersection between given line and solid!"
638  << G4endl
639  << " p = " << p << G4endl
640  << " v = " << v;
641  G4Exception("G4Paraboloid::DistanceToOut(p,v,...)", "GeomSolids1002",
642  JustWarning, message);
643 
644  return kInfinity;
645  }
646  else if ( (rho2 < paraRho2 + kCarTolerance
647  || sqr(rho2 - paraRho2 - 0.25 * tol2) < tol2 * paraRho2 )
648  && std::fabs(p.z()) < dz + tolh)
649  {
650  // If this is true we're somewhere in the border.
651 
652  G4ThreeVector normal = G4ThreeVector (p.x(), p.y(), -k1/2);
653 
654  if(std::fabs(p.z()) > dz - tolh)
655  {
656  // We're in the lower or upper edge
657  //
658  if( ((v.z() > 0) && (p.z() > 0)) || ((v.z() < 0) && (p.z() < 0)) )
659  { // If we're heading out of the object that is treated here
660  if(calcNorm)
661  {
662  *validNorm = true;
663  if(p.z() > 0)
664  { *n = G4ThreeVector(0, 0, 1); }
665  else
666  { *n = G4ThreeVector(0, 0, -1); }
667  }
668  return 0;
669  }
670 
671  if(v.z() == 0)
672  {
673  // Case where we're moving inside the surface needs to be
674  // treated separately.
675  // Distance until it goes out through a side is returned.
676 
677  G4double r = (p.z() > 0)? r2 : r1;
678  G4double pDotV = p.dot(v);
679  A = vRho2 * ( sqr(r) - sqr(p.x()) - sqr(p.y()));
680  intersection = (-pDotV + std::sqrt(A + sqr(pDotV))) / vRho2;
681 
682  if(calcNorm)
683  {
684  *validNorm = true;
685 
686  *n = (G4ThreeVector(0, 0, p.z()/std::fabs(p.z()))
687  + G4ThreeVector(p.x() + v.x() * intersection, p.y() + v.y()
688  * intersection, -k1/2).unit()).unit();
689  }
690  return intersection;
691  }
692  }
693  //
694  // Problem in the Logic :: Following condition for point on upper surface
695  // and Vz<0 will return 0 (Problem #1015), but
696  // it has to return intersection with parabolic
697  // surface or with lower plane surface (z = -dz)
698  // The logic has to be :: If not found intersection until now,
699  // do not exit but continue to search for possible intersection.
700  // Only for point situated on both borders (Z and parabolic)
701  // this condition has to be taken into account and done later
702  //
703  //
704  // else if(normal.dot(v) >= 0)
705  // {
706  // if(calcNorm)
707  // {
708  // *validNorm = true;
709  // *n = normal.unit();
710  // }
711  // return 0;
712  // }
713 
714  if(v.z() > 0)
715  {
716  // Check for collision with upper edge.
717 
718  intersection = (dz - p.z()) / v.z();
719  G4ThreeVector ip = p + intersection * v;
720 
721  if(ip.perp2() < sqr(r2 - tolh))
722  {
723  if(calcNorm)
724  {
725  *validNorm = true;
726  *n = G4ThreeVector(0, 0, 1);
727  }
728  return intersection;
729  }
730  else if(ip.perp2() < sqr(r2 + tolh))
731  {
732  if(calcNorm)
733  {
734  *validNorm = true;
735  *n = G4ThreeVector(0, 0, 1)
736  + G4ThreeVector(ip.x(), ip.y(), - k1 / 2).unit();
737  *n = n->unit();
738  }
739  return intersection;
740  }
741  }
742  if( v.z() < 0)
743  {
744  // Check for collision with lower edge.
745 
746  intersection = (-dz - p.z()) / v.z();
747  G4ThreeVector ip = p + intersection * v;
748 
749  if(ip.perp2() < sqr(r1 - tolh))
750  {
751  if(calcNorm)
752  {
753  *validNorm = true;
754  *n = G4ThreeVector(0, 0, -1);
755  }
756  return intersection;
757  }
758  else if(ip.perp2() < sqr(r1 + tolh))
759  {
760  if(calcNorm)
761  {
762  *validNorm = true;
763  *n = G4ThreeVector(0, 0, -1)
764  + G4ThreeVector(ip.x(), ip.y(), - k1 / 2).unit();
765  *n = n->unit();
766  }
767  return intersection;
768  }
769  }
770 
771  // Note: comparison with zero below would not be correct !
772  //
773  if(std::fabs(vRho2) > tol2) // precision error in the calculation of
774  { // intersection = (A+std::sqrt(B+sqr(A)))/vRho2
775  A = A/vRho2;
776  B = (k1 * p.z() + k2 - rho2);
777  if(std::fabs(B)>kCarTolerance)
778  {
779  B = (B)/vRho2;
780  intersection = B/(-A + std::sqrt(B + sqr(A)));
781  }
782  else // Point is On both borders: Z and parabolic
783  { // solution depends on normal.dot(v) sign
784  if(normal.dot(v) >= 0)
785  {
786  if(calcNorm)
787  {
788  *validNorm = true;
789  *n = normal.unit();
790  }
791  return 0;
792  }
793  intersection = 2.*A;
794  }
795  }
796  else
797  {
798  intersection = ((rho2 - k2) / k1 - p.z()) / v.z();
799  }
800 
801  if(calcNorm)
802  {
803  *validNorm = true;
804  *n = G4ThreeVector(p.x() + intersection * v.x(), p.y()
805  + intersection * v.y(), - k1 / 2);
806  *n = n->unit();
807  }
808  return intersection;
809  }
810  else
811  {
812 #ifdef G4SPECSDEBUG
813  if(kOutside == Inside(p))
814  {
815  G4Exception("G4Paraboloid::DistanceToOut(p,v,...)", "GeomSolids1002",
816  JustWarning, "Point p is outside!");
817  }
818  else
819  G4Exception("G4Paraboloid::DistanceToOut(p,v,...)", "GeomSolids1002",
820  JustWarning, "There's an error in this functions code.");
821 #endif
822  return kInfinity;
823  }
824  return 0;
825 }
826 
828 //
829 // Calculate distance (<=actual) to closest surface of shape from inside
830 
832 {
833  G4double safe=0.0,rho,safeR,safeZ ;
834  G4double tanRMax,secRMax,pRMax ;
835 
836 #ifdef G4SPECSDEBUG
837  if( Inside(p) == kOutside )
838  {
839  G4cout << G4endl ;
840  DumpInfo();
841  std::ostringstream message;
842  G4int oldprc = message.precision(16);
843  message << "Point p is outside !?" << G4endl
844  << "Position:" << G4endl
845  << " p.x() = " << p.x()/mm << " mm" << G4endl
846  << " p.y() = " << p.y()/mm << " mm" << G4endl
847  << " p.z() = " << p.z()/mm << " mm";
848  message.precision(oldprc) ;
849  G4Exception("G4Paraboloid::DistanceToOut(p)", "GeomSolids1002",
850  JustWarning, message);
851  }
852 #endif
853 
854  rho = p.perp();
855  safeZ = dz - std::fabs(p.z()) ;
856 
857  tanRMax = (r2 - r1)*0.5/dz ;
858  secRMax = std::sqrt(1.0 + tanRMax*tanRMax) ;
859  pRMax = tanRMax*p.z() + (r1+r2)*0.5 ;
860  safeR = (pRMax - rho)/secRMax ;
861 
862  if (safeZ < safeR) { safe = safeZ; }
863  else { safe = safeR; }
864  if ( safe < 0.5 * kCarTolerance ) { safe = 0; }
865  return safe ;
866 }
867 
869 //
870 // G4EntityType
871 
873 {
874  return G4String("G4Paraboloid");
875 }
876 
878 //
879 // Make a clone of the object
880 
882 {
883  return new G4Paraboloid(*this);
884 }
885 
887 //
888 // Stream object contents to an output stream
889 
890 std::ostream& G4Paraboloid::StreamInfo( std::ostream& os ) const
891 {
892  G4int oldprc = os.precision(16);
893  os << "-----------------------------------------------------------\n"
894  << " *** Dump for solid - " << GetName() << " ***\n"
895  << " ===================================================\n"
896  << " Solid type: G4Paraboloid\n"
897  << " Parameters: \n"
898  << " z half-axis: " << dz/mm << " mm \n"
899  << " radius at -dz: " << r1/mm << " mm \n"
900  << " radius at dz: " << r2/mm << " mm \n"
901  << "-----------------------------------------------------------\n";
902  os.precision(oldprc);
903 
904  return os;
905 }
906 
908 //
909 // GetPointOnSurface
910 
912 {
914  G4double z = G4RandFlat::shoot(0.,1.);
915  G4double phi = G4RandFlat::shoot(0., twopi);
916  if(pi*(sqr(r1) + sqr(r2))/A >= z)
917  {
918  G4double rho;
919  if(pi * sqr(r1) / A > z)
920  {
921  rho = r1 * std::sqrt(G4RandFlat::shoot(0., 1.));
922  return G4ThreeVector(rho * std::cos(phi), rho * std::sin(phi), -dz);
923  }
924  else
925  {
926  rho = r2 * std::sqrt(G4RandFlat::shoot(0., 1));
927  return G4ThreeVector(rho * std::cos(phi), rho * std::sin(phi), dz);
928  }
929  }
930  else
931  {
932  z = G4RandFlat::shoot(0., 1.)*2*dz - dz;
933  return G4ThreeVector(std::sqrt(z*k1 + k2)*std::cos(phi),
934  std::sqrt(z*k1 + k2)*std::sin(phi), z);
935  }
936 }
937 
939 //
940 // Methods for visualisation
941 
943 {
944  scene.AddSolid(*this);
945 }
946 
948 {
949  return new G4PolyhedronParaboloid(r1, r2, dz, 0., twopi);
950 }
951 
952 
954 {
955  if (!fpPolyhedron ||
959  {
960  G4AutoLock l(&polyhedronMutex);
961  delete fpPolyhedron;
963  fRebuildPolyhedron = false;
964  l.unlock();
965  }
966  return fpPolyhedron;
967 }
968 
969 #endif // !defined(G4GEOM_USE_UPARABOLOID) || !defined(G4GEOM_USE_SYS_USOLIDS)
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
void set(double x, double y, double z)
double perp() const
CLHEP::Hep3Vector G4ThreeVector
G4Polyhedron * fpPolyhedron
std::vector< ExP01TrackerHit * > a
Definition: ExP01Classes.hh:33
virtual void AddSolid(const G4Box &)=0
static const G4double kInfinity
Definition: geomdefs.hh:42
virtual ~G4Paraboloid()
static constexpr double mm
Definition: G4SIunits.hh:115
#define G4endl
Definition: G4ios.hh:61
const char * p
Definition: xmltok.h:285
Double_t z
void message(RunManager *runmanager)
Definition: ts_scorers.cc:72
G4ThreeVector GetPointOnSurface() const
double z() const
static double normal(HepRandomEngine *eptr)
Definition: RandPoisson.cc:77
double dot(const Hep3Vector &) const
Float_t tmp
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
G4VSolid * Clone() const
G4VSolid & operator=(const G4VSolid &rhs)
Definition: G4VSolid.cc:110
double G4double
Definition: G4Types.hh:76
bool G4bool
Definition: G4Types.hh:79
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:88
void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4Polyhedron * GetPolyhedron() const
G4double kCarTolerance
Definition: G4VSolid.hh:307
static constexpr double twopi
Definition: G4SIunits.hh:76
G4double fSurfaceArea
double A(double temperature)
double mag2() const
EInside Inside(const G4ThreeVector &p) const
ThreeVector shoot(const G4int Ap, const G4int Af)
G4Paraboloid & operator=(const G4Paraboloid &rhs)
Hep3Vector unit() const
static G4int GetNumberOfRotationSteps()
G4double fCubicVolume
std::ostream & StreamInfo(std::ostream &os) const
G4GeometryType GetEntityType() const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.hh:65
G4Polyhedron * CreatePolyhedron() const
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
int G4int
Definition: G4Types.hh:78
EInside
Definition: geomdefs.hh:58
EAxis
Definition: geomdefs.hh:54
G4String GetName() const
void DumpInfo() const
double perp2() const
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=G4bool(false), G4bool *validNorm=0, G4ThreeVector *n=0) const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4bool fRebuildPolyhedron
G4GLOB_DLL std::ostream G4cout
double x() const
Char_t n[5]
G4double CalculateSurfaceArea() const
T sqr(const T &x)
Definition: templates.hh:145
static constexpr double pi
Definition: G4SIunits.hh:75
double y() const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4Paraboloid(const G4String &pName, G4double pDz, G4double pR1, G4double pR2)
Definition: G4Paraboloid.cc:66
double B(double temperature)
std::mutex G4Mutex
Definition: G4Threading.hh:84