49 #if !defined(G4GEOM_USE_UEXTRUDEDSOLID)
71 const std::vector<G4TwoVector>& polygon,
72 const std::vector<ZSection>& zsections)
75 fNz(zsections.size()),
80 fGeometryType(
"G4ExtrudedSolid")
89 std::ostringstream message;
90 message <<
"Number of vertices in polygon < 3 - " << pName;
91 G4Exception(
"G4ExtrudedSolid::G4ExtrudedSolid()",
"GeomSolids0002",
97 std::ostringstream message;
98 message <<
"Number of z-sides < 2 - " << pName;
99 G4Exception(
"G4ExtrudedSolid::G4ExtrudedSolid()",
"GeomSolids0002",
103 for (
G4int i=0; i<fNz-1; ++i )
105 if ( zsections[i].fZ > zsections[i+1].fZ )
107 std::ostringstream message;
108 message <<
"Z-sections have to be ordered by z value (z0 < z1 < z2...) - "
110 G4Exception(
"G4ExtrudedSolid::G4ExtrudedSolid()",
"GeomSolids0002",
115 std::ostringstream message;
116 message <<
"Z-sections with the same z position are not supported - "
118 G4Exception(
"G4ExtrudedSolid::G4ExtrudedSolid()",
"GeomSolids0001",
129 std::vector<G4int> removedVertices;
132 if (removedVertices.size() != 0)
134 G4int nremoved = removedVertices.size();
135 std::ostringstream message;
136 message <<
"The following "<< nremoved
137 <<
" vertices have been removed from polygon in " << pName
138 <<
"\nas collinear or coincident with other vertices: "
139 << removedVertices[0];
140 for (
G4int i=1; i<nremoved; ++i) message <<
", " << removedVertices[i];
141 G4Exception(
"G4ExtrudedSolid::G4ExtrudedSolid()",
"GeomSolids1001",
145 fNv = fPolygon.size();
148 std::ostringstream message;
149 message <<
"Number of vertices in polygon after removal < 3 - " << pName;
150 G4Exception(
"G4ExtrudedSolid::G4ExtrudedSolid()",
"GeomSolids0002",
163 std::reverse(fPolygon.begin(),fPolygon.end());
168 fZSections = zsections;
173 std::ostringstream message;
174 message <<
"Making facets failed - " << pName;
175 G4Exception(
"G4ExtrudedSolid::G4ExtrudedSolid()",
"GeomSolids0003",
180 ComputeProjectionParameters();
186 const std::vector<G4TwoVector>& polygon,
197 fGeometryType(
"G4ExtrudedSolid")
206 std::ostringstream message;
207 message <<
"Number of vertices in polygon < 3 - " << pName;
208 G4Exception(
"G4ExtrudedSolid::G4ExtrudedSolid()",
"GeomSolids0002",
218 std::vector<G4int> removedVertices;
221 if (removedVertices.size() != 0)
223 G4int nremoved = removedVertices.size();
224 std::ostringstream message;
225 message <<
"The following "<< nremoved
226 <<
" vertices have been removed from polygon in " << pName
227 <<
"\nas collinear or coincident with other vertices: "
228 << removedVertices[0];
229 for (
G4int i=1; i<nremoved; ++i) message <<
", " << removedVertices[i];
230 G4Exception(
"G4ExtrudedSolid::G4ExtrudedSolid()",
"GeomSolids1001",
234 fNv = fPolygon.size();
237 std::ostringstream message;
238 message <<
"Number of vertices in polygon after removal < 3 - " << pName;
239 G4Exception(
"G4ExtrudedSolid::G4ExtrudedSolid()",
"GeomSolids0002",
252 std::reverse(fPolygon.begin(),fPolygon.end());
257 fZSections.push_back(
ZSection(-dz, off1, scale1));
258 fZSections.push_back(
ZSection( dz, off2, scale2));
263 std::ostringstream message;
264 message <<
"Making facets failed - " << pName;
265 G4Exception(
"G4ExtrudedSolid::G4ExtrudedSolid()",
"GeomSolids0003",
270 ComputeProjectionParameters();
277 fTriangles(), fIsConvex(false), fGeometryType(
"G4ExtrudedSolid")
287 fPolygon(rhs.fPolygon), fZSections(rhs.fZSections),
288 fTriangles(rhs.fTriangles), fIsConvex(rhs.fIsConvex),
289 fGeometryType(rhs.fGeometryType), fKScales(rhs.fKScales),
290 fScale0s(rhs.fScale0s), fKOffsets(rhs.fKOffsets), fOffset0s(rhs.fOffset0s)
301 if (
this == &rhs) {
return *
this; }
309 fNv = rhs.fNv; fNz = rhs.fNz;
310 fPolygon = rhs.fPolygon; fZSections = rhs.fZSections;
311 fTriangles = rhs.fTriangles; fIsConvex = rhs.fIsConvex;
312 fGeometryType = rhs.fGeometryType; fKScales = rhs.fKScales;
313 fScale0s = rhs.fScale0s; fKOffsets = rhs.fKOffsets;
314 fOffset0s = rhs.fOffset0s;
328 void G4ExtrudedSolid::ComputeProjectionParameters()
338 for (
G4int iz=0; iz<fNz-1; ++iz)
342 G4double scale1 = fZSections[iz].fScale;
343 G4double scale2 = fZSections[iz+1].fScale;
347 G4double kscale = (scale2 - scale1)/(z2 - z1);
348 G4double scale0 = scale2 - kscale*(z2 - z1)/2.0;
352 fKScales.push_back(kscale);
353 fScale0s.push_back(scale0);
354 fKOffsets.push_back(koff);
355 fOffset0s.push_back(off0);
366 return G4ThreeVector( fPolygon[ind].x() * fZSections[iz].fScale
367 + fZSections[iz].fOffset.x(),
368 fPolygon[ind].y() * fZSections[iz].fScale
369 + fZSections[iz].fOffset.y(), fZSections[iz].fZ);
386 while ( point.
z() > fZSections[iz+1].fZ && iz < fNz-2 ) { ++iz; }
389 G4double z0 = ( fZSections[iz+1].fZ + fZSections[iz].fZ )/2.0;
391 G4double pscale = fKScales[iz]*(point.
z()-
z0) + fScale0s[iz];
392 G4TwoVector poffset = fKOffsets[iz]*(point.
z()-
z0) + fOffset0s[iz];
401 return (p2 - poffset)/pscale;
412 if ( l1.
x() == l2.
x() )
427 G4bool squareComp = (dy*dy < (1+slope*slope)
451 return IsSameLine(p, l1, l2);
463 return ( (p1.
x() - l1.
x()) * (l2.
y() - l1.
y())
464 - (l2.
x() - l1.
x()) * (p1.
y() - l1.
y()) )
465 * ( (p2.
x() - l1.
x()) * (l2.
y() - l1.
y())
466 - (l2.
x() - l1.
x()) * (p2.
y() - l1.
y()) ) > 0;
481 if ( ( p.
x() < a.
x() && p.
x() < b.
x() && p.
x() < c.
x() ) ||
482 ( p.
x() > a.
x() && p.
x() > b.
x() && p.
x() > c.
x() ) ||
483 ( p.
y() < a.
y() && p.
y() < b.
y() && p.
y() < c.
y() ) ||
484 ( p.
y() > a.
y() && p.
y() > b.
y() && p.
y() > c.
y() ) )
return false;
487 = IsSameSide(p, a, b, c)
488 && IsSameSide(p, b, a, c)
489 && IsSameSide(p, c, a, b);
492 = IsSameLineSegment(p, a, b)
493 || IsSameLineSegment(p, b, c)
494 || IsSameLineSegment(p, c, a);
496 return inside || onEdge;
513 if ( result < 0 ) result += 2*
pi;
521 G4ExtrudedSolid::MakeDownFacet(
G4int ind1,
G4int ind2,
G4int ind3)
const
526 std::vector<G4ThreeVector> vertices;
534 = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[1]);
536 if ( cross.
z() > 0.0 )
544 vertices[1] = vertices[2];
560 std::vector<G4ThreeVector> vertices;
561 vertices.push_back(
GetVertex(fNz-1, ind1));
562 vertices.push_back(
GetVertex(fNz-1, ind2));
563 vertices.push_back(
GetVertex(fNz-1, ind3));
568 = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[1]);
570 if ( cross.
z() < 0.0 )
578 vertices[1] = vertices[2];
588 G4bool G4ExtrudedSolid::AddGeneralPolygonFacets()
592 typedef std::pair < G4TwoVector, G4int > Vertex;
594 static const G4double kAngTolerance =
599 std::vector< Vertex > verticesToBeDone;
600 for (
G4int i=0; i<fNv; ++i )
602 verticesToBeDone.push_back(Vertex(fPolygon[i], i));
604 std::vector< Vertex > ears;
606 std::vector< Vertex >::iterator c1 = verticesToBeDone.begin();
607 std::vector< Vertex >::iterator c2 = c1+1;
608 std::vector< Vertex >::iterator c3 = c1+2;
609 while ( verticesToBeDone.size()>2 )
626 while ( angle >= (
pi-kAngTolerance) )
635 if ( c3 == verticesToBeDone.end() ) { c3 = verticesToBeDone.begin(); }
641 angle = GetAngle(c2->first, c3->first, c1->first);
646 if ( counter > fNv) {
647 G4Exception(
"G4ExtrudedSolid::AddGeneralPolygonFacets",
649 "Triangularisation has failed.");
655 std::vector< Vertex >::iterator it;
656 for ( it=verticesToBeDone.begin(); it != verticesToBeDone.end(); ++it )
660 if ( it == c1 || it == c2 || it == c3 ) {
continue; }
662 if ( IsPointInside(c1->first, c2->first, c3->first, it->first) )
672 if ( c3 == verticesToBeDone.end() ) { c3 = verticesToBeDone.begin(); }
687 result =
AddFacet( MakeDownFacet(c1->second, c2->second, c3->second) );
688 if ( ! result ) {
return false; }
690 result =
AddFacet( MakeUpFacet(c1->second, c2->second, c3->second) );
691 if ( ! result ) {
return false; }
693 std::vector<G4int> triangle(3);
694 triangle[0] = c1->second;
695 triangle[1] = c2->second;
696 triangle[2] = c3->second;
697 fTriangles.push_back(triangle);
701 verticesToBeDone.erase(c2);
702 c1 = verticesToBeDone.begin();
712 G4bool G4ExtrudedSolid::MakeFacets()
724 if ( ! good ) {
return false; }
730 if ( ! good ) {
return false; }
732 std::vector<G4int> triangle(3);
736 fTriangles.push_back(triangle);
744 if ( ! good ) {
return false; }
751 if ( ! good ) {
return false; }
753 std::vector<G4int> triangle1(3);
757 fTriangles.push_back(triangle1);
759 std::vector<G4int> triangle2(3);
763 fTriangles.push_back(triangle2);
767 good = AddGeneralPolygonFacets();
768 if ( ! good ) {
return false; }
773 for (
G4int iz = 0; iz < fNz-1; ++iz )
775 for (
G4int i = 0; i < fNv; ++i )
777 G4int j = (i+1) % fNv;
781 if ( ! good ) {
return false; }
796 return fGeometryType;
833 for (
G4int i=0; i<fNv; ++i )
835 G4int j = (i+1) % fNv;
836 if ( IsSameLineSegment(pscaled, fPolygon[i], fPolygon[j]) )
847 std::vector< std::vector<G4int> >::const_iterator it = fTriangles.begin();
851 if ( IsPointInside(fPolygon[(*it)[0]], fPolygon[(*it)[1]],
852 fPolygon[(*it)[2]], pscaled) ) { inside =
true; }
854 }
while ( (inside ==
false) && (it != fTriangles.end()) );
892 if (validNorm) { *validNorm = fIsConvex; }
919 if (x < xmin0) xmin0 = x;
920 if (x > xmax0) xmax0 = x;
922 if (y < ymin0) ymin0 = y;
923 if (y > ymax0) ymax0 = y;
930 for (
G4int i=0; i<nsect; ++i)
936 xmin =
std::min(xmin,xmin0*scale+dx);
937 xmax =
std::max(xmax,xmax0*scale+dx);
938 ymin =
std::min(ymin,ymin0*scale+dy);
939 ymax =
std::max(ymax,ymax0*scale+dy);
945 pMin.
set(xmin,ymin,zmin);
946 pMax.
set(xmax,ymax,zmax);
950 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
952 std::ostringstream message;
953 message <<
"Bad bounding box (min >= max) for solid: "
955 <<
"\npMin = " << pMin
956 <<
"\npMax = " << pMax;
981 if (
true)
return bbox.
CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
985 return exist = (pMin < pMax) ?
true :
false;
999 std::ostringstream message;
1000 message <<
"Triangulation of the base polygon has failed for solid: "
1002 <<
"\nExtent has been calculated using boundary box";
1010 std::vector<const G4ThreeVectorList *> polygons;
1011 polygons.resize(nsect);
1017 G4int ntria = triangles.size()/3;
1018 for (
G4int i=0; i<ntria; ++i)
1021 for (
G4int k=0; k<nsect; ++k)
1030 G4ThreeVectorList::iterator iter = ptr->begin();
1031 G4double x0 = triangles[i3+0].x()*scale+dx;
1032 G4double y0 = triangles[i3+0].y()*scale+dy;
1035 G4double x1 = triangles[i3+1].x()*scale+dx;
1036 G4double y1 = triangles[i3+1].y()*scale+dy;
1039 G4double x2 = triangles[i3+2].x()*scale+dx;
1040 G4double y2 = triangles[i3+2].y()*scale+dy;
1047 if (!benv.
CalculateExtent(pAxis,pVoxelLimit,pTransform,emin,emax))
continue;
1048 if (emin < pMin) pMin = emin;
1049 if (emax > pMax) pMax =
emax;
1050 if (eminlim > pMin && emaxlim < pMax)
break;
1053 for (
G4int k=0; k<nsect; ++k) {
delete polygons[k]; polygons[k]=0;}
1054 return (pMin < pMax);
1061 G4int oldprc = os.precision(16);
1062 os <<
"-----------------------------------------------------------\n"
1063 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1064 <<
" ===================================================\n"
1065 <<
" Solid geometry type: " << fGeometryType <<
G4endl;
1068 { os <<
" Convex polygon; list of vertices:" <<
G4endl; }
1070 { os <<
" Concave polygon; list of vertices:" <<
G4endl; }
1072 for (
G4int i=0; i<fNv; ++i )
1074 os << std::setw(5) <<
"#" << i
1075 <<
" vx = " << fPolygon[i].x()/
mm <<
" mm"
1076 <<
" vy = " << fPolygon[i].y()/
mm <<
" mm" <<
G4endl;
1079 os <<
" Sections:" <<
G4endl;
1080 for (
G4int iz=0; iz<fNz; ++iz )
1082 os <<
" z = " << fZSections[iz].fZ/
mm <<
" mm "
1083 <<
" x0= " << fZSections[iz].fOffset.x()/
mm <<
" mm "
1084 <<
" y0= " << fZSections[iz].fOffset.y()/
mm <<
" mm "
1085 <<
" scale= " << fZSections[iz].fScale <<
G4endl;
1104 os.precision(oldprc);
G4double G4ParticleHPJENDLHEData::G4double result
void set(double x, double y, double z)
G4GeometryType GetEntityType() const
void SetSolidClosed(const G4bool t)
void Extent(G4ThreeVector &pMin, G4ThreeVector &pMax) const
static constexpr double mm
static const G4double kInfinity
CLHEP::Hep3Vector G4ThreeVector
G4double GetMaxXExtent() const
static G4double angle[DIM]
G4ExtrudedSolid(const G4String &pName, const std::vector< G4TwoVector > &polygon, const std::vector< ZSection > &zsections)
G4double GetMinXExtent() const
virtual ~G4ExtrudedSolid()
EInside Inside(const G4ThreeVector &p) const
G4double GetMaxZExtent() const
G4TwoVector GetVertex(G4int index) const
G4double kCarToleranceHalf
G4double GetMinZExtent() const
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const
virtual G4double DistanceToOut(const G4ThreeVector &p) const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const
G4int GetNofVertices() const
G4bool AddFacet(G4VFacet *aFacet)
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4bool BoundingBoxVsVoxelLimits(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
std::vector< G4ThreeVector > G4ThreeVectorList
G4int GetNofZSections() const
std::ostream & StreamInfo(std::ostream &os) const
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
static const G4double emax
T max(const T t1, const T t2)
brief Return the largest of the two arguments
ZSection GetZSection(G4int index) const
T min(const T t1, const T t2)
brief Return the smallest of the two arguments
static constexpr double pi
G4double GetMaxExtent(const EAxis pAxis) const
G4double GetMaxYExtent() const
G4double GetAngularTolerance() const
G4ExtrudedSolid & operator=(const G4ExtrudedSolid &rhs)
G4double GetMinExtent(const EAxis pAxis) const
static G4GeometryTolerance * GetInstance()
G4double GetMinYExtent() const
G4TessellatedSolid & operator=(const G4TessellatedSolid &right)