53 std::vector<G4TwoVector> polygon,
54 std::vector<ZSection> zsections)
57 fNz(zsections.size()),
62 fGeometryType(
"G4ExtrudedSolid")
71 std::ostringstream message;
72 message <<
"Number of polygon vertices < 3 - " << pName;
73 G4Exception(
"G4ExtrudedSolid::G4ExtrudedSolid()",
"GeomSolids0002",
79 std::ostringstream message;
80 message <<
"Number of z-sides < 2 - " << pName;
81 G4Exception(
"G4ExtrudedSolid::G4ExtrudedSolid()",
"GeomSolids0002",
85 for (
G4int i=0; i<fNz-1; ++i )
87 if ( zsections[i].fZ > zsections[i+1].fZ )
89 std::ostringstream message;
90 message <<
"Z-sections have to be ordered by z value (z0 < z1 < z2...) - "
92 G4Exception(
"G4ExtrudedSolid::G4ExtrudedSolid()",
"GeomSolids0002",
95 if ( std::fabs( zsections[i+1].fZ - zsections[i].fZ ) <
kCarTolerance * 0.5 )
97 std::ostringstream message;
98 message <<
"Z-sections with the same z position are not supported - "
100 G4Exception(
"G4ExtrudedSolid::G4ExtrudedSolid()",
"GeomSolids0001",
109 for (
G4int i=0; i<fNv; ++i ) {
111 if ( j == fNv ) j = 0;
112 area += 0.5 * ( polygon[i].x()*polygon[j].y() - polygon[j].x()*polygon[i].y());
119 for (
G4int i=0; i<fNv; ++i ) { fPolygon.push_back(polygon[i]); }
126 for (
G4int i=0; i<fNv; ++i ) { fPolygon.push_back(polygon[fNv-i-1]); }
132 for (
G4int i=0; i<fNz; ++i ) { fZSections.push_back(zsections[i]); }
135 G4bool result = MakeFacets();
138 std::ostringstream message;
139 message <<
"Making facets failed - " << pName;
140 G4Exception(
"G4ExtrudedSolid::G4ExtrudedSolid()",
"GeomSolids0003",
143 fIsConvex = IsConvex();
146 ComputeProjectionParameters();
152 std::vector<G4TwoVector> polygon,
163 fGeometryType(
"G4ExtrudedSolid")
172 std::ostringstream message;
173 message <<
"Number of polygon vertices < 3 - " << pName;
174 G4Exception(
"G4ExtrudedSolid::G4ExtrudedSolid()",
"GeomSolids0002",
182 for (
G4int i=0; i<fNv; ++i )
185 if ( j == fNv ) { j = 0; }
186 area += 0.5 * ( polygon[i].x()*polygon[j].y()
187 - polygon[j].x()*polygon[i].y());
195 for (
G4int i=0; i<fNv; ++i ) { fPolygon.push_back(polygon[i]); }
203 for (
G4int i=0; i<fNv; ++i ) { fPolygon.push_back(polygon[fNv-i-1]); }
208 fZSections.push_back(
ZSection(-dz, off1, scale1));
209 fZSections.push_back(
ZSection( dz, off2, scale2));
211 G4bool result = MakeFacets();
214 std::ostringstream message;
215 message <<
"Making facets failed - " << pName;
216 G4Exception(
"G4ExtrudedSolid::G4ExtrudedSolid()",
"GeomSolids0003",
219 fIsConvex = IsConvex();
221 ComputeProjectionParameters();
228 fTriangles(), fIsConvex(false), fGeometryType(
"G4ExtrudedSolid")
238 fPolygon(rhs.fPolygon), fZSections(rhs.fZSections),
239 fTriangles(rhs.fTriangles), fIsConvex(rhs.fIsConvex),
240 fGeometryType(rhs.fGeometryType), fKScales(rhs.fKScales),
241 fScale0s(rhs.fScale0s), fKOffsets(rhs.fKOffsets), fOffset0s(rhs.fOffset0s)
252 if (
this == &rhs) {
return *
this; }
260 fNv = rhs.fNv; fNz = rhs.fNz;
261 fPolygon = rhs.fPolygon; fZSections = rhs.fZSections;
262 fTriangles = rhs.fTriangles; fIsConvex = rhs.fIsConvex;
263 fGeometryType = rhs.fGeometryType; fKScales = rhs.fKScales;
264 fScale0s = rhs.fScale0s; fKOffsets = rhs.fKOffsets;
265 fOffset0s = rhs.fOffset0s;
279void G4ExtrudedSolid::ComputeProjectionParameters()
289 for (
G4int iz=0; iz<fNz-1; ++iz)
293 G4double scale1 = fZSections[iz].fScale;
294 G4double scale2 = fZSections[iz+1].fScale;
298 G4double kscale = (scale2 - scale1)/(z2 - z1);
299 G4double scale0 = scale2 - kscale*(z2 - z1)/2.0;
303 fKScales.push_back(kscale);
304 fScale0s.push_back(scale0);
305 fKOffsets.push_back(koff);
306 fOffset0s.push_back(off0);
317 return G4ThreeVector( fPolygon[ind].x() * fZSections[iz].fScale
318 + fZSections[iz].fOffset.x(),
319 fPolygon[ind].y() * fZSections[iz].fScale
320 + fZSections[iz].fOffset.y(), fZSections[iz].fZ);
337 while ( point.
z() > fZSections[iz+1].fZ && iz < fNz-2 ) { ++iz; }
339 G4double z0 = ( fZSections[iz+1].fZ + fZSections[iz].fZ )/2.0;
341 G4double pscale = fKScales[iz]*(point.
z()-z0) + fScale0s[iz];
342 G4TwoVector poffset = fKOffsets[iz]*(point.
z()-z0) + fOffset0s[iz];
351 return (p2 - poffset)/pscale;
361 if ( l1.
x() == l2.
x() )
366 return std::fabs (p.
y() - l1.
y() - ((l2.
y() - l1.
y())/(l2.
x() - l1.
x()))
386 return IsSameLine(p, l1, l2);
396 return ( (p1.
x() - l1.
x()) * (l2.
y() - l1.
y())
397 - (l2.
x() - l1.
x()) * (p1.
y() - l1.
y()) )
398 * ( (p2.
x() - l1.
x()) * (l2.
y() - l1.
y())
399 - (l2.
x() - l1.
x()) * (p2.
y() - l1.
y()) ) > 0;
412 if ( ( p.
x() < a.
x() && p.
x() < b.
x() && p.
x() < c.
x() ) ||
413 ( p.
x() > a.
x() && p.
x() > b.
x() && p.
x() > c.
x() ) ||
414 ( p.
y() < a.
y() && p.
y() < b.
y() && p.
y() < c.
y() ) ||
415 ( p.
y() > a.
y() && p.
y() > b.
y() && p.
y() > c.
y() ) )
return false;
418 = IsSameSide(p, a, b, c)
419 && IsSameSide(p, b, a, c)
420 && IsSameSide(p, c, a, b);
423 = IsSameLineSegment(p, a, b)
424 || IsSameLineSegment(p, b, c)
425 || IsSameLineSegment(p, c, a);
427 return inside || onEdge;
440 G4double result = (std::atan2(t1.
y(), t1.
x()) - std::atan2(t2.
y(), t2.
x()));
442 if ( result < 0 ) result += 2*
pi;
450G4ExtrudedSolid::MakeDownFacet(
G4int ind1,
G4int ind2,
G4int ind3)
const
455 std::vector<G4ThreeVector> vertices;
463 = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[1]);
465 if ( cross.
z() > 0.0 )
473 vertices[1] = vertices[2];
489 std::vector<G4ThreeVector> vertices;
490 vertices.push_back(
GetVertex(fNz-1, ind1));
491 vertices.push_back(
GetVertex(fNz-1, ind2));
492 vertices.push_back(
GetVertex(fNz-1, ind3));
497 = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[1]);
499 if ( cross.
z() < 0.0 )
507 vertices[1] = vertices[2];
517G4bool G4ExtrudedSolid::AddGeneralPolygonFacets()
521 typedef std::pair < G4TwoVector, G4int > Vertex;
525 std::vector< Vertex > verticesToBeDone;
526 for (
G4int i=0; i<fNv; ++i )
528 verticesToBeDone.push_back(Vertex(fPolygon[i], i));
530 std::vector< Vertex > ears;
532 std::vector< Vertex >::iterator c1 = verticesToBeDone.begin();
533 std::vector< Vertex >::iterator c2 = c1+1;
534 std::vector< Vertex >::iterator c3 = c1+2;
535 while ( verticesToBeDone.size()>2 )
544 G4double angle = GetAngle(c2->first, c3->first, c1->first);
557 if ( c3 == verticesToBeDone.end() ) { c3 = verticesToBeDone.begin(); }
563 angle = GetAngle(c2->first, c3->first, c1->first);
568 if ( counter > fNv) {
569 G4Exception(
"G4ExtrudedSolid::AddGeneralPolygonFacets",
571 "Triangularisation has failed.");
577 std::vector< Vertex >::iterator it;
578 for ( it=verticesToBeDone.begin(); it != verticesToBeDone.end(); ++it )
582 if ( it == c1 || it == c2 || it == c3 ) {
continue; }
584 if ( IsPointInside(c1->first, c2->first, c3->first, it->first) )
594 if ( c3 == verticesToBeDone.end() ) { c3 = verticesToBeDone.begin(); }
609 result =
AddFacet( MakeDownFacet(c1->second, c2->second, c3->second) );
610 if ( ! result ) {
return false; }
612 result =
AddFacet( MakeUpFacet(c1->second, c2->second, c3->second) );
613 if ( ! result ) {
return false; }
615 std::vector<G4int> triangle(3);
616 triangle[0] = c1->second;
617 triangle[1] = c2->second;
618 triangle[2] = c3->second;
619 fTriangles.push_back(triangle);
623 verticesToBeDone.erase(c2);
624 c1 = verticesToBeDone.begin();
634G4bool G4ExtrudedSolid::MakeFacets()
646 if ( ! good ) {
return false; }
650 if ( ! good ) {
return false; }
652 std::vector<G4int> triangle(3);
656 fTriangles.push_back(triangle);
664 if ( ! good ) {
return false; }
669 if ( ! good ) {
return false; }
671 std::vector<G4int> triangle1(3);
675 fTriangles.push_back(triangle1);
677 std::vector<G4int> triangle2(3);
681 fTriangles.push_back(triangle2);
685 good = AddGeneralPolygonFacets();
686 if ( ! good ) {
return false; }
691 for (
G4int iz = 0; iz < fNz-1; ++iz )
693 for (
G4int i = 0; i < fNv; ++i )
695 G4int j = (i+1) % fNv;
699 if ( ! good ) {
return false; }
710G4bool G4ExtrudedSolid::IsConvex()
const
714 for (
G4int i=0; i< fNv; ++i )
716 G4int j = ( i + 1 ) % fNv;
717 G4int k = ( i + 2 ) % fNv;
721 if ( dphi < 0. ) { dphi += 2.*
pi; }
723 if ( dphi >= pi ) {
return false; }
735 return fGeometryType;
772 for (
G4int i=0; i<fNv; ++i )
774 G4int j = (i+1) % fNv;
775 if ( IsSameLineSegment(pscaled, fPolygon[i], fPolygon[j]) )
786 std::vector< std::vector<G4int> >::const_iterator it = fTriangles.begin();
790 if ( IsPointInside(fPolygon[(*it)[0]], fPolygon[(*it)[1]],
791 fPolygon[(*it)[2]], pscaled) ) { inside =
true; }
793 }
while ( (inside ==
false) && (it != fTriangles.end()) );
799 if ( std::fabs( p.
z() - fZSections[0].fZ ) <
kCarTolerance * 0.5 ||
831 if (validNorm) { *validNorm = fIsConvex; }
850 G4int oldprc = os.precision(16);
851 os <<
"-----------------------------------------------------------\n"
852 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
853 <<
" ===================================================\n"
854 <<
" Solid geometry type: " << fGeometryType <<
G4endl;
857 { os <<
" Convex polygon; list of vertices:" <<
G4endl; }
859 { os <<
" Concave polygon; list of vertices:" <<
G4endl; }
861 for (
G4int i=0; i<fNv; ++i )
863 os << std::setw(5) <<
"#" << i
864 <<
" vx = " << fPolygon[i].x()/mm <<
" mm"
865 <<
" vy = " << fPolygon[i].y()/mm <<
" mm" <<
G4endl;
868 os <<
" Sections:" <<
G4endl;
869 for (
G4int iz=0; iz<fNz; ++iz )
871 os <<
" z = " << fZSections[iz].fZ/mm <<
" mm "
872 <<
" x0= " << fZSections[iz].fOffset.x()/mm <<
" mm "
873 <<
" y0= " << fZSections[iz].fOffset.y()/mm <<
" mm "
874 <<
" scale= " << fZSections[iz].fScale <<
G4endl;
892 os.precision(oldprc);
CLHEP::Hep3Vector G4ThreeVector
EInside Inside(const G4ThreeVector &p) const
std::ostream & StreamInfo(std::ostream &os) const
virtual ~G4ExtrudedSolid()
G4ExtrudedSolid & operator=(const G4ExtrudedSolid &rhs)
G4ExtrudedSolid(const G4String &pName, std::vector< G4TwoVector > polygon, std::vector< ZSection > zsections)
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const
G4GeometryType GetEntityType() const
G4TwoVector GetVertex(G4int index) const
G4double GetMinYExtent() const
G4double GetMinZExtent() const
G4TessellatedSolid & operator=(const G4TessellatedSolid &right)
G4bool AddFacet(G4VFacet *aFacet)
G4double GetMaxYExtent() const
G4double GetMaxZExtent() const
G4double GetMaxXExtent() const
virtual G4double DistanceToOut(const G4ThreeVector &p) const
G4double GetMinXExtent() const
void SetSolidClosed(const G4bool t)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)