Files
geant4/source/geometry/solids/CSG/src/G4Trap.cc
T
2016-06-09 10:28:22 +02:00

1692 lines
48 KiB
C++

//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// $Id: G4Trap.cc,v 1.17 2003/06/16 16:53:42 gunter Exp $
// GEANT4 tag $Name: geant4-05-02 $
//
// class G4Trap
//
// Implementation for G4Trap class
//
// History:
// 21.03.95 P.Kent: Modified for `tolerant' geometry
// 09.09.96 V. Grichine: Final modifications before to commit
// 01.11.96 V.Grichine: Costructor for Right Angular Wedge from STEP, G4Trd/Para
// 08.12.97 J.Allison: Added "nominal" constructor and method SetAllParameters.
// 04.06.99 S.Giani: Fixed CalculateExtent in rotated case.
// 19.11.99 V.Grichine: kUndef was added to Eside enum
// 13.12.99 V.Grichine: bug fixed in DistanceToIn(p,v)
//
// ********************************************************************
#include "G4Trap.hh"
#include "G4VoxelLimits.hh"
#include "G4AffineTransform.hh"
#include "G4VPVParameterisation.hh"
#include "G4VGraphicsScene.hh"
#include "G4Polyhedron.hh"
#include "G4NURBS.hh"
#include "G4NURBSbox.hh"
////////////////////////////////////////////////////////////////////////
//
// Accuracy of coplanarity
const G4double kCoplanar_Tolerance = 1E-4 ;
//////////////////////////////////////////////////////////////////////////
//
// Private enum: Not for external use
enum Eside {kUndef,ks0,ks1,ks2,ks3,kPZ,kMZ};
////////////////////////////////////////////////////////////////////////
//
// Destructor
G4Trap::~G4Trap()
{
}
//////////////////////////////////////////////////////////////////////////
//
// Constructor - check and set half-widths as well as angles:
// final check of coplanarity
G4Trap::G4Trap( const G4String& pName,
G4double pDz,
G4double pTheta, G4double pPhi,
G4double pDy1, G4double pDx1, G4double pDx2,
G4double pAlp1,
G4double pDy2, G4double pDx3, G4double pDx4,
G4double pAlp2)
: G4CSGSolid(pName)
{
if ( pDz > 0 && pDy1 > 0 && pDx1 > 0 &&
pDx2 > 0 && pDy2 > 0 && pDx3 > 0 && pDx4 > 0 )
{
fDz=pDz;
fTthetaCphi=tan(pTheta)*cos(pPhi);
fTthetaSphi=tan(pTheta)*sin(pPhi);
fDy1=pDy1;
fDx1=pDx1;
fDx2=pDx2;
fTalpha1=tan(pAlp1);
fDy2=pDy2;
fDx3=pDx3;
fDx4=pDx4;
fTalpha2=tan(pAlp2);
MakePlanes();
}
else
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl
<< " Invalid dimensions !" << G4endl
<< " X - "
<< pDx1 << ", " << pDx2 << ", " << pDx3 << ", " << pDx4 << G4endl
<< " Y - " << pDy1 << ", " << pDy2 << G4endl
<< " Z - " << pDz << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl
<< " Invalid dimensions !" << G4endl
<< " X - "
<< pDx1 << ", " << pDx2 << ", " << pDx3 << ", " << pDx4 << G4endl
<< " Y - " << pDy1 << ", " << pDy2 << G4endl
<< " Z - " << pDz << G4endl;
G4Exception("G4Trap::G4Trap() - Invalid length G4Trap parameters");
}
}
////////////////////////////////////////////////////////////////////////////
//
// Constructor - Design of trapezoid based on 8 G4ThreeVector parameters,
// which are its vertices. Checking of planarity with preparation of
// fPlanes[] and than calculation of other members
G4Trap::G4Trap( const G4String& pName,
const G4ThreeVector pt[8] )
: G4CSGSolid(pName)
{
if ( pt[0].z()<0 && pt[0].z()==pt[1].z()
&& pt[0].z()==pt[2].z() && pt[0].z()==pt[3].z()
&& pt[4].z()>0 && pt[4].z()==pt[5].z()
&& pt[4].z()==pt[6].z() && pt[4].z()==pt[7].z()
&& (pt[0].z()+pt[4].z())== 0
&& pt[0].y()==pt[1].y() && pt[2].y()==pt[3].y()
&& pt[4].y()==pt[5].y() && pt[6].y()==pt[7].y()
&& (pt[0].y()+pt[2].y()+pt[4].y()+pt[6].y())==0 )
{
G4bool good;
// Bottom side with normal approx. -Y
//
good=MakePlane(pt[0],pt[4],pt[5],pt[1],fPlanes[0]);
if (!good)
{
DumpInfo();
G4Exception("G4Trap::G4Trap() - face at ~-Y not planar");
}
// Top side with normal approx. +Y
//
good=MakePlane(pt[2],pt[3],pt[7],pt[6],fPlanes[1]);
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~+Y not planar");
}
// Front side with normal approx. -X
//
good=MakePlane(pt[0],pt[2],pt[6],pt[4],fPlanes[2]);
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~-X not planar");
}
// Back side iwth normal approx. +X
//
good=MakePlane(pt[1],pt[5],pt[7],pt[3],fPlanes[3]);
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~+X not planar");
}
fDz = (pt[7]).z() ;
fDy1 = ((pt[2]).y()-(pt[1]).y())*0.5 ;
fDx1 = ((pt[1]).x()-(pt[0]).x())*0.5 ;
fDx2 = ((pt[3]).x()-(pt[2]).x())*0.5 ;
fTalpha1 = ((pt[2]).x()+(pt[3]).x()-(pt[1]).x()-(pt[0]).x())*0.25/fDy1 ;
fDy2 = ((pt[6]).y()-(pt[5]).y())*0.5 ;
fDx3 = ((pt[5]).x()-(pt[4]).x())*0.5 ;
fDx4 = ((pt[7]).x()-(pt[6]).x())*0.5 ;
fTalpha2 = ((pt[6]).x()+(pt[7]).x()-(pt[5]).x()-(pt[4]).x())*0.25/fDy2 ;
fTthetaCphi = ((pt[4]).x()+fDy2*fTalpha2+fDx3)/fDz ;
fTthetaSphi = ((pt[4]).y()+fDy2)/fDz ;
}
else
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - Invalid vertice coordinates");
}
}
//////////////////////////////////////////////////////////////////////////////
//
// Constructor for Right Angular Wedge from STEP
G4Trap::G4Trap( const G4String& pName,
G4double pZ,
G4double pY,
G4double pX, G4double pLTX )
: G4CSGSolid(pName)
{
G4bool good;
if ( pZ>0 && pY>0 && pX>0 && pLTX>0 && pLTX<=pX )
{
fDz = 0.5*pZ ;
fTthetaCphi = 0 ;
fTthetaSphi = 0 ;
fDy1 = 0.5*pY;
fDx1 = 0.5*pX ;
fDx2 = 0.5*pLTX;
fTalpha1 = 0.5*(pLTX - pX)/pY;
fDy2 = fDy1 ;
fDx3 = fDx1;
fDx4 = fDx2 ;
fTalpha2 = fTalpha1 ;
G4ThreeVector pt[8] ;
pt[0]=G4ThreeVector(-fDz*fTthetaCphi-fDy1*fTalpha1-fDx1,
-fDz*fTthetaSphi-fDy1,-fDz);
pt[1]=G4ThreeVector(-fDz*fTthetaCphi-fDy1*fTalpha1+fDx1,
-fDz*fTthetaSphi-fDy1,-fDz);
pt[2]=G4ThreeVector(-fDz*fTthetaCphi+fDy1*fTalpha1-fDx2,
-fDz*fTthetaSphi+fDy1,-fDz);
pt[3]=G4ThreeVector(-fDz*fTthetaCphi+fDy1*fTalpha1+fDx2,
-fDz*fTthetaSphi+fDy1,-fDz);
pt[4]=G4ThreeVector(+fDz*fTthetaCphi-fDy2*fTalpha2-fDx3,
+fDz*fTthetaSphi-fDy2,+fDz);
pt[5]=G4ThreeVector(+fDz*fTthetaCphi-fDy2*fTalpha2+fDx3,
+fDz*fTthetaSphi-fDy2,+fDz);
pt[6]=G4ThreeVector(+fDz*fTthetaCphi+fDy2*fTalpha2-fDx4,
+fDz*fTthetaSphi+fDy2,+fDz);
pt[7]=G4ThreeVector(+fDz*fTthetaCphi+fDy2*fTalpha2+fDx4,
+fDz*fTthetaSphi+fDy2,+fDz);
// Bottom side with normal approx. -Y
//
good=MakePlane(pt[0],pt[4],pt[5],pt[1],fPlanes[0]);
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~-Y not planar");
}
// Top side with normal approx. +Y
//
good=MakePlane(pt[2],pt[3],pt[7],pt[6],fPlanes[1]);
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~+Y not planar");
}
// Front side with normal approx. -X
//
good=MakePlane(pt[0],pt[2],pt[6],pt[4],fPlanes[2]);
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~-X not planar");
}
// Back side iwth normal approx. +X
//
good=MakePlane(pt[1],pt[5],pt[7],pt[3],fPlanes[3]);
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~+X not planar");
}
}
else
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - Invalid length G4Trap parameters");
}
}
///////////////////////////////////////////////////////////////////////////////
//
// Constructor for G4Trd
G4Trap::G4Trap( const G4String& pName,
G4double pDx1, G4double pDx2,
G4double pDy1, G4double pDy2,
G4double pDz )
: G4CSGSolid(pName)
{
G4bool good;
if ( pDz>0 && pDy1>0 && pDx1>0 && pDx2>0 && pDy2>0 )
{
fDz = pDz;
fTthetaCphi = 0 ;
fTthetaSphi = 0 ;
fDy1 = pDy1 ;
fDx1 = pDx1 ;
fDx2 = pDx1 ;
fTalpha1 = 0 ;
fDy2 = pDy2 ;
fDx3 = pDx2 ;
fDx4 = pDx2 ;
fTalpha2 = 0 ;
G4ThreeVector pt[8] ;
pt[0]=G4ThreeVector(-fDz*fTthetaCphi-fDy1*fTalpha1-fDx1,
-fDz*fTthetaSphi-fDy1,-fDz);
pt[1]=G4ThreeVector(-fDz*fTthetaCphi-fDy1*fTalpha1+fDx1,
-fDz*fTthetaSphi-fDy1,-fDz);
pt[2]=G4ThreeVector(-fDz*fTthetaCphi+fDy1*fTalpha1-fDx2,
-fDz*fTthetaSphi+fDy1,-fDz);
pt[3]=G4ThreeVector(-fDz*fTthetaCphi+fDy1*fTalpha1+fDx2,
-fDz*fTthetaSphi+fDy1,-fDz);
pt[4]=G4ThreeVector(+fDz*fTthetaCphi-fDy2*fTalpha2-fDx3,
+fDz*fTthetaSphi-fDy2,+fDz);
pt[5]=G4ThreeVector(+fDz*fTthetaCphi-fDy2*fTalpha2+fDx3,
+fDz*fTthetaSphi-fDy2,+fDz);
pt[6]=G4ThreeVector(+fDz*fTthetaCphi+fDy2*fTalpha2-fDx4,
+fDz*fTthetaSphi+fDy2,+fDz);
pt[7]=G4ThreeVector(+fDz*fTthetaCphi+fDy2*fTalpha2+fDx4,
+fDz*fTthetaSphi+fDy2,+fDz);
// Bottom side with normal approx. -Y
//
good=MakePlane(pt[0],pt[4],pt[5],pt[1],fPlanes[0]);
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~-Y not planar");
}
// Top side with normal approx. +Y
//
good=MakePlane(pt[2],pt[3],pt[7],pt[6],fPlanes[1]);
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~+Y not planar");
}
// Front side with normal approx. -X
//
good=MakePlane(pt[0],pt[2],pt[6],pt[4],fPlanes[2]);
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~-X not planar");
}
// Back side iwth normal approx. +X
//
good=MakePlane(pt[1],pt[5],pt[7],pt[3],fPlanes[3]);
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~+X not planar");
}
}
else
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - Invalid length G4Trap parameters");
}
}
////////////////////////////////////////////////////////////////////////////
//
// Constructor for G4Para
G4Trap::G4Trap( const G4String& pName,
G4double pDx, G4double pDy,
G4double pDz,
G4double pAlpha,
G4double pTheta, G4double pPhi)
: G4CSGSolid(pName)
{
G4bool good;
if ( pDz>0 && pDy>0 && pDx>0 )
{
fDz = pDz ;
fTthetaCphi = tan(pTheta)*cos(pPhi) ;
fTthetaSphi = tan(pTheta)*sin(pPhi) ;
fDy1 = pDy ;
fDx1 = pDx ;
fDx2 = pDx ;
fTalpha1 = tan(pAlpha) ;
fDy2 = pDy ;
fDx3 = pDx ;
fDx4 = pDx ;
fTalpha2 = fTalpha1 ;
G4ThreeVector pt[8] ;
pt[0]=G4ThreeVector(-fDz*fTthetaCphi-fDy1*fTalpha1-fDx1,
-fDz*fTthetaSphi-fDy1,-fDz);
pt[1]=G4ThreeVector(-fDz*fTthetaCphi-fDy1*fTalpha1+fDx1,
-fDz*fTthetaSphi-fDy1,-fDz);
pt[2]=G4ThreeVector(-fDz*fTthetaCphi+fDy1*fTalpha1-fDx2,
-fDz*fTthetaSphi+fDy1,-fDz);
pt[3]=G4ThreeVector(-fDz*fTthetaCphi+fDy1*fTalpha1+fDx2,
-fDz*fTthetaSphi+fDy1,-fDz);
pt[4]=G4ThreeVector(+fDz*fTthetaCphi-fDy2*fTalpha2-fDx3,
+fDz*fTthetaSphi-fDy2,+fDz);
pt[5]=G4ThreeVector(+fDz*fTthetaCphi-fDy2*fTalpha2+fDx3,
+fDz*fTthetaSphi-fDy2,+fDz);
pt[6]=G4ThreeVector(+fDz*fTthetaCphi+fDy2*fTalpha2-fDx4,
+fDz*fTthetaSphi+fDy2,+fDz);
pt[7]=G4ThreeVector(+fDz*fTthetaCphi+fDy2*fTalpha2+fDx4,
+fDz*fTthetaSphi+fDy2,+fDz);
// Bottom side with normal approx. -Y
//
good=MakePlane(pt[0],pt[4],pt[5],pt[1],fPlanes[0]);
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~-Y not planar");
}
// Top side with normal approx. +Y
//
good=MakePlane(pt[2],pt[3],pt[7],pt[6],fPlanes[1]);
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~+Y not planar");
}
// Front side with normal approx. -X
//
good=MakePlane(pt[0],pt[2],pt[6],pt[4],fPlanes[2]);
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~-X not planar");
}
// Back side iwth normal approx. +X
//
good=MakePlane(pt[1],pt[5],pt[7],pt[3],fPlanes[3]);
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~+X not planar");
}
}
else
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - Invalid length G4Trap parameters");
}
}
///////////////////////////////////////////////////////////////////////////
//
// Nominal constructor for G4Trap whose parameters are to be set by
// a G4VParamaterisation later. Check and set half-widths as well as
// angles: final check of coplanarity
G4Trap::G4Trap( const G4String& pName )
: G4CSGSolid (pName),
fDz (1.),
fTthetaCphi (0.),
fTthetaSphi (0.),
fDy1 (1.),
fDx1 (1.),
fDx2 (1.),
fTalpha1 (0.),
fDy2 (1.),
fDx3 (1.),
fDx4 (1.),
fTalpha2 (0.)
{
}
///////////////////////////////////////////////////////////////////////
//
// Set all parameters, as for constructor - check and set half-widths
// as well as angles: final check of coplanarity
void G4Trap::SetAllParameters ( G4double pDz,
G4double pTheta,
G4double pPhi,
G4double pDy1,
G4double pDx1,
G4double pDx2,
G4double pAlp1,
G4double pDy2,
G4double pDx3,
G4double pDx4,
G4double pAlp2 )
{
if ( pDz>0 && pDy1>0 && pDx1>0 && pDx2>0 && pDy2>0 && pDx3>0 && pDx4>0 )
{
fDz=pDz;
fTthetaCphi=tan(pTheta)*cos(pPhi);
fTthetaSphi=tan(pTheta)*sin(pPhi);
fDy1=pDy1;
fDx1=pDx1;
fDx2=pDx2;
fTalpha1=tan(pAlp1);
fDy2=pDy2;
fDx3=pDx3;
fDx4=pDx4;
fTalpha2=tan(pAlp2);
MakePlanes();
}
else
{
G4cout << "ERROR - G4Trap()::SetAllParameters(): " << GetName() << G4endl
<< " Invalid dimensions !" << G4endl
<< " X - "
<< pDx1 << ", " << pDx2 << ", " << pDx3 << ", " << pDx4 << G4endl
<< " Y - " << pDy1 << ", " << pDy2 << G4endl
<< " Z - " << pDz << G4endl;
G4cerr << "ERROR - G4Trap()::SetAllParameters(): " << GetName() << G4endl
<< " Invalid dimensions !" << G4endl
<< " X - "
<< pDx1 << ", " << pDx2 << ", " << pDx3 << ", " << pDx4 << G4endl
<< " Y - " << pDy1 << ", " << pDy2 << G4endl
<< " Z - " << pDz << G4endl;
G4Exception("G4Trap::SetAllParameters() - Invalid Length Parameters");
}
}
//////////////////////////////////////////////////////////////////////////
//
// Checking of coplanarity
G4bool G4Trap::MakePlanes()
{
G4bool good = true;
G4ThreeVector pt[8] ;
pt[0]=G4ThreeVector(-fDz*fTthetaCphi-fDy1*fTalpha1-fDx1,
-fDz*fTthetaSphi-fDy1,-fDz);
pt[1]=G4ThreeVector(-fDz*fTthetaCphi-fDy1*fTalpha1+fDx1,
-fDz*fTthetaSphi-fDy1,-fDz);
pt[2]=G4ThreeVector(-fDz*fTthetaCphi+fDy1*fTalpha1-fDx2,
-fDz*fTthetaSphi+fDy1,-fDz);
pt[3]=G4ThreeVector(-fDz*fTthetaCphi+fDy1*fTalpha1+fDx2,
-fDz*fTthetaSphi+fDy1,-fDz);
pt[4]=G4ThreeVector(+fDz*fTthetaCphi-fDy2*fTalpha2-fDx3,
+fDz*fTthetaSphi-fDy2,+fDz);
pt[5]=G4ThreeVector(+fDz*fTthetaCphi-fDy2*fTalpha2+fDx3,
+fDz*fTthetaSphi-fDy2,+fDz);
pt[6]=G4ThreeVector(+fDz*fTthetaCphi+fDy2*fTalpha2-fDx4,
+fDz*fTthetaSphi+fDy2,+fDz);
pt[7]=G4ThreeVector(+fDz*fTthetaCphi+fDy2*fTalpha2+fDx4,
+fDz*fTthetaSphi+fDy2,+fDz);
// Bottom side with normal approx. -Y
//
good=MakePlane(pt[0],pt[4],pt[5],pt[1],fPlanes[0]) ;
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~-Y not planar");
}
// Top side with normal approx. +Y
//
good=MakePlane(pt[2],pt[3],pt[7],pt[6],fPlanes[1]);
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~+Y not planar");
}
// Front side with normal approx. -X
//
good=MakePlane(pt[0],pt[2],pt[6],pt[4],fPlanes[2]);
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~-X not planar");
}
// Back side iwth normal approx. +X
//
good=MakePlane(pt[1],pt[5],pt[7],pt[3],fPlanes[3]);
if (!good)
{
G4cout << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::G4Trap(): " << GetName() << G4endl;
G4Exception("G4Trap::G4Trap() - face at ~+X not planar");
}
return good;
}
//////////////////////////////////////////////////////////////////////////////
//
// Calculate the coef's of the plane p1->p2->p3->p4->p1
// where the ThreeVectors 1-4 are in anti-clockwise order when viewed from
// infront of the plane.
//
// Return true if the ThreeVectors are coplanar + set coef;s
// false if ThreeVectors are not coplanar
G4bool G4Trap::MakePlane( const G4ThreeVector& p1,
const G4ThreeVector& p2,
const G4ThreeVector& p3,
const G4ThreeVector& p4,
TrapSidePlane& plane )
{
G4double a,b,c,s;
G4ThreeVector v12,v13,v14,Vcross;
G4bool good;
v12 = p2-p1;
v13 = p3-p1;
v14 = p4-p1;
Vcross=v12.cross(v13);
if (fabs(Vcross.dot(v14)/(Vcross.mag()*v14.mag())) > kCoplanar_Tolerance)
{
good=false;
}
else
{
// a,b,c correspond to the x/y/z components of the
// normal vector to the plane
a=(p2.y()-p1.y())*(p1.z()+p2.z())+(p3.y()-p2.y())*(p2.z()+p3.z());
a+=(p4.y()-p3.y())*(p3.z()+p4.z())+(p1.y()-p4.y())*(p4.z()+p1.z()); // ?
b=(p2.z()-p1.z())*(p1.x()+p2.x())+(p3.z()-p2.z())*(p2.x()+p3.x());
b+=(p4.z()-p3.z())*(p3.x()+p4.x())+(p1.z()-p4.z())*(p4.x()+p1.x()); // ?
c=(p2.x()-p1.x())*(p1.y()+p2.y())+(p3.x()-p2.x())*(p2.y()+p3.y());
c+=(p4.x()-p3.x())*(p3.y()+p4.y())+(p1.x()-p4.x())*(p4.y()+p1.y()); // ?
// Let create diagonals 4-2 and 3-1 than (4-2)x(3-1) provides
// vector perpendicular to the plane directed to outside !!!
// and a,b,c, = f(1,2,3,4)
// a = +(p4.y() - p2.y())*(p3.z() - p1.z())
// - (p3.y() - p1.y())*(p4.z() - p2.z()) ;
// b = -(p4.x() - p2.x())*(p3.z() - p1.z())
// + (p3.x() - p1.x())*(p4.z() - p2.z()) ;
// c = +(p4.x() - p2.x())*(p3.y() - p1.y())
// - (p3.x() - p1.x())*(p4.y() - p2.y()) ;
s=sqrt(a*a+b*b+c*c); // so now vector plane.(a,b,c) is unit
if( s > 0 )
{
plane.a=a/s;
plane.b=b/s;
plane.c=c/s;
}
else
{
G4cout << "ERROR - G4Trap()::MakePlane(): " << GetName() << G4endl;
G4cerr << "ERROR - G4Trap()::MakePlane(): " << GetName() << G4endl;
G4Exception("G4Trap::MakePlane() - Invalid parameters") ;
}
// Calculate D: p1 in in plane so D=-n.p1.Vect()
//
plane.d=-(plane.a*p1.x()+plane.b*p1.y()+plane.c*p1.z());
good=true;
}
return good;
}
//////////////////////////////////////////////////////////////////////////////
//
// Dispatch to parameterisation for replication mechanism dimension
// computation & modification.
void G4Trap::ComputeDimensions( G4VPVParameterisation* p,
const G4int n,
const G4VPhysicalVolume* pRep )
{
p->ComputeDimensions(*this,n,pRep);
}
////////////////////////////////////////////////////////////////////////
//
// Calculate extent under transform and specified limit
G4bool G4Trap::CalculateExtent( const EAxis pAxis,
const G4VoxelLimits& pVoxelLimit,
const G4AffineTransform& pTransform,
G4double& pMin, G4double& pMax) const
{
G4double xMin, xMax, yMin, yMax, zMin, zMax;
G4bool flag;
if (!pTransform.IsRotated())
{
// Special case handling for unrotated trapezoids
// Compute z/x/y/ mins and maxs respecting limits, with early returns
// if outside limits. Then switch() on pAxis
G4int i ;
G4double xoffset;
G4double yoffset;
G4double zoffset;
G4double temp[8] ; // some points for intersection with zMin/zMax
G4ThreeVector pt[8]; // vertices after translation
xoffset=pTransform.NetTranslation().x();
yoffset=pTransform.NetTranslation().y();
zoffset=pTransform.NetTranslation().z();
pt[0]=G4ThreeVector(xoffset-fDz*fTthetaCphi-fDy1*fTalpha1-fDx1,
yoffset-fDz*fTthetaSphi-fDy1,zoffset-fDz);
pt[1]=G4ThreeVector(xoffset-fDz*fTthetaCphi-fDy1*fTalpha1+fDx1,
yoffset-fDz*fTthetaSphi-fDy1,zoffset-fDz);
pt[2]=G4ThreeVector(xoffset-fDz*fTthetaCphi+fDy1*fTalpha1-fDx2,
yoffset-fDz*fTthetaSphi+fDy1,zoffset-fDz);
pt[3]=G4ThreeVector(xoffset-fDz*fTthetaCphi+fDy1*fTalpha1+fDx2,
yoffset-fDz*fTthetaSphi+fDy1,zoffset-fDz);
pt[4]=G4ThreeVector(xoffset+fDz*fTthetaCphi-fDy2*fTalpha2-fDx3,
yoffset+fDz*fTthetaSphi-fDy2,zoffset+fDz);
pt[5]=G4ThreeVector(xoffset+fDz*fTthetaCphi-fDy2*fTalpha2+fDx3,
yoffset+fDz*fTthetaSphi-fDy2,zoffset+fDz);
pt[6]=G4ThreeVector(xoffset+fDz*fTthetaCphi+fDy2*fTalpha2-fDx4,
yoffset+fDz*fTthetaSphi+fDy2,zoffset+fDz);
pt[7]=G4ThreeVector(xoffset+fDz*fTthetaCphi+fDy2*fTalpha2+fDx4,
yoffset+fDz*fTthetaSphi+fDy2,zoffset+fDz);
zMin=zoffset-fDz;
zMax=zoffset+fDz;
if ( pVoxelLimit.IsZLimited() )
{
if ( (zMin > pVoxelLimit.GetMaxZExtent() + kCarTolerance)
|| (zMax < pVoxelLimit.GetMinZExtent() - kCarTolerance) )
{
return false;
}
else
{
if ( zMin < pVoxelLimit.GetMinZExtent() )
{
zMin = pVoxelLimit.GetMinZExtent() ;
}
if ( zMax > pVoxelLimit.GetMaxZExtent() )
{
zMax = pVoxelLimit.GetMaxZExtent() ;
}
}
}
temp[0] = pt[0].y()+(pt[4].y()-pt[0].y())*(zMin-pt[0].z())
/(pt[4].z()-pt[0].z()) ;
temp[1] = pt[0].y()+(pt[4].y()-pt[0].y())*(zMax-pt[0].z())
/(pt[4].z()-pt[0].z()) ;
temp[2] = pt[2].y()+(pt[6].y()-pt[2].y())*(zMin-pt[2].z())
/(pt[6].z()-pt[2].z()) ;
temp[3] = pt[2].y()+(pt[6].y()-pt[2].y())*(zMax-pt[2].z())
/(pt[6].z()-pt[2].z()) ;
yMax = yoffset - fabs(fDz*fTthetaSphi) - fDy1 - fDy2 ;
yMin = -yMax ;
for( i = 0 ; i < 4 ; i++ )
{
if( temp[i] > yMax ) yMax = temp[i] ;
if( temp[i] < yMin ) yMin = temp[i] ;
}
if ( pVoxelLimit.IsYLimited() )
{
if ( (yMin > pVoxelLimit.GetMaxYExtent() + kCarTolerance)
|| (yMax < pVoxelLimit.GetMinYExtent() - kCarTolerance) )
{
return false;
}
else
{
if ( yMin < pVoxelLimit.GetMinYExtent() )
{
yMin = pVoxelLimit.GetMinYExtent() ;
}
if ( yMax > pVoxelLimit.GetMaxYExtent() )
{
yMax = pVoxelLimit.GetMaxYExtent() ;
}
}
}
temp[0] = pt[0].x()+(pt[4].x()-pt[0].x())
*(zMin-pt[0].z())/(pt[4].z()-pt[0].z()) ;
temp[1] = pt[0].x()+(pt[4].x()-pt[0].x())
*(zMax-pt[0].z())/(pt[4].z()-pt[0].z()) ;
temp[2] = pt[2].x()+(pt[6].x()-pt[2].x())
*(zMin-pt[2].z())/(pt[6].z()-pt[2].z()) ;
temp[3] = pt[2].x()+(pt[6].x()-pt[2].x())
*(zMax-pt[2].z())/(pt[6].z()-pt[2].z()) ;
temp[4] = pt[3].x()+(pt[7].x()-pt[3].x())
*(zMin-pt[3].z())/(pt[7].z()-pt[3].z()) ;
temp[5] = pt[3].x()+(pt[7].x()-pt[3].x())
*(zMax-pt[3].z())/(pt[7].z()-pt[3].z()) ;
temp[6] = pt[1].x()+(pt[5].x()-pt[1].x())
*(zMin-pt[1].z())/(pt[5].z()-pt[1].z()) ;
temp[7] = pt[1].x()+(pt[5].x()-pt[1].x())
*(zMax-pt[1].z())/(pt[5].z()-pt[1].z()) ;
xMax = xoffset - fabs(fDz*fTthetaCphi) - fDx1 - fDx2 -fDx3 - fDx4 ;
xMin = -xMax ;
for( i = 0 ; i < 8 ; i++ )
{
if( temp[i] > xMax) xMax = temp[i] ;
if( temp[i] < xMin) xMin = temp[i] ;
}
if (pVoxelLimit.IsXLimited()) // xMax/Min = f(yMax/Min) ?
{
if ( (xMin > pVoxelLimit.GetMaxXExtent() + kCarTolerance)
|| (xMax < pVoxelLimit.GetMinXExtent() - kCarTolerance) )
{
return false;
}
else
{
if ( xMin < pVoxelLimit.GetMinXExtent() )
{
xMin = pVoxelLimit.GetMinXExtent() ;
}
if ( xMax > pVoxelLimit.GetMaxXExtent() )
{
xMax = pVoxelLimit.GetMaxXExtent() ;
}
}
}
switch (pAxis)
{
case kXAxis:
pMin=xMin;
pMax=xMax;
break;
case kYAxis:
pMin=yMin;
pMax=yMax;
break;
case kZAxis:
pMin=zMin;
pMax=zMax;
break;
default:
break;
}
pMin -= kCarTolerance;
pMax += kCarTolerance;
flag = true;
}
else // General rotated case -
{
G4bool existsAfterClip = false ;
G4ThreeVectorList* vertices;
pMin = +kInfinity;
pMax = -kInfinity;
// Calculate rotated vertex coordinates. Operator 'new' is called
vertices = CreateRotatedVertices(pTransform);
xMin = +kInfinity; yMin = +kInfinity; zMin = +kInfinity;
xMax = -kInfinity; yMax = -kInfinity; zMax = -kInfinity;
for( G4int nv = 0 ; nv < 8 ; nv++ )
{
if( (*vertices)[nv].x() > xMax ) xMax = (*vertices)[nv].x();
if( (*vertices)[nv].y() > yMax ) yMax = (*vertices)[nv].y();
if( (*vertices)[nv].z() > zMax ) zMax = (*vertices)[nv].z();
if( (*vertices)[nv].x() < xMin ) xMin = (*vertices)[nv].x();
if( (*vertices)[nv].y() < yMin ) yMin = (*vertices)[nv].y();
if( (*vertices)[nv].z() < zMin ) zMin = (*vertices)[nv].z();
}
if ( pVoxelLimit.IsZLimited() )
{
if ( (zMin > pVoxelLimit.GetMaxZExtent() + kCarTolerance)
|| (zMax < pVoxelLimit.GetMinZExtent() - kCarTolerance) )
{
delete vertices ; // 'new' in the function called
return false;
}
else
{
if ( zMin < pVoxelLimit.GetMinZExtent() )
{
zMin = pVoxelLimit.GetMinZExtent() ;
}
if ( zMax > pVoxelLimit.GetMaxZExtent() )
{
zMax = pVoxelLimit.GetMaxZExtent() ;
}
}
}
if ( pVoxelLimit.IsYLimited() )
{
if ( (yMin > pVoxelLimit.GetMaxYExtent() + kCarTolerance)
|| (yMax < pVoxelLimit.GetMinYExtent() - kCarTolerance) )
{
delete vertices ; // 'new' in the function called
return false;
}
else
{
if ( yMin < pVoxelLimit.GetMinYExtent() )
{
yMin = pVoxelLimit.GetMinYExtent() ;
}
if ( yMax > pVoxelLimit.GetMaxYExtent() )
{
yMax = pVoxelLimit.GetMaxYExtent() ;
}
}
}
if ( pVoxelLimit.IsXLimited() )
{
if ( (xMin > pVoxelLimit.GetMaxXExtent() + kCarTolerance)
|| (xMax < pVoxelLimit.GetMinXExtent() - kCarTolerance) )
{
delete vertices ; // 'new' in the function called
return false ;
}
else
{
if ( xMin < pVoxelLimit.GetMinXExtent() )
{
xMin = pVoxelLimit.GetMinXExtent() ;
}
if ( xMax > pVoxelLimit.GetMaxXExtent() )
{
xMax = pVoxelLimit.GetMaxXExtent() ;
}
}
}
switch (pAxis)
{
case kXAxis:
pMin=xMin;
pMax=xMax;
break;
case kYAxis:
pMin=yMin;
pMax=yMax;
break;
case kZAxis:
pMin=zMin;
pMax=zMax;
break;
default:
break;
}
if ( (pMin != kInfinity) || (pMax != -kInfinity) )
{
existsAfterClip=true;
// Add tolerance to avoid precision troubles
//
pMin -= kCarTolerance ;
pMax += kCarTolerance ;
}
delete vertices ; // 'new' in the function called
flag = existsAfterClip ;
}
return flag;
}
////////////////////////////////////////////////////////////////////////
//
// Return whether point inside/outside/on surface, using tolerance
EInside G4Trap::Inside( const G4ThreeVector& p ) const
{
EInside in;
G4double Dist;
G4int i;
if (fabs(p.z())<=fDz-kCarTolerance/2)
{
in=kInside;
for (i=0;i<4;i++)
{
Dist=fPlanes[i].a*p.x()+fPlanes[i].b*p.y()
+fPlanes[i].c*p.z()+fPlanes[i].d;
if (Dist>kCarTolerance/2)
{
return in=kOutside;
}
else if (Dist>-kCarTolerance/2)
{
in=kSurface;
}
}
}
else if (fabs(p.z())<=fDz+kCarTolerance/2)
{
in=kSurface;
for (i=0;i<4;i++)
{
Dist=fPlanes[i].a*p.x()+fPlanes[i].b*p.y()
+fPlanes[i].c*p.z()+fPlanes[i].d;
if (Dist>kCarTolerance/2)
{
return in=kOutside;
}
}
}
else
{
in=kOutside;
}
return in;
}
/////////////////////////////////////////////////////////////////////////////
//
// Calculate side nearest to p, and return normal
// If 2+ sides equidistant, first side's normal returned (arbitrarily)
G4ThreeVector G4Trap::SurfaceNormal( const G4ThreeVector& p ) const
{
G4double safe=kInfinity,Dist,safez;
G4int i,imin=0;
for (i=0;i<4;i++)
{
Dist=fabs(fPlanes[i].a*p.x()+fPlanes[i].b*p.y()
+fPlanes[i].c*p.z()+fPlanes[i].d);
if (Dist<safe)
{
safe=Dist;
imin=i;
}
}
safez=fabs(fabs(p.z())-fDz);
if (safe<safez)
{
return G4ThreeVector(fPlanes[imin].a,fPlanes[imin].b,fPlanes[imin].c);
}
else
{
if (p.z()>0)
{
return G4ThreeVector(0,0,1);
}
else
{
return G4ThreeVector(0,0,-1);
}
}
}
////////////////////////////////////////////////////////////////////////////
//
// Calculate distance to shape from outside - return kInfinity if no intersection
//
// ALGORITHM:
// For each component, calculate pair of minimum and maximum intersection
// values for which the particle is in the extent of the shape
// - The smallest (MAX minimum) allowed distance of the pairs is intersect
G4double G4Trap::DistanceToIn( const G4ThreeVector& p,
const G4ThreeVector& v ) const
{
G4double snxt; // snxt = default return value
G4double max,smax,smin;
G4double pdist,Comp,vdist;
G4int i;
//
// Z Intersection range
//
if ( v.z() > 0 )
{
max = fDz - p.z() ;
if (max > 0.5*kCarTolerance)
{
smax = max/v.z();
smin = (-fDz-p.z())/v.z();
}
else
{
return snxt=kInfinity;
}
}
else if (v.z() < 0 )
{
max = - fDz - p.z() ;
if (max < -0.5*kCarTolerance )
{
smax=max/v.z();
smin=(fDz-p.z())/v.z();
}
else
{
return snxt=kInfinity;
}
}
else
{
if (fabs(p.z())<fDz - 0.5*kCarTolerance) // Inside was <=fDz
{
smin=0;
smax=kInfinity;
}
else
{
return snxt=kInfinity;
}
}
for (i=0;i<4;i++)
{
pdist=fPlanes[i].a*p.x()+fPlanes[i].b*p.y()
+fPlanes[i].c*p.z()+fPlanes[i].d;
Comp=fPlanes[i].a*v.x()+fPlanes[i].b*v.y()+fPlanes[i].c*v.z();
if ( pdist >= -0.5*kCarTolerance ) // was >0
{
//
// Outside the plane -> this is an extent entry distance
//
if (Comp >= 0) // was >0
{
return snxt=kInfinity ;
}
else
{
vdist=-pdist/Comp;
if (vdist>smin)
{
if (vdist<smax)
{
smin = vdist;
}
else
{
return snxt=kInfinity;
}
}
}
}
else
{
//
// Inside the plane -> couble be an extent exit distance (smax)
//
if (Comp>0) // Will leave extent
{
vdist=-pdist/Comp;
if (vdist<smax)
{
if (vdist>smin)
{
smax=vdist;
}
else
{
return snxt=kInfinity;
}
}
}
}
}
//
// Checks in non z plane intersections ensure smin<smax
//
if (smin >=0 )
{
snxt = smin ;
}
else
{
snxt = 0 ;
}
return snxt;
}
///////////////////////////////////////////////////////////////////////////
//
// Calculate exact shortest distance to any boundary from outside
// This is the best fast estimation of the shortest distance to trap
// - Returns 0 is ThreeVector inside
G4double G4Trap::DistanceToIn( const G4ThreeVector& p ) const
{
G4double safe,Dist;
G4int i;
safe=fabs(p.z())-fDz;
for (i=0;i<4;i++)
{
Dist=fPlanes[i].a*p.x()+fPlanes[i].b*p.y()
+fPlanes[i].c*p.z()+fPlanes[i].d;
if (Dist > safe) safe=Dist;
}
if (safe<0) safe=0;
return safe;
}
/////////////////////////////////////////////////////////////////////////////////
//
// Calculate distance to surface of shape from inside
// Calculate distance to x/y/z planes - smallest is exiting distance
G4double G4Trap::DistanceToOut(const G4ThreeVector& p, const G4ThreeVector& v,
const G4bool calcNorm,
G4bool *validNorm, G4ThreeVector *n) const
{
Eside side = kUndef;
G4double snxt; // snxt = return value
G4double pdist,Comp,vdist,max;
//
// Z Intersections
//
if (v.z()>0)
{
max=fDz-p.z();
if (max>kCarTolerance/2)
{
snxt=max/v.z();
side=kPZ;
}
else
{
if (calcNorm)
{
*validNorm=true;
*n=G4ThreeVector(0,0,1);
}
return snxt=0;
}
}
else if (v.z()<0)
{
max=-fDz-p.z();
if (max<-kCarTolerance/2)
{
snxt=max/v.z();
side=kMZ;
}
else
{
if (calcNorm)
{
*validNorm=true;
*n=G4ThreeVector(0,0,-1);
}
return snxt=0;
}
}
else
{
snxt=kInfinity;
}
//
// Intersections with planes[0] (expanded because of setting enum)
//
pdist=fPlanes[0].a*p.x()+fPlanes[0].b*p.y()+fPlanes[0].c*p.z()+fPlanes[0].d;
Comp=fPlanes[0].a*v.x()+fPlanes[0].b*v.y()+fPlanes[0].c*v.z();
if (pdist>0)
{
// Outside the plane
if (Comp>0)
{
// Leaving immediately
if (calcNorm)
{
*validNorm=true;
*n=G4ThreeVector(fPlanes[0].a,fPlanes[0].b,fPlanes[0].c);
}
return snxt=0;
}
}
else if (pdist<-kCarTolerance/2)
{
// Inside the plane
if (Comp>0)
{
// Will leave extent
vdist=-pdist/Comp;
if (vdist<snxt)
{
snxt=vdist;
side=ks0;
}
}
}
else
{
// On surface
if (Comp>0)
{
if (calcNorm)
{
*validNorm=true;
*n=G4ThreeVector(fPlanes[0].a,fPlanes[0].b,fPlanes[0].c);
}
return snxt=0;
}
}
//
// Intersections with planes[1] (expanded because of setting enum)
//
pdist=fPlanes[1].a*p.x()+fPlanes[1].b*p.y()+fPlanes[1].c*p.z()+fPlanes[1].d;
Comp=fPlanes[1].a*v.x()+fPlanes[1].b*v.y()+fPlanes[1].c*v.z();
if (pdist>0)
{
// Outside the plane
if (Comp>0)
{
// Leaving immediately
if (calcNorm)
{
*validNorm=true;
*n=G4ThreeVector(fPlanes[1].a,fPlanes[1].b,fPlanes[1].c);
}
return snxt=0;
}
}
else if (pdist<-kCarTolerance/2)
{
// Inside the plane
if (Comp>0)
{
// Will leave extent
vdist=-pdist/Comp;
if (vdist<snxt)
{
snxt=vdist;
side=ks1;
}
}
}
else
{
// On surface
if (Comp>0)
{
if (calcNorm)
{
*validNorm=true;
*n=G4ThreeVector(fPlanes[1].a,fPlanes[1].b,fPlanes[1].c);
}
return snxt=0;
}
}
//
// Intersections with planes[2] (expanded because of setting enum)
//
pdist=fPlanes[2].a*p.x()+fPlanes[2].b*p.y()+fPlanes[2].c*p.z()+fPlanes[2].d;
Comp=fPlanes[2].a*v.x()+fPlanes[2].b*v.y()+fPlanes[2].c*v.z();
if (pdist>0)
{
// Outside the plane
if (Comp>0)
{
// Leaving immediately
if (calcNorm)
{
*validNorm=true;
*n=G4ThreeVector(fPlanes[2].a,fPlanes[2].b,fPlanes[2].c);
}
return snxt=0;
}
}
else if (pdist<-kCarTolerance/2)
{
// Inside the plane
if (Comp>0)
{
// Will leave extent
vdist=-pdist/Comp;
if (vdist<snxt)
{
snxt=vdist;
side=ks2;
}
}
}
else
{
// On surface
if (Comp>0)
{
if (calcNorm)
{
*validNorm=true;
*n=G4ThreeVector(fPlanes[2].a,fPlanes[2].b,fPlanes[2].c);
}
return snxt=0;
}
}
//
// Intersections with planes[3] (expanded because of setting enum)
//
pdist=fPlanes[3].a*p.x()+fPlanes[3].b*p.y()+fPlanes[3].c*p.z()+fPlanes[3].d;
Comp=fPlanes[3].a*v.x()+fPlanes[3].b*v.y()+fPlanes[3].c*v.z();
if (pdist>0)
{
// Outside the plane
if (Comp>0)
{
// Leaving immediately
if (calcNorm)
{
*validNorm=true;
*n=G4ThreeVector(fPlanes[3].a,fPlanes[3].b,fPlanes[3].c);
}
return snxt=0;
}
}
else if (pdist<-kCarTolerance/2)
{
// Inside the plane
if (Comp>0)
{
// Will leave extent
vdist=-pdist/Comp;
if (vdist<snxt)
{
snxt=vdist;
side=ks3;
}
}
}
else
{
// On surface
if (Comp>0)
{
if (calcNorm)
{
*validNorm=true;
*n=G4ThreeVector(fPlanes[3].a,fPlanes[3].b,fPlanes[3].c);
}
return snxt=0;
}
}
// set normal
if (calcNorm)
{
*validNorm=true;
switch(side)
{
case ks0:
*n=G4ThreeVector(fPlanes[0].a,fPlanes[0].b,fPlanes[0].c);
break;
case ks1:
*n=G4ThreeVector(fPlanes[1].a,fPlanes[1].b,fPlanes[1].c);
break;
case ks2:
*n=G4ThreeVector(fPlanes[2].a,fPlanes[2].b,fPlanes[2].c);
break;
case ks3:
*n=G4ThreeVector(fPlanes[3].a,fPlanes[3].b,fPlanes[3].c);
break;
case kMZ:
*n=G4ThreeVector(0,0,-1);
break;
case kPZ:
*n=G4ThreeVector(0,0,1);
break;
default:
break;
}
}
return snxt;
}
//////////////////////////////////////////////////////////////////////////////
//
// Calculate exact shortest distance to any boundary from inside
// - Returns 0 is ThreeVector outside
G4double G4Trap::DistanceToOut( const G4ThreeVector& p ) const
{
G4double safe,Dist;
G4int i;
#ifdef G4CSGDEBUG
if( Inside(p) == kOutside )
{
G4cout.precision(16) ;
G4cout << G4endl ;
DumpInfo();
G4cout << "Position:" << G4endl << G4endl ;
G4cout << "p.x() = " << p.x()/mm << " mm" << G4endl ;
G4cout << "p.y() = " << p.y()/mm << " mm" << G4endl ;
G4cout << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl ;
G4cout << "G4Trap::DistanceToOut(p) - point p is outside ?!" << G4endl ;
G4cerr << "G4Trap::DistanceToOut(p) - point p is outside ?!" << G4endl ;
}
#endif
safe=fDz-fabs(p.z());
if (safe<0) safe=0;
else
{
for (i=0;i<4;i++)
{
Dist=-(fPlanes[i].a*p.x()+fPlanes[i].b*p.y()
+fPlanes[i].c*p.z()+fPlanes[i].d);
if (Dist<safe) safe=Dist;
}
if (safe<0) safe=0;
}
return safe;
}
//////////////////////////////////////////////////////////////////////////
//
// Create a List containing the transformed vertices
// Ordering [0-3] -fDz cross section
// [4-7] +fDz cross section such that [0] is below [4],
// [1] below [5] etc.
// Note:
// Caller has deletion resposibility
G4ThreeVectorList*
G4Trap::CreateRotatedVertices( const G4AffineTransform& pTransform ) const
{
G4ThreeVectorList *vertices;
vertices=new G4ThreeVectorList();
vertices->reserve(8);
if (vertices)
{
G4ThreeVector vertex0(-fDz*fTthetaCphi-fDy1*fTalpha1-fDx1,
-fDz*fTthetaSphi-fDy1,-fDz);
G4ThreeVector vertex1(-fDz*fTthetaCphi-fDy1*fTalpha1+fDx1,
-fDz*fTthetaSphi-fDy1,-fDz);
G4ThreeVector vertex2(-fDz*fTthetaCphi+fDy1*fTalpha1-fDx2,
-fDz*fTthetaSphi+fDy1,-fDz);
G4ThreeVector vertex3(-fDz*fTthetaCphi+fDy1*fTalpha1+fDx2,
-fDz*fTthetaSphi+fDy1,-fDz);
G4ThreeVector vertex4(+fDz*fTthetaCphi-fDy2*fTalpha2-fDx3,
+fDz*fTthetaSphi-fDy2,+fDz);
G4ThreeVector vertex5(+fDz*fTthetaCphi-fDy2*fTalpha2+fDx3,
+fDz*fTthetaSphi-fDy2,+fDz);
G4ThreeVector vertex6(+fDz*fTthetaCphi+fDy2*fTalpha2-fDx4,
+fDz*fTthetaSphi+fDy2,+fDz);
G4ThreeVector vertex7(+fDz*fTthetaCphi+fDy2*fTalpha2+fDx4,
+fDz*fTthetaSphi+fDy2,+fDz);
vertices->push_back(pTransform.TransformPoint(vertex0));
vertices->push_back(pTransform.TransformPoint(vertex1));
vertices->push_back(pTransform.TransformPoint(vertex2));
vertices->push_back(pTransform.TransformPoint(vertex3));
vertices->push_back(pTransform.TransformPoint(vertex4));
vertices->push_back(pTransform.TransformPoint(vertex5));
vertices->push_back(pTransform.TransformPoint(vertex6));
vertices->push_back(pTransform.TransformPoint(vertex7));
}
else
{
DumpInfo();
G4Exception("G4Trap::CreateRotatedVertices() - Out of memory !");
}
return vertices;
}
//////////////////////////////////////////////////////////////////////////
//
// GetEntityType
G4GeometryType G4Trap::GetEntityType() const
{
return G4String("G4Trap");
}
//////////////////////////////////////////////////////////////////////////
//
// Stream object contents to an output stream
std::ostream& G4Trap::StreamInfo( std::ostream& os ) const
{
os << "-----------------------------------------------------------\n"
<< " *** Dump for solid - " << GetName() << " ***\n"
<< " ===================================================\n"
<< " Solid type: G4Trap\n"
<< " Parameters: \n"
<< " half length Z: " << fDz/mm << " mm \n"
<< " half length Y of face -fDz: " << fDy1/mm << " mm \n"
<< " half length X of side -fDy1, face -fDz: " << fDx1/mm << " mm \n"
<< " half length X of side +fDy1, face -fDz: " << fDx2/mm << " mm \n"
<< " half length Y of face +fDz: " << fDy2/mm << " mm \n"
<< " half length X of side -fDy2, face +fDz: " << fDx3/mm << " mm \n"
<< " half length X of side +fDy2, face +fDz: " << fDx4/mm << " mm \n"
<< " tan(theta)*cos(phi): " << fTthetaCphi/degree << " degrees \n"
<< " tan(theta)*sin(phi): " << fTthetaSphi/degree << " degrees \n"
<< " tan(alpha), -fDz: " << fTalpha1/degree << " degrees \n"
<< " tan(alpha), +fDz: " << fTalpha2/degree << " degrees \n"
<< " trap side plane equations:\n"
<< " " << fPlanes[0].a << " X + " << fPlanes[0].b << " Y + "
<< fPlanes[0].c << " Z + " << fPlanes[0].d << " = 0\n"
<< " " << fPlanes[1].a << " X + " << fPlanes[1].b << " Y + "
<< fPlanes[1].c << " Z + " << fPlanes[1].d << " = 0\n"
<< " " << fPlanes[2].a << " X + " << fPlanes[2].b << " Y + "
<< fPlanes[2].c << " Z + " << fPlanes[2].d << " = 0\n"
<< " " << fPlanes[3].a << " X + " << fPlanes[3].b << " Y + "
<< fPlanes[3].c << " Z + " << fPlanes[3].d << " = 0\n"
<< "-----------------------------------------------------------\n";
return os;
}
///////////////////////////////////////////////////////////////////////////////
//
// Methods for visualisation
void G4Trap::DescribeYourselfTo ( G4VGraphicsScene& scene ) const
{
scene.AddThis (*this);
}
G4Polyhedron* G4Trap::CreatePolyhedron () const
{
G4double phi = atan2(fTthetaSphi, fTthetaCphi);
G4double alpha1 = atan(fTalpha1);
G4double alpha2 = atan(fTalpha2);
G4double theta = atan(sqrt(fTthetaCphi*fTthetaCphi+fTthetaSphi*fTthetaSphi));
return new G4PolyhedronTrap(fDz, theta, phi,
fDy1, fDx1, fDx2, alpha1,
fDy2, fDx3, fDx4, alpha2);
}
G4NURBS* G4Trap::CreateNURBS () const
{
// return new G4NURBSbox (fDx, fDy, fDz);
return 0 ;
}
// ******************************** End of G4Trap.cc ********************************