Import Geant4 0.1.0 source tree
This commit is contained in:
@@ -1,4 +1,15 @@
|
||||
// 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: G4BREPSolid.cc,v 1.8 1999/06/10 09:49:30 sgiani Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
|
||||
#include "G4BREPSolid.hh"
|
||||
#include "G4VoxelLimits.hh"
|
||||
#include "G4AffineTransform.hh"
|
||||
#include "G4VGraphicsScene.hh"
|
||||
#include "G4Polyhedron.hh"
|
||||
@@ -10,7 +21,7 @@
|
||||
#include "G4SphericalSurface.hh"
|
||||
|
||||
G4Ray G4BREPSolid::Track;
|
||||
G4double G4BREPSolid::ShortestDistance=1000000;
|
||||
G4double G4BREPSolid::ShortestDistance= kInfinity;
|
||||
int G4BREPSolid::NumberOfSolids=0;
|
||||
InstMgr G4BREPSolid::InstanceList;
|
||||
|
||||
@@ -68,7 +79,7 @@ void G4BREPSolid::Initialize()
|
||||
{
|
||||
// Calc bounding box for solids and surfaces
|
||||
// Convert concave planes to convex
|
||||
ShortestDistance=1000000;
|
||||
ShortestDistance= kInfinity;
|
||||
IsBox();
|
||||
CheckSurfaceNormals();
|
||||
|
||||
@@ -489,330 +500,401 @@ G4bool G4BREPSolid::IsConvex()
|
||||
}
|
||||
|
||||
|
||||
G4bool G4BREPSolid::CalculateExtent(const EAxis pAxis,
|
||||
const G4VoxelLimits& pVoxelLimit,
|
||||
const G4AffineTransform& pTransform,
|
||||
G4double& pMin,
|
||||
G4double& pMax ) const
|
||||
G4bool G4BREPSolid::CalculateExtent(const EAxis pAxis,
|
||||
const G4VoxelLimits& pVoxelLimit,
|
||||
const G4AffineTransform& pTransform,
|
||||
G4double& pMin, G4double& pMax) const
|
||||
{
|
||||
G4Point3D Min = bbox->GetBoxMin();
|
||||
G4Point3D Max = bbox->GetBoxMax();
|
||||
|
||||
G4ThreeVector VMin(Min.x(),Min.y(),Min.z());
|
||||
G4ThreeVector VMax(Max.x(),Max.y(),Max.z());
|
||||
|
||||
switch (pAxis)
|
||||
{
|
||||
case kXAxis:
|
||||
pMin=Min.x();
|
||||
pMax=Max.x();
|
||||
break;
|
||||
|
||||
case kYAxis:
|
||||
pMin=Min.y();
|
||||
pMax=Max.y();
|
||||
break;
|
||||
if (!pTransform.IsRotated())
|
||||
{
|
||||
// Special case handling for unrotated boxes
|
||||
// Compute x/y/z mins and maxs respecting limits, with early returns
|
||||
// if outside limits. Then switch() on pAxis
|
||||
G4double xoffset,xMin,xMax;
|
||||
G4double yoffset,yMin,yMax;
|
||||
G4double zoffset,zMin,zMax;
|
||||
|
||||
case kZAxis:
|
||||
pMin=Min.z();
|
||||
pMax=Max.z();
|
||||
break;
|
||||
}
|
||||
|
||||
pMin-=kCarTolerance;
|
||||
pMax+=kCarTolerance;
|
||||
|
||||
return true;
|
||||
xoffset=pTransform.NetTranslation().x();
|
||||
xMin=xoffset+Min.x();
|
||||
xMax=xoffset+Max.x();
|
||||
if (pVoxelLimit.IsXLimited())
|
||||
{
|
||||
if (xMin>pVoxelLimit.GetMaxXExtent()
|
||||
||xMax<pVoxelLimit.GetMinXExtent())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (xMin<pVoxelLimit.GetMinXExtent())
|
||||
{
|
||||
xMin=pVoxelLimit.GetMinXExtent();
|
||||
}
|
||||
if (xMax>pVoxelLimit.GetMaxXExtent())
|
||||
{
|
||||
xMax=pVoxelLimit.GetMaxXExtent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (!pTransform.IsRotated())
|
||||
{
|
||||
// if(pVoxelLimit.Inside(VMin))
|
||||
// if(pVoxelLimit.Inside(VMax))
|
||||
{
|
||||
switch (pAxis)
|
||||
{
|
||||
case kXAxis:
|
||||
pMin=VMin.x();
|
||||
pMax=VMax.x();
|
||||
break;
|
||||
case kYAxis:
|
||||
pMin=VMin.y();
|
||||
pMax=VMax.y();
|
||||
break;
|
||||
case kZAxis:
|
||||
pMin=VMin.z();
|
||||
pMax=VMax.z();
|
||||
break;
|
||||
}
|
||||
|
||||
// pMin-=kCarTolerance;
|
||||
// pMax+=kCarTolerance;
|
||||
return true;
|
||||
}
|
||||
// else
|
||||
{
|
||||
// return false;
|
||||
}
|
||||
}
|
||||
// else
|
||||
{
|
||||
// return false;
|
||||
}
|
||||
yoffset=pTransform.NetTranslation().y();
|
||||
yMin=yoffset+Min.y();
|
||||
yMax=yoffset+Max.y();
|
||||
if (pVoxelLimit.IsYLimited())
|
||||
{
|
||||
if (yMin>pVoxelLimit.GetMaxYExtent()
|
||||
||yMax<pVoxelLimit.GetMinYExtent())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (yMin<pVoxelLimit.GetMinYExtent())
|
||||
{
|
||||
yMin=pVoxelLimit.GetMinYExtent();
|
||||
}
|
||||
if (yMax>pVoxelLimit.GetMaxYExtent())
|
||||
{
|
||||
yMax=pVoxelLimit.GetMaxYExtent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;*/
|
||||
|
||||
zoffset=pTransform.NetTranslation().z();
|
||||
zMin=zoffset+Min.z();
|
||||
zMax=zoffset+Max.z();
|
||||
if (pVoxelLimit.IsZLimited())
|
||||
{
|
||||
if (zMin>pVoxelLimit.GetMaxZExtent()
|
||||
||zMax<pVoxelLimit.GetMinZExtent())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (zMin<pVoxelLimit.GetMinZExtent())
|
||||
{
|
||||
zMin=pVoxelLimit.GetMinZExtent();
|
||||
}
|
||||
if (zMax>pVoxelLimit.GetMaxZExtent())
|
||||
{
|
||||
zMax=pVoxelLimit.GetMaxZExtent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch (pAxis)
|
||||
{
|
||||
case kXAxis:
|
||||
pMin=xMin;
|
||||
pMax=xMax;
|
||||
break;
|
||||
case kYAxis:
|
||||
pMin=yMin;
|
||||
pMax=yMax;
|
||||
break;
|
||||
case kZAxis:
|
||||
pMin=zMin;
|
||||
pMax=zMax;
|
||||
break;
|
||||
}
|
||||
|
||||
pMin-=kCarTolerance;
|
||||
pMax+=kCarTolerance;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// General rotated case - create and clip mesh to boundaries
|
||||
|
||||
G4bool existsAfterClip=false;
|
||||
G4ThreeVectorList *vertices;
|
||||
|
||||
pMin=+kInfinity;
|
||||
pMax=-kInfinity;
|
||||
// Calculate rotated vertex coordinates
|
||||
|
||||
vertices=CreateRotatedVertices(pTransform);
|
||||
ClipCrossSection(vertices,0,pVoxelLimit,pAxis,pMin,pMax);
|
||||
ClipCrossSection(vertices,4,pVoxelLimit,pAxis,pMin,pMax);
|
||||
ClipBetweenSections(vertices,0,pVoxelLimit,pAxis,pMin,pMax);
|
||||
|
||||
if (pMin!=kInfinity||pMax!=-kInfinity)
|
||||
{
|
||||
existsAfterClip=true;
|
||||
|
||||
// Add 2*tolerance to avoid precision troubles
|
||||
pMin-=kCarTolerance;
|
||||
pMax+=kCarTolerance;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check for case where completely enveloping clipping volume
|
||||
// If point inside then we are confident that the solid completely
|
||||
// envelopes the clipping volume. Hence set min/max extents according
|
||||
// to clipping volume extents along the specified axis.
|
||||
G4ThreeVector clipCentre(
|
||||
(pVoxelLimit.GetMinXExtent()+pVoxelLimit.GetMaxXExtent())*0.5,
|
||||
(pVoxelLimit.GetMinYExtent()+pVoxelLimit.GetMaxYExtent())*0.5,
|
||||
(pVoxelLimit.GetMinZExtent()+pVoxelLimit.GetMaxZExtent())*0.5);
|
||||
|
||||
if (Inside(pTransform.Inverse().TransformPoint(clipCentre))!=kOutside)
|
||||
{
|
||||
existsAfterClip=true;
|
||||
pMin=pVoxelLimit.GetMinExtent(pAxis);
|
||||
pMax=pVoxelLimit.GetMaxExtent(pAxis);
|
||||
}
|
||||
}
|
||||
delete vertices;
|
||||
return existsAfterClip;
|
||||
}
|
||||
}
|
||||
|
||||
G4ThreeVectorList*
|
||||
G4BREPSolid::CreateRotatedVertices(const G4AffineTransform& pTransform) const
|
||||
{
|
||||
G4Point3D Min = bbox->GetBoxMin();
|
||||
G4Point3D Max = bbox->GetBoxMax();
|
||||
|
||||
G4ThreeVectorList *vertices;
|
||||
vertices=new G4ThreeVectorList(8);
|
||||
|
||||
if (vertices)
|
||||
{
|
||||
G4ThreeVector vertex0(Min.x(),Min.y(),Min.z());
|
||||
G4ThreeVector vertex1(Max.x(),Min.y(),Min.z());
|
||||
G4ThreeVector vertex2(Max.x(),Max.y(),Min.z());
|
||||
G4ThreeVector vertex3(Min.x(),Max.y(),Min.z());
|
||||
G4ThreeVector vertex4(Min.x(),Min.y(),Max.z());
|
||||
G4ThreeVector vertex5(Max.x(),Min.y(),Max.z());
|
||||
G4ThreeVector vertex6(Max.x(),Max.y(),Max.z());
|
||||
G4ThreeVector vertex7(Min.x(),Max.y(),Max.z());
|
||||
|
||||
vertices->insert(pTransform.TransformPoint(vertex0));
|
||||
vertices->insert(pTransform.TransformPoint(vertex1));
|
||||
vertices->insert(pTransform.TransformPoint(vertex2));
|
||||
vertices->insert(pTransform.TransformPoint(vertex3));
|
||||
vertices->insert(pTransform.TransformPoint(vertex4));
|
||||
vertices->insert(pTransform.TransformPoint(vertex5));
|
||||
vertices->insert(pTransform.TransformPoint(vertex6));
|
||||
vertices->insert(pTransform.TransformPoint(vertex7));
|
||||
}
|
||||
else
|
||||
{
|
||||
G4Exception("G4BREPSolid::CreateRotatedVertices Out of memory - Cannot alloc vertices");
|
||||
}
|
||||
return vertices;
|
||||
}
|
||||
|
||||
|
||||
EInside G4BREPSolid::Inside(register const G4ThreeVector& Pt)const
|
||||
{
|
||||
// This function find if the point Pt is inside,
|
||||
// outside or on the surface of the solid
|
||||
|
||||
G4cout<<"\n Solid Id="<<GetId();
|
||||
|
||||
// Tolerance has also to be considered i.e. the cases
|
||||
// where the Point is very close to the box. -1 is
|
||||
// returned when the Point is within the boundary.
|
||||
Reset();
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
|
||||
// Get the bounding box extents
|
||||
const G4Point3D min = bbox->GetBoxMin();
|
||||
const G4Point3D max = bbox->GetBoxMax();
|
||||
G4Vector3D v(1, 0, 0.01);
|
||||
G4Vector3D Pttmp(Pt);
|
||||
G4Vector3D Vtmp(v);
|
||||
G4Ray r(Pttmp, Vtmp);
|
||||
|
||||
// First check if the point is Inside the bbox
|
||||
// of the solid.
|
||||
if((Pt.x() < min.x() || Pt.x() > max.x())||
|
||||
(Pt.y() < min.y() || Pt.y() > max.y())||
|
||||
(Pt.z() < min.z() || Pt.z() > max.z()))
|
||||
// Check if point is inside the PCone bounding box
|
||||
if( !GetBBox()->Inside(Pttmp) )
|
||||
return kOutside;
|
||||
|
||||
// If the point is Inside the bbox, it is possibly Inside
|
||||
// the solid
|
||||
|
||||
// Create the ray.
|
||||
G4Vector3D v(0,0,1);
|
||||
Track.Init( Pt, v);
|
||||
|
||||
// Check the bboxes of the surfaces first to get the favorable
|
||||
// surfaces to process.
|
||||
TestSurfaceBBoxes( Track );
|
||||
|
||||
// At this point it might be useful to have a routine that checks
|
||||
// if the point is outside all the face bboxes, Inside any of them
|
||||
// or Inside all of them. The last case would mean Inside the solid for
|
||||
// sure. Also should be considered if various types of solids should be
|
||||
// handled separately i.e. convex polyhedras versus b-spline solids.
|
||||
int Hits = 0;
|
||||
|
||||
// Continue by shooting an arbitrary ray (G4Vector3D = v) starting from Point
|
||||
// Repeat this until no more hits are found. The amount of hits gives the
|
||||
// answer (par : outside; odd : inside)
|
||||
// Tolerance is a problem as there might be cases where we don't
|
||||
// get the actual intersection on the surface and the Step is not long
|
||||
// enough to jump over the real boundary.
|
||||
G4double Tolerance = 0.0001;
|
||||
G4double Dist=Tolerance+1;
|
||||
|
||||
const G4Vector3D& RayDir = Track.GetDir();
|
||||
|
||||
while(Intersect( Track ))
|
||||
if(FinalEvaluation( Track ))
|
||||
{
|
||||
// Step over the tolerance and shoot again in the same
|
||||
// direction using the Hit point as a starting point
|
||||
// for the new ray
|
||||
Hits++;
|
||||
|
||||
// Tolerance Step
|
||||
if(Hits==1)
|
||||
Dist=ShortestDistance;
|
||||
|
||||
const G4Point3D& NewStart = intersection_point+(Tolerance*RayDir);
|
||||
|
||||
// Set ray starting point
|
||||
Track.SetStart(NewStart);
|
||||
|
||||
Reset();
|
||||
|
||||
// To make the routine more robust a check could be made that
|
||||
// Hits doesn't grow too much say > 10. If this happens
|
||||
// v could be changed to be something else. This may avoid
|
||||
// situations where the direction chosen for the test
|
||||
// is not plausible since at that direction there are many
|
||||
// faces very close to each other or a face is highly complex or
|
||||
// the direction is in the direction of the face.
|
||||
//if(Hits > 10)
|
||||
// {
|
||||
// r.SetStart(Point);Hits = 0;
|
||||
// r.set_G4Vector3D(G4Vector3D(1,0,0));
|
||||
// while(first_intersect( r ))
|
||||
// {
|
||||
// Hits++;
|
||||
// intersection_point.X() += Tolerance;
|
||||
// r.SetStart(intersection_point);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
// else
|
||||
// break;
|
||||
|
||||
// Set the surfaces to active again
|
||||
G4Surface* Srf;
|
||||
Reset();
|
||||
|
||||
for(G4int a=0;a<nb_of_surfaces;a++)
|
||||
{
|
||||
Srf = SurfaceVec[a];
|
||||
Srf->Reset();
|
||||
}
|
||||
// Test if the bounding box of each surface is intersected
|
||||
// by the ray. If not, the surface become deactive.
|
||||
TestSurfaceBBoxes(r);
|
||||
|
||||
G4int hits=0, samehit=0;
|
||||
|
||||
// G4cout << "\n Inside::Hits = " << Hits << "\n";
|
||||
if(Dist < (0.5*kCarTolerance))
|
||||
return kSurface;
|
||||
|
||||
// Take the mod of hits with 2
|
||||
if(Hits&1)
|
||||
// Inside
|
||||
for(G4int a=0; a < nb_of_surfaces; a++)
|
||||
{
|
||||
if(SurfaceVec[a]->Active())
|
||||
{
|
||||
// count the number of intersections.
|
||||
// if this number is odd, the start of the ray is
|
||||
// inside the volume bounded by the surfaces, so
|
||||
// increment the number of intersection by 1 if the
|
||||
// point is not on the surface and if this intersection
|
||||
// was not founded before
|
||||
if( (SurfaceVec[a]->Intersect(r)) & 1 )
|
||||
{
|
||||
// test if the point is on the surface
|
||||
if(SurfaceVec[a]->Distance() < kCarTolerance)
|
||||
return kSurface;
|
||||
|
||||
// test if this intersection was founded before
|
||||
for(G4int i=0; i<a; i++)
|
||||
if(SurfaceVec[a]->Distance() == SurfaceVec[i]->Distance())
|
||||
{
|
||||
samehit++;
|
||||
break;
|
||||
}
|
||||
|
||||
// count the number of surfaces intersected by the ray
|
||||
if(!samehit)
|
||||
hits++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the number of surfaces intersected is odd,
|
||||
// the point is inside the solid
|
||||
if(hits&1)
|
||||
return kInside;
|
||||
else
|
||||
// Outside
|
||||
return kOutside;
|
||||
}
|
||||
|
||||
|
||||
G4ThreeVector G4BREPSolid::SurfaceNormal(const G4ThreeVector& GetStart)const
|
||||
G4ThreeVector G4BREPSolid::SurfaceNormal(const G4ThreeVector& Pt)const
|
||||
{
|
||||
return GetStart;;
|
||||
// This function calculates the normal of the surface
|
||||
// at a point on the surface
|
||||
// Note : the sense of the normal depends on the sense of the surface
|
||||
|
||||
G4Vector3D n(0,0,0);
|
||||
G4int iplane;
|
||||
|
||||
G4Vector3D norm;
|
||||
G4Ray r( Pt, G4Vector3D(1, 0, 0) );
|
||||
|
||||
// Find on which surface the point is
|
||||
for(iplane = 0; iplane < nb_of_surfaces; iplane++)
|
||||
{
|
||||
if(SurfaceVec[iplane]->HowNear(Pt) < kCarTolerance)
|
||||
// the point is on this surface
|
||||
break;
|
||||
}
|
||||
|
||||
// calcul of the normal at this point
|
||||
norm = SurfaceVec[iplane]->SurfaceNormal(Pt);
|
||||
|
||||
n = G4ThreeVector ( norm.x(), norm.y(), norm.z() );
|
||||
n = n.unit();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolid::DistanceToIn(const G4ThreeVector& Pt)const
|
||||
{
|
||||
// This function calculates the approximative distance
|
||||
// of a point from a surface. For exemple, the DistanceToIn
|
||||
// from a point to a G4FPlane is the closest distance
|
||||
// Calculates the shortest distance ("safety") from a point
|
||||
// outside the solid to any boundary of this solid.
|
||||
// Return 0 if the point is already inside.
|
||||
|
||||
G4cout<<"\n Solid Id="<<GetId();
|
||||
|
||||
Reset();
|
||||
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
G4Surface* srf;
|
||||
G4double PointDistance = INFINITY;
|
||||
G4double TmpDistance = 0;
|
||||
|
||||
for(G4int a=0; a<nb_of_surfaces;a++)
|
||||
{
|
||||
srf = SurfaceVec[a];
|
||||
TmpDistance = fabs(srf->ClosestDistanceToPoint(Pt));
|
||||
|
||||
if( (TmpDistance < PointDistance) && (TmpDistance > halfTolerance) )
|
||||
PointDistance = TmpDistance;
|
||||
else if(TmpDistance < halfTolerance)
|
||||
PointDistance = 0; // the point is on the surface,
|
||||
// but maybe not into the boundary
|
||||
G4double *dists = new G4double[nb_of_surfaces];
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
G4int a;
|
||||
|
||||
// Set the surfaces to active again
|
||||
Reset();
|
||||
|
||||
if(PointDistance < ShortestDistance)
|
||||
ShortestDistance = PointDistance;
|
||||
}
|
||||
// calcul of the shortest distance of the point to each surfaces
|
||||
// Be carreful : it's a signed value
|
||||
for(a=0; a< nb_of_surfaces; a++)
|
||||
dists[a] = SurfaceVec[a]->HowNear(Pt);
|
||||
|
||||
G4double Dist = kInfinity;
|
||||
|
||||
return ShortestDistance;
|
||||
// if dists[] is positive, the point is outside
|
||||
// so take the shortest of the shortest positive distances
|
||||
// dists[] can be equal to 0 : point on a surface
|
||||
// ( Problem with the G4FPlane : there is no inside and no outside...
|
||||
// So, to test if the point is inside to return 0, utilize the Inside
|
||||
// function. But I don`t know if it is really needed because dToIn is
|
||||
// called only if the point is outside )
|
||||
for(a = 0; a < nb_of_surfaces; a++)
|
||||
if( fabs(Dist) > fabs(dists[a]) )
|
||||
//if( dists[a] >= 0)
|
||||
Dist = dists[a];
|
||||
|
||||
delete[] dists;
|
||||
|
||||
if(Dist == kInfinity)
|
||||
// the point is inside the solid or on a surface
|
||||
return 0;
|
||||
else
|
||||
//return Dist;
|
||||
return fabs(Dist);
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolid::DistanceToIn(register const G4ThreeVector& Pt,
|
||||
register const G4ThreeVector& V )const
|
||||
{
|
||||
G4cout<<"\n Solid Id="<<GetId();
|
||||
// Calculates the distance from a point outside the solid
|
||||
// to the solid`s boundary along a specified direction vector.
|
||||
//
|
||||
// Note : Intersections with boundaries less than the
|
||||
// tolerance must be ignored if the direction
|
||||
// is away from the boundary
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if(V.mag2() == 0.0)
|
||||
G4Exception("Error in G4BREPSolid::DistanceToIn(Pt, Vec) : Vec = 0");
|
||||
#endif
|
||||
|
||||
Reset();
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
Track.Init(G4Point3D(Pt),V);
|
||||
|
||||
|
||||
if(!bbox->Test(Track))
|
||||
return kInfinity;
|
||||
|
||||
/*
|
||||
if(AxisBox)
|
||||
{
|
||||
ShortestDistance = bbox->GetDistance();
|
||||
|
||||
if(ShortestDistance > halfTolerance)
|
||||
return ShortestDistance;
|
||||
|
||||
// L. Broglia
|
||||
// Do not see this surface
|
||||
//else
|
||||
// ShortestDistance = kInfinity;
|
||||
//return 0; // the point is on the surface
|
||||
}
|
||||
*/
|
||||
|
||||
TestSurfaceBBoxes(Track);
|
||||
|
||||
if(Intersect( Track ))
|
||||
if(FinalEvaluation(Track,1))
|
||||
return sqrt(ShortestDistance);
|
||||
|
||||
return kInfinity;
|
||||
|
||||
/*
|
||||
G4Vector3D Pttmp(Pt);
|
||||
G4Vector3D Vtmp(V);
|
||||
// G4double kInfinity = 10e20;
|
||||
G4Ray r(Pttmp, Vtmp);
|
||||
if(!bbox->Test3dBBox(r))
|
||||
return kInfinity;
|
||||
if(AxisBox)
|
||||
{
|
||||
ShortestDistance = bbox->GetDistance();
|
||||
if(ShortestDistance > halfTolerance)
|
||||
return ShortestDistance;
|
||||
else
|
||||
ShortestDistance = kInfinity;
|
||||
}
|
||||
// if(number_of_Surfaces>75)
|
||||
// RemoveHiddenFaces(r, 1);
|
||||
TestSurfaceBBoxes(r);
|
||||
if(Intersect( r ))
|
||||
if(FinalEvaluation(r,1))
|
||||
return sqrt(ShortestDistance);
|
||||
return kInfinity;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolid::DistanceToOut(const G4ThreeVector& Pt)const
|
||||
{
|
||||
|
||||
G4cout<<"\n Solid Id="<<GetId();
|
||||
G4int a;
|
||||
|
||||
// Set the surfaces to active again
|
||||
Reset();
|
||||
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
G4Surface* srf;
|
||||
G4double PointDistance = INFINITY;
|
||||
G4double TmpDistance = 0;
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
G4Vector3D Pttmp(Pt);
|
||||
G4Vector3D Vtmp(V);
|
||||
G4Ray r(Pttmp, Vtmp);
|
||||
|
||||
// Test if the bounding box of each surface is intersected
|
||||
// by the ray. If not, the surface become deactive.
|
||||
TestSurfaceBBoxes(r);
|
||||
|
||||
for(G4int a=0; a<nb_of_surfaces;a++)
|
||||
ShortestDistance = kInfinity;
|
||||
|
||||
for(a=0; a< nb_of_surfaces; a++)
|
||||
{
|
||||
srf = SurfaceVec[a];
|
||||
TmpDistance = fabs(srf->ClosestDistanceToPoint(Pt));
|
||||
|
||||
if( (TmpDistance < PointDistance) && (TmpDistance > halfTolerance) )
|
||||
PointDistance = TmpDistance;
|
||||
else if(TmpDistance < halfTolerance)
|
||||
PointDistance = 0 ; // the point is on the surface
|
||||
if(SurfaceVec[a]->Active())
|
||||
{
|
||||
// test if the ray intersect the surface
|
||||
if( (SurfaceVec[a]->Intersect(r)) )
|
||||
{
|
||||
// if more than 1 surface is intersected,
|
||||
// take the nearest one
|
||||
if( SurfaceVec[a]->Distance() < ShortestDistance )
|
||||
if( SurfaceVec[a]->Distance() > halfTolerance )
|
||||
{
|
||||
ShortestDistance = SurfaceVec[a]->Distance();
|
||||
}
|
||||
else
|
||||
{
|
||||
// the point is within the boundary
|
||||
// ignored it if the direction is away from the boundary
|
||||
G4Vector3D Norm = SurfaceVec[a]->SurfaceNormal(Pttmp);
|
||||
|
||||
if( (Norm * Vtmp) < 0 )
|
||||
ShortestDistance = SurfaceVec[a]->Distance();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(PointDistance < ShortestDistance)
|
||||
ShortestDistance = PointDistance;
|
||||
|
||||
return ShortestDistance;
|
||||
// Be carreful !
|
||||
// SurfaceVec->Distance is in fact the squared distance
|
||||
if(ShortestDistance != kInfinity)
|
||||
return sqrt(ShortestDistance);
|
||||
else
|
||||
// no intersection, return kInfinity
|
||||
return kInfinity;
|
||||
}
|
||||
|
||||
|
||||
@@ -822,28 +904,111 @@ G4double G4BREPSolid::DistanceToOut(register const G4ThreeVector& P,
|
||||
G4bool *validNorm,
|
||||
G4ThreeVector *n ) const
|
||||
{
|
||||
G4cout<<"\n Solid Id="<<GetId();
|
||||
|
||||
if(validNorm)
|
||||
*validNorm = false;
|
||||
// Calculates the distance from a point inside the solid
|
||||
// to the solid`s boundary along a specified direction vector.
|
||||
// Return 0 if the point is already outside.
|
||||
//
|
||||
// Note : If the shortest distance to a boundary is less
|
||||
// than the tolerance, it is ignored. This allows
|
||||
// for a point within a tolerant boundary to leave
|
||||
// immediately
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if(D.mag2() == 0.0)
|
||||
G4Exception("Error in G4BREPSolid::DistanceToOut(Pt, Vec) : Vec = 0");
|
||||
#endif
|
||||
|
||||
// Set the surfaces to active again
|
||||
Reset();
|
||||
|
||||
const G4double halfTolerance = kCarTolerance*0.5;
|
||||
G4Vector3D Ptv = P;
|
||||
G4int a;
|
||||
|
||||
// I don`t understand this line
|
||||
if(validNorm)
|
||||
*validNorm=false;
|
||||
|
||||
G4Vector3D Pttmp(Ptv);
|
||||
G4Vector3D Vtmp(D);
|
||||
|
||||
G4Ray r(Pttmp, Vtmp);
|
||||
|
||||
// Test if the bounding box of each surface is intersected
|
||||
// by the ray. If not, the surface become deactive.
|
||||
TestSurfaceBBoxes(r);
|
||||
|
||||
ShortestDistance = kInfinity;
|
||||
|
||||
for(a=0; a< nb_of_surfaces; a++)
|
||||
{
|
||||
if(SurfaceVec[a]->Active())
|
||||
{
|
||||
// test if the ray intersect the surface
|
||||
if( (SurfaceVec[a]->Intersect(r)) )
|
||||
{
|
||||
// if more than 1 surface is intersected,
|
||||
// take the nearest one
|
||||
if( SurfaceVec[a]->Distance() < ShortestDistance )
|
||||
if( SurfaceVec[a]->Distance() > halfTolerance )
|
||||
{
|
||||
ShortestDistance = SurfaceVec[a]->Distance();
|
||||
}
|
||||
else
|
||||
{
|
||||
// the point is within the boundary: ignored it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Be carreful !
|
||||
// SurfaceVec->Distance is in fact the squared distance
|
||||
if(ShortestDistance != kInfinity)
|
||||
return sqrt(ShortestDistance);
|
||||
else
|
||||
// if no intersection is founded, the point is outside
|
||||
// so return 0
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolid::DistanceToOut(const G4ThreeVector& Pt)const
|
||||
{
|
||||
// Calculates the shortest distance ("safety") from a point
|
||||
// inside the solid to any boundary of this solid.
|
||||
// Return 0 if the point is already outside.
|
||||
|
||||
G4double *dists = new G4double[nb_of_surfaces];
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
G4int a;
|
||||
|
||||
// Set the surfaces to active again
|
||||
Reset();
|
||||
|
||||
Track.Init(G4Point3D(P),D);
|
||||
|
||||
TestSurfaceBBoxes(Track);
|
||||
|
||||
if(Intersect(Track))
|
||||
if(FinalEvaluation(Track))
|
||||
if(ShortestDistance > kCarTolerance/2) // if d=0, do not see the surface
|
||||
return sqrt(ShortestDistance);
|
||||
// calcul of the shortest distance of the point to each surfaces
|
||||
// Be carreful : it's a signed value
|
||||
for(a=0; a< nb_of_surfaces; a++)
|
||||
dists[a] = SurfaceVec[a]->HowNear(Pt);
|
||||
|
||||
G4double Dist = kInfinity;
|
||||
|
||||
return kInfinity; // This should never happen
|
||||
// if dists[] is negative, the point is inside
|
||||
// so take the shortest of the shortest negative distances
|
||||
// dists[] can be equal to 0 : point on a surface
|
||||
// ( Problem with the G4FPlane : there is no inside and no outside...
|
||||
// So, to test if the point is outside to return 0, utilize the Inside
|
||||
// function. But I don`t know if it is really needed because dToOut is
|
||||
// called only if the point is inside )
|
||||
|
||||
for(a = 0; a < nb_of_surfaces; a++)
|
||||
if( fabs(Dist) > fabs(dists[a]) )
|
||||
//if( dists[a] <= 0)
|
||||
Dist = dists[a];
|
||||
|
||||
delete[] dists;
|
||||
|
||||
if(Dist == kInfinity)
|
||||
// the point is ouside the solid or on a surface
|
||||
return 0;
|
||||
else
|
||||
// return Dist;
|
||||
return fabs(Dist);
|
||||
}
|
||||
|
||||
|
||||
@@ -937,6 +1102,7 @@ void G4BREPSolid::CalcBBoxes()
|
||||
// Find max and min of face bboxes to make
|
||||
// solids bbox.
|
||||
|
||||
// replace by Extend
|
||||
// max < box_max;
|
||||
if(max.x() < box_max.x()) max.setX(box_max.x());
|
||||
if(max.y() < box_max.y()) max.setY(box_max.y());
|
||||
@@ -1086,20 +1252,7 @@ int G4BREPSolid::Intersect(register const G4Ray& rayref) const
|
||||
{
|
||||
register G4Surface* tmp;
|
||||
|
||||
// L. Broglia
|
||||
// What is the utility of this test ?
|
||||
// If only 1 surface is intersected, it return 0
|
||||
// instead the intersection exist
|
||||
|
||||
/*
|
||||
if((a+1)<nb_of_surfaces)
|
||||
tmp = SurfaceVec[a+1];
|
||||
else
|
||||
tmp = 0;
|
||||
|
||||
if((tmp) && ( tmp->Active()))
|
||||
{
|
||||
*/
|
||||
|
||||
// Get the evaluated point on the surface
|
||||
G4Point3D& closest_point = srf->closest_hit;
|
||||
@@ -1234,7 +1387,7 @@ int G4BREPSolid::FinalEvaluation(register const G4Ray& rayref,
|
||||
|
||||
if(( Dir * Norm ) >= 0)
|
||||
{
|
||||
Dist = INFINITY;
|
||||
Dist = kInfinity;
|
||||
srf->Deactivate();
|
||||
}
|
||||
|
||||
@@ -1243,7 +1396,7 @@ int G4BREPSolid::FinalEvaluation(register const G4Ray& rayref,
|
||||
}
|
||||
else
|
||||
{
|
||||
Dist = INFINITY;
|
||||
Dist = kInfinity;
|
||||
srf->Deactivate();
|
||||
}
|
||||
}
|
||||
@@ -1263,7 +1416,7 @@ int G4BREPSolid::FinalEvaluation(register const G4Ray& rayref,
|
||||
if(TestDistance > Dist)
|
||||
{
|
||||
// Hit behind ray starting point, no intersection.
|
||||
Dist = INFINITY;
|
||||
Dist = kInfinity;
|
||||
srf->Deactivate();
|
||||
}
|
||||
else
|
||||
@@ -1286,7 +1439,7 @@ int G4BREPSolid::FinalEvaluation(register const G4Ray& rayref,
|
||||
//if(( Dir * Norm ) >= 0)
|
||||
if(( Dir * Norm ) < 0)
|
||||
{
|
||||
Dist = INFINITY;
|
||||
Dist = kInfinity;
|
||||
srf->Deactivate();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4BREPSolidBox.cc,v 1.1 1999/01/07 16:07:38 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
#include "G4BREPSolidBox.hh"
|
||||
#include "G4FPlane.hh"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4BREPSolidCone.cc,v 1.1 1999/01/07 16:07:38 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
|
||||
#include "G4BREPSolidCone.hh"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4BREPSolidCylinder.cc,v 1.1 1999/01/07 16:07:38 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
|
||||
#include "G4BREPSolidCylinder.hh"
|
||||
|
||||
@@ -5,9 +5,17 @@
|
||||
// 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 $
|
||||
// $Id: G4BREPSolidPCone.cc,v 1.12 1999/05/24 13:51:56 magni Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
//
|
||||
// The polyconical solid G4BREPSolidPCone is a shape defined by a set of
|
||||
// inner and outer conical or cylindrical surface sections and two planes
|
||||
// perpendicular to the Z axis. Each conical surface is defined by its
|
||||
// radius at two different planes perpendicular to the Z-axis. Inner and
|
||||
// outer conical surfaces are defined using common Z planes.
|
||||
//
|
||||
|
||||
#include "G4BREPSolidPCone.hh"
|
||||
#include "G4FCylindricalSurface.hh"
|
||||
#include "G4FConicalSurface.hh"
|
||||
@@ -38,18 +46,6 @@ G4BREPSolidPCone::G4BREPSolidPCone(G4String name,
|
||||
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
|
||||
@@ -66,10 +62,13 @@ G4BREPSolidPCone::G4BREPSolidPCone(G4String name,
|
||||
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++)
|
||||
for(a = 1; a < num_z_planes-1; a++)
|
||||
if (RMIN[a] >= RMAX[a])
|
||||
G4Exception("RMAX must be greater than RMIN");
|
||||
G4Exception("RMAX must be greater that RMIN in the middle Z planes.");
|
||||
|
||||
if( (RMIN[num_z_planes-1] > RMAX[num_z_planes-1] )
|
||||
|| (RMIN[0] > RMAX[0]) )
|
||||
G4Exception("RMAX must be greater or equal to RMIN at the ends.");
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Create cylindrical et conical surfaces
|
||||
@@ -97,10 +96,9 @@ G4BREPSolidPCone::G4BREPSolidPCone(G4String name,
|
||||
}
|
||||
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");
|
||||
G4cerr << "Error in construction of G4BREPSolidPCone "
|
||||
<< "Exactly the same z, rmin and rmax given for "
|
||||
<< "consecutive indices, " << a << " and " << a+1 << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -138,6 +136,9 @@ G4BREPSolidPCone::G4BREPSolidPCone(G4String name,
|
||||
|
||||
SurfaceVec[b] = new G4FPlane(PlaneDir, PlaneAxis, LocalOrigin);
|
||||
SurfaceVec[b]->SetBoundaries(&cv1);
|
||||
|
||||
// set sense of the surface
|
||||
// SurfaceVec[b]->SetSameSense(1);
|
||||
|
||||
nb_of_surfaces--;
|
||||
b++;
|
||||
@@ -157,6 +158,8 @@ G4BREPSolidPCone::G4BREPSolidPCone(G4String name,
|
||||
|
||||
SurfaceVec[b] = new G4FConicalSurface(ConeOrigin, Axis, Length,
|
||||
RMIN[a+1], RMIN[a]);
|
||||
// set sense of the surface
|
||||
SurfaceVec[b]->SetSameSense(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -166,6 +169,9 @@ G4BREPSolidPCone::G4BREPSolidPCone(G4String name,
|
||||
|
||||
SurfaceVec[b] = new G4FConicalSurface(ConeOrigin, Axis2,
|
||||
Length, RMIN[a], RMIN[a+1]);
|
||||
|
||||
// set sense of the surface
|
||||
SurfaceVec[b]->SetSameSense(0);
|
||||
}
|
||||
|
||||
b++;
|
||||
@@ -185,6 +191,10 @@ G4BREPSolidPCone::G4BREPSolidPCone(G4String name,
|
||||
|
||||
SurfaceVec[b] = new G4FCylindricalSurface(CylOrigin, Axis,
|
||||
RMIN[a], Length );
|
||||
|
||||
// set sense of the surface
|
||||
SurfaceVec[b]->SetSameSense(0);
|
||||
|
||||
b++;
|
||||
}
|
||||
}
|
||||
@@ -199,6 +209,9 @@ G4BREPSolidPCone::G4BREPSolidPCone(G4String name,
|
||||
|
||||
SurfaceVec[b] = new G4FConicalSurface(ConeOrigin, Axis,
|
||||
Length, RMAX[a+1], RMAX[a]);
|
||||
|
||||
// set sense of the surface
|
||||
SurfaceVec[b]->SetSameSense(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -208,6 +221,9 @@ G4BREPSolidPCone::G4BREPSolidPCone(G4String name,
|
||||
|
||||
SurfaceVec[b] = new G4FConicalSurface(ConeOrigin, Axis2,
|
||||
Length, RMAX[a], RMAX[a+1]);
|
||||
|
||||
// set sense of the surface
|
||||
SurfaceVec[b]->SetSameSense(1);
|
||||
}
|
||||
|
||||
b++;
|
||||
@@ -230,6 +246,10 @@ G4BREPSolidPCone::G4BREPSolidPCone(G4String name,
|
||||
|
||||
SurfaceVec[b] = new G4FCylindricalSurface(CylOrigin, Axis,
|
||||
RMAX[a], Length );
|
||||
|
||||
// set sense of the surface
|
||||
SurfaceVec[b]->SetSameSense(1);
|
||||
|
||||
b++;
|
||||
}
|
||||
}
|
||||
@@ -241,53 +261,71 @@ G4BREPSolidPCone::G4BREPSolidPCone(G4String name,
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// 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);
|
||||
if(RMIN[0] < RMAX[0]) {
|
||||
|
||||
SurfaceVec[nb_of_surfaces-2] = new G4FPlane(PlaneDir, PlaneAxis, Origin);
|
||||
SurfaceVec[nb_of_surfaces-2]->SetBoundaries(&cv);
|
||||
// Create start G4Plane & boundaries
|
||||
G4Point3D ArcStart1a = Origin + (RMIN[0]*PlaneDir);
|
||||
G4Point3D ArcStart1b = Origin + (RMAX[0]*PlaneDir);
|
||||
|
||||
|
||||
// Create end G4Plane & boundaries
|
||||
G4Point3D ArcStart2a = LocalOrigin + (RMIN[sections]*PlaneDir);
|
||||
G4Point3D ArcStart2b = LocalOrigin + (RMAX[sections]*PlaneDir);
|
||||
tmp = new G4CircularCurve;
|
||||
tmp->Init(G4Axis2Placement3D(PlaneDir, PlaneAxis, Origin), RMIN[0]);
|
||||
tmp->SetBounds(ArcStart1a, ArcStart1a);
|
||||
tmp->SetSameSense(0);
|
||||
cv.append(tmp);
|
||||
|
||||
cv.clear();
|
||||
tmp = new G4CircularCurve;
|
||||
tmp->Init(G4Axis2Placement3D(PlaneDir, PlaneAxis, Origin), RMAX[0]);
|
||||
tmp->SetBounds(ArcStart1b, ArcStart1b);
|
||||
tmp->SetSameSense(1);
|
||||
cv.append(tmp);
|
||||
|
||||
tmp = new G4CircularCurve;
|
||||
tmp->Init(G4Axis2Placement3D(PlaneDir, PlaneAxis, LocalOrigin),
|
||||
RMIN[sections]);
|
||||
tmp->SetBounds(ArcStart2a, ArcStart2a);
|
||||
tmp->SetSameSense(0);
|
||||
cv.append(tmp);
|
||||
SurfaceVec[nb_of_surfaces-2] = new G4FPlane(PlaneDir, -PlaneAxis, Origin);
|
||||
SurfaceVec[nb_of_surfaces-2]->SetBoundaries(&cv);
|
||||
|
||||
tmp = new G4CircularCurve;
|
||||
tmp->Init(G4Axis2Placement3D(PlaneDir, PlaneAxis, LocalOrigin),
|
||||
RMAX[sections]);
|
||||
tmp->SetBounds(ArcStart2b, ArcStart2b);
|
||||
tmp->SetSameSense(1);
|
||||
cv.append(tmp);
|
||||
// set sense of the surface
|
||||
SurfaceVec[nb_of_surfaces-2]->SetSameSense(0);
|
||||
}else{
|
||||
// RMIN[0] == RMAX[0]
|
||||
// no surface is needed, it is a line!
|
||||
nb_of_surfaces--;
|
||||
}
|
||||
|
||||
if(RMIN[sections] < RMAX[sections]) {
|
||||
|
||||
// Create end G4Plane & boundaries
|
||||
G4Point3D ArcStart2a = LocalOrigin + (RMIN[sections]*PlaneDir);
|
||||
G4Point3D ArcStart2b = LocalOrigin + (RMAX[sections]*PlaneDir);
|
||||
|
||||
SurfaceVec[nb_of_surfaces-1]= new G4FPlane(PlaneDir, PlaneAxis, LocalOrigin);
|
||||
SurfaceVec[nb_of_surfaces-1]->SetBoundaries(&cv);
|
||||
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);
|
||||
|
||||
// set sense of the surface
|
||||
SurfaceVec[nb_of_surfaces-1]->SetSameSense(0);
|
||||
}else{
|
||||
// RMIN[0] == RMAX[0]
|
||||
// no surface is needed, it is a line!
|
||||
nb_of_surfaces--;
|
||||
}
|
||||
|
||||
active=1;
|
||||
Initialize();
|
||||
@@ -355,181 +393,202 @@ void G4BREPSolidPCone::Initialize()
|
||||
|
||||
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);
|
||||
// This function find if the point Pt is inside,
|
||||
// outside or on the surface of the solid
|
||||
|
||||
if((dist1 < -kCarTolerance && dist2 <-kCarTolerance)||
|
||||
(dist1 > kCarTolerance && dist2 >kCarTolerance) )
|
||||
return kOutside;
|
||||
|
||||
G4Vector3D v(1,0,0);
|
||||
G4double Dist;
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
|
||||
// G4Vector3D v(1, 0, 0.01);
|
||||
G4Vector3D v(1, 0, 0);
|
||||
G4Vector3D Pttmp(Pt);
|
||||
G4Vector3D Vtmp(v);
|
||||
G4Ray r(Pttmp, Vtmp);
|
||||
|
||||
// Check if point is inside the PCone bounding box
|
||||
if( !GetBBox()->Inside(Pttmp) )
|
||||
return kOutside;
|
||||
|
||||
// Set the surfaces to active again
|
||||
Reset();
|
||||
|
||||
// Test if the bounding box of each surface is intersected
|
||||
// by the ray. If not, the surface become deactive.
|
||||
TestSurfaceBBoxes(r);
|
||||
G4int hits=0;
|
||||
|
||||
G4double dist = kInfinity;
|
||||
G4bool isIntersected = false;
|
||||
G4int WhichSurface = 0;
|
||||
|
||||
// Chech if the point is on the surface, otherwise
|
||||
// find the nearest intersected suface. If there are not intersections the
|
||||
// point is outside
|
||||
|
||||
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++;
|
||||
{
|
||||
if(fabs(SurfaceVec[a]->HowNear(Pt)) < kCarTolerance)
|
||||
return kSurface;
|
||||
|
||||
if ( SurfaceVec[a]->Intersect(r) ) {
|
||||
isIntersected = true;
|
||||
if ( fabs(SurfaceVec[a]->Distance()) < dist ) {
|
||||
dist = SurfaceVec[a]->Distance();
|
||||
WhichSurface = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !isIntersected ) return kOutside;
|
||||
|
||||
// Set the surfaces to active again
|
||||
for(G4int b=0; b < nb_of_surfaces; b++)
|
||||
SurfaceVec[b]->Reset();
|
||||
// Find the point of intersection on the surface and the normal
|
||||
// !!!! be carefull the distance is sqrt(dist) !!!!
|
||||
|
||||
|
||||
if(hits&1)
|
||||
return kInside;
|
||||
|
||||
G4ThreeVector IntersectionPoint = Pttmp + sqrt(dist)*Vtmp;
|
||||
G4ThreeVector Normal = SurfaceVec[WhichSurface]->SurfaceNormal(IntersectionPoint);
|
||||
if ( Normal*Vtmp > 0 ) return kInside;
|
||||
return kOutside;
|
||||
|
||||
}
|
||||
|
||||
|
||||
G4ThreeVector G4BREPSolidPCone::SurfaceNormal(const G4ThreeVector& Pt) const
|
||||
{
|
||||
G4cout<<" SurfaceNormal() of G4BREPSolidPCone modified by L. Broglia";
|
||||
|
||||
G4Vector3D Ptv = Pt;
|
||||
{
|
||||
// This function calculates the normal of the surface
|
||||
// at a point on the surface
|
||||
// Note : the sense of the normal depends on the sense of the surface
|
||||
|
||||
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;
|
||||
G4int normflag = 0;
|
||||
|
||||
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++)
|
||||
// Find on which surface the point is
|
||||
for(iplane = 0; iplane < nb_of_surfaces; 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;
|
||||
if( fabs(SurfaceVec[iplane]->HowNear(Pt)) < kCarTolerance) {
|
||||
// the point is on this surface
|
||||
normflag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
norm = SurfaceVec[iplane]->SurfaceNormal(Pt);
|
||||
// calcul of the normal at this point
|
||||
if ( normflag ) {
|
||||
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 = G4ThreeVector ( norm.x(), norm.y(), norm.z() );
|
||||
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;
|
||||
return n;
|
||||
} else {
|
||||
cout << "Warning ... PCone not able to return normal .. " << endl;
|
||||
return ( G4ThreeVector(1,0,0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidPCone::DistanceToIn(const G4ThreeVector& Pt) const
|
||||
{
|
||||
// Calculates the shortest distance ("safety") from a point
|
||||
// outside the solid to any boundary of this solid.
|
||||
// Return 0 if the point is already inside.
|
||||
|
||||
|
||||
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));
|
||||
// Set the surfaces to active again
|
||||
Reset();
|
||||
|
||||
G4double Dist=kInfinity;
|
||||
// calcul of the shortest distance of the point to each surfaces
|
||||
// Be carreful : it's a signed value
|
||||
for(a=0; a< nb_of_surfaces; a++)
|
||||
dists[a] = SurfaceVec[a]->HowNear(Pt);
|
||||
|
||||
G4double Dist = kInfinity;
|
||||
|
||||
for(a=0; a< nb_of_surfaces;a++)
|
||||
if(Dist>dists[a]) Dist = dists[a];
|
||||
// if dists[] is positive, the point is outside
|
||||
// so take the shortest of the shortest positive distances
|
||||
// dists[] can be equal to 0 : point on a surface
|
||||
// ( Problem with the G4FPlane : there is no inside and no outside...
|
||||
// So, to test if the point is inside to return 0, utilize the Inside
|
||||
// function. But I don`t know if it is really needed because dToIn is
|
||||
// called only if the point is outside )
|
||||
for(a = 0; a < nb_of_surfaces; a++)
|
||||
if( fabs(Dist) > fabs(dists[a]) )
|
||||
//if( dists[a] >= 0)
|
||||
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;
|
||||
if(Dist == kInfinity)
|
||||
// the point is inside the solid or on a surface
|
||||
return 0;
|
||||
else
|
||||
//return Dist;
|
||||
return fabs(Dist);
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidPCone::DistanceToIn(register const G4ThreeVector& Pt,
|
||||
register const G4ThreeVector& V) const
|
||||
{
|
||||
int a;
|
||||
// Calculates the distance from a point outside the solid
|
||||
// to the solid`s boundary along a specified direction vector.
|
||||
//
|
||||
// Note : Intersections with boundaries less than the
|
||||
// tolerance must be ignored if the direction
|
||||
// is away from the boundary
|
||||
|
||||
G4int a;
|
||||
|
||||
// Set the surfaces to active again
|
||||
Reset();
|
||||
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
G4Vector3D Pttmp(Pt);
|
||||
G4Vector3D Vtmp(V);
|
||||
// G4double kInfinity = ;
|
||||
G4Ray r(Pttmp, Vtmp);
|
||||
|
||||
// Test if the bounding box of each surface is intersected
|
||||
// by the ray. If not, the surface become deactive.
|
||||
TestSurfaceBBoxes(r);
|
||||
|
||||
ShortestDistance = kInfinity;
|
||||
|
||||
for(a=0; a< nb_of_surfaces;a++)
|
||||
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)
|
||||
{
|
||||
// test if the ray intersect the surface
|
||||
G4Vector3D Norm = SurfaceVec[a]->SurfaceNormal(Pttmp);
|
||||
if( (Norm * Vtmp) < 0 && fabs(SurfaceVec[a]->HowNear(Pt)) < halfTolerance )
|
||||
return 0;
|
||||
if( (SurfaceVec[a]->Intersect(r)) ) {
|
||||
|
||||
// if more than 1 surface is intersected,
|
||||
// take the nearest one
|
||||
if( SurfaceVec[a]->Distance() < ShortestDistance )
|
||||
if( 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();
|
||||
|
||||
|
||||
// Be careful !
|
||||
// SurfaceVec->Distance is in fact the squared distance
|
||||
if(ShortestDistance != kInfinity)
|
||||
return sqrt(ShortestDistance);
|
||||
|
||||
return kInfinity;
|
||||
else
|
||||
// no intersection, return kInfinity
|
||||
return kInfinity;
|
||||
}
|
||||
|
||||
|
||||
@@ -539,76 +598,110 @@ G4double G4BREPSolidPCone::DistanceToOut(register const G4ThreeVector& Pt,
|
||||
G4bool *validNorm,
|
||||
G4ThreeVector *n ) const
|
||||
{
|
||||
// Calculates the distance from a point inside the solid
|
||||
// to the solid`s boundary along a specified direction vector.
|
||||
// Return 0 if the point is already outside.
|
||||
//
|
||||
// Note : If the shortest distance to a boundary is less
|
||||
// than the tolerance, it is ignored. This allows
|
||||
// for a point within a tolerant boundary to leave
|
||||
// immediately
|
||||
|
||||
// Set the surfaces to active again
|
||||
Reset();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// I don`t understand this line
|
||||
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();
|
||||
|
||||
// Test if the bounding box of each surface is intersected
|
||||
// by the ray. If not, the surface become deactive.
|
||||
TestSurfaceBBoxes(r);
|
||||
|
||||
ShortestDistance = kInfinity;
|
||||
|
||||
for(a=0; a< nb_of_surfaces; a++)
|
||||
{
|
||||
if(SurfaceVec[a]->Active())
|
||||
{
|
||||
G4Vector3D Norm = SurfaceVec[a]->SurfaceNormal(Pttmp);
|
||||
if( (Norm * Vtmp) > 0 && fabs(SurfaceVec[a]->HowNear(Pt)) < halfTolerance )
|
||||
return 0;
|
||||
// test if the ray intersect the surface
|
||||
if( (SurfaceVec[a]->Intersect(r)) )
|
||||
{
|
||||
// if more than 1 surface is intersected,
|
||||
// take the nearest one
|
||||
if( SurfaceVec[a]->Distance() < ShortestDistance )
|
||||
if( SurfaceVec[a]->Distance() > halfTolerance )
|
||||
{
|
||||
ShortestDistance = SurfaceVec[a]->Distance();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Be carreful !
|
||||
// SurfaceVec->Distance is in fact the squared distance
|
||||
if(ShortestDistance != kInfinity)
|
||||
return sqrt(ShortestDistance);
|
||||
|
||||
return kInfinity;
|
||||
else
|
||||
// if no intersection is founded, the point is outside
|
||||
// so return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidPCone::DistanceToOut(const G4ThreeVector& Pt) const
|
||||
{
|
||||
int a;
|
||||
// Calculates the shortest distance ("safety") from a point
|
||||
// inside the solid to any boundary of this solid.
|
||||
// Return 0 if the point is already outside.
|
||||
|
||||
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];
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
G4int a;
|
||||
|
||||
// Set the surfaces to active again
|
||||
for(G4int b=0; b < nb_of_surfaces; b++)
|
||||
SurfaceVec[b]->Reset();
|
||||
Reset();
|
||||
|
||||
// calcul of the shortest distance of the point to each surfaces
|
||||
// Be carreful : it's a signed value
|
||||
for(a=0; a< nb_of_surfaces; a++)
|
||||
dists[a] = SurfaceVec[a]->HowNear(Pt);
|
||||
|
||||
G4double Dist = kInfinity;
|
||||
|
||||
// if dists[] is negative, the point is inside
|
||||
// so take the shortest of the shortest negative distances
|
||||
// dists[] can be equal to 0 : point on a surface
|
||||
// ( Problem with the G4FPlane : there is no inside and no outside...
|
||||
// So, to test if the point is outside to return 0, utilize the Inside
|
||||
// function. But I don`t know if it is really needed because dToOut is
|
||||
// called only if the point is inside )
|
||||
|
||||
// If we are on a surface, the return value Dist must be zero!
|
||||
delete[] dists;
|
||||
return Dist;
|
||||
for(a = 0; a < nb_of_surfaces; a++)
|
||||
if( fabs(Dist) > fabs(dists[a]) )
|
||||
//if( dists[a] <= 0)
|
||||
Dist = dists[a];
|
||||
|
||||
delete[] dists;
|
||||
|
||||
if(Dist == kInfinity)
|
||||
// the point is ouside the solid or on a surface
|
||||
return 0;
|
||||
else
|
||||
// return Dist;
|
||||
return fabs(Dist);
|
||||
}
|
||||
|
||||
|
||||
@@ -639,3 +732,6 @@ G4Polyhedron* G4BREPSolidPCone::CreatePolyhedron() const
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,8 +5,26 @@
|
||||
// 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 $
|
||||
// $Id: G4BREPSolidPolyhedra.cc,v 1.9 1999/05/28 08:49:12 sgiani Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
// Corrections by S.Giani:
|
||||
// - Xaxis now corresponds to phi=0
|
||||
// - partial angle = phiTotal / Nsides
|
||||
// - end planes exact boundary calculation for phiTotal < 2pi
|
||||
// (also including case with RMIN=RMAX)
|
||||
// - Xaxis now properly rotated to compute correct scope of vertixes
|
||||
// - corrected surface orientation for outer faces parallel to Z
|
||||
// - completed explicit setting of the orientation for all faces
|
||||
// - some comparison between doubles avoided by using tolerances.
|
||||
//
|
||||
//
|
||||
// The polygonal solid G4BREPSolidPolyhedra is a shape defined by an inner
|
||||
// and outer polygonal surface and two planes perpendicular to the Z axis.
|
||||
// Each polygonal surface is created by linking a series of polygons created
|
||||
// at different planes perpendicular to the Z-axis. All these polygons all
|
||||
// have the same number of sides (sides) and are defined at the same Z planes
|
||||
// for both inner and outer polygonal surfaces.
|
||||
//
|
||||
|
||||
#include "G4BREPSolidPolyhedra.hh"
|
||||
@@ -26,7 +44,7 @@ G4BREPSolidPolyhedra::G4BREPSolidPolyhedra(G4String name,
|
||||
{
|
||||
const int sections= num_z_planes - 1;
|
||||
|
||||
if(dphi == 2*pi)
|
||||
if(dphi >= 2*pi-perMillion)
|
||||
nb_of_surfaces = 2*(sections * sides) + 2;
|
||||
else
|
||||
nb_of_surfaces = 2*(sections * sides) + 4;
|
||||
@@ -35,28 +53,13 @@ G4BREPSolidPolyhedra::G4BREPSolidPolyhedra(G4String name,
|
||||
SurfaceVec = new G4Surface*[nb_of_surfaces];
|
||||
|
||||
G4Vector3D Axis(0,0,1);
|
||||
G4Vector3D YAxis(0,1,0);
|
||||
G4Vector3D XAxis(1,0,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;
|
||||
G4Point3D Origin(0,0,z_start);
|
||||
G4Point3D LocalOrigin(0,0,z_start);
|
||||
G4double Length;
|
||||
G4int Count = 0 ;
|
||||
G4double PartAngle = (dphi)/sides;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
@@ -64,9 +67,13 @@ G4BREPSolidPolyhedra::G4BREPSolidPolyhedra(G4String name,
|
||||
|
||||
for(G4int a=0;a<sections;a++)
|
||||
{
|
||||
TmpAxis= YAxis;
|
||||
TmpAxis= XAxis;
|
||||
TmpAxis.rotateZ(phi1);
|
||||
Length = z_values[a+1] - z_values[a];
|
||||
|
||||
// L. Broglia
|
||||
// Be careful in the construction of the planes
|
||||
// See G4FPlane
|
||||
|
||||
// Create sides
|
||||
for(int b=0;b<sides;b++)
|
||||
@@ -74,25 +81,34 @@ G4BREPSolidPolyhedra::G4BREPSolidPolyhedra(G4String name,
|
||||
G4Point3DVector PointList(4);
|
||||
// Create inner side
|
||||
// Calc points for the planar surface boundary
|
||||
// The order of the point give the sense
|
||||
PointList[0] = LocalOrigin + (RMIN[a] * TmpAxis);
|
||||
PointList[1] = LocalOrigin + (Length*Axis) + (RMIN[a+1] * TmpAxis);
|
||||
PointList[3] = 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);
|
||||
PointList[1] = LocalOrigin + (RMIN[a] * TmpAxis);
|
||||
|
||||
// Add to surface list and reverse sense
|
||||
SurfaceVec[Count] = new G4FPlane( &PointList, 0, 0);
|
||||
|
||||
Count++;
|
||||
|
||||
// Rotate axis back for the other surface point calculation
|
||||
TmpAxis.rotateZ(-PartAngle);
|
||||
|
||||
// Calc points for the planar surface boundary
|
||||
|
||||
// Create outer side
|
||||
// Calc points for the planar surface boundary
|
||||
// The order of the point give the sense
|
||||
G4Point3DVector PointList2(4);
|
||||
PointList2[0] = LocalOrigin + (RMAX[a] * TmpAxis);
|
||||
PointList2[1] = LocalOrigin + (Length*Axis) + (RMAX[a+1] * TmpAxis);
|
||||
PointList2[3] = 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);
|
||||
PointList2[1] = LocalOrigin + (RMAX[a] * TmpAxis);
|
||||
|
||||
// Add to surface list and set sense
|
||||
SurfaceVec[Count] = new G4FPlane(&PointList2);
|
||||
|
||||
Count++;
|
||||
}
|
||||
|
||||
@@ -101,14 +117,14 @@ G4BREPSolidPolyhedra::G4BREPSolidPolyhedra(G4String name,
|
||||
|
||||
// Create end planes
|
||||
|
||||
if(dphi == 2*pi)
|
||||
if(dphi >= 2*pi-perMillion)
|
||||
{
|
||||
// Create only end planes
|
||||
G4Point3DVector EndPointList(sides);
|
||||
G4Point3DVector InnerPointList(sides);
|
||||
G4Point3DVector EndPointList2(sides);
|
||||
G4Point3DVector InnerPointList2(sides);
|
||||
TmpAxis = YAxis;
|
||||
TmpAxis = XAxis;
|
||||
TmpAxis.rotateZ(phi1);
|
||||
TmpAxis.rotateZ(dphi);
|
||||
|
||||
@@ -122,59 +138,44 @@ G4BREPSolidPolyhedra::G4BREPSolidPolyhedra(G4String name,
|
||||
TmpAxis.rotateZ(-PartAngle);
|
||||
}
|
||||
|
||||
// Add to surface list and set sense
|
||||
SurfaceVec[nb_of_surfaces-2] =
|
||||
new G4FPlane(&EndPointList, &InnerPointList);
|
||||
|
||||
// Add to surface list and reverse sense
|
||||
SurfaceVec[nb_of_surfaces-1] =
|
||||
new G4FPlane(&EndPointList2, &InnerPointList2);
|
||||
new G4FPlane(&EndPointList2, &InnerPointList2, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
TmpAxis = YAxis;
|
||||
// If phi section, create a single boundary (case with RMIN=0 included)
|
||||
TmpAxis = XAxis;
|
||||
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;
|
||||
// Create end planes
|
||||
G4Point3DVector EndPointList ((sides+1)*2);
|
||||
G4Point3DVector EndPointList2((sides+1)*2);
|
||||
|
||||
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);
|
||||
// outer polylines for origin end and opposite side
|
||||
EndPointList[c] = Origin + (RMAX[0] * TmpAxis);
|
||||
EndPointList[(sides+1)*2-1-c] = Origin + (RMIN[0] * TmpAxis);
|
||||
EndPointList2[c] = LocalOrigin + (RMAX[sections] * TmpAxis);
|
||||
InnerPointList2[c] = LocalOrigin + (RMIN[sections] * TmpAxis);
|
||||
EndPointList2[(sides+1)*2-1-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;
|
||||
// Create the lateral planars
|
||||
TmpAxis = XAxis;
|
||||
G4ThreeVector TmpAxis2 = XAxis;
|
||||
TmpAxis.rotateZ(phi1);
|
||||
TmpAxis2.rotateZ(phi1);
|
||||
TmpAxis2.rotateZ(dphi);
|
||||
|
||||
LocalOrigin=Origin;
|
||||
points = sections*2+2;
|
||||
int points = sections*2+2;
|
||||
G4Point3DVector GapPointList(points);
|
||||
G4Point3DVector GapPointList2(points);
|
||||
Count=0;
|
||||
@@ -193,8 +194,26 @@ G4BREPSolidPolyhedra::G4BREPSolidPolyhedra(G4String name,
|
||||
LocalOrigin = LocalOrigin+(Length*Axis);
|
||||
}
|
||||
|
||||
SurfaceVec[nb_of_surfaces-2] = new G4FPlane(&GapPointList);
|
||||
SurfaceVec[nb_of_surfaces-1] = new G4FPlane(&GapPointList2);
|
||||
// Add the lateral planars to the surfaces list and set/reverse sense
|
||||
|
||||
SurfaceVec[nb_of_surfaces-4] = new G4FPlane(&GapPointList);
|
||||
SurfaceVec[nb_of_surfaces-3] = new G4FPlane(&GapPointList2, 0, 0);
|
||||
|
||||
//Add the end planes to the surfaces list and set/reverse sense
|
||||
|
||||
if(RMAX[0]-RMIN[0] >= perMillion){
|
||||
SurfaceVec[nb_of_surfaces-2] = new G4FPlane(&EndPointList);
|
||||
}
|
||||
else{
|
||||
nb_of_surfaces -= 1;
|
||||
};
|
||||
|
||||
if(RMAX[sections]-RMIN[sections] >= perMillion){
|
||||
SurfaceVec[nb_of_surfaces-1] = new G4FPlane(&EndPointList2, 0, 0);
|
||||
}
|
||||
else{
|
||||
nb_of_surfaces -= 1;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -217,6 +236,32 @@ G4BREPSolidPolyhedra::G4BREPSolidPolyhedra(G4String name,
|
||||
original_parameters.Rmin[is]= RMIN[is]/rFactor;
|
||||
original_parameters.Rmax[is]= RMAX[is]/rFactor;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Print for debugging
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
static G4int print_pgone_parameters = 1;
|
||||
|
||||
if(print_pgone_parameters)
|
||||
{
|
||||
G4cout << "Parameters of the G4PGone " << name << endl;
|
||||
G4cout << " starting angle =" << original_parameters.Start_angle << endl;
|
||||
G4cout << " opening angle =" << original_parameters.Opening_angle << endl;
|
||||
G4cout << " sides =" << original_parameters.Sides << endl;
|
||||
G4cout << " nb of z planes=" << original_parameters.Num_z_planes << endl;
|
||||
|
||||
for (G4int nb = 0; nb <= sections; nb++)
|
||||
{
|
||||
G4cout << " Z[" << nb << "] = " << original_parameters.Z_values[nb];
|
||||
G4cout << " Rmin[" << nb << "] = " << original_parameters.Rmin[nb];
|
||||
G4cout << " Rmax[" << nb << "] = " << original_parameters.Rmax[nb]
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// z_values[0] should be equal to z_start, for consistency
|
||||
// with what the constructor does.
|
||||
@@ -261,93 +306,95 @@ void G4BREPSolidPolyhedra::Initialize()
|
||||
|
||||
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;
|
||||
}
|
||||
// This function find if the point Pt is inside,
|
||||
// outside or on the surface of the solid
|
||||
|
||||
if(Dist > halfTolerance)
|
||||
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
|
||||
G4Vector3D v(1, 0, 0.01);
|
||||
G4Vector3D Pttmp(Pt);
|
||||
G4Vector3D Vtmp(v);
|
||||
G4Ray r(Pttmp, Vtmp);
|
||||
|
||||
// Check if point is inside the Polyhedra bounding box
|
||||
if( !GetBBox()->Inside(Pttmp) )
|
||||
return kOutside;
|
||||
|
||||
// Set the surfaces to active again
|
||||
Reset();
|
||||
|
||||
if(Dist < -halfTolerance)
|
||||
return kInside;
|
||||
// Test if the bounding box of each surface is intersected
|
||||
// by the ray. If not, the surface become deactive.
|
||||
TestSurfaceBBoxes(r);
|
||||
|
||||
return kSurface;
|
||||
G4int hits=0, samehit=0;
|
||||
|
||||
for(G4int a=0; a < nb_of_surfaces; a++)
|
||||
{
|
||||
if(SurfaceVec[a]->Active())
|
||||
{
|
||||
// count the number of intersections.
|
||||
// if this number is odd, the start of the ray is
|
||||
// inside the volume bounded by the surfaces, so
|
||||
// increment the number of intersection by 1 if the
|
||||
// point is not on the surface and if this intersection
|
||||
// was not founded before
|
||||
if( (SurfaceVec[a]->Intersect(r)) & 1 )
|
||||
{
|
||||
// test if the point is on the surface
|
||||
if(SurfaceVec[a]->Distance() <= kCarTolerance*kCarTolerance)
|
||||
return kSurface;
|
||||
|
||||
// test if this intersection was founded before
|
||||
for(G4int i=0; i<a; i++)
|
||||
if(SurfaceVec[a]->Distance() == SurfaceVec[i]->Distance())
|
||||
{
|
||||
samehit++;
|
||||
break;
|
||||
}
|
||||
|
||||
// count the number of surfaces intersected by the ray
|
||||
if(!samehit)
|
||||
hits++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the number of surfaces intersected is odd,
|
||||
// the point is inside the solid
|
||||
if(hits&1)
|
||||
return kInside;
|
||||
else
|
||||
return kOutside;
|
||||
}
|
||||
|
||||
|
||||
G4ThreeVector G4BREPSolidPolyhedra::SurfaceNormal
|
||||
(const G4ThreeVector& Pt) const
|
||||
{
|
||||
G4cout<<" SurfaceNormal() of G4BREPSolidPolyhedra modified by L. Broglia";
|
||||
// This function calculates the normal of the surface
|
||||
// at a point on the surface
|
||||
// Note : the sense of the normal depends on the sense of the surface
|
||||
|
||||
/*
|
||||
//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++)
|
||||
|
||||
// Find on which surface the point is
|
||||
for(iplane = 0; iplane < nb_of_surfaces; 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;
|
||||
if(SurfaceVec[iplane]->HowNear(Pt) < kCarTolerance)
|
||||
// the point is on this surface
|
||||
break;
|
||||
}
|
||||
|
||||
norm = SurfaceVec[iplane]->SurfaceNormal(Pt);
|
||||
// calcul of the normal at this point
|
||||
norm = SurfaceVec[iplane]->SurfaceNormal(Pt);
|
||||
|
||||
n = G4ThreeVector ( norm.x(), norm.y(), norm.z());
|
||||
n = G4ThreeVector ( norm.x(), norm.y(), norm.z() );
|
||||
n = n.unit();
|
||||
|
||||
return n;
|
||||
@@ -356,113 +403,228 @@ G4ThreeVector G4BREPSolidPolyhedra::SurfaceNormal
|
||||
|
||||
G4double G4BREPSolidPolyhedra::DistanceToIn(const G4ThreeVector& Pt) const
|
||||
{
|
||||
G4double Dist=kInfinity;
|
||||
G4double tmpdist=kInfinity;
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
// Calculates the shortest distance ("safety") from a point
|
||||
// outside the solid to any boundary of this solid.
|
||||
// Return 0 if the point is already inside.
|
||||
|
||||
|
||||
G4double *dists = new G4double[nb_of_surfaces];
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
G4int a;
|
||||
|
||||
// Set the surfaces to active again
|
||||
Reset();
|
||||
|
||||
for(int a=0; a< nb_of_surfaces;a++)
|
||||
{
|
||||
tmpdist = fabs(SurfaceVec[a]->HowNear(Pt));
|
||||
if(Dist>tmpdist && tmpdist> halfTolerance) Dist = tmpdist;
|
||||
}
|
||||
// calcul of the shortest distance of the point to each surfaces
|
||||
// Be carreful : it's a signed value
|
||||
for(a=0; a< nb_of_surfaces; a++)
|
||||
dists[a] = SurfaceVec[a]->HowNear(Pt);
|
||||
|
||||
G4double Dist = kInfinity;
|
||||
|
||||
return Dist;
|
||||
// if dists[] is positive, the point is outside
|
||||
// so take the shortest of the shortest positive distances
|
||||
// dists[] can be equal to 0 : point on a surface
|
||||
// ( Problem with the G4FPlane : there is no inside and no outside...
|
||||
// So, to test if the point is inside to return 0, utilize the Inside
|
||||
// function. But I don`t know if it is really needed because dToIn is
|
||||
// called only if the point is outside )
|
||||
for(a = 0; a < nb_of_surfaces; a++)
|
||||
if( fabs(Dist) > fabs(dists[a]) )
|
||||
//if( dists[a] >= 0)
|
||||
Dist = dists[a];
|
||||
|
||||
delete[] dists;
|
||||
|
||||
if(Dist == kInfinity)
|
||||
// the point is inside the solid or on a surface
|
||||
return 0;
|
||||
else
|
||||
//return Dist;
|
||||
return fabs(Dist);
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidPolyhedra::DistanceToIn(register const G4ThreeVector& Pt,
|
||||
register const G4ThreeVector& V
|
||||
) const
|
||||
register const G4ThreeVector& V) const
|
||||
{
|
||||
Reset();
|
||||
G4Point3D Pttmp(Pt);
|
||||
G4Vector3D Vtmp(V);
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
|
||||
// G4double kInfinity = kInfinity;
|
||||
// Calculates the distance from a point outside the solid
|
||||
// to the solid`s boundary along a specified direction vector.
|
||||
//
|
||||
// Note : Intersections with boundaries less than the
|
||||
// tolerance must be ignored if the direction
|
||||
// is away from the boundary
|
||||
|
||||
G4int a;
|
||||
|
||||
// Set the surfaces to active again
|
||||
Reset();
|
||||
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
G4Vector3D Pttmp(Pt);
|
||||
G4Vector3D Vtmp(V);
|
||||
G4Ray r(Pttmp, Vtmp);
|
||||
|
||||
// Test if the bounding box of each surface is intersected
|
||||
// by the ray. If not, the surface become deactive.
|
||||
TestSurfaceBBoxes(r);
|
||||
QuickSort(SurfaceVec, 0, nb_of_surfaces-1);
|
||||
|
||||
ShortestDistance = kInfinity;
|
||||
|
||||
for(int a=0; a< nb_of_surfaces;a++)
|
||||
for(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)
|
||||
{
|
||||
// test if the ray intersect the surface
|
||||
if( (SurfaceVec[a]->Intersect(r)) )
|
||||
{
|
||||
// if more than 1 surface is intersected,
|
||||
// take the nearest one
|
||||
if( SurfaceVec[a]->Distance() < ShortestDistance )
|
||||
if( SurfaceVec[a]->Distance() > halfTolerance )
|
||||
{
|
||||
ShortestDistance = SurfaceVec[a]->Distance();
|
||||
}
|
||||
else
|
||||
{
|
||||
G4ThreeVector Norm = SurfaceVec[a]->SurfaceNormal(Pttmp);
|
||||
|
||||
if((Norm * Vtmp)<0)
|
||||
// the point is within the boundary
|
||||
// ignored it if the direction is away from the boundary
|
||||
G4Vector3D Norm = SurfaceVec[a]->SurfaceNormal(Pttmp);
|
||||
|
||||
if( (Norm * Vtmp) < 0 )
|
||||
ShortestDistance = SurfaceVec[a]->Distance();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Be carreful !
|
||||
// SurfaceVec->Distance is in fact the squared distance
|
||||
if(ShortestDistance != kInfinity)
|
||||
return sqrt(ShortestDistance);
|
||||
|
||||
return kInfinity;
|
||||
else
|
||||
// no intersection, return kInfinity
|
||||
return kInfinity;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidPolyhedra::DistanceToOut(register const G4ThreeVector& Pt,
|
||||
register const G4ThreeVector& V,
|
||||
const G4bool calcNorm,
|
||||
G4bool *validNorm,
|
||||
G4ThreeVector *n) const
|
||||
G4double G4BREPSolidPolyhedra::DistanceToOut(register const G4ThreeVector& Pt,
|
||||
register const G4ThreeVector& V,
|
||||
const G4bool calcNorm,
|
||||
G4bool *validNorm,
|
||||
G4ThreeVector *n ) const
|
||||
{
|
||||
// Calculates the distance from a point inside the solid
|
||||
// to the solid`s boundary along a specified direction vector.
|
||||
// Return 0 if the point is already outside (even number of
|
||||
// intersections greater than the tolerance).
|
||||
//
|
||||
// Note : If the shortest distance to a boundary is less
|
||||
// than the tolerance, it is ignored. This allows
|
||||
// for a point within a tolerant boundary to leave
|
||||
// immediately
|
||||
|
||||
G4int parity = 0;
|
||||
|
||||
// Set the surfaces to active again
|
||||
Reset();
|
||||
|
||||
const G4double halfTolerance = kCarTolerance*0.5;
|
||||
G4Vector3D Ptv = Pt;
|
||||
G4int a;
|
||||
|
||||
// I don`t understand this line
|
||||
if(validNorm)
|
||||
*validNorm = false;
|
||||
*validNorm=false;
|
||||
|
||||
Reset();
|
||||
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
G4Point3D Pttmp(Pt);
|
||||
G4Vector3D Pttmp(Pt);
|
||||
G4Vector3D Vtmp(V);
|
||||
|
||||
// G4double kInfinity = 10e20;
|
||||
G4Ray r(Pttmp, Vtmp);
|
||||
|
||||
// Test if the bounding box of each surface is intersected
|
||||
// by the ray. If not, the surface become deactive.
|
||||
TestSurfaceBBoxes(r);
|
||||
QuickSort(SurfaceVec, 0, nb_of_surfaces-1);
|
||||
ShortestDistance = kInfinity;
|
||||
|
||||
for(int a=0; a< nb_of_surfaces;a++)
|
||||
ShortestDistance = kInfinity; // this is actually the square of the distance
|
||||
|
||||
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();
|
||||
{
|
||||
// test if the ray intersects the surface
|
||||
if( (SurfaceVec[a]->Intersect(r)) )
|
||||
{
|
||||
parity += 1;
|
||||
|
||||
// if more than 1 surface is intersected,
|
||||
// take the nearest one
|
||||
if( SurfaceVec[a]->Distance() < ShortestDistance )
|
||||
if( SurfaceVec[a]->Distance() > halfTolerance*halfTolerance )
|
||||
{
|
||||
ShortestDistance = SurfaceVec[a]->Distance();
|
||||
}
|
||||
else
|
||||
{
|
||||
// the point is within the boundary: ignore it
|
||||
parity -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(ShortestDistance != kInfinity)
|
||||
|
||||
// Be carreful !
|
||||
// SurfaceVec->Distance is in fact the squared distance
|
||||
if((ShortestDistance != kInfinity) && (parity&1))
|
||||
return sqrt(ShortestDistance);
|
||||
|
||||
return kInfinity;
|
||||
else
|
||||
// if no intersection is found, the point is outside
|
||||
// so return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
G4double G4BREPSolidPolyhedra::DistanceToOut(const G4ThreeVector& Pt) const
|
||||
{
|
||||
G4double Dist=kInfinity;
|
||||
G4double tmpdist=kInfinity;
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
// Calculates the shortest distance ("safety") from a point
|
||||
// inside the solid to any boundary of this solid.
|
||||
// Return 0 if the point is already outside.
|
||||
|
||||
G4double *dists = new G4double[nb_of_surfaces];
|
||||
G4double halfTolerance = kCarTolerance*0.5;
|
||||
G4int a;
|
||||
|
||||
// Set the surfaces to active again
|
||||
Reset();
|
||||
|
||||
for(int a=0; a< nb_of_surfaces;a++)
|
||||
{
|
||||
tmpdist = fabs(SurfaceVec[a]->HowNear(Pt));
|
||||
// calcul of the shortest distance of the point to each surfaces
|
||||
// Be carreful : it's a signed value
|
||||
for(a=0; a< nb_of_surfaces; a++)
|
||||
dists[a] = SurfaceVec[a]->HowNear(Pt);
|
||||
|
||||
G4double Dist = kInfinity;
|
||||
|
||||
if(Dist>tmpdist && tmpdist> halfTolerance)
|
||||
Dist = tmpdist;
|
||||
}
|
||||
// if dists[] is negative, the point is inside
|
||||
// so take the shortest of the shortest negative distances
|
||||
// dists[] can be equal to 0 : point on a surface
|
||||
// ( Problem with the G4FPlane : there is no inside and no outside...
|
||||
// So, to test if the point is outside to return 0, utilize the Inside
|
||||
// function. But I don`t know if it is really needed because dToOut is
|
||||
// called only if the point is inside )
|
||||
|
||||
for(a = 0; a < nb_of_surfaces; a++)
|
||||
if( fabs(Dist) > fabs(dists[a]) )
|
||||
//if( dists[a] <= 0)
|
||||
Dist = dists[a];
|
||||
|
||||
return Dist;
|
||||
delete[] dists;
|
||||
|
||||
if(Dist == kInfinity)
|
||||
// the point is ouside the solid or on a surface
|
||||
return 0;
|
||||
else
|
||||
// return Dist;
|
||||
return fabs(Dist);
|
||||
}
|
||||
|
||||
|
||||
@@ -479,6 +641,3 @@ G4Polyhedron* G4BREPSolidPolyhedra::CreatePolyhedron() const
|
||||
original_parameters.Rmin,
|
||||
original_parameters.Rmax);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4BREPSolidSphere.cc,v 1.1 1999/01/07 16:07:39 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
|
||||
#include "G4BREPSolidSphere.hh"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4BREPSolidTorus.cc,v 1.1 1999/01/07 16:07:39 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
#include "G4BREPSolidTorus.hh"
|
||||
#include "G4ToroidalSurface.hh"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4BSplineCurve.cc,v 1.1 1999/01/07 16:07:39 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
#include "G4BSplineCurve.hh"
|
||||
#include "G4ControlPoints.hh"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4BSplineCurveWithKnots.cc,v 1.1 1999/01/07 16:07:39 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
#include "G4BSplineCurveWithKnots.hh"
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4BSplineSurface.cc,v 1.2 1999/05/20 17:39:21 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
|
||||
#include "EntityInst.h"
|
||||
@@ -312,7 +312,7 @@ void G4BSplineSurface::FindIntersections(const G4Ray& rayref)
|
||||
|
||||
// Loop through the bezier List
|
||||
G4BezierSurface* bez_ptr;
|
||||
distance = INFINITY;
|
||||
distance = kInfinity;
|
||||
|
||||
while(bezier_list.index != (G4Surface*)0)
|
||||
{
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// based on the Program) you indicate your acceptance of this statement,
|
||||
// and all its terms.
|
||||
//
|
||||
// $Id: G4BezierSurface.cc,v 2.8 1998/11/24 16:41:24 broglia Exp $
|
||||
// GEANT4 tag $Name: geant4-00 $
|
||||
// $Id: G4BezierSurface.cc,v 1.1 1999/01/07 16:07:40 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
// L. Broglia, 10/10/98
|
||||
// Error in line 331 and replaced addition of coordinates by
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
// 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"
|
||||
|
||||
@@ -311,6 +311,21 @@ G4double G4BoundingBox3D::DistanceToIn(const G4Point3D& p,
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
G4int G4BoundingBox3D::Inside(const G4Point3D& Pt)
|
||||
{
|
||||
if( ( Pt.x() >= box_min.x() && Pt.x() <= box_max.x() ) &&
|
||||
( Pt.y() >= box_min.y() && Pt.y() <= box_max.y() ) &&
|
||||
( Pt.z() >= box_min.z() && Pt.z() <= box_max.z() ) )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4CircularCurve.cc,v 1.1 1999/01/07 16:07:41 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
|
||||
#include "G4CircularCurve.hh"
|
||||
|
||||
@@ -45,7 +45,7 @@ G4Curve* G4CompositeCurve::Project(const G4Transform3D& tr)
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void G4CompositeCurve::IntersectRay2D(const G4Ray& ray,
|
||||
G4CurveRayIntersection& is)
|
||||
{
|
||||
@@ -62,7 +62,26 @@ void G4CompositeCurve::IntersectRay2D(const G4Ray& ray,
|
||||
|
||||
lastIntersection= is;
|
||||
}
|
||||
*/
|
||||
|
||||
G4int G4CompositeCurve::IntersectRay2D(const G4Ray& ray)
|
||||
{
|
||||
G4int nbinter = 0, temp = 0;
|
||||
|
||||
for (G4int i=0; i<segments.entries(); i++)
|
||||
{
|
||||
G4Curve& c= *(segments(i));
|
||||
temp = c.IntersectRay2D(ray);
|
||||
|
||||
// test if the point is on the composite curve
|
||||
if( temp==999 )
|
||||
return 999;
|
||||
else
|
||||
nbinter+= temp;
|
||||
}
|
||||
|
||||
return nbinter;
|
||||
}
|
||||
|
||||
G4bool G4CompositeCurve::Tangent(G4CurvePoint& cp, G4Vector3D& v)
|
||||
{
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4ConicalSurface.cc,v 1.1 1999/01/07 16:07:41 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
/* /usr/local/gismo/repo/geometry/G4ConicalSurface.cc,v 1.6 1994/08/03 17:15:01 burnett Exp */
|
||||
// File: G4ConicalSurface.cc
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4ControlPoints.cc,v 1.1 1999/01/07 16:07:41 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
//
|
||||
// Modif 8 oct 98 : A.Floquet
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4Curve.cc,v 1.1 1999/01/07 16:07:41 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
#include "G4Curve.hh"
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4CylindricalSurface.cc,v 1.1 1999/01/07 16:07:42 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
/* /usr/local/gismo/repo/geometry/G4CylindricalSurface.cc,v 1.24 1994/08/03 17:15:09 burnett Exp */
|
||||
// File: G4CylindricalSurface.cc
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4Ellipse.cc,v 1.1 1999/01/07 16:07:42 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
|
||||
#include "G4Ellipse.hh"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4FConicalSurface.cc,v 1.8 1999/05/19 16:57:11 magni Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
/* /usr/local/gismo/repo/geometry/G4FConicalSurface.cc,v 1.2 1993/02/05 00:38:39 alanb Exp */
|
||||
// File: G4FConicalSurface.cc
|
||||
@@ -27,6 +27,7 @@
|
||||
//
|
||||
// End ---------------------------------------------------------------
|
||||
|
||||
|
||||
#include "G4FConicalSurface.hh"
|
||||
#include "G4Sort.hh"
|
||||
#include "G4CircularCurve.hh"
|
||||
@@ -37,25 +38,20 @@ G4FConicalSurface::G4FConicalSurface(const G4Point3D& o,
|
||||
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
|
||||
// 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
|
||||
// Create the position with origin o, axis a, and a direction
|
||||
|
||||
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
|
||||
@@ -255,234 +251,152 @@ void G4FConicalSurface::resize( G4double l, G4double sr, G4double lr )
|
||||
|
||||
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;
|
||||
// This function count the number of intersections of a
|
||||
// bounded conical surface by a ray.
|
||||
// At first, calculates the intersections with the semi-infinite
|
||||
// conical surfsace. After, count the intersections within the
|
||||
// finite conical surface boundaries, and set "distance" to the
|
||||
// closest distance from the start point to the nearest intersection
|
||||
// If the point is on the surface it returns or the intersection with
|
||||
// the opposite surface or kInfinity
|
||||
// If no intersection is founded, set distance = kInfinity and
|
||||
// return 0
|
||||
|
||||
G4Vector3D lv ( FLT_MAXX, FLT_MAXX, FLT_MAXX );
|
||||
closest_hit = lv;
|
||||
distance = kInfinity;
|
||||
closest_hit = PINFINITY;
|
||||
|
||||
// Origin and G4Vector3D unit vector of Ray.
|
||||
|
||||
G4Vector3D x = ry.GetStart();
|
||||
// origin and direction of the ray
|
||||
G4Point3D x = ry.GetStart();
|
||||
G4Vector3D dhat = ry.GetDir();
|
||||
|
||||
// Cone angle and axis unit vector.
|
||||
G4double ta = tan_angle;
|
||||
// cone angle and axis
|
||||
G4double ta = tan_angle;
|
||||
G4Vector3D ahat = Position.GetAxis();
|
||||
int isoln = 0, maxsoln = 2;
|
||||
|
||||
// array of solutions in distance along the Ray
|
||||
// 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)
|
||||
|
||||
// calculate the two intersections (quadratic equation)
|
||||
G4Vector3D gamma = x - Position.GetLocation();
|
||||
|
||||
G4double T = 1.0 + ta * ta;
|
||||
G4double t = 1 + 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
|
||||
G4double A = t * da * da - dhat * dhat;
|
||||
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 );
|
||||
|
||||
G4double radical = B * B - 4.0 * A * C;
|
||||
|
||||
// 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
|
||||
if ( radical < 0.0 )
|
||||
// no intersection
|
||||
return 0;
|
||||
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 );
|
||||
}
|
||||
G4double root = sqrt( radical );
|
||||
s[0] = ( - B + root ) / ( 2. * A );
|
||||
s[1] = ( - B - root ) / ( 2. * A );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// validity of the solutions
|
||||
// the hit point must be into the bounding box of the conical surface
|
||||
G4Point3D p0 = x + s[0]*dhat;
|
||||
G4Point3D p1 = x + s[1]*dhat;
|
||||
|
||||
if( !GetBBox()->Inside(p0) )
|
||||
s[0] = kInfinity;
|
||||
|
||||
// order the possible solutions by increasing distance along the Ray
|
||||
// (G4Sorting routines are in support/G4Sort.h)
|
||||
G4Sort_double( s, isoln, maxsoln-1 );
|
||||
if( !GetBBox()->Inside(p1) )
|
||||
s[1] = kInfinity;
|
||||
|
||||
// now loop over each positive solution, keeping the first one (smallest
|
||||
// distance along the ray) which is within the boundary of the sub-shape
|
||||
G4int nbinter = 0;
|
||||
distance = kInfinity;
|
||||
|
||||
// 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;
|
||||
}
|
||||
for ( G4int i = 0; i < 2; i++ )
|
||||
{
|
||||
if(s[i] < kInfinity) {
|
||||
if ( (s[i] > kCarTolerance*0.5) ) {
|
||||
nbinter++;
|
||||
if ( distance > (s[i]*s[i]) ) {
|
||||
distance = s[i]*s[i];
|
||||
}
|
||||
}
|
||||
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;
|
||||
return nbinter;
|
||||
}
|
||||
|
||||
|
||||
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.
|
||||
// Shortest distance from the point x to the G4FConicalSurface.
|
||||
// The distance will be always positive
|
||||
// This function works only with Cone axis equal (0,0,1) or (0,0,-1), it project
|
||||
// the surface and the point on the x,z plane and compute the distance in analytical
|
||||
// way
|
||||
|
||||
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);
|
||||
G4Vector3D upcorner = G4Vector3D ( small_radius, 0 , origin.z()+Position.GetAxis().z()*length);
|
||||
G4Vector3D downcorner = G4Vector3D ( large_radius, 0 , origin.z());
|
||||
G4Vector3D xd;
|
||||
|
||||
xd = G4Vector3D ( sqrt ( x.x()*x.x() + x.y()*x.y() ) , 0 , x.z() );
|
||||
|
||||
G4double m = (upcorner.z() - downcorner.z()) / (upcorner.x() - downcorner.x());
|
||||
G4double q = (downcorner.z()*upcorner.x() - upcorner.z()*downcorner.x()) /
|
||||
(upcorner.x() - downcorner.x());
|
||||
|
||||
G4double Zinter = (xd.z()*m*m + xd.x()*m +q)/(1+m*m) ;
|
||||
|
||||
if ( ((Zinter >= downcorner.z()) && (Zinter <=upcorner.z())) ||
|
||||
((Zinter >= upcorner.z()) && (Zinter <=downcorner.z())) ) {
|
||||
hownear = fabs(m*xd.x()-xd.z()+q)/sqrt(1+m*m);
|
||||
return hownear;
|
||||
} else {
|
||||
hownear = min ( (xd-upcorner).mag() , (xd-downcorner).mag() );
|
||||
return hownear;
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
G4Vector3D s = p - origin;
|
||||
G4double da = s * Position.GetAxis();
|
||||
G4double r = sqrt( s*s - da*da);
|
||||
G4double z = tan_angle * r;
|
||||
|
||||
// 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 (Position.GetAxis().z() < 0)
|
||||
z = -z;
|
||||
|
||||
if ( ap == 0.0 )
|
||||
return G4Vector3D( 1.0, 0.0, 0.0 );
|
||||
else
|
||||
return G4Vector3D( ay / ap, -ax / ap, 0.0 );
|
||||
}
|
||||
G4Vector3D n(p.x(), p.y(), z);
|
||||
n = n.unit();
|
||||
|
||||
if( !sameSense )
|
||||
n = -n;
|
||||
|
||||
// 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4FCylindricalSurface.cc,v 1.8 1999/05/27 10:44:55 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
/* /usr/local/gismo/repo/geometry/FG4Cylinder.cc,v 1.1 1992/10/27 22:02:29 alanb Exp */
|
||||
// File: FG4Cylinder.cc
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "G4Sort.hh"
|
||||
|
||||
|
||||
|
||||
G4FCylindricalSurface::G4FCylindricalSurface( const G4Point3D& o,
|
||||
const G4Vector3D& a,
|
||||
const G4double r,
|
||||
@@ -39,11 +40,11 @@ G4FCylindricalSurface::G4FCylindricalSurface( const G4Point3D& o,
|
||||
// radius r, and length l
|
||||
G4Vector3D dir(1,1,1);
|
||||
Position.Init(dir, a, o);
|
||||
origin = o;
|
||||
|
||||
origin = o;
|
||||
radius = r;
|
||||
|
||||
// Require length to be positive or zero
|
||||
// if ( l > 0.0 )
|
||||
if ( l >= 0.0 )
|
||||
length = l;
|
||||
else
|
||||
@@ -66,7 +67,6 @@ G4FCylindricalSurface::G4FCylindricalSurface( const G4Point3D& o,
|
||||
|
||||
radius = 0.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -137,150 +137,114 @@ void G4FCylindricalSurface::CalcBBox()
|
||||
|
||||
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.
|
||||
// This function count the number of intersections of a
|
||||
// bounded cylindrical surface by a ray.
|
||||
// At first, calculates the intersections with the infinite
|
||||
// cylindrical surfsace. After, count the intersections within the
|
||||
// finite cylindrical surface boundaries, and set "distance" to the
|
||||
// closest distance from the start point to the nearest intersection
|
||||
// If the point is on the surface it returns or the intersection with
|
||||
// the opposite surface or kInfinity
|
||||
|
||||
// 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;
|
||||
// If no intersection is founded, set distance = kInfinity and
|
||||
// return 0
|
||||
|
||||
// Origin and G4Vector3D unit vector of Ray.
|
||||
G4Vector3D x = ry.GetStart();
|
||||
distance = kInfinity;
|
||||
closest_hit = PINFINITY;
|
||||
|
||||
// origin and direction of the ray
|
||||
G4Point3D 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
|
||||
// cylinder axis
|
||||
G4Vector3D ahat = Position.GetAxis();
|
||||
|
||||
// array of solutions in distance along the ray
|
||||
G4double s[2];
|
||||
s[0] = -1.0;
|
||||
s[1] = -1.0 ;
|
||||
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;
|
||||
// calculate the two intersections (quadratic equation)
|
||||
G4Vector3D gamma = x - Position.GetLocation();
|
||||
|
||||
if ( a <= 0.0 )
|
||||
return 0;
|
||||
|
||||
G4double b = 2. * ( d * dhat - da * dira );
|
||||
G4double c = rsq - qsq;
|
||||
G4double radical = b * b + 4. * a * c;
|
||||
|
||||
G4double ga = gamma * ahat;
|
||||
G4double da = dhat * ahat;
|
||||
|
||||
G4double A = da * da - dhat * dhat;
|
||||
G4double B = 2 * ( -gamma * dhat + ga * da );
|
||||
G4double C = -gamma * gamma + ga * ga + radius * radius ;
|
||||
|
||||
G4double radical = B * B - 4.0 * A * C;
|
||||
|
||||
if ( radical < 0.0 )
|
||||
// no intersection
|
||||
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++ )
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
G4double root = sqrt( radical );
|
||||
s[0] = ( - B + root ) / ( 2. * A );
|
||||
s[1] = ( - B - root ) / ( 2. * A );
|
||||
}
|
||||
|
||||
// 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;
|
||||
// validity of the solutions
|
||||
// the hit point must be into the bounding box of the cylindrical surface
|
||||
G4Point3D p0 = x + s[0]*dhat;
|
||||
G4Point3D p1 = x + s[1]*dhat;
|
||||
|
||||
if( !GetBBox()->Inside(p0) )
|
||||
s[0] = kInfinity;
|
||||
|
||||
if( !GetBBox()->Inside(p1) )
|
||||
s[1] = kInfinity;
|
||||
|
||||
// now loop over each positive solution, keeping the first one (smallest
|
||||
// distance along the Ray) which is within the boundary of the sub-shape
|
||||
G4int nbinter = 0;
|
||||
distance = kInfinity;
|
||||
|
||||
for ( G4int i = 0; i < 2; i++ )
|
||||
{
|
||||
if(s[i] < kInfinity) {
|
||||
if ( s[i] >= kCarTolerance*0.5 ) {
|
||||
nbinter ++;
|
||||
// real intersection
|
||||
// set the distance if it is the smallest
|
||||
if( distance > s[i]*s[i]) {
|
||||
distance = s[i]*s[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nbinter;
|
||||
}
|
||||
|
||||
|
||||
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.
|
||||
// Shortest distance from the point x to the G4FCylindricalSurface.
|
||||
// The distance will be always positive
|
||||
|
||||
G4Vector3D d = x - origin;
|
||||
G4double dA = d * Position.GetAxis();
|
||||
G4double rad = sqrt( d.mag2() - dA*dA );
|
||||
G4double hownear;
|
||||
G4double hownear;
|
||||
|
||||
G4Vector3D upcorner = G4Vector3D ( radius, 0 , origin.z()+length);
|
||||
G4Vector3D downcorner = G4Vector3D ( radius, 0 , origin.z());
|
||||
G4Vector3D xd;
|
||||
|
||||
xd = G4Vector3D ( sqrt ( x.x()*x.x() + x.y()*x.y() ) , 0 , x.z() );
|
||||
|
||||
|
||||
G4double Zinter = (xd.z()) ;
|
||||
|
||||
if ( ((Zinter >= downcorner.z()) && (Zinter <=upcorner.z())) ) {
|
||||
hownear = fabs( radius - xd.x() );
|
||||
} else {
|
||||
hownear = min ( (xd-upcorner).mag() , (xd-downcorner).mag() );
|
||||
}
|
||||
|
||||
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
|
||||
@@ -315,6 +279,9 @@ G4Vector3D G4FCylindricalSurface::SurfaceNormal( const G4Point3D& p ) const
|
||||
|
||||
if ( nmag != 0.0 )
|
||||
n = n * (1/nmag);
|
||||
|
||||
if( !sameSense )
|
||||
n = -n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -5,10 +5,16 @@
|
||||
// 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 $
|
||||
// $Id: G4FPlane.cc,v 1.6 1999/06/08 11:22:07 sgiani Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
|
||||
// Corrections by S.Giani:
|
||||
// - The constructor using iVec now properly stores both the internal and
|
||||
// external boundaries in the bounds vector.
|
||||
// - Proper initialization of sameSense in both the constructors.
|
||||
// - Addition of third argument (sense) in the second constructor to ensure
|
||||
// consistent setting of the normal in all the client code.
|
||||
// - Proper use of the tolerance in the Intersect function.
|
||||
|
||||
#include "G4FPlane.hh"
|
||||
#include "G4CompositeCurve.hh"
|
||||
@@ -25,15 +31,17 @@ G4FPlane::G4FPlane( const G4Vector3D& direction,
|
||||
G4Point3D Pt2 = Pt0 + axis.cross(direction);
|
||||
|
||||
G4Ray::CalcPlane3Pts( Pl, Pt0, Pt1, Pt2 );
|
||||
|
||||
|
||||
active = 1;
|
||||
sameSense = 1;
|
||||
CalcNormal();
|
||||
distance = kInfinity;
|
||||
Type = 1;
|
||||
}
|
||||
|
||||
|
||||
G4FPlane::G4FPlane(const G4Point3DVector* pVec, const G4Point3DVector* iVec)
|
||||
G4FPlane::G4FPlane(const G4Point3DVector* pVec, const G4Point3DVector* iVec, int
|
||||
sense)
|
||||
: pplace( (*pVec)[0]-(*pVec)[1], // direction
|
||||
((*pVec)[pVec->length()-1]-(*pVec)[0])
|
||||
.cross((*pVec)[0]-(*pVec)[1]), // axis
|
||||
@@ -46,18 +54,38 @@ G4FPlane::G4FPlane(const G4Point3DVector* pVec, const G4Point3DVector* iVec)
|
||||
G4CompositeCurve* polygon;
|
||||
|
||||
projectedBoundary = new G4SurfaceBoundary;
|
||||
|
||||
|
||||
sameSense = sense;
|
||||
|
||||
// Outer boundary
|
||||
|
||||
polygon= new G4CompositeCurve(*pVec);
|
||||
|
||||
for (G4int i=0; i< polygon->GetSegments().length(); i++)
|
||||
polygon->GetSegments()[i]->SetSameSense(sameSense);
|
||||
|
||||
bounds.insert(polygon);
|
||||
|
||||
// Eventual inner boundary
|
||||
|
||||
if (iVec)
|
||||
{
|
||||
polygon= new G4CompositeCurve(*iVec);
|
||||
|
||||
for (G4int i=0; i< polygon->GetSegments().length(); i++)
|
||||
polygon->GetSegments()[i]->SetSameSense(sameSense);
|
||||
|
||||
bounds.insert(polygon);
|
||||
}
|
||||
|
||||
SetBoundaries(&bounds);
|
||||
// Set sense for boundaries
|
||||
|
||||
for (G4int j=0; j< bounds.length(); j++)
|
||||
bounds[j]->SetSameSense(sameSense);
|
||||
|
||||
|
||||
SetBoundaries(&bounds);
|
||||
|
||||
CalcNormal();
|
||||
IsConvex();
|
||||
distance = kInfinity;
|
||||
@@ -147,10 +175,12 @@ int G4FPlane::IsConvex()
|
||||
|
||||
int G4FPlane::Intersect(const G4Ray& rayref)
|
||||
{
|
||||
Intersected =1;
|
||||
// This function count the number of intersections of a
|
||||
// bounded surface by a ray.
|
||||
|
||||
|
||||
// closest_hit = pplace.EvaluateIntersection(rayref);
|
||||
// L. Broglia : before in G4Placement
|
||||
// Find the intersection with the infinite plane
|
||||
Intersected =1;
|
||||
|
||||
// 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
|
||||
@@ -170,9 +200,9 @@ int G4FPlane::Intersect(const G4Ray& rayref)
|
||||
|
||||
b = norm.x() * dirx + norm.y() * diry + norm.z() * dirz;
|
||||
|
||||
if ( fabs(b) < 0.001 )
|
||||
if ( fabs(b) < perMillion )
|
||||
{
|
||||
// G4cout << "\nLine is parallel to G4Plane.No Hit.";
|
||||
// G4cout << "\nLine is parallel to G4Plane.No Hit.";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -192,12 +222,21 @@ int G4FPlane::Intersect(const G4Ray& rayref)
|
||||
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);
|
||||
|
||||
// solve tolerance problem
|
||||
if( (t*dirx >= -kCarTolerance/2) && (t*dirx <= kCarTolerance/2) )
|
||||
solx = startx;
|
||||
|
||||
if( (t*diry >= -kCarTolerance/2) && (t*diry <= kCarTolerance/2) )
|
||||
soly = starty;
|
||||
|
||||
if( (t*dirz >= -kCarTolerance/2) && (t*dirz <= kCarTolerance/2) )
|
||||
solz = startz;
|
||||
|
||||
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
|
||||
@@ -205,70 +244,59 @@ int G4FPlane::Intersect(const G4Ray& rayref)
|
||||
|
||||
if(closest_hit.x() == kInfinity)
|
||||
{
|
||||
// no hit
|
||||
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;
|
||||
}
|
||||
// calculate the squared distance from the point to the intersection
|
||||
// and set it in the distance data member (all clients know they have
|
||||
// to take the sqrt)
|
||||
Distance( RayStart.distance2(closest_hit) );
|
||||
|
||||
G4Point3D hit = closest_hit;
|
||||
// now, we have to verify that the hit point founded
|
||||
// is included into the G4FPlane boundaries
|
||||
|
||||
// project the hit to the xy plane,
|
||||
// with the same projection that took the boundary
|
||||
// into projectedBoundary
|
||||
G4Point3D projectedHit= pplace.GetToPlacementCoordinates() * hit;
|
||||
G4Point3D projectedHit= pplace.GetToPlacementCoordinates() * closest_hit;
|
||||
|
||||
// test ray from the hit on the xy plane
|
||||
G4Ray testRay( projectedHit, G4Vector3D(1, 0.01, 0) );
|
||||
|
||||
// check if it intersects the boundary
|
||||
G4Ray testRay(projectedHit, G4Vector3D(1, 0, 0));
|
||||
G4int nbinter = projectedBoundary->IntersectRay2D(testRay);
|
||||
|
||||
G4CurveRayIntersection is;
|
||||
projectedBoundary->IntersectRay2D(testRay, is);
|
||||
|
||||
// if not, we are outside
|
||||
if ( is.GetDistance() >= kInfinity )
|
||||
// If this number is par, it`s signify that the projected point
|
||||
// is outside the projected surface, so the hit point is outside
|
||||
// the bounded surface
|
||||
if(nbinter&1)
|
||||
{
|
||||
// the intersection point is into the boundaries
|
||||
// check if the intersection point is on the surface
|
||||
if(distance <= kCarTolerance*0.5*kCarTolerance*0.5)
|
||||
{
|
||||
// the point is on the surface, set the distance to 0
|
||||
Distance(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the point is outside the surface
|
||||
}
|
||||
|
||||
return 1 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the intersection point is out the boundaries
|
||||
// it is not a real intersection
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,7 +306,9 @@ 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);
|
||||
G4double dist = Pt.x()*Pl.a + Pt.y()*Pl.b + Pt.z()*Pl.c - Pl.d;
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
|
||||
@@ -290,15 +320,11 @@ void G4FPlane::InitBounded()
|
||||
surfaceBoundary.Project( pplace.GetToPlacementCoordinates() );
|
||||
}
|
||||
|
||||
G4double G4FPlane::HowNear( const G4Vector3D& x ) const
|
||||
G4double G4FPlane::HowNear( const G4Vector3D& Pt ) 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);
|
||||
G4double hownear = Pt.x()*Pl.a + Pt.y()*Pl.b + Pt.z()*Pl.c - Pl.d;
|
||||
|
||||
return hownear;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4Hyperbola.cc,v 1.1 1999/01/07 16:07:43 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
|
||||
#include "G4Hyperbola.hh"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4KnotVector.cc,v 1.1 1999/01/07 16:07:43 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
|
||||
#include "G4KnotVector.hh"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4Line.cc,v 1.3 1999/05/20 09:35:35 sgiani Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
#include "G4Line.hh"
|
||||
|
||||
@@ -17,15 +17,22 @@ G4Curve* G4Line::Project(const G4Transform3D& tr)
|
||||
{
|
||||
G4Vector3D newDir= tr*dir;
|
||||
|
||||
if (abs(newDir.x())+abs(newDir.y()) < kCarTolerance)
|
||||
return 0;
|
||||
if (abs(newDir.x())+abs(newDir.y()) < kCarTolerance){
|
||||
|
||||
newDir.setX(kCarTolerance);
|
||||
newDir.setY(kCarTolerance);
|
||||
};
|
||||
|
||||
G4Point3D newPnt= tr*pnt;
|
||||
newDir.setZ(0);
|
||||
newPnt.setZ(0);
|
||||
|
||||
G4Line* r= new G4Line();
|
||||
r->Init(newDir, newPnt);
|
||||
|
||||
// L. Broglia : terrible mistake !!!!
|
||||
//r->Init(newDir, newPnt);
|
||||
r->Init(newPnt, newDir);
|
||||
|
||||
r->SetBounds(GetPStart(), GetPEnd());
|
||||
|
||||
return r;
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4NISTStepReader.cc,v 1.1 1999/01/07 16:07:44 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
#include "G4NISTStepReader.hh"
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4OsloMatrix.cc,v 1.1 1999/01/07 16:07:44 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
|
||||
#include "G4OsloMatrix.hh"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4Parabola.cc,v 1.1 1999/01/07 16:07:44 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
#include "G4Parabola.hh"
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4PlacedSolid.cc,v 1.1 1999/01/07 16:07:44 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
#include "G4PlacedSolid.hh"
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4PointRat.cc,v 1.1 1999/01/07 16:07:45 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
//
|
||||
// Modif 8 oct 98 : A.Floquet
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4ProjectedSurface.cc,v 1.2 1999/05/20 17:39:22 japost Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
#include "G4ProjectedSurface.hh"
|
||||
|
||||
@@ -90,10 +90,10 @@ void G4ProjectedSurface::CalcBBox()
|
||||
// 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;
|
||||
box_minx = kInfinity;
|
||||
box_miny = kInfinity;
|
||||
box_maxx = -kInfinity;
|
||||
box_maxy = -kInfinity;
|
||||
|
||||
G4double bminx,bminy,bmaxx,bmaxy,tmpx,tmpy;
|
||||
bminx = box_minx; bminy = box_miny;
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4Ray.cc,v 1.1 1999/01/07 16:07:45 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
#include "G4Ray.hh"
|
||||
#include "G4PointRat.hh"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4RectangularTrimmedSurface.cc,v 1.1 1999/01/07 16:07:45 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
#include "SdaiCONFIG_CONTROL_DESIGN.h"
|
||||
#include "G4RectangularTrimmedSurface.hh"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4Sort.cc,v 1.1 1999/01/07 16:07:46 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
// File: G4Sort.cc
|
||||
// Author: Alan Breakstone
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4SphericalSurface.cc,v 1.1 1999/01/07 16:07:46 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
/* $Header: /private/Net/unixhub/u1/ea/liml/gismo/gismo-0.2/geometry/RCS/G4SphericalSurface.cc,v 1.10 1992/08 */
|
||||
// File: G4SphericalSurface.cc
|
||||
|
||||
@@ -125,7 +125,7 @@ G4double G4Surface::ClosestDistanceToPoint(const G4Point3D& Pt)
|
||||
// Be carreful ! pointdistance is the squared distance
|
||||
return sqrt(pointDistance);
|
||||
|
||||
// G4double PointDistance=INFINITY;
|
||||
// G4double PointDistance=kInfinity;
|
||||
// G4double TmpDistance=0;
|
||||
// PointDistance = OuterBoundary->ClosestDistanceToPoint(Pt);
|
||||
// TmpDistance =0;
|
||||
@@ -138,7 +138,7 @@ G4double G4Surface::ClosestDistanceToPoint(const G4Point3D& Pt)
|
||||
|
||||
//G4double G4Boundary::ClosestDistanceToPoint(const G4ThreeVec& Pt)
|
||||
//{
|
||||
// G4double PointDistance = INFINITY;
|
||||
// G4double PointDistance = kInfinity;
|
||||
// G4double TmpDistance = 0;
|
||||
// for(int a =0; a < NumberOfPoints;a++)
|
||||
// {
|
||||
|
||||
@@ -98,7 +98,7 @@ G4SurfaceBoundary* G4SurfaceBoundary::Project(const G4Transform3D& tr)
|
||||
return lof;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void G4SurfaceBoundary::IntersectRay2D(const G4Ray& ray,
|
||||
G4CurveRayIntersection& is)
|
||||
{
|
||||
@@ -116,6 +116,26 @@ void G4SurfaceBoundary::IntersectRay2D(const G4Ray& ray,
|
||||
|
||||
lastIntersection= is;
|
||||
}
|
||||
*/
|
||||
|
||||
G4int G4SurfaceBoundary::IntersectRay2D(const G4Ray& ray)
|
||||
{
|
||||
G4int nbinter = 0, temp = 0;
|
||||
|
||||
for (G4int i=0; i < bounds.entries(); i++)
|
||||
{
|
||||
G4Curve& c = *bounds.at(i);
|
||||
temp = c.IntersectRay2D(ray);
|
||||
|
||||
// test if the point is on the surface boundary
|
||||
if( temp==999 )
|
||||
return 1;
|
||||
else
|
||||
nbinter +=temp;
|
||||
}
|
||||
|
||||
return nbinter;
|
||||
}
|
||||
|
||||
|
||||
G4bool G4SurfaceBoundary::Tangent(G4CurvePoint& cp, G4Vector3D& v)
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4SurfaceList.cc,v 1.1 1999/01/07 16:07:47 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
#include "G4SurfaceList.hh"
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4ThreeMat.cc,v 1.1 1999/01/07 16:07:47 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
/* G4ThreeMat.cc,v 1.5 1993/08/02 22:21:27 atwood Exp */
|
||||
// File: G4ThreeMat.cc
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// 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 $
|
||||
// $Id: G4ToroidalSurface.cc,v 1.1 1999/01/07 16:07:48 gunter Exp $
|
||||
// GEANT4 tag $Name: geant4-00-01 $
|
||||
//
|
||||
#include "G4ToroidalSurface.hh"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user