Geant4  10.00.p02
G4GenericTrap.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: G4GenericTrap.cc 81641 2014-06-04 09:11:38Z gcosmo $
28 //
29 //
30 // --------------------------------------------------------------------
31 // GEANT 4 class source file
32 //
33 // G4GenericTrap.cc
34 //
35 // Authors:
36 // Tatiana Nikitina, CERN; Ivana Hrivnacova, IPN Orsay
37 // Adapted from Root Arb8 implementation by Andrei Gheata, CERN
38 //
39 // History :
40 // 04 August 2011 T.Nikitina Add SetReferences() and InvertFacets()
41 // to CreatePolyhedron() for Visualisation of Boolean
42 // --------------------------------------------------------------------
43 
44 #include <iomanip>
45 
46 #include "G4GenericTrap.hh"
47 #include "G4PhysicalConstants.hh"
48 #include "G4SystemOfUnits.hh"
49 #include "G4TessellatedSolid.hh"
50 #include "G4TriangularFacet.hh"
51 #include "G4QuadrangularFacet.hh"
52 #include "G4VoxelLimits.hh"
53 #include "G4AffineTransform.hh"
54 #include "Randomize.hh"
55 
56 #include "G4VGraphicsScene.hh"
57 #include "G4Polyhedron.hh"
58 #include "G4PolyhedronArbitrary.hh"
59 #include "G4VisExtent.hh"
60 
63 
64 // --------------------------------------------------------------------
65 
67  const std::vector<G4TwoVector>& vertices )
68  : G4VSolid(name),
69  fpPolyhedron(0),
70  fDz(halfZ),
71  fVertices(),
72  fIsTwisted(false),
73  fTessellatedSolid(0),
74  fMinBBoxVector(G4ThreeVector(0,0,0)),
75  fMaxBBoxVector(G4ThreeVector(0,0,0)),
76  fVisSubdivisions(0),
77  fSurfaceArea(0.),
78  fCubicVolume(0.)
79 
80 {
81  // General constructor
82  const G4double min_length=5*1.e-6;
83  G4double length = 0.;
84  G4int k=0;
85  G4String errorDescription = "InvalidSetup in \" ";
86  errorDescription += name;
87  errorDescription += "\"";
88 
90 
91  // Check vertices size
92 
93  if ( G4int(vertices.size()) != fgkNofVertices )
94  {
95  G4Exception("G4GenericTrap::G4GenericTrap()", "GeomSolids0002",
96  FatalErrorInArgument, "Number of vertices != 8");
97  }
98 
99  // Check dZ
100  //
101  if (halfZ < kCarTolerance)
102  {
103  G4Exception("G4GenericTrap::G4GenericTrap()", "GeomSolids0002",
104  FatalErrorInArgument, "dZ is too small or negative");
105  }
106 
107  // Check Ordering and Copy vertices
108  //
109  if(CheckOrder(vertices))
110  {
111  for (G4int i=0; i<fgkNofVertices; ++i) {fVertices.push_back(vertices[i]);}
112  }
113  else
114  {
115  for (G4int i=0; i <4; ++i) {fVertices.push_back(vertices[3-i]);}
116  for (G4int i=0; i <4; ++i) {fVertices.push_back(vertices[7-i]);}
117  }
118 
119  // Check length of segments and Adjust
120  //
121  for (G4int j=0; j < 2; j++)
122  {
123  for (G4int i=1; i<4; ++i)
124  {
125  k = j*4+i;
126  length = (fVertices[k]-fVertices[k-1]).mag();
127  if ( ( length < min_length) && ( length > kCarTolerance ) )
128  {
129  std::ostringstream message;
130  message << "Length segment is too small." << G4endl
131  << "Distance between " << fVertices[k-1] << " and "
132  << fVertices[k] << " is only " << length << " mm !";
133  G4Exception("G4GenericTrap::G4GenericTrap()", "GeomSolids1001",
134  JustWarning, message, "Vertices will be collapsed.");
135  fVertices[k]=fVertices[k-1];
136  }
137  }
138  }
139 
140  // Compute Twist
141  //
142  for( G4int i=0; i<4; i++) { fTwist[i]=0.; }
144 
145  // Compute Bounding Box
146  //
147  ComputeBBox();
148 
149  // If not twisted - create tessellated solid
150  // (an alternative implementation for testing)
151  //
152 #ifdef G4TESS_TEST
154 #endif
155 }
156 
157 // --------------------------------------------------------------------
158 
160  : G4VSolid(a),
161  fpPolyhedron(0),
162  halfCarTolerance(0.),
163  fDz(0.),
164  fVertices(),
165  fIsTwisted(false),
166  fTessellatedSolid(0),
167  fMinBBoxVector(G4ThreeVector(0,0,0)),
168  fMaxBBoxVector(G4ThreeVector(0,0,0)),
169  fVisSubdivisions(0),
170  fSurfaceArea(0.),
171  fCubicVolume(0.)
172 {
173  // Fake default constructor - sets only member data and allocates memory
174  // for usage restricted to object persistency.
175 
176  for (size_t i=0; i<4; ++i) { fTwist[i]=0.; }
177 }
178 
179 // --------------------------------------------------------------------
180 
182 {
183  // Destructor
184  delete fTessellatedSolid;
185 }
186 
187 // --------------------------------------------------------------------
188 
190  : G4VSolid(rhs),
191  fpPolyhedron(0), halfCarTolerance(rhs.halfCarTolerance),
192  fDz(rhs.fDz), fVertices(rhs.fVertices),
193  fIsTwisted(rhs.fIsTwisted), fTessellatedSolid(0),
194  fMinBBoxVector(rhs.fMinBBoxVector), fMaxBBoxVector(rhs.fMaxBBoxVector),
195  fVisSubdivisions(rhs.fVisSubdivisions),
196  fSurfaceArea(rhs.fSurfaceArea), fCubicVolume(rhs.fCubicVolume)
197 {
198  for (size_t i=0; i<4; ++i) { fTwist[i] = rhs.fTwist[i]; }
199 #ifdef G4TESS_TEST
200  if (rhs.fTessellatedSolid && !fIsTwisted )
202 #endif
204 }
205 
206 // --------------------------------------------------------------------
207 
209 {
210  // Check assignment to self
211  //
212  if (this == &rhs) { return *this; }
213 
214  // Copy base class data
215  //
216  G4VSolid::operator=(rhs);
217 
218  // Copy data
219  //
221  fDz = rhs.fDz; fVertices = rhs.fVertices;
226 
227  for (size_t i=0; i<4; ++i) { fTwist[i] = rhs.fTwist[i]; }
228 #ifdef G4TESS_TEST
229  if (rhs.fTessellatedSolid && !fIsTwisted )
231 #endif
233 
234  return *this;
235 }
236 
237 // --------------------------------------------------------------------
238 
239 EInside
241  const std::vector<G4TwoVector>& poly) const
242 {
243  EInside in = kInside;
244  G4double cross, len2;
245  G4int count=0;
246 
247  for (G4int i = 0; i < 4; i++)
248  {
249  G4int j = (i+1) % 4;
250 
251  cross = (p.x()-poly[i].x())*(poly[j].y()-poly[i].y())-
252  (p.y()-poly[i].y())*(poly[j].x()-poly[i].x());
253 
254  len2=(poly[i]-poly[j]).mag2();
255  if (len2 > kCarTolerance)
256  {
257  if(cross*cross<=len2*halfCarTolerance*halfCarTolerance) // Surface check
258  {
259  G4double test;
260 
261  // Check if p lies between the two extremes of the segment
262  //
263  G4int iMax;
264  G4int iMin;
265 
266  if (poly[j].x() > poly[i].x())
267  {
268  iMax = j;
269  iMin = i;
270  }
271  else {
272  iMax = i;
273  iMin = j;
274  }
275  if ( p.x() > poly[iMax].x()+halfCarTolerance
276  || p.x() < poly[iMin].x()-halfCarTolerance )
277  {
278  return kOutside;
279  }
280 
281  if (poly[j].y() > poly[i].y())
282  {
283  iMax = j;
284  iMin = i;
285  }
286  else
287  {
288  iMax = i;
289  iMin = j;
290  }
291  if ( p.y() > poly[iMax].y()+halfCarTolerance
292  || p.y() < poly[iMin].y()-halfCarTolerance )
293  {
294  return kOutside;
295  }
296 
297  if ( poly[iMax].x() != poly[iMin].x() )
298  {
299  test = (p.x()-poly[iMin].x())/(poly[iMax].x()-poly[iMin].x())
300  * (poly[iMax].y()-poly[iMin].y())+poly[iMin].y();
301  }
302  else
303  {
304  test = p.y();
305  }
306 
307  // Check if point is Inside Segment
308  //
309  if( (test>=(poly[iMin].y()-halfCarTolerance))
310  && (test<=(poly[iMax].y()+halfCarTolerance)) )
311  {
312  return kSurface;
313  }
314  else
315  {
316  return kOutside;
317  }
318  }
319  else if (cross<0.) { return kOutside; }
320  }
321  else
322  {
323  count++;
324  }
325  }
326 
327  // All collapsed vertices, Tet like
328  //
329  if(count==4)
330  {
331  if ( (std::fabs(p.x()-poly[0].x())+std::fabs(p.y()-poly[0].y())) > halfCarTolerance )
332  {
333  in=kOutside;
334  }
335  }
336  return in;
337 }
338 
339 // --------------------------------------------------------------------
340 
342 {
343  // Test if point is inside this shape
344 
345 #ifdef G4TESS_TEST
346  if ( fTessellatedSolid )
347  {
348  return fTessellatedSolid->Inside(p);
349  }
350 #endif
351 
352  EInside innew=kOutside;
353  std::vector<G4TwoVector> xy;
354 
355  if (std::fabs(p.z()) <= fDz+halfCarTolerance) // First check Z range
356  {
357  // Compute intersection between Z plane containing point and the shape
358  //
359  G4double cf = 0.5*(fDz-p.z())/fDz;
360  for (G4int i=0; i<4; i++)
361  {
362  xy.push_back(fVertices[i+4]+cf*( fVertices[i]-fVertices[i+4]));
363  }
364 
365  innew=InsidePolygone(p,xy);
366 
367  if( (innew==kInside) || (innew==kSurface) )
368  {
369  if(std::fabs(p.z()) > fDz-halfCarTolerance) { innew=kSurface; }
370  }
371  }
372  return innew;
373 }
374 
375 // --------------------------------------------------------------------
376 
378 {
379  // Calculate side nearest to p, and return normal
380  // If two sides are equidistant, sum of the Normal is returned
381 
382 #ifdef G4TESS_TEST
383  if ( fTessellatedSolid )
384  {
385  return fTessellatedSolid->SurfaceNormal(p);
386  }
387 #endif
388 
389  G4ThreeVector lnorm, sumnorm(0.,0.,0.), apprnorm(0.,0.,1.),
390  p0, p1, p2, r1, r2, r3, r4;
391  G4int noSurfaces = 0;
392  G4double distxy,distz;
393  G4bool zPlusSide=false;
394 
395  distz = fDz-std::fabs(p.z());
396  if (distz < halfCarTolerance)
397  {
398  if(p.z()>0)
399  {
400  zPlusSide=true;
401  sumnorm=G4ThreeVector(0,0,1);
402  }
403  else
404  {
405  sumnorm=G4ThreeVector(0,0,-1);
406  }
407  noSurfaces ++;
408  }
409 
410  // Check lateral planes
411  //
412  std:: vector<G4TwoVector> vertices;
413  G4double cf = 0.5*(fDz-p.z())/fDz;
414  for (G4int i=0; i<4; i++)
415  {
416  vertices.push_back(fVertices[i+4]+cf*(fVertices[i]-fVertices[i+4]));
417  }
418 
419  // Compute distance for lateral planes
420  //
421  for (G4int q=0; q<4; q++)
422  {
423  p0=G4ThreeVector(vertices[q].x(),vertices[q].y(),p.z());
424  if(zPlusSide)
425  {
426  p1=G4ThreeVector(fVertices[q].x(),fVertices[q].y(),-fDz);
427  }
428  else
429  {
430  p1=G4ThreeVector(fVertices[q+4].x(),fVertices[q+4].y(),fDz);
431  }
432  p2=G4ThreeVector(vertices[(q+1)%4].x(),vertices[(q+1)%4].y(),p.z());
433 
434  // Collapsed vertices
435  //
436  if ( (p2-p0).mag2() < kCarTolerance )
437  {
438  if ( std::fabs(p.z()+fDz) > kCarTolerance )
439  {
440  p2=G4ThreeVector(fVertices[(q+1)%4].x(),fVertices[(q+1)%4].y(),-fDz);
441  }
442  else
443  {
444  p2=G4ThreeVector(fVertices[(q+1)%4+4].x(),fVertices[(q+1)%4+4].y(),fDz);
445  }
446  }
447  lnorm = (p1-p0).cross(p2-p0);
448  lnorm = lnorm.unit();
449  if(zPlusSide) { lnorm=-lnorm; }
450 
451  // Adjust Normal for Twisted Surface
452  //
453  if ( (fIsTwisted) && (GetTwistAngle(q)!=0) )
454  {
455  G4double normP=(p2-p0).mag();
456  if(normP)
457  {
458  G4double proj=(p-p0).dot(p2-p0)/normP;
459  if(proj<0) { proj=0; }
460  if(proj>normP) { proj=normP; }
461  G4int j=(q+1)%4;
462  r1=G4ThreeVector(fVertices[q+4].x(),fVertices[q+4].y(),fDz);
463  r2=G4ThreeVector(fVertices[j+4].x(),fVertices[j+4].y(),fDz);
464  r3=G4ThreeVector(fVertices[q].x(),fVertices[q].y(),-fDz);
465  r4=G4ThreeVector(fVertices[j].x(),fVertices[j].y(),-fDz);
466  r1=r1+proj*(r2-r1)/normP;
467  r3=r3+proj*(r4-r3)/normP;
468  r2=r1-r3;
469  r4=r2.cross(p2-p0); r4=r4.unit();
470  lnorm=r4;
471  }
472  } // End if fIsTwisted
473 
474  distxy=std::fabs((p0-p).dot(lnorm));
475  if ( distxy<halfCarTolerance )
476  {
477  noSurfaces ++;
478 
479  // Negative sign for Normal is taken for Outside Normal
480  //
481  sumnorm=sumnorm+lnorm;
482  }
483 
484  // For ApproxSurfaceNormal
485  //
486  if (distxy<distz)
487  {
488  distz=distxy;
489  apprnorm=lnorm;
490  }
491  } // End for loop
492 
493  // Calculate final Normal, add Normal in the Corners and Touching Sides
494  //
495  if ( noSurfaces == 0 )
496  {
497  G4Exception("G4GenericTrap::SurfaceNormal(p)", "GeomSolids1002",
498  JustWarning, "Point p is not on surface !?" );
499  sumnorm=apprnorm;
500  // Add Approximative Surface Normal Calculation?
501  }
502  else if ( noSurfaces == 1 ) { sumnorm = sumnorm; }
503  else { sumnorm = sumnorm.unit(); }
504 
505  return sumnorm ;
506 }
507 
508 // --------------------------------------------------------------------
509 
511  const G4int ipl ) const
512 {
513  // Return normal to given lateral plane ipl
514 
515 #ifdef G4TESS_TEST
516  if ( fTessellatedSolid )
517  {
518  return fTessellatedSolid->SurfaceNormal(p);
519  }
520 #endif
521 
522  G4ThreeVector lnorm, norm(0.,0.,0.), p0,p1,p2;
523 
524  G4double distz = fDz-p.z();
525  G4int i=ipl; // current plane index
526 
527  G4TwoVector u,v;
528  G4ThreeVector r1,r2,r3,r4;
529  G4double cf = 0.5*(fDz-p.z())/fDz;
530  G4int j=(i+1)%4;
531 
532  u=fVertices[i+4]+cf*(fVertices[i]-fVertices[i+4]);
533  v=fVertices[j+4]+cf*(fVertices[j]-fVertices[j+4]);
534 
535  // Compute cross product
536  //
537  p0=G4ThreeVector(u.x(),u.y(),p.z());
538 
539  if (std::fabs(distz)<halfCarTolerance)
540  {
541  p1=G4ThreeVector(fVertices[i].x(),fVertices[i].y(),-fDz);distz=-1;}
542  else
543  {
544  p1=G4ThreeVector(fVertices[i+4].x(),fVertices[i+4].y(),fDz);
545  }
546  p2=G4ThreeVector(v.x(),v.y(),p.z());
547 
548  // Collapsed vertices
549  //
550  if ( (p2-p0).mag2() < kCarTolerance )
551  {
552  if ( std::fabs(p.z()+fDz) > halfCarTolerance )
553  {
554  p2=G4ThreeVector(fVertices[j].x(),fVertices[j].y(),-fDz);
555  }
556  else
557  {
558  p2=G4ThreeVector(fVertices[j+4].x(),fVertices[j+4].y(),fDz);
559  }
560  }
561  lnorm=-(p1-p0).cross(p2-p0);
562  if (distz>-halfCarTolerance) { lnorm=-lnorm.unit(); }
563  else { lnorm=lnorm.unit(); }
564 
565  // Adjust Normal for Twisted Surface
566  //
567  if( (fIsTwisted) && (GetTwistAngle(ipl)!=0) )
568  {
569  G4double normP=(p2-p0).mag();
570  if(normP)
571  {
572  G4double proj=(p-p0).dot(p2-p0)/normP;
573  if (proj<0) { proj=0; }
574  if (proj>normP) { proj=normP; }
575 
576  r1=G4ThreeVector(fVertices[i+4].x(),fVertices[i+4].y(),fDz);
577  r2=G4ThreeVector(fVertices[j+4].x(),fVertices[j+4].y(),fDz);
578  r3=G4ThreeVector(fVertices[i].x(),fVertices[i].y(),-fDz);
579  r4=G4ThreeVector(fVertices[j].x(),fVertices[j].y(),-fDz);
580  r1=r1+proj*(r2-r1)/normP;
581  r3=r3+proj*(r4-r3)/normP;
582  r2=r1-r3;
583  r4=r2.cross(p2-p0);r4=r4.unit();
584  lnorm=r4;
585  }
586  } // End if fIsTwisted
587 
588  return lnorm;
589 }
590 
591 // --------------------------------------------------------------------
592 
594  const G4ThreeVector& v,
595  const G4int ipl) const
596 {
597  // Computes distance to plane ipl :
598  // ipl=0 : points 0,4,1,5
599  // ipl=1 : points 1,5,2,6
600  // ipl=2 : points 2,6,3,7
601  // ipl=3 : points 3,7,0,4
602 
603  G4double xa,xb,xc,xd,ya,yb,yc,yd;
604 
605  G4int j = (ipl+1)%4;
606 
607  xa=fVertices[ipl].x();
608  ya=fVertices[ipl].y();
609  xb=fVertices[ipl+4].x();
610  yb=fVertices[ipl+4].y();
611  xc=fVertices[j].x();
612  yc=fVertices[j].y();
613  xd=fVertices[4+j].x();
614  yd=fVertices[4+j].y();
615 
616  G4double dz2 =0.5/fDz;
617  G4double tx1 =dz2*(xb-xa);
618  G4double ty1 =dz2*(yb-ya);
619  G4double tx2 =dz2*(xd-xc);
620  G4double ty2 =dz2*(yd-yc);
621  G4double dzp =fDz+p.z();
622  G4double xs1 =xa+tx1*dzp;
623  G4double ys1 =ya+ty1*dzp;
624  G4double xs2 =xc+tx2*dzp;
625  G4double ys2 =yc+ty2*dzp;
626  G4double dxs =xs2-xs1;
627  G4double dys =ys2-ys1;
628  G4double dtx =tx2-tx1;
629  G4double dty =ty2-ty1;
630 
631  G4double a = (dtx*v.y()-dty*v.x()+(tx1*ty2-tx2*ty1)*v.z())*v.z();
632  G4double b = dxs*v.y()-dys*v.x()+(dtx*p.y()-dty*p.x()+ty2*xs1-ty1*xs2
633  + tx1*ys2-tx2*ys1)*v.z();
634  G4double c=dxs*p.y()-dys*p.x()+xs1*ys2-xs2*ys1;
636  G4double x1,x2,y1,y2,xp,yp,zi;
637 
638  if (std::fabs(a)<kCarTolerance)
639  {
640  if (std::fabs(b)<kCarTolerance) { return kInfinity; }
641  q=-c/b;
642 
643  // Check if Point is on the Surface
644 
645  if (q>-halfCarTolerance)
646  {
647  if (q<halfCarTolerance)
648  {
649  if (NormalToPlane(p,ipl).dot(v)<=0)
650  { if(Inside(p) != kOutside) { return 0.; } }
651  else
652  { return kInfinity; }
653  }
654 
655  // Check the Intersection
656  //
657  zi=p.z()+q*v.z();
658  if (std::fabs(zi)<fDz)
659  {
660  x1=xs1+tx1*v.z()*q;
661  x2=xs2+tx2*v.z()*q;
662  xp=p.x()+q*v.x();
663  y1=ys1+ty1*v.z()*q;
664  y2=ys2+ty2*v.z()*q;
665  yp=p.y()+q*v.y();
666  zi = (xp-x1)*(xp-x2)+(yp-y1)*(yp-y2);
667  if (zi<=halfCarTolerance) { return q; }
668  }
669  }
670  return kInfinity;
671  }
672  G4double d=b*b-4*a*c;
673  if (d>=0)
674  {
675  if (a>0) { q=0.5*(-b-std::sqrt(d))/a; }
676  else { q=0.5*(-b+std::sqrt(d))/a; }
677 
678  // Check if Point is on the Surface
679  //
680  if (q>-halfCarTolerance)
681  {
682  if(q<halfCarTolerance)
683  {
684  if (NormalToPlane(p,ipl).dot(v)<=0)
685  {
686  if(Inside(p)!= kOutside) { return 0.; }
687  }
688  else // Check second root; return kInfinity
689  {
690  if (a>0) { q=0.5*(-b+std::sqrt(d))/a; }
691  else { q=0.5*(-b-std::sqrt(d))/a; }
692  if (q<=halfCarTolerance) { return kInfinity; }
693  }
694  }
695  // Check the Intersection
696  //
697  zi=p.z()+q*v.z();
698  if (std::fabs(zi)<fDz)
699  {
700  x1=xs1+tx1*v.z()*q;
701  x2=xs2+tx2*v.z()*q;
702  xp=p.x()+q*v.x();
703  y1=ys1+ty1*v.z()*q;
704  y2=ys2+ty2*v.z()*q;
705  yp=p.y()+q*v.y();
706  zi = (xp-x1)*(xp-x2)+(yp-y1)*(yp-y2);
707  if (zi<=halfCarTolerance) { return q; }
708  }
709  }
710  if (a>0) { q=0.5*(-b+std::sqrt(d))/a; }
711  else { q=0.5*(-b-std::sqrt(d))/a; }
712 
713  // Check if Point is on the Surface
714  //
715  if (q>-halfCarTolerance)
716  {
717  if(q<halfCarTolerance)
718  {
719  if (NormalToPlane(p,ipl).dot(v)<=0)
720  {
721  if(Inside(p) != kOutside) { return 0.; }
722  }
723  else // Check second root; return kInfinity.
724  {
725  if (a>0) { q=0.5*(-b-std::sqrt(d))/a; }
726  else { q=0.5*(-b+std::sqrt(d))/a; }
727  if (q<=halfCarTolerance) { return kInfinity; }
728  }
729  }
730  // Check the Intersection
731  //
732  zi=p.z()+q*v.z();
733  if (std::fabs(zi)<fDz)
734  {
735  x1=xs1+tx1*v.z()*q;
736  x2=xs2+tx2*v.z()*q;
737  xp=p.x()+q*v.x();
738  y1=ys1+ty1*v.z()*q;
739  y2=ys2+ty2*v.z()*q;
740  yp=p.y()+q*v.y();
741  zi = (xp-x1)*(xp-x2)+(yp-y1)*(yp-y2);
742  if (zi<=halfCarTolerance) { return q; }
743  }
744  }
745  }
746  return kInfinity;
747 }
748 
749 // --------------------------------------------------------------------
750 
752  const G4ThreeVector& v) const
753 {
754 #ifdef G4TESS_TEST
755  if ( fTessellatedSolid )
756  {
757  return fTessellatedSolid->DistanceToIn(p, v);
758  }
759 #endif
760 
761  G4double dist[5];
763 
764  // Check lateral faces
765  //
766  G4int i;
767  for (i=0; i<4; i++)
768  {
769  dist[i]=DistToPlane(p, v, i);
770  }
771 
772  // Check Z planes
773  //
774  dist[4]=kInfinity;
775  if (std::fabs(p.z())>fDz-halfCarTolerance)
776  {
777  if (v.z())
778  {
779  G4ThreeVector pt;
780  if (p.z()>0)
781  {
782  dist[4] = (fDz-p.z())/v.z();
783  }
784  else
785  {
786  dist[4] = (-fDz-p.z())/v.z();
787  }
788  if (dist[4]<-halfCarTolerance)
789  {
790  dist[4]=kInfinity;
791  }
792  else
793  {
794  if(dist[4]<halfCarTolerance)
795  {
796  if(p.z()>0) { n=G4ThreeVector(0,0,1); }
797  else { n=G4ThreeVector(0,0,-1); }
798  if (n.dot(v)<0) { dist[4]=0.; }
799  else { dist[4]=kInfinity; }
800  }
801  pt=p+dist[4]*v;
802  if (Inside(pt)==kOutside) { dist[4]=kInfinity; }
803  }
804  }
805  }
806  G4double distmin = dist[0];
807  for (i=1;i<5;i++)
808  {
809  if (dist[i] < distmin) { distmin = dist[i]; }
810  }
811 
812  if (distmin<halfCarTolerance) { distmin=0.; }
813 
814  return distmin;
815 }
816 
817 // --------------------------------------------------------------------
818 
820 {
821  // Computes the closest distance from given point to this shape
822 
823 #ifdef G4TESS_TEST
824  if ( fTessellatedSolid )
825  {
826  return fTessellatedSolid->DistanceToIn(p);
827  }
828 #endif
829 
830  G4double safz = std::fabs(p.z())-fDz;
831  if(safz<0) { safz=0; }
832 
833  G4int iseg;
834  G4double safe = safz;
835  G4double safxy = safz;
836 
837  for (iseg=0; iseg<4; iseg++)
838  {
839  safxy = SafetyToFace(p,iseg);
840  if (safxy>safe) { safe=safxy; }
841  }
842 
843  return safe;
844 }
845 
846 // --------------------------------------------------------------------
847 
848 G4double
850 {
851  // Estimate distance to lateral plane defined by segment iseg in range [0,3]
852  // Might be negative: plane seen only from inside
853 
854  G4ThreeVector p1,norm;
855  G4double safe;
856 
857  p1=G4ThreeVector(fVertices[iseg].x(),fVertices[iseg].y(),-fDz);
858 
859  norm=NormalToPlane(p,iseg);
860  safe = (p-p1).dot(norm); // Can be negative
861 
862  return safe;
863 }
864 
865 // --------------------------------------------------------------------
866 
867 G4double
869  const G4ThreeVector& v, const G4int ipl) const
870 {
871  G4double xa=fVertices[ipl].x();
872  G4double ya=fVertices[ipl].y();
873  G4double xb=fVertices[ipl+4].x();
874  G4double yb=fVertices[ipl+4].y();
875  G4int j=(ipl+1)%4;
876  G4double xc=fVertices[j].x();
877  G4double yc=fVertices[j].y();
878  G4double zab=2*fDz;
879  G4double zac=0;
880 
881  if ( (std::fabs(xa-xc)+std::fabs(ya-yc)) < halfCarTolerance )
882  {
883  xc=fVertices[j+4].x();
884  yc=fVertices[j+4].y();
885  zac=2*fDz;
886  zab=2*fDz;
887 
888  //Line case
889  //
890  if ( (std::fabs(xb-xc)+std::fabs(yb-yc)) < halfCarTolerance )
891  {
892  return kInfinity;
893  }
894  }
895  G4double a=(yb-ya)*zac-(yc-ya)*zab;
896  G4double b=(xc-xa)*zab-(xb-xa)*zac;
897  G4double c=(xb-xa)*(yc-ya)-(xc-xa)*(yb-ya);
898  G4double d=-xa*a-ya*b+fDz*c;
899  G4double t=a*v.x()+b*v.y()+c*v.z();
900 
901  if (t!=0)
902  {
903  t=-(a*p.x()+b*p.y()+c*p.z()+d)/t;
904  }
905  if ( (t<halfCarTolerance) && (t>-halfCarTolerance) )
906  {
907  if (NormalToPlane(p,ipl).dot(v)<kCarTolerance)
908  {
909  t=kInfinity;
910  }
911  else
912  {
913  t=0;
914  }
915  }
916  if (Inside(p+v*t) != kSurface) { t=kInfinity; }
917 
918  return t;
919 }
920 
921 // --------------------------------------------------------------------
922 
924  const G4ThreeVector& v,
925  const G4bool calcNorm,
926  G4bool* validNorm,
927  G4ThreeVector* n) const
928 {
929 #ifdef G4TESS_TEST
930  if ( fTessellatedSolid )
931  {
932  return fTessellatedSolid->DistanceToOut(p, v, calcNorm, validNorm, n);
933  }
934 #endif
935 
936  G4double distmin;
937  G4bool lateral_cross = false;
938  ESide side = kUndefined;
939 
940  if (calcNorm) { *validNorm=true; } // All normals are valid
941 
942  if (v.z() < 0)
943  {
944  distmin=(-fDz-p.z())/v.z();
945  if (calcNorm) { side=kMZ; *n=G4ThreeVector(0,0,-1); }
946  }
947  else
948  {
949  if (v.z() > 0)
950  {
951  distmin = (fDz-p.z())/v.z();
952  if (calcNorm) { side=kPZ; *n=G4ThreeVector(0,0,1); }
953  }
954  else { distmin = kInfinity; }
955  }
956 
957  G4double dz2 =0.5/fDz;
958  G4double xa,xb,xc,xd;
959  G4double ya,yb,yc,yd;
960 
961  for (G4int ipl=0; ipl<4; ipl++)
962  {
963  G4int j = (ipl+1)%4;
964  xa=fVertices[ipl].x();
965  ya=fVertices[ipl].y();
966  xb=fVertices[ipl+4].x();
967  yb=fVertices[ipl+4].y();
968  xc=fVertices[j].x();
969  yc=fVertices[j].y();
970  xd=fVertices[4+j].x();
971  yd=fVertices[4+j].y();
972 
973  if ( ((std::fabs(xb-xd)+std::fabs(yb-yd))<halfCarTolerance)
974  || ((std::fabs(xa-xc)+std::fabs(ya-yc))<halfCarTolerance) )
975  {
976  G4double q=DistToTriangle(p,v,ipl) ;
977  if ( (q>=0) && (q<distmin) )
978  {
979  distmin=q;
980  lateral_cross=true;
981  side=ESide(ipl+1);
982  }
983  continue;
984  }
985  G4double tx1 =dz2*(xb-xa);
986  G4double ty1 =dz2*(yb-ya);
987  G4double tx2 =dz2*(xd-xc);
988  G4double ty2 =dz2*(yd-yc);
989  G4double dzp =fDz+p.z();
990  G4double xs1 =xa+tx1*dzp;
991  G4double ys1 =ya+ty1*dzp;
992  G4double xs2 =xc+tx2*dzp;
993  G4double ys2 =yc+ty2*dzp;
994  G4double dxs =xs2-xs1;
995  G4double dys =ys2-ys1;
996  G4double dtx =tx2-tx1;
997  G4double dty =ty2-ty1;
998  G4double a = (dtx*v.y()-dty*v.x()+(tx1*ty2-tx2*ty1)*v.z())*v.z();
999  G4double b = dxs*v.y()-dys*v.x()+(dtx*p.y()-dty*p.x()+ty2*xs1-ty1*xs2
1000  + tx1*ys2-tx2*ys1)*v.z();
1001  G4double c=dxs*p.y()-dys*p.x()+xs1*ys2-xs2*ys1;
1002  G4double q=kInfinity;
1003 
1004  if (std::fabs(a) < kCarTolerance)
1005  {
1006  if (std::fabs(b) < kCarTolerance) { continue; }
1007  q=-c/b;
1008 
1009  // Check for Point on the Surface
1010  //
1011  if ((q > -halfCarTolerance) && (q < distmin))
1012  {
1013  if (q < halfCarTolerance)
1014  {
1015  if (NormalToPlane(p,ipl).dot(v)<0.) { continue; }
1016  }
1017  distmin =q;
1018  lateral_cross=true;
1019  side=ESide(ipl+1);
1020  }
1021  continue;
1022  }
1023  G4double d=b*b-4*a*c;
1024  if (d >= 0.)
1025  {
1026  if (a > 0) { q=0.5*(-b-std::sqrt(d))/a; }
1027  else { q=0.5*(-b+std::sqrt(d))/a; }
1028 
1029  // Check for Point on the Surface
1030  //
1031  if (q > -halfCarTolerance )
1032  {
1033  if (q < distmin)
1034  {
1035  if(q < halfCarTolerance)
1036  {
1037  if (NormalToPlane(p,ipl).dot(v)<0.) // Check second root
1038  {
1039  if (a > 0) { q=0.5*(-b+std::sqrt(d))/a; }
1040  else { q=0.5*(-b-std::sqrt(d))/a; }
1041  if (( q > halfCarTolerance) && (q < distmin))
1042  {
1043  distmin=q;
1044  lateral_cross = true;
1045  side=ESide(ipl+1);
1046  }
1047  continue;
1048  }
1049  }
1050  distmin = q;
1051  lateral_cross = true;
1052  side=ESide(ipl+1);
1053  }
1054  }
1055  else
1056  {
1057  if (a > 0) { q=0.5*(-b+std::sqrt(d))/a; }
1058  else { q=0.5*(-b-std::sqrt(d))/a; }
1059 
1060  // Check for Point on the Surface
1061  //
1062  if ((q > -halfCarTolerance) && (q < distmin))
1063  {
1064  if (q < halfCarTolerance)
1065  {
1066  if (NormalToPlane(p,ipl).dot(v)<0.) // Check second root
1067  {
1068  if (a > 0) { q=0.5*(-b-std::sqrt(d))/a; }
1069  else { q=0.5*(-b+std::sqrt(d))/a; }
1070  if ( ( q > halfCarTolerance) && (q < distmin) )
1071  {
1072  distmin=q;
1073  lateral_cross = true;
1074  side=ESide(ipl+1);
1075  }
1076  continue;
1077  }
1078  }
1079  distmin =q;
1080  lateral_cross = true;
1081  side=ESide(ipl+1);
1082  }
1083  }
1084  }
1085  }
1086  if (!lateral_cross) // Make sure that track crosses the top or bottom
1087  {
1088  if (distmin >= kInfinity) { distmin=kCarTolerance; }
1089  G4ThreeVector pt=p+distmin*v;
1090 
1091  // Check if propagated point is in the polygon
1092  //
1093  G4int i=0;
1094  if (v.z()>0.) { i=4; }
1095  std::vector<G4TwoVector> xy;
1096  for ( G4int j=0; j<4; j++) { xy.push_back(fVertices[i+j]); }
1097 
1098  // Check Inside
1099  //
1100  if (InsidePolygone(pt,xy)==kOutside)
1101  {
1102  if(calcNorm)
1103  {
1104  if (v.z()>0) {side= kPZ; *n = G4ThreeVector(0,0,1);}
1105  else { side=kMZ; *n = G4ThreeVector(0,0,-1);}
1106  }
1107  return 0.;
1108  }
1109  else
1110  {
1111  if(v.z()>0) {side=kPZ;}
1112  else {side=kMZ;}
1113  }
1114  }
1115 
1116  if (calcNorm)
1117  {
1118  G4ThreeVector pt=p+v*distmin;
1119  switch (side)
1120  {
1121  case kXY0:
1122  *n=NormalToPlane(pt,0);
1123  break;
1124  case kXY1:
1125  *n=NormalToPlane(pt,1);
1126  break;
1127  case kXY2:
1128  *n=NormalToPlane(pt,2);
1129  break;
1130  case kXY3:
1131  *n=NormalToPlane(pt,3);
1132  break;
1133  case kPZ:
1134  *n=G4ThreeVector(0,0,1);
1135  break;
1136  case kMZ:
1137  *n=G4ThreeVector(0,0,-1);
1138  break;
1139  default:
1140  DumpInfo();
1141  std::ostringstream message;
1142  G4int oldprc = message.precision(16);
1143  message << "Undefined side for valid surface normal to solid." << G4endl
1144  << "Position:" << G4endl
1145  << " p.x() = " << p.x()/mm << " mm" << G4endl
1146  << " p.y() = " << p.y()/mm << " mm" << G4endl
1147  << " p.z() = " << p.z()/mm << " mm" << G4endl
1148  << "Direction:" << G4endl
1149  << " v.x() = " << v.x() << G4endl
1150  << " v.y() = " << v.y() << G4endl
1151  << " v.z() = " << v.z() << G4endl
1152  << "Proposed distance :" << G4endl
1153  << " distmin = " << distmin/mm << " mm";
1154  message.precision(oldprc);
1155  G4Exception("G4GenericTrap::DistanceToOut(p,v,..)",
1156  "GeomSolids1002", JustWarning, message);
1157  break;
1158  }
1159  }
1160 
1161  if (distmin<halfCarTolerance) { distmin=0.; }
1162 
1163  return distmin;
1164 }
1165 
1166 // --------------------------------------------------------------------
1167 
1169 {
1170 
1171 #ifdef G4TESS_TEST
1172  if ( fTessellatedSolid )
1173  {
1174  return fTessellatedSolid->DistanceToOut(p);
1175  }
1176 #endif
1177 
1178  G4double safz = fDz-std::fabs(p.z());
1179  if (safz<0) { safz = 0; }
1180 
1181  G4double safe = safz;
1182  G4double safxy = safz;
1183 
1184  for (G4int iseg=0; iseg<4; iseg++)
1185  {
1186  safxy = std::fabs(SafetyToFace(p,iseg));
1187  if (safxy < safe) { safe = safxy; }
1188  }
1189 
1190  return safe;
1191 }
1192 
1193 // --------------------------------------------------------------------
1194 
1196  const G4VoxelLimits& pVoxelLimit,
1197  const G4AffineTransform& pTransform,
1198  G4double& pMin, G4double& pMax) const
1199 {
1200 #ifdef G4TESS_TEST
1201  if ( fTessellatedSolid )
1202  {
1203  return fTessellatedSolid->CalculateExtent(pAxis, pVoxelLimit,
1204  pTransform, pMin, pMax);
1205  }
1206 #endif
1207 
1208  // Computes bounding vectors for a shape
1209  //
1210  G4double Dx,Dy;
1211  G4ThreeVector minVec = GetMinimumBBox();
1212  G4ThreeVector maxVec = GetMaximumBBox();
1213  Dx = 0.5*(maxVec.x()- minVec.x());
1214  Dy = 0.5*(maxVec.y()- minVec.y());
1215 
1216  if (!pTransform.IsRotated())
1217  {
1218  // Special case handling for unrotated shapes
1219  // Compute x/y/z mins and maxs respecting limits, with early returns
1220  // if outside limits. Then switch() on pAxis
1221  //
1222  G4double xoffset,xMin,xMax;
1223  G4double yoffset,yMin,yMax;
1224  G4double zoffset,zMin,zMax;
1225 
1226  xoffset=pTransform.NetTranslation().x();
1227  xMin=xoffset-Dx;
1228  xMax=xoffset+Dx;
1229  if (pVoxelLimit.IsXLimited())
1230  {
1231  if ( (xMin>pVoxelLimit.GetMaxXExtent()+kCarTolerance)
1232  || (xMax<pVoxelLimit.GetMinXExtent()-kCarTolerance) )
1233  {
1234  return false;
1235  }
1236  else
1237  {
1238  if (xMin<pVoxelLimit.GetMinXExtent())
1239  {
1240  xMin=pVoxelLimit.GetMinXExtent();
1241  }
1242  if (xMax>pVoxelLimit.GetMaxXExtent())
1243  {
1244  xMax=pVoxelLimit.GetMaxXExtent();
1245  }
1246  }
1247  }
1248 
1249  yoffset=pTransform.NetTranslation().y();
1250  yMin=yoffset-Dy;
1251  yMax=yoffset+Dy;
1252  if (pVoxelLimit.IsYLimited())
1253  {
1254  if ( (yMin>pVoxelLimit.GetMaxYExtent()+kCarTolerance)
1255  || (yMax<pVoxelLimit.GetMinYExtent()-kCarTolerance) )
1256  {
1257  return false;
1258  }
1259  else
1260  {
1261  if (yMin<pVoxelLimit.GetMinYExtent())
1262  {
1263  yMin=pVoxelLimit.GetMinYExtent();
1264  }
1265  if (yMax>pVoxelLimit.GetMaxYExtent())
1266  {
1267  yMax=pVoxelLimit.GetMaxYExtent();
1268  }
1269  }
1270  }
1271 
1272  zoffset=pTransform.NetTranslation().z();
1273  zMin=zoffset-fDz;
1274  zMax=zoffset+fDz;
1275  if (pVoxelLimit.IsZLimited())
1276  {
1277  if ( (zMin>pVoxelLimit.GetMaxZExtent()+kCarTolerance)
1278  || (zMax<pVoxelLimit.GetMinZExtent()-kCarTolerance) )
1279  {
1280  return false;
1281  }
1282  else
1283  {
1284  if (zMin<pVoxelLimit.GetMinZExtent())
1285  {
1286  zMin=pVoxelLimit.GetMinZExtent();
1287  }
1288  if (zMax>pVoxelLimit.GetMaxZExtent())
1289  {
1290  zMax=pVoxelLimit.GetMaxZExtent();
1291  }
1292  }
1293  }
1294 
1295  switch (pAxis)
1296  {
1297  case kXAxis:
1298  pMin = xMin;
1299  pMax = xMax;
1300  break;
1301  case kYAxis:
1302  pMin = yMin;
1303  pMax = yMax;
1304  break;
1305  case kZAxis:
1306  pMin = zMin;
1307  pMax = zMax;
1308  break;
1309  default:
1310  break;
1311  }
1312  pMin-=kCarTolerance;
1313  pMax+=kCarTolerance;
1314 
1315  return true;
1316  }
1317  else
1318  {
1319  // General rotated case - create and clip mesh to boundaries
1320 
1321  G4bool existsAfterClip=false;
1322  G4ThreeVectorList *vertices;
1323 
1324  pMin=+kInfinity;
1325  pMax=-kInfinity;
1326 
1327  // Calculate rotated vertex coordinates
1328  //
1329  vertices=CreateRotatedVertices(pTransform);
1330  ClipCrossSection(vertices,0,pVoxelLimit,pAxis,pMin,pMax);
1331  ClipCrossSection(vertices,4,pVoxelLimit,pAxis,pMin,pMax);
1332  ClipBetweenSections(vertices,0,pVoxelLimit,pAxis,pMin,pMax);
1333 
1334  if ( (pMin!=kInfinity) || (pMax!=-kInfinity) )
1335  {
1336  existsAfterClip=true;
1337 
1338  // Add 2*tolerance to avoid precision troubles
1339  //
1340  pMin-=kCarTolerance;
1341  pMax+=kCarTolerance;
1342  }
1343  else
1344  {
1345  // Check for case where completely enveloping clipping volume.
1346  // If point inside then we are confident that the solid completely
1347  // envelopes the clipping volume. Hence set min/max extents according
1348  // to clipping volume extents along the specified axis.
1349  //
1350  G4ThreeVector clipCentre(
1351  (pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
1352  (pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
1353  (pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5);
1354 
1355  if (Inside(pTransform.Inverse().TransformPoint(clipCentre))!=kOutside)
1356  {
1357  existsAfterClip=true;
1358  pMin=pVoxelLimit.GetMinExtent(pAxis);
1359  pMax=pVoxelLimit.GetMaxExtent(pAxis);
1360  }
1361  }
1362  delete vertices;
1363  return existsAfterClip;
1364  }
1365 }
1366 
1367 // --------------------------------------------------------------------
1368 
1371 {
1372  // Create a List containing the transformed vertices
1373  // Ordering [0-3] -fDz cross section
1374  // [4-7] +fDz cross section such that [0] is below [4],
1375  // [1] below [5] etc.
1376  // Note: caller has deletion responsibility
1377 
1378  G4ThreeVector Min = GetMinimumBBox();
1379  G4ThreeVector Max = GetMaximumBBox();
1380 
1381  G4ThreeVectorList *vertices;
1382  vertices=new G4ThreeVectorList();
1383 
1384  if (vertices)
1385  {
1386  vertices->reserve(8);
1387  G4ThreeVector vertex0(Min.x(),Min.y(),Min.z());
1388  G4ThreeVector vertex1(Max.x(),Min.y(),Min.z());
1389  G4ThreeVector vertex2(Max.x(),Max.y(),Min.z());
1390  G4ThreeVector vertex3(Min.x(),Max.y(),Min.z());
1391  G4ThreeVector vertex4(Min.x(),Min.y(),Max.z());
1392  G4ThreeVector vertex5(Max.x(),Min.y(),Max.z());
1393  G4ThreeVector vertex6(Max.x(),Max.y(),Max.z());
1394  G4ThreeVector vertex7(Min.x(),Max.y(),Max.z());
1395 
1396  vertices->push_back(pTransform.TransformPoint(vertex0));
1397  vertices->push_back(pTransform.TransformPoint(vertex1));
1398  vertices->push_back(pTransform.TransformPoint(vertex2));
1399  vertices->push_back(pTransform.TransformPoint(vertex3));
1400  vertices->push_back(pTransform.TransformPoint(vertex4));
1401  vertices->push_back(pTransform.TransformPoint(vertex5));
1402  vertices->push_back(pTransform.TransformPoint(vertex6));
1403  vertices->push_back(pTransform.TransformPoint(vertex7));
1404  }
1405  else
1406  {
1407  G4Exception("G4GenericTrap::CreateRotatedVertices()", "FatalError",
1408  FatalException, "Out of memory - Cannot allocate vertices!");
1409  }
1410  return vertices;
1411 }
1412 
1413 // --------------------------------------------------------------------
1414 
1416 {
1417  return G4String("G4GenericTrap");
1418 }
1419 
1420 // --------------------------------------------------------------------
1421 
1423 {
1424  return new G4GenericTrap(*this);
1425 }
1426 
1427 // --------------------------------------------------------------------
1428 
1429 std::ostream& G4GenericTrap::StreamInfo(std::ostream& os) const
1430 {
1431  G4int oldprc = os.precision(16);
1432  os << "-----------------------------------------------------------\n"
1433  << " *** Dump for solid - " << GetName() << " *** \n"
1434  << " =================================================== \n"
1435  << " Solid geometry type: " << GetEntityType() << G4endl
1436  << " half length Z: " << fDz/mm << " mm \n"
1437  << " list of vertices:\n";
1438 
1439  for ( G4int i=0; i<fgkNofVertices; ++i )
1440  {
1441  os << std::setw(5) << "#" << i
1442  << " vx = " << fVertices[i].x()/mm << " mm"
1443  << " vy = " << fVertices[i].y()/mm << " mm" << G4endl;
1444  }
1445  os.precision(oldprc);
1446 
1447  return os;
1448 }
1449 
1450 // --------------------------------------------------------------------
1451 
1453 {
1454 
1455 #ifdef G4TESS_TEST
1456  if ( fTessellatedSolid )
1457  {
1459  }
1460 #endif
1461 
1462  G4ThreeVector point;
1463  G4TwoVector u,v,w;
1464  G4double rand,area,chose,cf,lambda0,lambda1,alfa,beta,zp;
1465  G4int ipl,j;
1466 
1467  std::vector<G4ThreeVector> vertices;
1468  for (G4int i=0; i<4;i++)
1469  {
1470  vertices.push_back(G4ThreeVector(fVertices[i].x(),fVertices[i].y(),-fDz));
1471  }
1472  for (G4int i=4; i<8;i++)
1473  {
1474  vertices.push_back(G4ThreeVector(fVertices[i].x(),fVertices[i].y(),fDz));
1475  }
1476 
1477  // Surface Area of Planes(only estimation for twisted)
1478  //
1479  G4double Surface0=GetFaceSurfaceArea(vertices[0],vertices[1],
1480  vertices[2],vertices[3]);//-fDz plane
1481  G4double Surface1=GetFaceSurfaceArea(vertices[0],vertices[1],
1482  vertices[5],vertices[4]);// Lat plane
1483  G4double Surface2=GetFaceSurfaceArea(vertices[3],vertices[0],
1484  vertices[4],vertices[7]);// Lat plane
1485  G4double Surface3=GetFaceSurfaceArea(vertices[2],vertices[3],
1486  vertices[7],vertices[6]);// Lat plane
1487  G4double Surface4=GetFaceSurfaceArea(vertices[2],vertices[1],
1488  vertices[5],vertices[6]);// Lat plane
1489  G4double Surface5=GetFaceSurfaceArea(vertices[4],vertices[5],
1490  vertices[6],vertices[7]);// fDz plane
1491  rand = G4UniformRand();
1492  area = Surface0+Surface1+Surface2+Surface3+Surface4+Surface5;
1493  chose = rand*area;
1494 
1495  if ( ( chose < Surface0)
1496  || ( chose > (Surface0+Surface1+Surface2+Surface3+Surface4)) )
1497  { // fDz or -fDz Plane
1498  ipl = G4int(G4UniformRand()*4);
1499  j = (ipl+1)%4;
1500  if(chose < Surface0)
1501  {
1502  zp = -fDz;
1503  u = fVertices[ipl]; v = fVertices[j];
1504  w = fVertices[(ipl+3)%4];
1505  }
1506  else
1507  {
1508  zp = fDz;
1509  u = fVertices[ipl+4]; v = fVertices[j+4];
1510  w = fVertices[(ipl+3)%4+4];
1511  }
1512  alfa = G4UniformRand();
1513  beta = G4UniformRand();
1514  lambda1=alfa*beta;
1515  lambda0=alfa-lambda1;
1516  v = v-u;
1517  w = w-u;
1518  v = u+lambda0*v+lambda1*w;
1519  }
1520  else // Lateral Plane Twisted or Not
1521  {
1522  if (chose < Surface0+Surface1) { ipl=0; }
1523  else if (chose < Surface0+Surface1+Surface2) { ipl=1; }
1524  else if (chose < Surface0+Surface1+Surface2+Surface3) { ipl=2; }
1525  else { ipl=3; }
1526  j = (ipl+1)%4;
1527  zp = -fDz+G4UniformRand()*2*fDz;
1528  cf = 0.5*(fDz-zp)/fDz;
1529  u = fVertices[ipl+4]+cf*( fVertices[ipl]-fVertices[ipl+4]);
1530  v = fVertices[j+4]+cf*(fVertices[j]-fVertices[j+4]);
1531  v = u+(v-u)*G4UniformRand();
1532  }
1533  point=G4ThreeVector(v.x(),v.y(),zp);
1534 
1535  return point;
1536 }
1537 
1538 // --------------------------------------------------------------------
1539 
1541 {
1542  if(fCubicVolume != 0.) {;}
1544  return fCubicVolume;
1545 }
1546 
1547 // --------------------------------------------------------------------
1548 
1550 {
1551  if(fSurfaceArea != 0.) {;}
1552  else
1553  {
1554  std::vector<G4ThreeVector> vertices;
1555  for (G4int i=0; i<4;i++)
1556  {
1557  vertices.push_back(G4ThreeVector(fVertices[i].x(),fVertices[i].y(),-fDz));
1558  }
1559  for (G4int i=4; i<8;i++)
1560  {
1561  vertices.push_back(G4ThreeVector(fVertices[i].x(),fVertices[i].y(),fDz));
1562  }
1563 
1564  // Surface Area of Planes(only estimation for twisted)
1565  //
1566  G4double fSurface0=GetFaceSurfaceArea(vertices[0],vertices[1],
1567  vertices[2],vertices[3]);//-fDz plane
1568  G4double fSurface1=GetFaceSurfaceArea(vertices[0],vertices[1],
1569  vertices[5],vertices[4]);// Lat plane
1570  G4double fSurface2=GetFaceSurfaceArea(vertices[3],vertices[0],
1571  vertices[4],vertices[7]);// Lat plane
1572  G4double fSurface3=GetFaceSurfaceArea(vertices[2],vertices[3],
1573  vertices[7],vertices[6]);// Lat plane
1574  G4double fSurface4=GetFaceSurfaceArea(vertices[2],vertices[1],
1575  vertices[5],vertices[6]);// Lat plane
1576  G4double fSurface5=GetFaceSurfaceArea(vertices[4],vertices[5],
1577  vertices[6],vertices[7]);// fDz plane
1578 
1579  // Total Surface Area
1580  //
1581  if(!fIsTwisted)
1582  {
1583  fSurfaceArea = fSurface0+fSurface1+fSurface2
1584  + fSurface3+fSurface4+fSurface5;
1585  }
1586  else
1587  {
1589  }
1590  }
1591  return fSurfaceArea;
1592 }
1593 
1594 // --------------------------------------------------------------------
1595 
1597  const G4ThreeVector& p1,
1598  const G4ThreeVector& p2,
1599  const G4ThreeVector& p3) const
1600 {
1601  // Auxiliary method for Get Surface Area of Face
1602 
1603  G4double aOne, aTwo;
1604  G4ThreeVector t, u, v, w, Area, normal;
1605 
1606  t = p2 - p1;
1607  u = p0 - p1;
1608  v = p2 - p3;
1609  w = p0 - p3;
1610 
1611  Area = w.cross(v);
1612  aOne = 0.5*Area.mag();
1613 
1614  Area = t.cross(u);
1615  aTwo = 0.5*Area.mag();
1616 
1617  return aOne + aTwo;
1618 }
1619 
1620 // --------------------------------------------------------------------
1621 
1623 {
1624  // Computes tangents of twist angles (angles between projections on XY plane
1625  // of corresponding -dz +dz edges).
1626 
1627  G4bool twisted = false;
1628  G4double dx1, dy1, dx2, dy2;
1629  G4int nv = fgkNofVertices/2;
1630 
1631  for ( G4int i=0; i<4; i++ )
1632  {
1633  dx1 = fVertices[(i+1)%nv].x()-fVertices[i].x();
1634  dy1 = fVertices[(i+1)%nv].y()-fVertices[i].y();
1635  if ( (dx1 == 0) && (dy1 == 0) ) { continue; }
1636 
1637  dx2 = fVertices[nv+(i+1)%nv].x()-fVertices[nv+i].x();
1638  dy2 = fVertices[nv+(i+1)%nv].y()-fVertices[nv+i].y();
1639 
1640  if ( dx2 == 0 && dy2 == 0 ) { continue; }
1641  G4double twist_angle = std::fabs(dy1*dx2 - dx1*dy2);
1642  if ( twist_angle < fgkTolerance ) { continue; }
1643  twisted = true;
1644  SetTwistAngle(i,twist_angle);
1645 
1646  // Check on big angles, potentially navigation problem
1647 
1648  twist_angle = std::acos( (dx1*dx2 + dy1*dy2)
1649  / (std::sqrt(dx1*dx1+dy1*dy1)
1650  * std::sqrt(dx2*dx2+dy2*dy2)) );
1651 
1652  if ( std::fabs(twist_angle) > 0.5*pi+kCarTolerance )
1653  {
1654  std::ostringstream message;
1655  message << "Twisted Angle is bigger than 90 degrees - " << GetName()
1656  << G4endl
1657  << " Potential problem of malformed Solid !" << G4endl
1658  << " TwistANGLE = " << twist_angle
1659  << "*rad for lateral plane N= " << i;
1660  G4Exception("G4GenericTrap::ComputeIsTwisted()", "GeomSolids1002",
1661  JustWarning, message);
1662  }
1663  }
1664 
1665  return twisted;
1666 }
1667 
1668 // --------------------------------------------------------------------
1669 
1670 G4bool G4GenericTrap::CheckOrder(const std::vector<G4TwoVector>& vertices) const
1671 {
1672  // Test if the vertices are in a clockwise order, if not reorder them.
1673  // Also test if they're well defined without crossing opposite segments
1674 
1675  G4bool clockwise_order=true;
1676  G4double sum1 = 0.;
1677  G4double sum2 = 0.;
1678  G4int j;
1679 
1680  for (G4int i=0; i<4; i++)
1681  {
1682  j = (i+1)%4;
1683  sum1 += vertices[i].x()*vertices[j].y() - vertices[j].x()*vertices[i].y();
1684  sum2 += vertices[i+4].x()*vertices[j+4].y()
1685  - vertices[j+4].x()*vertices[i+4].y();
1686  }
1687  if (sum1*sum2 < -fgkTolerance)
1688  {
1689  std::ostringstream message;
1690  message << "Lower/upper faces defined with opposite clockwise - "
1691  << GetName();
1692  G4Exception("G4GenericTrap::CheckOrder()", "GeomSolids0002",
1693  FatalException, message);
1694  }
1695 
1696  if ((sum1 > 0.)||(sum2 > 0.))
1697  {
1698  std::ostringstream message;
1699  message << "Vertices must be defined in clockwise XY planes - "
1700  << GetName();
1701  G4Exception("G4GenericTrap::CheckOrder()", "GeomSolids1001",
1702  JustWarning,message, "Re-ordering...");
1703  clockwise_order = false;
1704  }
1705 
1706  // Check for illegal crossings
1707  //
1708  G4bool illegal_cross = false;
1709  illegal_cross = IsSegCrossingZ(vertices[0],vertices[4],
1710  vertices[1],vertices[5]);
1711 
1712  if (!illegal_cross)
1713  {
1714  illegal_cross = IsSegCrossingZ(vertices[2],vertices[6],
1715  vertices[3],vertices[7]);
1716  }
1717  // +/- dZ planes
1718  if (!illegal_cross)
1719  {
1720  illegal_cross = IsSegCrossing(vertices[0],vertices[1],
1721  vertices[2],vertices[3]);
1722  }
1723  if (!illegal_cross)
1724  {
1725  illegal_cross = IsSegCrossing(vertices[0],vertices[3],
1726  vertices[1],vertices[2]);
1727  }
1728  if (!illegal_cross)
1729  {
1730  illegal_cross = IsSegCrossing(vertices[4],vertices[5],
1731  vertices[6],vertices[7]);
1732  }
1733  if (!illegal_cross)
1734  {
1735  illegal_cross = IsSegCrossing(vertices[4],vertices[7],
1736  vertices[5],vertices[6]);
1737  }
1738 
1739  if (illegal_cross)
1740  {
1741  std::ostringstream message;
1742  message << "Malformed polygone with opposite sides - " << GetName();
1743  G4Exception("G4GenericTrap::CheckOrderAndSetup()",
1744  "GeomSolids0002", FatalException, message);
1745  }
1746  return clockwise_order;
1747 }
1748 
1749 // --------------------------------------------------------------------
1750 
1751 void G4GenericTrap::ReorderVertices(std::vector<G4ThreeVector>& vertices) const
1752 {
1753  // Reorder the vector of vertices
1754 
1755  std::vector<G4ThreeVector> oldVertices(vertices);
1756 
1757  for ( G4int i=0; i < G4int(oldVertices.size()); ++i )
1758  {
1759  vertices[i] = oldVertices[oldVertices.size()-1-i];
1760  }
1761 }
1762 
1763 // --------------------------------------------------------------------
1764 
1765 G4bool
1767  const G4TwoVector& c, const G4TwoVector& d) const
1768 {
1769  // Check if segments [A,B] and [C,D] are crossing
1770 
1771  G4bool stand1 = false;
1772  G4bool stand2 = false;
1773  G4double dx1,dx2,xm=0.,ym=0.,a1=0.,a2=0.,b1=0.,b2=0.;
1774  dx1=(b-a).x();
1775  dx2=(d-c).x();
1776 
1777  if( std::fabs(dx1) < fgkTolerance ) { stand1 = true; }
1778  if( std::fabs(dx2) < fgkTolerance ) { stand2 = true; }
1779  if (!stand1)
1780  {
1781  a1 = (b.x()*a.y()-a.x()*b.y())/dx1;
1782  b1 = (b-a).y()/dx1;
1783  }
1784  if (!stand2)
1785  {
1786  a2 = (d.x()*c.y()-c.x()*d.y())/dx2;
1787  b2 = (d-c).y()/dx2;
1788  }
1789  if (stand1 && stand2)
1790  {
1791  // Segments parallel and vertical
1792  //
1793  if (std::fabs(a.x()-c.x())<fgkTolerance)
1794  {
1795  // Check if segments are overlapping
1796  //
1797  if ( ((c.y()-a.y())*(c.y()-b.y())<-fgkTolerance)
1798  || ((d.y()-a.y())*(d.y()-b.y())<-fgkTolerance)
1799  || ((a.y()-c.y())*(a.y()-d.y())<-fgkTolerance)
1800  || ((b.y()-c.y())*(b.y()-d.y())<-fgkTolerance) ) { return true; }
1801 
1802  return false;
1803  }
1804  // Different x values
1805  //
1806  return false;
1807  }
1808 
1809  if (stand1) // First segment vertical
1810  {
1811  xm = a.x();
1812  ym = a2+b2*xm;
1813  }
1814  else
1815  {
1816  if (stand2) // Second segment vertical
1817  {
1818  xm = c.x();
1819  ym = a1+b1*xm;
1820  }
1821  else // Normal crossing
1822  {
1823  if (std::fabs(b1-b2) < fgkTolerance)
1824  {
1825  // Parallel segments, are they aligned
1826  //
1827  if (std::fabs(c.y()-(a1+b1*c.x())) > fgkTolerance) { return false; }
1828 
1829  // Aligned segments, are they overlapping
1830  //
1831  if ( ((c.x()-a.x())*(c.x()-b.x())<-fgkTolerance)
1832  || ((d.x()-a.x())*(d.x()-b.x())<-fgkTolerance)
1833  || ((a.x()-c.x())*(a.x()-d.x())<-fgkTolerance)
1834  || ((b.x()-c.x())*(b.x()-d.x())<-fgkTolerance) ) { return true; }
1835 
1836  return false;
1837  }
1838  xm = (a1-a2)/(b2-b1);
1839  ym = (a1*b2-a2*b1)/(b2-b1);
1840  }
1841  }
1842 
1843  // Check if crossing point is both between A,B and C,D
1844  //
1845  G4double check = (xm-a.x())*(xm-b.x())+(ym-a.y())*(ym-b.y());
1846  if (check > -fgkTolerance) { return false; }
1847  check = (xm-c.x())*(xm-d.x())+(ym-c.y())*(ym-d.y());
1848  if (check > -fgkTolerance) { return false; }
1849 
1850  return true;
1851 }
1852 
1853 // --------------------------------------------------------------------
1854 
1855 G4bool
1857  const G4TwoVector& c, const G4TwoVector& d) const
1858 {
1859  // Check if segments [A,B] and [C,D] are crossing when
1860  // A and C are on -dZ and B and D are on +dZ
1861 
1862  // Calculate the Intersection point between two lines in 3D
1863  //
1864  G4ThreeVector temp1,temp2;
1865  G4ThreeVector v1,v2,p1,p2,p3,p4,dv;
1866  G4double q,det;
1867  p1=G4ThreeVector(a.x(),a.y(),-fDz);
1868  p2=G4ThreeVector(c.x(),c.y(),-fDz);
1869  p3=G4ThreeVector(b.x(),b.y(),fDz);
1870  p4=G4ThreeVector(d.x(),d.y(),fDz);
1871  v1=p3-p1;
1872  v2=p4-p2;
1873  dv=p2-p1;
1874 
1875  // In case of Collapsed Vertices No crossing
1876  //
1877  if( (std::fabs(dv.x()) < kCarTolerance )&&
1878  (std::fabs(dv.y()) < kCarTolerance ) ) { return false; }
1879 
1880  if( (std::fabs((p4-p3).x()) < kCarTolerance )&&
1881  (std::fabs((p4-p3).y()) < kCarTolerance ) ) { return false; }
1882 
1883  // First estimate if Intersection is possible( if det is 0)
1884  //
1885  det = dv.x()*v1.y()*v2.z()+dv.y()*v1.z()*v2.x()
1886  - dv.x()*v1.z()*v2.y()-dv.y()*v1.x()*v2.z();
1887 
1888  if (std::fabs(det)<kCarTolerance) //Intersection
1889  {
1890  temp1 = v1.cross(v2);
1891  temp2 = (p2-p1).cross(v2);
1892  if (temp1.dot(temp2) < 0) { return false; } // intersection negative
1893  q = temp1.mag();
1894 
1895  if ( q < kCarTolerance ) { return false; } // parallel lines
1896  q = ((dv).cross(v2)).mag()/q;
1897 
1898  if(q < 1.-kCarTolerance) { return true; }
1899  }
1900  return false;
1901 }
1902 
1903 // --------------------------------------------------------------------
1904 
1905 G4VFacet*
1906 G4GenericTrap::MakeDownFacet(const std::vector<G4ThreeVector>& fromVertices,
1907  G4int ind1, G4int ind2, G4int ind3) const
1908 {
1909  // Create a triangular facet from the polygon points given by indices
1910  // forming the down side ( the normal goes in -z)
1911  // Do not create facet if 2 vertices are the same
1912 
1913  if ( (fromVertices[ind1] == fromVertices[ind2]) ||
1914  (fromVertices[ind2] == fromVertices[ind3]) ||
1915  (fromVertices[ind1] == fromVertices[ind3]) ) { return 0; }
1916 
1917  std::vector<G4ThreeVector> vertices;
1918  vertices.push_back(fromVertices[ind1]);
1919  vertices.push_back(fromVertices[ind2]);
1920  vertices.push_back(fromVertices[ind3]);
1921 
1922  // first vertex most left
1923  //
1924  G4ThreeVector cross=(vertices[1]-vertices[0]).cross(vertices[2]-vertices[1]);
1925 
1926  if ( cross.z() > 0.0 )
1927  {
1928  // Should not happen, as vertices should have been reordered at this stage
1929 
1930  std::ostringstream message;
1931  message << "Vertices in wrong order - " << GetName();
1932  G4Exception("G4GenericTrap::MakeDownFacet", "GeomSolids0002",
1933  FatalException, message);
1934  }
1935 
1936  return new G4TriangularFacet(vertices[0], vertices[1], vertices[2], ABSOLUTE);
1937 }
1938 
1939 // --------------------------------------------------------------------
1940 
1941 G4VFacet*
1942 G4GenericTrap::MakeUpFacet(const std::vector<G4ThreeVector>& fromVertices,
1943  G4int ind1, G4int ind2, G4int ind3) const
1944 {
1945  // Create a triangular facet from the polygon points given by indices
1946  // forming the upper side ( z>0 )
1947 
1948  // Do not create facet if 2 vertices are the same
1949  //
1950  if ( (fromVertices[ind1] == fromVertices[ind2]) ||
1951  (fromVertices[ind2] == fromVertices[ind3]) ||
1952  (fromVertices[ind1] == fromVertices[ind3]) ) { return 0; }
1953 
1954  std::vector<G4ThreeVector> vertices;
1955  vertices.push_back(fromVertices[ind1]);
1956  vertices.push_back(fromVertices[ind2]);
1957  vertices.push_back(fromVertices[ind3]);
1958 
1959  // First vertex most left
1960  //
1961  G4ThreeVector cross=(vertices[1]-vertices[0]).cross(vertices[2]-vertices[1]);
1962 
1963  if ( cross.z() < 0.0 )
1964  {
1965  // Should not happen, as vertices should have been reordered at this stage
1966 
1967  std::ostringstream message;
1968  message << "Vertices in wrong order - " << GetName();
1969  G4Exception("G4GenericTrap::MakeUpFacet", "GeomSolids0002",
1970  FatalException, message);
1971  }
1972 
1973  return new G4TriangularFacet(vertices[0], vertices[1], vertices[2], ABSOLUTE);
1974 }
1975 
1976 // --------------------------------------------------------------------
1977 
1978 G4VFacet*
1980  const G4ThreeVector& downVertex1,
1981  const G4ThreeVector& upVertex1,
1982  const G4ThreeVector& upVertex0) const
1983 {
1984  // Creates a triangular facet from the polygon points given by indices
1985  // forming the upper side ( z>0 )
1986 
1987  if ( (downVertex0 == downVertex1) && (upVertex0 == upVertex1) )
1988  {
1989  return 0;
1990  }
1991 
1992  if ( downVertex0 == downVertex1 )
1993  {
1994  return new G4TriangularFacet(downVertex0, upVertex1, upVertex0, ABSOLUTE);
1995  }
1996 
1997  if ( upVertex0 == upVertex1 )
1998  {
1999  return new G4TriangularFacet(downVertex0, downVertex1, upVertex0, ABSOLUTE);
2000  }
2001 
2002  return new G4QuadrangularFacet(downVertex0, downVertex1,
2003  upVertex1, upVertex0, ABSOLUTE);
2004 }
2005 
2006 // --------------------------------------------------------------------
2007 
2009 {
2010  // 3D vertices
2011  //
2012  G4int nv = fgkNofVertices/2;
2013  std::vector<G4ThreeVector> downVertices;
2014  for ( G4int i=0; i<nv; i++ )
2015  {
2016  downVertices.push_back(G4ThreeVector(fVertices[i].x(),
2017  fVertices[i].y(), -fDz));
2018  }
2019 
2020  std::vector<G4ThreeVector> upVertices;
2021  for ( G4int i=nv; i<2*nv; i++ )
2022  {
2023  upVertices.push_back(G4ThreeVector(fVertices[i].x(),
2024  fVertices[i].y(), fDz));
2025  }
2026 
2027  // Reorder vertices if they are not ordered anti-clock wise
2028  //
2029  G4ThreeVector cross
2030  = (downVertices[1]-downVertices[0]).cross(downVertices[2]-downVertices[1]);
2031  G4ThreeVector cross1
2032  = (upVertices[1]-upVertices[0]).cross(upVertices[2]-upVertices[1]);
2033  if ( (cross.z() > 0.0) || (cross1.z() > 0.0) )
2034  {
2035  ReorderVertices(downVertices);
2036  ReorderVertices(upVertices);
2037  }
2038 
2039  G4TessellatedSolid* tessellatedSolid = new G4TessellatedSolid(GetName());
2040 
2041  G4VFacet* facet = 0;
2042  facet = MakeDownFacet(downVertices, 0, 1, 2);
2043  if (facet) { tessellatedSolid->AddFacet( facet ); }
2044  facet = MakeDownFacet(downVertices, 0, 2, 3);
2045  if (facet) { tessellatedSolid->AddFacet( facet ); }
2046  facet = MakeUpFacet(upVertices, 0, 2, 1);
2047  if (facet) { tessellatedSolid->AddFacet( facet ); }
2048  facet = MakeUpFacet(upVertices, 0, 3, 2);
2049  if (facet) { tessellatedSolid->AddFacet( facet ); }
2050 
2051  // The quadrangular sides
2052  //
2053  for ( G4int i = 0; i < nv; ++i )
2054  {
2055  G4int j = (i+1) % nv;
2056  facet = MakeSideFacet(downVertices[j], downVertices[i],
2057  upVertices[i], upVertices[j]);
2058 
2059  if ( facet ) { tessellatedSolid->AddFacet( facet ); }
2060  }
2061 
2062  tessellatedSolid->SetSolidClosed(true);
2063 
2064  return tessellatedSolid;
2065 }
2066 
2067 // --------------------------------------------------------------------
2068 
2070 {
2071  // Computes bounding box for a shape.
2072 
2073  G4double minX, maxX, minY, maxY;
2074  minX = maxX = fVertices[0].x();
2075  minY = maxY = fVertices[0].y();
2076 
2077  for (G4int i=1; i< fgkNofVertices; i++)
2078  {
2079  if (minX>fVertices[i].x()) { minX=fVertices[i].x(); }
2080  if (maxX<fVertices[i].x()) { maxX=fVertices[i].x(); }
2081  if (minY>fVertices[i].y()) { minY=fVertices[i].y(); }
2082  if (maxY<fVertices[i].y()) { maxY=fVertices[i].y(); }
2083  }
2084  fMinBBoxVector = G4ThreeVector(minX,minY,-fDz);
2085  fMaxBBoxVector = G4ThreeVector(maxX,maxY, fDz);
2086 }
2087 
2088 // --------------------------------------------------------------------
2089 
2091 {
2092 
2093 #ifdef G4TESS_TEST
2094  if ( fTessellatedSolid )
2095  {
2096  return fTessellatedSolid->GetPolyhedron();
2097  }
2098 #endif
2099 
2100  if ( (!fpPolyhedron)
2102  fpPolyhedron->GetNumberOfRotationSteps()) )
2103  {
2104  delete fpPolyhedron;
2106  }
2107  return fpPolyhedron;
2108 }
2109 
2110 // --------------------------------------------------------------------
2111 
2113 {
2114 
2115 #ifdef G4TESS_TEST
2116  if ( fTessellatedSolid )
2117  {
2118  return fTessellatedSolid->DescribeYourselfTo(scene);
2119  }
2120 #endif
2121 
2122  scene.AddSolid(*this);
2123 }
2124 
2125 // --------------------------------------------------------------------
2126 
2128 {
2129  // Computes bounding vectors for the shape
2130 
2131 #ifdef G4TESS_TEST
2132  if ( fTessellatedSolid )
2133  {
2134  return fTessellatedSolid->GetExtent();
2135  }
2136 #endif
2137 
2138  G4double Dx,Dy;
2139  G4ThreeVector minVec = GetMinimumBBox();
2140  G4ThreeVector maxVec = GetMaximumBBox();
2141  Dx = 0.5*(maxVec.x()- minVec.x());
2142  Dy = 0.5*(maxVec.y()- minVec.y());
2143 
2144  return G4VisExtent (-Dx, Dx, -Dy, Dy, -fDz, fDz);
2145 }
2146 
2147 // --------------------------------------------------------------------
2148 
2150 {
2151 
2152 #ifdef G4TESS_TEST
2153  if ( fTessellatedSolid )
2154  {
2156  }
2157 #endif
2158 
2159  // Approximation of Twisted Side
2160  // Construct extra Points, if Twisted Side
2161  //
2162  G4PolyhedronArbitrary* polyhedron;
2163  size_t nVertices, nFacets;
2164 
2165  G4int subdivisions=0;
2166  G4int i;
2167  if(fIsTwisted)
2168  {
2169  if ( GetVisSubdivisions()!= 0 )
2170  {
2171  subdivisions=GetVisSubdivisions();
2172  }
2173  else
2174  {
2175  // Estimation of Number of Subdivisions for smooth visualisation
2176  //
2177  G4double maxTwist=0.;
2178  for(i=0; i<4; i++)
2179  {
2180  if(GetTwistAngle(i)>maxTwist) { maxTwist=GetTwistAngle(i); }
2181  }
2182 
2183  // Computes bounding vectors for the shape
2184  //
2185  G4double Dx,Dy;
2186  G4ThreeVector minVec = GetMinimumBBox();
2187  G4ThreeVector maxVec = GetMaximumBBox();
2188  Dx = 0.5*(maxVec.x()- minVec.y());
2189  Dy = 0.5*(maxVec.y()- minVec.y());
2190  if (Dy > Dx) { Dx=Dy; }
2191 
2192  subdivisions=8*G4int(maxTwist/(Dx*Dx*Dx)*fDz);
2193  if (subdivisions<4) { subdivisions=4; }
2194  if (subdivisions>30) { subdivisions=30; }
2195  }
2196  }
2197  G4int sub4=4*subdivisions;
2198  nVertices = 8+subdivisions*4;
2199  nFacets = 6+subdivisions*4;
2200  G4double cf=1./(subdivisions+1);
2201  polyhedron = new G4PolyhedronArbitrary (nVertices, nFacets);
2202 
2203  // Add Vertex
2204  //
2205  for (i=0;i<4;i++)
2206  {
2207  polyhedron->AddVertex(G4ThreeVector(fVertices[i].x(),
2208  fVertices[i].y(),-fDz));
2209  }
2210  for( i=0;i<subdivisions;i++)
2211  {
2212  for(G4int j=0;j<4;j++)
2213  {
2214  G4TwoVector u=fVertices[j]+cf*(i+1)*( fVertices[j+4]-fVertices[j]);
2215  polyhedron->AddVertex(G4ThreeVector(u.x(),u.y(),-fDz+cf*2*fDz*(i+1)));
2216  }
2217  }
2218  for (i=4;i<8;i++)
2219  {
2220  polyhedron->AddVertex(G4ThreeVector(fVertices[i].x(),
2221  fVertices[i].y(),fDz));
2222  }
2223 
2224  // Add Facets
2225  //
2226  polyhedron->AddFacet(1,4,3,2); //Z-plane
2227  for (i=0;i<subdivisions+1;i++)
2228  {
2229  G4int is=i*4;
2230  polyhedron->AddFacet(5+is,8+is,4+is,1+is);
2231  polyhedron->AddFacet(8+is,7+is,3+is,4+is);
2232  polyhedron->AddFacet(7+is,6+is,2+is,3+is);
2233  polyhedron->AddFacet(6+is,5+is,1+is,2+is);
2234  }
2235  polyhedron->AddFacet(5+sub4,6+sub4,7+sub4,8+sub4); //Z-plane
2236 
2237  polyhedron->SetReferences();
2238  polyhedron->InvertFacets();
2239 
2240  return (G4Polyhedron*) polyhedron;
2241 }
2242 
2243 // --------------------------------------------------------------------
G4String GetName() const
static const G4int fgkNofVertices
void ClipCrossSection(G4ThreeVectorList *pVertices, const G4int pSectionIndex, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
Definition: G4VSolid.cc:347
G4Polyhedron * GetPolyhedron() const
G4int GetVisSubdivisions() const
void SetTwistAngle(G4int index, G4double twist)
void SetSolidClosed(const G4bool t)
G4bool IsSegCrossingZ(const G4TwoVector &a, const G4TwoVector &b, const G4TwoVector &c, const G4TwoVector &d) const
G4GenericTrap(const G4String &name, G4double halfZ, const std::vector< G4TwoVector > &vertices)
static const G4double kInfinity
Definition: geomdefs.hh:42
G4double GetMinYExtent() const
CLHEP::Hep3Vector G4ThreeVector
G4VisExtent GetExtent() const
G4double fTwist[4]
G4TessellatedSolid * CreateTessellatedSolid() const
virtual void DescribeYourselfTo(G4VGraphicsScene &scene) const
G4AffineTransform Inverse() const
G4Polyhedron * fpPolyhedron
G4double DistToPlane(const G4ThreeVector &p, const G4ThreeVector &v, const G4int ipl) const
G4bool IsYLimited() const
G4VFacet * MakeSideFacet(const G4ThreeVector &downVertex0, const G4ThreeVector &downVertex1, const G4ThreeVector &upVertex1, const G4ThreeVector &upVertex0) const
virtual G4VisExtent GetExtent() const
G4String name
Definition: TRTMaterials.hh:40
static const G4double a1
G4int fVisSubdivisions
G4VSolid * Clone() const
const G4double pi
virtual G4double GetCubicVolume()
Definition: G4VSolid.cc:188
G4double GetFaceSurfaceArea(const G4ThreeVector &p0, const G4ThreeVector &p1, const G4ThreeVector &p2, const G4ThreeVector &p3) const
G4bool IsRotated() const
G4ThreeVector NormalToPlane(const G4ThreeVector &p, const G4int ipl) const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const
G4GeometryType GetEntityType() const
G4ThreeVector NetTranslation() const
G4bool IsXLimited() const
G4double a
Definition: TRTMaterials.hh:39
G4VFacet * MakeUpFacet(const std::vector< G4ThreeVector > &fromVertices, G4int ind1, G4int ind2, G4int ind3) const
virtual void AddSolid(const G4Box &)=0
int G4int
Definition: G4Types.hh:78
G4bool ComputeIsTwisted()
G4double SafetyToFace(const G4ThreeVector &p, const G4int iseg) const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
G4double GetSurfaceArea()
void DumpInfo() const
G4ThreeVector GetMaximumBBox() const
static double normal(HepRandomEngine *eptr)
Definition: RandPoisson.cc:77
G4double GetMaxXExtent() const
G4double GetMinZExtent() const
G4TessellatedSolid * fTessellatedSolid
#define G4UniformRand()
Definition: Randomize.hh:87
G4ThreeVector GetPointOnSurface() const
G4VFacet * MakeDownFacet(const std::vector< G4ThreeVector > &fromVertices, G4int ind1, G4int ind2, G4int ind3) const
virtual G4double DistanceToOut(const G4ThreeVector &p) const
G4GenericTrap & operator=(const G4GenericTrap &rhs)
virtual G4Polyhedron * CreatePolyhedron() const
virtual EInside Inside(const G4ThreeVector &p) const
bool G4bool
Definition: G4Types.hh:79
std::ostream & StreamInfo(std::ostream &os) const
G4bool AddFacet(G4VFacet *aFacet)
G4double GetTwistAngle(G4int index) const
G4double DistToTriangle(const G4ThreeVector &p, const G4ThreeVector &v, const G4int ipl) const
std::vector< G4ThreeVector > G4ThreeVectorList
Definition: G4VSolid.hh:79
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const
static const G4double b2
G4double fSurfaceArea
const G4int n
G4double GetCubicVolume()
virtual G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
std::vector< G4TwoVector > fVertices
void AddVertex(const G4ThreeVector &v)
EInside Inside(const G4ThreeVector &p) const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
G4ThreeVectorList * CreateRotatedVertices(const G4AffineTransform &pTransform) const
G4double fCubicVolume
virtual G4Polyhedron * GetPolyhedron() const
G4ThreeVector GetMinimumBBox() const
G4double GetMinXExtent() const
G4ThreeVector TransformPoint(const G4ThreeVector &vec) const
G4Polyhedron * CreatePolyhedron() const
G4double GetMaxZExtent() const
void ReorderVertices(std::vector< G4ThreeVector > &vertices) const
EInside
Definition: geomdefs.hh:58
EInside InsidePolygone(const G4ThreeVector &p, const std::vector< G4TwoVector > &poly) const
EAxis
Definition: geomdefs.hh:54
void AddFacet(const G4int iv1, const G4int iv2, const G4int iv3, const G4int iv4=0)
static const G4double b1
CLHEP::Hep2Vector G4TwoVector
Definition: G4TwoVector.hh:42
#define G4endl
Definition: G4ios.hh:61
G4double GetMaxYExtent() const
G4VSolid & operator=(const G4VSolid &rhs)
Definition: G4VSolid.cc:110
G4double kCarTolerance
Definition: G4VSolid.hh:305
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
G4double halfCarTolerance
G4bool IsSegCrossing(const G4TwoVector &a, const G4TwoVector &b, const G4TwoVector &c, const G4TwoVector &d) const
double G4double
Definition: G4Types.hh:76
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const
G4bool CheckOrder(const std::vector< G4TwoVector > &vertices) const
G4double GetMaxExtent(const EAxis pAxis) const
virtual G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const
G4bool IsZLimited() const
static const double mm
Definition: G4SIunits.hh:102
virtual G4double GetSurfaceArea()
Definition: G4VSolid.cc:250
virtual G4ThreeVector GetPointOnSurface() const
G4ThreeVector fMinBBoxVector
virtual G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const
static const G4double fgkTolerance
void ClipBetweenSections(G4ThreeVectorList *pVertices, const G4int pSectionIndex, const G4VoxelLimits &pVoxelLimit, const EAxis pAxis, G4double &pMin, G4double &pMax) const
Definition: G4VSolid.cc:378
G4double GetMinExtent(const EAxis pAxis) const
G4ThreeVector fMaxBBoxVector
static const G4double a2
void DescribeYourselfTo(G4VGraphicsScene &scene) const