Import Geant4 0.0.0 source tree
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
#include "G4Assembly.hh"
|
||||
|
||||
|
||||
G4Assembly::G4Assembly()
|
||||
{
|
||||
// ReadSTEPFile();
|
||||
// CopySTEPData();
|
||||
}
|
||||
|
||||
|
||||
G4Assembly::~G4Assembly()
|
||||
{
|
||||
for(G4int a=0;a<numberOfSolids;a++)
|
||||
delete placedVec[a];
|
||||
}
|
||||
|
||||
|
||||
void G4Assembly::SetPlacedVector(G4PlacedVector& pVec)
|
||||
{
|
||||
numberOfSolids = pVec.entries();
|
||||
|
||||
for(G4int a=0;a<numberOfSolids;a++)
|
||||
placedVec.append( pVec[a]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
#include "G4Axis2Placement3D.hh"
|
||||
|
||||
//G4Axis2Placement3D
|
||||
G4Axis2Placement3D::G4Axis2Placement3D(){}
|
||||
G4Axis2Placement3D::~G4Axis2Placement3D(){}
|
||||
|
||||
// this function is used in STEPinterface directory
|
||||
G4Axis2Placement3D::G4Axis2Placement3D(const G4Axis2Placement3D& place)
|
||||
{
|
||||
refDirection = place.GetRefDirection();
|
||||
axis = place.GetAxis();
|
||||
location = place.GetLocation();
|
||||
pX = place.GetPX();
|
||||
pY = place.GetPY();
|
||||
pZ = place.GetPZ();
|
||||
toPlacementCoordinates = GetToPlacementCoordinates();
|
||||
fromPlacementCoordinates = GetFromPlacementCoordinates();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
G4Axis2Placement3D::G4Axis2Placement3D(const G4ThreeVec Dir,
|
||||
const G4ThreeVec Axis,
|
||||
const G4Point3d Pt )
|
||||
{
|
||||
dir=Dir;
|
||||
axis=Axis;
|
||||
srf_point=Pt;
|
||||
ComputeNormal();
|
||||
G4Point3d Pt2 = Pt+Dir;
|
||||
G4Point3d Pt3 = Pt+Axis;
|
||||
G4Ray::CalcPlane3Pts(Pl, Pt, Pt2, Pt3);
|
||||
}
|
||||
|
||||
G4Axis2Placement3D::G4Axis2Placement3D(const G4ThreeVec Dir, const G4ThreeVec Axis, const G4Point3d Pt1, const G4Point3d Pt2, const G4Point3d Pt3)
|
||||
{
|
||||
dir=Dir;
|
||||
axis=Axis;
|
||||
srf_point=Pt1;
|
||||
ComputeNormal();
|
||||
G4Ray::CalcPlane3Pts(Pl, Pt1, Pt2, Pt3);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
void G4Axis2Placement3D::ProjectPlacement(const G4Plane& Pl1, const G4Plane& Pl2)
|
||||
{
|
||||
Project(ProjectedDir, dir, Pl1, Pl2);
|
||||
Project(ProjectedAxis, axis, Pl1, Pl2);
|
||||
Project(ProjectedSrfPoint, srf_point, Pl1, Pl2);
|
||||
Project(ProjectedNormal, Normal, Pl1, Pl2);
|
||||
}
|
||||
|
||||
void G4Axis2Placement3D::ComputeNormal()
|
||||
{
|
||||
|
||||
if(dir == axis)
|
||||
Normal = dir;
|
||||
else
|
||||
{
|
||||
Normal.X(dir.Y()*axis.Z() - dir.Z()*axis.Y());
|
||||
Normal.Y(dir.X()*axis.Z()- dir.Z()*axis.X());
|
||||
Normal.Z(dir.X()*axis.Y() - dir.Y()*axis.X());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
G4Point3d G4Axis2Placement3D::EvaluateIntersection(register const G4Ray& rray)
|
||||
{
|
||||
|
||||
// s is solution, line is p + tq, n is G4Plane Normal, r is point on G4Plane
|
||||
// all parameters are pointers to arrays of three elements
|
||||
|
||||
register G4double a, b, t;
|
||||
register const G4ThreeVec& RayDir = rray.GetDir();
|
||||
register const G4Point3d& RayStart = rray.GetStart();
|
||||
G4double dirx = RayDir.X();
|
||||
G4double diry = RayDir.Y();
|
||||
G4double dirz = RayDir.Z();
|
||||
b = Normal.X() * dirx + Normal.Y() * diry + Normal.Z() * dirz;
|
||||
|
||||
if (fabs(b) < 0.001)//== 0.0) // or some better test involving a small positive e
|
||||
// if (b == 0.0) // or some better test involving a small positive e
|
||||
{
|
||||
// G4cout << "\nLine is parallel to G4Plane.No Hit.";
|
||||
G4Point3d hit_point( kInfinity, kInfinity, kInfinity);
|
||||
return hit_point;
|
||||
}
|
||||
G4double startx = RayStart.X();
|
||||
G4double starty = RayStart.Y();
|
||||
G4double startz = RayStart.Z();
|
||||
|
||||
a = Normal.X() * (srf_point.X() - startx) + Normal.Y() * (srf_point.Y() - starty)
|
||||
+ Normal.Z() * (srf_point.Z() - startz);
|
||||
|
||||
t = a/b;
|
||||
|
||||
// substitute t into line equation
|
||||
// to calculate final solution
|
||||
G4Point3d hit_point(startx + t * dirx,starty + t * diry,startz + t * dirz);
|
||||
|
||||
// G4cout << "\nPLANE HIT POINT :" << hit_point.X() << " " << hit_point.Y() << " " << hit_point.Z();
|
||||
return hit_point;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,98 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4BREPSolidBox.cc,v 2.3 1998/10/20 16:33:37 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4BREPSolidBox.hh"
|
||||
#include "G4FPlane.hh"
|
||||
#include "G4Point3DVector.hh"
|
||||
|
||||
G4BREPSolidBox::G4BREPSolidBox(G4String name,
|
||||
const G4Point3D& Pt1,
|
||||
const G4Point3D& Pt2,
|
||||
const G4Point3D& Pt3,
|
||||
const G4Point3D& Pt4,
|
||||
const G4Point3D& Pt5,
|
||||
const G4Point3D& Pt6,
|
||||
const G4Point3D& Pt7,
|
||||
const G4Point3D& Pt8): G4BREPSolid(name)
|
||||
{
|
||||
nb_of_surfaces=6;
|
||||
active=1;PlaneSolid=1;
|
||||
SurfaceVec = new G4Surface*[6];
|
||||
G4Point3DVector PVec(4);
|
||||
|
||||
PVec[0] = Pt1;
|
||||
PVec[1] = Pt2;
|
||||
PVec[2] = Pt3;
|
||||
PVec[3] = Pt4;
|
||||
SurfaceVec[0] = new G4FPlane(&PVec);
|
||||
|
||||
PVec[2] = Pt6;
|
||||
PVec[3] = Pt5;
|
||||
SurfaceVec[1] = new G4FPlane(&PVec);
|
||||
|
||||
PVec[0] = Pt2;
|
||||
PVec[1] = Pt6;
|
||||
PVec[2] = Pt7;
|
||||
PVec[3] = Pt3;
|
||||
SurfaceVec[2] = new G4FPlane(&PVec);
|
||||
|
||||
PVec[0] = Pt3;
|
||||
PVec[1] = Pt7;
|
||||
PVec[2] = Pt8;
|
||||
PVec[3] = Pt4;
|
||||
SurfaceVec[3] = new G4FPlane(&PVec);
|
||||
|
||||
PVec[0] = Pt1;
|
||||
PVec[1] = Pt5;
|
||||
PVec[2] = Pt8;
|
||||
PVec[3] = Pt4;
|
||||
SurfaceVec[4] = new G4FPlane(&PVec);
|
||||
|
||||
PVec[0] = Pt5;
|
||||
PVec[1] = Pt6;
|
||||
PVec[2] = Pt7;
|
||||
PVec[3] = Pt8;
|
||||
SurfaceVec[5] = new G4FPlane(&PVec);
|
||||
|
||||
Initialize();
|
||||
|
||||
}
|
||||
|
||||
|
||||
EInside G4BREPSolidBox::Inside(register const G4ThreeVector& Pt) const
|
||||
{
|
||||
G4Point3D Point(Pt);
|
||||
|
||||
// Get the bounding box extent
|
||||
G4Point3D min = bbox->GetBoxMin();
|
||||
min = min + -(0.5*kCarTolerance);
|
||||
|
||||
G4Point3D max = bbox->GetBoxMax();
|
||||
max = max + (0.5*kCarTolerance);
|
||||
|
||||
if( (Point.x() < min.x() || Point.x() > max.x()) ||
|
||||
(Point.y() < min.y() || Point.y() > max.y()) ||
|
||||
(Point.z() < min.z() || Point.z() > max.z()) )
|
||||
return kOutside;
|
||||
|
||||
if( (Point.x() > min.x() && Point.x() < max.x())&&
|
||||
(Point.y() > min.y() && Point.y() < max.y())&&
|
||||
(Point.z() > min.z() && Point.z() < max.z()) )
|
||||
return kInside;
|
||||
|
||||
return kSurface;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4BREPSolidCone.cc,v 2.5 1998/10/29 17:49:33 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
|
||||
#include "G4BREPSolidCone.hh"
|
||||
#include "G4FPlane.hh"
|
||||
#include "G4FConicalSurface.hh"
|
||||
#include "G4FCylindricalSurface.hh"
|
||||
#include "G4CircularCurve.hh"
|
||||
|
||||
G4BREPSolidCone::G4BREPSolidCone(G4String name,
|
||||
const G4ThreeVector& origin,
|
||||
const G4ThreeVector& axis,
|
||||
const G4ThreeVector& direction,
|
||||
const G4double length,
|
||||
const G4double radius,
|
||||
const G4double large_radius):G4BREPSolid(name)
|
||||
|
||||
{
|
||||
SurfaceVec = new G4Surface*[3];
|
||||
G4Point3D ArcStart1 = origin + (radius*direction);
|
||||
G4Vector3D tmpaxis(axis);
|
||||
G4Vector3D tmporigin(origin);
|
||||
G4Point3D paska;
|
||||
|
||||
paska= origin + (length*tmpaxis);
|
||||
G4Point3D origin2(paska.x(), paska.y(), paska.z());
|
||||
|
||||
paska= origin2 + (large_radius*tmpaxis);
|
||||
G4Point3D ArcStart2(paska.x(), paska.y(), paska.z());
|
||||
|
||||
G4Ray::Vcross(tmpaxis, axis, direction);
|
||||
G4ThreeVector axis2(tmpaxis.x(),tmpaxis.y(), tmpaxis.z());
|
||||
|
||||
G4CurveVector CVec;
|
||||
G4CircularCurve* tmp;
|
||||
|
||||
tmp = new G4CircularCurve();
|
||||
tmp->Init(G4Axis2Placement3D(direction, axis2, origin) , large_radius);
|
||||
tmp->SetBounds(ArcStart1, ArcStart1);
|
||||
CVec.insert(tmp);
|
||||
|
||||
tmp = new G4CircularCurve();
|
||||
tmp->Init(G4Axis2Placement3D(direction, axis2, origin2), large_radius);
|
||||
tmp->SetBounds(ArcStart2, ArcStart2);
|
||||
CVec.insert(tmp);
|
||||
|
||||
SurfaceVec[0] = new G4FConicalSurface(tmporigin, axis,
|
||||
length, radius, large_radius);
|
||||
SurfaceVec[0]->SetBoundaries(&CVec);
|
||||
|
||||
// new G4AdvancedFace("G4FConicalSurface", tmporigin, direction,
|
||||
// axis, CVec, 1, 0,0,length, radius, large_radius);
|
||||
|
||||
// Create end planes & boundaries for cone solid
|
||||
G4CurveVector CVec2;
|
||||
tmp = new G4CircularCurve();
|
||||
tmp->Init(G4Axis2Placement3D(direction, axis2, origin), radius);
|
||||
tmp->SetBounds(ArcStart1, ArcStart1);
|
||||
CVec2.insert(tmp);
|
||||
|
||||
SurfaceVec[1] = new G4FPlane(tmpaxis, direction, origin2);
|
||||
//new G4AdvancedFace("G4FPlane" , origin2, direction, tmpaxis, CVec2, 1);
|
||||
SurfaceVec[1]->SetBoundaries(&CVec2);
|
||||
|
||||
CVec2[0] = tmp = new G4CircularCurve();
|
||||
tmp->Init(G4Axis2Placement3D(direction, axis2, origin2), large_radius);
|
||||
tmp->SetBounds(ArcStart2, ArcStart2);
|
||||
|
||||
SurfaceVec[2] = new G4FPlane(tmpaxis, direction, origin);
|
||||
//new G4AdvancedFace("G4FPlane", origin, direction, tmpaxis, CVec2, 1);
|
||||
SurfaceVec[2]->SetBoundaries(&CVec2);
|
||||
|
||||
nb_of_surfaces = 3;
|
||||
active=1;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void G4BREPSolidCone::Initialize()
|
||||
{
|
||||
// Calc bounding box for solids and surfaces
|
||||
// Convert concave planes to convex
|
||||
ShortestDistance=1000000;
|
||||
CheckSurfaceNormals();
|
||||
if(!Box || !AxisBox)
|
||||
IsConvex();
|
||||
CalcBBoxes();
|
||||
}
|
||||
|
||||
|
||||
EInside G4BREPSolidCone::Inside(register const G4ThreeVector& Pt) const
|
||||
{
|
||||
G4double dist1 = SurfaceVec[0]->HowNear(Pt);
|
||||
G4double dist2 = SurfaceVec[1]->ClosestDistanceToPoint(Pt);
|
||||
G4double dist3 = SurfaceVec[2]->ClosestDistanceToPoint(Pt);
|
||||
if(dist1 > dist2) dist1 = dist2;
|
||||
if(dist1 > dist3) dist1 = dist3;
|
||||
if(dist1 > 0) return kInside;
|
||||
if(dist1 < 0) return kOutside;
|
||||
return kSurface;
|
||||
}
|
||||
|
||||
G4ThreeVector G4BREPSolidCone::SurfaceNormal(const G4ThreeVector& Pt) const
|
||||
{
|
||||
G4Vector3D n = SurfaceVec[0]->Normal(Pt);
|
||||
G4ThreeVector norm(n.x(), n.y(), n.z());
|
||||
return norm;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidCone::DistanceToIn(const G4ThreeVector& Pt) const
|
||||
{
|
||||
G4double dist1 = fabs(SurfaceVec[0]->HowNear(Pt));
|
||||
G4double dist2 = fabs(SurfaceVec[1]->ClosestDistanceToPoint(Pt));
|
||||
G4double dist3 = fabs(SurfaceVec[2]->ClosestDistanceToPoint(Pt));
|
||||
if(dist1 > dist2) dist1 = dist2;
|
||||
if(dist1 > dist3) dist1 = dist3;
|
||||
return dist1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidCone::DistanceToIn(register const G4ThreeVector& Pt,
|
||||
register const G4ThreeVector& V) const
|
||||
{
|
||||
Reset();
|
||||
G4Vector3D Pttmp(Pt);
|
||||
G4Vector3D Vtmp(V);
|
||||
// G4double kInfinity = 10e20;
|
||||
G4Ray r(Pttmp, Vtmp);
|
||||
|
||||
if(SurfaceVec[0]->Intersect( r ))
|
||||
{
|
||||
ShortestDistance = SurfaceVec[0]->Distance();
|
||||
return ShortestDistance;
|
||||
}
|
||||
return kInfinity;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidCone::DistanceToOut(register const G4ThreeVector& Pt,
|
||||
register const G4ThreeVector& V,
|
||||
const G4bool calcNorm,
|
||||
G4bool *validNorm,
|
||||
G4ThreeVector *n) const
|
||||
{
|
||||
if(validNorm)
|
||||
*validNorm = false;
|
||||
Reset();
|
||||
|
||||
G4Vector3D Pttmp(Pt);
|
||||
G4Vector3D Vtmp(V);
|
||||
// G4double kInfinity = 10e20;
|
||||
|
||||
G4Ray r(Pttmp, Vtmp);
|
||||
if(SurfaceVec[0]->Intersect( r ))
|
||||
{
|
||||
ShortestDistance = SurfaceVec[0]->Distance();
|
||||
return ShortestDistance;
|
||||
}
|
||||
return kInfinity;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidCone::DistanceToOut(const G4ThreeVector& Pt) const
|
||||
{
|
||||
G4double dist1 = fabs(SurfaceVec[0]->HowNear(Pt));
|
||||
G4double dist2 = fabs(SurfaceVec[1]->ClosestDistanceToPoint(Pt));
|
||||
G4double dist3 = fabs(SurfaceVec[2]->ClosestDistanceToPoint(Pt));
|
||||
if(dist1 > dist2) dist1 = dist2;
|
||||
if(dist1 > dist3) dist1 = dist3;
|
||||
return dist1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4BREPSolidCylinder.cc,v 2.6 1998/11/27 17:41:38 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
|
||||
#include "G4BREPSolidCylinder.hh"
|
||||
#include "G4CircularCurve.hh"
|
||||
#include "G4FPlane.hh"
|
||||
#include "G4FCylindricalSurface.hh"
|
||||
|
||||
|
||||
G4BREPSolidCylinder::G4BREPSolidCylinder(G4String name,
|
||||
const G4ThreeVector& origin,
|
||||
const G4ThreeVector& axis,
|
||||
const G4ThreeVector& direction,
|
||||
const G4double& radius,
|
||||
const G4double& length)
|
||||
:G4BREPSolid(name)
|
||||
{
|
||||
SurfaceVec = new G4Surface*[3];
|
||||
G4CurveVector cv;
|
||||
G4CircularCurve* tmp;
|
||||
|
||||
|
||||
|
||||
// Creation of the cylindrical surface
|
||||
SurfaceVec[0] = new G4FCylindricalSurface(origin, axis, radius , length);
|
||||
//SurfaceVec[0]->SetBoundaries(&cv);
|
||||
//cv.clear();
|
||||
|
||||
|
||||
// Creation of the first circlular surface, which origin is origin
|
||||
G4Point3D ArcStart1 = origin + ( radius*direction );
|
||||
G4Vector3D axis1 = axis.cross( direction );
|
||||
|
||||
tmp = new G4CircularCurve;
|
||||
tmp->Init( G4Axis2Placement3D(direction, axis1, origin), radius );
|
||||
tmp->SetBounds(ArcStart1, ArcStart1);
|
||||
cv.insert(tmp);
|
||||
|
||||
SurfaceVec[1] = new G4FPlane(direction, axis1, origin);
|
||||
SurfaceVec[1]->SetBoundaries(&cv);
|
||||
cv.clear();
|
||||
|
||||
|
||||
// Creation of the second circlular surfac
|
||||
G4Point3D origin2 = origin + ( length*axis );
|
||||
G4Point3D ArcStart2 = origin2 + ( radius*direction );
|
||||
G4Vector3D axis2 = axis1;
|
||||
|
||||
tmp = new G4CircularCurve;
|
||||
tmp->Init( G4Axis2Placement3D(direction, axis2, origin2), radius);
|
||||
tmp->SetBounds(ArcStart2, ArcStart2);
|
||||
cv.insert(tmp);
|
||||
|
||||
SurfaceVec[2] = new G4FPlane(direction, axis2, origin2);
|
||||
SurfaceVec[2]->SetBoundaries(&cv);
|
||||
cv.clear();
|
||||
|
||||
|
||||
nb_of_surfaces = 3;
|
||||
active=1;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,641 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4BREPSolidPCone.cc,v 2.27 1998/12/11 13:40:43 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4BREPSolidPCone.hh"
|
||||
#include "G4FCylindricalSurface.hh"
|
||||
#include "G4FConicalSurface.hh"
|
||||
#include "G4CircularCurve.hh"
|
||||
#include "G4FPlane.hh"
|
||||
|
||||
|
||||
G4BREPSolidPCone::G4BREPSolidPCone(G4String name,
|
||||
const G4double start_angle,
|
||||
const G4double opening_angle,
|
||||
const int num_z_planes, // sections,
|
||||
const G4double z_start,
|
||||
const G4double z_values[],
|
||||
const G4double RMIN[],
|
||||
const G4double RMAX[]
|
||||
): G4BREPSolid(name)
|
||||
|
||||
{
|
||||
const int sections= num_z_planes-1;
|
||||
nb_of_surfaces = 2*sections+2;
|
||||
SurfaceVec = new G4Surface*[nb_of_surfaces];
|
||||
G4ThreeVector Axis(0,0,1);
|
||||
G4ThreeVector Origin(0,0,z_start);
|
||||
G4double Length;
|
||||
G4ThreeVector LocalOrigin(0,0,z_start);
|
||||
G4int a, b = 0;
|
||||
|
||||
G4ThreeVector PlaneAxis(0, 0, 1);
|
||||
G4ThreeVector PlaneDir (0, 1, 0);
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Temporary
|
||||
for (G4int x = 0; x <= sections; x++)
|
||||
{
|
||||
G4cout<<"Z"<<x<<"="<<z_values[x];
|
||||
G4cout<<" Rmin"<<x<<"="<<RMIN[x];
|
||||
G4cout<<" Rmax"<<x<<"="<<RMAX[x]<<endl;
|
||||
}
|
||||
|
||||
G4cout<<"start angle ="<<start_angle<<endl;
|
||||
G4cout<<"open angle ="<<opening_angle<<endl;
|
||||
G4cout<<"zstart ="<<z_start<<endl;
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Test the validity of the R values
|
||||
|
||||
// RMIN[0] and RMIN[num_z_planes-1] cannot be = 0
|
||||
// when RMIN[0] or RMIN[num_z_planes-1] are = 0
|
||||
if( ((RMIN[0] == 0) && (RMAX[0] == 0)) ||
|
||||
((RMIN[num_z_planes-1] == 0) && (RMAX[num_z_planes-1] == 0)) )
|
||||
G4Exception("RMIN at the extremities can not be nul when RMAX = 0");
|
||||
|
||||
// only RMAX[0] and RMAX[num_z_planes-1] can be = 0
|
||||
for(a = 1; a < num_z_planes-1; a++)
|
||||
if (RMAX[a] == 0)
|
||||
G4Exception("RMAX inside the solid can not be nul");
|
||||
|
||||
// RMAX[a] must be greater than RMIN[a]
|
||||
for(a = 0; a < num_z_planes; a++)
|
||||
if (RMIN[a] >= RMAX[a])
|
||||
G4Exception("RMAX must be greater than RMIN");
|
||||
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Create cylindrical et conical surfaces
|
||||
|
||||
for(a=0; a<sections; a++)
|
||||
{
|
||||
// Surface length
|
||||
Length = z_values[a+1] - z_values[a];
|
||||
|
||||
if (Length == 0)
|
||||
{
|
||||
// The surface to create is planar
|
||||
|
||||
G4double R1, R2;
|
||||
// test where is the plane surface
|
||||
if(RMAX[a] != RMAX[a+1])
|
||||
{
|
||||
R1 = RMAX[a];
|
||||
R2 = RMAX[a+1];
|
||||
}
|
||||
else if(RMIN[a] != RMIN[a+1])
|
||||
{
|
||||
R1 = RMIN[a];
|
||||
R2 = RMIN[a+1];
|
||||
}
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in construction of G4BREPSolidPCone: "
|
||||
<< "Exactly the same z, rmin and rmax given for "
|
||||
<< "consecutive indices, " << a << " and " << a+1 << endl;
|
||||
// G4Exception("G4BREPSolidPCone constructor: Error in parameter values");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create plane surface
|
||||
G4Point3D ArcStart1 = LocalOrigin + (R1*PlaneDir);
|
||||
G4Point3D ArcStart2 = LocalOrigin + (R2*PlaneDir);
|
||||
|
||||
G4CurveVector cv1;
|
||||
G4CircularCurve *tmp1, *tmp2;
|
||||
|
||||
if(R1 != 0)
|
||||
{
|
||||
tmp1 = new G4CircularCurve;
|
||||
tmp1->Init(G4Axis2Placement3D(PlaneDir, PlaneAxis, LocalOrigin), R1);
|
||||
tmp1->SetBounds(ArcStart1, ArcStart1);
|
||||
if(R1>R2)
|
||||
tmp1->SetSameSense(1);
|
||||
else
|
||||
tmp1->SetSameSense(0);
|
||||
|
||||
cv1.append(tmp1);
|
||||
}
|
||||
|
||||
if(R2 != 0)
|
||||
{
|
||||
tmp2 = new G4CircularCurve;
|
||||
tmp2->Init(G4Axis2Placement3D(PlaneDir, PlaneAxis, LocalOrigin), R2);
|
||||
tmp2->SetBounds(ArcStart2, ArcStart2);
|
||||
if(R1>R2)
|
||||
tmp2->SetSameSense(0);
|
||||
else
|
||||
tmp2->SetSameSense(1);
|
||||
cv1.append(tmp2);
|
||||
}
|
||||
|
||||
SurfaceVec[b] = new G4FPlane(PlaneDir, PlaneAxis, LocalOrigin);
|
||||
SurfaceVec[b]->SetBoundaries(&cv1);
|
||||
|
||||
nb_of_surfaces--;
|
||||
b++;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// The surface to create is conical or cylindrical
|
||||
|
||||
// Inner PCone
|
||||
if(RMIN[a] != RMIN[a+1])
|
||||
{
|
||||
// Create cone
|
||||
if(RMIN[a] > RMIN[a+1])
|
||||
{
|
||||
G4Vector3D ConeOrigin = LocalOrigin ;
|
||||
|
||||
SurfaceVec[b] = new G4FConicalSurface(ConeOrigin, Axis, Length,
|
||||
RMIN[a+1], RMIN[a]);
|
||||
}
|
||||
else
|
||||
{
|
||||
G4Vector3D Axis2 = (-1*Axis);
|
||||
G4Vector3D LocalOrigin2 = LocalOrigin + (Length*Axis);
|
||||
G4Vector3D ConeOrigin = LocalOrigin2 ;
|
||||
|
||||
SurfaceVec[b] = new G4FConicalSurface(ConeOrigin, Axis2,
|
||||
Length, RMIN[a], RMIN[a+1]);
|
||||
}
|
||||
|
||||
b++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (RMIN[a] == 0)
|
||||
{
|
||||
// Do not create any surface
|
||||
// and decrease nb_of_surfaces
|
||||
nb_of_surfaces--;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create cylinder
|
||||
G4Vector3D CylOrigin = LocalOrigin ;
|
||||
|
||||
SurfaceVec[b] = new G4FCylindricalSurface(CylOrigin, Axis,
|
||||
RMIN[a], Length );
|
||||
b++;
|
||||
}
|
||||
}
|
||||
|
||||
// Outer PCone
|
||||
if(RMAX[a] != RMAX[a+1])
|
||||
{
|
||||
// Create cone
|
||||
if(RMAX[a] > RMAX[a+1])
|
||||
{
|
||||
G4Vector3D ConeOrigin = LocalOrigin ;
|
||||
|
||||
SurfaceVec[b] = new G4FConicalSurface(ConeOrigin, Axis,
|
||||
Length, RMAX[a+1], RMAX[a]);
|
||||
}
|
||||
else
|
||||
{
|
||||
G4Vector3D Axis2 = (-1*Axis);
|
||||
G4Vector3D LocalOrigin2 = LocalOrigin + (Length*Axis);
|
||||
G4Vector3D ConeOrigin = LocalOrigin2 ;
|
||||
|
||||
SurfaceVec[b] = new G4FConicalSurface(ConeOrigin, Axis2,
|
||||
Length, RMAX[a], RMAX[a+1]);
|
||||
}
|
||||
|
||||
b++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create cylinder
|
||||
G4Vector3D CylOrigin = LocalOrigin ;
|
||||
|
||||
if (RMAX[a] == 0)
|
||||
{
|
||||
// Do not create any surface
|
||||
// and decrease nb_of_surfaces
|
||||
nb_of_surfaces--;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create cylinder
|
||||
G4Vector3D CylOrigin = LocalOrigin ;
|
||||
|
||||
SurfaceVec[b] = new G4FCylindricalSurface(CylOrigin, Axis,
|
||||
RMAX[a], Length );
|
||||
b++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move surface origin to next section
|
||||
LocalOrigin = LocalOrigin + (Length*Axis);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Create two end planes
|
||||
|
||||
// Create start G4Plane & boundaries
|
||||
G4Point3D ArcStart1a = Origin + (RMIN[0]*PlaneDir);
|
||||
G4Point3D ArcStart1b = Origin + (RMAX[0]*PlaneDir);
|
||||
|
||||
G4CurveVector cv;
|
||||
G4CircularCurve* tmp;
|
||||
|
||||
tmp = new G4CircularCurve;
|
||||
tmp->Init(G4Axis2Placement3D(PlaneDir, PlaneAxis, Origin), RMIN[0]);
|
||||
tmp->SetBounds(ArcStart1a, ArcStart1a);
|
||||
tmp->SetSameSense(0);
|
||||
cv.append(tmp);
|
||||
|
||||
tmp = new G4CircularCurve;
|
||||
tmp->Init(G4Axis2Placement3D(PlaneDir, PlaneAxis, Origin), RMAX[0]);
|
||||
tmp->SetBounds(ArcStart1b, ArcStart1b);
|
||||
tmp->SetSameSense(1);
|
||||
cv.append(tmp);
|
||||
|
||||
SurfaceVec[nb_of_surfaces-2] = new G4FPlane(PlaneDir, PlaneAxis, Origin);
|
||||
SurfaceVec[nb_of_surfaces-2]->SetBoundaries(&cv);
|
||||
|
||||
|
||||
// Create end G4Plane & boundaries
|
||||
G4Point3D ArcStart2a = LocalOrigin + (RMIN[sections]*PlaneDir);
|
||||
G4Point3D ArcStart2b = LocalOrigin + (RMAX[sections]*PlaneDir);
|
||||
|
||||
cv.clear();
|
||||
|
||||
tmp = new G4CircularCurve;
|
||||
tmp->Init(G4Axis2Placement3D(PlaneDir, PlaneAxis, LocalOrigin),
|
||||
RMIN[sections]);
|
||||
tmp->SetBounds(ArcStart2a, ArcStart2a);
|
||||
tmp->SetSameSense(0);
|
||||
cv.append(tmp);
|
||||
|
||||
tmp = new G4CircularCurve;
|
||||
tmp->Init(G4Axis2Placement3D(PlaneDir, PlaneAxis, LocalOrigin),
|
||||
RMAX[sections]);
|
||||
tmp->SetBounds(ArcStart2b, ArcStart2b);
|
||||
tmp->SetSameSense(1);
|
||||
cv.append(tmp);
|
||||
|
||||
SurfaceVec[nb_of_surfaces-1]= new G4FPlane(PlaneDir, PlaneAxis, LocalOrigin);
|
||||
SurfaceVec[nb_of_surfaces-1]->SetBoundaries(&cv);
|
||||
|
||||
|
||||
active=1;
|
||||
Initialize();
|
||||
|
||||
// Store the original parameters, to be used in visualisation
|
||||
original_parameters.Start_angle= start_angle;
|
||||
original_parameters.Opening_angle= opening_angle;
|
||||
original_parameters.Num_z_planes= num_z_planes;
|
||||
// original_parameters.z_start= z_start;
|
||||
original_parameters.Z_values= new G4double[num_z_planes];
|
||||
original_parameters.Rmin= new G4double[nb_of_surfaces];
|
||||
original_parameters.Rmax= new G4double[nb_of_surfaces];
|
||||
|
||||
for(int is=0;is<num_z_planes;is++)
|
||||
{
|
||||
original_parameters.Z_values[is]= z_values[is];
|
||||
original_parameters.Rmin[is]= RMIN[is];
|
||||
original_parameters.Rmax[is]= RMAX[is];
|
||||
}
|
||||
|
||||
// z_values[0] should be equal to z_start, for consistency
|
||||
// with what the constructor does.
|
||||
// Otherwise the z_values that are given are used
|
||||
// shifted by z_values[0] - z_start:
|
||||
// (because z_values are only used in
|
||||
// line 26: Length = z_values[a+1] - z_values[a];
|
||||
// ) // JA Apr 2, 97
|
||||
|
||||
/*
|
||||
if( z_values[0] != z_start )
|
||||
{
|
||||
G4cerr << "ERROR in creating G4BREPSolidPCone: "
|
||||
<< " z_values[0]= " << z_values[0] << " is not equal to "
|
||||
<< " z_start= " , z_start;
|
||||
// G4Exception(" Error in creating G4BREPSolidPCone: z_values[0] must be equal to z_start" );
|
||||
original_parameters.Z_values[0]= z_start;
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
G4BREPSolidPCone::~G4BREPSolidPCone()
|
||||
{
|
||||
delete[] original_parameters.Z_values;
|
||||
delete[] original_parameters.Rmin;
|
||||
delete[] original_parameters.Rmax;
|
||||
}
|
||||
|
||||
|
||||
void G4BREPSolidPCone::Initialize()
|
||||
{
|
||||
// Calc bounding box for solids and surfaces
|
||||
// Convert concave planes to convex
|
||||
ShortestDistance=1000000;
|
||||
CheckSurfaceNormals();
|
||||
|
||||
if(!Box || !AxisBox)
|
||||
IsConvex();
|
||||
|
||||
CalcBBoxes();
|
||||
}
|
||||
|
||||
|
||||
EInside G4BREPSolidPCone::Inside(register const G4ThreeVector& Pt) const
|
||||
{
|
||||
// Check if point lies between end planes of PCone
|
||||
G4double dist1 = SurfaceVec[nb_of_surfaces-1]->ClosestDistanceToPoint(Pt);
|
||||
G4double dist2 = SurfaceVec[nb_of_surfaces-2]->ClosestDistanceToPoint(Pt);
|
||||
|
||||
if((dist1 < -kCarTolerance && dist2 <-kCarTolerance)||
|
||||
(dist1 > kCarTolerance && dist2 >kCarTolerance) )
|
||||
return kOutside;
|
||||
|
||||
G4Vector3D v(1,0,0);
|
||||
G4double Dist;
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
G4Vector3D Pttmp(Pt);
|
||||
G4Vector3D Vtmp(v);
|
||||
G4Ray r(Pttmp, Vtmp);
|
||||
TestSurfaceBBoxes(r);
|
||||
G4int hits=0;
|
||||
|
||||
for(G4int a=0; a < nb_of_surfaces; a++)
|
||||
{
|
||||
if(SurfaceVec[a]->Active())
|
||||
if(SurfaceVec[a]->Intersect(r))
|
||||
{
|
||||
if(SurfaceVec[a]->Distance() < kCarTolerance)
|
||||
return kSurface;
|
||||
|
||||
hits++;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the surfaces to active again
|
||||
for(G4int b=0; b < nb_of_surfaces; b++)
|
||||
SurfaceVec[b]->Reset();
|
||||
|
||||
|
||||
if(hits&1)
|
||||
return kInside;
|
||||
|
||||
return kOutside;
|
||||
}
|
||||
|
||||
|
||||
G4ThreeVector G4BREPSolidPCone::SurfaceNormal(const G4ThreeVector& Pt) const
|
||||
{
|
||||
G4cout<<" SurfaceNormal() of G4BREPSolidPCone modified by L. Broglia";
|
||||
|
||||
G4Vector3D Ptv = Pt;
|
||||
G4Vector3D n(0,0,0);
|
||||
G4double zCoord = Pt.z();
|
||||
const G4int num_z_planes = original_parameters.Num_z_planes;
|
||||
G4int iplane;
|
||||
|
||||
// Find the appropriate z "slice"
|
||||
//
|
||||
for(iplane=0; iplane< num_z_planes; iplane++)
|
||||
if ( (zCoord < original_parameters.Z_values[iplane+1]) &&
|
||||
(zCoord >= original_parameters.Z_values[iplane]) )
|
||||
break;
|
||||
|
||||
G4Vector3D norm;
|
||||
G4Ray r( Pt, G4Vector3D(1, 0, 0) );
|
||||
|
||||
// We must find which is the correct surface, the inner or the outer one
|
||||
// (if they exist)
|
||||
for(iplane = 0; iplane < num_z_planes; iplane++)
|
||||
{
|
||||
// check if the point is on the surface
|
||||
if(SurfaceVec[iplane]->Intersect(r))
|
||||
if(SurfaceVec[iplane]->Distance() < kCarTolerance)
|
||||
// the point is on the surface
|
||||
break;
|
||||
}
|
||||
|
||||
norm = SurfaceVec[iplane]->SurfaceNormal(Pt);
|
||||
|
||||
n = G4ThreeVector ( norm.x(), norm.y(), norm.z());
|
||||
n = n.unit();
|
||||
|
||||
/*
|
||||
if ( SurfaceVec[innerSurface]->WithinBoundary(Ptv) == 1 )
|
||||
{
|
||||
norm = SurfaceVec[ innersurface ]->SurfaceNormal(Pt);
|
||||
}
|
||||
else if ( SurfaceVec[outerSurface]->WithinBoundary(Ptv) == 1 )
|
||||
{
|
||||
norm = SurfaceVec[ outerSurface]->SurfaceNormal(Pt);
|
||||
}
|
||||
|
||||
// Check if it is on one of the top/bottom planes
|
||||
//
|
||||
if ( fabs(zCoord - original_parameters.Z_values[0]) < kCarTolerance )
|
||||
{
|
||||
// n = G4ThreeVector (0., 0., sign( original_parameters.Z_values[0]
|
||||
// -original_parameters.Z_values[1]) );
|
||||
|
||||
n = G4ThreeVector (0., 0., original_parameters.Z_values[0]
|
||||
-original_parameters.Z_values[1] );
|
||||
n = n.unit();
|
||||
}
|
||||
else if (fabs(zCoord - original_parameters.Z_values[num_z_planes-1]) <
|
||||
kCarTolerance)
|
||||
{
|
||||
n = G4ThreeVector(0., 0., original_parameters.Z_values[num_z_planes]
|
||||
-original_parameters.Z_values[num_z_planes-1] );
|
||||
n = n.unit();
|
||||
}
|
||||
*/
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidPCone::DistanceToIn(const G4ThreeVector& Pt) const
|
||||
{
|
||||
G4double *dists = new G4double[nb_of_surfaces];
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
G4int a;
|
||||
|
||||
for(a=0; a< nb_of_surfaces;a++)
|
||||
dists[a] = fabs(SurfaceVec[a]->HowNear(Pt));
|
||||
|
||||
G4double Dist=kInfinity;
|
||||
|
||||
for(a=0; a< nb_of_surfaces;a++)
|
||||
if(Dist>dists[a]) Dist = dists[a];
|
||||
|
||||
delete[] dists;
|
||||
|
||||
// Set the surfaces to active again
|
||||
for(G4int b=0; b < nb_of_surfaces; b++)
|
||||
SurfaceVec[b]->Reset();
|
||||
|
||||
return Dist;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidPCone::DistanceToIn(register const G4ThreeVector& Pt,
|
||||
register const G4ThreeVector& V) const
|
||||
{
|
||||
int a;
|
||||
Reset();
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
G4Vector3D Pttmp(Pt);
|
||||
G4Vector3D Vtmp(V);
|
||||
// G4double kInfinity = ;
|
||||
G4Ray r(Pttmp, Vtmp);
|
||||
TestSurfaceBBoxes(r);
|
||||
ShortestDistance = kInfinity;
|
||||
|
||||
for(a=0; a< nb_of_surfaces;a++)
|
||||
{
|
||||
if(SurfaceVec[a]->Active())
|
||||
if(SurfaceVec[a]->Intersect( r ))
|
||||
{
|
||||
if(ShortestDistance > SurfaceVec[a]->Distance())
|
||||
if(SurfaceVec[a]->Distance()> halfTolerance)
|
||||
{
|
||||
ShortestDistance = SurfaceVec[a]->Distance();
|
||||
}
|
||||
else
|
||||
{
|
||||
G4Vector3D Norm = SurfaceVec[a]->SurfaceNormal(Pttmp);
|
||||
if((Norm * Vtmp)<0)
|
||||
ShortestDistance = SurfaceVec[a]->Distance();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the surfaces to active again
|
||||
for(G4int b=0; b < nb_of_surfaces; b++)
|
||||
SurfaceVec[b]->Reset();
|
||||
|
||||
if(ShortestDistance != kInfinity)
|
||||
return sqrt(ShortestDistance);
|
||||
|
||||
return kInfinity;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidPCone::DistanceToOut(register const G4ThreeVector& Pt,
|
||||
register const G4ThreeVector& V,
|
||||
const G4bool calcNorm,
|
||||
G4bool *validNorm,
|
||||
G4ThreeVector *n ) const
|
||||
{
|
||||
const G4double halfTolerance = kCarTolerance*0.5;
|
||||
G4Vector3D Ptv = Pt;
|
||||
G4double wb = 0.0;
|
||||
G4int a;
|
||||
|
||||
for( a=0; a< nb_of_surfaces-2; a++)
|
||||
{
|
||||
wb = fabs( SurfaceVec[a]->HowNear(Ptv) );
|
||||
|
||||
// If we are on a surface and exiting it return Zero
|
||||
if ( (wb < halfTolerance) && (V.dot(SurfaceVec[a]->Normal(Ptv))>0) )
|
||||
{
|
||||
return (0.0);
|
||||
}
|
||||
}
|
||||
|
||||
if(validNorm)
|
||||
*validNorm=false;
|
||||
|
||||
Reset();
|
||||
|
||||
G4Vector3D Pttmp(Pt);
|
||||
G4Vector3D Vtmp(V);
|
||||
|
||||
// G4double kInfinity = 10e20;
|
||||
G4Ray r(Pttmp, Vtmp);
|
||||
TestSurfaceBBoxes(r);
|
||||
ShortestDistance = kInfinity;
|
||||
|
||||
for(a=0; a< nb_of_surfaces;a++)
|
||||
if(SurfaceVec[a]->Active())
|
||||
if(SurfaceVec[a]->Intersect( r ))
|
||||
if(ShortestDistance > SurfaceVec[a]->Distance()&&
|
||||
SurfaceVec[a]->Distance()> halfTolerance)
|
||||
ShortestDistance = SurfaceVec[a]->Distance();
|
||||
|
||||
// Set the surfaces to active again
|
||||
for(G4int b=0; b < nb_of_surfaces; b++)
|
||||
SurfaceVec[b]->Reset();
|
||||
|
||||
if(ShortestDistance != kInfinity)
|
||||
return sqrt(ShortestDistance);
|
||||
|
||||
return kInfinity;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidPCone::DistanceToOut(const G4ThreeVector& Pt) const
|
||||
{
|
||||
int a;
|
||||
|
||||
G4double *dists = new G4double[nb_of_surfaces];
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
|
||||
for(a=0; a< nb_of_surfaces; a++)
|
||||
dists[a] = fabs(SurfaceVec[a]->HowNear(Pt));
|
||||
|
||||
G4double Dist=kInfinity;
|
||||
|
||||
for(a=0; a< nb_of_surfaces;a++)
|
||||
if( Dist>dists[a] ) Dist = dists[a];
|
||||
|
||||
// Set the surfaces to active again
|
||||
for(G4int b=0; b < nb_of_surfaces; b++)
|
||||
SurfaceVec[b]->Reset();
|
||||
|
||||
|
||||
// If we are on a surface, the return value Dist must be zero!
|
||||
delete[] dists;
|
||||
return Dist;
|
||||
}
|
||||
|
||||
|
||||
// In graphics_reps:
|
||||
|
||||
#include "G4Polyhedron.hh"
|
||||
|
||||
G4Polyhedron* G4BREPSolidPCone::CreatePolyhedron() const
|
||||
{
|
||||
return new G4PolyhedronPcon( original_parameters.Start_angle,
|
||||
original_parameters.Opening_angle,
|
||||
original_parameters.Num_z_planes,
|
||||
original_parameters.Z_values,
|
||||
original_parameters.Rmin,
|
||||
original_parameters.Rmax);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,484 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4BREPSolidPolyhedra.cc,v 2.11 1998/12/11 13:40:46 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
|
||||
#include "G4BREPSolidPolyhedra.hh"
|
||||
#include "G4FPlane.hh"
|
||||
|
||||
|
||||
G4BREPSolidPolyhedra::G4BREPSolidPolyhedra(G4String name,
|
||||
const G4double phi1,
|
||||
const G4double dphi,
|
||||
const int sides,
|
||||
const int num_z_planes,
|
||||
const G4double z_start,
|
||||
const G4double z_values[],
|
||||
const G4double RMIN[],
|
||||
const G4double RMAX[]
|
||||
) : G4BREPSolid(name)
|
||||
{
|
||||
const int sections= num_z_planes - 1;
|
||||
|
||||
if(dphi == 2*pi)
|
||||
nb_of_surfaces = 2*(sections * sides) + 2;
|
||||
else
|
||||
nb_of_surfaces = 2*(sections * sides) + 4;
|
||||
|
||||
|
||||
SurfaceVec = new G4Surface*[nb_of_surfaces];
|
||||
|
||||
G4Vector3D Axis(0,0,1);
|
||||
G4Vector3D YAxis(0,1,0);
|
||||
G4Vector3D TmpAxis;
|
||||
G4Point3D Origin(0,0,z_start);
|
||||
G4Point3D LocalOrigin(0,0,z_start);
|
||||
G4double Length;
|
||||
int Count =0;
|
||||
G4double PartAngle = (dphi - phi1)/sides;
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Temporary
|
||||
|
||||
for (G4int x = 0; x <= sections; x++)
|
||||
{
|
||||
cout<<"Z"<<x<<"="<<z_values[x];
|
||||
cout<<" Rmin"<<x<<"="<<RMIN[x];
|
||||
cout<<" Rmax"<<x<<"="<<RMAX[x]<<endl;
|
||||
}
|
||||
|
||||
cout<<"phi1 ="<<phi1<<endl;
|
||||
cout<<"dphi ="<<dphi<<endl;
|
||||
cout<<"sides ="<<sides<<endl;
|
||||
cout<<"zstart ="<<z_start<<endl;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
|
||||
for(G4int a=0;a<sections;a++)
|
||||
{
|
||||
TmpAxis= YAxis;
|
||||
TmpAxis.rotateZ(phi1);
|
||||
Length = z_values[a+1] - z_values[a];
|
||||
|
||||
// Create sides
|
||||
for(int b=0;b<sides;b++)
|
||||
{
|
||||
G4Point3DVector PointList(4);
|
||||
// Create inner side
|
||||
// Calc points for the planar surface boundary
|
||||
PointList[0] = LocalOrigin + (RMIN[a] * TmpAxis);
|
||||
PointList[1] = LocalOrigin + (Length*Axis) + (RMIN[a+1] * TmpAxis);
|
||||
TmpAxis.rotateZ(PartAngle);
|
||||
PointList[2] = LocalOrigin + (Length*Axis) + (RMIN[a+1] * TmpAxis);
|
||||
PointList[3] = LocalOrigin + (RMIN[a] * TmpAxis);
|
||||
SurfaceVec[Count] = new G4FPlane( &PointList);
|
||||
Count++;
|
||||
|
||||
// Rotate axis back for the other surface point calculation
|
||||
TmpAxis.rotateZ(-PartAngle);
|
||||
|
||||
// Calc points for the planar surface boundary
|
||||
G4Point3DVector PointList2(4);
|
||||
PointList2[0] = LocalOrigin + (RMAX[a] * TmpAxis);
|
||||
PointList2[1] = LocalOrigin + (Length*Axis) + (RMAX[a+1] * TmpAxis);
|
||||
TmpAxis.rotateZ(PartAngle);
|
||||
PointList2[2] = LocalOrigin + (Length*Axis) + (RMAX[a+1] * TmpAxis);
|
||||
PointList2[3] = LocalOrigin + (RMAX[a] * TmpAxis);
|
||||
SurfaceVec[Count] = new G4FPlane(&PointList2);
|
||||
Count++;
|
||||
}
|
||||
|
||||
LocalOrigin = LocalOrigin + (Length*Axis);
|
||||
}
|
||||
|
||||
// Create end planes
|
||||
|
||||
if(dphi == 2*pi)
|
||||
{
|
||||
// Create only end planes
|
||||
G4Point3DVector EndPointList(sides);
|
||||
G4Point3DVector InnerPointList(sides);
|
||||
G4Point3DVector EndPointList2(sides);
|
||||
G4Point3DVector InnerPointList2(sides);
|
||||
TmpAxis = YAxis;
|
||||
TmpAxis.rotateZ(phi1);
|
||||
TmpAxis.rotateZ(dphi);
|
||||
|
||||
for(int c=0;c<sides;c++)
|
||||
{
|
||||
// outer polyline for origin end
|
||||
EndPointList[c] = Origin + (RMAX[0] * TmpAxis);
|
||||
InnerPointList[c] = Origin + (RMIN[0] * TmpAxis);
|
||||
EndPointList2[c] = LocalOrigin + (RMAX[sections] * TmpAxis);
|
||||
InnerPointList2[c] = LocalOrigin + (RMIN[sections] * TmpAxis);
|
||||
TmpAxis.rotateZ(-PartAngle);
|
||||
}
|
||||
|
||||
SurfaceVec[nb_of_surfaces-2] =
|
||||
new G4FPlane(&EndPointList, &InnerPointList);
|
||||
|
||||
SurfaceVec[nb_of_surfaces-1] =
|
||||
new G4FPlane(&EndPointList2, &InnerPointList2);
|
||||
}
|
||||
else
|
||||
{
|
||||
TmpAxis = YAxis;
|
||||
TmpAxis.rotateZ(phi1);
|
||||
TmpAxis.rotateZ(dphi);
|
||||
|
||||
// Create end planes & two planes for the "missing" part
|
||||
G4Point3DVector EndPointList(sides+2);
|
||||
G4Point3DVector InnerPointList(sides+2);
|
||||
G4Point3DVector EndPointList2(sides+2);
|
||||
G4Point3DVector InnerPointList2(sides+2);
|
||||
TmpAxis = YAxis;
|
||||
|
||||
for(int c=0;c<sides+1;c++)
|
||||
{
|
||||
// outer polyline for origin end
|
||||
EndPointList[c] = Origin + (RMAX[0] * TmpAxis);
|
||||
InnerPointList[c] = Origin + (RMIN[0] * TmpAxis);
|
||||
EndPointList2[c] = LocalOrigin + (RMAX[sections] * TmpAxis);
|
||||
InnerPointList2[c] = LocalOrigin + (RMIN[sections] * TmpAxis);
|
||||
TmpAxis.rotateZ(-PartAngle);
|
||||
}
|
||||
|
||||
// Create the extra points on the axis
|
||||
TmpAxis = YAxis;
|
||||
TmpAxis.rotateZ(phi1);
|
||||
EndPointList[sides+1] = Origin;
|
||||
InnerPointList[sides+1] = Origin;
|
||||
EndPointList2[sides+1] = LocalOrigin;
|
||||
InnerPointList2[sides+1] = LocalOrigin;
|
||||
int points = sides+2;
|
||||
|
||||
SurfaceVec[nb_of_surfaces-4] =
|
||||
new G4FPlane(&EndPointList, &InnerPointList);
|
||||
|
||||
SurfaceVec[nb_of_surfaces-3] =
|
||||
new G4FPlane(&EndPointList2, &InnerPointList2);
|
||||
|
||||
// Create the planars for the "gap"
|
||||
TmpAxis = YAxis;
|
||||
G4ThreeVector TmpAxis2 = YAxis;
|
||||
TmpAxis.rotateZ(phi1);
|
||||
TmpAxis2.rotateZ(phi1);
|
||||
TmpAxis2.rotateZ(dphi);
|
||||
|
||||
LocalOrigin=Origin;
|
||||
points = sections*2+2;
|
||||
G4Point3DVector GapPointList(points);
|
||||
G4Point3DVector GapPointList2(points);
|
||||
Count=0;
|
||||
|
||||
for(int d=0;d<sections+1;d++)
|
||||
{
|
||||
GapPointList[Count] = LocalOrigin + (RMAX[d]*TmpAxis);
|
||||
GapPointList[points-1-Count] = LocalOrigin + (RMIN[d]*TmpAxis);
|
||||
|
||||
GapPointList2[Count] = LocalOrigin + (RMAX[d]*TmpAxis2);
|
||||
GapPointList2[points-1-Count] = LocalOrigin + (RMIN[d]*TmpAxis2);
|
||||
|
||||
Count++;
|
||||
|
||||
Length = z_values[d+1] - z_values[d];
|
||||
LocalOrigin = LocalOrigin+(Length*Axis);
|
||||
}
|
||||
|
||||
SurfaceVec[nb_of_surfaces-2] = new G4FPlane(&GapPointList);
|
||||
SurfaceVec[nb_of_surfaces-1] = new G4FPlane(&GapPointList2);
|
||||
|
||||
}
|
||||
|
||||
// Store the original parameters, to be used in visualisation
|
||||
// Note radii are scaled because this BREP uses the radius of the
|
||||
// inscribed circle but graphics_reps/G4Polyhedron uses the radius of
|
||||
// the circumscribed circle.
|
||||
original_parameters.Start_angle= phi1;
|
||||
original_parameters.Opening_angle= dphi;
|
||||
original_parameters.Sides= sides;
|
||||
original_parameters.Num_z_planes= num_z_planes;
|
||||
original_parameters.Z_values= new G4double[num_z_planes];
|
||||
original_parameters.Rmin= new G4double[num_z_planes];
|
||||
original_parameters.Rmax= new G4double[num_z_planes];
|
||||
G4double rFactor = cos(dphi/(2*sides));
|
||||
|
||||
for(int is=0;is<num_z_planes;is++)
|
||||
{
|
||||
original_parameters.Z_values[is]= z_values[is];
|
||||
original_parameters.Rmin[is]= RMIN[is]/rFactor;
|
||||
original_parameters.Rmax[is]= RMAX[is]/rFactor;
|
||||
}
|
||||
|
||||
// z_values[0] should be equal to z_start, for consistency
|
||||
// with what the constructor does.
|
||||
// Otherwise the z_values that are shifted by (z_values[0] - z_start) ,
|
||||
// because z_values are only used in the form
|
||||
// length = z_values[d+1] - z_values[d]; // JA Apr 2, 97
|
||||
|
||||
if( z_values[0] != z_start )
|
||||
{
|
||||
G4cerr << "ERROR in creating G4BREPSolidPolyhedra: " <<
|
||||
" z_values[0]= " << z_values[0] << " is not equal to " <<
|
||||
" z_start= " , z_start;
|
||||
// G4Exception(" Error in creating G4BREPSolidPolyhedra: z_values[0] must be equal to z_start" );
|
||||
original_parameters.Z_values[0]= z_start;
|
||||
}
|
||||
|
||||
active=1;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
|
||||
G4BREPSolidPolyhedra::~G4BREPSolidPolyhedra()
|
||||
{
|
||||
delete[] original_parameters.Z_values;
|
||||
delete[] original_parameters.Rmin;
|
||||
delete[] original_parameters.Rmax;
|
||||
}
|
||||
|
||||
|
||||
void G4BREPSolidPolyhedra::Initialize()
|
||||
{
|
||||
// Calc bounding box for solids and surfaces
|
||||
// Convert concave planes to convex
|
||||
ShortestDistance=1000000;
|
||||
CheckSurfaceNormals();
|
||||
if(!Box || !AxisBox)
|
||||
IsConvex();
|
||||
|
||||
CalcBBoxes();
|
||||
}
|
||||
|
||||
|
||||
EInside G4BREPSolidPolyhedra::Inside(register const G4ThreeVector& Pt) const
|
||||
{
|
||||
G4double *dists = new G4double[nb_of_surfaces];
|
||||
G4double Dist = kInfinity;
|
||||
G4double tmpdist=kInfinity;
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
|
||||
for(int a=0; a< nb_of_surfaces;a++)
|
||||
{
|
||||
tmpdist = (SurfaceVec[a]->HowNear(Pt));
|
||||
|
||||
if(fabs(Dist) > fabs(tmpdist))
|
||||
Dist = tmpdist;
|
||||
}
|
||||
|
||||
if(Dist > halfTolerance)
|
||||
return kOutside;
|
||||
|
||||
if(Dist < -halfTolerance)
|
||||
return kInside;
|
||||
|
||||
return kSurface;
|
||||
}
|
||||
|
||||
|
||||
G4ThreeVector G4BREPSolidPolyhedra::SurfaceNormal
|
||||
(const G4ThreeVector& Pt) const
|
||||
{
|
||||
G4cout<<" SurfaceNormal() of G4BREPSolidPolyhedra modified by L. Broglia";
|
||||
|
||||
/*
|
||||
//G4Exception(" SurfaceNormal() of G4BREPSolidPolyhedra is not yet implemented." );
|
||||
|
||||
#ifdef WILL_IMPLEMENT
|
||||
G4double zCoord= Pt.z();
|
||||
G4int a, zSlice, phiSlice;
|
||||
|
||||
// Try to find the appropriate z "slice"
|
||||
for(a=0; a< nb_of_surfaces-2;a++)
|
||||
if ( (zCoord < original_parameters.Z_values[a+1])
|
||||
&&(zCoord >= original_parameters.Z_values[a]) )
|
||||
break;
|
||||
|
||||
zSlice= a;
|
||||
|
||||
// Try to find the appropriate phi plane
|
||||
phiSlice = 0;
|
||||
|
||||
unsigned int isurface=0;
|
||||
|
||||
G4ThreeVec norm = SurfaceVec[isurface]->SurfaceNormal(Pt);
|
||||
G4ThreeVector normalVector = G4ThreeVector ( norm.GetX(),
|
||||
norm.GetY(),
|
||||
norm.GetZ());
|
||||
#else
|
||||
G4ThreeVector normalVector = G4ThreeVector ( 0.0, 0.0, 1.0);
|
||||
#endif
|
||||
*/
|
||||
|
||||
G4Vector3D Ptv = Pt;
|
||||
G4Vector3D n(0,0,0);
|
||||
G4double zCoord = Pt.z();
|
||||
const G4int num_z_planes = original_parameters.Num_z_planes;
|
||||
G4int iplane;
|
||||
|
||||
// Find the appropriate z "slice"
|
||||
//
|
||||
for(iplane=0; iplane< num_z_planes; iplane++)
|
||||
if ( (zCoord < original_parameters.Z_values[iplane+1]) &&
|
||||
(zCoord >= original_parameters.Z_values[iplane]) )
|
||||
break;
|
||||
|
||||
G4Vector3D norm;
|
||||
G4Ray r( Pt, G4Vector3D(1, 0, 0) );
|
||||
|
||||
// We must find which is the correct surface, the inner or the outer one
|
||||
// (if they exist)
|
||||
for(iplane = 0; iplane < num_z_planes; iplane++)
|
||||
{
|
||||
// check if the point is on the surface
|
||||
if(SurfaceVec[iplane]->Intersect(r))
|
||||
if(SurfaceVec[iplane]->Distance() < kCarTolerance)
|
||||
// the point is on the surface
|
||||
break;
|
||||
}
|
||||
|
||||
norm = SurfaceVec[iplane]->SurfaceNormal(Pt);
|
||||
|
||||
n = G4ThreeVector ( norm.x(), norm.y(), norm.z());
|
||||
n = n.unit();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidPolyhedra::DistanceToIn(const G4ThreeVector& Pt) const
|
||||
{
|
||||
G4double Dist=kInfinity;
|
||||
G4double tmpdist=kInfinity;
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
|
||||
for(int a=0; a< nb_of_surfaces;a++)
|
||||
{
|
||||
tmpdist = fabs(SurfaceVec[a]->HowNear(Pt));
|
||||
if(Dist>tmpdist && tmpdist> halfTolerance) Dist = tmpdist;
|
||||
}
|
||||
|
||||
return Dist;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidPolyhedra::DistanceToIn(register const G4ThreeVector& Pt,
|
||||
register const G4ThreeVector& V
|
||||
) const
|
||||
{
|
||||
Reset();
|
||||
G4Point3D Pttmp(Pt);
|
||||
G4Vector3D Vtmp(V);
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
|
||||
// G4double kInfinity = kInfinity;
|
||||
G4Ray r(Pttmp, Vtmp);
|
||||
TestSurfaceBBoxes(r);
|
||||
QuickSort(SurfaceVec, 0, nb_of_surfaces-1);
|
||||
ShortestDistance = kInfinity;
|
||||
|
||||
for(int a=0; a< nb_of_surfaces;a++)
|
||||
{
|
||||
if(SurfaceVec[a]->Active())
|
||||
// L. Broglia : old
|
||||
// if(SurfaceVec[a]->Intersect(r))
|
||||
if( (G4FPlane*)(SurfaceVec[a])->Evaluate(r) )
|
||||
if(ShortestDistance > SurfaceVec[a]->Distance())
|
||||
if(SurfaceVec[a]->Distance() > halfTolerance)
|
||||
ShortestDistance = SurfaceVec[a]->Distance();
|
||||
else
|
||||
{
|
||||
G4ThreeVector Norm = SurfaceVec[a]->SurfaceNormal(Pttmp);
|
||||
|
||||
if((Norm * Vtmp)<0)
|
||||
ShortestDistance = SurfaceVec[a]->Distance();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(ShortestDistance != kInfinity)
|
||||
return sqrt(ShortestDistance);
|
||||
|
||||
return kInfinity;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidPolyhedra::DistanceToOut(register const G4ThreeVector& Pt,
|
||||
register const G4ThreeVector& V,
|
||||
const G4bool calcNorm,
|
||||
G4bool *validNorm,
|
||||
G4ThreeVector *n) const
|
||||
{
|
||||
if(validNorm)
|
||||
*validNorm = false;
|
||||
|
||||
Reset();
|
||||
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
G4Point3D Pttmp(Pt);
|
||||
G4Vector3D Vtmp(V);
|
||||
|
||||
// G4double kInfinity = 10e20;
|
||||
G4Ray r(Pttmp, Vtmp);
|
||||
TestSurfaceBBoxes(r);
|
||||
QuickSort(SurfaceVec, 0, nb_of_surfaces-1);
|
||||
ShortestDistance = kInfinity;
|
||||
|
||||
for(int a=0; a< nb_of_surfaces;a++)
|
||||
{
|
||||
if(SurfaceVec[a]->Active())
|
||||
if(SurfaceVec[a]->Intersect(r))
|
||||
if(ShortestDistance > SurfaceVec[a]->Distance()&&
|
||||
SurfaceVec[a]->Distance() > halfTolerance)
|
||||
ShortestDistance = SurfaceVec[a]->Distance();
|
||||
}
|
||||
|
||||
if(ShortestDistance != kInfinity)
|
||||
return sqrt(ShortestDistance);
|
||||
|
||||
return kInfinity;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidPolyhedra::DistanceToOut(const G4ThreeVector& Pt) const
|
||||
{
|
||||
G4double Dist=kInfinity;
|
||||
G4double tmpdist=kInfinity;
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
|
||||
for(int a=0; a< nb_of_surfaces;a++)
|
||||
{
|
||||
tmpdist = fabs(SurfaceVec[a]->HowNear(Pt));
|
||||
|
||||
if(Dist>tmpdist && tmpdist> halfTolerance)
|
||||
Dist = tmpdist;
|
||||
}
|
||||
|
||||
return Dist;
|
||||
}
|
||||
|
||||
|
||||
// In graphics_reps:
|
||||
#include "G4Polyhedron.hh"
|
||||
|
||||
G4Polyhedron* G4BREPSolidPolyhedra::CreatePolyhedron() const
|
||||
{
|
||||
return new G4PolyhedronPgon( original_parameters.Start_angle,
|
||||
original_parameters.Opening_angle,
|
||||
original_parameters.Sides,
|
||||
original_parameters.Num_z_planes,
|
||||
original_parameters.Z_values,
|
||||
original_parameters.Rmin,
|
||||
original_parameters.Rmax);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4BREPSolidSphere.cc,v 2.2 1998/10/20 16:33:39 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
|
||||
#include "G4BREPSolidSphere.hh"
|
||||
#include "G4SphericalSurface.hh"
|
||||
|
||||
G4BREPSolidSphere::G4BREPSolidSphere(const G4String name,
|
||||
const G4Vector3D& o,
|
||||
const G4Vector3D& xhat,
|
||||
const G4Vector3D& zhat,
|
||||
G4double r): G4BREPSolid(name)
|
||||
{
|
||||
SurfaceVec = new G4Surface*[1];
|
||||
G4double ph1 = 0;
|
||||
G4double ph2 = 2*M_PI;
|
||||
G4double th1 = 0;
|
||||
G4double th2 = M_PI;
|
||||
SurfaceVec[0] = new G4SphericalSurface(o, xhat, zhat, r, ph1, ph2, th1, th2);
|
||||
nb_of_surfaces = 1;
|
||||
active=1;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
|
||||
EInside G4BREPSolidSphere::Inside(register const G4ThreeVector& Pt) const
|
||||
{
|
||||
G4double Dist = SurfaceVec[0]->HowNear(Pt);
|
||||
if(Dist > 0+kCarTolerance) return kInside;
|
||||
if(Dist < 0-kCarTolerance) return kOutside;
|
||||
return kSurface;
|
||||
}
|
||||
|
||||
|
||||
G4ThreeVector G4BREPSolidSphere::SurfaceNormal(const G4ThreeVector& Pt) const
|
||||
{
|
||||
G4Vector3D n = SurfaceVec[0]->Normal(Pt);
|
||||
G4ThreeVector norm(n.x(), n.y(), n.z());
|
||||
return norm;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidSphere::DistanceToIn(const G4ThreeVector& Pt) const
|
||||
{
|
||||
return fabs(SurfaceVec[0]->HowNear(Pt));
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidSphere::DistanceToIn(register const G4ThreeVector& Pt,
|
||||
register const G4ThreeVector& V) const
|
||||
{
|
||||
SphReset();
|
||||
G4Vector3D Pttmp(Pt);
|
||||
G4Vector3D Vtmp(V);
|
||||
G4Ray r(Pttmp, Vtmp);
|
||||
int Result = SurfaceVec[0]->Intersect( r );
|
||||
|
||||
if(Result>0)
|
||||
{
|
||||
ShortestDistance = SurfaceVec[0]->Distance();
|
||||
return sqrt(ShortestDistance);
|
||||
}
|
||||
return kInfinity;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidSphere::DistanceToOut(register const G4ThreeVector& Pt,
|
||||
register const G4ThreeVector& V,
|
||||
const G4bool calcNorm,
|
||||
G4bool *validNorm,
|
||||
G4ThreeVector *n) const
|
||||
{
|
||||
if(validNorm)
|
||||
*validNorm = false;
|
||||
SphReset();
|
||||
G4Vector3D Pttmp(Pt);
|
||||
G4Vector3D Vtmp(V);
|
||||
G4Ray r(Pttmp, Vtmp);
|
||||
|
||||
if(SurfaceVec[0]->Intersect( r ))
|
||||
{
|
||||
if(calcNorm)
|
||||
{
|
||||
*validNorm = true;
|
||||
*n = SurfaceNormal(Pt);
|
||||
}
|
||||
|
||||
ShortestDistance = SurfaceVec[0]->Distance();
|
||||
return sqrt(ShortestDistance);
|
||||
}
|
||||
return kInfinity;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidSphere::DistanceToOut(const G4ThreeVector& Pt) const
|
||||
{
|
||||
return fabs(SurfaceVec[0]->HowNear(Pt));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4BREPSolidTorus.cc,v 2.1 1998/10/20 16:33:39 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4BREPSolidTorus.hh"
|
||||
#include "G4ToroidalSurface.hh"
|
||||
|
||||
G4BREPSolidTorus::G4BREPSolidTorus(const G4String name,
|
||||
const G4ThreeVector& origin,
|
||||
const G4ThreeVector& axis,
|
||||
const G4ThreeVector& direction,
|
||||
G4double MinRadius,
|
||||
G4double MaxRadius): G4BREPSolid(name)
|
||||
{
|
||||
SurfaceVec = new G4Surface*[1];
|
||||
SurfaceVec[0] = new G4ToroidalSurface( origin, axis, direction,
|
||||
MinRadius, MaxRadius);
|
||||
nb_of_surfaces = 1;
|
||||
active = 1;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,240 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4BSplineCurve.cc,v 2.8 1998/12/15 15:45:15 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4BSplineCurve.hh"
|
||||
#include "G4ControlPoints.hh"
|
||||
#include "G4KnotVector.hh"
|
||||
|
||||
G4BSplineCurve::G4BSplineCurve()
|
||||
{
|
||||
}
|
||||
|
||||
void G4BSplineCurve::Init(G4int degree0, G4Point3DVector* controlPointsList0,
|
||||
G4doubleVector* knots0,
|
||||
G4doubleVector* weightsData0)
|
||||
{
|
||||
degree= degree0;
|
||||
|
||||
G4int nbpoints = controlPointsList0->length();
|
||||
controlPointsList = new G4Point3DVector(nbpoints);
|
||||
|
||||
G4int a;
|
||||
for(a = 0; a < nbpoints; a++)
|
||||
{
|
||||
(*controlPointsList)[a] = (*controlPointsList0)[a];
|
||||
}
|
||||
|
||||
G4int nbknots = knots0->length();
|
||||
knots = new G4doubleVector(nbknots);
|
||||
for(a = 0; a < nbknots; a++)
|
||||
{
|
||||
(*knots)[a] = (*knots0)[a];
|
||||
}
|
||||
|
||||
G4int nbweights = weightsData0->length();
|
||||
weightsData = new G4doubleVector(nbweights);
|
||||
for(a = 0; a < nbweights; a++)
|
||||
{
|
||||
(*weightsData)[a] = (*weightsData0)[a];
|
||||
}
|
||||
|
||||
|
||||
SetBounds((*knots)[0], (*knots)[knots->length()-1]);
|
||||
}
|
||||
|
||||
|
||||
G4BSplineCurve::~G4BSplineCurve()
|
||||
{
|
||||
delete controlPointsList;
|
||||
delete knots;
|
||||
if (weightsData) delete weightsData;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void G4BSplineCurve::CalcCurvePlaneNormal()
|
||||
{
|
||||
//Calc Normal for surface which is used for the projection
|
||||
G4ThreeVec norm;
|
||||
G4Point3d Pt1 = ControlPointList->get(0,0);
|
||||
G4Point3d Pt2 = ControlPointList->get(0,1);
|
||||
G4Point3d Pt3 = ControlPointList->get(0,2);
|
||||
G4Point3d a(Pt2.X()-Pt1.X(), Pt2.Y()-Pt1.Y(), Pt2.Z()-Pt1.Z());
|
||||
G4Point3d b(Pt3.X()-Pt1.X(), Pt3.Y()-Pt1.Y(), Pt3.Z()-Pt1.Z());
|
||||
norm.X((a.Y()*b.Z() - a.Z()*b.Y()));
|
||||
norm.Y((a.X()*b.Z() - a.Z()*b.X()));
|
||||
norm.Z((a.X()*b.Y() - a.Y()*b.X()));
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
G4Curve* G4BSplineCurve::Project(const G4Transform3D& tr)
|
||||
{
|
||||
// just transform + project all control points
|
||||
// what about self intersections?
|
||||
|
||||
G4int n = controlPointsList->length();
|
||||
G4Point3DVector* newControlPointsList = new G4Point3DVector(n);
|
||||
|
||||
for (G4int i=0; i<n; i++)
|
||||
{
|
||||
G4Point3D& p= (*newControlPointsList)(i);
|
||||
p= tr*(*controlPointsList)(i);
|
||||
p.setZ(0);
|
||||
}
|
||||
|
||||
G4doubleVector* newKnots= new G4doubleVector(*knots);
|
||||
G4doubleVector* newWeightsData=
|
||||
weightsData ? new G4doubleVector(*weightsData) : 0;
|
||||
|
||||
G4BSplineCurve* r= new G4BSplineCurve;
|
||||
r->Init(degree, newControlPointsList, newKnots, newWeightsData);
|
||||
|
||||
if (IsBounded())
|
||||
{
|
||||
r->SetBounds(GetPStart(), GetPEnd());
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void G4BSplineCurve::ProjectCurve(const G4Plane& Pl1, const G4Plane& Pl2)
|
||||
{
|
||||
int rows = ControlPointList->GetRows();
|
||||
int cols = ControlPointList->GetCols();
|
||||
int NumberOfPoints = cols * rows;
|
||||
ProjectedControlPoints = new G4Point2d*[NumberOfPoints];
|
||||
// Loop through points and do projection
|
||||
for(int a = 0; a<NumberOfPoints;a++)
|
||||
{
|
||||
// Create 2d-point
|
||||
ProjectedControlPoints[a] = new G4Point2d;
|
||||
// Project 3d points into 2d
|
||||
Project((*ProjectedControlPoints[a]), ControlPointList->get(0,a), Pl1, Pl2);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
int G4BSplineCurve::Inside( const G4Point3d& Hit, const G4Ray& rayref)
|
||||
{
|
||||
const G4Plane& Pl1 = rayref.GetPlane(0);
|
||||
const G4Plane& Pl2 = rayref.GetPlane(1);
|
||||
register G4double DistA1, DistA2, DistB1, DistB2;
|
||||
// Calc distance from Start point to ray planes
|
||||
DistA1 = Start.PlaneDistance(Pl1);
|
||||
// Calc distance from End point to ray planes
|
||||
DistB1 = End.PlaneDistance(Pl1);
|
||||
if((DistA1<0 && DistB1>0)||(DistA1>0 && DistB1 <0))
|
||||
{
|
||||
DistA2 = Start.PlaneDistance(Pl2);
|
||||
DistB2 = End.PlaneDistance(Pl2);
|
||||
// This checks the line Start-End of the convex hull
|
||||
if(DistA2<0&&DistB2<0)
|
||||
return 1;
|
||||
}
|
||||
// Test for the other lines of the convex hull
|
||||
// If one of them is on a different side than the
|
||||
// previously checked line, the curve has to be evaluated
|
||||
// against the G4Plane.
|
||||
int Points = ControlPointList->GetCols();
|
||||
|
||||
G4Point *CPoint1, *CPoint2;
|
||||
|
||||
register G4double CDistA1,CDistA2, CDistB1, CDistB2;
|
||||
int Flag=0;
|
||||
for(int a=0;a<Points-1;a++)
|
||||
{
|
||||
CPoint1 = &ControlPointList->get(0,a);
|
||||
CPoint2 = &ControlPointList->get(0,a+1);
|
||||
CDistA1 = CPoint1->PlaneDistance(Pl1);
|
||||
CDistB1 = CPoint2->PlaneDistance(Pl1);
|
||||
if((CDistA1<0 && CDistB1>0)||(CDistA1>0 && CDistB1<0))
|
||||
{
|
||||
CDistA2 = CPoint1->PlaneDistance(Pl2);
|
||||
CDistB2 = CPoint2->PlaneDistance(Pl2);
|
||||
if (!(CDistA2<0&&CDistB2<0))
|
||||
{
|
||||
Flag=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!Flag)
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
// Evaluate curve & Pl1 intersection, Calc the intersections distance
|
||||
// from Pl2 to check which side it lies on.
|
||||
G4Point3d IntPoint;
|
||||
// G4cout << "\nG4B_SplineCurve.cc:Inside - Evaluation not yet implemented!!!\n";
|
||||
// IntPoint = ...
|
||||
G4double IntDist = IntPoint.PlaneDistance(Pl2);
|
||||
if(IntDist<0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void G4BSplineCurve::InitBounded()
|
||||
{
|
||||
// just like in the old functions
|
||||
G4int pointCount = controlPointsList->length();
|
||||
bBox.Init( (*controlPointsList)(0) );
|
||||
for (G4int i=1; i<pointCount; i++)
|
||||
{
|
||||
bBox.Extend( (*controlPointsList)(i) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
G4Point3d G4BSplineCurve::GetBoundMin()
|
||||
{
|
||||
G4Point3d Min = PINFINITY;
|
||||
int PointCount = ControlPointList->GetCols();
|
||||
G4Point3d Tmp;
|
||||
for(int a=0;a<PointCount;a++)
|
||||
{
|
||||
Tmp = ControlPointList->get(0,a);
|
||||
Min > Tmp;
|
||||
}
|
||||
return Min;
|
||||
}
|
||||
|
||||
G4Point3d G4BSplineCurve::GetBoundMax()
|
||||
{
|
||||
G4Point3d Max = -PINFINITY;
|
||||
G4Point3d Tmp;
|
||||
int PointCount = ControlPointList->GetCols();
|
||||
for(int a=0;a<PointCount;a++)
|
||||
{
|
||||
Tmp = ControlPointList->get(0,a);
|
||||
Max > Tmp;
|
||||
}
|
||||
return Max;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
G4bool G4BSplineCurve::Tangent(G4CurvePoint& cp, G4Vector3D& v)
|
||||
{
|
||||
G4Exception("G4BSplineCurve::Tangent");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4BSplineCurveWithKnots.cc,v 2.1 1998/07/02 17:53:59 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4BSplineCurveWithKnots.hh"
|
||||
|
||||
@@ -0,0 +1,626 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4BSplineSurface.cc,v 2.10 1998/11/24 16:41:23 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
|
||||
#include "EntityInst.h"
|
||||
#include "G4BSplineSurface.hh"
|
||||
#include "G4BezierSurface.hh"
|
||||
|
||||
class G4ControlPoints;
|
||||
class G4BoundingBox;
|
||||
|
||||
G4BSplineSurface::G4BSplineSurface()
|
||||
{
|
||||
distance = kInfinity;
|
||||
dir=ROW;
|
||||
first_hit = Hit=(G4UVHit*)0;
|
||||
ctl_points = (G4ControlPoints*)0;
|
||||
}
|
||||
|
||||
|
||||
G4BSplineSurface::G4BSplineSurface(char* nurbfilename, G4Ray& rayref)
|
||||
{
|
||||
distance = kInfinity;
|
||||
Hit=(G4UVHit*)0;
|
||||
first_hit = Hit;
|
||||
}
|
||||
|
||||
|
||||
G4BSplineSurface::G4BSplineSurface(const G4BSplineSurface &tmp)
|
||||
{
|
||||
distance = tmp.distance;
|
||||
Hit=(G4UVHit*)0;
|
||||
first_hit=Hit;
|
||||
|
||||
// next=this;
|
||||
order[0] = tmp.order[0];
|
||||
order[1] = tmp.order[1];
|
||||
dir = tmp.dir;
|
||||
|
||||
u_knots = new G4KnotVector(*tmp.u_knots);
|
||||
v_knots = new G4KnotVector(*tmp.v_knots);
|
||||
|
||||
ctl_points = new G4ControlPoints(*tmp.ctl_points);
|
||||
}
|
||||
|
||||
|
||||
G4BSplineSurface::G4BSplineSurface(G4int u, G4int v, G4KnotVector& u_kv,
|
||||
G4KnotVector& v_kv,G4ControlPoints& cp)
|
||||
{
|
||||
order[0] = u+1;
|
||||
order[1] = v+1;
|
||||
|
||||
u_knots = new G4KnotVector(u_kv);
|
||||
v_knots = new G4KnotVector(v_kv);
|
||||
|
||||
ctl_points = new G4ControlPoints(cp);
|
||||
}
|
||||
|
||||
|
||||
G4BSplineSurface::~G4BSplineSurface()
|
||||
{
|
||||
delete u_knots;
|
||||
delete v_knots;
|
||||
delete ctl_points;
|
||||
G4UVHit* temphit=Hit;
|
||||
while(Hit!=(G4UVHit*)0)
|
||||
{
|
||||
Hit=Hit->next;
|
||||
delete temphit;
|
||||
temphit=Hit;
|
||||
}
|
||||
delete temphit;// remove last
|
||||
|
||||
}
|
||||
|
||||
|
||||
int G4BSplineSurface::Intersect(const G4Ray& rayref)
|
||||
{
|
||||
Intersected = 1;
|
||||
FindIntersections(rayref);
|
||||
G4BezierSurface *bez_ptr;
|
||||
bezier_list.MoveToFirst();
|
||||
distance = kInfinity;
|
||||
|
||||
while( bezier_list.index != (G4Surface*)0)
|
||||
{
|
||||
bez_ptr = (G4BezierSurface*)bezier_list.GetSurface();
|
||||
|
||||
if(bez_ptr->Active())
|
||||
if(distance > bez_ptr->Distance())
|
||||
{
|
||||
// Put data from closest bezier to b-spline data struct
|
||||
closest_hit = bez_ptr->AveragePoint();
|
||||
distance = bez_ptr->Distance();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set other beziers as inactive
|
||||
bez_ptr->Active(0);
|
||||
|
||||
// Remove beziers that are not closest
|
||||
// bezier_list.RemoveSurface(bez_ptr);
|
||||
}
|
||||
|
||||
bezier_list.Step();
|
||||
}
|
||||
|
||||
bezier_list.MoveToFirst();
|
||||
|
||||
if(bezier_list.number_of_elements)
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
active=0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
G4Point3D G4BSplineSurface::FinalIntersection()
|
||||
{
|
||||
// Compute the real intersection point.
|
||||
G4BezierSurface* bez_ptr;
|
||||
while ( bezier_list.number_of_elements > 0 &&
|
||||
bezier_list.index != (G4Surface*)0)
|
||||
{
|
||||
bez_ptr = (G4BezierSurface*)bezier_list.GetSurface();
|
||||
int tmp = 0;
|
||||
|
||||
// L. Broglia
|
||||
// Modify G4BezierSurface intersection function name
|
||||
// tmp = bez_ptr->Intersect( bezier_list);
|
||||
tmp = bez_ptr->BIntersect( bezier_list);
|
||||
|
||||
if(!tmp)
|
||||
{
|
||||
bezier_list.RemoveSurface(bez_ptr);
|
||||
if(bezier_list.index != (G4Surface*)0)
|
||||
bezier_list.index->Active(1);
|
||||
}
|
||||
else
|
||||
if(tmp==1)
|
||||
{
|
||||
active=1;
|
||||
// Hit found
|
||||
AddHit(bez_ptr->GetU(), bez_ptr->GetV());
|
||||
|
||||
// Delete beziers
|
||||
bezier_list.EmptyList();
|
||||
}
|
||||
else
|
||||
if(tmp==2)
|
||||
{
|
||||
// The bezier was split so the last
|
||||
// two surfaces in the List should
|
||||
// be bbox tested and if passed
|
||||
// clipped in both dirs.
|
||||
|
||||
// Move to first
|
||||
bezier_list.MoveToFirst();
|
||||
// Find the second last.
|
||||
if(bezier_list.index != bezier_list.last)
|
||||
while ( ((G4SurfaceList*)bezier_list.index)->next !=
|
||||
bezier_list.last) bezier_list.Step();
|
||||
G4BezierSurface* tmp = (G4BezierSurface*) bezier_list.GetSurface();
|
||||
tmp->CalcBBox();
|
||||
|
||||
// L. Broglia tmp->bbox->Test();
|
||||
|
||||
int result=0;
|
||||
if(tmp->bbox->GetTestResult())
|
||||
{
|
||||
// Clip
|
||||
while(!result)
|
||||
result = tmp->ClipBothDirs();
|
||||
}
|
||||
else
|
||||
{
|
||||
bezier_list.RemoveSurface(tmp);
|
||||
}
|
||||
// Second surface
|
||||
tmp = (G4BezierSurface*) bezier_list.GetLastSurface();
|
||||
tmp->CalcBBox();
|
||||
|
||||
// L. Broglia tmp->bbox->Test();
|
||||
|
||||
if(tmp->bbox->GetTestResult())
|
||||
{
|
||||
result = 0;
|
||||
while(!result)
|
||||
result = tmp->ClipBothDirs();
|
||||
}
|
||||
else
|
||||
{
|
||||
bezier_list.RemoveSurface(tmp);
|
||||
}
|
||||
|
||||
bezier_list.RemoveSurface(bez_ptr);
|
||||
bezier_list.MoveToFirst();
|
||||
}
|
||||
|
||||
bezier_list.Step();
|
||||
}//While....
|
||||
|
||||
Hit = first_hit;
|
||||
G4Point3D result;
|
||||
if(Hit == (G4UVHit*)0)
|
||||
active = 0;
|
||||
else
|
||||
{
|
||||
while(Hit != (G4UVHit*)0)
|
||||
{
|
||||
// L. Broglia
|
||||
// Modify function name
|
||||
// result = Evaluate();
|
||||
result = BSEvaluate();
|
||||
|
||||
Hit = Hit->next;
|
||||
}
|
||||
|
||||
Hit = first_hit;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void G4BSplineSurface::CalcBBox()
|
||||
{
|
||||
|
||||
// Finds the bounds of the b-spline surface iow
|
||||
// calculates the bounds for a bounding box
|
||||
// to the surface. The bounding box is used
|
||||
// for a preliminary check of intersection.
|
||||
|
||||
register G4Point3D box_min = PINFINITY;
|
||||
register G4Point3D box_max =-PINFINITY;
|
||||
|
||||
// Loop to search the whole control point mesh
|
||||
// for the minimum and maximum values for x, y and z.
|
||||
|
||||
for(register int a = ctl_points->GetRows()-1; a>=0;a--)
|
||||
for(register int b = ctl_points->GetCols()-1; b>=0;b--)
|
||||
{
|
||||
G4Point3D tmp = ctl_points->Get3D(a,b);
|
||||
if((box_min.x()) > (tmp.x())) box_min.setX(tmp.x());
|
||||
if((box_min.y()) > (tmp.y())) box_min.setY(tmp.y());
|
||||
if((box_min.z()) > (tmp.z())) box_min.setZ(tmp.z());
|
||||
if((box_max.x()) < (tmp.x())) box_max.setX(tmp.x());
|
||||
if((box_max.y()) < (tmp.y())) box_max.setY(tmp.y());
|
||||
if((box_max.z()) < (tmp.z())) box_max.setZ(tmp.z());
|
||||
}
|
||||
bbox = new G4BoundingBox3D( box_min, box_max);
|
||||
}
|
||||
|
||||
|
||||
G4ProjectedSurface* G4BSplineSurface::CopyToProjectedSurface
|
||||
(const G4Ray& rayref)
|
||||
{
|
||||
G4ProjectedSurface* proj_srf = new G4ProjectedSurface() ;
|
||||
proj_srf->PutOrder(0,GetOrder(0));
|
||||
proj_srf->PutOrder(1,GetOrder(1));
|
||||
proj_srf->dir = dir;
|
||||
|
||||
proj_srf->u_knots = new G4KnotVector(*u_knots);
|
||||
proj_srf->v_knots = new G4KnotVector(*v_knots);
|
||||
proj_srf->ctl_points = new G4ControlPoints
|
||||
(2, ctl_points->GetRows(), ctl_points->GetCols());
|
||||
|
||||
const G4Plane& plane1 = rayref.GetPlane(1);
|
||||
const G4Plane& plane2 = rayref.GetPlane(2);
|
||||
ProjectNURBSurfaceTo2D(plane1, plane2, proj_srf);
|
||||
|
||||
return proj_srf;
|
||||
}
|
||||
|
||||
|
||||
void G4BSplineSurface::FindIntersections(const G4Ray& rayref)
|
||||
{
|
||||
// Do the projection to 2D
|
||||
G4ProjectedSurface* proj_srf = CopyToProjectedSurface(rayref);
|
||||
|
||||
// Put surface in projected List
|
||||
projected_list.AddSurface(proj_srf);
|
||||
|
||||
// Loop through List of projected surfaces
|
||||
while(projected_list.number_of_elements > 0)
|
||||
{
|
||||
// Get first in List
|
||||
proj_srf = (G4ProjectedSurface*)projected_list.GetSurface();
|
||||
|
||||
// Create the bounding box for the projected surface.
|
||||
proj_srf->CalcBBox();
|
||||
|
||||
// L. Broglia proj_srf->bbox->Test();
|
||||
|
||||
// Check bbox test result is ok
|
||||
if(proj_srf->bbox->GetTestResult())
|
||||
// Convert the projected surface to a bezier. Split if necessary.
|
||||
proj_srf->ConvertToBezier(projected_list, bezier_list);
|
||||
|
||||
// Remove projected surface
|
||||
projected_list.RemoveSurface(proj_srf);
|
||||
}
|
||||
|
||||
// Loop through the bezier List
|
||||
G4BezierSurface* bez_ptr;
|
||||
distance = INFINITY;
|
||||
|
||||
while(bezier_list.index != (G4Surface*)0)
|
||||
{
|
||||
bez_ptr = (G4BezierSurface*)bezier_list.GetSurface();
|
||||
|
||||
// Add a temporary Hit
|
||||
AddHit(bez_ptr->UAverage(), bez_ptr->VAverage());
|
||||
|
||||
// Evaluate Hit
|
||||
|
||||
// L. Broglia
|
||||
// Modify function name
|
||||
// bez_ptr->SetAveragePoint(Evaluate());
|
||||
bez_ptr->SetAveragePoint(BSEvaluate());
|
||||
|
||||
// Calculate distance to ray origin
|
||||
bez_ptr->CalcDistance(rayref.GetStart());
|
||||
|
||||
// Put closest to b_splines distance value
|
||||
if(bez_ptr->Distance() < distance) distance = bez_ptr->Distance();
|
||||
|
||||
// Remove the temporary Hit
|
||||
delete Hit;
|
||||
first_hit = Hit = (G4UVHit*)0;
|
||||
|
||||
// Move to next in the List
|
||||
bezier_list.Step();
|
||||
}
|
||||
|
||||
bezier_list.MoveToFirst();
|
||||
if(bezier_list.number_of_elements == 0)
|
||||
{
|
||||
active=0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that approx Hit is in direction of ray
|
||||
const G4Point3D& Pt = rayref.GetStart();
|
||||
const G4Vector3D& Dir = rayref.GetDir();
|
||||
G4Point3D TestPoint = (0.00001*Dir) + Pt;
|
||||
G4BezierSurface* Bsrf = (G4BezierSurface*)bezier_list.GetSurface(0);
|
||||
|
||||
G4Point3D AveragePoint = Bsrf->AveragePoint();
|
||||
G4double TestDistance = TestPoint.distance2(AveragePoint);
|
||||
|
||||
if(TestDistance > distance)
|
||||
// Hit behind ray starting point, no intersection.
|
||||
active=0;
|
||||
}
|
||||
|
||||
|
||||
void G4BSplineSurface::AddHit(G4double u, G4double v)
|
||||
{
|
||||
if(Hit == (G4UVHit*)0)
|
||||
{
|
||||
first_hit = new G4UVHit(u,v);
|
||||
first_hit->next = (G4UVHit*)0;
|
||||
Hit = first_hit;
|
||||
}
|
||||
else
|
||||
{
|
||||
Hit->next = new G4UVHit(u,v);
|
||||
Hit = Hit->next;
|
||||
Hit->next=(G4UVHit*)0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void G4BSplineSurface::ProjectNURBSurfaceTo2D
|
||||
(const G4Plane& plane1, const G4Plane& plane2,
|
||||
register G4ProjectedSurface* proj_srf)
|
||||
{
|
||||
// Projects the nurb surface so that the z-axis = ray.
|
||||
|
||||
/* L. Broglia
|
||||
G4Point* tmp = (G4Point*)&ctl_points->get(0,0);
|
||||
*/
|
||||
|
||||
G4PointRat tmp = ctl_points->GetRat(0,0);
|
||||
int rational = tmp.GetType();// Get the type of control point
|
||||
register G4Point3D psrfcoords;
|
||||
register int rows = ctl_points->GetRows();
|
||||
register int cols = ctl_points->GetCols();
|
||||
|
||||
for (register int i=0; i< rows; i++)
|
||||
for(register int j=0; j < cols;j++)
|
||||
{
|
||||
if ( rational==4 ) // 4 coordinates
|
||||
{
|
||||
G4PointRat& srfcoords = ctl_points->GetRat(i, j);
|
||||
|
||||
// L. Broglia
|
||||
// Changes for new G4PointRat
|
||||
|
||||
// Calculate the x- and y-coordinates for the new
|
||||
// 2-D surface.
|
||||
psrfcoords.setX(( srfcoords.x() * plane1.a
|
||||
+srfcoords.y() * plane1.b
|
||||
+srfcoords.z() * plane1.c
|
||||
-srfcoords.w() * plane1.d));
|
||||
psrfcoords.setY(( srfcoords.x() * plane2.a
|
||||
+srfcoords.y() * plane2.b
|
||||
+srfcoords.z() * plane2.c
|
||||
-srfcoords.w() * plane2.d));
|
||||
|
||||
proj_srf->ctl_points->put(i,j,psrfcoords);
|
||||
}
|
||||
else // 3 coordinates
|
||||
{
|
||||
G4Point3D srfcoords = ctl_points->Get3D(i, j);
|
||||
|
||||
psrfcoords.setX(( srfcoords.x() * plane1.a
|
||||
+srfcoords.y() * plane1.b
|
||||
+srfcoords.z() * plane1.c
|
||||
- plane1.d));
|
||||
|
||||
psrfcoords.setY(( srfcoords.x() * plane2.a
|
||||
+srfcoords.y() * plane2.b
|
||||
+srfcoords.z() * plane2.c
|
||||
- plane2.d));
|
||||
|
||||
proj_srf->ctl_points->put(i,j,psrfcoords);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* L. Broglia
|
||||
Changes for new G4PointRat
|
||||
G4Point& G4BSplineSurface::InternalEvalCrv(int i, G4ControlPoints* crv)*/
|
||||
|
||||
G4PointRat& G4BSplineSurface::InternalEvalCrv(int i, G4ControlPoints* crv)
|
||||
{
|
||||
if ( ord <= 1 )
|
||||
return crv->GetRat(i, k_index);
|
||||
|
||||
register int j = k_index;
|
||||
|
||||
while ( j > (k_index - ord + 1))
|
||||
{
|
||||
register G4double k1, k2;
|
||||
|
||||
k1 = tmp_knots->GetKnot((j + ord - 1));
|
||||
k2 = tmp_knots->GetKnot(j);
|
||||
|
||||
if ((abs(k1 - k2)) > kCarTolerance )
|
||||
{
|
||||
/* L. Broglia
|
||||
register G4PointRat* pts1 = &crv->get(i,j-1);
|
||||
register G4PointRat* pts2 = &crv->get(i,j );
|
||||
if(pts1->GetType()==3)
|
||||
{
|
||||
crv->CalcValues(k1, param, *(G4Point3D*)pts1, k2, *(G4Point3D*)pts2);
|
||||
crv->put(0, j, *(G4Point3D*)pts2);
|
||||
}
|
||||
else
|
||||
{
|
||||
crv->CalcValues(k1, param, *(G4PointRat*)pts1, k2, *(G4PointRat*)pts2);
|
||||
crv->put(0, j, *(G4PointRat*)pts2);
|
||||
}
|
||||
*/
|
||||
register G4PointRat* pts1 = &crv->GetRat(i,j-1);
|
||||
register G4PointRat* pts2 = &crv->GetRat(i,j );
|
||||
}
|
||||
|
||||
j--;
|
||||
}
|
||||
|
||||
ord = ord-1;
|
||||
return InternalEvalCrv(0, crv); // Recursion
|
||||
}
|
||||
|
||||
|
||||
G4Point3D G4BSplineSurface::BSEvaluate()
|
||||
{
|
||||
register int i;
|
||||
register int row_size = ctl_points->GetRows();
|
||||
register G4ControlPoints *diff_curve;
|
||||
register G4ControlPoints* curves;
|
||||
G4Point3D result;
|
||||
|
||||
/* L. Broglia
|
||||
G4Point* tmp = (G4Point*)&ctl_points->get(0,0);
|
||||
*/
|
||||
|
||||
G4PointRat* tmp = &ctl_points->GetRat(0,0);
|
||||
|
||||
register int point_type = tmp->GetType();
|
||||
diff_curve = new G4ControlPoints(point_type, row_size, 1);
|
||||
k_index = u_knots->GetKnotIndex(Hit->u, GetOrder(ROW) );
|
||||
|
||||
ord = GetOrder(ROW);
|
||||
if(k_index==-1)
|
||||
{
|
||||
delete diff_curve;
|
||||
active = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
curves=new G4ControlPoints(*ctl_points);
|
||||
tmp_knots = u_knots;
|
||||
param = Hit->u;
|
||||
|
||||
if(point_type == 4)
|
||||
{
|
||||
for ( i = 0; i < row_size; i++)
|
||||
{
|
||||
ord = GetOrder(ROW);
|
||||
register G4PointRat rtr_pt = (G4PointRat&) InternalEvalCrv(i, curves);
|
||||
diff_curve->put(0,i,rtr_pt);
|
||||
}
|
||||
|
||||
k_index = v_knots->GetKnotIndex( Hit->v, GetOrder(COL) );
|
||||
if(k_index==-1)
|
||||
{
|
||||
delete diff_curve;
|
||||
delete curves;
|
||||
active = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
ord = GetOrder(COL);
|
||||
tmp_knots = v_knots;
|
||||
param = Hit->v;
|
||||
|
||||
// Evaluate the diff_curve...
|
||||
G4PointRat rat_result = (G4PointRat&) InternalEvalCrv(0, diff_curve);
|
||||
|
||||
// Calc the 3D values.
|
||||
// L. Broglia
|
||||
// Changes for new G4PointRat
|
||||
result.setX(rat_result.x()/rat_result.w());
|
||||
result.setY(rat_result.y()/rat_result.w());
|
||||
result.setZ(rat_result.z()/rat_result.w());
|
||||
}
|
||||
else
|
||||
if(point_type == 3)
|
||||
{
|
||||
for ( i = 0; i < row_size; i++)
|
||||
{
|
||||
ord = GetOrder(ROW);
|
||||
G4Point3D rtr_pt = (G4Point3D&) InternalEvalCrv(i, curves);
|
||||
diff_curve->put(0,i,rtr_pt);
|
||||
}
|
||||
|
||||
k_index = v_knots->GetKnotIndex( Hit->v, GetOrder(COL) );
|
||||
if(k_index==-1)
|
||||
{
|
||||
delete diff_curve;
|
||||
delete curves;
|
||||
active = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
ord = GetOrder(COL);
|
||||
tmp_knots = v_knots;
|
||||
param = Hit->v;
|
||||
|
||||
// Evaluate the diff_curve...
|
||||
result = (G4Point3D&) InternalEvalCrv(0, diff_curve);
|
||||
}
|
||||
|
||||
delete diff_curve;
|
||||
delete curves;
|
||||
closest_hit = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
G4Point3D G4BSplineSurface::Evaluation(const G4Ray& rayref)
|
||||
{
|
||||
// Delete old UVhits
|
||||
G4UVHit* temphit=Hit;
|
||||
while(Hit!=(G4UVHit*)0)
|
||||
{
|
||||
Hit=Hit->next;
|
||||
delete temphit;
|
||||
temphit=Hit;
|
||||
}
|
||||
|
||||
delete temphit;
|
||||
|
||||
// Get the real Hit point
|
||||
closest_hit = FinalIntersection();
|
||||
|
||||
// The following part (commented out) is old bullshit
|
||||
// Chech that Hit is not in a void i.e. InnerBoundary.
|
||||
// for(int a=0; a<NumberOfInnerBoundaries;a++)
|
||||
// if(InnerBoundary[a]->Inside(closest_hit, rayref))
|
||||
// {
|
||||
// Active(0);
|
||||
// Distance(kInfinity);
|
||||
// return closest_hit;
|
||||
// }
|
||||
return closest_hit;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BSplineSurface::ClosestDistanceToPoint(const G4Point3D& Pt)
|
||||
{
|
||||
G4double PointDistance=0;
|
||||
PointDistance = ctl_points->ClosestDistanceToPoint(Pt);
|
||||
return PointDistance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4BoundedSurface.cc,v 2.3 1998/10/20 16:33:42 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4BoundedSurface.hh"
|
||||
|
||||
@@ -0,0 +1,322 @@
|
||||
#include "G4BoundingBox3D.hh"
|
||||
#include "geomdefs.hh"
|
||||
|
||||
const G4BoundingBox3D G4BoundingBox3D::
|
||||
space( G4Point3D(-kInfinity, -kInfinity, -kInfinity),
|
||||
G4Point3D(+kInfinity, +kInfinity, +kInfinity) );
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4BoundingBox3D::G4BoundingBox3D() { distance =0; }
|
||||
|
||||
G4BoundingBox3D::G4BoundingBox3D(const G4Point3D& p1, const G4Point3D& p2)
|
||||
{
|
||||
Init(p1, p2);
|
||||
}
|
||||
|
||||
G4BoundingBox3D::G4BoundingBox3D(const G4Point3D& p)
|
||||
{
|
||||
Init(p);
|
||||
}
|
||||
|
||||
G4BoundingBox3D::~G4BoundingBox3D() {}
|
||||
|
||||
|
||||
void G4BoundingBox3D::Init(const G4Point3D& p1, const G4Point3D& p2)
|
||||
{
|
||||
// L. Broglia
|
||||
// Maybe temporary
|
||||
// Create a BBox bigger than the reality
|
||||
|
||||
box_min.setX( min(p1.x(), p2.x()) - kCarTolerance );
|
||||
box_min.setY( min(p1.y(), p2.y()) - kCarTolerance );
|
||||
box_min.setZ( min(p1.z(), p2.z()) - kCarTolerance );
|
||||
box_max.setX( max(p1.x(), p2.x()) + kCarTolerance );
|
||||
box_max.setY( max(p1.y(), p2.y()) + kCarTolerance );
|
||||
box_max.setZ( max(p1.z(), p2.z()) + kCarTolerance );
|
||||
|
||||
// Calc half spaces
|
||||
GeantBox = (box_max - box_min)*0.5;
|
||||
MiddlePoint = (box_min + box_max)*0.5;
|
||||
distance = 0;
|
||||
}
|
||||
|
||||
|
||||
void G4BoundingBox3D::Init(const G4Point3D& p)
|
||||
{
|
||||
box_min= box_max= MiddlePoint= p;
|
||||
GeantBox= G4Point3D(0, 0, 0);
|
||||
distance= 0;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void G4BoundingBox3D::Extend(const G4Point3D& p)
|
||||
{
|
||||
|
||||
// L. Broglia
|
||||
// Maybe temporary
|
||||
// Create a BBox bigger than the reality
|
||||
|
||||
if (p.x() < box_min.x())
|
||||
box_min.setX( p.x() - kCarTolerance );
|
||||
else if (p.x() > box_max.x())
|
||||
box_max.setX( p.x() + kCarTolerance );
|
||||
|
||||
if (p.y() < box_min.y())
|
||||
box_min.setY( p.y() - kCarTolerance );
|
||||
else if (p.y() > box_max.y())
|
||||
box_max.setY( p.y() + kCarTolerance );
|
||||
|
||||
if (p.z() < box_min.z())
|
||||
box_min.setZ( p.z() - kCarTolerance );
|
||||
else if (p.z() > box_max.z())
|
||||
box_max.setZ( p.z() + kCarTolerance );
|
||||
|
||||
// L. Broglia
|
||||
// Now re-calculate GeantBox and MiddlePoint
|
||||
GeantBox = (box_max - box_min)*0.5;
|
||||
MiddlePoint = (box_min + box_max)*0.5;
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
int G4BoundingBox3D::Test(const G4Ray& rayref)
|
||||
{
|
||||
const G4Point3D& tmp_ray_start = rayref.GetStart();
|
||||
const G4Vector3D& tmp_ray_dir = rayref.GetDir();
|
||||
|
||||
G4Point3D ray_start = tmp_ray_start ;
|
||||
G4Vector3D ray_dir = tmp_ray_dir ;
|
||||
|
||||
G4double rayx,rayy,rayz;
|
||||
rayx = ray_start.x();
|
||||
rayy = ray_start.y();
|
||||
rayz = ray_start.z();
|
||||
|
||||
// Test if ray starting point is in the bbox or not
|
||||
if((rayx < box_min.x()) || (rayx > box_max.x()) ||
|
||||
(rayy < box_min.y()) || (rayy > box_max.y()) ||
|
||||
(rayz < box_min.z()) || (rayz > box_max.z()) )
|
||||
{
|
||||
// Outside, check for intersection with bbox
|
||||
|
||||
// Adapt ray_starting point to box
|
||||
|
||||
const G4Point3D ray_start2 = ray_start - MiddlePoint;
|
||||
distance = DistanceToIn(ray_start2, ray_dir);
|
||||
|
||||
if(!distance)
|
||||
test_result = 0; // Miss
|
||||
else
|
||||
test_result = 1; // Starting point outside box & hits box
|
||||
}
|
||||
else
|
||||
{
|
||||
// Inside
|
||||
// G4cout << "\nRay starting point Inside bbox.";
|
||||
test_result = 1;
|
||||
distance = 0;
|
||||
}
|
||||
|
||||
return test_result;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// Does an intersection exist?
|
||||
//
|
||||
// ALGORITHM:
|
||||
//
|
||||
// Check that if point lies outside x/y/z extent of box, travel is towards
|
||||
// the box (ie. there is a possiblity of an intersection)
|
||||
|
||||
|
||||
int G4BoundingBox3D::BoxIntersect(const G4Point3D& gbox,
|
||||
const G4Point3D& p ,
|
||||
const G4Vector3D& v ) const
|
||||
{
|
||||
G4double safx, safy, safz;
|
||||
G4double fdx, fdy, fdz;
|
||||
|
||||
fdx = GeantBox.x();
|
||||
fdy = GeantBox.y();
|
||||
fdz = GeantBox.z();
|
||||
|
||||
safx=fabs(p.x())-fdx; // minimum distance to x surface of shape
|
||||
safy=fabs(p.y())-fdy;
|
||||
safz=fabs(p.z())-fdz;
|
||||
|
||||
// Will we Intersect?
|
||||
// If safx/y/z is >=0 the point is outside/on the box's x/y/z extent.
|
||||
// If both p.X()/y/z and v.X()/y/z repectively are both positive/negative,
|
||||
// travel is in a G4ThreeVec away from the shape.
|
||||
|
||||
if ( ( (p.x()*v.x()>=0.0 ) && safx>0.0 ) ||
|
||||
( (p.y()*v.y()>=0.0 ) && safy>0.0 ) ||
|
||||
( (p.z()*v.z()>=0.0 ) && safz>0.0 ) )
|
||||
return 0; // No intersection
|
||||
else
|
||||
return 1; // Possible intersection
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// Distance to in
|
||||
// Calculate distance to box from outside - return kBig if no intersection
|
||||
//
|
||||
// ALGORITHM:
|
||||
//
|
||||
// Check that if point lies outside x/y/z extent of box, travel is towards
|
||||
// the box (ie. there is a possiblity of an intersection)
|
||||
//
|
||||
// Calculate pairs of minimum and maximum distances for x/y/z travel for
|
||||
// intersection with the box's x/y/z extent.
|
||||
// If there is a valid intersection, it is given by the maximum min distance
|
||||
// (ie. distance to satisfy x/y/z intersections) *if* <= minimum max distance
|
||||
// (ie. distance after which 1+ of x/y/z intersections not satisfied)
|
||||
//
|
||||
// NOTE:
|
||||
//
|
||||
// `Inside' safe - meaningful answers given if point is Inside the exact
|
||||
// shape.
|
||||
|
||||
//G4double G4BoundingBox::distance_to_in(const G4Point3d& gbox, const G4Point3d& p, const G4ThreeVec& v) const
|
||||
G4double G4BoundingBox3D::DistanceToIn(const G4Point3D& p,
|
||||
const G4Vector3D& v) const
|
||||
{
|
||||
G4double safx, safy, safz, snxt = 0; // snxt = default return value
|
||||
G4double smin, sminx, sminy, sminz;
|
||||
G4double smax, smaxx, smaxy, smaxz;
|
||||
G4double stmp;
|
||||
G4double kBig = 10e20;
|
||||
G4double fdx,fdy,fdz;
|
||||
|
||||
fdx = GeantBox.x();
|
||||
fdy = GeantBox.y();
|
||||
fdz = GeantBox.z();
|
||||
|
||||
safx = fabs(p.x())-fdx; // minimum distance to x surface of shape
|
||||
safy = fabs(p.y())-fdy;
|
||||
safz = fabs(p.z())-fdz;
|
||||
|
||||
// Will we Intersect?
|
||||
// If safx/y/z is >=0 the point is outside/on the box's x/y/z extent.
|
||||
// If both p.X()/y/z and v.X()/y/z repectively are both positive/negative,
|
||||
// travel is in a G4ThreeVec away from the shape.
|
||||
|
||||
if ( ( ( p.x()*v.x()>=0.0 ) && safx>0.0) ||
|
||||
( ( p.y()*v.y()>=0.0 ) && safy>0.0) ||
|
||||
( ( p.z()*v.z()>=0.0 ) && safz>0.0) )
|
||||
return snxt;
|
||||
|
||||
// Compute min / max distance for x/y/z travel:
|
||||
if (safx<0.0)
|
||||
{
|
||||
// Inside x extent => Calc distance until trajectory leaves extent
|
||||
sminx=0.0;
|
||||
if (v.x())
|
||||
smaxx = fdx/fabs(v.x()) - p.x()/v.x();
|
||||
else
|
||||
smaxx = kBig;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Outside extent or on boundary
|
||||
if (v.x()==0)
|
||||
return snxt; // Travel parallel
|
||||
else
|
||||
{
|
||||
stmp = fabs(v.x());
|
||||
sminx = safx/stmp;
|
||||
smaxx = (fdx+fabs(p.x()))/stmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (safy<0.0)
|
||||
{
|
||||
// Inside y extent => Calc distance until trajectory leaves extent
|
||||
sminy=0.0;
|
||||
if (v.y())
|
||||
smaxy = fdy/fabs(v.y()) - p.y()/v.y();
|
||||
else
|
||||
smaxy = kBig;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Outside extent or on boundary
|
||||
if (v.y()==0)
|
||||
return snxt; // Travel parallel
|
||||
else
|
||||
{
|
||||
stmp = fabs(v.y());
|
||||
sminy = safy/stmp;
|
||||
smaxy = (fdy+fabs(p.y()))/stmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (safz<0.0)
|
||||
{
|
||||
// Inside z extent => Calc distance until trajectory leaves extent
|
||||
sminz=0.0;
|
||||
if (v.z())
|
||||
smaxz = fdz/fabs(v.z()) - p.z()/v.z();
|
||||
else
|
||||
smaxz = kBig;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Outside extent or on boundary
|
||||
if (v.z()==0)
|
||||
return snxt; // Travel parallel
|
||||
else
|
||||
{
|
||||
stmp = fabs(v.z());
|
||||
sminz = safz/stmp;
|
||||
smaxz = (fdz+fabs(p.z()))/stmp;
|
||||
}
|
||||
}
|
||||
|
||||
// Find minimum allowed Dist given min/max pairs
|
||||
if (sminx>sminy)
|
||||
smin = sminx; // MAX(sminx,sminy,sminz)
|
||||
else
|
||||
smin = sminy;
|
||||
|
||||
if (sminz>smin)
|
||||
smin=sminz;
|
||||
|
||||
if (smaxx<smaxy)
|
||||
smax = smaxx; // MIN(smaxx,smaxy,smaxz)
|
||||
else
|
||||
smax = smaxy;
|
||||
|
||||
if (smaxz<smax)
|
||||
smax = smaxz;
|
||||
|
||||
// If smin <= kCarTolerance then only clipping `tolerant' Area
|
||||
// -> no intersection
|
||||
|
||||
G4double kCarTolerance = 0;
|
||||
|
||||
if (smin>kCarTolerance && smin<=smax)
|
||||
snxt=smin;
|
||||
|
||||
return snxt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4CircularCurve.cc,v 2.4 1998/10/20 16:33:43 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
|
||||
#include "G4CircularCurve.hh"
|
||||
#include "G4Ellipse.hh"
|
||||
|
||||
// G4CircularCurve
|
||||
G4CircularCurve::G4CircularCurve() {}
|
||||
G4CircularCurve::~G4CircularCurve() {}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void G4CircularCurve::InitBounded()
|
||||
{
|
||||
// the bbox must include the start and endpoints as well as the
|
||||
// extreme points if they lie on the curve
|
||||
bBox.Init(GetStart(), GetEnd());
|
||||
|
||||
// the parameter values
|
||||
// belonging to the points with an extreme x, y and z coordinate
|
||||
for (G4int i=0; i<3; i++)
|
||||
{
|
||||
G4double u = atan2(position.GetPY()(i), position.GetPX()(i));
|
||||
|
||||
if (IsPOn(u))
|
||||
bBox.Extend(GetPoint(u));
|
||||
|
||||
if (IsPOn(u+pi))
|
||||
bBox.Extend(GetPoint(u+pi));
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4Curve* G4CircularCurve::Project(const G4Transform3D& tr)
|
||||
{
|
||||
G4Ellipse e;
|
||||
e.Init(position, radius, radius);
|
||||
e.SetBounds(GetPStart(), GetPEnd());
|
||||
|
||||
return e.Project(tr);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4bool G4CircularCurve::Tangent(G4CurvePoint& cp, G4Vector3D& v)
|
||||
{
|
||||
// The tangent is computed from the 3D point representation
|
||||
// for all conics. An alternaive implementation (based on
|
||||
// the parametric point) might be worthwhile adding
|
||||
// for efficiency.
|
||||
|
||||
const G4Axis2Placement3D& pos= *(GetPosition());
|
||||
G4Point3D p= pos.GetToPlacementCoordinates() * cp.GetPoint();
|
||||
|
||||
v= -p.y()*pos.GetPX() + p.x()*pos.GetPY();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
#include "G4CompositeCurve.hh"
|
||||
#include "G4Line.hh"
|
||||
|
||||
|
||||
G4CompositeCurve::G4CompositeCurve(){}
|
||||
G4CompositeCurve::G4CompositeCurve(const G4Point3DVector& vertices)
|
||||
{
|
||||
G4CurveVector cv;
|
||||
G4Line* l;
|
||||
for (G4int i=0; i<vertices.length(); i++)
|
||||
{
|
||||
G4Point3D p1= vertices[i];
|
||||
G4Point3D p2= vertices[(i+1) % vertices.length()];
|
||||
|
||||
G4Line* l= new G4Line;
|
||||
l->Init(p1, p2-p1);
|
||||
l->SetBounds(p1, p2);
|
||||
cv.insert(l);
|
||||
}
|
||||
|
||||
Init(cv);
|
||||
}
|
||||
|
||||
G4CompositeCurve::~G4CompositeCurve(){}
|
||||
|
||||
|
||||
G4Curve* G4CompositeCurve::Project(const G4Transform3D& tr)
|
||||
{
|
||||
G4CurveVector newSegments;
|
||||
|
||||
for (G4int i=0; i<segments.entries(); i++)
|
||||
{
|
||||
G4Curve* c= segments[i]->Project(tr);
|
||||
if (c==0)
|
||||
{
|
||||
newSegments.clearAndDestroy();
|
||||
return 0;
|
||||
}
|
||||
|
||||
newSegments.insert(c);
|
||||
}
|
||||
|
||||
G4CompositeCurve* r= new G4CompositeCurve;
|
||||
r->Init(newSegments);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
void G4CompositeCurve::IntersectRay2D(const G4Ray& ray,
|
||||
G4CurveRayIntersection& is)
|
||||
{
|
||||
is.Reset();
|
||||
|
||||
for (G4int i=0; i<segments.entries(); i++)
|
||||
{
|
||||
G4Curve& c= *(segments(i));
|
||||
G4CurveRayIntersection isTmp(c, ray);
|
||||
c.IntersectRay2D(ray, isTmp);
|
||||
if (isTmp.GetDistance() < is.GetDistance())
|
||||
is= isTmp;
|
||||
}
|
||||
|
||||
lastIntersection= is;
|
||||
}
|
||||
|
||||
|
||||
G4bool G4CompositeCurve::Tangent(G4CurvePoint& cp, G4Vector3D& v)
|
||||
{
|
||||
if (lastIntersection.GetDistance() == kInfinity)
|
||||
return false;
|
||||
|
||||
return lastIntersection.GetCurve().Tangent(lastIntersection, v);
|
||||
// should be true
|
||||
// cp is ignored for the moment
|
||||
}
|
||||
|
||||
|
||||
void G4CompositeCurve::InitBounded()
|
||||
{
|
||||
const G4BoundingBox3D* b= segments[0]->BBox();
|
||||
bBox.Init(b->GetBoxMin(), b->GetBoxMax());
|
||||
|
||||
for (G4int i=1; i<segments.entries(); i++)
|
||||
{
|
||||
b= segments[i]->BBox();
|
||||
bBox.Extend(b->GetBoxMin());
|
||||
bBox.Extend(b->GetBoxMax());
|
||||
}
|
||||
|
||||
// init for efficient parameter <-> 3D point conversions
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "G4Conic.hh"
|
||||
// G4Conic
|
||||
|
||||
G4Conic::G4Conic (): pShift(0) {}
|
||||
G4Conic::G4Conic (STEPentity& Ent){};
|
||||
G4Conic::~G4Conic() {}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
void G4ConicalCurve::ProjectCurve(const G4Plane& Pl1, const G4Plane& Pl2)
|
||||
{
|
||||
// Curve start
|
||||
Project(ProjStart, Start, Pl1, Pl2);
|
||||
// Curve end
|
||||
Project(ProjEnd, End, Pl1, Pl2);
|
||||
// Placement
|
||||
Position.ProjectPlacement(Pl1,Pl2);
|
||||
}
|
||||
|
||||
int G4ConicalCurve::HitPartOfCurve(G4double Angle, G4double Solution, const G4Point2d& ProjHit)
|
||||
{
|
||||
// Check if Solution1 is part of the curve i.e. in the "pie"
|
||||
G4double TmpSol1 = Solution - ProjHit.X();
|
||||
G4Point2d ArcHit1(TmpSol1, ProjHit.Y());
|
||||
G4double Cross1 = CrossProduct( ProjStart, ArcHit1);
|
||||
G4double Cross2 = CrossProduct( ArcHit1 , ProjEnd);
|
||||
if( (Angle<=0 && Cross1<=0 && Cross2 <=0) ||
|
||||
(Angle> 0 && !(Cross1>=0 && Cross2 >=0)) )
|
||||
// Solution1 is on the curve
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,552 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4ConicalSurface.cc,v 2.6 1998/11/13 13:58:30 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
/* /usr/local/gismo/repo/geometry/G4ConicalSurface.cc,v 1.6 1994/08/03 17:15:01 burnett Exp */
|
||||
// File: G4ConicalSurface.cc
|
||||
// Author: Alan Breakstone
|
||||
|
||||
// Contents ----------------------------------------------------------
|
||||
//
|
||||
// G4ConicalSurface::G4ConicalSurface()
|
||||
// G4ConicalSurface::G4ConicalSurface( const G4Vector3D& o,
|
||||
// const G4Vector3D& a, G4double e )
|
||||
// G4ConicalSurface::PrintOn( ostream& os ) const
|
||||
// G4ConicalSurface::HowNear( const G4Vector3D& x ) const
|
||||
// G4ConicalSurface::distanceAlongRay( int which_way, const Ray* ry,
|
||||
// G4Vector3D& p ) const
|
||||
// G4ConicalSurface::Inside( const G4Vector3D& x ) const
|
||||
// G4ConicalSurface::WithinBoundary( const G4Vector3D& x ) const
|
||||
// G4ConicalSurface::SetAngle( G4double e )
|
||||
//
|
||||
// End ---------------------------------------------------------------
|
||||
|
||||
#include "G4ConicalSurface.hh"
|
||||
#include "G4Sort.hh"
|
||||
#include "G4Globals.hh"
|
||||
|
||||
G4ConicalSurface::G4ConicalSurface() : G4Surface()
|
||||
{
|
||||
// default constructor
|
||||
// default axis is ( 1.0, 0.0, 0.0 ), default angle is 1.0 radians
|
||||
axis = G4Vector3D( 1.0, 0.0, 0.0 );
|
||||
angle = 1.0;
|
||||
}
|
||||
|
||||
G4ConicalSurface::G4ConicalSurface( const G4Point3D& o,
|
||||
const G4Vector3D& a,
|
||||
G4double e ) //: G4Surface( o )
|
||||
{
|
||||
// Normal constructor
|
||||
// require axis to be a unit vector
|
||||
/* L. Broglia
|
||||
G4double amag = a.Magnitude();
|
||||
|
||||
include/G4ThreeVec.hh: G4double Magnitude() const
|
||||
{ return sqrt( x*x + y*y + z*z ); }
|
||||
This function is mag2 for HepThreeVector
|
||||
*/
|
||||
G4double amag = a.mag2();
|
||||
|
||||
|
||||
if ( amag != 0.0 )
|
||||
/* L. Broglia
|
||||
axis = a / amag; // this makes the axis a unit vector
|
||||
*/
|
||||
axis = a*(1/amag);
|
||||
else {
|
||||
G4cerr << "Error in G4ConicalSurface::G4ConicalSurface"
|
||||
<<"--axis has zero length\n"
|
||||
<< "\tDefault axis ( 1.0, 0.0, 0.0 ) is used.\n";
|
||||
|
||||
axis = G4Vector3D( 1.0, 0.0, 0.0 );
|
||||
}
|
||||
|
||||
// Require angle to range from 0 to PI/2
|
||||
if ( ( e > 0.0 ) && ( e < ( 0.5 * M_PI ) ) )
|
||||
angle = e;
|
||||
else {
|
||||
G4cerr << "Error in G4ConicalSurface::G4ConicalSurface"
|
||||
<< "--asked for angle out of allowed range of 0 to PI/2\n"
|
||||
<< "\tDefault angle of 1.0 is used.\n";
|
||||
|
||||
angle = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void G4ConicalSurface::CalcBBox()
|
||||
{
|
||||
// Created by L. Broglia
|
||||
// copy of G4FPlane::CalcBBox()
|
||||
|
||||
bbox= new G4BoundingBox3D(surfaceBoundary.BBox().GetBoxMin(),
|
||||
surfaceBoundary.BBox().GetBoxMax());
|
||||
}
|
||||
|
||||
|
||||
void G4ConicalSurface::PrintOn( ostream& os ) const
|
||||
{
|
||||
// printing function using C++ ostream class
|
||||
os << "G4ConicalSurface surface with origin: " << origin << "\t"
|
||||
<< "angle: " << angle << " radians \tand axis " << axis << "\n";
|
||||
}
|
||||
|
||||
|
||||
G4double G4ConicalSurface::HowNear( const G4Vector3D& x ) const
|
||||
{
|
||||
// Distance from the point x to the semi-infinite G4ConicalSurface.
|
||||
// The distance will be positive if the point is Inside the G4ConicalSurface,
|
||||
// negative if the point is outside.
|
||||
// Note that this may not be correct for a bounded conical object
|
||||
// subclassed to G4ConicalSurface.
|
||||
|
||||
G4Vector3D d = x - origin;
|
||||
G4double l = d * axis;
|
||||
G4Vector3D q = origin + l * axis;
|
||||
G4Vector3D v = x - q;
|
||||
|
||||
/* L. Broglia
|
||||
G4double Dist = ( l * tan( angle ) - v.Magnitude() ) * cos ( angle );
|
||||
*/
|
||||
G4double Dist = ( l*tan(angle) - v.mag2() ) * cos(angle);
|
||||
|
||||
return Dist;
|
||||
}
|
||||
|
||||
|
||||
int G4ConicalSurface::Intersect( const G4Ray& ry )
|
||||
{
|
||||
// Distance along a Ray (straight line with G4Vector3D) to leave or enter
|
||||
// a G4ConicalSurface. The input variable which_way should be set to +1 to
|
||||
// indicate leaving a G4ConicalSurface, -1 to indicate entering a
|
||||
// G4ConicalSurface.
|
||||
// p is the point of intersection of the Ray with the G4ConicalSurface.
|
||||
// If the G4Vector3D of the Ray is opposite to that of the Normal to
|
||||
// the G4ConicalSurface at the intersection point, it will not leave the
|
||||
// G4ConicalSurface.
|
||||
// Similarly, if the G4Vector3D of the Ray is along that of the Normal
|
||||
// to the G4ConicalSurface at the intersection point, it will not enter the
|
||||
// G4ConicalSurface.
|
||||
// This method is called by all finite shapes sub-classed to
|
||||
// G4ConicalSurface.
|
||||
// Use the virtual function table to check if the intersection point
|
||||
// is within the boundary of the finite shape.
|
||||
// A negative result means no intersection.
|
||||
// If no valid intersection point is found, set the distance
|
||||
// and intersection point to large numbers.
|
||||
|
||||
int which_way = -1; //Originally a parameter.Read explanation above.
|
||||
|
||||
distance = FLT_MAXX;
|
||||
|
||||
// G4Vector3D lv ( FLT_MAXX, FLT_MAXX, FLT_MAXX );
|
||||
G4Vector3D lv ( FLT_MAXX, FLT_MAXX, FLT_MAXX );
|
||||
|
||||
// p = lv;
|
||||
closest_hit = lv;
|
||||
|
||||
// Origin and G4Vector3D unit vector of Ray.
|
||||
// G4Vector3D x = ry->position();
|
||||
G4Vector3D x = ry.GetStart();
|
||||
|
||||
// G4Vector3D dhat = ry->direction( 0.0 );
|
||||
G4Vector3D dhat = ry.GetDir();
|
||||
|
||||
|
||||
// Cone angle and axis unit vector.
|
||||
G4double ta = tan( GetAngle() );
|
||||
G4Vector3D ahat = GetAxis();
|
||||
int isoln = 0,
|
||||
maxsoln = 2;
|
||||
|
||||
// array of solutions in distance along the Ray
|
||||
// G4double s[2] = { -1.0, -1.0 };
|
||||
G4double s[2];
|
||||
s[0] = -1.0;
|
||||
s[1] = -1.0 ;
|
||||
|
||||
// calculate the two solutions (quadratic equation)
|
||||
G4Vector3D gamma = x - GetOrigin();
|
||||
G4double T = 1.0 + ta * ta;
|
||||
G4double ga = gamma * ahat;
|
||||
G4double da = dhat * ahat;
|
||||
G4double A = 1.0 - T * da * da;
|
||||
G4double B = 2.0 * ( gamma * dhat - T * ga * da );
|
||||
G4double C = gamma * gamma - T * ga * ga;
|
||||
|
||||
// if quadratic term vanishes, just do the simple solution
|
||||
if ( fabs( A ) < FLT_EPSILO )
|
||||
{
|
||||
if ( B == 0.0 )
|
||||
return 1;
|
||||
else
|
||||
s[0] = -C / B;
|
||||
}
|
||||
|
||||
// Normal quadratic case, no intersection if radical is less than zero
|
||||
else
|
||||
{
|
||||
G4double radical = B * B - 4.0 * A * C;
|
||||
if ( radical < 0.0 )
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
G4double root = sqrt( radical );
|
||||
s[0] = ( - B + root ) / ( 2. * A );
|
||||
s[1] = ( - B - root ) / ( 2. * A );
|
||||
}
|
||||
}
|
||||
|
||||
// order the possible solutions by increasing distance along the Ray
|
||||
// (G4Sorting routines are in support/G4Sort.h)
|
||||
G4Sort_double( s, isoln, maxsoln-1 );
|
||||
|
||||
// now loop over each positive solution, keeping the first one (smallest
|
||||
// distance along the Ray) which is within the boundary of the sub-shape
|
||||
// and which also has the correct G4Vector3D with respect to the Normal to
|
||||
// the G4ConicalSurface at the intersection point
|
||||
for ( isoln = 0; isoln < maxsoln; isoln++ )
|
||||
{
|
||||
if ( s[isoln] >= 0.0 )
|
||||
{
|
||||
if ( s[isoln] >= FLT_MAXX ) // quit if too large
|
||||
return 1;
|
||||
|
||||
distance = s[isoln];
|
||||
closest_hit = ry.GetPoint( distance );
|
||||
|
||||
// Following line necessary to select non-reflective solutions.
|
||||
if (( ahat * ( closest_hit - GetOrigin() ) > 0.0 ) &&
|
||||
((( dhat * SurfaceNormal( closest_hit ) * which_way )) >= 0.0 ) &&
|
||||
( fabs(HowNear( closest_hit )) < 0.1) )
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// get here only if there was no solution within the boundary, Reset
|
||||
// distance and intersection point to large numbers
|
||||
distance = FLT_MAXX;
|
||||
closest_hit = lv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
G4double G4ConicalSurface::distanceAlongHelix(int which_way, const Helix* hx,
|
||||
G4Vector3D& p ) const
|
||||
{ // Distance along a Helix to leave or enter a G4ConicalSurface.
|
||||
// The input variable which_way should be set to +1 to
|
||||
// indicate leaving a G4ConicalSurface, -1 to indicate entering a
|
||||
// G4ConicalSurface.
|
||||
// p is the point of intersection of the Helix with the G4ConicalSurface.
|
||||
// If the G4Vector3D of the Helix is opposite to that of the Normal to
|
||||
// the G4ConicalSurface at the intersection point, it will not leave the
|
||||
// G4ConicalSurface.
|
||||
// Similarly, if the G4Vector3D of the Helix is along that of the Normal
|
||||
// to the G4ConicalSurface at the intersection point, it will not enter the
|
||||
// G4ConicalSurface.
|
||||
// This method is called by all finite shapes sub-classed to
|
||||
// G4ConicalSurface.
|
||||
// Use the virtual function table to check if the intersection point
|
||||
// is within the boundary of the finite shape.
|
||||
// If no valid intersection point is found, set the distance
|
||||
// and intersection point to large numbers.
|
||||
// Possible negative distance solutions are discarded.
|
||||
G4double Dist = FLT_MAXX;
|
||||
G4Vector3D lv ( FLT_MAXX, FLT_MAXX, FLT_MAXX );
|
||||
p = lv;
|
||||
int isoln = 0, maxsoln = 4;
|
||||
|
||||
// Array of solutions in turning angle
|
||||
// G4double s[4] = { -1.0, -1.0, -1.0, -1.0 };
|
||||
G4double s[4];s[0] = -1.0; s[1]= -1.0 ;s[2] = -1.0; s[3]= -1.0 ;
|
||||
|
||||
// Flag set to 1 if exact solution is found
|
||||
int exact = 0;
|
||||
|
||||
// Helix parameters
|
||||
G4double rh = hx->GetRadius(); // radius of Helix
|
||||
G4Vector3D oh = hx->position(); // origin of Helix
|
||||
G4Vector3D dh = hx->direction( 0.0 ); // initial G4Vector3D of Helix
|
||||
G4Vector3D prp = hx->getPerp(); // perpendicular vector
|
||||
G4double prpmag = prp.Magnitude();
|
||||
G4double rhp = rh / prpmag;
|
||||
|
||||
// G4ConicalSurface parameters
|
||||
G4double ta = tan( GetAngle() ); // tangent of angle of G4ConicalSurface
|
||||
G4Vector3D oc = GetOrigin(); // origin of G4ConicalSurface
|
||||
G4Vector3D ac = GetAxis(); // axis of G4ConicalSurface
|
||||
|
||||
// Calculate quantities of use later on
|
||||
G4Vector3D alpha = rhp * prp;
|
||||
G4Vector3D beta = rhp * dh;
|
||||
G4Vector3D gamma = oh - oc;
|
||||
G4double T = 1.0 + ta * ta;
|
||||
G4double gc = gamma * ac;
|
||||
G4double bc = beta * ac;
|
||||
|
||||
// General approximate solution for sin(s)-->s and cos(s)-->1-s**2/2,
|
||||
// keeping only terms to second order in s
|
||||
G4double A = gamma * alpha - T * ( gc * alpha * ac - bc * bc ) +
|
||||
beta * beta;
|
||||
G4double B = 2.0 * ( gamma * beta - gc * bc * T );
|
||||
G4double C = gamma * gamma - gc * gc * T;
|
||||
|
||||
// Solution for no quadratic term
|
||||
if ( fabs( A ) < FLT_EPSILO )
|
||||
{
|
||||
if ( B == 0.0 )
|
||||
return Dist;
|
||||
else
|
||||
s[0] = -C / B;
|
||||
}
|
||||
|
||||
// General quadratic solutions
|
||||
else {
|
||||
G4double radical = B * B - 4.0 * A * C;
|
||||
if ( radical < 0.0 )
|
||||
// Radical is less than zero, either there is no intersection, or the
|
||||
// approximation doesn't hold, so try a cruder technique to find a
|
||||
// possible intersection point using the gropeAlongHelix function.
|
||||
s[0] = gropeAlongHelix( hx );
|
||||
// Normal non-negative radical solutions
|
||||
else {
|
||||
G4double root = sqrt( radical );
|
||||
s[0] = ( -B + root ) / ( 2.0 * A );
|
||||
s[1] = ( -B - root ) / ( 2.0 * A );
|
||||
if ( rh < 0.0 ) {
|
||||
s[0] = -s[0];
|
||||
s[1] = -s[1];
|
||||
}
|
||||
s[2] = s[0] + 2.0 * M_PI;
|
||||
s[3] = s[1] + 2.0 * M_PI;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Order the possible solutions by increasing turning angle
|
||||
// (G4Sorting routines are in support/G4Sort.h).
|
||||
G4Sort_double( s, isoln, maxsoln-1 );
|
||||
//
|
||||
// Now loop over each positive solution, keeping the first one (smallest
|
||||
// distance along the Helix) which is within the boundary of the sub-shape.
|
||||
for ( isoln = 0; isoln < maxsoln; isoln++ ) {
|
||||
if ( s[isoln] >= 0.0 ) {
|
||||
// Calculate distance along Helix and position and G4Vector3D vectors.
|
||||
Dist = s[isoln] * fabs( rhp );
|
||||
p = hx->position( Dist );
|
||||
G4Vector3D d = hx->direction( Dist );
|
||||
if ( exact == 0 ) { // only for approximate solns
|
||||
// Now do approximation to get remaining distance to correct this solution.
|
||||
// Iterate it until the accuracy is below the user-set surface precision.
|
||||
G4double delta = 0.;
|
||||
G4double delta0 = FLT_MAXX;
|
||||
int dummy = 1;
|
||||
int iter = 0;
|
||||
int in0 = Inside( hx->position() );
|
||||
int in1 = Inside( p );
|
||||
G4double sc = Scale();
|
||||
while ( dummy ) {
|
||||
iter++;
|
||||
// Terminate loop after 50 iterations and Reset distance to large number,
|
||||
// indicating no intersection with G4ConicalSurface.
|
||||
// This generally occurs if the Helix curls too tightly to Intersect it.
|
||||
if ( iter > 50 ) {
|
||||
Dist = FLT_MAXX;
|
||||
p = lv;
|
||||
break;
|
||||
}
|
||||
// Find distance from the current point along the above-calculated
|
||||
// G4Vector3D using a Ray.
|
||||
// The G4Vector3D of the Ray and the Sign of the distance are determined
|
||||
// by whether the starting point of the Helix is Inside or outside of
|
||||
// the G4ConicalSurface.
|
||||
in1 = Inside( p );
|
||||
if ( in1 ) { // current point Inside
|
||||
if ( in0 ) { // starting point Inside
|
||||
Ray* r = new Ray( p, d );
|
||||
delta =
|
||||
distanceAlongRay( 1, r, p );
|
||||
delete r;
|
||||
}
|
||||
else { // starting point outside
|
||||
Ray* r = new Ray( p, -d );
|
||||
delta =
|
||||
-distanceAlongRay( 1, r, p );
|
||||
delete r;
|
||||
}
|
||||
}
|
||||
else { // current point outside
|
||||
if ( in0 ) { // starting point Inside
|
||||
Ray* r = new Ray( p, -d );
|
||||
delta =
|
||||
-distanceAlongRay( -1, r, p );
|
||||
delete r;
|
||||
}
|
||||
else { // starting point outside
|
||||
Ray* r = new Ray( p, d );
|
||||
delta =
|
||||
distanceAlongRay( -1, r, p );
|
||||
delete r;
|
||||
}
|
||||
}
|
||||
// Test if distance is less than the surface precision, if so Terminate loop.
|
||||
if ( fabs( delta / sc ) <= SURFACE_PRECISION )
|
||||
break;
|
||||
// If delta has not changed sufficiently from the previous iteration,
|
||||
// skip out of this loop.
|
||||
if ( fabs( ( delta - delta0 ) / sc ) <=
|
||||
SURFACE_PRECISION )
|
||||
break;
|
||||
// If delta has increased in absolute value from the previous iteration
|
||||
// either the Helix doesn't Intersect the G4ConicalSurface or the approximate solution
|
||||
// is too far from the real solution. Try groping for a solution. If not
|
||||
// found, Reset distance to large number, indicating no intersection with
|
||||
// the G4ConicalSurface.
|
||||
if ( fabs( delta ) > fabs( delta0 ) ) {
|
||||
Dist = fabs( rhp ) *
|
||||
gropeAlongHelix( hx );
|
||||
if ( Dist < 0.0 ) {
|
||||
Dist = FLT_MAXX;
|
||||
p = lv;
|
||||
}
|
||||
else
|
||||
p = hx->position( Dist );
|
||||
break;
|
||||
}
|
||||
// Set old delta to new one.
|
||||
delta0 = delta;
|
||||
// Add distance to G4ConicalSurface to distance along Helix.
|
||||
Dist += delta;
|
||||
// Negative distance along Helix means Helix doesn't Intersect G4ConicalSurface.
|
||||
// Reset distance to large number, indicating no intersection with G4ConicalSurface.
|
||||
if ( Dist < 0.0 ) {
|
||||
Dist = FLT_MAXX;
|
||||
p = lv;
|
||||
break;
|
||||
}
|
||||
// Recalculate point along Helix and the G4Vector3D.
|
||||
p = hx->position( Dist );
|
||||
d = hx->direction( Dist );
|
||||
} // end of while loop
|
||||
} // end of exact == 0 condition
|
||||
// Now have best value of distance along Helix and position for this
|
||||
// solution, so test if it is within the boundary of the sub-shape
|
||||
// and require that it point in the correct G4Vector3D with respect to
|
||||
// the Normal to the G4ConicalSurface.
|
||||
if ( ( Dist < FLT_MAXX ) &&
|
||||
( ( hx->direction( Dist ) * Normal( p ) *
|
||||
which_way ) >= 0.0 ) &&
|
||||
( WithinBoundary( p ) == 1 ) )
|
||||
return Dist;
|
||||
} // end of if s[isoln] >= 0.0 condition
|
||||
} // end of for loop over solutions
|
||||
// If one gets here, there is no solution, so set distance along Helix
|
||||
// and position to large numbers.
|
||||
Dist = FLT_MAXX;
|
||||
p = lv;
|
||||
return Dist;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
G4Vector3D G4ConicalSurface::SurfaceNormal( const G4Point3D& p ) const
|
||||
{
|
||||
// return the Normal unit vector to the G4ConicalSurface at a point p
|
||||
// on (or nearly on) the G4ConicalSurface
|
||||
G4Vector3D s = p - origin;
|
||||
/* L. Broglia
|
||||
G4double smag = s.Magnitude();
|
||||
*/
|
||||
G4double smag = s.mag2();
|
||||
|
||||
// if the point happens to be at the origin, calculate a unit vector Normal
|
||||
// to the axis, with zero z component
|
||||
if ( smag == 0.0 )
|
||||
{
|
||||
G4double ax = axis.x();
|
||||
G4double ay = axis.y();
|
||||
G4double ap = sqrt( ax * ax + ay * ay );
|
||||
|
||||
if ( ap == 0.0 )
|
||||
return G4Vector3D( 1.0, 0.0, 0.0 );
|
||||
else
|
||||
return G4Vector3D( ay / ap, -ax / ap, 0.0 );
|
||||
}
|
||||
|
||||
// otherwise do the calculation of the Normal to the conical surface
|
||||
else
|
||||
{
|
||||
G4double l = s * axis;
|
||||
/* L. Broglia
|
||||
s = s / smag;
|
||||
*/
|
||||
s = s*(1/smag);
|
||||
G4Vector3D q = origin + l * axis;
|
||||
G4Vector3D v = p - q;
|
||||
/* L. Broglia
|
||||
G4double sl = v.Magnitude() * sin( angle );
|
||||
*/
|
||||
G4double sl = v.mag2() * sin( angle );
|
||||
G4Vector3D n = v - sl * s;
|
||||
/* L. Broglia
|
||||
G4double nmag = n.Magnitude();
|
||||
*/
|
||||
G4double nmag = n.mag2();
|
||||
|
||||
if ( nmag != 0.0 )
|
||||
/* L. Broglia
|
||||
n = n / nmag;
|
||||
*/
|
||||
n=n*(1/nmag);
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int G4ConicalSurface::Inside ( const G4Vector3D& x ) const
|
||||
{
|
||||
// Return 0 if point x is outside G4ConicalSurface, 1 if Inside.
|
||||
// Outside means that the distance to the G4ConicalSurface would be negative.
|
||||
// Use the HowNear function to calculate this distance.
|
||||
if ( HowNear( x ) >= -0.5*kCarTolerance )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int G4ConicalSurface::WithinBoundary( const G4Vector3D& x ) const
|
||||
{
|
||||
// return 1 if point x is on the G4ConicalSurface, otherwise return zero
|
||||
// base this on the surface precision factor set in support/globals.h
|
||||
if ( fabs( HowNear( x ) / Scale() ) <= SURFACE_PRECISION )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void G4ConicalSurface::SetAngle( G4double e )
|
||||
{
|
||||
// Reset the angle of the G4ConicalSurface
|
||||
// Require angle to range from 0 to PI/2
|
||||
// if ( ( e > 0.0 ) && ( e < ( 0.5 * M_PI ) ) )
|
||||
if ( (e > 0.0) && (e <= ( 0.5 * M_PI)) )
|
||||
angle = e;
|
||||
// use old value (do not change angle) if out of the range,
|
||||
//but Print message
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4ConicalSurface::SetAngle"
|
||||
<< "--asked for angle out of allowed range of 0 to PI/2\n"
|
||||
<< "\tDefault angle of " << angle << " is used.\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4ControlPoints.cc,v 2.6 1998/11/04 14:49:55 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
//
|
||||
// Modif 8 oct 98 : A.Floquet
|
||||
// G4PointRat datas are made of
|
||||
// . a point 3D
|
||||
// . a additional value : the scale factor which is set to 1 by default
|
||||
// G4ControlPoints includes only G4PointRat which in turn are made
|
||||
// of G4Point3D
|
||||
//
|
||||
|
||||
#include "G4ControlPoints.hh"
|
||||
|
||||
|
||||
G4ControlPoints::G4ControlPoints()
|
||||
{
|
||||
nr=nc=0;
|
||||
data=(G4PointRat**)0;
|
||||
}
|
||||
|
||||
|
||||
G4ControlPoints::G4ControlPoints( int rows, int columns)
|
||||
{
|
||||
nr=rows;
|
||||
nc=columns;
|
||||
data = (G4PointRat**) new G4PointRat *[nr*nc];
|
||||
|
||||
for(int a =0; a<nr*nc;a++)
|
||||
data[a]=new G4PointRat;
|
||||
}
|
||||
|
||||
|
||||
G4ControlPoints::G4ControlPoints( int point_type, int rows, int columns)
|
||||
{
|
||||
|
||||
// point_type is maintained only for compatibility
|
||||
// G4ControlPoints is now a array of G4pointRat only
|
||||
|
||||
nr=rows;
|
||||
nc=columns;
|
||||
data = (G4PointRat**)new G4PointRat *[nr*nc];
|
||||
|
||||
for(int a = 0; a < nr*nc ; a++ )
|
||||
data[a]=new G4PointRat;
|
||||
}
|
||||
|
||||
|
||||
G4ControlPoints::G4ControlPoints(const G4ControlPoints& old_points)
|
||||
{
|
||||
// copy constructor
|
||||
|
||||
nr = old_points.GetRows(); nc=old_points.GetCols();
|
||||
data = (G4PointRat**)new G4PointRat *[nr*nc];
|
||||
|
||||
G4int a, b;
|
||||
|
||||
for (a = 0; a < nr*nc ; a++ )
|
||||
data[a] = new G4PointRat;
|
||||
|
||||
for ( a = 0; a < nr ; a++ )
|
||||
for ( b = 0; b < nc ; b++ )
|
||||
put( a, b, old_points.GetRat(a,b));
|
||||
}
|
||||
|
||||
|
||||
G4ControlPoints::~G4ControlPoints()
|
||||
{
|
||||
for( int a = 0; a < nr*nc; a++)
|
||||
delete data[a];
|
||||
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
|
||||
void G4ControlPoints::SetWeights(G4double* weights)
|
||||
{
|
||||
for ( int a = 0; a < nr*nc; a++ )
|
||||
(data[a])->setW(weights[a]);
|
||||
}
|
||||
|
||||
|
||||
void G4ControlPoints::CalcValues ( G4double k1, G4double param,
|
||||
G4PointRat& pts1, G4double k2,
|
||||
G4PointRat& pts2 )
|
||||
{
|
||||
pts2.setX(Calc(k1,param,pts1.x(),k2,pts2.x()));
|
||||
pts2.setY(Calc(k1,param,pts1.y(),k2,pts2.y()));
|
||||
pts2.setZ(Calc(k1,param,pts1.z(),k2,pts2.z()));
|
||||
pts2.setW(Calc(k1,param,pts1.w(),k2,pts2.w()));
|
||||
}
|
||||
|
||||
|
||||
void G4ControlPoints::CalcValues(G4double k1, G4double param, G4Point3D& pts1,
|
||||
G4double k2, G4Point3D& pts2)
|
||||
{
|
||||
pts2.setX(Calc(k1,param,pts1.x(),k2,pts2.x()));
|
||||
pts2.setY(Calc(k1,param,pts1.y(),k2,pts2.y()));
|
||||
pts2.setZ(Calc(k1,param,pts1.z(),k2,pts2.z()));
|
||||
}
|
||||
|
||||
|
||||
G4double G4ControlPoints::ClosestDistanceToPoint( const G4Point3D& Pt)
|
||||
{
|
||||
// Square distance
|
||||
|
||||
G4double PointDist=1.e20;
|
||||
G4double TmpDist;
|
||||
G4Point3D Pt2;
|
||||
|
||||
for(int a=0;a<nr;a++)
|
||||
for(int b=0;b<nc;b++)
|
||||
{
|
||||
Pt2 = Get3D(a,b);
|
||||
TmpDist = Pt.distance2(Pt2);
|
||||
PointDist = ( PointDist > TmpDist ) ? TmpDist : PointDist;
|
||||
}
|
||||
|
||||
return PointDist;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4Curve.cc,v 2.3 1998/11/06 15:31:26 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4Curve.hh"
|
||||
|
||||
G4Curve::G4Curve():bounded(false),bBox(G4BoundingBox3D::space),
|
||||
sameSense(true){}
|
||||
|
||||
G4Curve::~G4Curve(){}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#include "G4CurvePoint.hh"
|
||||
|
||||
const G4int G4CurvePoint::pFlag= 1;
|
||||
const G4int G4CurvePoint::uFlag= 2;
|
||||
const G4int G4CurvePoint::allFlags= 0xFF; // lots of bits...
|
||||
@@ -0,0 +1,3 @@
|
||||
#include "G4CurveRayIntersection.hh"
|
||||
|
||||
const G4int G4CurveRayIntersection::dFlag= 4;
|
||||
@@ -0,0 +1,887 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4CylindricalSurface.cc,v 2.7 1998/12/10 11:02:55 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
/* /usr/local/gismo/repo/geometry/G4CylindricalSurface.cc,v 1.24 1994/08/03 17:15:09 burnett Exp */
|
||||
// File: G4CylindricalSurface.cc
|
||||
// Author: Alan Breakstone
|
||||
|
||||
// Contents ----------------------------------------------------------
|
||||
//
|
||||
// G4CylindricalSurface::G4CylindricalSurface()
|
||||
// G4CylindricalSurface::G4CylindricalSurface( const G4Vector3D& o,
|
||||
// const G4Vector3D& a,
|
||||
// G4double r )
|
||||
// G4CylindricalSurface::PrintOn( ostream& os ) const
|
||||
// G4CylindricalSurface::HowNear( const G4Vector3D& x ) const
|
||||
// G4CylindricalSurface::distanceAlongRay( int which_way, const Ray* ry,
|
||||
// G4Vector3D& p ) const
|
||||
// G4CylindricalSurface::distanceAlongHelix( int which_way,
|
||||
// const Helix* hx,
|
||||
// G4Vector3D& p ) const
|
||||
// G4CylindricalSurface::Normal( const G4Vector3D& p ) const
|
||||
// G4CylindricalSurface::Inside( const G4Vector3D& x ) const
|
||||
// G4CylindricalSurface::WithinBoundary( const G4Vector3D& x ) const
|
||||
// G4CylindricalSurface::Scale() const
|
||||
// G4CylindricalSurface::rotate( G4double alpha, G4double beta,
|
||||
// G4double gamma, G4ThreeMat& m, int inverse )
|
||||
// G4CylindricalSurface::rotate( G4double alpha, G4double beta,
|
||||
// G4double gamma, int inverse )
|
||||
// G4CylindricalSurface::SetRadius( G4double r )
|
||||
// G4CylindricalSurface::gropeAlongHelix( const Helix* hx ) const
|
||||
//
|
||||
// End ---------------------------------------------------------------
|
||||
|
||||
#include "G4CylindricalSurface.hh"
|
||||
#include "G4Sort.hh"
|
||||
#include "G4Globals.hh"
|
||||
|
||||
G4CylindricalSurface::G4CylindricalSurface() : G4Surface()
|
||||
{
|
||||
// default constructor
|
||||
// default axis is ( 1.0, 0.0, 0.0 ), default radius is 1.0
|
||||
axis = G4Vector3D( 1.0, 0.0, 0.0 );
|
||||
radius = 1.0;
|
||||
}
|
||||
|
||||
|
||||
G4CylindricalSurface::G4CylindricalSurface( const G4Vector3D& o,
|
||||
const G4Vector3D& a,
|
||||
G4double r ) //: G4Surface( o )
|
||||
{
|
||||
// Normal constructor
|
||||
// require axis to be a unit vector
|
||||
G4double amag = a.mag();
|
||||
if ( amag != 0.0 )
|
||||
axis = a * (1/ amag); // this makes the axis a unit vector
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4CylindricalSurface::G4CylindricalSurface--axis "
|
||||
<<"has zero length\n"
|
||||
<< "\tDefault axis ( 1.0, 0.0, 0.0 ) is used.\n";
|
||||
|
||||
axis = G4Vector3D( 1.0, 0.0, 0.0 );
|
||||
}
|
||||
|
||||
// Require radius to be non-negative
|
||||
if ( r >= 0.0 )
|
||||
radius = r;
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4CylindricalSurface::G4CylindricalSurface"
|
||||
<< "--asked for negative radius\n"
|
||||
<< "\tDefault radius of 1.0 is used.\n";
|
||||
|
||||
radius = 1.0;
|
||||
}
|
||||
|
||||
origin =o;
|
||||
}
|
||||
|
||||
|
||||
void G4CylindricalSurface::PrintOn( ostream& os ) const
|
||||
{
|
||||
// printing function using C++ ostream class
|
||||
os << "G4CylindricalSurface surface with origin: " << origin << "\t"
|
||||
<< "radius: " << radius << "\tand axis " << axis << "\n";
|
||||
}
|
||||
|
||||
//int G4Surface::Intersect(const G4Ray& ry)
|
||||
int G4CylindricalSurface::Intersect(const G4Ray& ry)
|
||||
{
|
||||
|
||||
// L. Broglia : copy of G4FCylindricalSurface::Intersect
|
||||
|
||||
// Distance along a Ray (straight line with G4ThreeVec) to leave or enter
|
||||
// a G4CylindricalSurface. The input variable which_way should be set
|
||||
// to +1 to indicate leaving a G4CylindricalSurface, -1 to indicate
|
||||
// entering a G4CylindricalSurface.
|
||||
// p is the point of intersection of the Ray with the G4CylindricalSurface.
|
||||
// If the G4Vector3D of the Ray is opposite to that of the Normal to
|
||||
// the G4CylindricalSurface at the intersection point, it will not leave
|
||||
// the G4CylindricalSurface.
|
||||
// Similarly, if the G4Vector3D of the Ray is along that of the Normal
|
||||
// to the G4CylindricalSurface at the intersection point, it will not enter
|
||||
// the G4CylindricalSurface.
|
||||
// This method is called by all finite shapes sub-classed to
|
||||
// G4CylindricalSurface.
|
||||
// Use the virtual function table to check if the intersection point
|
||||
// is within the boundary of the finite shape.
|
||||
// A negative result means no intersection.
|
||||
// If no valid intersection point is found, set the distance
|
||||
// and intersection point to large numbers.
|
||||
|
||||
// int which_way = -1;
|
||||
//Originally a parameter.Read explanation above.
|
||||
|
||||
int which_way=1;
|
||||
|
||||
if(!Inside(ry.GetStart()))
|
||||
which_way = -1;
|
||||
|
||||
distance = FLT_MAXX;
|
||||
G4Vector3D lv ( FLT_MAXX, FLT_MAXX, FLT_MAXX );
|
||||
|
||||
closest_hit = lv;
|
||||
|
||||
// Origin and G4Vector3D unit vector of Ray.
|
||||
G4Vector3D x = ry.GetStart();
|
||||
G4Vector3D dhat = ry.GetDir();
|
||||
|
||||
// Axis unit vector of the G4CylindricalSurface.
|
||||
G4Vector3D ahat = GetAxis();
|
||||
int isoln = 0,
|
||||
maxsoln = 2;
|
||||
|
||||
// array of solutions in distance along the Ray
|
||||
G4double s[2];
|
||||
s[0] = -1.0;
|
||||
s[1] = -1.0 ;
|
||||
|
||||
// calculate the two solutions (quadratic equation)
|
||||
G4Vector3D d = x - GetOrigin();
|
||||
G4double radiu = GetRadius();
|
||||
|
||||
//quit with no intersection if the radius of the G4CylindricalSurface is zero
|
||||
// if ( radiu <= 0.0 )
|
||||
// return 0;
|
||||
|
||||
G4double dsq = d * d;
|
||||
G4double da = d * ahat;
|
||||
G4double dasq = da * da;
|
||||
G4double rsq = radiu * radiu;
|
||||
G4double qsq = dsq - dasq;
|
||||
G4double dira = dhat * ahat;
|
||||
G4double a = 1.0 - dira * dira;
|
||||
|
||||
if ( a <= 0.0 )
|
||||
return 0;
|
||||
|
||||
G4double b = 2. * ( d * dhat - da * dira );
|
||||
G4double c = rsq - qsq;
|
||||
G4double radical = b * b + 4. * a * c;
|
||||
|
||||
if ( radical < 0.0 )
|
||||
return 0;
|
||||
|
||||
G4double root = sqrt( radical );
|
||||
s[0] = ( - b + root ) / ( 2. * a );
|
||||
s[1] = ( - b - root ) / ( 2. * a );
|
||||
|
||||
// order the possible solutions by increasing distance along the Ray
|
||||
// (G4Sorting routines are in support/G4Sort.h)
|
||||
G4Sort_double( s, isoln, maxsoln-1 );
|
||||
|
||||
// now loop over each positive solution, keeping the first one (smallest
|
||||
// distance along the Ray) which is within the boundary of the sub-shape
|
||||
// and which also has the correct G4Vector3D with respect to the Normal to
|
||||
// the G4CylindricalSurface at the intersection point
|
||||
for ( isoln = 0; isoln < maxsoln; isoln++ )
|
||||
{
|
||||
if ( s[isoln] >= kCarTolerance*0.5 )
|
||||
{
|
||||
if ( s[isoln] >= FLT_MAXX ) // quit if too large
|
||||
return 0;
|
||||
|
||||
distance = s[isoln];
|
||||
closest_hit = ry.GetPoint( distance );
|
||||
G4double tmp = dhat * (Normal( closest_hit ));
|
||||
|
||||
if ((tmp * which_way) >= 0.0 )
|
||||
if ( WithinBoundary( closest_hit ) == 1 )
|
||||
distance = distance*distance;
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// get here only if there was no solution within the boundary, Reset
|
||||
// distance and intersection point to large numbers
|
||||
distance = FLT_MAXX;
|
||||
closest_hit = lv;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
G4double G4CylindricalSurface::HowNear( const G4Vector3D& x ) const
|
||||
{
|
||||
// Distance from the point x to the infinite G4CylindricalSurface.
|
||||
// The distance will be positive if the point is Inside the
|
||||
// G4CylindricalSurface, negative if the point is outside.
|
||||
// Note that this may not be correct for a bounded cylindrical object
|
||||
// subclassed to G4CylindricalSurface.
|
||||
G4Vector3D d = x - origin;
|
||||
G4double dA = d * axis;
|
||||
G4double rad = sqrt( d.mag2() - dA*dA );
|
||||
G4double hownear = fabs( radius - rad );
|
||||
|
||||
return hownear;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
G4double G4CylindricalSurface::distanceAlongRay( int which_way, const G4Ray* ry,
|
||||
G4Vector3D& p ) const
|
||||
{ // Distance along a Ray (straight line with G4Vector3D) to leave or enter
|
||||
// a G4CylindricalSurface. The input variable which_way should be set to +1 to
|
||||
// indicate leaving a G4CylindricalSurface, -1 to indicate entering a G4CylindricalSurface.
|
||||
// p is the point of intersection of the Ray with the G4CylindricalSurface.
|
||||
// If the G4Vector3D of the Ray is opposite to that of the Normal to
|
||||
// the G4CylindricalSurface at the intersection point, it will not leave the G4CylindricalSurface.
|
||||
// Similarly, if the G4Vector3D of the Ray is along that of the Normal
|
||||
// to the G4CylindricalSurface at the intersection point, it will not enter the
|
||||
// G4CylindricalSurface.
|
||||
// This method is called by all finite shapes sub-classed to G4CylindricalSurface.
|
||||
// Use the virtual function table to check if the intersection point
|
||||
// is within the boundary of the finite shape.
|
||||
// A negative result means no intersection.
|
||||
// If no valid intersection point is found, set the distance
|
||||
// and intersection point to large numbers.
|
||||
G4double Dist = FLT_MAXX;
|
||||
G4Vector3D lv ( FLT_MAXX, FLT_MAXX, FLT_MAXX );
|
||||
p = lv;
|
||||
// Origin and G4Vector3D unit vector of Ray.
|
||||
G4Vector3D x = ry->Position();
|
||||
G4Vector3D dhat = ry->Direction( 0.0 );
|
||||
// Axis unit vector of the G4CylindricalSurface.
|
||||
G4Vector3D ahat = GetAxis();
|
||||
int isoln = 0, maxsoln = 2;
|
||||
// array of solutions in distance along the Ray
|
||||
// G4double s[2] = { -1.0, -1.0 };
|
||||
G4double s[2];s[0] = -1.0; s[1]= -1.0 ;
|
||||
// calculate the two solutions (quadratic equation)
|
||||
G4Vector3D d = x - GetOrigin();
|
||||
G4double radius = GetRadius();
|
||||
// quit with no intersection if the radius of the G4CylindricalSurface is zero
|
||||
if ( radius <= 0.0 )
|
||||
return Dist;
|
||||
G4double dsq = d * d;
|
||||
G4double da = d * ahat;
|
||||
G4double dasq = da * da;
|
||||
G4double rsq = radius * radius;
|
||||
G4double qsq = dsq - dasq;
|
||||
G4double dira = dhat * ahat;
|
||||
G4double a = 1.0 - dira * dira;
|
||||
if ( a <= 0.0 )
|
||||
return Dist;
|
||||
G4double b = 2. * ( d * dhat - da * dira );
|
||||
G4double c = rsq - qsq;
|
||||
G4double radical = b * b + 4. * a * c;
|
||||
if ( radical < 0.0 )
|
||||
return Dist;
|
||||
G4double root = sqrt( radical );
|
||||
s[0] = ( - b + root ) / ( 2. * a );
|
||||
s[1] = ( - b - root ) / ( 2. * a );
|
||||
// order the possible solutions by increasing distance along the Ray
|
||||
// (G4Sorting routines are in support/G4Sort.h)
|
||||
G4Sort_double( s, isoln, maxsoln-1 );
|
||||
// now loop over each positive solution, keeping the first one (smallest
|
||||
// distance along the Ray) which is within the boundary of the sub-shape
|
||||
// and which also has the correct G4Vector3D with respect to the Normal to
|
||||
// the G4CylindricalSurface at the intersection point
|
||||
for ( isoln = 0; isoln < maxsoln; isoln++ ) {
|
||||
if ( s[isoln] >= 0.0 ) {
|
||||
if ( s[isoln] >= FLT_MAXX ) // quit if too large
|
||||
return Dist;
|
||||
Dist = s[isoln];
|
||||
p = ry->Position( Dist );
|
||||
if ( ( ( dhat * Normal( p ) * which_way ) >= 0.0 )
|
||||
&& ( WithinBoundary( p ) == 1 ) )
|
||||
return Dist;
|
||||
}
|
||||
}
|
||||
// get here only if there was no solution within the boundary, Reset
|
||||
// distance and intersection point to large numbers
|
||||
p = lv;
|
||||
return FLT_MAXX;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
|
||||
G4double G4CylindricalSurface::distanceAlongHelix( int which_way, const Helix* hx,
|
||||
G4Vector3D& p ) const
|
||||
{ // Distance along a Helix to leave or enter a G4CylindricalSurface.
|
||||
// The input variable which_way should be set to +1 to
|
||||
// indicate leaving a G4CylindricalSurface, -1 to indicate entering a G4CylindricalSurface.
|
||||
// p is the point of intersection of the Helix with the G4CylindricalSurface.
|
||||
// If the G4Vector3D of the Helix is opposite to that of the Normal to
|
||||
// the G4CylindricalSurface at the intersection point, it will not leave the G4CylindricalSurface.
|
||||
// Similarly, if the G4Vector3D of the Helix is along that of the Normal
|
||||
// to the G4CylindricalSurface at the intersection point, it will not enter the
|
||||
// G4CylindricalSurface.
|
||||
// This method is called by all finite shapes sub-classed to G4CylindricalSurface.
|
||||
// Use the virtual function table to check if the intersection point
|
||||
// is within the boundary of the finite shape.
|
||||
// If no valid intersection point is found, set the distance
|
||||
// and intersection point to large numbers.
|
||||
// Possible negative distance solutions are discarded.
|
||||
G4double Dist = FLT_MAXX;
|
||||
G4Vector3D lv ( FLT_MAXX, FLT_MAXX, FLT_MAXX );
|
||||
G4Vector3D zerovec; // zero G4Vector3D
|
||||
p = lv;
|
||||
int isoln = 0, maxsoln = 4;
|
||||
// Array of solutions in turning angle
|
||||
// G4double s[4] = { -1.0, -1.0, -1.0, -1.0 };
|
||||
G4double s[4];s[0]=-1.0;s[1]= -1.0;s[2]= -1.0;s[3]= -1.0;
|
||||
|
||||
|
||||
// Flag set to 1 if exact solution is found
|
||||
int exact = 0;
|
||||
// Helix parameters
|
||||
G4double rh = hx->GetRadius(); // radius of Helix
|
||||
G4Vector3D ah = hx->GetAxis(); // axis of Helix
|
||||
G4Vector3D oh = hx->position(); // origin of Helix
|
||||
G4Vector3D dh = hx->direction( 0.0 ); // initial G4Vector3D of Helix
|
||||
G4Vector3D prp = hx->getPerp(); // perpendicular vector
|
||||
G4double prpmag = prp.Magnitude();
|
||||
G4double rhp = rh / prpmag;
|
||||
// G4CylindricalSurface parameters
|
||||
G4double rc = GetRadius(); // radius of G4CylindricalSurface
|
||||
if ( rc == 0.0 ) // quit if zero radius
|
||||
return Dist;
|
||||
G4Vector3D oc = GetOrigin(); // origin of G4CylindricalSurface
|
||||
G4Vector3D ac = GetAxis(); // axis of G4CylindricalSurface
|
||||
//
|
||||
// Calculate quantities of use later on.
|
||||
G4Vector3D alpha = rhp * prp;
|
||||
G4Vector3D beta = rhp * dh;
|
||||
G4Vector3D gamma = oh - oc;
|
||||
// Declare variables used later on in several places.
|
||||
G4double rcd2 = 0.0, alpha2 = 0.0;
|
||||
G4double A = 0.0, B = 0.0, C = 0.0, F = 0.0, G = 0.0, H = 0.0;
|
||||
G4double CoverB = 0.0, radical = 0.0, root = 0.0, s1 = 0.0, s2 = 0.0;
|
||||
G4Vector3D ghat;
|
||||
//
|
||||
// Set flag for special cases
|
||||
int special_case = 0; // 0 means general case
|
||||
//
|
||||
// Test to see if axes of Helix and G4CylindricalSurface are parallel, in which case
|
||||
// there are exact solutions.
|
||||
if ( ( fabs( ah.AngleBetween(ac) ) < FLT_EPSILO )
|
||||
|| ( fabs( ah.AngleBetween(ac) - M_PI ) < FLT_EPSILO ) ) {
|
||||
special_case = 1;
|
||||
// If, in addition, gamma is a zero vector or is parallel to the G4CylindricalSurface
|
||||
// axis, this simplifies the previous case.
|
||||
if ( gamma == zerovec ) {
|
||||
special_case = 3;
|
||||
ghat = gamma;
|
||||
}
|
||||
else {
|
||||
ghat = gamma / gamma.Magnitude();
|
||||
if ( ( fabs( ghat.AngleBetween(ac) ) < FLT_EPSILO )
|
||||
|| ( fabs( ghat.AngleBetween(ac) - M_PI ) <
|
||||
FLT_EPSILO ) )
|
||||
special_case = 3;
|
||||
}
|
||||
// Test to see if, in addition to the axes of the Helix and G4CylindricalSurface being
|
||||
// parallel, the axis of the G4CylindricalSurface is perpendicular to the initial
|
||||
// G4Vector3D of the Helix.
|
||||
if ( fabs( ( ac * dh ) ) < FLT_EPSILO ) {
|
||||
// And, if, in addition to all this, the difference in origins of the Helix
|
||||
// and G4CylindricalSurface is perpendicular to the initial G4Vector3D of the Helix,
|
||||
// there is a separate special case.
|
||||
if ( fabs( ( ghat * dh ) ) < FLT_EPSILO )
|
||||
special_case = 4;
|
||||
}
|
||||
} // end of section with axes of Helix and G4CylindricalSurface parallel
|
||||
//
|
||||
// Another peculiar case occurs if the axis of the G4CylindricalSurface and the initial
|
||||
// G4Vector3D of the Helix line up and their origins are the same. This will
|
||||
// require a higher order approximation than the general case.
|
||||
if ( ( ( fabs( dh.AngleBetween(ac) ) < FLT_EPSILO )
|
||||
|| ( fabs( dh.AngleBetween(ac) - M_PI ) < FLT_EPSILO ) )
|
||||
&& ( gamma == zerovec ) )
|
||||
special_case = 2;
|
||||
//
|
||||
// Now all the special cases have been tagged, so solutions are found
|
||||
// for each case. Exact solutions are indicated by setting exact = 1.
|
||||
// [For some reason switch doesn't work here, so do series of if's.]
|
||||
if ( special_case == 0 ) { // approximate quadratic solutions
|
||||
A = beta * beta - ( beta * ac ) * ( beta * ac )
|
||||
+ gamma * alpha - ( gamma * ac ) * ( alpha * ac );
|
||||
B = 2.0 * gamma * beta
|
||||
- 2.0 * ( gamma * ac ) * ( beta * ac );
|
||||
C = gamma * gamma
|
||||
- ( gamma * ac ) * ( gamma * ac ) - rc * rc;
|
||||
if ( fabs( A ) < FLT_EPSILO ) { // no quadratic term
|
||||
if ( B == 0.0 ) // no intersection, quit
|
||||
return Dist;
|
||||
else // B != 0
|
||||
s[0] = -C / B;
|
||||
}
|
||||
else { // A != 0, general quadratic solution
|
||||
radical = B * B - 4.0 * A * C;
|
||||
if ( radical < 0.0 ) // no solution, quit
|
||||
return Dist;
|
||||
root = sqrt( radical );
|
||||
s[0] = ( -B + root ) / ( 2.0 * A );
|
||||
s[1] = ( -B - root ) / ( 2.0 * A );
|
||||
if ( rh < 0.0 ) {
|
||||
s[0] = -s[0];
|
||||
s[1] = -s[1];
|
||||
}
|
||||
s[2] = s[0] + 2.0 * M_PI;
|
||||
s[3] = s[1] + 2.0 * M_PI;
|
||||
}
|
||||
}
|
||||
//
|
||||
else if ( special_case == 1 ) { // exact solutions
|
||||
exact = 1;
|
||||
H = 2.0 * ( alpha * alpha + gamma * alpha );
|
||||
F = gamma * gamma
|
||||
- ( ( gamma * ac ) * ( gamma * ac ) )
|
||||
- rc * rc + H;
|
||||
G = 2.0 * rhp *
|
||||
( gamma * dh - ( gamma * ac ) * ( ac * dh ) );
|
||||
A = G * G + H * H;
|
||||
B = -2.0 * F * H;
|
||||
C = F * F - G * G;
|
||||
if ( fabs( A ) < FLT_EPSILO ) { // no quadratic term
|
||||
if ( B == 0.0 ) // no intersection, quit
|
||||
return Dist;
|
||||
else { // B != 0
|
||||
CoverB = -C / B;
|
||||
if ( fabs( CoverB ) > 1.0 )
|
||||
return Dist;
|
||||
s[0] = acos( CoverB );
|
||||
}
|
||||
}
|
||||
else { // A != 0, general quadratic solution
|
||||
// Try a different method of calculation using F, G, and H to avoid
|
||||
// precision problems.
|
||||
// radical = B * B - 4.0 * A * C;
|
||||
// if ( radical < 0.0 ) {
|
||||
if ( fabs( H ) > FLT_EPSILO ) {
|
||||
G4double r1 = G / H;
|
||||
G4double r2 = F / H;
|
||||
G4double radsq = 1.0 + r1*r1 - r2*r2;
|
||||
if ( radsq < 0.0 )
|
||||
return Dist;
|
||||
root = G * sqrt( radsq );
|
||||
G4double denominator = H * ( 1.0 + r1*r1 );
|
||||
s1 = ( F + root ) / denominator;
|
||||
s2 = ( F - root ) / denominator;
|
||||
}
|
||||
else
|
||||
return Dist;
|
||||
// } // end radical < 0 condition
|
||||
// else {
|
||||
// root = sqrt( radical );
|
||||
// s1 = ( -B + root ) / ( 2.0 * A );
|
||||
// s2 = ( -B - root ) / ( 2.0 * A );
|
||||
// }
|
||||
if ( fabs( s1 ) <= 1.0 ) {
|
||||
s[0] = acos( s1 );
|
||||
s[2] = 2.0 * M_PI - s[0];
|
||||
}
|
||||
if ( fabs( s2 ) <= 1.0 ) {
|
||||
s[1] = acos( s2 );
|
||||
s[3] = 2.0 * M_PI - s[1];
|
||||
}
|
||||
// Must take only solutions which satisfy original unsquared equation:
|
||||
// Gsin(s) - Hcos(s) + F = 0. Take best solution of pair and set false
|
||||
// solutions to -1. Only do this if the result is significantly different
|
||||
// from zero.
|
||||
G4double temp1 = 0.0, temp2 = 0.0;
|
||||
G4double rsign = 1.0;
|
||||
if ( rh < 0.0 ) rsign = -1.0;
|
||||
if ( s[0] > 0.0 ) {
|
||||
temp1 = G * rsign * sin( s[0] )
|
||||
- H * cos( s[0] ) + F;
|
||||
temp2 = G * rsign * sin( s[2] )
|
||||
- H * cos( s[2] ) + F;
|
||||
if ( fabs( temp1 ) > fabs( temp2 ) )
|
||||
if ( fabs( temp1 ) > FLT_EPSILO )
|
||||
s[0] = -1.0;
|
||||
else
|
||||
if ( fabs( temp2 ) > FLT_EPSILO )
|
||||
s[2] = -1.0;
|
||||
}
|
||||
if ( s[1] > 0.0 ) {
|
||||
temp1 = G * rsign * sin( s[1] )
|
||||
- H * cos( s[1] ) + F;
|
||||
temp2 = G * rsign * sin( s[3] )
|
||||
- H * cos( s[3] ) + F;
|
||||
if ( fabs( temp1 ) > fabs( temp2 ) )
|
||||
if ( fabs( temp1 ) > FLT_EPSILO )
|
||||
s[1] = -1.0;
|
||||
else
|
||||
if ( fabs( temp2 ) > FLT_EPSILO )
|
||||
s[3] = -1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
else if ( special_case == 2 ) { // approximate solution
|
||||
G4Vector3D e = ah.cross( ac );
|
||||
G4double re = fabs( rhp ) * e.Magnitude();
|
||||
s[0] = sqrt( 2.0 * rc / re );
|
||||
}
|
||||
//
|
||||
else if ( special_case == 3 ) { // exact solutions
|
||||
exact = 1;
|
||||
alpha2 = alpha * alpha;
|
||||
rcd2 = rhp * rhp * ( 1.0 - ( (ac*dh) * (ac*dh) ) );
|
||||
A = alpha2 - rcd2;
|
||||
B = - 2.0 * alpha2;
|
||||
C = alpha2 + rcd2 - rc*rc;
|
||||
if ( fabs( A ) < FLT_EPSILO ) { // no quadratic term
|
||||
if ( B == 0.0 ) // no intersection, quit
|
||||
return Dist;
|
||||
else { // B != 0
|
||||
CoverB = -C / B;
|
||||
if ( fabs( CoverB ) > 1.0 )
|
||||
return Dist;
|
||||
s[0] = acos( CoverB );
|
||||
}
|
||||
}
|
||||
else { // A != 0, general quadratic solution
|
||||
radical = B * B - 4.0 * A * C;
|
||||
if ( radical < 0.0 )
|
||||
return Dist;
|
||||
root = sqrt( radical );
|
||||
s1 = ( -B + root ) / ( 2.0 * A );
|
||||
s2 = ( -B - root ) / ( 2.0 * A );
|
||||
if ( fabs( s1 ) <= 1.0 )
|
||||
s[0] = acos( s1 );
|
||||
if ( fabs( s2 ) <= 1.0 )
|
||||
s[1] = acos( s2 );
|
||||
}
|
||||
}
|
||||
//
|
||||
else if ( special_case == 4 ) { // exact solution
|
||||
exact = 1;
|
||||
F = gamma * gamma
|
||||
- ( ( gamma * ac ) * ( gamma * ac ) )
|
||||
- rc * rc;
|
||||
G = 2.0 * ( rhp * rhp + gamma * alpha );
|
||||
if ( G == 0.0 ) // no intersection, quit
|
||||
return Dist;
|
||||
G4double cs = 1.0 + ( F / G );
|
||||
if ( fabs( cs ) > 1.0 ) // no intersection, quit
|
||||
return Dist;
|
||||
s[0] = acos( cs );
|
||||
}
|
||||
//
|
||||
else // shouldn't get here
|
||||
return Dist;
|
||||
//
|
||||
// **************************************************************************
|
||||
//
|
||||
// Order the possible solutions by increasing turning angle
|
||||
// (G4Sorting routines are in support/G4Sort.h).
|
||||
G4Sort_double( s, isoln, maxsoln-1 );
|
||||
//
|
||||
// Now loop over each positive solution, keeping the first one (smallest
|
||||
// distance along the Helix) which is within the boundary of the sub-shape.
|
||||
for ( isoln = 0; isoln < maxsoln; isoln++ ) {
|
||||
if ( s[isoln] >= 0.0 ) {
|
||||
// Calculate distance along Helix and position and G4Vector3D vectors.
|
||||
Dist = s[isoln] * fabs( rhp );
|
||||
p = hx->position( Dist );
|
||||
G4Vector3D d = hx->direction( Dist );
|
||||
if ( exact == 0 ) { // only for approximate solns
|
||||
// Now do approximation to get remaining distance to correct this solution
|
||||
// iterate it until the accuracy is below the user-set surface precision.
|
||||
G4double delta = 0.0;
|
||||
G4double delta0 = FLT_MAXX;
|
||||
int dummy = 1;
|
||||
int iter = 0;
|
||||
int in0 = Inside( hx->position ( 0.0 ) );
|
||||
int in1 = Inside( p );
|
||||
G4double sc = Scale();
|
||||
while ( dummy ) {
|
||||
iter++;
|
||||
// Terminate loop after 50 iterations and Reset distance to large number,
|
||||
// indicating no intersection with G4CylindricalSurface.
|
||||
// This generally occurs if the Helix curls too tightly to Intersect it.
|
||||
if ( iter > 50 ) {
|
||||
Dist = FLT_MAXX;
|
||||
p = lv;
|
||||
break;
|
||||
}
|
||||
// Find distance from the current point along the above-calculated
|
||||
// G4Vector3D using a Ray.
|
||||
// The G4Vector3D of the Ray and the Sign of the distance are determined
|
||||
// by whether the starting point of the Helix is Inside or outside of
|
||||
// the G4CylindricalSurface.
|
||||
in1 = Inside( p );
|
||||
if ( in1 ) { // current point Inside
|
||||
if ( in0 ) { // starting point Inside
|
||||
Ray* r = new Ray( p, d );
|
||||
delta =
|
||||
distanceAlongRay( 1, r, p );
|
||||
delete r;
|
||||
}
|
||||
else { // starting point outside
|
||||
Ray* r = new Ray( p, -d );
|
||||
delta =
|
||||
-distanceAlongRay( 1, r, p );
|
||||
delete r;
|
||||
}
|
||||
}
|
||||
else { // current point outside
|
||||
if ( in0 ) { // starting point Inside
|
||||
Ray* r = new Ray( p, -d );
|
||||
delta =
|
||||
-distanceAlongRay( -1, r, p );
|
||||
delete r;
|
||||
}
|
||||
else { // starting point outside
|
||||
Ray* r = new Ray( p, d );
|
||||
delta =
|
||||
distanceAlongRay( -1, r, p );
|
||||
delete r;
|
||||
}
|
||||
}
|
||||
// Test if distance is less than the surface precision, if so Terminate loop.
|
||||
if ( fabs( delta / sc ) <= SURFACE_PRECISION )
|
||||
break;
|
||||
// If delta has not changed sufficiently from the previous iteration,
|
||||
// skip out of this loop.
|
||||
if ( fabs( ( delta - delta0 ) / sc ) <=
|
||||
SURFACE_PRECISION )
|
||||
break;
|
||||
// If delta has increased in absolute value from the previous iteration
|
||||
// either the Helix doesn't Intersect the G4CylindricalSurface or the approximate solution
|
||||
// is too far from the real solution. Try groping for a solution. If not
|
||||
// found, Reset distance to large number, indicating no intersection with
|
||||
// the G4CylindricalSurface.
|
||||
if ( fabs( delta ) > fabs( delta0 ) ) {
|
||||
Dist = fabs( rhp ) *
|
||||
gropeAlongHelix( hx );
|
||||
if ( Dist < 0.0 ) {
|
||||
Dist = FLT_MAXX;
|
||||
p = lv;
|
||||
}
|
||||
else
|
||||
p = hx->position( Dist );
|
||||
break;
|
||||
}
|
||||
// Set old delta to new one.
|
||||
delta0 = delta;
|
||||
// Add distance to G4CylindricalSurface to distance along Helix.
|
||||
Dist += delta;
|
||||
// Negative distance along Helix means Helix doesn't Intersect G4CylindricalSurface.
|
||||
// Reset distance to large number, indicating no intersection with G4CylindricalSurface.
|
||||
if ( Dist < 0.0 ) {
|
||||
Dist = FLT_MAXX;
|
||||
p = lv;
|
||||
break;
|
||||
}
|
||||
// Recalculate point along Helix and the G4Vector3D.
|
||||
p = hx->position( Dist );
|
||||
d = hx->direction( Dist );
|
||||
} // end of while loop
|
||||
} // end of exact == 0 condition
|
||||
// Now have best value of distance along Helix and position for this
|
||||
// solution, so test if it is within the boundary of the sub-shape
|
||||
// and require that it point in the correct G4Vector3D with respect to
|
||||
// the Normal to the G4CylindricalSurface.
|
||||
if ( ( Dist < FLT_MAXX ) &&
|
||||
( ( hx->direction( Dist ) * Normal( p ) *
|
||||
which_way ) >= 0.0 ) &&
|
||||
( WithinBoundary( p ) == 1 ) )
|
||||
return Dist;
|
||||
} // end of if s[isoln] >= 0.0 condition
|
||||
} // end of for loop over solutions
|
||||
// if one gets here, there is no solution, so set distance along Helix
|
||||
// and position to large numbers
|
||||
Dist = FLT_MAXX;
|
||||
p = lv;
|
||||
return Dist;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
G4Vector3D G4CylindricalSurface::Normal( const G4Vector3D& p ) const
|
||||
{
|
||||
// return the Normal unit vector to the G4CylindricalSurface
|
||||
// at a point p on (or nearly on) the G4CylindricalSurface
|
||||
|
||||
G4Vector3D n = ( p - origin ) - ( ( p - origin ) * axis ) * axis;
|
||||
G4double nmag = n.mag();
|
||||
|
||||
if ( nmag != 0.0 )
|
||||
n = n * (1/nmag);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
G4Vector3D G4CylindricalSurface::SurfaceNormal( const G4Point3D& p ) const
|
||||
{
|
||||
// return the Normal unit vector to the G4CylindricalSurface at a point
|
||||
// p on (or nearly on) the G4CylindricalSurface
|
||||
|
||||
G4Vector3D n = ( p - origin ) - ( ( p - origin ) * axis ) * axis;
|
||||
G4double nmag = n.mag();
|
||||
|
||||
if ( nmag != 0.0 )
|
||||
n = n * (1/nmag);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
int G4CylindricalSurface::Inside ( const G4Vector3D& x ) const
|
||||
{
|
||||
// Return 0 if point x is outside G4CylindricalSurface, 1 if Inside.
|
||||
// Outside means that the distance to the G4CylindricalSurface would
|
||||
// be negative.
|
||||
// Use the HowNear function to calculate this distance.
|
||||
if ( HowNear( x ) >= -0.5*kCarTolerance )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int G4CylindricalSurface::WithinBoundary( const G4Vector3D& x ) const
|
||||
{
|
||||
// return 1 if point x is on the G4CylindricalSurface, otherwise return zero
|
||||
// base this on the surface precision factor set in support/globals.h
|
||||
if ( fabs( HowNear( x ) / Scale() ) <= SURFACE_PRECISION )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
G4double G4CylindricalSurface::Scale() const
|
||||
{
|
||||
// Returns the radius of a G4CylindricalSurface unless it is zero, in which
|
||||
// case returns the arbitrary number 1.0.
|
||||
// This is ok since derived finite-sized classes will overwrite this.
|
||||
// Used for Scale-invariant tests of surface thickness.
|
||||
if ( radius == 0.0 )
|
||||
return 1.0;
|
||||
else
|
||||
return radius;
|
||||
}
|
||||
|
||||
|
||||
//void G4CylindricalSurface::rotate( G4double alpha, G4double beta,
|
||||
// G4double gamma, G4ThreeMat& m, int inverse )
|
||||
// // rotate G4CylindricalSurface first about global x-axis by angle alpha,
|
||||
// second about global y-axis by angle beta,
|
||||
// and third about global z-axis by angle gamma
|
||||
// by creating and using G4ThreeMat objects in Surface::rotate
|
||||
// angles are assumed to be given in radians
|
||||
// if inverse is non-zero, the order of rotations is reversed
|
||||
// the axis is rotated here, the origin is rotated by calling
|
||||
// Surface::rotate
|
||||
// G4Surface::rotate( alpha, beta, gamma, m, inverse );
|
||||
// axis = m * axis;
|
||||
//}
|
||||
|
||||
//void G4CylindricalSurface::rotate( G4double alpha, G4double beta,
|
||||
// G4double gamma, int inverse )
|
||||
//{ // rotate G4CylindricalSurface first about global x-axis by angle alpha,
|
||||
// second about global y-axis by angle beta,
|
||||
// and third about global z-axis by angle gamma
|
||||
// by creating and using G4ThreeMat objects in Surface::rotate
|
||||
// angles are assumed to be given in radians
|
||||
// if inverse is non-zero, the order of rotations is reversed
|
||||
// the axis is rotated here, the origin is rotated by calling
|
||||
// Surface::rotate
|
||||
// G4ThreeMat m;
|
||||
// G4Surface::rotate( alpha, beta, gamma, m, inverse );
|
||||
// axis = m * axis;
|
||||
//}
|
||||
|
||||
|
||||
void G4CylindricalSurface::SetRadius( G4double r )
|
||||
{
|
||||
// Reset the radius of the G4CylindricalSurface
|
||||
// Require radius to be non-negative
|
||||
if ( r >= 0.0 )
|
||||
radius = r;
|
||||
// use old value (do not change radius) if out of the range,
|
||||
// but Print message
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4CylindricalSurface::SetRadius"
|
||||
<< "--asked for negative radius\n"
|
||||
<< "\tDefault radius of " << radius << " is used.\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
G4double G4CylindricalSurface::gropeAlongHelix( const Helix* hx ) const
|
||||
{ // Grope for a solution of a Helix intersecting a G4CylindricalSurface.
|
||||
// This function returns the turning angle (in radians) where the
|
||||
// intersection occurs with only positive values allowed, or -1.0 if
|
||||
// no intersection is found.
|
||||
// The idea is to start at the beginning of the Helix, then take steps
|
||||
// of some fraction of a turn. If at the end of a Step, the current position
|
||||
// along the Helix and the previous position are on opposite sides of the
|
||||
// G4CylindricalSurface, then the solution must lie somewhere in between.
|
||||
int one_over_f = 8; // one over fraction of a turn to go in each Step
|
||||
G4double turn_angle = 0.0;
|
||||
G4double dist_along = 0.0;
|
||||
G4double d_new;
|
||||
G4double fk = 1.0 / G4double( one_over_f );
|
||||
G4double scal = Scale();
|
||||
G4double d_old = HowNear( hx->position( dist_along ) );
|
||||
G4double rh = hx->GetRadius(); // radius of Helix
|
||||
G4Vector3D prp = hx->getPerp(); // perpendicular vector
|
||||
G4double prpmag = prp.Magnitude();
|
||||
G4double rhp = rh / prpmag;
|
||||
int max_iter = one_over_f * HELIX_MAX_TURNS;
|
||||
// Take up to a user-settable number of turns along the Helix,
|
||||
// groping for an intersection point.
|
||||
for ( int k = 1; k < max_iter; k++ ) {
|
||||
turn_angle = 2.0 * M_PI * k / one_over_f;
|
||||
dist_along = turn_angle * fabs( rhp );
|
||||
d_new = HowNear( hx->position( dist_along ) );
|
||||
if ( ( d_old < 0.0 && d_new > 0.0 ) ||
|
||||
( d_old > 0.0 && d_new < 0.0 ) ) {
|
||||
d_old = d_new;
|
||||
// Old and new points are on opposite sides of the G4CylindricalSurface, therefore
|
||||
// a solution lies in between, use a binary search to pin the point down
|
||||
// to the surface precision, but don't do more than 50 iterations.
|
||||
int itr = 0;
|
||||
while ( fabs( d_new / scal ) > SURFACE_PRECISION ) {
|
||||
itr++;
|
||||
if ( itr > 50 )
|
||||
return turn_angle;
|
||||
turn_angle -= fk * M_PI;
|
||||
dist_along = turn_angle * fabs( rhp );
|
||||
d_new = HowNear( hx->position( dist_along ) );
|
||||
if ( ( d_old < 0.0 && d_new > 0.0 ) ||
|
||||
( d_old > 0.0 && d_new < 0.0 ) )
|
||||
fk *= -0.5;
|
||||
else
|
||||
fk *= 0.5;
|
||||
d_old = d_new;
|
||||
} // end of while loop
|
||||
return turn_angle; // this is the best solution
|
||||
} // end of if condition
|
||||
} // end of for loop
|
||||
// Get here only if no solution is found, so return -1.0 to indicate that.
|
||||
return -1.0;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4Ellipse.cc,v 2.9 1998/12/08 14:04:24 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
|
||||
#include "G4Ellipse.hh"
|
||||
|
||||
// G4Ellipse
|
||||
G4Ellipse::G4Ellipse(){}
|
||||
|
||||
G4Curve* G4Ellipse::Project(const G4Transform3D& tr)
|
||||
{
|
||||
G4Point3D newLocation = tr*position.GetLocation();
|
||||
newLocation.setZ(0);
|
||||
G4double axisZ = ( tr*position.GetPZ() ).unit().z();
|
||||
|
||||
if (abs(axisZ)<kAngTolerance)
|
||||
return 0;
|
||||
|
||||
G4Vector3D newAxis(0, 0, axisZ>0? +1: -1);
|
||||
|
||||
// get the parameter of an endpoint of an axis
|
||||
// (this is a point the distance of which from the center is extreme)
|
||||
G4Vector3D xPrime= tr*position.GetPX();
|
||||
xPrime.setZ(0);
|
||||
G4Vector3D yPrime= tr*position.GetPY();
|
||||
yPrime.setZ(0);
|
||||
|
||||
G4Vector3D a = semiAxis1*xPrime;
|
||||
G4Vector3D b = semiAxis2*yPrime;
|
||||
G4double u = atan2( 2*a*b, a.mag2()-b.mag2() ) / 2;
|
||||
|
||||
// get the coordinate axis directions and the semiaxis lengths
|
||||
G4Vector3D sAxis1 = a*cos(u)+b*sin(u);
|
||||
G4Vector3D sAxis2 = a*cos(u+pi/2)+b*sin(u+pi/2);
|
||||
G4double newSemiAxis1 = sAxis1.mag();
|
||||
G4double newSemiAxis2 = sAxis2.mag();
|
||||
G4Vector3D newRefDirection = sAxis1;
|
||||
|
||||
// create the new ellipse
|
||||
G4Axis2Placement3D newPosition;
|
||||
newPosition.Init(newRefDirection, newAxis, newLocation);
|
||||
G4Ellipse* r= new G4Ellipse;
|
||||
r->Init(newPosition, newSemiAxis1, newSemiAxis2);
|
||||
|
||||
// introduce the shift in the parametrization
|
||||
// maybe the Sign must be changed?
|
||||
r->SetPShift(u);
|
||||
|
||||
// set the bounds when necessary
|
||||
if (IsBounded())
|
||||
r->SetBounds(GetPStart(), GetPEnd());
|
||||
|
||||
// L. Broglia
|
||||
// copy sense of the curve
|
||||
r->SetSameSense(GetSameSense());
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
G4Ellipse::~G4Ellipse(){}
|
||||
|
||||
|
||||
void G4Ellipse::InitBounded()
|
||||
{
|
||||
// original implementation
|
||||
// const G4Point3D& center = position.GetLocation();
|
||||
// G4double maxEntent = max(semiAxis1, semiAxis2);
|
||||
// G4Vector3D halfExtent(maxEntent, maxEntent, maxEntent);
|
||||
// bBox.Init(center+halfExtent, center-halfExtent);
|
||||
|
||||
// the bbox must include the start and endpoints as well as the
|
||||
// extreme points if they lie on the curve
|
||||
bBox.Init(GetStart(), GetEnd());
|
||||
|
||||
// the parameter values
|
||||
// belonging to the points with an extreme x, y and z coordinate
|
||||
for (G4int i=0; i<3; i++)
|
||||
{
|
||||
G4double u= atan2(position.GetPY()(i)*semiAxis2,
|
||||
position.GetPX()(i)*semiAxis1);
|
||||
if (IsPOn(u))
|
||||
bBox.Extend(GetPoint(u));
|
||||
|
||||
if (IsPOn(u+pi))
|
||||
bBox.Extend(GetPoint(u+pi));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
G4bool G4Ellipse::Tangent(G4CurvePoint& cp, G4Vector3D& v)
|
||||
{
|
||||
// The tangent is computed from the 3D point representation
|
||||
// for all conics. An alternaive implementation (based on
|
||||
// the parametric point) might be worthwhile adding
|
||||
// for efficiency.
|
||||
|
||||
const G4Axis2Placement3D& pos = *(GetPosition());
|
||||
G4Point3D p= pos.GetToPlacementCoordinates() * cp.GetPoint();
|
||||
|
||||
v=forTangent*p.y()*pos.GetPX() + p.x()*pos.GetPY();
|
||||
if(GetSameSense())
|
||||
v = -v;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,488 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4FConicalSurface.cc,v 2.16 1998/12/10 17:26:41 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
/* /usr/local/gismo/repo/geometry/G4FConicalSurface.cc,v 1.2 1993/02/05 00:38:39 alanb Exp */
|
||||
// File: G4FConicalSurface.cc
|
||||
// Author: Alan Breakstone
|
||||
|
||||
// Contents ----------------------------------------------------------
|
||||
//
|
||||
// G4FConicalSurface::G4FConicalSurface( const G4Point3D& o,
|
||||
// const G4Vector3D& a,
|
||||
// G4double l, G4double sr, G4double lr )
|
||||
// G4FConicalSurface::G4FConicalSurface( const G4FConicalSurface& c )
|
||||
// G4FConicalSurface::PrintOn( ostream& os ) const
|
||||
// G4FConicalSurface::operator==( const G4FConicalSurface& c )
|
||||
// G4FConicalSurface::WithinBoundary( const G4Vector3D& x ) const
|
||||
// G4FConicalSurface::Scale() const
|
||||
// G4FConicalSurface::Area() const
|
||||
// G4FConicalSurface::resize( G4double l, G4double sr, G4double lr )
|
||||
//
|
||||
// End ---------------------------------------------------------------
|
||||
|
||||
#include "G4FConicalSurface.hh"
|
||||
#include "G4Sort.hh"
|
||||
#include "G4CircularCurve.hh"
|
||||
|
||||
|
||||
G4FConicalSurface::G4FConicalSurface(const G4Point3D& o,
|
||||
const G4Vector3D& a,
|
||||
G4double l,
|
||||
G4double sr,
|
||||
G4double lr
|
||||
) //: G4ConicalSurface( o, a, 1.0 )
|
||||
//: G4Surface( o ) doesn`t exist
|
||||
{
|
||||
// Make a G4FConicalSurface with origin o, axis a, length l, small radius
|
||||
// sr, and large radius lr. The angle is calculated below and the SetAngle
|
||||
// function of G4ConicalSurface is used to set it properly from the default
|
||||
// value used above in the initialization.
|
||||
|
||||
// L. Broglia
|
||||
// Position.SetSrfPoint(o);
|
||||
// Position.SetAxis(a);
|
||||
// Create the position with origin o, axis a, and a direction wich
|
||||
// is not important
|
||||
G4Vector3D dir(1,1,1);
|
||||
Position.Init(dir, a, o);
|
||||
origin = o;
|
||||
|
||||
// Require length to be nonnegative
|
||||
// if ( l > 0.0 )
|
||||
if (l >=0)
|
||||
length = l;
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4FConicalSurface::G4FConicalSurface"
|
||||
<< "--asked for negative length\n"
|
||||
<< "\tDefault length of 0.0 is used.\n";
|
||||
|
||||
length = 0.0;
|
||||
}
|
||||
|
||||
// Require small radius to be non-negative (i.e., allow zero)
|
||||
if ( sr >= 0.0 )
|
||||
small_radius = sr;
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4FConicalSurface::G4FConicalSurface"
|
||||
<< "--asked for negative small radius\n"
|
||||
<< "\tDefault value of 0.0 is used.\n";
|
||||
|
||||
small_radius = 0.0;
|
||||
}
|
||||
|
||||
// Require large radius to exceed small radius
|
||||
if ( lr > small_radius )
|
||||
large_radius = lr;
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4FConicalSurface::G4FConicalSurface"
|
||||
<< "--large radius must exceed small radius\n"
|
||||
<< "\tDefault value of small radius +1 is used.\n";
|
||||
|
||||
large_radius = small_radius + 1.0;
|
||||
}
|
||||
|
||||
// Calculate the angle of the G4ConicalSurface from the length and radii
|
||||
tan_angle = ( large_radius - small_radius ) / length ;
|
||||
}
|
||||
|
||||
|
||||
G4FConicalSurface::G4FConicalSurface( const G4FConicalSurface& c )
|
||||
//: G4ConicalSurface( c.origin, c.GetAxis(), c.GetAngle() )
|
||||
{
|
||||
// copy constructor
|
||||
small_radius = c.small_radius;
|
||||
large_radius = c.large_radius;
|
||||
length = c.length;
|
||||
tan_angle = c.tan_angle;
|
||||
}
|
||||
|
||||
|
||||
// Modified by L. Broglia (01/12/98)
|
||||
void G4FConicalSurface::CalcBBox()
|
||||
{
|
||||
G4Point3D Max = -PINFINITY;
|
||||
G4Point3D Min = PINFINITY;
|
||||
G4Point3D Tmp;
|
||||
G4double delta = small_radius / tan_angle;
|
||||
|
||||
G4Point3D Origin = Position.GetLocation();
|
||||
G4Point3D EndOrigin = Origin + (length * Position.GetAxis());
|
||||
|
||||
G4double radius = large_radius;
|
||||
G4Point3D Radius(radius, radius, 0);
|
||||
|
||||
// Default BBox
|
||||
G4Point3D Tolerance(kCarTolerance, kCarTolerance, kCarTolerance);
|
||||
G4Point3D BoxMin(Origin-Tolerance);
|
||||
G4Point3D BoxMax(Origin+Tolerance);
|
||||
|
||||
bbox = new G4BoundingBox3D();
|
||||
bbox->Init(BoxMin, BoxMax);
|
||||
|
||||
Tmp = (Origin - Radius);
|
||||
bbox->Extend(Tmp);
|
||||
|
||||
Tmp = Origin + Radius;
|
||||
bbox->Extend(Tmp);
|
||||
|
||||
Tmp = EndOrigin - Radius;
|
||||
bbox->Extend(Tmp);
|
||||
|
||||
Tmp = EndOrigin + Radius;
|
||||
bbox->Extend(Tmp);
|
||||
}
|
||||
|
||||
|
||||
void G4FConicalSurface::PrintOn( ostream& os ) const
|
||||
{
|
||||
// printing function using C++ ostream class
|
||||
os << "G4FConicalSurface with origin: " << origin << "\t"
|
||||
<< "and axis: " << Position.GetAxis() << "\n"
|
||||
<< "\t small radius: " << small_radius
|
||||
<< "\t large radius: " << large_radius
|
||||
<< "\t and length: " << length << "\n";
|
||||
}
|
||||
|
||||
|
||||
int G4FConicalSurface::operator==( const G4FConicalSurface& c )
|
||||
{
|
||||
return ( origin == c.origin &&
|
||||
Position.GetAxis() == c.Position.GetAxis() &&
|
||||
small_radius == c.small_radius &&
|
||||
large_radius == c.large_radius &&
|
||||
length == c.length &&
|
||||
tan_angle == c.tan_angle );
|
||||
}
|
||||
|
||||
|
||||
int G4FConicalSurface::WithinBoundary( const G4Vector3D& x ) const
|
||||
{
|
||||
// return 1 if point x is within the boundaries of the G4FConicalSurface
|
||||
// return 0 otherwise (assume it is on the G4ConicalSurface)
|
||||
G4Vector3D q = x - origin;
|
||||
|
||||
G4double qmag = q.mag();
|
||||
G4double s = sin( atan2(large_radius-small_radius, length) );
|
||||
G4double ls = small_radius / s;
|
||||
G4double ll = large_radius / s;
|
||||
|
||||
if ( ( qmag >= ls ) && ( qmag <= ll ) )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
G4double G4FConicalSurface::Scale() const
|
||||
{
|
||||
// Returns the small radius of a G4FConicalSurface unless it is zero, in
|
||||
// which case returns the large radius.
|
||||
// Used for Scale-invariant tests of surface thickness.
|
||||
if ( small_radius == 0.0 )
|
||||
return large_radius;
|
||||
else
|
||||
return small_radius;
|
||||
}
|
||||
|
||||
|
||||
G4double G4FConicalSurface::Area() const
|
||||
{
|
||||
// Returns the Area of a G4FConicalSurface
|
||||
G4double rdif = large_radius - small_radius;
|
||||
|
||||
return ( M_PI * ( small_radius + large_radius ) *
|
||||
sqrt( length * length + rdif * rdif ) );
|
||||
}
|
||||
|
||||
|
||||
void G4FConicalSurface::resize( G4double l, G4double sr, G4double lr )
|
||||
{
|
||||
// Resize a G4FConicalSurface to a new length l, and new radii sr and lr.
|
||||
// Must Reset angle of the G4ConicalSurface as well based on these new
|
||||
// values.
|
||||
// Require length to be non-negative
|
||||
|
||||
// if ( l > 0.0 )
|
||||
if ( l >= 0.0 )
|
||||
length = l;
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4FConicalSurface::resize"
|
||||
<< "--asked for negative length\n"
|
||||
<< "\tOriginal value of " << length << " is retained.\n";
|
||||
}
|
||||
|
||||
// Require small radius to be non-negative (i.e., allow zero)
|
||||
if ( sr >= 0.0 )
|
||||
small_radius = sr;
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4FConicalSurface::resize"
|
||||
<< "--asked for negative small radius\n"
|
||||
<< "\tOriginal value of " << small_radius
|
||||
<< " is retained.\n";
|
||||
}
|
||||
|
||||
// Require large radius to exceed small radius
|
||||
if ( lr > small_radius )
|
||||
large_radius = lr;
|
||||
else
|
||||
{
|
||||
G4double r = small_radius + 1.0;
|
||||
lr = ( large_radius <= small_radius ) ? r : large_radius;
|
||||
large_radius = lr;
|
||||
|
||||
G4cerr << "Error in G4FConicalSurface::G4FConicalSurface"
|
||||
<< "--large radius must exceed small radius\n"
|
||||
<< "\tDefault value of " << large_radius << " is used.\n";
|
||||
}
|
||||
|
||||
// Calculate the angle of the G4ConicalSurface from the length and radii
|
||||
tan_angle = ( large_radius - small_radius ) / length ;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int G4FConicalSurface::Intersect(const G4Ray& ry )
|
||||
{
|
||||
// Distance along a Ray (straight line with G4Vector3D) to leave or enter
|
||||
// a G4FConicalSurface. The input variable which_way should be set to +1 to
|
||||
// indicate leaving a G4ConicalSurface, -1 to indicate entering a
|
||||
// G4ConicalSurface.
|
||||
// p is the point of intersection of the Ray with the G4ConicalSurface.
|
||||
// If the G4Vector3D of the Ray is opposite to that of the Normal to
|
||||
// the G4FConicalSurface at the intersection point, it will not leave the
|
||||
// G4FConicalSurface.
|
||||
// Similarly, if the G4Vector3D of the Ray is along that of the Normal
|
||||
// to the G4ConicalSurface at the intersection point, it will not enter the
|
||||
// G4ConicalSurface.
|
||||
// This method is called by all finite shapes sub-classed to
|
||||
// G4ConicalSurface.
|
||||
// Use the virtual function table to check if the intersection point
|
||||
// is within the boundary of the finite shape.
|
||||
// A negative result means no intersection.
|
||||
// If no valid intersection point is found, set the distance
|
||||
// and intersection point to large numbers.
|
||||
|
||||
int which_way;
|
||||
|
||||
if(Inside(ry.GetStart()))
|
||||
which_way = 1;
|
||||
else
|
||||
which_way = -1;
|
||||
|
||||
distance = FLT_MAXX;
|
||||
|
||||
G4Vector3D lv ( FLT_MAXX, FLT_MAXX, FLT_MAXX );
|
||||
closest_hit = lv;
|
||||
|
||||
// Origin and G4Vector3D unit vector of Ray.
|
||||
|
||||
G4Vector3D x = ry.GetStart();
|
||||
G4Vector3D dhat = ry.GetDir();
|
||||
|
||||
// Cone angle and axis unit vector.
|
||||
G4double ta = tan_angle;
|
||||
G4Vector3D ahat = Position.GetAxis();
|
||||
int isoln = 0, maxsoln = 2;
|
||||
|
||||
// array of solutions in distance along the Ray
|
||||
G4double s[2];
|
||||
s[0]=-1.0;
|
||||
s[1]=-1.0;
|
||||
|
||||
// L. Broglia
|
||||
// calculate the two solutions (quadratic equation)
|
||||
|
||||
G4Vector3D gamma = x - Position.GetLocation();
|
||||
|
||||
G4double T = 1.0 + ta * ta;
|
||||
G4double ga = gamma * ahat;
|
||||
G4double da = dhat * ahat;
|
||||
/*
|
||||
G4double A = 1.0 - T * da * da;
|
||||
G4double B = 2.0 * ( gamma * dhat - T * ga * da );
|
||||
G4double C = gamma * gamma - T * ga * ga;
|
||||
*/
|
||||
|
||||
G4double A = - 1.0 + T * da * da;
|
||||
G4double B = 2 * ( -gamma * dhat + T * ga * da - large_radius * ta * da);
|
||||
G4double C = ( -gamma * gamma + T * ga * ga
|
||||
- 2 * large_radius * ta * ga
|
||||
+ large_radius * large_radius );
|
||||
|
||||
|
||||
// if quadratic term vanishes, just do the simple solution
|
||||
if ( fabs( A ) < FLT_EPSILO )
|
||||
if ( B == 0.0 )
|
||||
return 1;
|
||||
else
|
||||
s[0] = -C / B;
|
||||
|
||||
// Normal quadratic case, no intersection if radical is less than zero
|
||||
else
|
||||
{
|
||||
G4double radical = B * B - 4.0 * A * C;
|
||||
|
||||
if ( radical < 0.0 )
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
G4double root = sqrt( radical );
|
||||
s[0] = ( - B + root ) / ( 2. * A );
|
||||
s[1] = ( - B - root ) / ( 2. * A );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// order the possible solutions by increasing distance along the Ray
|
||||
// (G4Sorting routines are in support/G4Sort.h)
|
||||
G4Sort_double( s, isoln, maxsoln-1 );
|
||||
|
||||
// now loop over each positive solution, keeping the first one (smallest
|
||||
// distance along the Ray) which is within the boundary of the sub-shape
|
||||
// and which also has the correct G4Vector3D with respect to the Normal to
|
||||
// the G4ConicalSurface at the intersection point
|
||||
for ( isoln = 0; isoln < maxsoln; isoln++ )
|
||||
{
|
||||
if ( s[isoln] >= kCarTolerance*0.5 )
|
||||
{
|
||||
if ( s[isoln] >= FLT_MAXX ) // quit if too large
|
||||
return 0;
|
||||
|
||||
distance = s[isoln];
|
||||
closest_hit = ry.GetPoint( distance );
|
||||
|
||||
|
||||
// Following line necessary to select non-reflective solutions.
|
||||
if ((( ahat * ( closest_hit - Position.GetLocation() ) > 0.0 ) &&
|
||||
((( dhat * SurfaceNormal( closest_hit ) * which_way ) >= 0.0 )) &&
|
||||
( fabs(HowNear( closest_hit )) < 0.1)) )
|
||||
{
|
||||
if ( WithinBoundary ( closest_hit ) == 1 )
|
||||
{
|
||||
distance = distance*distance;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
distance = distance*distance;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
if ( s[isoln] >= -kCarTolerance*0.5 )
|
||||
{
|
||||
// the point is on the surface
|
||||
distance = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// get here only if there was no solution within the boundary, Reset
|
||||
// distance and intersection point to large numbers
|
||||
distance = FLT_MAXX;
|
||||
closest_hit = lv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
G4double G4FConicalSurface::HowNear( const G4Vector3D& x ) const
|
||||
{
|
||||
// Distance from the point x to the semi-infinite G4FConicalSurface.
|
||||
// The distance will be positive if the point is Inside the G4ConicalSurface,
|
||||
// negative if the point is outside.
|
||||
// Note that this may not be correct for a bounded conical object
|
||||
// subclassed to G4ConicalSurface.
|
||||
|
||||
G4Vector3D d = x - origin;
|
||||
G4double dA = d * Position.GetAxis();
|
||||
G4double rad = sqrt( d.mag2() - dA*dA );
|
||||
G4double teta = atan2( (large_radius - small_radius) , length );
|
||||
G4double radiu = fabs( rad - large_radius + dA*tan_angle );
|
||||
G4double hownear ;
|
||||
|
||||
if (dA > length)
|
||||
hownear =dA - length;
|
||||
else if (dA < 0)
|
||||
hownear =dA;
|
||||
else
|
||||
hownear = radiu * cos(teta);
|
||||
|
||||
return hownear;
|
||||
}
|
||||
|
||||
|
||||
// Add by L. Broglia
|
||||
// Verify this function
|
||||
G4Vector3D G4FConicalSurface::SurfaceNormal( const G4Point3D& p ) const
|
||||
{
|
||||
// return the Normal unit vector to the G4ConicalSurface at a point p
|
||||
// on (or nearly on) the G4ConicalSurface
|
||||
G4Vector3D s = p - origin;
|
||||
G4double smag = s.mag2();
|
||||
|
||||
// if the point happens to be at the origin, calculate a unit vector Normal
|
||||
// to the axis, with zero z component
|
||||
if ( smag == 0.0 )
|
||||
{
|
||||
G4double ax = Position.GetAxis().x();
|
||||
G4double ay = Position.GetAxis().y();
|
||||
G4double ap = sqrt( ax * ax + ay * ay );
|
||||
|
||||
if ( ap == 0.0 )
|
||||
return G4Vector3D( 1.0, 0.0, 0.0 );
|
||||
else
|
||||
return G4Vector3D( ay / ap, -ax / ap, 0.0 );
|
||||
}
|
||||
|
||||
// otherwise do the calculation of the Normal to the conical surface
|
||||
else
|
||||
{
|
||||
G4double l = s * Position.GetAxis();
|
||||
|
||||
s = s*(1/smag);
|
||||
G4Vector3D q = origin + l * Position.GetAxis();
|
||||
G4Vector3D v = p - q;
|
||||
|
||||
G4double sl = v.mag2() *
|
||||
sin( atan2((large_radius - small_radius), length) );
|
||||
|
||||
G4Vector3D n = v - sl * s;
|
||||
|
||||
G4double nmag = n.mag2();
|
||||
|
||||
if ( nmag != 0.0 )
|
||||
n=n*(1/nmag);
|
||||
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
// Add by L. Broglia
|
||||
int G4FConicalSurface::Inside ( const G4Vector3D& x ) const
|
||||
{
|
||||
// Return 0 if point x is outside G4ConicalSurface, 1 if Inside.
|
||||
// Outside means that the distance to the G4ConicalSurface would be negative.
|
||||
// Use the HowNear function to calculate this distance.
|
||||
if ( HowNear( x ) >= -0.5*kCarTolerance )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,359 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4FCylindricalSurface.cc,v 2.14 1998/12/10 17:26:42 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
/* /usr/local/gismo/repo/geometry/FG4Cylinder.cc,v 1.1 1992/10/27 22:02:29 alanb Exp */
|
||||
// File: FG4Cylinder.cc
|
||||
// Author: Alan Breakstone
|
||||
|
||||
// Contents ----------------------------------------------------------
|
||||
//
|
||||
// FG4Cylinder::FG4Cylinder( const G4Point3D& o, const G4ThreeVec& a,
|
||||
// G4double r, G4double l )
|
||||
// FG4Cylinder::FG4Cylinder( const FG4Cylinder& c )
|
||||
// FG4Cylinder::PrintOn( ostream& os ) const
|
||||
// FG4Cylinder::operator==( const FG4Cylinder& c )
|
||||
// FG4Cylinder::WithinBoundary( const G4ThreeVec& x ) const
|
||||
// FG4Cylinder::Scale() const
|
||||
// FG4Cylinder::resize( G4double r, G4double l )
|
||||
//
|
||||
// End ---------------------------------------------------------------
|
||||
|
||||
#include "G4FCylindricalSurface.hh"
|
||||
#include "G4Sort.hh"
|
||||
|
||||
|
||||
G4FCylindricalSurface::G4FCylindricalSurface( const G4Point3D& o,
|
||||
const G4Vector3D& a,
|
||||
const G4double r,
|
||||
const G4double l
|
||||
)
|
||||
{
|
||||
// make a G4FCylindricalSurface with origin o, axis a,
|
||||
// radius r, and length l
|
||||
G4Vector3D dir(1,1,1);
|
||||
Position.Init(dir, a, o);
|
||||
origin = o;
|
||||
|
||||
|
||||
// Require length to be positive or zero
|
||||
// if ( l > 0.0 )
|
||||
if ( l >= 0.0 )
|
||||
length = l;
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4FCylindricalSurface::G4FCylindricalSurface"
|
||||
<< "--asked for negative length\n"
|
||||
<< "\tDefault length of 0.0 is used.\n";
|
||||
|
||||
length = 0.0;
|
||||
}
|
||||
|
||||
// Require radius to be non-negative (i.e., allow zero)
|
||||
if ( r >= 0.0 )
|
||||
radius = r;
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4FCylindricalSurface::G4FCylindricalSurface"
|
||||
<< "--asked for negative radius\n"
|
||||
<< "\tDefault value of 0.0 is used.\n";
|
||||
|
||||
radius = 0.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// copy constructor
|
||||
G4FCylindricalSurface::G4FCylindricalSurface( const G4FCylindricalSurface& c )
|
||||
{
|
||||
length = c.length;
|
||||
}
|
||||
|
||||
// printing function using C++ ostream class
|
||||
void G4FCylindricalSurface::PrintOn( ostream& os ) const
|
||||
{
|
||||
os << "G4FCylindricalSurface with origin: " << origin << "\t"
|
||||
<< "and axis: " << Position.GetAxis() << "\n"
|
||||
<< "\t radius: " << radius << "\t and length: "
|
||||
<< length << "\n";
|
||||
}
|
||||
|
||||
|
||||
int G4FCylindricalSurface::operator==( const G4FCylindricalSurface& c )
|
||||
{
|
||||
/* return ( origin == c.origin &&
|
||||
axis == c.axis &&
|
||||
radius == c.radius &&
|
||||
length == c.length );*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// Added 18.7-95
|
||||
// Modified by L. Broglia (01/12/98)
|
||||
void G4FCylindricalSurface::CalcBBox()
|
||||
{
|
||||
// Finds the bounds of the surface iow
|
||||
// calculates the bounds for a bounding box
|
||||
// to the surface. The bounding box is used
|
||||
// for a preliminary check of intersection.
|
||||
G4Point3D Max = -PINFINITY;
|
||||
G4Point3D Min = PINFINITY;
|
||||
|
||||
G4Point3D Tmp;
|
||||
G4Point3D Origin = Position.GetLocation();
|
||||
G4Point3D EndOrigin = Origin + (length*Position.GetAxis());
|
||||
G4Point3D Radius(radius, radius, 0);
|
||||
|
||||
// Default BBox
|
||||
G4Point3D Tolerance(kCarTolerance, kCarTolerance, kCarTolerance);
|
||||
G4Point3D BoxMin(Origin-Tolerance);
|
||||
G4Point3D BoxMax(Origin+Tolerance);
|
||||
|
||||
bbox = new G4BoundingBox3D();
|
||||
bbox->Init(BoxMin, BoxMax);
|
||||
|
||||
|
||||
Tmp = (Origin - Radius);
|
||||
bbox->Extend(Tmp);
|
||||
|
||||
Tmp = Origin + Radius;
|
||||
bbox->Extend(Tmp);
|
||||
|
||||
Tmp = EndOrigin - Radius;
|
||||
bbox->Extend(Tmp);
|
||||
|
||||
Tmp = EndOrigin + Radius;
|
||||
bbox->Extend(Tmp);
|
||||
}
|
||||
|
||||
|
||||
int G4FCylindricalSurface::Intersect( const G4Ray& ry )
|
||||
{
|
||||
// Distance along a Ray (straight line with G4ThreeVec) to leave or enter
|
||||
// a G4CylindricalSurface. The input variable which_way should be set
|
||||
// to +1 to indicate leaving a G4CylindricalSurface, -1 to indicate
|
||||
// entering a G4CylindricalSurface.
|
||||
// p is the point of intersection of the Ray with the G4CylindricalSurface.
|
||||
// If the G4Vector3D of the Ray is opposite to that of the Normal to
|
||||
// the G4CylindricalSurface at the intersection point, it will not leave
|
||||
// the G4CylindricalSurface.
|
||||
// Similarly, if the G4Vector3D of the Ray is along that of the Normal
|
||||
// to the G4CylindricalSurface at the intersection point, it will not enter
|
||||
// the G4CylindricalSurface.
|
||||
// This method is called by all finite shapes sub-classed to
|
||||
// G4CylindricalSurface.
|
||||
// Use the virtual function table to check if the intersection point
|
||||
// is within the boundary of the finite shape.
|
||||
// A negative result means no intersection.
|
||||
// If no valid intersection point is found, set the distance
|
||||
// and intersection point to large numbers.
|
||||
|
||||
// int which_way = -1;
|
||||
//Originally a parameter.Read explanation above.
|
||||
|
||||
int which_way=1;
|
||||
|
||||
if(!Inside(ry.GetStart()))
|
||||
which_way = -1;
|
||||
|
||||
distance = FLT_MAXX;
|
||||
G4Vector3D lv ( FLT_MAXX, FLT_MAXX, FLT_MAXX );
|
||||
|
||||
closest_hit = lv;
|
||||
|
||||
// Origin and G4Vector3D unit vector of Ray.
|
||||
G4Vector3D x = ry.GetStart();
|
||||
G4Vector3D dhat = ry.GetDir();
|
||||
|
||||
// Axis unit vector of the G4CylindricalSurface.
|
||||
G4Vector3D ahat = GetAxis();
|
||||
int isoln = 0,
|
||||
maxsoln = 2;
|
||||
|
||||
// array of solutions in distance along the Ray
|
||||
G4double s[2];
|
||||
s[0] = -1.0;
|
||||
s[1] = -1.0 ;
|
||||
|
||||
// calculate the two solutions (quadratic equation)
|
||||
G4Vector3D d = x - GetOrigin();
|
||||
G4double radiu = GetRadius();
|
||||
|
||||
//quit with no intersection if the radius of the G4CylindricalSurface is zero
|
||||
// if ( radiu <= 0.0 )
|
||||
// return 0;
|
||||
|
||||
G4double dsq = d * d;
|
||||
G4double da = d * ahat;
|
||||
G4double dasq = da * da;
|
||||
G4double rsq = radiu * radiu;
|
||||
G4double qsq = dsq - dasq;
|
||||
G4double dira = dhat * ahat;
|
||||
G4double a = 1.0 - dira * dira;
|
||||
|
||||
if ( a <= 0.0 )
|
||||
return 0;
|
||||
|
||||
G4double b = 2. * ( d * dhat - da * dira );
|
||||
G4double c = rsq - qsq;
|
||||
G4double radical = b * b + 4. * a * c;
|
||||
|
||||
if ( radical < 0.0 )
|
||||
return 0;
|
||||
|
||||
G4double root = sqrt( radical );
|
||||
s[0] = ( - b + root ) / ( 2. * a );
|
||||
s[1] = ( - b - root ) / ( 2. * a );
|
||||
|
||||
// order the possible solutions by increasing distance along the Ray
|
||||
// (G4Sorting routines are in support/G4Sort.h)
|
||||
G4Sort_double( s, isoln, maxsoln-1 );
|
||||
|
||||
// now loop over each positive solution, keeping the first one (smallest
|
||||
// distance along the Ray) which is within the boundary of the sub-shape
|
||||
// and which also has the correct G4Vector3D with respect to the Normal to
|
||||
// the G4CylindricalSurface at the intersection point
|
||||
for ( isoln = 0; isoln < maxsoln; isoln++ )
|
||||
{
|
||||
if ( s[isoln] >= kCarTolerance*0.5 )
|
||||
{
|
||||
if ( s[isoln] >= FLT_MAXX ) // quit if too large
|
||||
return 0;
|
||||
|
||||
distance = s[isoln];
|
||||
closest_hit = ry.GetPoint( distance );
|
||||
G4double tmp = dhat * (Normal( closest_hit ));
|
||||
|
||||
// L. Broglia
|
||||
// After this test, somtimes we have the distance,
|
||||
// sometimes we have the squared distance
|
||||
// For the moment, I delete this test
|
||||
//if ((tmp * which_way) >= 0.0 )
|
||||
//if ( WithinBoundary( closest_hit ) == 1 )
|
||||
distance = distance*distance;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
if ( s[isoln] >= -kCarTolerance*0.5 )
|
||||
{
|
||||
// the point is on the surface
|
||||
distance = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// get here only if there was no solution within the boundary, Reset
|
||||
// distance and intersection point to large numbers
|
||||
distance = FLT_MAXX;
|
||||
closest_hit = lv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
G4double G4FCylindricalSurface::HowNear( const G4Vector3D& x ) const
|
||||
{
|
||||
// Distance from the point x to the infinite G4CylindricalSurface.
|
||||
// The distance will be positive if the point is Inside the
|
||||
// G4FCylindricalSurface, negative if the point is outside.
|
||||
|
||||
G4Vector3D d = x - origin;
|
||||
G4double dA = d * Position.GetAxis();
|
||||
G4double rad = sqrt( d.mag2() - dA*dA );
|
||||
G4double hownear;
|
||||
|
||||
if(dA > length)
|
||||
hownear = length - dA;
|
||||
else if(dA < 0)
|
||||
hownear = dA;
|
||||
else
|
||||
hownear = radius - rad;
|
||||
|
||||
return hownear;
|
||||
}
|
||||
|
||||
|
||||
int G4FCylindricalSurface::WithinBoundary( const G4Vector3D& x ) const
|
||||
{
|
||||
// return 1 if point x is within the boundaries of the G4FCylindricalSurface
|
||||
// return 0 otherwise (assume it is on the cylinder)
|
||||
if ( fabs( ( x - Position.GetLocation()) * Position.GetAxis() ) <= 0.5 * length )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
G4double G4FCylindricalSurface::Scale() const
|
||||
{
|
||||
// Returns the radius of a G4FCylindricalSurface unless it is zero, in which
|
||||
// case returns the length.
|
||||
// Used for Scale-invariant tests of surface thickness.
|
||||
if ( radius == 0.0 )
|
||||
return length;
|
||||
else
|
||||
return radius;
|
||||
}
|
||||
|
||||
|
||||
G4Vector3D G4FCylindricalSurface::SurfaceNormal( const G4Point3D& p ) const
|
||||
{
|
||||
// return the Normal unit vector to the G4CylindricalSurface at a point
|
||||
// p on (or nearly on) the G4CylindricalSurface
|
||||
|
||||
G4Vector3D n = ( p - Position.GetLocation() ) -
|
||||
( ( p - Position.GetLocation()) * Position.GetAxis() ) *Position.GetAxis();
|
||||
G4double nmag = n.mag();
|
||||
|
||||
if ( nmag != 0.0 )
|
||||
n = n * (1/nmag);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int G4FCylindricalSurface::Inside ( const G4Vector3D& x ) const
|
||||
{
|
||||
// Return 0 if point x is outside G4CylindricalSurface, 1 if Inside.
|
||||
// Outside means that the distance to the G4CylindricalSurface would
|
||||
// be negative.
|
||||
// Use the HowNear function to calculate this distance.
|
||||
if ( HowNear( x ) >= -0.5*kCarTolerance )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void G4FCylindricalSurface::resize( G4double r, G4double l )
|
||||
{
|
||||
// Resize a G4FCylindricalSurface to a new radius r and new length l
|
||||
// Require radius to be non-negative
|
||||
if ( r >= 0.0 )
|
||||
radius = r;
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4FCylindricalSurface::resize"
|
||||
<< "--asked for negative radius\n"
|
||||
<< "\tOriginal value of " << radius << " is retained.\n";
|
||||
}
|
||||
|
||||
// Require length to be positive
|
||||
if ( l > 0.0 )
|
||||
length = l;
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4FCylindricalSurface::resize"
|
||||
<< "--asked for negative or zero length\n"
|
||||
<< "\tOriginal value of " << length << " is retained.\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4FPlane.cc,v 2.30 1998/12/11 08:29:07 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
|
||||
|
||||
#include "G4FPlane.hh"
|
||||
#include "G4CompositeCurve.hh"
|
||||
|
||||
|
||||
G4FPlane::G4FPlane( const G4Vector3D& direction,
|
||||
const G4Vector3D& axis ,
|
||||
const G4Point3D& Pt0 ):pplace(direction, axis, Pt0)
|
||||
{
|
||||
G4Point3D Pt1 = Pt0 + direction;
|
||||
|
||||
// The plane include direction and axis is the normal,
|
||||
// so axis^direction is included in the plane
|
||||
G4Point3D Pt2 = Pt0 + axis.cross(direction);
|
||||
|
||||
G4Ray::CalcPlane3Pts( Pl, Pt0, Pt1, Pt2 );
|
||||
|
||||
active = 1;
|
||||
CalcNormal();
|
||||
distance = kInfinity;
|
||||
Type = 1;
|
||||
}
|
||||
|
||||
|
||||
G4FPlane::G4FPlane(const G4Point3DVector* pVec, const G4Point3DVector* iVec)
|
||||
: pplace( (*pVec)[0]-(*pVec)[1], // direction
|
||||
((*pVec)[pVec->length()-1]-(*pVec)[0])
|
||||
.cross((*pVec)[0]-(*pVec)[1]), // axis
|
||||
(*pVec)[0] ) // location
|
||||
|
||||
{
|
||||
G4Ray::CalcPlane3Pts( Pl, (*pVec)[0], (*pVec)[1], (*pVec)[2] );
|
||||
|
||||
G4CurveVector bounds;
|
||||
G4CompositeCurve* polygon;
|
||||
|
||||
projectedBoundary = new G4SurfaceBoundary;
|
||||
|
||||
polygon= new G4CompositeCurve(*pVec);
|
||||
bounds.insert(polygon);
|
||||
|
||||
if (iVec)
|
||||
{
|
||||
polygon= new G4CompositeCurve(*iVec);
|
||||
bounds.insert(polygon);
|
||||
}
|
||||
|
||||
SetBoundaries(&bounds);
|
||||
|
||||
CalcNormal();
|
||||
IsConvex();
|
||||
distance = kInfinity;
|
||||
Type=1;
|
||||
}
|
||||
|
||||
|
||||
void G4FPlane::CalcBBox()
|
||||
{
|
||||
// This is needed since the bounds are used for the Solid
|
||||
// bbox calculation. The bbox test is NOT performed for
|
||||
// planar surfaces.
|
||||
|
||||
// Finds the bounds of the G4Plane surface iow
|
||||
// calculates the bounds for a bounding box
|
||||
// to the surface. The bounding box is used
|
||||
// for a preliminary check of intersection.
|
||||
|
||||
bbox= new G4BoundingBox3D(surfaceBoundary.BBox().GetBoxMin(),
|
||||
surfaceBoundary.BBox().GetBoxMax());
|
||||
|
||||
}
|
||||
|
||||
|
||||
void G4FPlane::CalcNormal()
|
||||
{
|
||||
/*
|
||||
// Calc Normal for surface which is used for the projection
|
||||
// Make planes
|
||||
G4Vector3D norm;
|
||||
|
||||
G4Vector3D RefDirection = pplace.GetRefDirection();
|
||||
G4Vector3D Axis = pplace.GetAxis();
|
||||
|
||||
// L. Broglia : before in G4Placement
|
||||
if( RefDirection == Axis )
|
||||
norm = RefDirection;
|
||||
else
|
||||
{
|
||||
// L. Broglia : error on setY, and it`s better to use cross function
|
||||
// norm.setX( RefDirection.y() * Axis.z() - RefDirection.z() * Axis.y() );
|
||||
// norm.setY( RefDirection.x() * Axis.z() - RefDirection.z() * Axis.x() );
|
||||
// norm.setZ( RefDirection.x() * Axis.y() - RefDirection.y() * Axis.x() );
|
||||
|
||||
norm = RefDirection.cross(Axis);
|
||||
}
|
||||
|
||||
// const G4Point3D& tmp = pplace.GetSrfPoint();
|
||||
const G4Point3D tmp = pplace.GetLocation();
|
||||
*/
|
||||
|
||||
// L. Broglia
|
||||
// The direction of the normal is the axis of his location
|
||||
// Its sense depend on the orientation of the bounded curve
|
||||
const G4Point3D tmp = pplace.GetLocation();
|
||||
G4Vector3D norm;
|
||||
G4int sense = GetSameSense();
|
||||
|
||||
if (sense)
|
||||
norm = pplace.GetAxis();
|
||||
else
|
||||
norm = - pplace.GetAxis();
|
||||
|
||||
NormalX = new G4Ray(tmp, norm);
|
||||
NormalX->RayCheck();
|
||||
NormalX->CreatePlanes();
|
||||
}
|
||||
|
||||
|
||||
void G4FPlane::Project()
|
||||
{
|
||||
// Project
|
||||
const G4Plane& Plane1 = NormalX->GetPlane(1);
|
||||
const G4Plane& Plane2 = NormalX->GetPlane(2);
|
||||
|
||||
// probably not necessary
|
||||
// projections of the boundary should be handled by the intersection
|
||||
// OuterBoundary->ProjectBoundaryTo2D(Plane1, Plane2, 0);
|
||||
}
|
||||
|
||||
|
||||
int G4FPlane::IsConvex()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int G4FPlane::Intersect(const G4Ray& rayref)
|
||||
{
|
||||
Intersected =1;
|
||||
|
||||
// closest_hit = pplace.EvaluateIntersection(rayref);
|
||||
// L. Broglia : before in G4Placement
|
||||
|
||||
// s is solution, line is p + tq, n is G4Plane Normal, r is point on G4Plane
|
||||
// all parameters are pointers to arrays of three elements
|
||||
|
||||
hitpoint = PINFINITY;
|
||||
register G4double a, b, t;
|
||||
|
||||
register const G4Vector3D& RayDir = rayref.GetDir();
|
||||
register const G4Point3D& RayStart = rayref.GetStart();
|
||||
|
||||
G4double dirx = RayDir.x();
|
||||
G4double diry = RayDir.y();
|
||||
G4double dirz = RayDir.z();
|
||||
|
||||
G4Vector3D norm = (*NormalX).GetDir();
|
||||
G4Point3D srf_point = pplace.GetLocation();
|
||||
|
||||
b = norm.x() * dirx + norm.y() * diry + norm.z() * dirz;
|
||||
|
||||
if ( fabs(b) < 0.001 )
|
||||
{
|
||||
// G4cout << "\nLine is parallel to G4Plane.No Hit.";
|
||||
}
|
||||
else
|
||||
{
|
||||
G4double startx = RayStart.x();
|
||||
G4double starty = RayStart.y();
|
||||
G4double startz = RayStart.z();
|
||||
|
||||
a = norm.x() * (srf_point.x() - startx) +
|
||||
norm.y() * (srf_point.y() - starty) +
|
||||
norm.z() * (srf_point.z() - startz) ;
|
||||
|
||||
t = a/b;
|
||||
|
||||
// substitute t into line equation
|
||||
// to calculate final solution
|
||||
G4double solx,soly,solz;
|
||||
solx = startx + t * dirx;
|
||||
soly = starty + t * diry;
|
||||
solz = startz + t * dirz;
|
||||
|
||||
if(((dirx < 0 && solx < startx)||(dirx >= 0 && solx >= startx))&&
|
||||
((diry < 0 && soly < starty)||(diry >= 0 && soly >= starty))&&
|
||||
((dirz < 0 && solz < startz)||(dirz >= 0 && solz >= startz)))
|
||||
hitpoint= G4Point3D(solx,soly, solz);
|
||||
|
||||
}
|
||||
|
||||
// closest_hit is a public Point3D in G4Surface
|
||||
closest_hit = hitpoint;
|
||||
|
||||
if(closest_hit.x() == kInfinity)
|
||||
{
|
||||
active=0;
|
||||
Distance(kInfinity);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Distance( RayStart.distance2(closest_hit) );
|
||||
|
||||
if(distance < kCarTolerance*0.5)
|
||||
{
|
||||
// the point is on the surface
|
||||
active=1; //active=0;
|
||||
Distance(0); //Distance(kInfinity);
|
||||
return 1; //return 0;
|
||||
}
|
||||
|
||||
G4Point3D hit = closest_hit;
|
||||
|
||||
// project the hit to the xy plane,
|
||||
// with the same projection that took the boundary
|
||||
// into projectedBoundary
|
||||
G4Point3D projectedHit= pplace.GetToPlacementCoordinates() * hit;
|
||||
|
||||
// test ray from the hit on the xy plane
|
||||
// check if it intersects the boundary
|
||||
G4Ray testRay(projectedHit, G4Vector3D(1, 0, 0));
|
||||
|
||||
G4CurveRayIntersection is;
|
||||
projectedBoundary->IntersectRay2D(testRay, is);
|
||||
|
||||
// if not, we are outside
|
||||
if ( is.GetDistance() >= kInfinity )
|
||||
{
|
||||
active=0;
|
||||
Distance(kInfinity);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// if yes, we have to check on which side of the intersected
|
||||
// curve the hit lies
|
||||
G4Vector3D tangent;
|
||||
|
||||
projectedBoundary->Tangent(is, tangent);
|
||||
|
||||
// L. Broglia
|
||||
// Now replace tangent into the pplace
|
||||
tangent = pplace.GetFromPlacementCoordinates() * tangent;
|
||||
|
||||
// (let's assume that the tangent is defined)
|
||||
// criterion for outside: (d x t).z() < 0
|
||||
// d = hit - is & t = tangent
|
||||
|
||||
G4Point3D Is = pplace.GetFromPlacementCoordinates() * (is.GetPoint());
|
||||
G4Vector3D d = hit - Is;
|
||||
|
||||
if ( (d.cross(tangent)).z() < 0 )
|
||||
{
|
||||
active=0;
|
||||
Distance(kInfinity);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// a real intersection point
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
G4double G4FPlane::ClosestDistanceToPoint(const G4Point3D& Pt)
|
||||
{
|
||||
// Calculates signed distance of point Pt to G4Plane Pl
|
||||
// Be careful, the equation of the plane is :
|
||||
// ax + by + cz = d
|
||||
return ( Pt.x()*Pl.a + Pt.y()*Pl.b + Pt.z()*Pl.c - Pl.d);
|
||||
}
|
||||
|
||||
|
||||
void G4FPlane::InitBounded()
|
||||
{
|
||||
// L. Broglia
|
||||
|
||||
projectedBoundary =
|
||||
surfaceBoundary.Project( pplace.GetToPlacementCoordinates() );
|
||||
}
|
||||
|
||||
G4double G4FPlane::HowNear( const G4Vector3D& x ) const
|
||||
{
|
||||
const G4Point3D Pt = x;
|
||||
//G4double d = ClosestDistanceToPoint(Pt);
|
||||
//return d;
|
||||
return ( Pt.x()*Pl.a + Pt.y()*Pl.b + Pt.z()*Pl.c - Pl.d);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4Hyperbola.cc,v 2.8 1998/10/29 17:49:38 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
|
||||
#include "G4Hyperbola.hh"
|
||||
|
||||
G4Hyperbola::G4Hyperbola(){}
|
||||
|
||||
G4Curve* G4Hyperbola::Project(const G4Transform3D& tr)
|
||||
{
|
||||
G4Exception("G4Hyperbola::Project");
|
||||
|
||||
G4Point3D newLocation= tr*position.GetLocation();
|
||||
newLocation.setZ(0);
|
||||
G4double axisZ= (tr*position.GetPZ()).unit().z();
|
||||
|
||||
if (abs(axisZ)<kAngTolerance)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
G4Vector3D newAxis(0, 0, axisZ>0? +1: -1);
|
||||
|
||||
// get the parameter of an endpoint of an axis
|
||||
// (this is a point the distance of which from the center is extreme)
|
||||
G4Vector3D xPrime = tr*position.GetPX();
|
||||
xPrime.setZ(0);
|
||||
|
||||
G4Vector3D yPrime = tr*position.GetPY();
|
||||
yPrime.setZ(0);
|
||||
|
||||
G4Vector3D a = semiAxis*xPrime;
|
||||
G4Vector3D b = semiImagAxis*yPrime;
|
||||
|
||||
G4double xval = -2*a*b/(a.mag2()+b.mag2());
|
||||
|
||||
#ifdef WIN32
|
||||
G4double u= (0.5*log((1+xval)/(1-xval)))/2;
|
||||
#else
|
||||
G4double u= atanh( xval ) / 2;
|
||||
#endif
|
||||
|
||||
// get the coordinate axis directions and the semiaxis lengths
|
||||
G4Vector3D sAxis= a*cosh(u)+b*sinh(u);
|
||||
|
||||
//!!!!!!!!!!!!
|
||||
G4Vector3D sImagAxis= a*cosh(u+pi/2)+b*sinh(u+pi/2);
|
||||
|
||||
//!!!!!!!!!!!!
|
||||
G4double newSemiAxis = sAxis.mag();
|
||||
G4double newSemiImagAxis = sImagAxis.mag();
|
||||
G4Vector3D newRefDirection = sAxis;
|
||||
|
||||
// create the new hyperbola
|
||||
G4Axis2Placement3D newPosition;
|
||||
newPosition.Init(newRefDirection, newAxis, newLocation);
|
||||
|
||||
G4Hyperbola* r= new G4Hyperbola;
|
||||
r->Init(newPosition, newSemiAxis, newSemiImagAxis);
|
||||
|
||||
// introduce the shift in the parametrization
|
||||
// maybe the Sign must be changed?
|
||||
r->SetPShift(u);
|
||||
|
||||
// set the bounds when necessary
|
||||
if (IsBounded())
|
||||
r->SetBounds(GetPStart(), GetPEnd());
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
void G4Hyperbola::InitBounded()
|
||||
{
|
||||
// the bbox must include the start and endpoints as well as the
|
||||
// extreme points if they lie on the curve
|
||||
bBox.Init(GetStart(), GetEnd());
|
||||
|
||||
// the parameter values
|
||||
// belonging to the points with an extreme x, y and z coordinate
|
||||
for (G4int i=0; i<3; i++)
|
||||
{
|
||||
G4double x_i= position.GetPX()(i);
|
||||
|
||||
if (abs(x_i) <= kAngTolerance)
|
||||
{
|
||||
G4double tanhu= - (semiImagAxis*position.GetPY()(i)) / (semiAxis*x_i);
|
||||
|
||||
if (abs(tanhu)<=1)
|
||||
{
|
||||
#ifdef WIN32
|
||||
G4double u= 0.5*log((1+tanhu)/(1-tanhu));
|
||||
#else
|
||||
G4double u= atanh(tanhu);
|
||||
#endif
|
||||
|
||||
if (IsPOn(u)) bBox.Extend(GetPoint(u));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
G4Hyperbola::~G4Hyperbola(){}
|
||||
|
||||
|
||||
G4bool G4Hyperbola::Tangent(G4CurvePoint& cp, G4Vector3D& v)
|
||||
{
|
||||
// The tangent is computed from the 3D point representation
|
||||
// for all conics. An alternaive implementation (based on
|
||||
// the parametric point) might be worthwhile adding
|
||||
// for efficiency.
|
||||
|
||||
const G4Axis2Placement3D& pos= *(GetPosition());
|
||||
G4Point3D p= pos.GetToPlacementCoordinates() * cp.GetPoint();
|
||||
|
||||
v= forTangent*p.y()*pos.GetPX() + p.x()*pos.GetPY();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4KnotVector.cc,v 2.4 1998/10/20 16:33:51 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
|
||||
#include "G4KnotVector.hh"
|
||||
|
||||
G4KnotVector::G4KnotVector()
|
||||
{
|
||||
knots=(G4double*)0;
|
||||
}
|
||||
|
||||
G4KnotVector::G4KnotVector(const int sz)
|
||||
{
|
||||
k_size=sz;
|
||||
knots = new G4double[k_size];
|
||||
for(int a=0;a<k_size;a++)
|
||||
knots[a]=0;
|
||||
}
|
||||
|
||||
|
||||
G4KnotVector::~G4KnotVector() { delete [] knots;}
|
||||
|
||||
//Copy constructor
|
||||
G4KnotVector::G4KnotVector(const G4KnotVector& old_kv)
|
||||
{
|
||||
k_size = old_kv.GetSize();
|
||||
knots = new G4double[k_size];
|
||||
for(register int a=0; a < old_kv.k_size; a++)knots[a]=old_kv.knots[a];
|
||||
}
|
||||
|
||||
int G4KnotVector::GetKnotIndex(G4double k_value,const int order)
|
||||
{
|
||||
int i, knot_index;
|
||||
G4double knt;
|
||||
|
||||
if ( k_value < ( knt = knots[order - 1]))
|
||||
if (ApxEq( k_value, knt))
|
||||
k_value = knt;
|
||||
else
|
||||
return -1;
|
||||
|
||||
if ( k_value > ( knt = knots[k_size - order + 1]))
|
||||
if (ApxEq( k_value, knt))
|
||||
k_value = knt;
|
||||
else
|
||||
return -1;
|
||||
|
||||
if ( k_value == knots[k_size - order + 1] )
|
||||
knot_index = k_size - order - 1;
|
||||
else if ( k_value == knots[ order - 1] )
|
||||
knot_index = order - 1;
|
||||
else
|
||||
{
|
||||
knot_index = 0;
|
||||
|
||||
for ( i = 0; i < k_size - 1; i++)
|
||||
if((knots[i]<k_value) && (k_value <= knots[i+1]))
|
||||
knot_index = i;
|
||||
}
|
||||
|
||||
return knot_index;
|
||||
}
|
||||
|
||||
|
||||
G4KnotVector* G4KnotVector::MultiplyKnotVector(const int num,
|
||||
const G4double val)
|
||||
{
|
||||
int n;
|
||||
G4double* knots_to_add;
|
||||
|
||||
n = CheckKnotVector( val );
|
||||
knots_to_add = new G4double[num-n];
|
||||
|
||||
for (int i = 0; i < num - n; i++)
|
||||
knots_to_add[i] = val;
|
||||
|
||||
G4KnotVector* new_kv = new G4KnotVector();
|
||||
new_kv->k_size = num - n + GetSize();
|
||||
new_kv->knots = MergeKnotVector(knots_to_add, num-n);
|
||||
|
||||
delete [] knots_to_add;
|
||||
|
||||
return new_kv;
|
||||
}
|
||||
|
||||
|
||||
G4double* G4KnotVector::MergeKnotVector(const G4double* knots_to_add,
|
||||
const int add_size )
|
||||
{
|
||||
G4double *newknots;
|
||||
int kv1_ptr = 0,
|
||||
kv2_ptr = 0,
|
||||
newptr;
|
||||
int old_size = k_size;
|
||||
|
||||
newknots = new G4double[k_size + add_size];
|
||||
|
||||
for ( newptr = 0; newptr < k_size+add_size; newptr++)
|
||||
if ( kv1_ptr >= add_size )
|
||||
newknots[newptr] = knots[kv2_ptr++];
|
||||
else if ( kv2_ptr >= old_size )
|
||||
newknots[newptr] = knots_to_add[kv1_ptr++];
|
||||
else if ( knots_to_add[kv1_ptr] < knots[kv2_ptr])
|
||||
newknots[newptr] = knots_to_add[kv1_ptr++];
|
||||
else
|
||||
newknots[newptr] = knots[kv2_ptr++];
|
||||
|
||||
return newknots;
|
||||
}
|
||||
|
||||
|
||||
int G4KnotVector::CheckKnotVector(const G4double val)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
for ( int i = 0; i < k_size; i++)
|
||||
{
|
||||
// if ( abs(val - knots[i]) < kCarTolerance)
|
||||
if ( val == knots[i] )
|
||||
num++;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
void G4KnotVector::ExtractKnotVector( G4KnotVector* kv,
|
||||
const int upper,const int lower)
|
||||
{
|
||||
delete[] kv->knots;
|
||||
kv->k_size = upper-lower;
|
||||
kv->knots = new G4double[kv->k_size];
|
||||
|
||||
for ( int i = lower; i < upper; i++)
|
||||
kv->knots[i-lower] = knots[i];
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4Line.cc,v 2.6 1998/12/15 10:33:55 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4Line.hh"
|
||||
|
||||
G4Line::G4Line (){}
|
||||
G4Line::~G4Line (){}
|
||||
|
||||
G4Curve* G4Line::Project(const G4Transform3D& tr)
|
||||
{
|
||||
G4Vector3D newDir= tr*dir;
|
||||
|
||||
if (abs(newDir.x())+abs(newDir.y()) < kCarTolerance)
|
||||
return 0;
|
||||
|
||||
G4Point3D newPnt= tr*pnt;
|
||||
newDir.setZ(0);
|
||||
newPnt.setZ(0);
|
||||
|
||||
G4Line* r= new G4Line();
|
||||
r->Init(newDir, newPnt);
|
||||
r->SetBounds(GetPStart(), GetPEnd());
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4bool G4Line::Tangent(G4CurvePoint& cp, G4Vector3D& vec)
|
||||
{
|
||||
if(GetSameSense())
|
||||
vec = -dir;
|
||||
else
|
||||
vec = dir;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4NISTStepReader.cc,v 2.4 1998/11/04 14:49:56 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4NISTStepReader.hh"
|
||||
|
||||
void G4NISTStepReader::ReadSTEPFile(G4String STEPfilename)
|
||||
{
|
||||
// Reads the Step file into the nist toolkit class library
|
||||
|
||||
// if the comments below look canned, it's because they're taken
|
||||
// straight from the treg source... ;-)
|
||||
|
||||
// This has to be Done before anything else. This initializes
|
||||
// all of the registry information for the schema you are using.
|
||||
// The SchemaInit() function is generated by fedex_plus... see
|
||||
// extern statement above.
|
||||
Registry *registry = new Registry(SchemaInit);
|
||||
|
||||
// The nifty thing about the Registry is that it basically keeps a List
|
||||
// of everything in your schema. What this means is that we can go
|
||||
// through the Registry and instantiate, say, one of everything, without
|
||||
// knowing at coding-time what entities there are to instantiate. So,
|
||||
// this test could be linked with other class libraries produced from
|
||||
// other schema, rather than the example, and run happily.
|
||||
|
||||
// InstMgr InstanceList;
|
||||
STEPfile *sfile = new STEPfile(*registry, InstanceList);
|
||||
|
||||
// The STEPfile is actually an object that manages the relationship
|
||||
// between what's instantiated in the instance manager, and how that
|
||||
// information gets passed to the outside, e.g., a file on disk.
|
||||
|
||||
// First we're going to read in the data from the input STEPfile,
|
||||
// and Print it to stdout
|
||||
|
||||
// Reading the STEPfile instantiates all the objects in it.
|
||||
// The instances get pointers into the InstMgr, and each type
|
||||
// and entity gets a pointer into the registry.
|
||||
G4cout << "\n### Reading exchange file from " << STEPfilename << endl;
|
||||
sfile->ReadExchangeFile(STEPfilename);
|
||||
|
||||
// Just checking... ;-)
|
||||
G4cout << "\n### The InstMgr says there are ";
|
||||
G4cout << InstanceList.InstanceCount() << " instantiated objects" << endl;
|
||||
|
||||
// G4cout << "\n### Here is the exchange file:" << endl << endl;
|
||||
// sfile->WriteExchangeFile(G4cout);
|
||||
|
||||
delete sfile;
|
||||
delete registry;
|
||||
}
|
||||
|
||||
|
||||
void G4NISTStepReader::SaveSTEPFile(){}
|
||||
|
||||
void G4NISTStepReader::UpdateSTEPFile(){}
|
||||
@@ -0,0 +1,44 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4OsloMatrix.cc,v 2.1 1998/10/20 16:33:53 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
|
||||
#include "G4OsloMatrix.hh"
|
||||
|
||||
|
||||
Matrix::Matrix()
|
||||
{
|
||||
nr=nc=0;
|
||||
data=0;
|
||||
}
|
||||
|
||||
|
||||
Matrix::Matrix(int rows, int columns)
|
||||
{
|
||||
nr=rows;
|
||||
nc=columns;
|
||||
data = new G4double[nr*nc];
|
||||
|
||||
for(int a =0; a<nr*nc;a++)
|
||||
data[a]=0;
|
||||
}
|
||||
|
||||
|
||||
Matrix::Matrix(G4double vec[])
|
||||
{
|
||||
nr = 4;
|
||||
nc = 4;
|
||||
data = new G4double[nr*nc];
|
||||
|
||||
for(int a=0;a<nr*nc;a++)
|
||||
data[a]=vec[a];
|
||||
}
|
||||
|
||||
Matrix::~Matrix(){;}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4Parabola.cc,v 2.8 1998/10/29 17:49:38 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4Parabola.hh"
|
||||
|
||||
G4Parabola::G4Parabola(){}
|
||||
G4Parabola::~G4Parabola(){}
|
||||
|
||||
G4Curve* G4Parabola::Project(const G4Transform3D& tr)
|
||||
{
|
||||
G4double axisZ= (tr*position.GetPZ()).unit().z();
|
||||
|
||||
if (abs(axisZ)<kAngTolerance)
|
||||
return 0;
|
||||
|
||||
|
||||
G4Vector3D newAxis(0, 0, axisZ>0? +1: -1);
|
||||
|
||||
G4Vector3D xPrime= tr*position.GetPX();
|
||||
xPrime.setZ(0);
|
||||
G4Vector3D yPrime= tr*position.GetPY();
|
||||
yPrime.setZ(0);
|
||||
G4double u= -(xPrime*yPrime)/xPrime.mag2();
|
||||
|
||||
G4Point3D newLocation= tr*position.GetLocation()+
|
||||
focalDist*(u*u*xPrime+2*u*yPrime);
|
||||
|
||||
newLocation.setZ(0);
|
||||
G4Vector3D newRefDirection= xPrime;
|
||||
G4double newFocalDist= (focalDist*((2*u+1)*xPrime+2*yPrime)).mag()/sqrt(5.);
|
||||
|
||||
// create the new parabola
|
||||
G4Axis2Placement3D newPosition;
|
||||
newPosition.Init(newRefDirection, newAxis, newLocation);
|
||||
G4Parabola* r= new G4Parabola;
|
||||
r->Init(newPosition, newFocalDist);
|
||||
|
||||
// introduce the shift in the parametrization
|
||||
// maybe the Sign must be changed?
|
||||
r->SetPShift(u);
|
||||
|
||||
// set the bounds when necessary
|
||||
if (IsBounded())
|
||||
r->SetBounds(GetPStart(), GetPEnd());
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
void G4Parabola::InitBounded()
|
||||
{
|
||||
// the bbox must include the start and endpoints as well as the
|
||||
// extreme points if they lie on the curve
|
||||
bBox.Init(GetStart(), GetEnd());
|
||||
|
||||
// the parameter values
|
||||
// belonging to the points with an extreme x, y and z coordinate
|
||||
for (G4int i=0; i<3; i++)
|
||||
{
|
||||
G4double x_i= position.GetPX()(i);
|
||||
|
||||
if (abs(x_i) <= kAngTolerance)
|
||||
{
|
||||
G4double u= - position.GetPY()(i) / x_i;
|
||||
if (IsPOn(u))
|
||||
bBox.Extend(GetPoint(u));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
G4bool G4Parabola::Tangent(G4CurvePoint& cp, G4Vector3D& v)
|
||||
{
|
||||
// The tangent is computed from the 3D point representation
|
||||
// for all conics. An alternaive implementation (based on
|
||||
// the parametric point) might be worthwhile adding
|
||||
// for efficiency.
|
||||
|
||||
const G4Axis2Placement3D& pos= *(GetPosition());
|
||||
G4Point3D p= pos.GetToPlacementCoordinates() * cp.GetPoint();
|
||||
|
||||
v= p.y()*pos.GetPX() + (2*focalDist)*pos.GetPY();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4PlacedSolid.cc,v 2.2 1998/10/29 17:49:39 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4PlacedSolid.hh"
|
||||
|
||||
G4PlacedSolid::G4PlacedSolid()
|
||||
{
|
||||
solid =0;
|
||||
solidRotation =0;
|
||||
solidTranslation =0;
|
||||
}
|
||||
|
||||
|
||||
G4PlacedSolid::G4PlacedSolid(G4BREPSolid* s, G4Axis2Placement3D* p)
|
||||
{
|
||||
solid =s;
|
||||
|
||||
if(p)
|
||||
{
|
||||
G4double x,y,z;
|
||||
G4Point3D srfpoint = p->GetLocation();
|
||||
|
||||
x = srfpoint.x();
|
||||
y = srfpoint.y();
|
||||
z = srfpoint.z();
|
||||
solidTranslation = new G4ThreeVector(x,y,z);
|
||||
|
||||
G4Vector3D tmpvec = p->GetAxis();
|
||||
x = tmpvec.x();
|
||||
y = tmpvec.y();
|
||||
z = tmpvec.z();
|
||||
G4ThreeVector x_axis(x,y,z);
|
||||
|
||||
if( (x<kCarTolerance)&&
|
||||
(y<kCarTolerance)&&
|
||||
(z<kCarTolerance) )
|
||||
solidRotation=0;
|
||||
else
|
||||
{
|
||||
tmpvec = p->GetRefDirection();
|
||||
x = tmpvec.x();
|
||||
y = tmpvec.y();
|
||||
z = tmpvec.z();
|
||||
|
||||
G4ThreeVector y_axis(x,y,z);
|
||||
solidRotation = new HepRotation();
|
||||
solidRotation->rotateAxes(x_axis, y_axis, x_axis.cross(y_axis));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
solidTranslation=0;
|
||||
solidRotation=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
G4PlacedSolid::~G4PlacedSolid()
|
||||
{
|
||||
//delete solid;
|
||||
if(solidRotation)
|
||||
delete solidRotation;
|
||||
|
||||
if(solidTranslation)
|
||||
delete solidTranslation;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4PointRat.cc,v 2.2 1998/10/20 16:33:56 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
//
|
||||
// Modif 8 oct 98 : A.Floquet
|
||||
// G4PointRat datas are made of
|
||||
// . a point 3D
|
||||
// . a additional value : the scale factor which is set to 1 by default
|
||||
//
|
||||
|
||||
#include "G4PointRat.hh"
|
||||
|
||||
G4PointRat::G4PointRat():pt3d(){s=1;}
|
||||
|
||||
G4PointRat::G4PointRat(const G4Point3D& tmp):pt3d(tmp){s=1;}
|
||||
|
||||
G4PointRat::~G4PointRat(){}
|
||||
|
||||
void G4PointRat::operator=(const G4PointRat& a)
|
||||
{ pt3d.setX(a.x());
|
||||
pt3d.setY(a.y());
|
||||
pt3d.setZ(a.z());
|
||||
s=a.w();
|
||||
}
|
||||
|
||||
void G4PointRat::operator=(const G4Point3D& a)
|
||||
{ pt3d = a;
|
||||
s=1;
|
||||
}
|
||||
|
||||
void G4PointRat::CopyRationalValue(const RealNode& RNode)
|
||||
{
|
||||
s = RNode.value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,739 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4ProjectedSurface.cc,v 2.3 1998/10/20 16:33:56 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4ProjectedSurface.hh"
|
||||
|
||||
int G4ProjectedSurface::Splits=0;
|
||||
|
||||
G4ProjectedSurface::~G4ProjectedSurface()
|
||||
{
|
||||
delete u_knots;
|
||||
delete v_knots;
|
||||
delete ctl_points;
|
||||
|
||||
G4OsloMatrix* temp_oslo;
|
||||
if(oslo_m!=(G4OsloMatrix*)0)
|
||||
{
|
||||
while(oslo_m->next != oslo_m)
|
||||
{
|
||||
temp_oslo = oslo_m;
|
||||
oslo_m = oslo_m->next;
|
||||
|
||||
delete temp_oslo;
|
||||
}
|
||||
|
||||
delete oslo_m;
|
||||
}
|
||||
|
||||
delete bbox;
|
||||
}
|
||||
|
||||
|
||||
G4ProjectedSurface::G4ProjectedSurface()
|
||||
{
|
||||
distance = 0;
|
||||
oslo_m =(G4OsloMatrix*)0;
|
||||
}
|
||||
|
||||
|
||||
G4ProjectedSurface::G4ProjectedSurface(const G4ProjectedSurface &tmp)
|
||||
{
|
||||
distance = tmp.distance;
|
||||
oslo_m =(G4OsloMatrix*)0;
|
||||
|
||||
// next=this;
|
||||
|
||||
order[0] = tmp.order[0];
|
||||
order[1] = tmp.order[1];
|
||||
dir = tmp.dir;
|
||||
|
||||
u_knots = new G4KnotVector(*tmp.u_knots);
|
||||
v_knots = new G4KnotVector(*tmp.v_knots);
|
||||
|
||||
ctl_points = new G4ControlPoints(*tmp.ctl_points);
|
||||
bbox = new G4BoundingBox3D();
|
||||
}
|
||||
|
||||
|
||||
void G4ProjectedSurface::CopySurface()
|
||||
// Copies the projected surface into a bezier surface
|
||||
// and adds it to the List of bezier surfaces.
|
||||
{
|
||||
G4BezierSurface *bez = new G4BezierSurface();
|
||||
|
||||
bez->Distance(distance);
|
||||
bez->PutOrder(0, order[0]);
|
||||
bez->PutOrder(1, order[1]);
|
||||
bez->Dir(dir);
|
||||
bez->u_knots = new G4KnotVector(*u_knots);
|
||||
bez->v_knots = new G4KnotVector(*v_knots);
|
||||
bez->ctl_points = new G4ControlPoints(*ctl_points);
|
||||
|
||||
bezier_list->AddSurface(bez);
|
||||
}
|
||||
|
||||
|
||||
void G4ProjectedSurface::CalcBBox()
|
||||
{
|
||||
// Finds the bounds of the 2D-projected nurb iow
|
||||
// calculates the bounds for a bounding rectangle
|
||||
// to the surface. The bounding rectangle is used
|
||||
// for a preliminary check of intersection.
|
||||
|
||||
// Loop to search the whole control point mesh
|
||||
// for the minimum and maximum values for x and y.
|
||||
G4double box_minx,box_miny,box_maxx,box_maxy;
|
||||
box_minx = INFINITY;
|
||||
box_miny = INFINITY;
|
||||
box_maxx = -INFINITY;
|
||||
box_maxy = -INFINITY;
|
||||
|
||||
G4double bminx,bminy,bmaxx,bmaxy,tmpx,tmpy;
|
||||
bminx = box_minx; bminy = box_miny;
|
||||
bmaxx = box_maxx; bmaxy = box_maxy;
|
||||
|
||||
for(register int a = ctl_points->GetRows()-1; a>=0;a--)
|
||||
for(register int b = ctl_points->GetCols()-1; b>=0;b--)
|
||||
{
|
||||
/* L. Broglia
|
||||
G4Point2d& tmp = (G4Point2d&)ctl_points->get(a,b);
|
||||
*/
|
||||
G4Point3D tmp = ctl_points->Get3D(a,b);
|
||||
|
||||
tmpx = tmp.x(); tmpy = tmp.y();
|
||||
if(bminx > tmpx) box_minx=tmpx;
|
||||
if(bmaxx < tmpx) box_maxx=tmpx;
|
||||
if(bminy > tmpy) box_miny=tmpy;
|
||||
if(bmaxy < tmpy) box_maxy=tmpy;
|
||||
}
|
||||
|
||||
G4Point3D box_min(box_minx,box_miny);
|
||||
G4Point3D box_max(box_maxx,box_maxy);
|
||||
|
||||
delete bbox;
|
||||
bbox = new G4BoundingBox3D(box_min, box_max);
|
||||
}
|
||||
|
||||
|
||||
void G4ProjectedSurface::ConvertToBezier(G4SurfaceList& proj_list,
|
||||
G4SurfaceList& bez_list)
|
||||
{
|
||||
projected_list = &proj_list;
|
||||
bezier_list = &bez_list;
|
||||
|
||||
// Check wether the surface is a bezier surface by checking
|
||||
// if internal knots exist.
|
||||
if(CheckBezier())
|
||||
{
|
||||
// Make it a G4BezierSurface -object and add it to the bezier
|
||||
// surface List
|
||||
CopySurface();
|
||||
|
||||
// Retrieve a pointer to the newly added surface iow the
|
||||
// last in the List
|
||||
G4BezierSurface* bez_ptr = (G4BezierSurface*)bezier_list->GetLastSurface();
|
||||
|
||||
// Do the first clip to the bezier.
|
||||
bez_ptr->ClipSurface();
|
||||
G4double dMin = bez_ptr->SMin();
|
||||
G4double dMax = bez_ptr->SMax();
|
||||
G4double dMaxMinusdMin = dMax - dMin;
|
||||
|
||||
if(( dMaxMinusdMin > kCarTolerance ))
|
||||
{
|
||||
if( dMaxMinusdMin > 0.8 )
|
||||
{
|
||||
// The clipping routine selected a larger Area than one
|
||||
// knot interval which indicates that we have a case of
|
||||
// multiple intersections. The projected surface has to
|
||||
// be split again in order to separate the intersections
|
||||
// to different surfaces.
|
||||
|
||||
// Check tolerance of clipping
|
||||
// G4cout << "\nClip Area too big -> Split";
|
||||
dir = bez_ptr->dir;
|
||||
bezier_list->RemoveSurface(bez_ptr);
|
||||
|
||||
SplitNURBSurface();
|
||||
return;
|
||||
//}
|
||||
}
|
||||
else
|
||||
if( dMin > 0.0 || dMax < 0.0 )
|
||||
{
|
||||
// The ray intersects with the bounding box
|
||||
// but not with the surface itself.
|
||||
// G4cout << "\nConvex hull missed.";
|
||||
bezier_list->RemoveSurface(bez_ptr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(dMaxMinusdMin < kCarTolerance && dMaxMinusdMin > -kCarTolerance)
|
||||
{
|
||||
bezier_list->RemoveSurface(bez_ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
bez_ptr->LocalizeClipValues();
|
||||
bez_ptr->SetValues();
|
||||
|
||||
// Other G4ThreeVec clipping and testing.
|
||||
bez_ptr->ChangeDir();//bez->dir = !bez_ptr->dir;
|
||||
bez_ptr->ClipSurface();
|
||||
// G4cout<<"\nSMIN: " << bez_ptr->smin << " SMAX: "
|
||||
// << bez_ptr->smax << " DIR: " << bez_ptr->dir;
|
||||
|
||||
dMin = bez_ptr->SMin();
|
||||
dMax = bez_ptr->SMax();
|
||||
dMaxMinusdMin = dMax-dMin;
|
||||
|
||||
if((dMaxMinusdMin > kCarTolerance ))// ||
|
||||
// (dMaxMinusdMin < -kCarTolerance))
|
||||
{
|
||||
if( (dMaxMinusdMin) > 0.8 )
|
||||
{
|
||||
// G4cout << "\nClip Area too big -> Split";
|
||||
dir = bez_ptr->dir;//1.2 klo 18.30
|
||||
|
||||
// dir=!dir;
|
||||
bezier_list->RemoveSurface(bez_ptr);
|
||||
SplitNURBSurface();
|
||||
return;
|
||||
//}
|
||||
}
|
||||
else
|
||||
if( dMin > 1.0 || dMax < 0.0 )
|
||||
{
|
||||
// G4cout << "\nConvex hull missed.";
|
||||
bezier_list->RemoveSurface(bez_ptr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(dMaxMinusdMin < kCarTolerance && dMaxMinusdMin > -kCarTolerance)
|
||||
{
|
||||
bezier_list->RemoveSurface(bez_ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
bez_ptr->LocalizeClipValues();
|
||||
bez_ptr->SetValues();
|
||||
bez_ptr->CalcAverage();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Split the surface into two new surfaces. The G4ThreeVec
|
||||
// is set in the CheckBezier function.
|
||||
// G4cout << "\nNot a bezier surface -> Split";
|
||||
SplitNURBSurface();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int G4ProjectedSurface::CheckBezier()
|
||||
{
|
||||
// Checks if the surface is a bezier surface by
|
||||
// checking wether internal knots exist. If no internal
|
||||
// knots exist the quantity of knots is 2*order of the
|
||||
// surface. Returns 1 if the surface
|
||||
// is a bezier.
|
||||
|
||||
if( u_knots->GetSize() > (2.0 * GetOrder(ROW)))
|
||||
{dir=0;return 0;}
|
||||
|
||||
if( v_knots->GetSize() > (2.0 * GetOrder(COL)))
|
||||
{dir=1;return 0;}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void G4ProjectedSurface::SplitNURBSurface()
|
||||
{
|
||||
// Divides the surface in two parts. Uses the oslo-algorithm to calculate
|
||||
// the new knotvectors and controlpoints for the subsurfaces.
|
||||
|
||||
// G4cout << "\nProjected splitted.";
|
||||
|
||||
register G4double value;
|
||||
register int i;
|
||||
register int k_index;
|
||||
register G4ProjectedSurface *srf1, *srf2;
|
||||
register int nr,nc;
|
||||
|
||||
if ( dir == ROW )
|
||||
{
|
||||
value = u_knots->GetKnot((u_knots->GetSize()-1)/2);
|
||||
|
||||
for( i = 0; i < u_knots->GetSize(); i++)
|
||||
if( (abs(value - u_knots->GetKnot(i))) < kCarTolerance )
|
||||
{
|
||||
k_index = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( k_index == 0)
|
||||
{
|
||||
value = ( value + u_knots->GetKnot(u_knots->GetSize() -1))/2.0;
|
||||
k_index = GetOrder(ROW);
|
||||
}
|
||||
|
||||
new_knots = u_knots->MultiplyKnotVector(GetOrder(ROW), value);
|
||||
|
||||
ord = GetOrder(ROW);
|
||||
CalcOsloMatrix();
|
||||
|
||||
srf1 = new G4ProjectedSurface(*this);
|
||||
|
||||
//srf1->dir=ROW;
|
||||
srf1->dir=COL;
|
||||
|
||||
new_knots->ExtractKnotVector(srf1->u_knots,
|
||||
k_index + srf1->GetOrder(ROW),0);
|
||||
|
||||
nr= srf1->v_knots->GetSize() - srf1->GetOrder(COL);
|
||||
nc= srf1->u_knots->GetSize() - srf1->GetOrder(ROW);
|
||||
|
||||
delete srf1->ctl_points;
|
||||
srf1->ctl_points= new G4ControlPoints(2, nr, nc);
|
||||
|
||||
srf2 = new G4ProjectedSurface(*this);
|
||||
|
||||
//srf2->dir = ROW;
|
||||
srf2->dir = COL;
|
||||
|
||||
new_knots->ExtractKnotVector(srf2->u_knots,
|
||||
new_knots->GetSize(), k_index);
|
||||
|
||||
nr= srf2->v_knots->GetSize() - srf2->GetOrder(COL);
|
||||
nc= srf2->u_knots->GetSize() - srf2->GetOrder(ROW);
|
||||
|
||||
delete srf2->ctl_points;
|
||||
srf2->ctl_points = new G4ControlPoints(2, nr, nc);
|
||||
|
||||
lower = 0;
|
||||
upper = k_index;
|
||||
MapSurface(srf1);
|
||||
|
||||
lower = k_index;
|
||||
upper = new_knots->GetSize() - srf2->GetOrder(ROW);
|
||||
MapSurface(srf2);
|
||||
}
|
||||
else // G4ThreeVec = col
|
||||
{
|
||||
value = v_knots->GetKnot((v_knots->GetSize() -1)/2);
|
||||
|
||||
for( i = 0; i < v_knots->GetSize(); i++)
|
||||
if( (abs(value - v_knots->GetKnot(i))) < kCarTolerance )
|
||||
{
|
||||
k_index = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( k_index == 0)
|
||||
{
|
||||
value = ( value + v_knots->GetKnot(v_knots->GetSize() -1))/2.0;
|
||||
k_index = GetOrder(COL);
|
||||
}
|
||||
|
||||
new_knots = v_knots->MultiplyKnotVector( GetOrder(COL), value );
|
||||
ord = GetOrder(COL);
|
||||
|
||||
CalcOsloMatrix();
|
||||
|
||||
srf1 = new G4ProjectedSurface(*this);
|
||||
|
||||
//srf1->dir = COL;
|
||||
srf1->dir = ROW;
|
||||
|
||||
new_knots->ExtractKnotVector(srf1->v_knots,
|
||||
k_index + srf1->GetOrder(COL), 0);
|
||||
|
||||
nr = srf1->v_knots->GetSize() - srf1->GetOrder(COL);
|
||||
nc = srf1->u_knots->GetSize() - srf1->GetOrder(ROW);
|
||||
|
||||
delete srf1->ctl_points;
|
||||
srf1->ctl_points = new G4ControlPoints(2, nr, nc);
|
||||
|
||||
srf2 = new G4ProjectedSurface(*this);
|
||||
|
||||
//srf2->dir = COL;
|
||||
srf2->dir = ROW;
|
||||
|
||||
new_knots->ExtractKnotVector(srf2->v_knots, new_knots->GetSize(), k_index);
|
||||
|
||||
nr = srf2->v_knots->GetSize() - srf2->GetOrder(COL);
|
||||
nc = srf2->u_knots->GetSize() - srf2->GetOrder(ROW);
|
||||
|
||||
delete srf2->ctl_points;
|
||||
srf2->ctl_points = new G4ControlPoints(2,nr, nc);
|
||||
|
||||
lower = 0;
|
||||
upper = k_index;
|
||||
MapSurface(srf1);
|
||||
|
||||
lower = k_index;
|
||||
upper = new_knots->GetSize() - srf2->GetOrder(COL);
|
||||
MapSurface(srf2);
|
||||
}
|
||||
|
||||
// Check that surfaces are ok.
|
||||
int col_size = srf1->ctl_points->GetCols();
|
||||
int row_size = srf1->ctl_points->GetRows();
|
||||
|
||||
/* L. Broglia
|
||||
// get three cornerpoints of the controlpoint mesh.
|
||||
G4Point2d pt1 = srf1->ctl_points->get(0,0);
|
||||
G4Point2d pt2 = srf1->ctl_points->get(0,col_size-1);
|
||||
G4Point2d pt3 = srf1->ctl_points->get(row_size-1,0);
|
||||
|
||||
// Calc distance between points
|
||||
G4double pointDist1 = pt1.Distance(pt2);
|
||||
G4double pointDist2 = pt1.Distance(pt3);
|
||||
*/
|
||||
|
||||
// get three cornerpoints of the controlpoint mesh.
|
||||
G4Point3D pt1 = srf1->ctl_points->Get3D(0,0);
|
||||
G4Point3D pt2 = srf1->ctl_points->Get3D(0,col_size-1);
|
||||
G4Point3D pt3 = srf1->ctl_points->Get3D(row_size-1,0);
|
||||
|
||||
// Calc distance squared between points
|
||||
G4double pointDist1 = pt1.distance2(pt2);
|
||||
G4double pointDist2 = pt1.distance2(pt3);
|
||||
|
||||
|
||||
// Add surfaces to List of projected surfaces
|
||||
if(pointDist1 > kCarTolerance && pointDist2 > kCarTolerance)
|
||||
projected_list->AddSurface(srf1);
|
||||
else
|
||||
delete srf1;
|
||||
|
||||
col_size = srf2->ctl_points->GetCols();
|
||||
row_size = srf2->ctl_points->GetRows();
|
||||
|
||||
/* L. Broglia
|
||||
// get three cornerpoints of the controlpoint mesh.
|
||||
pt1 = srf2->ctl_points->get(0,0);
|
||||
pt2 = srf2->ctl_points->get(0,col_size-1);
|
||||
pt3 = srf2->ctl_points->get(row_size-1,0);
|
||||
|
||||
// Calc distance between points
|
||||
pointDist1 = pt1.Distance(pt2);
|
||||
pointDist2 = pt1.Distance(pt3);
|
||||
*/
|
||||
|
||||
// get three cornerpoints of the controlpoint mesh.
|
||||
pt1 = srf2->ctl_points->Get3D(0,0);
|
||||
pt2 = srf2->ctl_points->Get3D(0,col_size-1);
|
||||
pt3 = srf2->ctl_points->Get3D(row_size-1,0);
|
||||
|
||||
// Calc distance squared between points
|
||||
pointDist1 = pt1.distance2(pt2);
|
||||
pointDist2 = pt1.distance2(pt3);
|
||||
|
||||
// Add surfaces to List of projected surfaces
|
||||
if(pointDist1 > kCarTolerance && pointDist2 > kCarTolerance)
|
||||
projected_list->AddSurface(srf2);
|
||||
else
|
||||
delete srf2;
|
||||
|
||||
delete new_knots;
|
||||
|
||||
Splits++;
|
||||
}
|
||||
|
||||
void G4ProjectedSurface::CalcOsloMatrix()
|
||||
{
|
||||
// This algorithm is described in the paper "Making the Oslo-algorithm
|
||||
// more efficient" in SIAM J.NUMER.ANAL. Vol.23, No. 3, June '86
|
||||
// Calculates the oslo-matrix , which is used in mapping the new
|
||||
// knotvector- and controlpoint-values.
|
||||
|
||||
register G4KnotVector *ah;
|
||||
static G4KnotVector *newknots;
|
||||
register int i;
|
||||
register int j;
|
||||
register int mu, muprim;
|
||||
register int v, p;
|
||||
register int iu, il, ih, n1;
|
||||
register int ahi;
|
||||
register G4double beta1;
|
||||
register G4double tj;
|
||||
|
||||
ah = new G4KnotVector(ord*(ord + 1)/2);
|
||||
|
||||
newknots = new G4KnotVector(ord * 2 );
|
||||
|
||||
n1 = new_knots->GetSize() - ord;
|
||||
mu = 0;
|
||||
|
||||
if(oslo_m!=(G4OsloMatrix*)0)
|
||||
{
|
||||
G4OsloMatrix* tmp;
|
||||
while(oslo_m!=oslo_m->next)
|
||||
{
|
||||
tmp=oslo_m->next;
|
||||
delete oslo_m;
|
||||
oslo_m=tmp;
|
||||
}
|
||||
}
|
||||
|
||||
delete oslo_m;
|
||||
|
||||
oslo_m = new G4OsloMatrix();
|
||||
register G4OsloMatrix* o_ptr = oslo_m;
|
||||
|
||||
register G4KnotVector* old_knots;
|
||||
|
||||
if(dir)
|
||||
old_knots = v_knots;
|
||||
else
|
||||
old_knots = u_knots;
|
||||
|
||||
for (j = 0; j < n1; j++)
|
||||
{
|
||||
if ( j != 0 )
|
||||
{
|
||||
oslo_m->next = new G4OsloMatrix();
|
||||
oslo_m = oslo_m->next;
|
||||
}
|
||||
|
||||
//while (old_knots->GetKnot(mu + 1) <= new_knots->GetKnot(j))
|
||||
while ( (new_knots->GetKnot(j) - old_knots->GetKnot(mu + 1)) >
|
||||
kCarTolerance )
|
||||
mu = mu + 1; // find the bounding mu
|
||||
|
||||
i = j + 1;
|
||||
muprim = mu;
|
||||
|
||||
while ( ((abs(new_knots->GetKnot(i) - old_knots->GetKnot(muprim))) <
|
||||
kCarTolerance) && i < (j + ord) )
|
||||
{
|
||||
i++;
|
||||
muprim--;
|
||||
}
|
||||
|
||||
ih = muprim + 1;
|
||||
|
||||
for (v = 0, p = 1; p < ord; p++)
|
||||
{
|
||||
// if (new_knots->GetKnot(j + p) == old_knots->GetKnot(ih))
|
||||
if ( (abs((new_knots->GetKnot(j + p)) - (old_knots->GetKnot(ih)))) <
|
||||
kCarTolerance )
|
||||
ih++;
|
||||
else
|
||||
newknots->PutKnot(++v - 1,new_knots->GetKnot(j + p));
|
||||
}
|
||||
|
||||
ahi = AhIndex(0, ord - 1,ord);
|
||||
ah->PutKnot(ahi, 1.0);
|
||||
|
||||
for (p = 1; p <= v; p++)
|
||||
{
|
||||
beta1 = 0.0;
|
||||
tj = newknots->GetKnot(p-1);
|
||||
|
||||
if (p - 1 >= muprim)
|
||||
{
|
||||
beta1 = AhIndex(p - 1, ord - muprim,ord);
|
||||
beta1 = ((tj - old_knots->GetKnot(0)) * beta1) /
|
||||
(old_knots->GetKnot(p + ord - v) - old_knots->GetKnot(0));
|
||||
}
|
||||
|
||||
i = muprim - p + 1;
|
||||
il = Amax (1, i);
|
||||
i = n1 - 1 + v - p;
|
||||
iu = Amin (muprim, i);
|
||||
|
||||
for (i = il; i <= iu; i++)
|
||||
{
|
||||
register G4double d1, d2;
|
||||
register G4double beta;
|
||||
|
||||
d1 = tj - old_knots->GetKnot(i);
|
||||
d2 = old_knots->GetKnot(i + p + ord - v - 1) - tj;
|
||||
|
||||
beta = ah->GetKnot(AhIndex(p - 1, i + ord - muprim - 1,ord)) /
|
||||
(d1 + d2);
|
||||
|
||||
ah->PutKnot(AhIndex(p, i + ord - muprim - 2,ord), d2 * beta + beta1) ;
|
||||
beta1 = d1 * beta;
|
||||
}
|
||||
|
||||
ah->PutKnot(AhIndex(p, iu + ord - muprim - 1,ord), beta1);
|
||||
|
||||
if (iu < muprim)
|
||||
{
|
||||
register G4double kkk;
|
||||
register G4double ahv;
|
||||
|
||||
kkk = old_knots->GetKnot(n1 - 1 + ord);
|
||||
ahv = AhIndex (p - 1, iu + ord - muprim,ord);
|
||||
ah->PutKnot(AhIndex(p, iu + ord - muprim - 1,ord),
|
||||
beta1 + (kkk - tj) * ahv /
|
||||
(kkk - old_knots->GetKnot(iu + 1)));
|
||||
}
|
||||
}
|
||||
|
||||
delete oslo_m->o_vec;
|
||||
oslo_m->o_vec = new G4KnotVector(v+1);
|
||||
oslo_m->offset = Amax(muprim - v, 0);
|
||||
oslo_m->osize = v;
|
||||
|
||||
for ( i = v, p = 0; i >= 0; i--)
|
||||
oslo_m->o_vec->PutKnot ( p++, ah->GetKnot(AhIndex (v, (ord-1) - i,ord)));
|
||||
|
||||
}
|
||||
|
||||
delete ah;
|
||||
delete newknots;
|
||||
oslo_m->next = oslo_m;
|
||||
oslo_m = o_ptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void G4ProjectedSurface::MapSurface(G4ProjectedSurface* srf)
|
||||
{
|
||||
// This algorithm is described in the paper "Making the Oslo-algorithm
|
||||
// more efficient" in SIAM J.NUMER.ANAL. Vol.23, No. 3, June '86
|
||||
// Maps the new controlpoints into the new surface.
|
||||
|
||||
register G4ControlPoints *c_ptr;
|
||||
register G4OsloMatrix *o_ptr;
|
||||
register G4ControlPoints* new_pts;
|
||||
register G4ControlPoints* old_pts;
|
||||
|
||||
new_pts = srf->ctl_points;
|
||||
|
||||
// Copy the old points so they can be used in calculating the new ones.
|
||||
// In this version, where the splitted surfaces are given
|
||||
// as parameters the copying is not necessary.
|
||||
|
||||
old_pts = new G4ControlPoints(*ctl_points);
|
||||
register int j, // j loop
|
||||
i; // oslo loop
|
||||
c_ptr = new_pts;
|
||||
|
||||
register int size; // The number of rows or columns,
|
||||
// depending on processing order
|
||||
|
||||
if(!dir)
|
||||
size=new_pts->GetRows();
|
||||
else
|
||||
size=new_pts->GetCols();
|
||||
|
||||
for( register int a=0; a<size;a++)
|
||||
{
|
||||
if ( lower != 0)
|
||||
for ( i = 0, o_ptr = oslo_m; i < lower; i++, o_ptr = o_ptr->next);
|
||||
else
|
||||
o_ptr = oslo_m;
|
||||
|
||||
if(!dir)// Direction ROW
|
||||
{
|
||||
for ( j = lower; j < upper; j++, o_ptr = o_ptr->next)
|
||||
{
|
||||
register G4double o_scale;
|
||||
register int x;
|
||||
x=a;
|
||||
|
||||
/* L. Broglia
|
||||
register G4Point2d o_pts = (G4Point2d&)old_pts->get(x,o_ptr->offset);
|
||||
register G4Point2d tempc = (G4Point2d&)c_ptr->get(j/upper,
|
||||
(j)%upper-lower);
|
||||
*/
|
||||
register G4Point3D o_pts = old_pts->Get3D(x, o_ptr->offset);
|
||||
register G4Point3D tempc = c_ptr->Get3D(j/upper, (j)%upper-lower);
|
||||
o_scale = o_ptr->o_vec->GetKnot(0);
|
||||
|
||||
tempc.setX(o_pts.x() * o_scale);
|
||||
tempc.setY(o_pts.y() * o_scale);
|
||||
|
||||
for ( i = 1; i <= o_ptr->osize; i++)
|
||||
{
|
||||
o_scale = o_ptr->o_vec->GetKnot(i);
|
||||
|
||||
/* L. Broglia
|
||||
o_pts = (G4Point2d&)old_pts->get(x,i+o_ptr->offset);
|
||||
tempc.X(tempc.X() + o_scale * o_pts.X());
|
||||
tempc.Y(tempc.Y() + o_scale * o_pts.Y());
|
||||
*/
|
||||
|
||||
o_pts = old_pts->Get3D(x,i+o_ptr->offset);
|
||||
tempc.setX(tempc.x() + o_scale * o_pts.x());
|
||||
tempc.setY(tempc.y() + o_scale * o_pts.y());
|
||||
}
|
||||
|
||||
c_ptr->put(a,(j)%upper-lower,tempc);
|
||||
}
|
||||
}
|
||||
else // dir = COL
|
||||
{
|
||||
for ( j = lower; j < upper; j++, o_ptr = o_ptr->next)
|
||||
{
|
||||
register G4double o_scale;
|
||||
register int x;
|
||||
x=a;
|
||||
|
||||
/* L.Broglia
|
||||
register G4Point2d o_pts = (G4Point2d&)old_pts->get(o_ptr->offset,x);
|
||||
register G4Point2d tempc = (G4Point2d&)c_ptr->get((j)%upper-lower,
|
||||
j/upper);
|
||||
*/
|
||||
register G4Point3D o_pts = old_pts->Get3D(o_ptr->offset,x);
|
||||
register G4Point3D tempc = c_ptr->Get3D((j)%upper-lower, j/upper);
|
||||
|
||||
o_scale = o_ptr->o_vec->GetKnot(0);
|
||||
|
||||
tempc.setX(o_pts.x() * o_scale);
|
||||
tempc.setY(o_pts.y() * o_scale);
|
||||
|
||||
for ( i = 1; i <= o_ptr->osize; i++)
|
||||
{
|
||||
o_scale = o_ptr->o_vec->GetKnot(i);
|
||||
o_pts= old_pts->Get3D(i+o_ptr->offset,a);
|
||||
|
||||
tempc.setX(tempc.x() + o_scale * o_pts.x());
|
||||
tempc.setY(tempc.y() + o_scale * o_pts.y());
|
||||
}
|
||||
|
||||
c_ptr->put((j)%upper-lower,a,tempc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete old_pts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4Ray.cc,v 2.5 1998/10/29 17:49:40 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4Ray.hh"
|
||||
#include "G4PointRat.hh"
|
||||
|
||||
|
||||
/*
|
||||
define in .icc
|
||||
void G4Ray::SetStart(const G4Point3D& p)
|
||||
{
|
||||
SetStart(G4Point3D(p.x(),p.y(),p.z()));
|
||||
}
|
||||
|
||||
|
||||
G4Ray::G4Ray(const G4Point3D& s, const G4Vector3D& d)
|
||||
{
|
||||
SetStart(s);
|
||||
SetDir(G4Vector3D(d.x(),d.y(),d.z()));
|
||||
}
|
||||
|
||||
|
||||
void G4Ray::Init(const G4Point3D& s, const G4Vector3D& d)
|
||||
{
|
||||
SetStart(s); SetDir(G4Vector3D(d.x(),d.y(),d.z()));
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
const G4Plane& G4Ray::GetPlane(const int number_of_plane)const
|
||||
{
|
||||
if(number_of_plane==1)
|
||||
return plane2;
|
||||
else
|
||||
return plane1;
|
||||
}
|
||||
|
||||
|
||||
void G4Ray::CreatePlanes()
|
||||
{
|
||||
// Creates two orthogonal planes(plane1,plane2) the ray (rray)
|
||||
// situated in the intersection of the planes. The planes are
|
||||
// used to project the surface (nurb) in two dimensions.
|
||||
|
||||
G4Vector3D RayDir = dir;
|
||||
G4Point3D RayOrigin = start;
|
||||
|
||||
G4Point3D p1, p2, p3, p4;
|
||||
G4Vector3D dir1, dir2;
|
||||
G4Vector3D invdir = PINFINITY ;
|
||||
|
||||
if(!NearZero(RayDir.x(), SQRT_SMALL_FASTF))
|
||||
invdir.setX(1.0 / RayDir.x());
|
||||
|
||||
if(!NearZero(RayDir.y(), SQRT_SMALL_FASTF))
|
||||
invdir.setY(1.0 / RayDir.y());
|
||||
|
||||
if(!NearZero(RayDir.z(), SQRT_SMALL_FASTF))
|
||||
invdir.setZ(1.0 / RayDir.z());
|
||||
|
||||
MatVecOrtho(dir1, RayDir);
|
||||
|
||||
Vcross( dir2, RayDir, dir1);
|
||||
Vmove(p1, RayOrigin);
|
||||
Vadd2(p2, RayOrigin, RayDir);
|
||||
Vadd2(p3, RayOrigin, dir1);
|
||||
Vadd2(p4, RayOrigin, dir2);
|
||||
|
||||
CalcPlane3Pts( plane1, p1, p3, p2);
|
||||
CalcPlane3Pts( plane2, p1, p2, p4);
|
||||
}
|
||||
|
||||
|
||||
void G4Ray::MatVecOrtho(register G4Vector3D &out,register const G4Vector3D in )
|
||||
{
|
||||
register G4double f;
|
||||
int i_Which;
|
||||
|
||||
if(NearZero(in.x(), 0.0001) && NearZero(in.y(), 0.0001) &&
|
||||
NearZero(in.z(), 0.0001) )
|
||||
{
|
||||
Vsetall( out, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
// Find component closest to zero
|
||||
f = fabs(in.x());
|
||||
i_Which=0;
|
||||
|
||||
if( fabs(in.y()) < f )
|
||||
{
|
||||
f = fabs(in.y());
|
||||
i_Which=1;
|
||||
}
|
||||
|
||||
if( fabs(in.z()) < f )
|
||||
i_Which=2;
|
||||
|
||||
if(!i_Which)
|
||||
f = hypot( in.y(), in.z() );
|
||||
else
|
||||
if(i_Which==1)
|
||||
f = hypot( in.z(), in.x() );
|
||||
else
|
||||
f = hypot( in.x(), in.y() );
|
||||
|
||||
if( NearZero( f, SMALL ) )
|
||||
{
|
||||
Vsetall( out, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
f = 1.0/f;
|
||||
|
||||
if(!i_Which)
|
||||
{
|
||||
out.setX(0.0);
|
||||
out.setY(-in.z()*f);
|
||||
out.setZ( in.y()*f);
|
||||
}
|
||||
else
|
||||
if(i_Which==1)
|
||||
{
|
||||
out.setY(0.0);
|
||||
out.setZ(-in.x()*f);
|
||||
out.setX( in.y()*f);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.setZ(0.0);
|
||||
out.setX(-in.z()*f);
|
||||
out.setY( in.y()*f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// CALC_PLANE_3PTS
|
||||
//
|
||||
// Find the equation of a G4Plane that contains three points.
|
||||
// Note that Normal vector created is expected to point out (see vmath.h),
|
||||
// so the vector from A to C had better be counter-clockwise
|
||||
// (about the point A) from the vector from A to B.
|
||||
// This follows the outward-pointing Normal convention, and the
|
||||
// right-hand rule for cross products.
|
||||
//
|
||||
//
|
||||
// C
|
||||
// *
|
||||
// |\
|
||||
// | \
|
||||
// ^ N | \
|
||||
// | \ | \
|
||||
// | \ | \
|
||||
// |C-A \ | \
|
||||
// | \ | \
|
||||
// | \ | \
|
||||
// \| \
|
||||
// *---------*
|
||||
// A B
|
||||
// ----->
|
||||
// B-A
|
||||
//
|
||||
// If the points are given in the order A B C (eg, *counter*-clockwise),
|
||||
// then the outward pointing surface Normal N = (B-A) x (C-A).
|
||||
//
|
||||
// Explicit Return -
|
||||
// 0 OK
|
||||
// -1 Failure. At least two of the points were not distinct,
|
||||
// or all three were colinear.
|
||||
//
|
||||
// Implicit Return -
|
||||
// G4Plane The G4Plane equation is stored here.
|
||||
|
||||
|
||||
int G4Ray::CalcPlane3Pts(G4Plane &plane1,
|
||||
const G4Point3D& a,
|
||||
const G4Point3D& b,
|
||||
const G4Point3D& c )
|
||||
{
|
||||
// Creates the two orthogonal planes which are needed in projecting the
|
||||
// surface into 2D.
|
||||
|
||||
G4Vector3D B_A;
|
||||
G4Vector3D C_A;
|
||||
G4Vector3D C_B;
|
||||
|
||||
register G4double mag;
|
||||
|
||||
Vsub2( B_A, b, a );
|
||||
Vsub2( C_A, c, a );
|
||||
Vsub2( C_B, c, b );
|
||||
|
||||
Vcross( plane1, B_A, C_A );
|
||||
|
||||
// Ensure unit length Normal
|
||||
if( (mag = Magnitude(plane1)) <= SQRT_SMALL_FASTF )
|
||||
return(-1);// FAIL
|
||||
|
||||
mag = 1/mag;
|
||||
|
||||
G4Plane pl2(plane1);
|
||||
Vscale( plane1, pl2, mag );
|
||||
|
||||
// Find distance from the origin to the G4Plane
|
||||
plane1.d = Vdot( plane1, a );
|
||||
|
||||
return(0); //ok
|
||||
}
|
||||
|
||||
|
||||
void G4Ray::RayCheck()
|
||||
{
|
||||
// Check that the ray has a G4Vector3D...
|
||||
if (dir==G4Vector3D(0, 0, 0))
|
||||
{
|
||||
G4cout << "\nZero direction given. Exiting...\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Make sure that the vector is unit length
|
||||
dir= dir.unit();
|
||||
r_min = 0;
|
||||
r_max = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4RectangularTrimmedSurface.cc,v 2.3 1998/10/20 16:33:58 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "SdaiCONFIG_CONTROL_DESIGN.h"
|
||||
#include "G4RectangularTrimmedSurface.hh"
|
||||
#include "G4FPlane.hh"
|
||||
#include "G4BSplineSurface.hh"
|
||||
#include "G4ToroidalSurface.hh"
|
||||
#include "G4SphericalSurface.hh"
|
||||
|
||||
G4RectangularTrimmedSurface::G4RectangularTrimmedSurface(){}
|
||||
G4RectangularTrimmedSurface::~G4RectangularTrimmedSurface()
|
||||
{
|
||||
delete BasisSurface;
|
||||
}
|
||||
|
||||
|
||||
void G4RectangularTrimmedSurface::CalcBBox()
|
||||
{
|
||||
BasisSurface->CalcBBox();
|
||||
bbox = BasisSurface->bbox;
|
||||
}
|
||||
|
||||
|
||||
int G4RectangularTrimmedSurface::Intersect(const G4Ray& Rayref)
|
||||
{
|
||||
if(BasisSurface->Intersect(Rayref))
|
||||
{
|
||||
G4double UHit = BasisSurface->GetUHit();
|
||||
G4double VHit = BasisSurface->GetVHit();
|
||||
|
||||
if((TrimU1<=UHit)&&(TrimU2>=UHit)&&(TrimV1<=VHit)&&(TrimV2>=VHit))
|
||||
{
|
||||
closest_hit = BasisSurface->closest_hit;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4Sort.cc,v 2.1 1998/10/20 16:33:59 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
// File: G4Sort.cc
|
||||
// Author: Alan Breakstone
|
||||
//
|
||||
// Description
|
||||
//
|
||||
// Routines to G4Sort arrays of various kinds of numbers
|
||||
//
|
||||
|
||||
#include "G4Sort.hh"
|
||||
|
||||
|
||||
void G4Sort_double( G4double v[], int left, int right )
|
||||
{
|
||||
// G4Sort elements in array from v[left] to v[right]
|
||||
// used recursively
|
||||
// algorithm comes from Kernighan and Ritchie, "The C Programming
|
||||
// Language", second edition, p.87
|
||||
|
||||
int i, last;
|
||||
if ( left >= right ) // do nothing if array contains
|
||||
return; // fewer than two elements
|
||||
|
||||
swap_double( v, left, ( left + right ) / 2 ); // move part. elt.
|
||||
last = left; // to v[0]
|
||||
|
||||
for ( i = left+1; i <= right; i++ ) // partition
|
||||
if ( v[i] < v[left] )
|
||||
swap_double( v, ++last, i );
|
||||
|
||||
swap_double( v, left, last ); // restore partition element
|
||||
|
||||
G4Sort_double( v, left, last-1 );
|
||||
G4Sort_double( v, last+1, right );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void swap_double( G4double v[], int i, int j )
|
||||
{
|
||||
/* interchange elements i and j in an array */
|
||||
G4double temp;
|
||||
temp = v[i];
|
||||
v[i] = v[j];
|
||||
v[j] = temp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,881 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4SphericalSurface.cc,v 2.8 1998/11/11 11:22:03 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
/* $Header: /private/Net/unixhub/u1/ea/liml/gismo/gismo-0.2/geometry/RCS/G4SphericalSurface.cc,v 1.10 1992/08 */
|
||||
// File: G4SphericalSurface.cc
|
||||
// Author: Lorraine Lim
|
||||
// Additional author: Alan Breakstone
|
||||
|
||||
// Contents ----------------------------------------------------------
|
||||
//
|
||||
// G4SphericalSurface::G4SphericalSurface()
|
||||
// G4SphericalSurface::G4SphericalSurface( const G4Vector3D& o, const G4Vector3D& xhat,
|
||||
// const G4Vector3D& zhat,
|
||||
// G4double r, G4double ph1, G4double ph2,
|
||||
// G4double th1, G4double th2 )
|
||||
// G4SphericalSurface::PrintOn( ostream& os ) const
|
||||
// G4SphericalSurface::HowNear( const G4Vector3D& x ) const
|
||||
// G4SphericalSurface::distanceAlongRay( int which_way, const Ray* ry,
|
||||
// G4Vector3D& p ) const
|
||||
// G4SphericalSurface::distanceAlongHelix( int which_way, const Helix* hx,
|
||||
// G4Vector3D& p ) const
|
||||
// G4SphericalSurface::Normal( const G4Vector3D& p ) const
|
||||
// G4SphericalSurface::Inside( const G4Vector3D& x ) const
|
||||
// G4SphericalSurface::WithinBoundary( const G4Vector3D& x ) const
|
||||
// G4SphericalSurface::Scale() const
|
||||
// G4SphericalSurface::Area() const
|
||||
// G4SphericalSurface::resize( G4double r, G4double ph1, G4double ph2,
|
||||
// G4double th1, G4double th2 )
|
||||
// G4SphericalSurface::rotate( G4double alpha, G4double beta,
|
||||
// G4double gamma, G4ThreeMat& m, int inverse )
|
||||
// G4SphericalSurface::rotate( G4double alpha, G4double beta,
|
||||
// G4double gamma, int inverse )
|
||||
// G4SphericalSurface::gropeAlongHelix( const Helix* hx ) const
|
||||
//
|
||||
// End ---------------------------------------------------------------
|
||||
|
||||
#include "G4SphericalSurface.hh"
|
||||
|
||||
|
||||
/*
|
||||
G4SphericalSurface::G4SphericalSurface() : G4Surface()
|
||||
{ // default constructor
|
||||
// default x_axis is ( 1.0, 0.0, 0.0 ), z_axis is ( 0.0, 0.0, 1.0 ),
|
||||
// default radius is 1.0
|
||||
// default phi_1 is 0, phi_2 is 2*PI
|
||||
// default theta_1 is 0, theta_2 is PI
|
||||
x_axis = G4Vector3D( 1.0, 0.0, 0.0 );
|
||||
z_axis = G4Vector3D( 0.0, 0.0, 1.0 );
|
||||
radius = 1.0;
|
||||
phi_1 = 0.0;
|
||||
phi_2 = 2*M_PI;
|
||||
theta_1 = 0.0;
|
||||
theta_2 = M_PI;
|
||||
// OuterBoundary = new G4BREPPolyline();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
G4SphericalSurface::G4SphericalSurface( const G4Vector3D& o,
|
||||
const G4Vector3D& xhat,
|
||||
const G4Vector3D& zhat,
|
||||
G4double r,
|
||||
G4double ph1, G4double ph2,
|
||||
G4double th1, G4double th2)
|
||||
//: G4Surface( o )
|
||||
{
|
||||
// Normal constructor
|
||||
G4double twopi = 2.0 * M_PI;
|
||||
|
||||
// Require both x_axis and z_axis to be unit vectors
|
||||
G4double xhatmag = xhat.mag();
|
||||
if ( xhatmag != 0.0 )
|
||||
x_axis = xhat * (1/ xhatmag); // this makes the x_axis a unit vector
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4SphericalSurface::G4SphericalSurface--"
|
||||
<<"x_axis has zero length\n"
|
||||
<< "\tDefault x_axis of (1, 0, 0) is used.\n";
|
||||
|
||||
x_axis = G4Vector3D( 1.0, 0.0, 0.0 );
|
||||
}
|
||||
|
||||
G4double zhatmag = zhat.mag();
|
||||
|
||||
if (zhatmag != 0.0)
|
||||
z_axis = zhat *(1/ zhatmag); // this makes the z_axis a unit vector
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4SphericalSurface::G4SphericalSurface--"
|
||||
<<"z_axis has zero length\n"
|
||||
<< "\tDefault z_axis of (0, 0, 1) is used. \n";
|
||||
|
||||
z_axis = G4Vector3D( 0.0, 0.0, 1.0 );
|
||||
}
|
||||
|
||||
// Require radius to be non-negative
|
||||
if ( r >= 0.0 )
|
||||
radius = r;
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4SphericalSurface::G4SphericalSurface"
|
||||
<< "--radius cannot be less than zero.\n"
|
||||
<< "\tDefault radius of 1.0 is used.\n";
|
||||
|
||||
radius = 1.0;
|
||||
}
|
||||
|
||||
// Require phi_1 in the range: 0 <= phi_1 < 2*PI
|
||||
// and phi_2 in the range: phi_1 < phi_2 <= phi_1 + 2*PI
|
||||
if ( ( ph1 >= 0.0 ) && ( ph1 < 2*M_PI ) )
|
||||
phi_1 = ph1;
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4SphericalSurface::G4SphericalSurface"
|
||||
<< "--lower azimuthal limit is out of range\n"
|
||||
<< "\tDefault angle of 0 is used.\n";
|
||||
|
||||
phi_1 = 0.0;
|
||||
}
|
||||
|
||||
if ( ( ph2 > phi_1 ) && ( ph2 <= ( phi_1 + twopi ) ) )
|
||||
phi_2 = ph2;
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4SphericalSurface::G4SphericalSurface"
|
||||
<< "--upper azimuthal limit is out of range\n"
|
||||
<< "\tDefault angle of 2*PI is used.\n";
|
||||
|
||||
phi_2 = twopi;
|
||||
}
|
||||
|
||||
// Require theta_1 in the range: 0 <= theta_1 < PI
|
||||
// and theta-2 in the range: theta_1 < theta_2 <= theta_1 + PI
|
||||
if ( ( th1 >= 0.0 ) && ( th1 < M_PI ) )
|
||||
theta_1 = th1;
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4SphericalSurface::G4SphericalSurface"
|
||||
<< "--lower polar limit is out of range\n"
|
||||
<< "\tDefault angle of 0 is used.\n";
|
||||
|
||||
theta_1 = 0.0;
|
||||
}
|
||||
|
||||
if ( ( th2 > theta_1 ) && ( th2 <= ( theta_1 + M_PI ) ) )
|
||||
theta_2 =th2;
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4SphericalSurface::G4SphericalSurface"
|
||||
<< "--upper polar limit is out of range\n"
|
||||
<< "\tDefault angle of PI is used.\n";
|
||||
|
||||
theta_2 = M_PI;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void G4SphericalSurface::PrintOn( ostream& os ) const
|
||||
{
|
||||
// printing function using C++ ostream class
|
||||
os << "G4SphericalSurface surface with origin: " << origin << "\t"
|
||||
<< "radius: " << radius << "\n"
|
||||
<< "\t local x_axis: " << x_axis
|
||||
<< "\t local z_axis: " << z_axis << "\n"
|
||||
<< "\t lower azimuthal limit: " << phi_1 << " radians\n"
|
||||
<< "\t upper azimuthal limit: " << phi_2 << " radians\n"
|
||||
<< "\t lower polar limit : " << theta_1 << " radians\n"
|
||||
<< "\t upper polar limit : " << theta_2 << " radians\n";
|
||||
}
|
||||
|
||||
|
||||
G4double G4SphericalSurface::HowNear( const G4Vector3D& x ) const
|
||||
{
|
||||
// Distance from the point x to the G4SphericalSurface.
|
||||
// The distance will be positive if the point is Inside the
|
||||
// G4SphericalSurface, negative if the point is outside.
|
||||
G4Vector3D d = x - origin;
|
||||
G4double rad = d.mag();
|
||||
return (radius - rad);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
G4double G4SphericalSurface::distanceAlongRay( int which_way, const G4Ray* ry,
|
||||
G4Vector3D& p ) const
|
||||
{ // Distance along a Ray (straight line with G4Vector3D) to leave or enter
|
||||
// a G4SphericalSurface. The input variable which_way should be set to +1 to
|
||||
// indicate leaving a G4SphericalSurface, -1 to indicate entering a G4SphericalSurface.
|
||||
// p is the point of intersection of the Ray with the G4SphericalSurface.
|
||||
// If the G4Vector3D of the Ray is opposite to that of the Normal to
|
||||
// the G4SphericalSurface at the intersection point, it will not leave the
|
||||
// G4SphericalSurface.
|
||||
// Similarly, if the G4Vector3D of the Ray is along that of the Normal
|
||||
// to the G4SphericalSurface at the intersection point, it will not enter the
|
||||
// G4SphericalSurface.
|
||||
// This method is called by all finite shapes sub-classed to G4SphericalSurface.
|
||||
// Use the virtual function table to check if the intersection point
|
||||
// is within the boundary of the finite shape.
|
||||
// A negative result means no intersection.
|
||||
// If no valid intersection point is found, set the distance
|
||||
// and intersection point to large numbers.
|
||||
G4double Dist = FLT_MAXX;
|
||||
G4Vector3D lv ( FLT_MAXX, FLT_MAXX, FLT_MAXX );
|
||||
p = lv;
|
||||
// Origin and G4Vector3D unit vector of Ray.
|
||||
G4Vector3D x = ry->Position( 0.0 );
|
||||
G4Vector3D dhat = ry->Direction( 0.0 );
|
||||
int isoln = 0, maxsoln = 2;
|
||||
// array of solutions in distance along the Ray
|
||||
// G4double s[2] = { -1.0, -1.0 };
|
||||
G4double s[2];s[0] = -1.0; s[1]= -1.0 ;
|
||||
// calculate the two solutions (quadratic equation)
|
||||
G4Vector3D d = x - GetOrigin();
|
||||
G4double radius = GetRadius();
|
||||
// quit with no intersection if the radius of the G4SphericalSurface is zero
|
||||
if ( radius <= 0.0 )
|
||||
return Dist;
|
||||
G4double dsq = d * d;
|
||||
G4double rsq = radius * radius;
|
||||
G4double b = d * dhat;
|
||||
G4double c = dsq - rsq;
|
||||
G4double radical = b * b - c;
|
||||
// quit with no intersection if the radical is negative
|
||||
if ( radical < 0.0 )
|
||||
return Dist;
|
||||
G4double root = sqrt( radical );
|
||||
s[0] = -b + root;
|
||||
s[1] = -b - root;
|
||||
// order the possible solutions by increasing distance along the Ray
|
||||
// (G4Sorting routines are in support/G4Sort.h)
|
||||
G4Sort_double( s, isoln, maxsoln-1 );
|
||||
// now loop over each positive solution, keeping the first one (smallest
|
||||
// distance along the Ray) which is within the boundary of the sub-shape
|
||||
// and which also has the correct G4Vector3D with respect to the Normal to
|
||||
// the G4SphericalSurface at the intersection point
|
||||
for ( isoln = 0; isoln < maxsoln; isoln++ ) {
|
||||
if ( s[isoln] >= 0.0 ) {
|
||||
if ( s[isoln] >= FLT_MAXX ) // quit if too large
|
||||
return Dist;
|
||||
Dist = s[isoln];
|
||||
p = ry->Position( Dist );
|
||||
if ( ( ( dhat * Normal( p ) * which_way ) >= 0.0 )
|
||||
&& ( WithinBoundary( p ) == 1 ) )
|
||||
return Dist;
|
||||
}
|
||||
}
|
||||
// get here only if there was no solution within the boundary, Reset
|
||||
// distance and intersection point to large numbers
|
||||
p = lv;
|
||||
return FLT_MAXX;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void G4SphericalSurface::CalcBBox()
|
||||
{
|
||||
G4double x_min = origin.x() - radius;
|
||||
G4double y_min = origin.y() - radius;
|
||||
G4double z_min = origin.z() - radius;
|
||||
G4double x_max = origin.x() + radius;
|
||||
G4double y_max = origin.y() + radius;
|
||||
G4double z_max = origin.z() + radius;
|
||||
|
||||
G4Point3D Min(x_min, y_min, z_min);
|
||||
G4Point3D Max(x_max, y_max, z_max);
|
||||
bbox = new G4BoundingBox3D( Min, Max);
|
||||
}
|
||||
|
||||
|
||||
int G4SphericalSurface::Intersect( const G4Ray& ry )
|
||||
{
|
||||
// Distance along a Ray (straight line with G4Vector3D) to leave or enter
|
||||
// a G4SphericalSurface. The input variable which_way should be set to +1
|
||||
// to indicate leaving a G4SphericalSurface, -1 to indicate entering a
|
||||
// G4SphericalSurface.
|
||||
// p is the point of intersection of the Ray with the G4SphericalSurface.
|
||||
// If the G4Vector3D of the Ray is opposite to that of the Normal to
|
||||
// the G4SphericalSurface at the intersection point, it will not leave the
|
||||
// G4SphericalSurface.
|
||||
// Similarly, if the G4Vector3D of the Ray is along that of the Normal
|
||||
// to the G4SphericalSurface at the intersection point, it will not enter
|
||||
// the G4SphericalSurface.
|
||||
// This method is called by all finite shapes sub-classed to
|
||||
// G4SphericalSurface.
|
||||
// Use the virtual function table to check if the intersection point
|
||||
// is within the boundary of the finite shape.
|
||||
// A negative result means no intersection.
|
||||
// If no valid intersection point is found, set the distance
|
||||
// and intersection point to large numbers.
|
||||
|
||||
int which_way = (int)HowNear(ry.GetStart());
|
||||
//Originally a parameter.Read explanation above.
|
||||
|
||||
if(!which_way)which_way =-1;
|
||||
distance = FLT_MAXX;
|
||||
|
||||
G4Vector3D lv ( FLT_MAXX, FLT_MAXX, FLT_MAXX );
|
||||
|
||||
// p = lv;
|
||||
closest_hit = lv;
|
||||
|
||||
// Origin and G4Vector3D unit vector of Ray.
|
||||
// G4Vector3D x = ry->position( 0.0 );
|
||||
G4Vector3D x=ry.GetStart();
|
||||
|
||||
// G4Vector3D dhat = ry->direction( 0.0 );
|
||||
G4Vector3D dhat = ry.GetDir();
|
||||
int isoln = 0, maxsoln = 2;
|
||||
|
||||
// array of solutions in distance along the Ray
|
||||
G4double s[2];
|
||||
s[0] = -1.0 ;
|
||||
s[1] = -1.0 ;
|
||||
|
||||
// calculate the two solutions (quadratic equation)
|
||||
G4Vector3D d = x - GetOrigin();
|
||||
G4double r = GetRadius();
|
||||
|
||||
// quit with no intersection if the radius of the G4SphericalSurface is zero
|
||||
if ( r <= 0.0 )
|
||||
return 0;
|
||||
|
||||
G4double dsq = d * d;
|
||||
G4double rsq = r * r;
|
||||
G4double b = d * dhat;
|
||||
G4double c = dsq - rsq;
|
||||
G4double radical = b * b - c;
|
||||
|
||||
// quit with no intersection if the radical is negative
|
||||
if ( radical < 0.0 )
|
||||
return 0;
|
||||
|
||||
G4double root = sqrt( radical );
|
||||
s[0] = -b + root;
|
||||
s[1] = -b - root;
|
||||
|
||||
// order the possible solutions by increasing distance along the Ray
|
||||
// (G4Sorting routines are in support/G4Sort.h)
|
||||
// G4Sort_double( s, isoln, maxsoln-1 );
|
||||
if(s[0] > s[1])
|
||||
{
|
||||
G4double tmp =s[0];
|
||||
s[0] = s[1];
|
||||
s[1] = tmp;
|
||||
}
|
||||
|
||||
// now loop over each positive solution, keeping the first one (smallest
|
||||
// distance along the Ray) which is within the boundary of the sub-shape
|
||||
// and which also has the correct G4Vector3D with respect to the Normal to
|
||||
// the G4SphericalSurface at the intersection point
|
||||
for ( isoln = 0; isoln < maxsoln; isoln++ )
|
||||
{
|
||||
if ( s[isoln] >= kCarTolerance*0.5 )
|
||||
{
|
||||
if ( s[isoln] >= FLT_MAXX ) // quit if too large
|
||||
return 0;
|
||||
|
||||
distance = s[isoln];
|
||||
closest_hit = ry.GetPoint( distance );
|
||||
if ( ( ( dhat * Normal( closest_hit ) * which_way ) >= 0.0 ) &&
|
||||
( WithinBoundary( closest_hit ) == 1 ) )
|
||||
{
|
||||
distance = distance*distance;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get here only if there was no solution within the boundary, Reset
|
||||
// distance and intersection point to large numbers
|
||||
// p = lv;
|
||||
// return FLT_MAXX;
|
||||
distance = FLT_MAXX;
|
||||
closest_hit = lv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
G4double G4SphericalSurface::distanceAlongHelix( int which_way, const Helix* hx,
|
||||
G4Vector3D& p ) const
|
||||
{ // Distance along a Helix to leave or enter a G4SphericalSurface.
|
||||
// The input variable which_way should be set to +1 to
|
||||
// indicate leaving a G4SphericalSurface, -1 to indicate entering a G4SphericalSurface.
|
||||
// p is the point of intersection of the Helix with the G4SphericalSurface.
|
||||
// If the G4Vector3D of the Helix is opposite to that of the Normal to
|
||||
// the G4SphericalSurface at the intersection point, it will not leave the
|
||||
// G4SphericalSurface.
|
||||
// Similarly, if the G4Vector3D of the Helix is along that of the Normal
|
||||
// to the G4SphericalSurface at the intersection point, it will not enter the
|
||||
// G4SphericalSurface.
|
||||
// This method is called by all finite shapes sub-classed to G4SphericalSurface.
|
||||
// Use the virtual function table to check if the intersection point
|
||||
// is within the boundary of the finite shape.
|
||||
// If no valid intersection point is found, set the distance
|
||||
// and intersection point to large numbers.
|
||||
// Possible negative distance solutions are discarded.
|
||||
G4double Dist = FLT_MAXX;
|
||||
G4Vector3D lv ( FLT_MAXX, FLT_MAXX, FLT_MAXX );
|
||||
p = lv;
|
||||
int isoln = 0, maxsoln = 4;
|
||||
// Array of solutions in turning angle
|
||||
// G4double s[4] = { -1.0, -1.0, -1.0, -1.0 };
|
||||
G4double s[4];s[0] = -1.0; s[1]= -1.0 ;s[2] = -1.0; s[3]= -1.0 ;
|
||||
|
||||
// Helix parameters
|
||||
G4double rh = hx->GetRadius(); // radius of Helix
|
||||
G4Vector3D oh = hx->position( 0.0 ); // origin of Helix
|
||||
G4Vector3D dh = hx->direction( 0.0 ); // initial G4Vector3D of Helix
|
||||
G4Vector3D prp = hx->getPerp(); // perpendicular vector
|
||||
G4double prpmag = prp.mag();
|
||||
G4double rhp = rh / prpmag;
|
||||
// G4SphericalSurface parameters
|
||||
G4double rs = GetRadius(); // radius of G4SphericalSurface
|
||||
if ( rs == 0.0 ) // quit if zero radius
|
||||
return Dist;
|
||||
G4Vector3D os = GetOrigin(); // origin of G4SphericalSurface
|
||||
//
|
||||
// Calculate quantities of use later on
|
||||
G4Vector3D alpha = rhp * prp;
|
||||
G4Vector3D beta = rhp * dh;
|
||||
G4Vector3D gamma = oh - os;
|
||||
//
|
||||
// Only consider approximate solutions to quadratic order in the turning
|
||||
// angle along the Helix
|
||||
G4double A = beta * beta + gamma * alpha;
|
||||
G4double B = 2.0 * gamma * beta;
|
||||
G4double C = gamma * gamma - rs * rs;
|
||||
// Case if quadratic term is zero
|
||||
if ( fabs( A ) < FLT_EPSILO ) {
|
||||
if ( B == 0.0 ) // no intersection, quit
|
||||
return Dist;
|
||||
else // B != 0
|
||||
s[0] = -C / B;
|
||||
}
|
||||
// General quadratic solution, A != 0
|
||||
else {
|
||||
G4double radical = B * B - 4.0 * A * C;
|
||||
if ( radical < 0.0 ) // no intersection, quit
|
||||
return Dist;
|
||||
G4double root = sqrt( radical );
|
||||
s[0] = ( -B + root ) / ( 2.0 * A );
|
||||
s[1] = ( -B - root ) / ( 2.0 * A );
|
||||
if ( rh < 0.0 ) {
|
||||
s[0] = -s[0];
|
||||
s[1] = -s[1];
|
||||
}
|
||||
s[2] = s[0] + 2.0 * M_PI;
|
||||
s[3] = s[1] + 2.0 * M_PI;
|
||||
}
|
||||
//
|
||||
// Order the possible solutions by increasing turning angle
|
||||
// (G4Sorting routines are in support/G4Sort.h).
|
||||
G4Sort_double( s, isoln, maxsoln-1 );
|
||||
//
|
||||
// Now loop over each positive solution, keeping the first one (smallest
|
||||
// distance along the Helix) which is within the boundary of the sub-shape.
|
||||
for ( isoln = 0; isoln < maxsoln; isoln++ ) {
|
||||
if ( s[isoln] >= 0.0 ) {
|
||||
// Calculate distance along Helix and position and G4Vector3D vectors.
|
||||
Dist = s[isoln] * fabs( rhp );
|
||||
p = hx->position( Dist );
|
||||
G4Vector3D d = hx->direction( Dist );
|
||||
// Now do approximation to get remaining distance to correct this solution
|
||||
// iterate it until the accuracy is below the user-set surface precision.
|
||||
G4double delta = 0.;
|
||||
G4double delta0 = FLT_MAXX;
|
||||
int dummy = 1;
|
||||
int iter = 0;
|
||||
int in0 = Inside( hx->position ( 0.0 ) );
|
||||
int in1 = Inside( p );
|
||||
G4double sc = Scale();
|
||||
while ( dummy ) {
|
||||
iter++;
|
||||
// Terminate loop after 50 iterations and Reset distance to large number,
|
||||
// indicating no intersection with G4SphericalSurface.
|
||||
// This generally occurs if the Helix curls too tightly to Intersect it.
|
||||
if ( iter > 50 ) {
|
||||
Dist = FLT_MAXX;
|
||||
p = lv;
|
||||
break;
|
||||
}
|
||||
// Find distance from the current point along the above-calculated
|
||||
// G4Vector3D using a Ray.
|
||||
// The G4Vector3D of the Ray and the Sign of the distance are determined
|
||||
// by whether the starting point of the Helix is Inside or outside of
|
||||
// the G4SphericalSurface.
|
||||
in1 = Inside( p );
|
||||
if ( in1 ) { // current point Inside
|
||||
if ( in0 ) { // starting point Inside
|
||||
Ray* r = new Ray( p, d );
|
||||
delta =
|
||||
distanceAlongRay( 1, r, p );
|
||||
delete r;
|
||||
}
|
||||
else { // starting point outside
|
||||
Ray* r = new Ray( p, -d );
|
||||
delta =
|
||||
-distanceAlongRay( 1, r, p );
|
||||
delete r;
|
||||
}
|
||||
}
|
||||
else { // current point outside
|
||||
if ( in0 ) { // starting point Inside
|
||||
Ray* r = new Ray( p, -d );
|
||||
delta =
|
||||
-distanceAlongRay( -1, r, p );
|
||||
delete r;
|
||||
}
|
||||
else { // starting point outside
|
||||
Ray* r = new Ray( p, d );
|
||||
delta =
|
||||
distanceAlongRay( -1, r, p );
|
||||
delete r;
|
||||
}
|
||||
}
|
||||
// Test if distance is less than the surface precision, if so Terminate loop.
|
||||
if ( fabs( delta / sc ) <= SURFACE_PRECISION )
|
||||
break;
|
||||
// Ff delta has not changed sufficiently from the previous iteration,
|
||||
// skip out of this loop.
|
||||
if ( fabs( ( delta - delta0 ) / sc ) <=
|
||||
SURFACE_PRECISION )
|
||||
break;
|
||||
// If delta has increased in absolute value from the previous iteration
|
||||
// either the Helix doesn't Intersect the G4SphericalSurface or the approximate
|
||||
// solution is too far from the real solution. Try groping for a solution.
|
||||
// If not found, Reset distance to large number, indicating no intersection
|
||||
// with the G4SphericalSurface.
|
||||
if ( ( fabs( delta ) > fabs( delta0 ) ) ) {
|
||||
Dist = fabs( rhp ) *
|
||||
gropeAlongHelix( hx );
|
||||
if ( Dist < 0.0 ) {
|
||||
Dist = FLT_MAXX;
|
||||
p = lv;
|
||||
}
|
||||
else
|
||||
p = hx->position( Dist );
|
||||
break;
|
||||
}
|
||||
// Set old delta to new one.
|
||||
delta0 = delta;
|
||||
// Add distance to G4SphericalSurface to distance along Helix.
|
||||
Dist += delta;
|
||||
// Negative distance along Helix means Helix doesn't Intersect G4SphericalSurface.
|
||||
// Reset distance to large number, indicating no intersection with G4SphericalSurface.
|
||||
if ( Dist < 0.0 ) {
|
||||
Dist = FLT_MAXX;
|
||||
p = lv;
|
||||
break;
|
||||
}
|
||||
// Recalculate point along Helix and the G4Vector3D.
|
||||
p = hx->position( Dist );
|
||||
d = hx->direction( Dist );
|
||||
} // end of while loop
|
||||
// Now have best value of distance along Helix and position for this
|
||||
// solution, so test if it is within the boundary of the sub-shape
|
||||
// and require that it point in the correct G4Vector3D with respect to
|
||||
// the Normal to the G4SphericalSurface.
|
||||
if ( ( Dist < FLT_MAXX ) &&
|
||||
( ( hx->direction( Dist ) * Normal( p ) *
|
||||
which_way ) >= 0.0 ) &&
|
||||
( WithinBoundary( p ) == 1 ) )
|
||||
return Dist;
|
||||
} // end of if s[isoln] >= 0.0 condition
|
||||
} // end of for loop over solutions
|
||||
// If one gets here, there is no solution, so set distance along Helix
|
||||
// and position to large numbers.
|
||||
Dist = FLT_MAXX;
|
||||
p = lv;
|
||||
return Dist;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
G4Vector3D G4SphericalSurface::Normal( const G4Vector3D& p ) const
|
||||
{ // Return the Normal unit vector to the G4SphericalSurface at a point p on
|
||||
// (or nearly on) the G4SphericalSurface.
|
||||
G4Vector3D n = p - origin;
|
||||
G4double nmag = n.mag();
|
||||
if ( nmag != 0.0 )
|
||||
n = n / nmag;
|
||||
// If the point p happens to coincide with the origin (which is possible
|
||||
// if the radius is zero), set the Normal to the z-axis unit vector.
|
||||
else
|
||||
n = G4Vector3D( 0.0, 0.0, 1.0 );
|
||||
return n;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
G4Vector3D G4SphericalSurface::Normal( const G4Vector3D& p ) const
|
||||
{
|
||||
// Return the Normal unit vector to the G4SphericalSurface at a point p on
|
||||
// (or nearly on) the G4SphericalSurface.
|
||||
G4Vector3D n = p - origin;
|
||||
G4double nmag = n.mag();
|
||||
|
||||
if ( nmag != 0.0 )
|
||||
n = n * (1/ nmag);
|
||||
|
||||
// If the point p happens to coincide with the origin (which is possible
|
||||
// if the radius is zero), set the Normal to the z-axis unit vector.
|
||||
else
|
||||
n = G4Vector3D( 0.0, 0.0, 1.0 );
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
G4Vector3D G4SphericalSurface::SurfaceNormal( const G4Point3D& p ) const
|
||||
{
|
||||
// Return the Normal unit vector to the G4SphericalSurface at a point p on
|
||||
// (or nearly on) the G4SphericalSurface.
|
||||
G4Vector3D n = p - origin;
|
||||
G4double nmag = n.mag();
|
||||
|
||||
if ( nmag != 0.0 )
|
||||
n = n * (1/ nmag);
|
||||
|
||||
// If the point p happens to coincide with the origin (which is possible
|
||||
// if the radius is zero), set the Normal to the z-axis unit vector.
|
||||
else
|
||||
n = G4Vector3D( 0.0, 0.0, 1.0 );
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
int G4SphericalSurface::Inside ( const G4Vector3D& x ) const
|
||||
{
|
||||
// Return 0 if point x is outside G4SphericalSurface, 1 if Inside.
|
||||
// Outside means that the distance to the G4SphericalSurface would
|
||||
// be negative.
|
||||
// Use the HowNear function to calculate this distance.
|
||||
if ( HowNear( x ) >= 0.0 )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int G4SphericalSurface::WithinBoundary( const G4Vector3D& x ) const
|
||||
{
|
||||
// return 1 if point x is on the G4SphericalSurface, otherwise return zero
|
||||
// (x is assumed to lie on the surface of the G4SphericalSurface, so one
|
||||
// only checks the angular limits)
|
||||
G4Vector3D y_axis = z_axis.cross( x_axis );
|
||||
|
||||
// components of x in the local coordinate system of the G4SphericalSurface
|
||||
G4double px = x * x_axis;
|
||||
G4double py = x * y_axis;
|
||||
G4double pz = x * z_axis;
|
||||
|
||||
// check if within polar angle limits
|
||||
G4double theta = acos( pz / x.mag() ); // acos in range 0 to PI
|
||||
|
||||
// Normal case
|
||||
if ( theta_2 <= M_PI )
|
||||
{
|
||||
if ( ( theta < theta_1 ) || ( theta > theta_2 ) )
|
||||
return 0;
|
||||
}
|
||||
|
||||
// this is for the case that theta_2 is greater than PI
|
||||
else
|
||||
{
|
||||
theta += M_PI;
|
||||
if ( ( theta < theta_1 ) || ( theta > theta_2 ) )
|
||||
return 0;
|
||||
}
|
||||
|
||||
// now check if within azimuthal angle limits
|
||||
G4double phi = atan2( py, px ); // atan2 in range -PI to PI
|
||||
G4double twopi = 2.0 * M_PI;
|
||||
|
||||
if ( phi < 0.0 )
|
||||
phi += twopi;
|
||||
|
||||
// Normal case
|
||||
if ( ( phi >= phi_1 ) && ( phi <= phi_2 ) )
|
||||
return 1;
|
||||
|
||||
// this is for the case that phi_2 is greater than 2*PI
|
||||
phi += twopi;
|
||||
|
||||
if ( ( phi >= phi_1 ) && ( phi <= phi_2 ) )
|
||||
return 1;
|
||||
// get here if not within azimuthal limits
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
G4double G4SphericalSurface::Scale() const
|
||||
{
|
||||
// Returns the radius of a G4SphericalSurface unless it is zero, in which
|
||||
// case returns the arbitrary number 1.0.
|
||||
// Used for Scale-invariant tests of surface thickness.
|
||||
if ( radius == 0.0 )
|
||||
return 1.0;
|
||||
else
|
||||
return radius;
|
||||
}
|
||||
|
||||
|
||||
G4double G4SphericalSurface::Area() const
|
||||
{
|
||||
// Returns the Area of a G4SphericalSurface
|
||||
return ( 2.0*( theta_2 - theta_1 )*( phi_2 - phi_1)*radius*radius/M_PI );
|
||||
}
|
||||
|
||||
|
||||
void G4SphericalSurface::resize( G4double r,
|
||||
G4double ph1, G4double ph2,
|
||||
G4double th1, G4double th2 )
|
||||
{
|
||||
// Resize the G4SphericalSurface to new radius r, new lower and upper
|
||||
// azimuthal angle limits ph1 and ph2, and new lower and upper polar
|
||||
// angle limits th1 and th2.
|
||||
|
||||
// Require radius to be non-negative
|
||||
if ( r >= 0.0 )
|
||||
radius = r;
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4SphericalSurface::resize"
|
||||
<< "--radius cannot be less than zero.\n"
|
||||
<< "\tOriginal value of " << radius << " is retained.\n";
|
||||
}
|
||||
|
||||
// Require azimuthal angles to be within bounds
|
||||
G4double twopi = 2.0 * M_PI;
|
||||
|
||||
if ( ( ph1 >= 0.0 ) && ( ph1 < twopi ) )
|
||||
phi_1 = ph1;
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4SphericalSurface::resize"
|
||||
<< "--lower azimuthal limit out of range\n"
|
||||
<< "\tOriginal value of " << phi_1 << " is retained.\n";
|
||||
}
|
||||
|
||||
if ( ( ph2 > phi_1 ) && ( ph2 <= ( phi_1 + twopi ) ) )
|
||||
phi_2 = ph2;
|
||||
else
|
||||
{
|
||||
ph2 = ( phi_2 <= phi_1 ) ? ( phi_1 + FLT_EPSILO ) : phi_2;
|
||||
phi_2 = ph2;
|
||||
G4cerr << "Error in G4SphericalSurface::resize"
|
||||
<< "--upper azimuthal limit out of range\n"
|
||||
<< "\tValue of " << phi_2 << " is used.\n";
|
||||
}
|
||||
|
||||
// Require polar angles to be within bounds
|
||||
if ( ( th1 >= 0.0 ) && ( th1 < M_PI ) )
|
||||
theta_1 = th1;
|
||||
else
|
||||
{
|
||||
G4cerr << "Error in G4SphericalSurface::resize"
|
||||
<< "--lower polar limit out of range\n"
|
||||
<< "\tOriginal value of " << theta_1 << " is retained.\n";
|
||||
}
|
||||
|
||||
if ( ( th2 > theta_1 ) && ( th2 <= ( theta_1 + M_PI ) ) )
|
||||
theta_2 = th2;
|
||||
else
|
||||
{
|
||||
th2 = ( theta_2 <= theta_1 ) ? ( theta_1 + FLT_EPSILO ) : theta_2;
|
||||
theta_2 = th2;
|
||||
G4cerr << "Error in G4SphericalSurface::resize"
|
||||
<< "--upper polar limit out of range\n"
|
||||
<< "\tValue of " << theta_2 << " is used.\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void G4SphericalSurface::rotate( G4double alpha, G4double beta,
|
||||
G4double gamma, G4ThreeMat& m, int inverse )
|
||||
{ // rotate G4SphericalSurface first about global x_axis by angle alpha,
|
||||
// second about global y-axis by angle beta,
|
||||
// and third about global z_axis by angle gamma
|
||||
// by creating and using G4ThreeMat objects in Surface::rotate
|
||||
// angles are assumed to be given in radians
|
||||
// if inverse is non-zero, the order of rotations is reversed
|
||||
// the axis is rotated here, the origin is rotated by calling
|
||||
// Surface::rotate
|
||||
G4Surface::rotate( alpha, beta, gamma, m, inverse );
|
||||
x_axis = m * x_axis;
|
||||
z_axis = m * z_axis;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
void G4SphericalSurface::rotate( G4double alpha, G4double beta,
|
||||
G4double gamma, int inverse )
|
||||
{ // rotate G4SphericalSurface first about global x_axis by angle alpha,
|
||||
// second about global y-axis by angle beta,
|
||||
// and third about global z_axis by angle gamma
|
||||
// by creating and using G4ThreeMat objects in Surface::rotate
|
||||
// angles are assumed to be given in radians
|
||||
// if inverse is non-zero, the order of rotations is reversed
|
||||
// the axis is rotated here, the origin is rotated by calling
|
||||
// Surface::rotate
|
||||
G4ThreeMat m;
|
||||
G4Surface::rotate( alpha, beta, gamma, m, inverse );
|
||||
x_axis = m * x_axis;
|
||||
z_axis = m * z_axis;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
G4double G4SphericalSurface::gropeAlongHelix( const Helix* hx ) const
|
||||
{ // Grope for a solution of a Helix intersecting a G4SphericalSurface.
|
||||
// This function returns the turning angle (in radians) where the
|
||||
// intersection occurs with only positive values allowed, or -1.0 if
|
||||
// no intersection is found.
|
||||
// The idea is to start at the beginning of the Helix, then take steps
|
||||
// of some fraction of a turn. If at the end of a Step, the current position
|
||||
// along the Helix and the previous position are on opposite sides of the
|
||||
// G4SphericalSurface, then the solution must lie somewhere in between.
|
||||
int one_over_f = 8; // one over fraction of a turn to go in each Step
|
||||
G4double turn_angle = 0.0;
|
||||
G4double dist_along = 0.0;
|
||||
G4double d_new;
|
||||
G4double fk = 1.0 / G4double( one_over_f );
|
||||
G4double scal = Scale();
|
||||
G4double d_old = HowNear( hx->position( dist_along ) );
|
||||
G4double rh = hx->GetRadius(); // radius of Helix
|
||||
G4Vector3D prp = hx->getPerp(); // perpendicular vector
|
||||
G4double prpmag = prp.mag();
|
||||
G4double rhp = rh / prpmag;
|
||||
int max_iter = one_over_f * HELIX_MAX_TURNS;
|
||||
// Take up to a user-settable number of turns along the Helix,
|
||||
// groping for an intersection point.
|
||||
for ( int k = 1; k < max_iter; k++ ) {
|
||||
turn_angle = 2.0 * M_PI * k / one_over_f;
|
||||
dist_along = turn_angle * fabs( rhp );
|
||||
d_new = HowNear( hx->position( dist_along ) );
|
||||
if ( ( d_old < 0.0 && d_new > 0.0 ) ||
|
||||
( d_old > 0.0 && d_new < 0.0 ) ) {
|
||||
d_old = d_new;
|
||||
// Old and new points are on opposite sides of the G4SphericalSurface, therefore
|
||||
// a solution lies in between, use a binary search to pin the point down
|
||||
// to the surface precision, but don't do more than 50 iterations.
|
||||
int itr = 0;
|
||||
while ( fabs( d_new / scal ) > SURFACE_PRECISION ) {
|
||||
itr++;
|
||||
if ( itr > 50 )
|
||||
return turn_angle;
|
||||
turn_angle -= fk * M_PI;
|
||||
dist_along = turn_angle * fabs( rhp );
|
||||
d_new = HowNear( hx->position( dist_along ) );
|
||||
if ( ( d_old < 0.0 && d_new > 0.0 ) ||
|
||||
( d_old > 0.0 && d_new < 0.0 ) )
|
||||
fk *= -0.5;
|
||||
else
|
||||
fk *= 0.5;
|
||||
d_old = d_new;
|
||||
} // end of while loop
|
||||
return turn_angle; // this is the best solution
|
||||
} // end of if condition
|
||||
} // end of for loop
|
||||
// Get here only if no solution is found, so return -1.0 to indicate that.
|
||||
return -1.0;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,324 @@
|
||||
#include "G4Surface.hh"
|
||||
#include "G4CompositeCurve.hh"
|
||||
|
||||
G4Surface::G4Surface(): FLT_MAXX(kInfinity), FLT_EPSILO(0.0001)
|
||||
{
|
||||
AdvancedFace=0;
|
||||
active = 1;
|
||||
distance = 1.0e20;
|
||||
Type=0;
|
||||
bbox = (G4BoundingBox3D*)0;
|
||||
}
|
||||
|
||||
G4Surface::~G4Surface() {}
|
||||
|
||||
//void G4Surface::read_surface(fstream& tmp){;}
|
||||
G4Point3D G4Surface::Evaluation(const G4Ray& rayref){return closest_hit;}
|
||||
int G4Surface::Evaluate(const G4Ray& rayref){return 0;}
|
||||
|
||||
void G4Surface::SetBoundaries(G4CurveVector* boundaries)
|
||||
{
|
||||
surfaceBoundary.Init(*boundaries);
|
||||
InitBounded();
|
||||
}
|
||||
|
||||
|
||||
void G4Surface::CalcBBox()
|
||||
{
|
||||
// Finds the bounds of the surface iow
|
||||
// calculates the bounds for a bounding box
|
||||
// to the surface. The bounding box is used
|
||||
// for a preliminary check of intersection.
|
||||
|
||||
bbox = new G4BoundingBox3D(surfaceBoundary.BBox().GetBoxMin(),
|
||||
surfaceBoundary.BBox().GetBoxMax());
|
||||
// old implementation
|
||||
// G4Point3d BoundaryMax = OuterBoundary->GetBoundsMax();
|
||||
// G4Point3d BoundaryMin = OuterBoundary->GetBoundsMin();
|
||||
// bbox = new G4BoundingBox( BoundaryMin, BoundaryMax);
|
||||
// return;
|
||||
}
|
||||
|
||||
G4Vector3D G4Surface::Normal( const G4Vector3D& ) const
|
||||
{ // return the Normal unit vector to a Surface at the point p on
|
||||
// (or nearly on) the Surface.
|
||||
// The default is not well defined, so return ( 0, 0, 0 ).
|
||||
return G4Vector3D( 0.0, 0.0, 0.0 );
|
||||
}
|
||||
|
||||
|
||||
int G4Surface::Intersect(const G4Ray& rayref)
|
||||
{
|
||||
int Result = 0;
|
||||
|
||||
G4Exception("G4Surface::Intersect is not implemented. It should not be called. ");
|
||||
|
||||
#ifdef NEW_IMPLEMENTATION
|
||||
// get the intersection
|
||||
// Result = Intersect(rayref);
|
||||
|
||||
// Check that the point is within the polyline
|
||||
// Get Normal at Hitpoint
|
||||
const G4Vector3D& Vec = Normal(closest_hit);
|
||||
G4Ray Normal(closest_hit, Vec);
|
||||
|
||||
// Project points & Hit
|
||||
// OuterBoundary->ProjectBoundaryTo2D(Normal.GetPlane(1),
|
||||
// Normal.GetPlane(2), 0);
|
||||
|
||||
|
||||
|
||||
|
||||
G4Point3D Hit = closest_hit.Project(Normal.GetPlane(1),
|
||||
Normal.GetPlane(2) );
|
||||
// Check point in polygon
|
||||
// Result = OuterBoundary->Inside(Hit, rayref);
|
||||
|
||||
#endif
|
||||
return Result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
G4double G4Surface::ClosestDistanceToPoint(const G4Point3D& Pt)
|
||||
{
|
||||
// in fact, a squared distance is returned
|
||||
|
||||
// a bit suspicious, this function
|
||||
// the distance is almost always an overestimate
|
||||
G4double pointDistance= kInfinity;
|
||||
G4double tmpDistance;
|
||||
const G4CurveVector& bounds= surfaceBoundary.GetBounds();
|
||||
|
||||
G4int entr = bounds.entries();
|
||||
|
||||
for (G4int i=0; i<entr; i++)
|
||||
{
|
||||
G4Curve* c= bounds(i);
|
||||
|
||||
if (c->GetEntityType() == "G4CompositeCurve")
|
||||
{
|
||||
G4CompositeCurve* cc= (G4CompositeCurve*)c;
|
||||
const G4CurveVector& segments= cc->GetSegments();
|
||||
for (G4int i=0; i<segments.entries(); i++)
|
||||
{
|
||||
G4Curve* ccc= segments(i);
|
||||
tmpDistance= (G4Point3D(Pt.x(), Pt.y(), Pt.z())-ccc->GetEnd()).mag2();
|
||||
if (pointDistance > tmpDistance)
|
||||
{
|
||||
pointDistance= tmpDistance;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpDistance= (G4Point3D(Pt.x(), Pt.y(), Pt.z())-c->GetEnd()).mag2();
|
||||
if (pointDistance > tmpDistance)
|
||||
{
|
||||
pointDistance= tmpDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// L. Broglia
|
||||
// Be carreful ! pointdistance is the squared distance
|
||||
return sqrt(pointDistance);
|
||||
|
||||
// G4double PointDistance=INFINITY;
|
||||
// G4double TmpDistance=0;
|
||||
// PointDistance = OuterBoundary->ClosestDistanceToPoint(Pt);
|
||||
// TmpDistance =0;
|
||||
// for(int a=0;a<NumberOfInnerBoundaries;a++)
|
||||
// {
|
||||
// TmpDistance = InnerBoundary[a]->ClosestDistanceToPoint(Pt);
|
||||
// if(PointDistance > TmpDistance) PointDistance = TmpDistance;
|
||||
// }
|
||||
// return PointDistance;
|
||||
|
||||
//G4double G4Boundary::ClosestDistanceToPoint(const G4ThreeVec& Pt)
|
||||
//{
|
||||
// G4double PointDistance = INFINITY;
|
||||
// G4double TmpDistance = 0;
|
||||
// for(int a =0; a < NumberOfPoints;a++)
|
||||
// {
|
||||
// G4Point3d& Pt2 = GetPoint(a);
|
||||
// TmpDistance = Pt2.Distance(Pt);
|
||||
// if(PointDistance > TmpDistance)PointDistance = TmpDistance;
|
||||
// }
|
||||
// return PointDistance;
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
// Gismo members, modified by J.Sulkimo
|
||||
|
||||
// Author: Alan Breakstone
|
||||
|
||||
// Contents ----------------------------------------------------------
|
||||
//
|
||||
// operator<<( ostream& os, const Surface& s )
|
||||
// Surface::PrintOn( ostream& os ) const
|
||||
// Surface::HowNear( const G4ThreeVec& x ) const
|
||||
// Surface::distanceAlongRay( int which_way, const Ray* ry,
|
||||
// G4ThreeVec& p ) const
|
||||
// Surface::distanceAlongHelix( int which_way, const Helix* hx,
|
||||
// G4ThreeVec& p ) const
|
||||
// Surface::Normal() const
|
||||
// Surface::Normal( const G4ThreeVec& p ) const
|
||||
// Surface::Inside( const G4ThreeVec& p ) const
|
||||
// Surface::move( const G4ThreeVec& p )
|
||||
// Surface::rotate( G4double alpha, G4double beta,
|
||||
// G4double gamma, G4ThreeMat& m, int inverse )
|
||||
// Surface::rotate( G4double alpha, G4double beta,
|
||||
// G4double gamma, int inverse )
|
||||
//
|
||||
// End ---------------------------------------------------------------
|
||||
|
||||
ostream& operator<<( ostream& os, const G4Surface& s )
|
||||
{
|
||||
// overwrite output operator << to Print out Surface objects
|
||||
// using the PrintOn function defined below
|
||||
// s.PrintOn( os );
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
G4double G4Surface::HowNear( const G4Vector3D& x ) const
|
||||
{
|
||||
// Distance from the point x to a Surface.
|
||||
// The default for a Surface is the distance from the point to the origin.
|
||||
G4Vector3D p = x - origin;
|
||||
return p.mag();
|
||||
}
|
||||
|
||||
/*
|
||||
G4double G4Surface::distanceAlongRay( int which_way, const G4Ray* ry,
|
||||
G4ThreeVec& p ) const
|
||||
{ // Distance along a Ray (straight line with G4ThreeVec) to leave or enter
|
||||
// a Surface. The input variable which_way should be set to +1 to indicate
|
||||
// leaving a Surface, -1 to indicate entering a Surface.
|
||||
// p is the point of intersection of the Ray with the Surface.
|
||||
// This is a default function which just gives the distance
|
||||
// between the origin of the Ray and the origin of the Surface.
|
||||
// Since a generic Surface doesn't have a well-defined Normal, no
|
||||
// further checks are Done.
|
||||
// This should always be overwritten for derived classes so Print out
|
||||
// a warning message if this is called.
|
||||
G4cout << "WARNING from Surface::distanceAlongRay\n"
|
||||
<< " This function should be overwritten by a derived class.\n"
|
||||
<< " Using the Surface base class default.\n";
|
||||
p = GetOrigin();
|
||||
G4ThreeVec d = ry->Position() - p;
|
||||
return d.Magnitude();
|
||||
}
|
||||
|
||||
G4double G4Surface::distanceAlongHelix( int which_way, const Helix* hx,
|
||||
G4ThreeVec& p ) const
|
||||
{ // Distance along a Helix to leave or enter a Surface.
|
||||
// The input variable which_way should be set to +1 to indicate
|
||||
// leaving a Surface, -1 to indicate entering a Surface.
|
||||
// p is the point of intersection of the Helix with the Surface.
|
||||
// This is a default function which just gives the distance
|
||||
// between the origin of the Helix and the origin of the Surface.
|
||||
// Since a generic Surface doesn't have a well-defined Normal, no
|
||||
// further checks are Done.
|
||||
// This should always be overwritten for derived classes so Print out
|
||||
// a warning message if this is called.
|
||||
G4cout << "WARNING from Surface::distanceAlongHelix\n"
|
||||
<< " This function should be overwritten by a derived class.\n"
|
||||
<< " Using the Surface base class default.\n";
|
||||
p = GetOrigin();
|
||||
G4ThreeVec d = hx->position() - p;
|
||||
return d.Magnitude();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
G4ThreeVec G4Surface::Normal() const
|
||||
{ // return the Normal unit vector to a Surface
|
||||
// (This is only meaningful for Surfaces for which the Normal does
|
||||
// not depend on location on the Surface).
|
||||
// The default is not well defined, so return ( 0, 0, 0 ).
|
||||
return G4ThreeVec( 0.0, 0.0, 0.0 );
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
G4ThreeVec G4Surface::Normal( const G4ThreeVec& ) const
|
||||
{ // return the Normal unit vector to a Surface at the point p on
|
||||
// (or nearly on) the Surface.
|
||||
// The default is not well defined, so return ( 0, 0, 0 ).
|
||||
return G4ThreeVec( 0.0, 0.0, 0.0 );
|
||||
}
|
||||
|
||||
int G4Surface::Inside( const G4ThreeVec& ) const
|
||||
{ // return 0 if point p is outside Surface, 1 if Inside
|
||||
// default is not well defined, so return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
void G4Surface::move( const G4ThreeVec& p )
|
||||
{ // translate origin of Surface by vector p
|
||||
origin += p;
|
||||
}
|
||||
|
||||
void G4Surface::rotate( G4double alpha, G4double beta,
|
||||
G4double gamma, G4ThreeMat& m, int inverse )
|
||||
{ // rotate Surface first about global x-axis by angle alpha,
|
||||
// second about global y-axis by angle beta,
|
||||
// and third about global z-axis by angle gamma
|
||||
// by creating and using G4ThreeMat objects
|
||||
// angles are assumed to be given in radians
|
||||
// returns also the overall rotation matrix for use by subclasses
|
||||
// if inverse is non-zero, the order of rotations is reversed
|
||||
// for a generic Surface, only the origin is rotated
|
||||
// G4double ax[3][3] = { 0., 0., 0., 0., 0., 0., 0., 0., 0. };
|
||||
G4double ax[3][3];
|
||||
G4double ay[3][3];
|
||||
G4double az[3][3];
|
||||
// G4double ay[3][3] = { 0., 0., 0., 0., 0., 0., 0., 0., 0. };
|
||||
// G4double az[3][3] = { 0., 0., 0., 0., 0., 0., 0., 0., 0. };
|
||||
ax[0][0] = 1.;
|
||||
ax[1][1] = cos( alpha );
|
||||
ax[2][2] = ax[1][1];
|
||||
ax[2][1] = sin( alpha );
|
||||
ax[1][2] = -ax[2][1];
|
||||
ay[1][1] = 1.;
|
||||
ay[0][0] = cos( beta );
|
||||
ay[2][2] = ay[0][0];
|
||||
ay[0][2] = sin( beta );
|
||||
ay[2][0] = -ay[0][2];
|
||||
az[2][2] = 1.;
|
||||
az[0][0] = cos( gamma );
|
||||
az[1][1] = az[0][0];
|
||||
az[1][0] = sin( gamma );
|
||||
az[0][1] = -az[1][0];
|
||||
G4ThreeMat &Rx = *new G4ThreeMat( ax ); // x-rotation matrix
|
||||
G4ThreeMat &Ry = *new G4ThreeMat( ay ); // y-rotation matrix
|
||||
G4ThreeMat &Rz = *new G4ThreeMat( az ); // z-rotation matrix
|
||||
if ( inverse )
|
||||
m = Rx * ( Ry * Rz );
|
||||
else
|
||||
m = Rz * ( Ry * Rx );
|
||||
origin = m * origin;
|
||||
}
|
||||
|
||||
void G4Surface::rotate( G4double alpha, G4double beta,
|
||||
G4double gamma, int inverse )
|
||||
{ // rotate Surface first about global x-axis by angle alpha,
|
||||
// second about global y-axis by angle beta,
|
||||
// and third about global z-axis by angle gamma
|
||||
// by creating and using G4ThreeMat objects
|
||||
// angles are assumed to be given in radians
|
||||
// if inverse is non-zero, the order of rotations is reversed
|
||||
G4ThreeMat m;
|
||||
// Just call the above function to do this rotation
|
||||
rotate( alpha, beta, gamma, m, inverse );
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
#include "G4SurfaceBoundary.hh"
|
||||
#include "geomdefs.hh"
|
||||
#include "G4CompositeCurve.hh"
|
||||
|
||||
|
||||
G4SurfaceBoundary::G4SurfaceBoundary(){}
|
||||
|
||||
void G4SurfaceBoundary::Init(const G4CurveVector& bounds0)
|
||||
{
|
||||
bounds= bounds0;
|
||||
lastIntersection.Reset();
|
||||
|
||||
const G4BoundingBox3D* b= bounds[0]->BBox();
|
||||
bBox.Init(b->GetBoxMin(), b->GetBoxMax());
|
||||
|
||||
G4int i;
|
||||
for ( i=1; i<bounds.entries(); i++)
|
||||
{
|
||||
b= bounds[i]->BBox();
|
||||
bBox.Extend(b->GetBoxMin());
|
||||
bBox.Extend(b->GetBoxMax());
|
||||
}
|
||||
|
||||
// the points array is probably unused, so the following code is useless
|
||||
G4int cnt= 0;
|
||||
|
||||
G4int entr = bounds.entries();
|
||||
|
||||
for (i=0; i < entr; i++)
|
||||
{
|
||||
G4Curve* c = bounds(i);
|
||||
|
||||
if (c->GetEntityType() == "G4CompositeCurve")
|
||||
{
|
||||
G4CompositeCurve* cc = (G4CompositeCurve*)c;
|
||||
const G4CurveVector& segments = cc->GetSegments();
|
||||
cnt+= segments.entries();
|
||||
}
|
||||
else
|
||||
cnt++;
|
||||
}
|
||||
|
||||
points.reshape(cnt);
|
||||
|
||||
G4int j= 0;
|
||||
|
||||
for (i=0; i<bounds.entries(); i++)
|
||||
{
|
||||
G4Curve* c= bounds(i);
|
||||
if (c->GetEntityType() == "G4CompositeCurve")
|
||||
{
|
||||
G4CompositeCurve* cc = (G4CompositeCurve*)c;
|
||||
const G4CurveVector& segments = cc->GetSegments();
|
||||
|
||||
for (G4int i=0; i<segments.entries(); i++)
|
||||
{
|
||||
G4Curve* ccc = segments(i);
|
||||
G4Point3D p = ccc->GetEnd();
|
||||
points[j]= p;
|
||||
j++;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
G4Point3D p= c->GetEnd();
|
||||
points[j]= p;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
G4SurfaceBoundary::~G4SurfaceBoundary() {}
|
||||
|
||||
|
||||
G4SurfaceBoundary* G4SurfaceBoundary::Project(const G4Transform3D& tr)
|
||||
{
|
||||
G4CurveVector newBounds;
|
||||
|
||||
for (G4int i=0; i<bounds.entries(); i++)
|
||||
{
|
||||
G4Curve* c= bounds[i]->Project(tr);
|
||||
|
||||
if (c==0)
|
||||
{
|
||||
newBounds.clearAndDestroy();
|
||||
return 0;
|
||||
}
|
||||
// L. Broglia
|
||||
c->SetSameSense( bounds[i]->GetSameSense() );
|
||||
|
||||
newBounds.insert(c);
|
||||
}
|
||||
|
||||
G4SurfaceBoundary* lof= new G4SurfaceBoundary;
|
||||
lof->Init(newBounds);
|
||||
return lof;
|
||||
}
|
||||
|
||||
|
||||
void G4SurfaceBoundary::IntersectRay2D(const G4Ray& ray,
|
||||
G4CurveRayIntersection& is)
|
||||
{
|
||||
is.Reset();
|
||||
G4int entr = bounds.entries();
|
||||
for (G4int i=0; i < entr; i++)
|
||||
{
|
||||
G4Curve& c = *bounds.at(i);
|
||||
G4CurveRayIntersection isTmp(c, ray);
|
||||
c.IntersectRay2D(ray, isTmp);
|
||||
|
||||
if (fabs(isTmp.GetDistance()) < fabs(is.GetDistance()))
|
||||
is= isTmp;
|
||||
}
|
||||
|
||||
lastIntersection= is;
|
||||
}
|
||||
|
||||
|
||||
G4bool G4SurfaceBoundary::Tangent(G4CurvePoint& cp, G4Vector3D& v)
|
||||
{
|
||||
if (lastIntersection.GetDistance() == kInfinity)
|
||||
return false;
|
||||
|
||||
return lastIntersection.GetCurve().Tangent(lastIntersection, v);
|
||||
// should be true
|
||||
|
||||
// cp is ignored for the moment
|
||||
}
|
||||
|
||||
|
||||
void G4SurfaceBoundary::SplitWithPlane(const G4Point3D& p0,
|
||||
const G4Vector3D& n,
|
||||
G4SurfaceBoundary*& new1,
|
||||
G4SurfaceBoundary*& new2)
|
||||
{
|
||||
G4Exception("To be implemented");
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4SurfaceList.cc,v 2.2 1998/10/20 16:34:01 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4SurfaceList.hh"
|
||||
|
||||
G4SurfaceList::G4SurfaceList()
|
||||
{
|
||||
first = index = last = (G4Surface*)0;
|
||||
number_of_elements=0;
|
||||
}
|
||||
|
||||
|
||||
G4SurfaceList::~G4SurfaceList() { EmptyList(); }
|
||||
|
||||
void G4SurfaceList::MoveToFirst(G4Surface* srf)
|
||||
{
|
||||
if(number_of_elements)
|
||||
{
|
||||
RemovePointer();
|
||||
srf->next = first;
|
||||
first = srf;
|
||||
index=first;
|
||||
number_of_elements++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void G4SurfaceList::AddSurface(G4Surface* srf)
|
||||
{
|
||||
if(first == (G4Surface*)0)
|
||||
{
|
||||
index = srf;
|
||||
first = srf;
|
||||
last = srf;
|
||||
first->next = (G4Surface*)0;
|
||||
}
|
||||
else
|
||||
{
|
||||
srf->next = last->next;
|
||||
last->next = srf;
|
||||
last = last->next;
|
||||
}
|
||||
|
||||
number_of_elements++;
|
||||
index=first;
|
||||
}
|
||||
|
||||
|
||||
G4Surface* G4SurfaceList::GetSurface()
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
G4Surface* G4SurfaceList::GetSurface(int number)
|
||||
{
|
||||
index = first;
|
||||
for(int a=0;a<number;a++)
|
||||
Step();
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
G4Surface* G4SurfaceList::GetLastSurface()
|
||||
{
|
||||
return last;
|
||||
}
|
||||
|
||||
|
||||
void G4SurfaceList::RemoveSurface(G4Surface* srf)
|
||||
{
|
||||
if(srf!=(G4Surface*)0)
|
||||
{
|
||||
number_of_elements--;
|
||||
temp = first;
|
||||
|
||||
if(srf == first)
|
||||
{
|
||||
first=first->next;
|
||||
index = first;
|
||||
if(number_of_elements == 0)last = first;
|
||||
delete srf;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(temp->next != srf) temp = temp->next;
|
||||
index = srf->next;
|
||||
temp->next = index;
|
||||
if(srf == last) last = temp;
|
||||
index = first;
|
||||
delete srf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void G4SurfaceList::RemovePointer()
|
||||
{
|
||||
// Remove the current pointer from the List
|
||||
// Do not delete the object itself
|
||||
if(number_of_elements)
|
||||
if(first != index)
|
||||
{
|
||||
temp = first;
|
||||
|
||||
// Find previous
|
||||
while(temp->next != index) temp = temp->next;
|
||||
|
||||
// Hop over the one to be removed
|
||||
temp->next = index->next;
|
||||
|
||||
// Correct the index pointer
|
||||
index = temp->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hop over the first
|
||||
first = first->next;
|
||||
index = first;
|
||||
}
|
||||
|
||||
number_of_elements--;
|
||||
}
|
||||
|
||||
|
||||
void G4SurfaceList::EmptyList()
|
||||
{
|
||||
//Deletes all surfaces in List
|
||||
while (first != (G4Surface*)0)
|
||||
{
|
||||
temp = first;
|
||||
first = first->next;
|
||||
delete temp;
|
||||
number_of_elements--;
|
||||
}
|
||||
|
||||
last = index = first;
|
||||
}
|
||||
|
||||
|
||||
void G4SurfaceList::MoveToFirst()
|
||||
{
|
||||
index = first;
|
||||
}
|
||||
|
||||
|
||||
void G4SurfaceList::Step()
|
||||
{
|
||||
if(index!=(G4Surface*)0)
|
||||
index = index->next;
|
||||
}
|
||||
|
||||
|
||||
void G4SurfaceList::G4SortList()
|
||||
{
|
||||
if(number_of_elements == 1) return;
|
||||
|
||||
// First create a vector of the surface distances
|
||||
// to the ray origin
|
||||
G4Surface** distances = new G4Surface*[number_of_elements];
|
||||
int x = 0;
|
||||
MoveToFirst();
|
||||
|
||||
// Copy surface pointers to vector
|
||||
if(number_of_elements > 1)
|
||||
{
|
||||
while(x < number_of_elements)
|
||||
{
|
||||
distances[x] = index;
|
||||
index = index->next;
|
||||
x++;
|
||||
}
|
||||
|
||||
MoveToFirst();
|
||||
|
||||
// Sort List of pointers using quick G4Sort
|
||||
QuickG4Sort( distances, 0, number_of_elements-1 );
|
||||
|
||||
// Organize the linked List of surfaces according
|
||||
// to the quickG4Sorted List.
|
||||
x = 0;
|
||||
first = distances[x];
|
||||
last = first;
|
||||
x++;
|
||||
|
||||
while (x < number_of_elements)
|
||||
{
|
||||
last->next = distances[x];
|
||||
last = last ->next;
|
||||
x++;
|
||||
}
|
||||
|
||||
last->next = (G4Surface*)0;
|
||||
MoveToFirst();
|
||||
}
|
||||
|
||||
delete[] distances;
|
||||
}
|
||||
|
||||
|
||||
void G4SurfaceList::QuickG4Sort(G4Surface** Dist, int left, int right)
|
||||
{
|
||||
register int i=left;
|
||||
register int j=right;
|
||||
|
||||
G4Surface* elem1;
|
||||
G4Surface* elem2 = Dist[(left+right)/2];
|
||||
|
||||
do
|
||||
{
|
||||
while ( (Dist[i]->Distance() < elem2->Distance()) && (i < right) )
|
||||
i++;
|
||||
|
||||
while ( (elem2->Distance() < Dist[j]->Distance()) && (j > left))
|
||||
j--;
|
||||
|
||||
if(i<=j)
|
||||
{
|
||||
elem1 = Dist[i];
|
||||
Dist[i] = Dist[j];
|
||||
Dist[j] = elem1;
|
||||
i++;
|
||||
j--;
|
||||
}
|
||||
} while (i<=j);
|
||||
|
||||
if( left < j )
|
||||
QuickG4Sort(Dist, left, j );
|
||||
|
||||
if( i < right )
|
||||
QuickG4Sort(Dist, i, right);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
#include "G4SurfaceOfLinearExtrusion.hh"
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
#include "G4SurfaceOfRevolution.hh"
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4ThreeMat.cc,v 2.2 1998/10/20 16:34:01 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
/* G4ThreeMat.cc,v 1.5 1993/08/02 22:21:27 atwood Exp */
|
||||
// File: G4ThreeMat.cc
|
||||
// Author: Alan Breakstone
|
||||
|
||||
// Contents -------------------------------------------------------------
|
||||
//
|
||||
// G4ThreeMat::G4ThreeMat()
|
||||
// G4ThreeMat::G4ThreeMat( G4double a[3][3] )
|
||||
// operator<<( ostream&, const G4ThreeMat& m );
|
||||
// G4ThreeMat::PrintOn( ostream& os ) const
|
||||
// operator==( const G4ThreeMat& m )
|
||||
// G4ThreeMat::operator=( const G4ThreeMat& m )
|
||||
// G4ThreeMat::operator-()
|
||||
// G4ThreeMat::operator+=( const G4ThreeMat& m2 )
|
||||
// G4ThreeMat::operator-=( const G4ThreeMat& m2 )
|
||||
// operator+( const G4ThreeMat& m1, const G4ThreeMat& m2 )
|
||||
// operator-( const G4ThreeMat& m1, const G4ThreeMat& m2 )
|
||||
// operator*( G4double x, const G4ThreeMat& m )
|
||||
// operator*( const G4ThreeMat& m, const G4ThreeVec& v )
|
||||
// operator*( const G4ThreeMat& m1, const G4ThreeMat& m2 )
|
||||
// G4ThreeMat::Determinant()
|
||||
//
|
||||
// End ------------------------------------------------------------------
|
||||
|
||||
#include "G4ThreeMat.hh"
|
||||
|
||||
G4ThreeMat::G4ThreeMat()
|
||||
{
|
||||
// default (null) constructor
|
||||
for ( int i = 0; i < 3 ; i++ )
|
||||
{
|
||||
row[i] = G4Vector3D( 0., 0., 0. );
|
||||
column[i] = G4Vector3D( 0., 0., 0. );
|
||||
|
||||
for ( int j = 0; j < 3 ; j++ )
|
||||
element[i][j] = 0.;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
G4ThreeMat::G4ThreeMat( G4double a[3][3] )
|
||||
{
|
||||
// constructor to make matrix from array
|
||||
for ( int i = 0; i < 3 ; i++ )
|
||||
{
|
||||
row[i] = G4Vector3D( a[i][0], a[i][1], a[i][2] );
|
||||
column[i] = G4Vector3D( a[0][i], a[1][i], a[2][i] );
|
||||
|
||||
for ( int j = 0; j < 3 ; j++ )
|
||||
element[i][j] = a[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
G4ThreeMat::G4ThreeMat( const G4ThreeMat& m )
|
||||
{
|
||||
// copy constructor
|
||||
for ( int i = 0; i < 3 ; i++ )
|
||||
{
|
||||
row[i] = m.row[i];
|
||||
column[i] = m.column[i];
|
||||
|
||||
for ( int j = 0; j < 3 ; j++ )
|
||||
element[i][j] = m.element[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ostream& operator<<( ostream& os, const G4ThreeMat& m )
|
||||
{
|
||||
// overwrite output operator << to Print out G4ThreeMat objects
|
||||
// using the PrintOn function defined below
|
||||
m.PrintOn( os );
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
void G4ThreeMat::PrintOn( ostream& os ) const
|
||||
{
|
||||
// printing function using C++ ostream class
|
||||
os << "[ " << element[0][0] << "\t"
|
||||
<< element[0][1] << "\t"
|
||||
<< element[0][2] << "\n "
|
||||
<< element[1][0] << "\t"
|
||||
<< element[1][1] << "\t"
|
||||
<< element[1][2] << "\n "
|
||||
<< element[2][0] << "\t"
|
||||
<< element[2][1] << "\t"
|
||||
<< element[2][2] << " ]\n";
|
||||
/*
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
os << "row [" << i << "] " << row[i] << "\n"
|
||||
<< "column[" << i << "] " << column[i] << "\n";
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
int G4ThreeMat::operator==( const G4ThreeMat& m )
|
||||
{
|
||||
for ( int i = 0; i < 3 ; i++ )
|
||||
{
|
||||
for ( int j = 0; j < 3 ; j++ )
|
||||
{
|
||||
if ( element[i][j] != m.element[i][j] )
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void G4ThreeMat::operator=( const G4ThreeMat& m )
|
||||
{
|
||||
// assignment operator
|
||||
for ( int i = 0; i < 3 ; i++ )
|
||||
{
|
||||
row[i] = m.row[i];
|
||||
column[i] = m.column[i];
|
||||
|
||||
for ( int j = 0; j < 3 ; j++ )
|
||||
element[i][j] = m.element[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
G4ThreeMat G4ThreeMat::operator-()
|
||||
{
|
||||
// unary - operator, change Sign of all elements
|
||||
G4double a[3][3];
|
||||
|
||||
for ( int i = 0; i < 3 ; i++ )
|
||||
{
|
||||
for ( int j = 0; j < 3 ; j++ )
|
||||
a[i][j] = -element[i][j];
|
||||
}
|
||||
|
||||
return G4ThreeMat( a );
|
||||
}
|
||||
|
||||
|
||||
G4ThreeMat G4ThreeMat::operator+=( const G4ThreeMat& m2 )
|
||||
{
|
||||
// overload += operator
|
||||
for ( int i = 0; i < 3 ; i++ )
|
||||
{
|
||||
this->row[i] += m2.row[i];
|
||||
this->column[i] += m2.column[i];
|
||||
|
||||
for ( int j = 0; j < 3 ; j++ )
|
||||
this->element[i][j] += m2.element[i][j];
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
G4ThreeMat G4ThreeMat::operator-=( const G4ThreeMat& m2 )
|
||||
{
|
||||
// overload -= operator
|
||||
for ( int i = 0; i < 3 ; i++ )
|
||||
{
|
||||
this->row[i] -= m2.row[i];
|
||||
this->column[i] -= m2.column[i];
|
||||
|
||||
for ( int j = 0; j < 3 ; j++ )
|
||||
this->element[i][j] -= m2.element[i][j];
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
G4ThreeMat operator+( const G4ThreeMat& m1, const G4ThreeMat& m2 )
|
||||
{
|
||||
// overload binary + operator
|
||||
G4double a[3][3];
|
||||
|
||||
for ( int i = 0; i < 3 ; i++ )
|
||||
{
|
||||
for ( int j = 0; j < 3 ; j++ )
|
||||
a[i][j] = m1.element[i][j] + m2.element[i][j];
|
||||
|
||||
}
|
||||
|
||||
return G4ThreeMat( a );
|
||||
}
|
||||
|
||||
|
||||
G4ThreeMat operator-( const G4ThreeMat& m1, const G4ThreeMat& m2 )
|
||||
{
|
||||
// overload binary - operator
|
||||
G4double a[3][3];
|
||||
|
||||
for ( int i = 0; i < 3 ; i++ )
|
||||
{
|
||||
for ( int j = 0; j < 3 ; j++ )
|
||||
a[i][j] = m1.element[i][j] - m2.element[i][j];
|
||||
}
|
||||
|
||||
return G4ThreeMat( a );
|
||||
}
|
||||
|
||||
|
||||
G4ThreeMat operator*( G4double x, const G4ThreeMat& m )
|
||||
{
|
||||
// overload binary * operator for constant Times matrix
|
||||
G4double a[3][3];
|
||||
for ( int i = 0; i < 3 ; i++ ){
|
||||
for ( int j = 0; j < 3 ; j++ ) {
|
||||
a[i][j] = x * m.element[i][j];
|
||||
}
|
||||
}
|
||||
return G4ThreeMat( a );
|
||||
}
|
||||
|
||||
|
||||
G4Vector3D operator*( const G4ThreeMat& m, const G4Vector3D& v )
|
||||
{
|
||||
// overload binary * operator for matrix Times vector
|
||||
G4double a[3];
|
||||
for ( int i = 0; i < 3 ; i++ ){
|
||||
a[i] = m.row[i] * v;
|
||||
}
|
||||
return G4Vector3D( a[0], a[1], a[2] );
|
||||
}
|
||||
|
||||
|
||||
G4ThreeMat operator*( const G4ThreeMat& m1, const G4ThreeMat& m2 )
|
||||
{
|
||||
// overload binary * operator for matrix Times matrix
|
||||
G4double a[3][3];
|
||||
for ( int i = 0; i < 3 ; i++ ){
|
||||
for ( int j = 0; j < 3 ; j++ ) {
|
||||
a[i][j] = m1.row[i] * m2.column[j];
|
||||
}
|
||||
}
|
||||
return G4ThreeMat( a );
|
||||
}
|
||||
|
||||
|
||||
G4double G4ThreeMat::Determinant()
|
||||
{
|
||||
// Determinant of a three by three matrix
|
||||
return element[0][0] * ( element[1][1] * element[2][2]
|
||||
- element[2][1] * element[1][2] )
|
||||
- element[0][1] * ( element[1][0] * element[2][2]
|
||||
- element[2][0] * element[1][2] )
|
||||
+ element[0][2] * ( element[1][0] * element[2][1]
|
||||
- element[2][0] * element[1][1] );
|
||||
}
|
||||
@@ -0,0 +1,445 @@
|
||||
// This code implementation is the intellectual property of
|
||||
// the RD44 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: G4ToroidalSurface.cc,v 2.7 1998/10/29 17:49:41 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
//
|
||||
#include "G4ToroidalSurface.hh"
|
||||
|
||||
|
||||
|
||||
|
||||
G4ToroidalSurface::G4ToroidalSurface(): EQN_EPS(1e-9){}
|
||||
|
||||
G4ToroidalSurface::G4ToroidalSurface(const G4Vector3D& Location,
|
||||
const G4Vector3D& Ax,
|
||||
const G4Vector3D& Dir,
|
||||
const G4double MinRad,
|
||||
const G4double MaxRad): EQN_EPS(1e-9)
|
||||
{
|
||||
Placement.Init(Dir, Ax, Location);
|
||||
|
||||
MinRadius = MinRad;
|
||||
MaxRadius = MaxRad;
|
||||
TransMatrix= new Matrix(4,4);
|
||||
}
|
||||
|
||||
|
||||
G4ToroidalSurface::~G4ToroidalSurface(){}
|
||||
|
||||
|
||||
void G4ToroidalSurface::CalcBBox()
|
||||
{
|
||||
// L. Broglia
|
||||
// G4Point3D Origin = Placement.GetSrfPoint();
|
||||
G4Point3D Origin = Placement.GetLocation();
|
||||
|
||||
G4Point3D Min(Origin.x()-MaxRadius,
|
||||
Origin.y()-MaxRadius,
|
||||
Origin.z()-MaxRadius);
|
||||
G4Point3D Max(Origin.x()+MaxRadius,
|
||||
Origin.y()+MaxRadius,
|
||||
Origin.z()+MaxRadius);
|
||||
|
||||
bbox = new G4BoundingBox3D(Min,Max);
|
||||
}
|
||||
|
||||
|
||||
G4double G4ToroidalSurface::ClosestDistanceToPoint(const G4Point3D &Pt)
|
||||
{
|
||||
// L. Broglia
|
||||
// G4Point3D Origin = Placement.GetSrfPoint();
|
||||
G4Point3D Origin = Placement.GetLocation();
|
||||
|
||||
G4double Dist = Pt.distance(Origin);
|
||||
|
||||
return ((Dist - MaxRadius)*(Dist - MaxRadius));
|
||||
}
|
||||
|
||||
|
||||
int G4ToroidalSurface::Intersect(const G4Ray& Ray)
|
||||
{
|
||||
// ---- inttor - Intersect a ray with a torus. ------------------------
|
||||
// from GraphicsGems II by
|
||||
|
||||
// Description:
|
||||
// Inttor determines the intersection of a ray with a torus.
|
||||
//
|
||||
// On entry:
|
||||
// raybase = The coordinate defining the base of the
|
||||
// intersecting ray.
|
||||
// raycos = The G4Vector3D cosines of the above ray.
|
||||
// center = The center location of the torus.
|
||||
// radius = The major radius of the torus.
|
||||
// rplane = The minor radius in the G4Plane of the torus.
|
||||
// rnorm = The minor radius Normal to the G4Plane of the torus.
|
||||
// tran = A 4x4 transformation matrix that will position
|
||||
// the torus at the origin and orient it such that
|
||||
// the G4Plane of the torus lyes in the x-z G4Plane.
|
||||
//
|
||||
// On return:
|
||||
// nhits = The number of intersections the ray makes with
|
||||
// the torus.
|
||||
// rhits = The entering/leaving distances of the
|
||||
// intersections.
|
||||
//
|
||||
// Returns: True if the ray intersects the torus.
|
||||
//
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// Variables. Should be optimized later...
|
||||
G4Point3D Base = Ray.GetStart(); // Base of the intersection ray
|
||||
G4Vector3D DCos = Ray.GetDir(); // Direction cosines of the ray
|
||||
int nhits=0; // Number of intersections
|
||||
G4double rhits[4]; // Intersection distances
|
||||
G4double hits[4]; // Ordered intersection distances
|
||||
G4double rho, a0, b0; // Related constants
|
||||
G4double f, l, t, g, q, m, u; // Ray dependent terms
|
||||
G4double C[5]; // Quartic coefficients
|
||||
|
||||
// Transform the intersection ray
|
||||
|
||||
|
||||
// MultiplyPointByMatrix (Base); // Matriisi puuttuu viela!
|
||||
// MultiplyVectorByMatrix (DCos);
|
||||
|
||||
// Compute constants related to the torus.
|
||||
G4double rnorm = MaxRadius - MinRadius; // ei tietoa onko oikein...
|
||||
rho = MinRadius*MinRadius / (rnorm*rnorm);
|
||||
a0 = 4. * MaxRadius*MaxRadius;
|
||||
b0 = MaxRadius*MaxRadius - MinRadius*MinRadius;
|
||||
|
||||
// Compute ray dependent terms.
|
||||
f = 1. - DCos.y()*DCos.y();
|
||||
l = 2. * (Base.x()*DCos.x() + Base.z()*DCos.z());
|
||||
t = Base.x()*Base.x() + Base.z()*Base.z();
|
||||
g = f + rho * DCos.y()*DCos.y();
|
||||
q = a0 / (g*g);
|
||||
m = (l + 2.*rho*DCos.y()*Base.y()) / g;
|
||||
u = (t + rho*Base.y()*Base.y() + b0) / g;
|
||||
|
||||
// Compute the coefficients of the quartic.
|
||||
|
||||
C[4] = 1.0;
|
||||
C[3] = 2. * m;
|
||||
C[2] = m*m + 2.*u - q*f;
|
||||
C[1] = 2.*m*u - q*l;
|
||||
C[0] = u*u - q*t;
|
||||
|
||||
// Use quartic root solver found in "Graphics Gems" by Jochen Schwarze.
|
||||
nhits = SolveQuartic (C,rhits);
|
||||
|
||||
// SolveQuartic returns root pairs in reversed order.
|
||||
m = rhits[0]; u = rhits[1]; rhits[0] = u; rhits[1] = m;
|
||||
m = rhits[2]; u = rhits[3]; rhits[2] = u; rhits[3] = m;
|
||||
|
||||
// return (*nhits != 0);
|
||||
|
||||
if(nhits != 0)
|
||||
{
|
||||
// Convert Hit distances to intersection points
|
||||
/*
|
||||
G4Point3D** IntersectionPoints = new G4Point3D*[nhits];
|
||||
for(int a=0;a<nhits;a++)
|
||||
{
|
||||
G4double Dist = rhits[a];
|
||||
IntersectionPoints[a] = new G4Point3D((Base - Dist * DCos));
|
||||
}
|
||||
// Check wether any of the hits are on the actual surface
|
||||
// Start with checking for the intersections that are Inside the bbox
|
||||
|
||||
G4Point3D* Hit;
|
||||
int InsideBox[2]; // Max 2 intersections on the surface
|
||||
int Counter=0;
|
||||
*/
|
||||
|
||||
G4Point3D BoxMin = bbox->GetBoxMin();
|
||||
G4Point3D BoxMax = bbox->GetBoxMax();
|
||||
G4Point3D Hit;
|
||||
int c1 = 0;
|
||||
int c2;
|
||||
G4double tempVec[4];
|
||||
|
||||
for(int a=0;a<nhits;a++)
|
||||
{
|
||||
while ( (c1 < 4) && (hits[c1] <= rhits[a]) )
|
||||
{
|
||||
tempVec[c1]=hits[c1];
|
||||
c1++;
|
||||
}
|
||||
|
||||
for(c2=c1+1;c2<4;c2++)
|
||||
tempVec[c2]=hits[c2-1];
|
||||
|
||||
if(c1<4)
|
||||
{
|
||||
tempVec[c1]=rhits[a];
|
||||
|
||||
for(c2=0;c2<4;c2++)
|
||||
hits[c2]=tempVec[c2];
|
||||
}
|
||||
}
|
||||
|
||||
for(int b=0;b<nhits;b++)
|
||||
{
|
||||
// Hit = IntersectionPoints[b];
|
||||
if(hits[b] >=kCarTolerance*0.5)
|
||||
{
|
||||
Hit = Base + (hits[b]*DCos);
|
||||
// InsideBox[Counter]=b;
|
||||
if( (Hit.x() > BoxMin.x()) &&
|
||||
(Hit.x() < BoxMax.x()) &&
|
||||
(Hit.y() > BoxMin.y()) &&
|
||||
(Hit.y() < BoxMax.y()) &&
|
||||
(Hit.z() > BoxMin.z()) &&
|
||||
(Hit.z() < BoxMax.z()) )
|
||||
{
|
||||
closest_hit = Hit;
|
||||
distance = hits[b]*hits[b];
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Counter++;
|
||||
}
|
||||
}
|
||||
|
||||
// If two Inside bbox, find closest
|
||||
int Closest=0;
|
||||
|
||||
// if(Counter>1)
|
||||
// if(rhits[InsideBox[0]] > rhits[InsideBox[1]])
|
||||
// Closest=1;
|
||||
|
||||
// Project polygon and do point in polygon
|
||||
// Projection also for curves etc.
|
||||
// Should probably be implemented in the curve class.
|
||||
G4Plane Plane1 = Ray.GetPlane(1);
|
||||
G4Plane Plane2 = Ray.GetPlane(2);
|
||||
|
||||
// Point in polygon
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int G4ToroidalSurface::SolveQuartic(G4double c[], G4double s[] )
|
||||
{
|
||||
// From Graphics Gems I by Jochen Schwartz
|
||||
|
||||
G4double coeffs[ 4 ];
|
||||
G4double z, u, v, sub;
|
||||
G4double A, B, C, D;
|
||||
G4double sq_A, p, q, r;
|
||||
int i, num;
|
||||
|
||||
// Normal form: x^4 + Ax^3 + Bx^2 + Cx + D = 0
|
||||
|
||||
A = c[ 3 ] / c[ 4 ];
|
||||
B = c[ 2 ] / c[ 4 ];
|
||||
C = c[ 1 ] / c[ 4 ];
|
||||
D = c[ 0 ] / c[ 4 ];
|
||||
|
||||
// substitute x = y - A/4 to eliminate cubic term:
|
||||
// x^4 + px^2 + qx + r = 0
|
||||
|
||||
sq_A = A * A;
|
||||
p = - 3.0/8 * sq_A + B;
|
||||
q = 1.0/8 * sq_A * A - 1.0/2 * A * B + C;
|
||||
r = - 3.0/256*sq_A*sq_A + 1.0/16*sq_A*B - 1.0/4*A*C + D;
|
||||
|
||||
if (IsZero(r))
|
||||
{
|
||||
// no absolute term: y(y^3 + py + q) = 0
|
||||
|
||||
coeffs[ 0 ] = q;
|
||||
coeffs[ 1 ] = p;
|
||||
coeffs[ 2 ] = 0;
|
||||
coeffs[ 3 ] = 1;
|
||||
|
||||
num = SolveCubic(coeffs, s);
|
||||
|
||||
s[ num++ ] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// solve the resolvent cubic ...
|
||||
coeffs[ 0 ] = 1.0/2 * r * p - 1.0/8 * q * q;
|
||||
coeffs[ 1 ] = - r;
|
||||
coeffs[ 2 ] = - 1.0/2 * p;
|
||||
coeffs[ 3 ] = 1;
|
||||
|
||||
(void) SolveCubic(coeffs, s);
|
||||
|
||||
// ... and take the one real solution ...
|
||||
z = s[ 0 ];
|
||||
|
||||
// ... to Build two quadric equations
|
||||
u = z * z - r;
|
||||
v = 2 * z - p;
|
||||
|
||||
if (IsZero(u))
|
||||
u = 0;
|
||||
else if (u > 0)
|
||||
u = sqrt(u);
|
||||
else
|
||||
return 0;
|
||||
|
||||
if (IsZero(v))
|
||||
v = 0;
|
||||
else if (v > 0)
|
||||
v = sqrt(v);
|
||||
else
|
||||
return 0;
|
||||
|
||||
coeffs[ 0 ] = z - u;
|
||||
coeffs[ 1 ] = q < 0 ? -v : v;
|
||||
coeffs[ 2 ] = 1;
|
||||
|
||||
num = SolveQuadric(coeffs, s);
|
||||
|
||||
coeffs[ 0 ]= z + u;
|
||||
coeffs[ 1 ] = q < 0 ? v : -v;
|
||||
coeffs[ 2 ] = 1;
|
||||
|
||||
num += SolveQuadric(coeffs, s + num);
|
||||
}
|
||||
|
||||
// resubstitute
|
||||
|
||||
sub = 1.0/4 * A;
|
||||
|
||||
for (i = 0; i < num; ++i)
|
||||
s[ i ] -= sub;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
int G4ToroidalSurface::SolveCubic(G4double c[], G4double s[] )
|
||||
{
|
||||
// From Graphics Gems I bu Jochen Schwartz
|
||||
int i, num;
|
||||
G4double sub;
|
||||
G4double A, B, C;
|
||||
G4double sq_A, p, q;
|
||||
G4double cb_p, D;
|
||||
|
||||
// Normal form: x^3 + Ax^2 + Bx + C = 0
|
||||
A = c[ 2 ] / c[ 3 ];
|
||||
B = c[ 1 ] / c[ 3 ];
|
||||
C = c[ 0 ] / c[ 3 ];
|
||||
|
||||
// substitute x = y - A/3 to eliminate quadric term:
|
||||
// x^3 +px + q = 0
|
||||
sq_A = A * A;
|
||||
p = 1.0/3 * (- 1.0/3 * sq_A + B);
|
||||
q = 1.0/2 * (2.0/27 * A * sq_A - 1.0/3 * A * B + C);
|
||||
|
||||
// use Cardano's formula
|
||||
cb_p = p * p * p;
|
||||
D = q * q + cb_p;
|
||||
|
||||
if (IsZero(D))
|
||||
{
|
||||
if (IsZero(q)) // one triple solution
|
||||
{
|
||||
s[ 0 ] = 0;
|
||||
num = 1;
|
||||
}
|
||||
else // one single and one G4double solution
|
||||
{
|
||||
G4double u = cbrt(-q);
|
||||
s[ 0 ] = 2 * u;
|
||||
s[ 1 ] = - u;
|
||||
num = 2;
|
||||
}
|
||||
}
|
||||
else if (D < 0) // Casus irreducibilis: three real solutions
|
||||
{
|
||||
G4double phi = 1.0/3 * acos(-q / sqrt(-cb_p));
|
||||
G4double t = 2 * sqrt(-p);
|
||||
|
||||
s[ 0 ] = t * cos(phi);
|
||||
s[ 1 ] = - t * cos(phi + M_PI / 3);
|
||||
s[ 2 ] = - t * cos(phi - M_PI / 3);
|
||||
num = 3;
|
||||
}
|
||||
else // one real solution
|
||||
{
|
||||
G4double sqrt_D = sqrt(D);
|
||||
G4double u = cbrt(sqrt_D - q);
|
||||
G4double v = - cbrt(sqrt_D + q);
|
||||
|
||||
s[ 0 ] = u + v;
|
||||
num = 1;
|
||||
}
|
||||
|
||||
// resubstitute
|
||||
sub = 1.0/3 * A;
|
||||
|
||||
for (i = 0; i < num; ++i)
|
||||
s[ i ] -= sub;
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
int G4ToroidalSurface::SolveQuadric(G4double c[], G4double s[] )
|
||||
{
|
||||
// From Graphics Gems I by Jochen Schwartz
|
||||
G4double p, q, D;
|
||||
|
||||
// Normal form: x^2 + px + q = 0
|
||||
p = c[ 1 ] / (2 * c[ 2 ]);
|
||||
q = c[ 0 ] / c[ 2 ];
|
||||
|
||||
D = p * p - q;
|
||||
|
||||
if (IsZero(D))
|
||||
{
|
||||
s[ 0 ] = - p;
|
||||
return 1;
|
||||
}
|
||||
else if (D < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (D > 0)
|
||||
{
|
||||
G4double sqrt_D = sqrt(D);
|
||||
|
||||
s[ 0 ] = sqrt_D - p;
|
||||
s[ 1 ] = - sqrt_D - p;
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user