68 G4bool start = (phiOther > phi);
79 normal =
G4ThreeVector( zSign*radial.y(), -zSign*radial.x(), 0 );
84 allBehind = (zSign*(std::cos(phiOther)*radial.y() - std::sin(phiOther)*radial.x()) < 0);
89 G4double midPhi = phi + (start ? +0.5 : -0.5)*deltaPhi;
91 sinMid = std::sin(midPhi);
95 const std::size_t maxEdges = numEdges>0 ? numEdges : 1;
108 corn->
r = iterRZ.
GetA();
109 corn->
z = iterRZ.
GetB();
110 corn->
x = corn->
r*radial.x();
111 corn->
y = corn->
r*radial.y();
115 if( corn == corners )
116 { corn->
prev = corners+maxEdges-1;}
118 { corn->
prev = helper; }
122 if( corn < corners+maxEdges-1 )
123 { corn->
next = corn+1;}
125 { corn->
next = corners; }
128 }
while( ++corn, iterRZ.
Next() );
138 G4double rFact = std::cos(0.5*deltaPhi);
139 G4double rFactNormalize = 1.0/std::sqrt(1.0+rFact*rFact);
152 dz = here->z - prev->
z;
154 edge->
length = std::sqrt( dr*dr + dz*dz );
166 G4double zSignOther = start ? -1 : 1;
168 -zSignOther*std::cos(phiOther), 0 );
175 sideNorm *= rFactNormalize;
180 }
while( edge++, prev=here, ++here < corners+maxEdges );
194 G4double norm = std::sqrt( rPart*rPart + zPart*zPart );
218 G4double zSignOther = start ? -1 : 1;
220 -zSignOther*std::cos(phiOther), 0 );
222 xyVector = - normal - normalOther;
246 }
while( prevEdge=edge, ++edge < edges+maxEdges );
252 zAve = 0.5*(zMax-zMin);
253 surface =
G4ThreeVector( rAve*radial.x(), rAve*radial.y(), zAve );
269 test -= 1E-6*corner->
norm3D;
273 G4Exception(
"G4PolyPhiFace::Diagnose()",
"GeomSolids0002",
276 }
while( ++corner < corners+numEdges );
283 : rMin(0.), rMax(0.), zMin(0.), zMax(0.), kCarTolerance(0.)
312 if (
this == &source) {
return *
this; }
331 numEdges = source.numEdges;
332 normal = source.normal;
333 radial = source.radial;
334 surface = source.surface;
339 allBehind = source.allBehind;
343 fSurfaceArea = source.fSurfaceArea;
345 const std::size_t maxEdges = (numEdges > 0) ? numEdges : 1;
352 *sourceCorn = source.corners;
356 }
while( ++sourceCorn, ++corn < corners+maxEdges );
361 edges =
new G4PolyPhiFaceEdge[maxEdges];
363 G4PolyPhiFaceVertex* prev = corners+maxEdges-1,
365 G4PolyPhiFaceEdge* edge = edges,
366 * sourceEdge = source.edges;
372 }
while( ++sourceEdge, ++edge, prev=here, ++here < corners+maxEdges );
386 G4double normSign = outgoing ? +1 : -1;
391 isAllBehind = allBehind;
398 G4double dotProd = normSign*normal.dot(v);
400 if (dotProd <= 0) {
return false; }
407 distFromSurface = -normSign*ps.
dot(normal);
409 if (distFromSurface < -surfTolerance) {
return false; }
415 distance = distFromSurface/dotProd;
427 return InsideEdgesExact( r, ip.
z(), normSign, p, v );
434 G4double normSign = outgoing ? +1 : -1;
439 G4double distPhi = -normSign*normal.dot(ps);
441 if (distPhi < -0.5*kCarTolerance)
460 if (InsideEdges( r, p.
z(), &distRZ2,
nullptr ))
471 return std::sqrt( distPhi*distPhi + distRZ2 );
499 if (InsideEdges( r, p.
z(), &distRZ2, &base3Dnorm, &head3Dnorm ))
504 *bestDistance = std::fabs(distPhi);
509 if (distPhi < -tolerance) {
return kInside; }
510 if (distPhi < tolerance) {
return kSurface; }
518 *bestDistance = std::sqrt( distPhi*distPhi + distRZ2 );
524 base3Dnorm->
r*radial.y(),
528 if ( distRZ2 > tolerance*tolerance )
536 if (normDist < -tolerance) {
return kInside; }
537 if (normDist < tolerance) {
return kSurface; }
565 if (InsideEdges( r, p.
z(), &distRZ2,
nullptr ))
570 *bestDistance = std::fabs(distPhi);
577 *bestDistance = std::sqrt( distPhi*distPhi + distRZ2 );
595 +
axis.y()*corner->
r*radial.y()
596 +
axis.z()*corner->
z;
597 if (here > max) { max = here; }
598 }
while( ++corner < corners + numEdges );
623 point += radial*corner->
r;
626 }
while( ++corner < corners + numEdges );
667 if ( (z < zMin-kCarTolerance)
668 || (z > zMax+kCarTolerance) ) {
return false; }
678 G4PolyPhiFaceVertex *corn = corners,
679 *prev = corners+numEdges-1;
683 prevZ = ExactZOrder( z, qx, qy, qz, v, normSign, prev );
689 cornZ = ExactZOrder( z, qx, qy, qz, v, normSign, corn );
693 if (prevZ < 0) {
continue; }
697 if (prevZ > 0) {
continue; }
706 if (prevZ == 0) {
continue; }
716 G4PolyPhiFaceVertex *next = corn;
721 if (next == corners+numEdges) { next = corners; }
723 nextZ = ExactZOrder( z, qx, qy, qz, v, normSign, next );
724 }
while( nextZ == 0 );
729 if (nextZ*prevZ < 0) {
continue; }
738 G4ThreeVector qa( qx - prev->x, qy - prev->y, qz - prev->z ),
739 qb( qx - corn->
x, qy - corn->
y, qz - corn->
z );
741 G4double aboveOrBelow = normSign*qa.cross(qb).dot(v);
743 if (aboveOrBelow > 0)
747 else if (aboveOrBelow < 0)
760 }
while( prevZ = cornZ, prev=corn, ++corn < corners+numEdges );
795 if ( r < rMin || r > rMax ) {
return false; }
796 if ( z < zMin || z > zMax ) {
return false; }
803 return InsideEdges( r, z, ¬Used,
nullptr );
818 G4PolyPhiFaceEdge* edge = edges;
821 G4PolyPhiFaceVertex* testMe =
nullptr;
822 G4PolyPhiFaceVertex* v0_vertex = edge->
v0;
823 G4PolyPhiFaceVertex* v1_vertex = edge->
v1;
827 G4double dr = (r-v0_vertex->
r), dz = (z-v0_vertex->
z);
830 G4double distance2 = distOut*distOut;
831 if (distance2 > bestDistance2) {
continue; }
846 else if (q > edge->
length)
856 if (distance2 < bestDistance2)
858 bestDistance2 = distance2;
859 if (testMe !=
nullptr)
862 answer = (distNorm <= 0);
863 if (base3Dnorm !=
nullptr)
865 *base3Dnorm = testMe;
866 *head3Dnorm = &testMe->
norm3D;
871 answer = (distOut <= 0);
872 if (base3Dnorm !=
nullptr)
874 *base3Dnorm = v0_vertex;
875 *head3Dnorm = &edge->
norm3D;
879 }
while( ++edge < edges + numEdges );
881 *bestDist2 = bestDistance2;
900 *p4=p2 + lambda1*w + lambda2*v;
908 if ( fSurfaceArea==0. ) { Triangulate(); }
917 return surface_point;
930 return ((b.
x()-a.
x())*(c.
y()-a.
y())-
931 (c.
x()-a.
x())*(b.
y()-a.
y()));
940 return Area2(a,b,c)>0;
949 return Area2(a,b,c)>=0;
958 return Area2(a,b,c)==0;
968 if( Collinear(a,b,c) || Collinear(a,b,d)||
969 Collinear(c,d,a) || Collinear(c,d,b) ) {
return false; }
972 Positive = !(Left(a,b,c))^!(Left(a,b,d));
973 return Positive && ((!Left(c,d,a)^!Left(c,d,b)) != 0);
981 if( !Collinear(a,b,c) ) {
return false; }
985 return ((a.
x()<=c.
x())&&(c.
x()<=b.
x()))||
986 ((a.
x()>=c.
x())&&(c.
x()>=b.
x()));
989 return ((a.
y()<=c.
y())&&(c.
y()<=b.
y()))||
990 ((a.
y()>=c.
y())&&(c.
y()>=b.
y()));
1000 if( IntersectProp(a,b,c,d) ) {
return true; }
1002 if( Between(a,b,c) || Between(a,b,d)
1003 || Between(c,d,a) || Between(c,d,b) ) {
return true; }
1014 G4PolyPhiFaceVertex *corner = triangles;
1015 G4PolyPhiFaceVertex *corner_next=triangles;
1020 corner_next=corner->
next;
1024 if( (corner!=a)&&(corner_next!=a)
1025 &&(corner!=b)&&(corner_next!=b) )
1032 if(
Intersect(rz1,rz2,rz3,rz4) ) {
return false; }
1034 corner=corner->
next;
1036 }
while( corner != triangles );
1048 G4PolyPhiFaceVertex *
a0,*a1;
1057 if(LeftOn(arz,arz1,arz0))
1059 return Left(arz,brz,arz0)&&Left(brz,arz,arz1);
1063 return !( LeftOn(arz,brz,arz1)&&LeftOn(brz,arz,arz0));
1071 return InCone(a,b) && InCone(b,a) && Diagonalie(a,b);
1077void G4PolyPhiFace::EarInit()
1079 G4PolyPhiFaceVertex* corner = triangles;
1080 G4PolyPhiFaceVertex* c_prev, *c_next;
1086 c_next=corner->
next;
1087 c_prev=corner->
prev;
1091 corner->
ear=Diagonal(c_prev,c_next);
1092 corner=corner->
next;
1094 }
while( corner!=triangles );
1100void G4PolyPhiFace::Triangulate()
1105 const std::size_t maxEdges = (numEdges > 0) ? numEdges : 1;
1106 auto tri_help =
new G4PolyPhiFaceVertex[maxEdges];
1107 triangles = tri_help;
1108 G4PolyPhiFaceVertex* triang = triangles;
1110 std::vector<G4double> areas;
1111 std::vector<G4ThreeVector> points;
1113 G4PolyPhiFaceVertex *v0,*v1,*v2,*v3,*v4;
1118 G4PolyPhiFaceVertex* helper = corners;
1119 G4PolyPhiFaceVertex* helper2 = corners;
1122 triang->
r = helper->
r;
1123 triang->
z = helper->
z;
1124 triang->
x = helper->
x;
1125 triang->
y = helper->
y;
1129 if( helper==corners )
1130 { triang->
prev=triangles+maxEdges-1; }
1132 { triang->
prev=helper2; }
1136 if( helper<corners+maxEdges-1 )
1137 { triang->
next=triang+1; }
1139 { triang->
next=triangles; }
1141 helper=helper->
next;
1142 triang=triang->
next;
1144 }
while( helper!=corners );
1151 const G4int max_n_loops=numEdges*10000;
1173 G4double result1 = SurfaceTriangle(p1,p2,p3,&p4 );
1174 points.push_back(p4);
1175 areas.push_back(result1);
1180 v1->
ear=Diagonal(v0,v3);
1181 v3->
ear=Diagonal(v1,v4);
1196 }
while( v2!=triangles );
1203 "Maximum number of steps is reached for triangulation!" );
1207 if(v2->
next !=
nullptr)
1215 G4double result1 = SurfaceTriangle(p1,p2,p3,&p4 );
1216 points.push_back(p4);
1217 areas.push_back(result1);
1223 fSurfaceArea = area;
1232 Achose1=0; Achose2=0.;
1237 if(chose>=Achose1 && chose<Achose2)
1241 surface_point=point;
1244 ++i; Achose1=Achose2;
1245 }
while( i<numEdges-2 );
const G4double kCarTolerance
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4double G4QuickRand(uint32_t seed=0)
CLHEP::Hep3Vector G4ThreeVector
CLHEP::Hep2Vector G4TwoVector
Hep3Vector cross(const Hep3Vector &) const
double dot(const Hep3Vector &) const
G4ClippablePolygon in a utility class defining a polygon that can be clipped by a voxel.
G4bool PartialClip(const G4VoxelLimits &voxelLimit, const EAxis IgnoreMe)
void AddVertexInOrder(const G4ThreeVector &vertex)
void SetNormal(const G4ThreeVector &newNormal)
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
G4PolyPhiFace is a face that bounds a polycone or polyhedra when it has a phi opening....
G4double Distance(const G4ThreeVector &p, G4bool outgoing) override
EInside Inside(const G4ThreeVector &p, G4double tolerance, G4double *bestDistance) override
void Diagnose(G4VSolid *solid)
void CalculateExtent(const EAxis axis, const G4VoxelLimits &voxelLimit, const G4AffineTransform &tranform, G4SolidExtentList &extentList) override
G4PolyPhiFace & operator=(const G4PolyPhiFace &source)
G4double Extent(const G4ThreeVector axis) override
G4ThreeVector Normal(const G4ThreeVector &p, G4double *bestDistance) override
G4bool Intersect(const G4ThreeVector &p, const G4ThreeVector &v, G4bool outgoing, G4double surfTolerance, G4double &distance, G4double &distFromSurface, G4ThreeVector &normal, G4bool &allBehind) override
~G4PolyPhiFace() override
G4double SurfaceArea() override
G4PolyPhiFace(const G4ReduciblePolygon *rz, G4double phi, G4double deltaPhi, G4double phiOther)
G4ReduciblePolygonIterator is companion class for iterating over the vertices of a polygon.
G4ReduciblePolygon is a utility class used to specify, test, reduce, and/or otherwise manipulate a 2D...
G4int NumVertices() const
G4SolidExtentList is utility class designed for calculating the extent of a CSG-like solid for a voxe...
void AddSurface(const G4ClippablePolygon &surface)
virtual G4ThreeVector GetPointOnFace()=0
G4VSolid is an abstract base class for solids, physical shapes that can be tracked through....
virtual EInside Inside(const G4ThreeVector &p) const =0
G4VoxelLimits represents limitation/restrictions of space, where restrictions are only made perpendic...
const axis_t axis_to_type< N >::axis
G4PolyPhiFaceVertex * next
G4PolyPhiFaceVertex * prev