source: trunk/source/geometry/solids/CSG/src/G4Para.cc @ 1199

Last change on this file since 1199 was 1058, checked in by garnier, 15 years ago

file release beta

File size: 36.9 KB
Line 
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: G4Para.cc,v 1.39 2006/10/19 15:33:37 gcosmo Exp $
28// GEANT4 tag $Name: geant4-09-02-ref-02 $
29//
30// class G4Para
31//
32// Implementation for G4Para class
33//
34// History:
35//
36// 23.10.05 V.Grichine: bug fixed in DistanceToOut(p,v,...) for the v.x()<0 case
37// 28.04.05 V.Grichine: new SurfaceNormal according to J. Apostolakis proposal
38// 30.11.04 V.Grichine: modifications in SurfaceNormal for edges/vertices and
39//                      in constructor with vertices
40// 14.02.02 V.Grichine: bug fixed in Inside according to proposal of D.Wright
41// 18.11.99 V.Grichine: kUndef was added to ESide
42// 31.10.96 V.Grichine: Modifications according G4Box/Tubs before to commit
43// 21.03.95 P.Kent: Modified for `tolerant' geom
44//
45////////////////////////////////////////////////////////////////////////////
46
47#include "G4Para.hh"
48
49#include "G4VoxelLimits.hh"
50#include "G4AffineTransform.hh"
51#include "Randomize.hh"
52
53#include "G4VPVParameterisation.hh"
54
55#include "G4VGraphicsScene.hh"
56#include "G4Polyhedron.hh"
57#include "G4NURBS.hh"
58#include "G4NURBSbox.hh"
59
60using namespace CLHEP;
61
62// Private enum: Not for external use
63   
64enum ESide {kUndef,kPX,kMX,kPY,kMY,kPZ,kMZ};
65
66// used internally for normal routine
67
68enum ENSide {kNZ,kNX,kNY};
69
70/////////////////////////////////////////////////////////////////////
71//
72// Constructor - check and set half-widths
73
74void G4Para::SetAllParameters( G4double pDx, G4double pDy, G4double pDz, 
75                               G4double pAlpha, G4double pTheta, G4double pPhi )
76{
77  if ( pDx > 0 && pDy > 0 && pDz > 0 )
78  {
79    fDx         = pDx;
80    fDy         = pDy;
81    fDz         = pDz;
82    fTalpha     = std::tan(pAlpha);
83    fTthetaCphi = std::tan(pTheta)*std::cos(pPhi);
84    fTthetaSphi = std::tan(pTheta)*std::sin(pPhi);
85  }
86  else
87  {
88    G4cerr << "ERROR - G4Para()::SetAllParameters(): " << GetName() << G4endl
89           << "        Invalid dimensions ! - "
90           << pDx << ", " << pDy << ", " << pDz << G4endl;
91    G4Exception("G4Para::SetAllParameters()", "InvalidSetup",
92                FatalException, "Invalid Length Parameters.");
93  }
94  fCubicVolume = 0.;
95  fSurfaceArea = 0.;
96  fpPolyhedron = 0;
97}
98
99///////////////////////////////////////////////////////////////////////////
100//
101
102G4Para::G4Para(const G4String& pName,
103                     G4double pDx, G4double pDy, G4double pDz,
104                     G4double pAlpha, G4double pTheta, G4double pPhi)
105  : G4CSGSolid(pName)
106{
107  if (pDx>0&&pDy>0&&pDz>0)
108  {
109    SetAllParameters( pDx, pDy, pDz, pAlpha, pTheta, pPhi);
110  }
111  else
112  {
113    G4cerr << "ERROR - G4Para()::G4Para(): " << GetName() << G4endl
114           << "        Invalid dimensions ! - "
115           << pDx << ", " << pDy << ", " << pDz << G4endl;
116    G4Exception("G4Para::G4Para()", "InvalidSetup",
117                FatalException, "Invalid Length Parameters.");
118  }
119}
120
121////////////////////////////////////////////////////////////////////////
122//
123// Constructor - Design of trapezoid based on 8 G4ThreeVector parameters,
124// which are its vertices. Checking of planarity with preparation of
125// fPlanes[] and than calculation of other members
126
127G4Para::G4Para( const G4String& pName,
128                const G4ThreeVector pt[8] )
129  : G4CSGSolid(pName)
130{
131  if ( pt[0].z()<0 && pt[0].z()==pt[1].z() && pt[0].z()==pt[2].z() &&
132       pt[0].z()==pt[3].z() && pt[4].z()>0 && pt[4].z()==pt[5].z() &&
133       pt[4].z()==pt[6].z() && pt[4].z()==pt[7].z()           &&
134       (pt[0].z()+pt[4].z())==0                               &&
135       pt[0].y()==pt[1].y() && pt[2].y()==pt[3].y()           &&
136       pt[4].y()==pt[5].y() && pt[6].y()==pt[7].y()           &&
137       ( pt[0].y() + pt[2].y() + pt[4].y() + pt[6].y() ) == 0 && 
138       ( pt[0].x() + pt[1].x() + pt[4].x() + pt[5].x() ) == 0)
139  {
140    fDz = (pt[7]).z() ;
141
142    fDy = ((pt[2]).y()-(pt[1]).y())*0.5 ;
143    fDx = ((pt[1]).x()-(pt[0]).x())*0.5 ;
144    fDx = ((pt[3]).x()-(pt[2]).x())*0.5 ;
145    fTalpha = ((pt[2]).x()+(pt[3]).x()-(pt[1]).x()-(pt[0]).x())*0.25/fDy ;
146
147    // fDy = ((pt[6]).y()-(pt[5]).y())*0.5 ;
148    // fDx = ((pt[5]).x()-(pt[4]).x())*0.5 ;
149    // fDx = ((pt[7]).x()-(pt[6]).x())*0.5 ;
150    // fTalpha = ((pt[6]).x()+(pt[7]).x()-(pt[5]).x()-(pt[4]).x())*0.25/fDy ;
151
152    fTthetaCphi = ((pt[4]).x()+fDy*fTalpha+fDx)/fDz ;
153    fTthetaSphi = ((pt[4]).y()+fDy)/fDz ;
154  }
155  else
156  {
157    G4cerr << "ERROR - G4Para()::G4Para(): " << GetName() << G4endl
158           << "        Invalid dimensions !" << G4endl;
159    G4Exception("G4Para::G4Para()", "InvalidSetup",
160                FatalException, "Invalid vertice coordinates.");
161  }   
162}
163
164///////////////////////////////////////////////////////////////////////
165//
166// Fake default constructor - sets only member data and allocates memory
167//                            for usage restricted to object persistency.
168//
169G4Para::G4Para( __void__& a )
170  : G4CSGSolid(a)
171{
172}
173
174//////////////////////////////////////////////////////////////////////////
175//
176
177G4Para::~G4Para()
178{
179}
180
181//////////////////////////////////////////////////////////////////////////
182//
183// Dispatch to parameterisation for replication mechanism dimension
184// computation & modification.
185
186void G4Para::ComputeDimensions(      G4VPVParameterisation* p,
187                                const G4int n,
188                                const G4VPhysicalVolume* pRep )
189{
190  p->ComputeDimensions(*this,n,pRep);
191}
192
193
194//////////////////////////////////////////////////////////////
195//
196// Calculate extent under transform and specified limit
197
198G4bool G4Para::CalculateExtent( const EAxis pAxis,
199                                const G4VoxelLimits& pVoxelLimit,
200                                const G4AffineTransform& pTransform,
201                                     G4double& pMin, G4double& pMax ) const
202{
203  G4bool flag;
204
205  if (!pTransform.IsRotated())
206  { 
207    // Special case handling for unrotated trapezoids
208    // Compute z/x/y/ mins and maxs respecting limits, with early returns
209    // if outside limits. Then switch() on pAxis
210
211    G4int i ; 
212    G4double xoffset,xMin,xMax;
213    G4double yoffset,yMin,yMax;
214    G4double zoffset,zMin,zMax;
215    G4double temp[8] ;       // some points for intersection with zMin/zMax
216   
217    xoffset=pTransform.NetTranslation().x();     
218    yoffset=pTransform.NetTranslation().y();
219    zoffset=pTransform.NetTranslation().z();
220 
221    G4ThreeVector pt[8];   // vertices after translation
222    pt[0]=G4ThreeVector(xoffset-fDz*fTthetaCphi-fDy*fTalpha-fDx,
223                        yoffset-fDz*fTthetaSphi-fDy,zoffset-fDz);
224    pt[1]=G4ThreeVector(xoffset-fDz*fTthetaCphi-fDy*fTalpha+fDx,
225                        yoffset-fDz*fTthetaSphi-fDy,zoffset-fDz);
226    pt[2]=G4ThreeVector(xoffset-fDz*fTthetaCphi+fDy*fTalpha-fDx,
227                        yoffset-fDz*fTthetaSphi+fDy,zoffset-fDz);
228    pt[3]=G4ThreeVector(xoffset-fDz*fTthetaCphi+fDy*fTalpha+fDx,
229                        yoffset-fDz*fTthetaSphi+fDy,zoffset-fDz);
230    pt[4]=G4ThreeVector(xoffset+fDz*fTthetaCphi-fDy*fTalpha-fDx,
231                        yoffset+fDz*fTthetaSphi-fDy,zoffset+fDz);
232    pt[5]=G4ThreeVector(xoffset+fDz*fTthetaCphi-fDy*fTalpha+fDx,
233                        yoffset+fDz*fTthetaSphi-fDy,zoffset+fDz);
234    pt[6]=G4ThreeVector(xoffset+fDz*fTthetaCphi+fDy*fTalpha-fDx,
235                        yoffset+fDz*fTthetaSphi+fDy,zoffset+fDz);
236    pt[7]=G4ThreeVector(xoffset+fDz*fTthetaCphi+fDy*fTalpha+fDx,
237                        yoffset+fDz*fTthetaSphi+fDy,zoffset+fDz);
238    zMin=zoffset-fDz;
239    zMax=zoffset+fDz;
240    if ( pVoxelLimit.IsZLimited() )
241    {
242      if   ( (zMin>pVoxelLimit.GetMaxZExtent()+kCarTolerance)
243          || (zMax<pVoxelLimit.GetMinZExtent()-kCarTolerance) )
244      {
245        return false;
246      }
247      else
248      {
249        if (zMin<pVoxelLimit.GetMinZExtent())
250        {
251          zMin=pVoxelLimit.GetMinZExtent();
252        }
253        if (zMax>pVoxelLimit.GetMaxZExtent())
254        {
255          zMax=pVoxelLimit.GetMaxZExtent();
256        }
257      }
258    }
259
260    temp[0] = pt[0].y()+(pt[4].y()-pt[0].y())
261                       *(zMin-pt[0].z())/(pt[4].z()-pt[0].z()) ;
262    temp[1] = pt[0].y()+(pt[4].y()-pt[0].y())
263                       *(zMax-pt[0].z())/(pt[4].z()-pt[0].z()) ;
264    temp[2] = pt[2].y()+(pt[6].y()-pt[2].y())
265                       *(zMin-pt[2].z())/(pt[6].z()-pt[2].z()) ;
266    temp[3] = pt[2].y()+(pt[6].y()-pt[2].y())
267                       *(zMax-pt[2].z())/(pt[6].z()-pt[2].z()) ;       
268    yMax = yoffset - std::fabs(fDz*fTthetaSphi) - fDy - fDy ;
269    yMin = -yMax ;
270    for(i=0;i<4;i++)
271    {
272      if(temp[i] > yMax) yMax = temp[i] ;
273      if(temp[i] < yMin) yMin = temp[i] ;
274    }
275     
276    if (pVoxelLimit.IsYLimited())
277    {
278      if ( (yMin>pVoxelLimit.GetMaxYExtent()+kCarTolerance)
279        || (yMax<pVoxelLimit.GetMinYExtent()-kCarTolerance) )
280      {
281        return false;
282      }
283      else
284      {
285        if (yMin<pVoxelLimit.GetMinYExtent())
286        {
287          yMin=pVoxelLimit.GetMinYExtent();
288        }
289        if (yMax>pVoxelLimit.GetMaxYExtent())
290        {
291          yMax=pVoxelLimit.GetMaxYExtent();
292        }
293      }
294    }
295
296    temp[0] = pt[0].x()+(pt[4].x()-pt[0].x())
297                       *(zMin-pt[0].z())/(pt[4].z()-pt[0].z()) ;
298    temp[1] = pt[0].x()+(pt[4].x()-pt[0].x())
299                       *(zMax-pt[0].z())/(pt[4].z()-pt[0].z()) ;
300    temp[2] = pt[2].x()+(pt[6].x()-pt[2].x())
301                       *(zMin-pt[2].z())/(pt[6].z()-pt[2].z()) ;
302    temp[3] = pt[2].x()+(pt[6].x()-pt[2].x())
303                       *(zMax-pt[2].z())/(pt[6].z()-pt[2].z()) ;
304    temp[4] = pt[3].x()+(pt[7].x()-pt[3].x())
305                       *(zMin-pt[3].z())/(pt[7].z()-pt[3].z()) ;
306    temp[5] = pt[3].x()+(pt[7].x()-pt[3].x())
307                       *(zMax-pt[3].z())/(pt[7].z()-pt[3].z()) ;
308    temp[6] = pt[1].x()+(pt[5].x()-pt[1].x())
309                       *(zMin-pt[1].z())/(pt[5].z()-pt[1].z()) ;
310    temp[7] = pt[1].x()+(pt[5].x()-pt[1].x())
311                       *(zMax-pt[1].z())/(pt[5].z()-pt[1].z()) ;
312
313    xMax = xoffset - std::fabs(fDz*fTthetaCphi) - fDx - fDx -fDx - fDx;
314    xMin = -xMax ;
315    for(i=0;i<8;i++)
316    {
317      if(temp[i] > xMax) xMax = temp[i] ;
318      if(temp[i] < xMin) xMin = temp[i] ;
319    }
320      // xMax/Min = f(yMax/Min) ?
321    if (pVoxelLimit.IsXLimited())
322    {
323      if ( (xMin>pVoxelLimit.GetMaxXExtent()+kCarTolerance)
324        || (xMax<pVoxelLimit.GetMinXExtent()-kCarTolerance) )
325      {
326        return false;
327      }
328      else
329      {
330        if (xMin<pVoxelLimit.GetMinXExtent())
331        {
332          xMin=pVoxelLimit.GetMinXExtent();
333        }
334        if (xMax>pVoxelLimit.GetMaxXExtent())
335        {
336          xMax=pVoxelLimit.GetMaxXExtent();
337        }
338      }
339    }
340
341    switch (pAxis)
342    {
343      case kXAxis:
344        pMin=xMin;
345        pMax=xMax;
346        break;
347      case kYAxis:
348        pMin=yMin;
349        pMax=yMax;
350        break;
351      case kZAxis:
352        pMin=zMin;
353        pMax=zMax;
354        break;
355      default:
356        break;
357    }
358
359    pMin-=kCarTolerance;
360    pMax+=kCarTolerance;
361    flag = true;
362  }
363  else
364  {
365    // General rotated case - create and clip mesh to boundaries
366
367    G4bool existsAfterClip=false;
368    G4ThreeVectorList *vertices;
369
370    pMin=+kInfinity;
371    pMax=-kInfinity;
372
373    // Calculate rotated vertex coordinates
374
375    vertices=CreateRotatedVertices(pTransform);
376    ClipCrossSection(vertices,0,pVoxelLimit,pAxis,pMin,pMax);
377    ClipCrossSection(vertices,4,pVoxelLimit,pAxis,pMin,pMax);
378    ClipBetweenSections(vertices,0,pVoxelLimit,pAxis,pMin,pMax);
379     
380    if (pMin!=kInfinity||pMax!=-kInfinity)
381    {
382      existsAfterClip=true;
383       
384      // Add 2*tolerance to avoid precision troubles
385      //
386      pMin-=kCarTolerance;
387      pMax+=kCarTolerance;
388    }
389    else
390    {
391      // Check for case where completely enveloping clipping volume
392      // If point inside then we are confident that the solid completely
393      // envelopes the clipping volume. Hence set min/max extents according
394      // to clipping volume extents along the specified axis.
395       
396      G4ThreeVector clipCentre(
397        (pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
398        (pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
399        (pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5);
400       
401      if (Inside(pTransform.Inverse().TransformPoint(clipCentre))!=kOutside)
402      {
403        existsAfterClip=true;
404        pMin=pVoxelLimit.GetMinExtent(pAxis);
405        pMax=pVoxelLimit.GetMaxExtent(pAxis);
406      }
407    }
408    delete vertices ;          //  'new' in the function called
409    flag = existsAfterClip ;
410  }
411  return flag;
412}
413
414/////////////////////////////////////////////////////////////////////////////
415//
416// Check in p is inside/on surface/outside solid
417
418EInside G4Para::Inside( const G4ThreeVector& p ) const
419{
420  G4double xt, yt, yt1;
421  EInside  in = kOutside;
422
423  yt1 = p.y() - fTthetaSphi*p.z();
424  yt  = std::fabs(yt1) ;
425
426  // xt = std::fabs( p.x() - fTthetaCphi*p.z() - fTalpha*yt );
427
428  xt = std::fabs( p.x() - fTthetaCphi*p.z() - fTalpha*yt1 );
429
430  if ( std::fabs( p.z() ) <= fDz - kCarTolerance*0.5)
431  {
432    if (yt <= fDy - kCarTolerance*0.5)
433    {
434      if      ( xt <= fDx - kCarTolerance*0.5 ) in = kInside;
435      else if ( xt <= fDx + kCarTolerance*0.5 ) in = kSurface;
436    }
437    else if ( yt <= fDy + kCarTolerance*0.5)
438    {
439      if ( xt <= fDx + kCarTolerance*0.5 ) in = kSurface; 
440    }
441  }
442  else  if ( std::fabs(p.z()) <= fDz + kCarTolerance*0.5 )
443  {
444    if ( yt <= fDy + kCarTolerance*0.5)
445    {
446      if ( xt <= fDx + kCarTolerance*0.5 ) in = kSurface; 
447    }
448  }
449  return in;
450}
451
452///////////////////////////////////////////////////////////////////////////
453//
454// Calculate side nearest to p, and return normal
455// If 2+ sides equidistant, first side's normal returned (arbitrarily)
456
457G4ThreeVector G4Para::SurfaceNormal( const G4ThreeVector& p ) const
458{
459  G4ThreeVector norm, sumnorm(0.,0.,0.);
460  G4int noSurfaces = 0; 
461  G4double distx,disty,distz;
462  G4double newpx,newpy,xshift;
463  G4double calpha,salpha;      // Sin/Cos(alpha) - needed to recalc G4Parameter
464  G4double tntheta,cosntheta;  // tan and cos of normal's theta component
465  G4double ycomp;
466  G4double delta = 0.5*kCarTolerance;
467
468  newpx  = p.x()-fTthetaCphi*p.z();
469  newpy  = p.y()-fTthetaSphi*p.z();
470
471  calpha = 1/std::sqrt(1+fTalpha*fTalpha);
472  if (fTalpha) {salpha = -calpha/fTalpha;} // NOTE: using MINUS std::sin(alpha)
473  else         {salpha = 0.;}
474 
475  //  xshift = newpx*calpha+newpy*salpha;
476  xshift = newpx - newpy*fTalpha;
477
478  //  distx  = std::fabs(std::fabs(xshift)-fDx*calpha);
479  distx  = std::fabs(std::fabs(xshift)-fDx);
480  disty  = std::fabs(std::fabs(newpy)-fDy);
481  distz  = std::fabs(std::fabs(p.z())-fDz);
482
483  tntheta   = fTthetaCphi*calpha + fTthetaSphi*salpha;
484  cosntheta = 1/std::sqrt(1+tntheta*tntheta);
485  ycomp     = 1/std::sqrt(1+fTthetaSphi*fTthetaSphi);
486
487  G4ThreeVector nX  = G4ThreeVector( calpha*cosntheta,
488                                     salpha*cosntheta,
489                                    -tntheta*cosntheta);
490  G4ThreeVector nY  = G4ThreeVector( 0, ycomp,-fTthetaSphi*ycomp);
491  G4ThreeVector nZ  = G4ThreeVector( 0, 0,  1.0);
492
493  if (distx <= delta)     
494  {
495    noSurfaces ++;
496    if ( xshift >= 0.) {sumnorm += nX;}
497    else               {sumnorm -= nX;}
498  }
499  if (disty <= delta)
500  {
501    noSurfaces ++;
502    if ( newpy >= 0.)  {sumnorm += nY;}
503    else               {sumnorm -= nY;}
504  }
505  if (distz <= delta) 
506  {
507    noSurfaces ++;
508    if ( p.z() >= 0.)  {sumnorm += nZ;}
509    else               {sumnorm -= nZ;}
510  }
511  if ( noSurfaces == 0 )
512  {
513#ifdef G4CSGDEBUG
514    G4Exception("G4Para::SurfaceNormal(p)", "Notification", JustWarning, 
515                "Point p is not on surface !?" );
516#endif
517     norm = ApproxSurfaceNormal(p);
518  }
519  else if ( noSurfaces == 1 ) {norm = sumnorm;}
520  else                        {norm = sumnorm.unit();}
521
522  return norm;
523}
524
525
526////////////////////////////////////////////////////////////////////////
527//
528// Algorithm for SurfaceNormal() following the original specification
529// for points not on the surface
530
531G4ThreeVector G4Para::ApproxSurfaceNormal( const G4ThreeVector& p ) const
532{
533  ENSide  side;
534  G4ThreeVector norm;
535  G4double distx,disty,distz;
536  G4double newpx,newpy,xshift;
537  G4double calpha,salpha;  // Sin/Cos(alpha) - needed to recalc G4Parameter
538  G4double tntheta,cosntheta;  // tan and cos of normal's theta component
539  G4double ycomp;
540
541  newpx=p.x()-fTthetaCphi*p.z();
542  newpy=p.y()-fTthetaSphi*p.z();
543
544  calpha=1/std::sqrt(1+fTalpha*fTalpha);
545  if (fTalpha)
546  {
547    salpha=-calpha/fTalpha;  // NOTE: actually use MINUS std::sin(alpha)
548  }
549  else
550  {
551    salpha=0;
552  }
553
554  xshift=newpx*calpha+newpy*salpha;
555
556  distx=std::fabs(std::fabs(xshift)-fDx*calpha);
557  disty=std::fabs(std::fabs(newpy)-fDy);
558  distz=std::fabs(std::fabs(p.z())-fDz);
559   
560  if (distx<disty)
561  {
562    if (distx<distz) {side=kNX;}
563    else {side=kNZ;}
564  }
565  else
566  {
567    if (disty<distz) {side=kNY;}
568    else {side=kNZ;}
569  }
570
571  switch (side)
572  {
573    case kNX:
574      tntheta=fTthetaCphi*calpha+fTthetaSphi*salpha;
575      if (xshift<0)
576      {
577        cosntheta=-1/std::sqrt(1+tntheta*tntheta);
578      }
579      else
580      {
581        cosntheta=1/std::sqrt(1+tntheta*tntheta);
582      }
583      norm=G4ThreeVector(calpha*cosntheta,salpha*cosntheta,-tntheta*cosntheta);
584      break;
585    case kNY:
586      if (newpy<0)
587      {
588        ycomp=-1/std::sqrt(1+fTthetaSphi*fTthetaSphi);
589      }
590      else
591      {
592        ycomp=1/std::sqrt(1+fTthetaSphi*fTthetaSphi);
593      }
594      norm=G4ThreeVector(0,ycomp,-fTthetaSphi*ycomp);
595      break;
596    case kNZ:           // Closest to Z
597      if (p.z()>=0)
598      {
599        norm=G4ThreeVector(0,0,1);
600      }
601      else
602      {
603        norm=G4ThreeVector(0,0,-1);
604      }
605      break;
606  }
607  return norm;
608}
609
610//////////////////////////////////////////////////////////////////////////////
611//
612// Calculate distance to shape from outside
613// - return kInfinity if no intersection
614//
615// ALGORITHM:
616// For each component, calculate pair of minimum and maximum intersection
617// values for which the particle is in the extent of the shape
618// - The smallest (MAX minimum) allowed distance of the pairs is intersect
619// - Z plane intersectin uses tolerance
620// - XZ YZ planes use logic & *SLIGHTLY INCORRECT* tolerance
621//   (this saves at least 1 sqrt, 1 multiply and 1 divide... in applicable
622//    cases)
623// - Note: XZ and YZ planes each divide space into four regions,
624//   characterised by ss1 ss2
625
626G4double G4Para::DistanceToIn( const G4ThreeVector& p,
627                               const G4ThreeVector& v ) const
628{
629  G4double snxt;    // snxt = default return value
630  G4double smin,smax;
631  G4double tmin,tmax;
632  G4double yt,vy,xt,vx;
633  G4double max;
634  //
635  // Z Intersection range
636  //
637  if (v.z()>0)
638  {
639    max=fDz-p.z();
640    if (max>kCarTolerance*0.5)
641    {
642      smax=max/v.z();
643      smin=(-fDz-p.z())/v.z();
644    }
645    else
646    {
647      return snxt=kInfinity;
648    }
649  }
650  else if (v.z()<0)
651  {
652    max=-fDz-p.z();
653    if (max<-kCarTolerance*0.5)
654    {
655      smax=max/v.z();
656      smin=(fDz-p.z())/v.z();
657    }
658    else
659    {
660      return snxt=kInfinity;
661    }
662  }
663  else
664  {
665    if (std::fabs(p.z())<=fDz) // Inside
666    {
667      smin=0;
668      smax=kInfinity;
669    }
670    else
671    {
672      return snxt=kInfinity;
673    }
674  }
675   
676  //
677  // Y G4Parallel planes intersection
678  //
679
680  yt=p.y()-fTthetaSphi*p.z();
681  vy=v.y()-fTthetaSphi*v.z();
682
683  if (vy>0)
684  {
685    max=fDy-yt;
686    if (max>kCarTolerance*0.5)
687    {
688      tmax=max/vy;
689      tmin=(-fDy-yt)/vy;
690    }
691    else
692    {
693      return snxt=kInfinity;
694    }
695  }
696  else if (vy<0)
697  {
698    max=-fDy-yt;
699    if (max<-kCarTolerance*0.5)
700    {
701      tmax=max/vy;
702      tmin=(fDy-yt)/vy;
703    }
704    else
705    {
706      return snxt=kInfinity;
707    }
708  }
709  else
710  {
711    if (std::fabs(yt)<=fDy)
712    {
713      tmin=0;
714      tmax=kInfinity;
715    }
716    else
717    {
718      return snxt=kInfinity;
719    }
720  }
721
722  // Re-Calc valid intersection range
723  //
724  if (tmin>smin) smin=tmin;
725  if (tmax<smax) smax=tmax;
726  if (smax<=smin)
727  {
728    return snxt=kInfinity;
729  }
730  else
731  {
732    //
733    // X G4Parallel planes intersection
734    //
735    xt=p.x()-fTthetaCphi*p.z()-fTalpha*yt;
736    vx=v.x()-fTthetaCphi*v.z()-fTalpha*vy;
737    if (vx>0)
738    {
739      max=fDx-xt;
740      if (max>kCarTolerance*0.5)
741      {
742        tmax=max/vx;
743        tmin=(-fDx-xt)/vx;
744      }
745      else
746      {
747        return snxt=kInfinity;
748      }
749    }
750    else if (vx<0)
751    {
752      max=-fDx-xt;
753      if (max<-kCarTolerance*0.5)
754      {
755        tmax=max/vx;
756        tmin=(fDx-xt)/vx;
757      }
758      else
759      {
760        return snxt=kInfinity;
761      }
762    }
763    else
764    {
765      if (std::fabs(xt)<=fDx)
766      {
767        tmin=0;
768        tmax=kInfinity;
769      }
770      else
771      {
772        return snxt=kInfinity;
773      }
774    }
775    if (tmin>smin) smin=tmin;
776    if (tmax<smax) smax=tmax;
777  }
778
779  if (smax>0&&smin<smax)
780  {
781    if (smin>0)
782    {
783      snxt=smin;
784    }
785    else
786    {
787      snxt=0;
788    }
789  }
790  else
791  {
792    snxt=kInfinity;
793  }
794  return snxt;
795}
796
797////////////////////////////////////////////////////////////////////////////
798//
799// Calculate exact shortest distance to any boundary from outside
800// - Returns 0 is point inside
801
802G4double G4Para::DistanceToIn( const G4ThreeVector& p ) const
803{
804  G4double safe=0.0;
805  G4double distz1,distz2,disty1,disty2,distx1,distx2;
806  G4double trany,cosy,tranx,cosx;
807
808  // Z planes
809  //
810  distz1=p.z()-fDz;
811  distz2=-fDz-p.z();
812  if (distz1>distz2)
813  {
814    safe=distz1;
815  }
816  else
817  {
818    safe=distz2;
819  }
820
821  trany=p.y()-fTthetaSphi*p.z(); // Transformed y into `box' system
822
823  // Transformed x into `box' system
824  //
825  cosy=1.0/std::sqrt(1.0+fTthetaSphi*fTthetaSphi);
826  disty1=(trany-fDy)*cosy;
827  disty2=(-fDy-trany)*cosy;
828   
829  if (disty1>safe) safe=disty1;
830  if (disty2>safe) safe=disty2;
831
832  tranx=p.x()-fTthetaCphi*p.z()-fTalpha*trany;
833  cosx=1.0/std::sqrt(1.0+fTalpha*fTalpha+fTthetaCphi*fTthetaCphi);
834  distx1=(tranx-fDx)*cosx;
835  distx2=(-fDx-tranx)*cosx;
836   
837  if (distx1>safe) safe=distx1;
838  if (distx2>safe) safe=distx2;
839   
840  if (safe<0) safe=0;
841  return safe; 
842}
843
844//////////////////////////////////////////////////////////////////////////
845//
846// Calculate distance to surface of shape from inside
847// Calculate distance to x/y/z planes - smallest is exiting distance
848
849G4double G4Para::DistanceToOut(const G4ThreeVector& p, const G4ThreeVector& v,
850                               const G4bool calcNorm,
851                               G4bool *validNorm, G4ThreeVector *n) const
852{
853  ESide side = kUndef;
854  G4double snxt;    // snxt = return value
855  G4double max,tmax;
856  G4double yt,vy,xt,vx;
857
858  G4double ycomp,calpha,salpha,tntheta,cosntheta;
859
860  //
861  // Z Intersections
862  //
863
864  if (v.z()>0)
865  {
866    max=fDz-p.z();
867    if (max>kCarTolerance*0.5)
868    {
869      snxt=max/v.z();
870      side=kPZ;
871    }
872    else
873    {
874      if (calcNorm)
875      {
876        *validNorm=true;
877        *n=G4ThreeVector(0,0,1);
878      }
879      return snxt=0;
880    }
881  }
882  else if (v.z()<0)
883  {
884    max=-fDz-p.z();
885    if (max<-kCarTolerance*0.5)
886    {
887      snxt=max/v.z();
888      side=kMZ;
889    }
890    else
891    {
892      if (calcNorm)
893      {
894        *validNorm=true;
895        *n=G4ThreeVector(0,0,-1);
896      }
897      return snxt=0;
898    }
899  }
900  else
901  {
902    snxt=kInfinity;
903  }
904   
905  //
906  // Y plane intersection
907  //
908
909  yt=p.y()-fTthetaSphi*p.z();
910  vy=v.y()-fTthetaSphi*v.z();
911
912  if (vy>0)
913  {
914    max=fDy-yt;
915    if (max>kCarTolerance*0.5)
916    {
917      tmax=max/vy;
918      if (tmax<snxt)
919      {
920        snxt=tmax;
921        side=kPY;
922      }
923    }
924    else
925    {
926      if (calcNorm)
927      {     
928        *validNorm=true; // Leaving via plus Y
929        ycomp=1/std::sqrt(1+fTthetaSphi*fTthetaSphi);
930        *n=G4ThreeVector(0,ycomp,-fTthetaSphi*ycomp);
931      }
932      return snxt=0;
933    }
934  }
935  else if (vy<0)
936  {
937    max=-fDy-yt;
938    if (max<-kCarTolerance*0.5)
939    {
940      tmax=max/vy;
941      if (tmax<snxt)
942      {
943        snxt=tmax;
944        side=kMY;
945      }
946    }
947    else
948    {
949      if (calcNorm)
950      {
951        *validNorm=true; // Leaving via minus Y
952        ycomp=-1/std::sqrt(1+fTthetaSphi*fTthetaSphi);
953        *n=G4ThreeVector(0,ycomp,-fTthetaSphi*ycomp);
954      }
955      return snxt=0;
956    }
957  }
958
959  //
960  // X plane intersection
961  //
962
963  xt=p.x()-fTthetaCphi*p.z()-fTalpha*yt;
964  vx=v.x()-fTthetaCphi*v.z()-fTalpha*vy;
965  if (vx>0)
966  {
967    max=fDx-xt;
968    if (max>kCarTolerance*0.5)
969    {
970      tmax=max/vx;
971      if (tmax<snxt)
972      {
973        snxt=tmax;
974        side=kPX;
975      }
976    }
977    else
978    {
979      if (calcNorm)
980      {
981        *validNorm=true; // Leaving via plus X
982        calpha=1/std::sqrt(1+fTalpha*fTalpha);
983        if (fTalpha)
984        {
985          salpha=-calpha/fTalpha;  // NOTE: actually use MINUS std::sin(alpha)
986        }
987        else
988        {
989          salpha=0;
990        }
991        tntheta=fTthetaCphi*calpha+fTthetaSphi*salpha;
992        cosntheta=1/std::sqrt(1+tntheta*tntheta);
993        *n=G4ThreeVector(calpha*cosntheta,salpha*cosntheta,-tntheta*cosntheta);
994      }
995      return snxt=0;
996    }
997  }
998  else if (vx<0)
999  {
1000    max=-fDx-xt;
1001    if (max<-kCarTolerance*0.5)
1002    {
1003      tmax=max/vx;
1004      if (tmax<snxt)
1005      {
1006        snxt=tmax;
1007        side=kMX;
1008      }
1009    }
1010    else
1011    {
1012      if (calcNorm)
1013      {
1014        *validNorm=true; // Leaving via minus X
1015        calpha=1/std::sqrt(1+fTalpha*fTalpha);
1016        if (fTalpha)
1017        {
1018          salpha=-calpha/fTalpha;  // NOTE: actually use MINUS std::sin(alpha)
1019        }
1020        else
1021        {
1022          salpha=0;
1023        }
1024        tntheta=fTthetaCphi*calpha+fTthetaSphi*salpha;
1025        cosntheta=-1/std::sqrt(1+tntheta*tntheta);
1026        *n=G4ThreeVector(calpha*cosntheta,salpha*cosntheta,-tntheta*cosntheta);
1027      }
1028      return snxt=0;
1029    }
1030  }
1031
1032  if (calcNorm)
1033  {
1034    *validNorm=true;
1035    switch (side)
1036    {
1037      case kMZ:
1038        *n=G4ThreeVector(0,0,-1);
1039        break;
1040      case kPZ:
1041        *n=G4ThreeVector(0,0,1);
1042        break;
1043      case kMY:
1044        ycomp=-1/std::sqrt(1+fTthetaSphi*fTthetaSphi);
1045        *n=G4ThreeVector(0,ycomp,-fTthetaSphi*ycomp);
1046        break;       
1047      case kPY:
1048        ycomp=1/std::sqrt(1+fTthetaSphi*fTthetaSphi);
1049        *n=G4ThreeVector(0,ycomp,-fTthetaSphi*ycomp);
1050        break;       
1051      case kMX:
1052        calpha=1/std::sqrt(1+fTalpha*fTalpha);
1053        if (fTalpha)
1054        {
1055          salpha=-calpha/fTalpha;  // NOTE: actually use MINUS std::sin(alpha)
1056        }
1057        else
1058        {
1059          salpha=0;
1060        }
1061        tntheta=fTthetaCphi*calpha+fTthetaSphi*salpha;
1062        cosntheta=-1/std::sqrt(1+tntheta*tntheta);
1063        *n=G4ThreeVector(calpha*cosntheta,salpha*cosntheta,-tntheta*cosntheta);
1064        break;
1065      case kPX:
1066        calpha=1/std::sqrt(1+fTalpha*fTalpha);
1067        if (fTalpha)
1068        {
1069          salpha=-calpha/fTalpha;  // NOTE: actually use MINUS std::sin(alpha)
1070        }
1071        else
1072        {
1073          salpha=0;
1074        }
1075        tntheta=fTthetaCphi*calpha+fTthetaSphi*salpha;
1076        cosntheta=1/std::sqrt(1+tntheta*tntheta);
1077        *n=G4ThreeVector(calpha*cosntheta,salpha*cosntheta,-tntheta*cosntheta);
1078        break;
1079      default:
1080        DumpInfo();
1081        G4Exception("G4Para::DistanceToOut(p,v,..)","Notification",JustWarning,
1082                    "Undefined side for valid surface normal to solid.");
1083        break;
1084    }
1085  }
1086  return snxt;
1087}
1088
1089/////////////////////////////////////////////////////////////////////////////
1090//
1091// Calculate exact shortest distance to any boundary from inside
1092// - Returns 0 is point outside
1093
1094G4double G4Para::DistanceToOut( const G4ThreeVector& p ) const
1095{
1096  G4double safe=0.0;
1097  G4double distz1,distz2,disty1,disty2,distx1,distx2;
1098  G4double trany,cosy,tranx,cosx;
1099
1100#ifdef G4CSGDEBUG
1101  if( Inside(p) == kOutside )
1102  {
1103     G4cout.precision(16) ;
1104     G4cout << G4endl ;
1105     DumpInfo();
1106     G4cout << "Position:"  << G4endl << G4endl ;
1107     G4cout << "p.x() = "   << p.x()/mm << " mm" << G4endl ;
1108     G4cout << "p.y() = "   << p.y()/mm << " mm" << G4endl ;
1109     G4cout << "p.z() = "   << p.z()/mm << " mm" << G4endl << G4endl ;
1110     G4Exception("G4Para::DistanceToOut(p)", "Notification",
1111                 JustWarning, "Point p is outside !?" );
1112  }
1113#endif
1114
1115  // Z planes
1116  //
1117  distz1=fDz-p.z();
1118  distz2=fDz+p.z();
1119  if (distz1<distz2)
1120  {
1121    safe=distz1;
1122  }
1123  else
1124  {
1125    safe=distz2;
1126  }
1127
1128  trany=p.y()-fTthetaSphi*p.z(); // Transformed y into `box' system
1129
1130  // Transformed x into `box' system
1131  //
1132  cosy=1.0/std::sqrt(1.0+fTthetaSphi*fTthetaSphi);
1133  disty1=(fDy-trany)*cosy;
1134  disty2=(fDy+trany)*cosy;
1135   
1136  if (disty1<safe) safe=disty1;
1137  if (disty2<safe) safe=disty2;
1138
1139  tranx=p.x()-fTthetaCphi*p.z()-fTalpha*trany;
1140  cosx=1.0/std::sqrt(1.0+fTalpha*fTalpha+fTthetaCphi*fTthetaCphi);
1141  distx1=(fDx-tranx)*cosx;
1142  distx2=(fDx+tranx)*cosx;
1143   
1144  if (distx1<safe) safe=distx1;
1145  if (distx2<safe) safe=distx2;
1146   
1147  if (safe<0) safe=0;
1148  return safe; 
1149}
1150
1151////////////////////////////////////////////////////////////////////////////////
1152//
1153// Create a List containing the transformed vertices
1154// Ordering [0-3] -fDz cross section
1155//          [4-7] +fDz cross section such that [0] is below [4],
1156//                                             [1] below [5] etc.
1157// Note:
1158//  Caller has deletion resposibility
1159
1160G4ThreeVectorList*
1161G4Para::CreateRotatedVertices( const G4AffineTransform& pTransform ) const
1162{
1163  G4ThreeVectorList *vertices;
1164  vertices=new G4ThreeVectorList();
1165  vertices->reserve(8);
1166  if (vertices)
1167  {
1168    G4ThreeVector vertex0(-fDz*fTthetaCphi-fDy*fTalpha-fDx,
1169                          -fDz*fTthetaSphi-fDy, -fDz);
1170    G4ThreeVector vertex1(-fDz*fTthetaCphi-fDy*fTalpha+fDx,
1171                          -fDz*fTthetaSphi-fDy, -fDz);
1172    G4ThreeVector vertex2(-fDz*fTthetaCphi+fDy*fTalpha-fDx,
1173                          -fDz*fTthetaSphi+fDy, -fDz);
1174    G4ThreeVector vertex3(-fDz*fTthetaCphi+fDy*fTalpha+fDx,
1175                          -fDz*fTthetaSphi+fDy, -fDz);
1176    G4ThreeVector vertex4(+fDz*fTthetaCphi-fDy*fTalpha-fDx,
1177                          +fDz*fTthetaSphi-fDy, +fDz);
1178    G4ThreeVector vertex5(+fDz*fTthetaCphi-fDy*fTalpha+fDx,
1179                          +fDz*fTthetaSphi-fDy, +fDz);
1180    G4ThreeVector vertex6(+fDz*fTthetaCphi+fDy*fTalpha-fDx,
1181                          +fDz*fTthetaSphi+fDy, +fDz);
1182    G4ThreeVector vertex7(+fDz*fTthetaCphi+fDy*fTalpha+fDx,
1183                          +fDz*fTthetaSphi+fDy, +fDz);
1184
1185    vertices->push_back(pTransform.TransformPoint(vertex0));
1186    vertices->push_back(pTransform.TransformPoint(vertex1));
1187    vertices->push_back(pTransform.TransformPoint(vertex2));
1188    vertices->push_back(pTransform.TransformPoint(vertex3));
1189    vertices->push_back(pTransform.TransformPoint(vertex4));
1190    vertices->push_back(pTransform.TransformPoint(vertex5));
1191    vertices->push_back(pTransform.TransformPoint(vertex6));
1192    vertices->push_back(pTransform.TransformPoint(vertex7));
1193  }
1194  else
1195  {
1196    DumpInfo();
1197    G4Exception("G4Para::CreateRotatedVertices()",
1198                "FatalError", FatalException,
1199                "Error in allocation of vertices. Out of memory !");
1200  }
1201  return vertices;
1202}
1203
1204//////////////////////////////////////////////////////////////////////////
1205//
1206// GetEntityType
1207
1208G4GeometryType G4Para::GetEntityType() const
1209{
1210  return G4String("G4Para");
1211}
1212
1213//////////////////////////////////////////////////////////////////////////
1214//
1215// Stream object contents to an output stream
1216
1217std::ostream& G4Para::StreamInfo( std::ostream& os ) const
1218{
1219  os << "-----------------------------------------------------------\n"
1220     << "    *** Dump for solid - " << GetName() << " ***\n"
1221     << "    ===================================================\n"
1222     << " Solid type: G4Para\n"
1223     << " Parameters: \n"
1224     << "    half length X: " << fDx/mm << " mm \n"
1225     << "    half length Y: " << fDy/mm << " mm \n"
1226     << "    half length Z: " << fDz/mm << " mm \n"
1227     << "    std::tan(alpha)         : " << fTalpha/degree << " degrees \n"
1228     << "    std::tan(theta)*std::cos(phi): " << fTthetaCphi/degree
1229     << " degrees \n"
1230     << "    std::tan(theta)*std::sin(phi): " << fTthetaSphi/degree
1231     << " degrees \n"
1232     << "-----------------------------------------------------------\n";
1233
1234  return os;
1235}
1236
1237//////////////////////////////////////////////////////////////////////////////
1238//
1239// GetPointOnPlane
1240// Auxiliary method for Get Point on Surface
1241//
1242
1243G4ThreeVector G4Para::GetPointOnPlane(G4ThreeVector p0, G4ThreeVector p1, 
1244                                      G4ThreeVector p2, G4ThreeVector p3, 
1245                                      G4double& area) const
1246{
1247  G4double lambda1, lambda2, chose, aOne, aTwo;
1248  G4ThreeVector t, u, v, w, Area, normal;
1249 
1250  t = p1 - p0;
1251  u = p2 - p1;
1252  v = p3 - p2;
1253  w = p0 - p3;
1254
1255  Area = G4ThreeVector(w.y()*v.z() - w.z()*v.y(),
1256                       w.z()*v.x() - w.x()*v.z(),
1257                       w.x()*v.y() - w.y()*v.x());
1258 
1259  aOne = 0.5*Area.mag();
1260 
1261  Area = G4ThreeVector(t.y()*u.z() - t.z()*u.y(),
1262                       t.z()*u.x() - t.x()*u.z(),
1263                       t.x()*u.y() - t.y()*u.x());
1264 
1265  aTwo = 0.5*Area.mag();
1266 
1267  area = aOne + aTwo;
1268 
1269  chose = RandFlat::shoot(0.,aOne+aTwo);
1270
1271  if( (chose>=0.) && (chose < aOne) )
1272  {
1273    lambda1 = RandFlat::shoot(0.,1.);
1274    lambda2 = RandFlat::shoot(0.,lambda1);
1275    return (p2+lambda1*v+lambda2*w);   
1276  }
1277
1278  // else
1279
1280  lambda1 = RandFlat::shoot(0.,1.);
1281  lambda2 = RandFlat::shoot(0.,lambda1);
1282  return (p0+lambda1*t+lambda2*u);   
1283}
1284
1285/////////////////////////////////////////////////////////////////////////
1286//
1287// GetPointOnSurface
1288//
1289// Return a point (G4ThreeVector) randomly and uniformly
1290// selected on the solid surface
1291
1292G4ThreeVector G4Para::GetPointOnSurface() const
1293{
1294  G4ThreeVector One, Two, Three, Four, Five, Six;
1295  G4ThreeVector pt[8] ;
1296  G4double chose, aOne, aTwo, aThree, aFour, aFive, aSix;
1297
1298  pt[0] = G4ThreeVector(-fDz*fTthetaCphi-fDy*fTalpha-fDx,
1299                        -fDz*fTthetaSphi-fDy, -fDz);
1300  pt[1] = G4ThreeVector(-fDz*fTthetaCphi-fDy*fTalpha+fDx,
1301                        -fDz*fTthetaSphi-fDy, -fDz);
1302  pt[2] = G4ThreeVector(-fDz*fTthetaCphi+fDy*fTalpha-fDx,
1303                        -fDz*fTthetaSphi+fDy, -fDz);
1304  pt[3] = G4ThreeVector(-fDz*fTthetaCphi+fDy*fTalpha+fDx,
1305                        -fDz*fTthetaSphi+fDy, -fDz);
1306  pt[4] = G4ThreeVector(+fDz*fTthetaCphi-fDy*fTalpha-fDx,
1307                        +fDz*fTthetaSphi-fDy, +fDz);
1308  pt[5] = G4ThreeVector(+fDz*fTthetaCphi-fDy*fTalpha+fDx,
1309                        +fDz*fTthetaSphi-fDy, +fDz);
1310  pt[6] = G4ThreeVector(+fDz*fTthetaCphi+fDy*fTalpha-fDx,
1311                        +fDz*fTthetaSphi+fDy, +fDz);
1312  pt[7] = G4ThreeVector(+fDz*fTthetaCphi+fDy*fTalpha+fDx,
1313                        +fDz*fTthetaSphi+fDy, +fDz);
1314
1315  // make sure we provide the points in a clockwise fashion
1316
1317  One   = GetPointOnPlane(pt[0],pt[1],pt[3],pt[2], aOne);
1318  Two   = GetPointOnPlane(pt[4],pt[5],pt[7],pt[6], aTwo);
1319  Three = GetPointOnPlane(pt[6],pt[7],pt[3],pt[2], aThree);
1320  Four  = GetPointOnPlane(pt[4],pt[5],pt[1],pt[0], aFour); 
1321  Five  = GetPointOnPlane(pt[0],pt[2],pt[6],pt[4], aFive);
1322  Six   = GetPointOnPlane(pt[1],pt[3],pt[7],pt[5], aSix);
1323
1324  chose = RandFlat::shoot(0.,aOne+aTwo+aThree+aFour+aFive+aSix);
1325 
1326  if( (chose>=0.) && (chose<aOne) )                   
1327    { return One; }
1328  else if(chose>=aOne && chose<aOne+aTwo) 
1329    { return Two; }
1330  else if(chose>=aOne+aTwo && chose<aOne+aTwo+aThree)
1331    { return Three; }
1332  else if(chose>=aOne+aTwo+aThree && chose<aOne+aTwo+aThree+aFour)
1333    { return Four; }
1334  else if(chose>=aOne+aTwo+aThree+aFour && chose<aOne+aTwo+aThree+aFour+aFive)
1335    { return Five; }
1336  return Six;
1337}
1338
1339////////////////////////////////////////////////////////////////////////////
1340//
1341// Methods for visualisation
1342
1343void G4Para::DescribeYourselfTo ( G4VGraphicsScene& scene ) const
1344{
1345  scene.AddSolid (*this);
1346}
1347
1348G4Polyhedron* G4Para::CreatePolyhedron () const
1349{
1350  G4double phi = std::atan2(fTthetaSphi, fTthetaCphi);
1351  G4double alpha = std::atan(fTalpha);
1352  G4double theta = std::atan(std::sqrt(fTthetaCphi*fTthetaCphi
1353                            +fTthetaSphi*fTthetaSphi));
1354   
1355  return new G4PolyhedronPara(fDx, fDy, fDz, alpha, theta, phi);
1356}
1357
1358G4NURBS* G4Para::CreateNURBS () const
1359{
1360  // return new G4NURBSbox (fDx, fDy, fDz);
1361  return 0 ;
1362}
Note: See TracBrowser for help on using the repository browser.