// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // // // $Id: G4BREPSolid.cc,v 1.37 2008/03/13 14:18:57 gcosmo Exp $ // GEANT4 tag $Name: geant4-09-03 $ // // ---------------------------------------------------------------------- // GEANT 4 class source file // // G4BREPSolid.cc // // ---------------------------------------------------------------------- #include "G4BREPSolid.hh" #include "G4VoxelLimits.hh" #include "G4AffineTransform.hh" #include "G4VGraphicsScene.hh" #include "G4Polyhedron.hh" #include "G4NURBSbox.hh" #include "G4BoundingBox3D.hh" #include "G4FPlane.hh" #include "G4BSplineSurface.hh" #include "G4ToroidalSurface.hh" #include "G4SphericalSurface.hh" G4Ray G4BREPSolid::Track; G4double G4BREPSolid::ShortestDistance= kInfinity; G4int G4BREPSolid::NumberOfSolids=0; G4BREPSolid::G4BREPSolid(const G4String& name) : G4VSolid(name), Box(0), Convex(0), AxisBox(0), PlaneSolid(0), place(0), bbox(0), intersectionDistance(kInfinity), active(1), startInside(0), nb_of_surfaces(0), SurfaceVec(0), solidname(name), fStatistics(1000000), fCubVolEpsilon(0.001), fAreaAccuracy(-1.), fCubicVolume(0.), fSurfaceArea(0.), fpPolyhedron(0) { } G4BREPSolid::G4BREPSolid( const G4String& name , G4Surface** srfVec , G4int numberOfSrfs ) : G4VSolid(name), Box(0), Convex(0), AxisBox(0), PlaneSolid(0), place(0), bbox(0), intersectionDistance(kInfinity), active(1), startInside(0), nb_of_surfaces(numberOfSrfs), SurfaceVec(srfVec), fStatistics(1000000), fCubVolEpsilon(0.001), fAreaAccuracy(-1.), fCubicVolume(0.), fSurfaceArea(0.), fpPolyhedron(0) { Initialize(); } G4BREPSolid::G4BREPSolid( __void__& a ) : G4VSolid(a), Box(0), Convex(0), AxisBox(0), PlaneSolid(0), place(0), bbox(0), intersectionDistance(kInfinity), active(1), startInside(0), nb_of_surfaces(0), SurfaceVec(0), fStatistics(1000000), fCubVolEpsilon(0.001), fAreaAccuracy(-1.), fCubicVolume(0.), fSurfaceArea(0.), fpPolyhedron(0) { } G4BREPSolid::~G4BREPSolid() { if(place) delete place; if(bbox) delete bbox; for(G4int a=0;a 0 && SurfaceVec != 0 ) delete [] SurfaceVec; delete fpPolyhedron; } void G4BREPSolid::Initialize() { if(active) { // Compute bounding box for solids and surfaces // Convert concave planes to convex // ShortestDistance= kInfinity; IsBox(); CheckSurfaceNormals(); if(!Box || !AxisBox) IsConvex(); CalcBBoxes(); } } G4String G4BREPSolid::GetEntityType() const { return "Closed_Shell"; } void G4BREPSolid::Reset() const { ((G4BREPSolid*)this)->active=1; ((G4BREPSolid*)this)->intersectionDistance=kInfinity; ((G4BREPSolid*)this)->startInside=0; for(register G4int a=0;aReset(); ShortestDistance = kInfinity; } void G4BREPSolid::CheckSurfaceNormals() { if(!PlaneSolid) return; // All faces must be planar Convex=1; // Checks that the normals of the surfaces point outwards. // If not, turns the Normal to point out. // Loop through each face and check the G4Vector3D of the Normal // G4Surface* srf; G4Point3D V; G4int PointNum=0; G4int SrfNum = 0; G4double YValue=0; G4Point3D Pt; G4int a, b; for(a=0; aGetNumberOfPoints(); for(b =0; bGetPoint(b); if(YValue < Pt.y()) { YValue = Pt.y(); PointNum = b; // Save point number SrfNum = a; // Save srf number } } } // Move the selected face to the first in the List // srf = SurfaceVec[SrfNum]; // Start handling the surfaces in order and compare // the neighbouring ones and turn their normals if they // point inwards // G4Point3D Pt1; G4Point3D Pt2; G4Point3D Pt3; G4Point3D Pt4; G4Vector3D N1; G4Vector3D N2; G4Vector3D N3; G4Vector3D N4; G4int* ConnectedList = new G4int[nb_of_surfaces]; for(a=0; aGetNumberOfPoints(); N1 = (srf->Norm())->GetDir(); for(b=a+1; bGetNumberOfPoints(); for(G4int c=0;cGetPoint(c); for(G4int d=0;dGetPoint(d); if( Pt1 == Pt2 ) { // Common point found. Compare normals. // N2 = ((ConnectedSrf)->Norm())->GetDir(); // Check cross product. // G4Vector3D CP1 = G4Vector3D( N1.cross(N2) ); G4double CrossProd1 = CP1.x()+CP1.y()+CP1.z(); // Create the other normals // if(c==0) Pt3 = srf->GetPoint(c+1); else Pt3 = srf->GetPoint(0); N3 = (Pt1-Pt3); if(d==0) Pt4 = (ConnectedSrf)->GetPoint(d+1); else Pt4 = (ConnectedSrf)->GetPoint(0); N4 = (Pt1-Pt4); G4Vector3D CP2 = G4Vector3D( N3.cross(N4) ); G4double CrossProd2 = CP2.x()+CP2.y()+CP2.z(); G4cout << "\nCroosProd2: " << CrossProd2; if( (CrossProd1 < 0 && CrossProd2 < 0) || (CrossProd1 > 0 && CrossProd2 > 0) ) { // Turn Normal // (ConnectedSrf)->Norm() ->SetDir(-1 * (ConnectedSrf)->Norm()->GetDir()); // Take the CrossProd1 again as the other Normal was turned. // CP1 = N1.cross(N2); CrossProd1 = CP1.x()+CP1.y()+CP1.z(); } if(CrossProd1 > 0) Convex=0; } } } } } delete []ConnectedList; } G4int G4BREPSolid::IsBox() { // This is done by checking that the solid consists of 6 planes. // Then the type is checked to be planar face by face. // For each G4Plane the Normal is computed. The dot product // of one face Normal and each other face Normal is computed. // One result should be 1 and the rest 0 in order to the solid // to be a box. Box=0; G4Surface* srf1, *srf2; register G4int a; // Compute the Normal for the planes // for(a=0; a < nb_of_surfaces;a++) { srf1 = SurfaceVec[a]; if(srf1->MyType()==1) (srf1)->Project(); // Compute the projection else { PlaneSolid=0; return 0; } } // Check that all faces are planar // for(a=0; a < nb_of_surfaces;a++) { srf1 = SurfaceVec[a]; if (srf1->MyType()!=1) return 0; } PlaneSolid = 1; // Check that the amount of faces is correct // if(nb_of_surfaces!=6) return 0; G4Point3D Pt; G4int Points; G4int Sides=0; G4int Opposite=0; srf1 = SurfaceVec[0]; Points = (srf1)->GetNumberOfPoints(); if(Points!=4) return 0; G4Vector3D Normal1 = (srf1->Norm())->GetDir(); G4double Result; for(G4int b=1; b < nb_of_surfaces;b++) { srf2 = SurfaceVec[b]; G4Vector3D Normal2 = ((srf2)->Norm())->GetDir(); Result = std::fabs(Normal1 * Normal2); if((Result != 0) && (Result != 1)) return 0; else { if(!(G4int)Result) Sides++; else if(((G4int)Result) == 1) Opposite++; } } if((Opposite != 1) && (Sides != nb_of_surfaces-2)) return 0; G4Vector3D x_axis(1,0,0); G4Vector3D y_axis(0,1,0); if(((std::fabs(x_axis * Normal1) == 1) && (std::fabs(y_axis * Normal1) == 0)) || ((std::fabs(x_axis * Normal1) == 0) && (std::fabs(y_axis * Normal1) == 1)) || ((std::fabs(x_axis * Normal1) == 0) && (std::fabs(y_axis * Normal1) == 0))) AxisBox=1; else Box=1; return 1; } G4bool G4BREPSolid::IsConvex() { if(!PlaneSolid) return 0; // All faces must be planar // This is not robust. There can be concave solids // where the concavity comes for example from three triangles. // Additional checking 20.8. For each face the connecting faces are // found and the cross product computed between the face and each // connecting face. If the result changes value at any point the // solid is concave. G4Surface* Srf; G4Surface* ConnectedSrf; G4int Result; Convex = 1; G4int a, b, c, d; for(a=0;a solid is concave. This is not enough to // distinguish all the cases of concavity. // Result = Srf->IsConvex(); if(Result != -1) { Convex = 0; return 0; } } Srf = SurfaceVec[0]; G4Point3D Pt1; G4Point3D Pt2; G4int ConnectingPoints=0; G4Vector3D N1; G4Vector3D N2; // L. Broglia // The number of connecting points can be // (nb_of_surfaces-1) * nb_of_surfaces (loop a & loop b) // G4int* ConnectedList = new G4int[nb_of_surfaces]; G4int* ConnectedList = new G4int[(nb_of_surfaces-1) * nb_of_surfaces]; for(a=0; aGetNumberOfPoints(); Result=0; for(b=0; bGetNumberOfPoints(); for(c=0; cGetPoint(c); for(d=0; dGetPoint(d); if(Pts1 == Pts2) ConnectingPoints++; } if(ConnectingPoints > 0) break; } if( ConnectingPoints > 0 ) { Connections++; ConnectedList[Connections]=b; } ConnectingPoints=0; } } // If connected, check for concavity. // Get surfaces from ConnectedList and compare their normals // for(c=0; cNorm()->GetDir(); N2 = ConnectedSrf->Norm()->GetDir(); // Check cross product // G4Vector3D CP = G4Vector3D( N1.cross(N2) ); G4double CrossProd = CP.x()+CP.y()+CP.z(); if( CrossProd > 0 ) Left++; if(CrossProd < 0) Right++; if(Left&&Right) { Convex = 0; return 0; } Connections=0; } Convex=1; // L. Broglia // Problems with this delete when there are many solids to create // delete [] ConnectedList; return 1; } 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(); 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; xoffset=pTransform.NetTranslation().x(); xMin=xoffset+Min.x(); xMax=xoffset+Max.x(); if (pVoxelLimit.IsXLimited()) { if (xMin>pVoxelLimit.GetMaxXExtent() ||xMaxpVoxelLimit.GetMaxXExtent()) { xMax=pVoxelLimit.GetMaxXExtent(); } } } yoffset=pTransform.NetTranslation().y(); yMin=yoffset+Min.y(); yMax=yoffset+Max.y(); if (pVoxelLimit.IsYLimited()) { if (yMin>pVoxelLimit.GetMaxYExtent() ||yMaxpVoxelLimit.GetMaxYExtent()) { yMax=pVoxelLimit.GetMaxYExtent(); } } } zoffset=pTransform.NetTranslation().z(); zMin=zoffset+Min.z(); zMax=zoffset+Max.z(); if (pVoxelLimit.IsZLimited()) { if (zMin>pVoxelLimit.GetMaxZExtent() ||zMaxpVoxelLimit.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; default: 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(); vertices->reserve(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->push_back(pTransform.TransformPoint(vertex0)); vertices->push_back(pTransform.TransformPoint(vertex1)); vertices->push_back(pTransform.TransformPoint(vertex2)); vertices->push_back(pTransform.TransformPoint(vertex3)); vertices->push_back(pTransform.TransformPoint(vertex4)); vertices->push_back(pTransform.TransformPoint(vertex5)); vertices->push_back(pTransform.TransformPoint(vertex6)); vertices->push_back(pTransform.TransformPoint(vertex7)); } else { G4Exception("G4BREPSolid::CreateRotatedVertices()", "FatalError", FatalException, "Out of memory - Cannot allocate vertices!"); } return vertices; } EInside G4BREPSolid::Inside(register const G4ThreeVector& Pt) const { // This function finds if the point Pt is inside, // outside or on the surface of the solid const G4double sqrHalfTolerance = kCarTolerance*kCarTolerance*0.25; G4Vector3D v(1, 0, 0.01); 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, samehit=0; for(G4int a=0; a < nb_of_surfaces; a++) { if(SurfaceVec[a]->IsActive()) { // 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 found before. // if( (SurfaceVec[a]->Intersect(r)) & 1 ) { // Test if the point is on the surface // if(SurfaceVec[a]->GetDistance() < sqrHalfTolerance) return kSurface; // Test if this intersection was found before // for(G4int i=0; iGetDistance() == SurfaceVec[i]->GetDistance()) { 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 G4BREPSolid::SurfaceNormal(const G4ThreeVector& Pt) const { // This function calculates the normal of the surface at a point on the // surface. If the point is not on the surface the result is undefined. // Note : the sense of the normal depends on the sense of the surface. const G4double sqrHalfTolerance = kCarTolerance*kCarTolerance*0.25; G4int iplane; // Find on which surface the point is // for(iplane = 0; iplane < nb_of_surfaces; iplane++) { if(SurfaceVec[iplane]->HowNear(Pt) < sqrHalfTolerance) // the point is on this surface break; } // Calculate the normal at this point // G4ThreeVector norm = SurfaceVec[iplane]->SurfaceNormal(Pt); return norm.unit(); } G4double G4BREPSolid::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]; G4int a; // Set the surfaces to active again // Reset(); // Compute the shortest distance of the point to each surface. // Be careful : 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 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( std::fabs(Dist) > std::fabs(dists[a]) ) //if( dists[a] >= 0) Dist = dists[a]; delete[] dists; if(Dist == kInfinity) return 0; // the point is inside the solid or on a surface else return std::fabs(Dist); } G4double G4BREPSolid::DistanceToIn(register const G4ThreeVector& Pt, register const G4ThreeVector& V ) const { // 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(); const G4double sqrHalfTolerance = kCarTolerance*kCarTolerance*0.25; 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); ShortestDistance = kInfinity; for(a=0; a< nb_of_surfaces; a++) { if( SurfaceVec[a]->IsActive() ) { // Test if the ray intersects the surface // if( SurfaceVec[a]->Intersect(r) ) { G4double surfDistance = SurfaceVec[a]->GetDistance(); // If more than 1 surface is intersected, take the nearest one // if( surfDistance < ShortestDistance ) { if( surfDistance > sqrHalfTolerance ) { ShortestDistance = surfDistance; } else { // The point is within the boundary. It is ignored it if // the direction is away from the boundary // G4Vector3D Norm = SurfaceVec[a]->SurfaceNormal(Pttmp); if( (Norm * Vtmp) < 0 ) { ShortestDistance = surfDistance; } } } } } } // Be careful ! // SurfaceVec->Distance is in fact the squared distance // if(ShortestDistance != kInfinity) return std::sqrt(ShortestDistance); else return kInfinity; // No intersection } G4double G4BREPSolid::DistanceToOut(register const G4ThreeVector& P, register const G4ThreeVector& D, const G4bool, G4bool *validNorm, G4ThreeVector* ) const { // Calculates the distance from a point inside the solid to the solid's // boundary along a specified direction vector. // Returns 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 sqrHalfTolerance = kCarTolerance*kCarTolerance*0.25; G4Vector3D Ptv = P; G4int a; 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]->IsActive()) { // Test if the ray intersect the surface // if( (SurfaceVec[a]->Intersect(r)) ) { // If more than 1 surface is intersected, take the nearest one // G4double surfDistance = SurfaceVec[a]->GetDistance(); if( surfDistance < ShortestDistance ) { if( surfDistance > sqrHalfTolerance ) { ShortestDistance = surfDistance; } else { // The point is within the boundary: ignore it } } } } } // Be careful ! // SurfaceVec->Distance is in fact the squared distance // if(ShortestDistance != kInfinity) return std::sqrt(ShortestDistance); else return 0.0; // No intersection is found, the point is outside } G4double G4BREPSolid::DistanceToOut(const G4ThreeVector& Pt)const { // Calculates the shortest distance ("safety") from a point // inside the solid to any boundary of this solid. // Returns 0 if the point is already outside. G4double *dists = new G4double[nb_of_surfaces]; G4int a; // Set the surfaces to active again // Reset(); // Compute the shortest distance of the point to each surfaces // Be careful : 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 ) // for(a = 0; a < nb_of_surfaces; a++) if( std::fabs(Dist) > std::fabs(dists[a]) ) //if( dists[a] <= 0) Dist = dists[a]; delete[] dists; if(Dist == kInfinity) return 0; // The point is ouside the solid or on a surface else return std::fabs(Dist); } void G4BREPSolid::DescribeYourselfTo (G4VGraphicsScene& scene) const { scene.AddSolid (*this); } G4Polyhedron* G4BREPSolid::CreatePolyhedron () const { // Approximate implementation, just a box ... G4Point3D Min = bbox->GetBoxMin(); G4Point3D Max = bbox->GetBoxMax(); return new G4PolyhedronBox (Max.x(), Max.y(), Max.z()); } G4NURBS* G4BREPSolid::CreateNURBS () const { // Approximate implementation, just a box ... G4Point3D Min = bbox->GetBoxMin(); G4Point3D Max = bbox->GetBoxMax(); return new G4NURBSbox (Max.x(), Max.y(), Max.z()); } void G4BREPSolid::CalcBBoxes() { // First initialization. Calculates the bounding boxes // for the surfaces and for the solid. G4Surface* srf; G4Point3D min, max; if(active) { min = PINFINITY; max = -PINFINITY; for(G4int a = 0;a < nb_of_surfaces;a++) { // Get first in List // srf = SurfaceVec[a]; G4int convex=1; G4int concavepoint=-1; if (srf->MyType() == 1) { concavepoint = srf->IsConvex(); convex = srf->GetConvex(); } // Make bbox for face // // if(convex && Concavepoint==-1) { srf->CalcBBox(); G4Point3D box_min = srf->GetBBox()->GetBoxMin(); G4Point3D box_max = srf->GetBBox()->GetBoxMax(); // 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()); if(max.z() < box_max.z()) max.setZ(box_max.z()); // min > box_min // if(min.x() > box_min.x()) min.setX(box_min.x()); if(min.y() > box_min.y()) min.setY(box_min.y()); if(min.z() > box_min.z()) min.setZ(box_min.z()); } } bbox = new G4BoundingBox3D(min, max); return; } G4cerr << "ERROR - G4BREPSolid::CalcBBoxes()" << G4endl << " No bbox calculated for solid. Error." << G4endl; } void G4BREPSolid::RemoveHiddenFaces(register const G4Ray& rayref, G4int In ) const { // Deactivates the planar faces that are on the "back" side of a solid. // B-splines are not handled by this function. Also cases where the ray // starting point is Inside the bbox of the solid are ignored as we don't // know if the starting point is Inside the actual solid except for // axis-oriented box-like solids. register G4Surface* srf; register const G4Vector3D& RayDir = rayref.GetDir(); register G4double Result; G4int a; // In all other cases the ray starting point is outside the solid // if(!In) for(a=0; a