#include <G4PolyPhiFace.hh>
Inheritance diagram for G4PolyPhiFace:
Definition at line 85 of file G4PolyPhiFace.hh.
G4PolyPhiFace::G4PolyPhiFace | ( | const G4ReduciblePolygon * | rz, | |
G4double | phi, | |||
G4double | deltaPhi, | |||
G4double | phiOther | |||
) |
Definition at line 61 of file G4PolyPhiFace.cc.
References allBehind, G4ReduciblePolygon::Amax(), G4ReduciblePolygon::Amin(), G4ReduciblePolygonIterator::Begin(), G4ReduciblePolygon::Bmax(), G4ReduciblePolygon::Bmin(), corners, DBL_MIN, edges, G4ReduciblePolygonIterator::GetA(), G4ReduciblePolygonIterator::GetB(), G4GeometryTolerance::GetInstance(), G4GeometryTolerance::GetSurfaceTolerance(), kCarTolerance, G4PolyPhiFaceEdge::length, G4ReduciblePolygonIterator::Next(), G4PolyPhiFaceVertex::next, G4PolyPhiFaceVertex::norm3D, G4PolyPhiFaceEdge::norm3D, normal, numEdges, G4ReduciblePolygon::NumVertices(), G4PolyPhiFaceVertex::prev, G4PolyPhiFaceVertex::r, radial, rMax, rMin, G4PolyPhiFaceVertex::rNorm, surface, G4PolyPhiFaceEdge::tr, G4PolyPhiFaceEdge::tz, G4PolyPhiFaceEdge::v0, G4PolyPhiFaceEdge::v1, G4PolyPhiFaceVertex::x, G4PolyPhiFaceVertex::y, G4PolyPhiFaceVertex::z, zMax, zMin, and G4PolyPhiFaceVertex::zNorm.
Referenced by Clone().
00065 : fSurfaceArea(0.), triangles(0) 00066 { 00067 kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance(); 00068 00069 numEdges = rz->NumVertices(); 00070 00071 rMin = rz->Amin(); 00072 rMax = rz->Amax(); 00073 zMin = rz->Bmin(); 00074 zMax = rz->Bmax(); 00075 00076 // 00077 // Is this the "starting" phi edge of the two? 00078 // 00079 G4bool start = (phiOther > phi); 00080 00081 // 00082 // Build radial vector 00083 // 00084 radial = G4ThreeVector( std::cos(phi), std::sin(phi), 0.0 ); 00085 00086 // 00087 // Build normal 00088 // 00089 G4double zSign = start ? 1 : -1; 00090 normal = G4ThreeVector( zSign*radial.y(), -zSign*radial.x(), 0 ); 00091 00092 // 00093 // Is allBehind? 00094 // 00095 allBehind = (zSign*(std::cos(phiOther)*radial.y() - std::sin(phiOther)*radial.x()) < 0); 00096 00097 // 00098 // Adjacent edges 00099 // 00100 G4double midPhi = phi + (start ? +0.5 : -0.5)*deltaPhi; 00101 G4double cosMid = std::cos(midPhi), 00102 sinMid = std::sin(midPhi); 00103 00104 // 00105 // Allocate corners 00106 // 00107 corners = new G4PolyPhiFaceVertex[numEdges]; 00108 // 00109 // Fill them 00110 // 00111 G4ReduciblePolygonIterator iterRZ(rz); 00112 00113 G4PolyPhiFaceVertex *corn = corners; 00114 G4PolyPhiFaceVertex *helper=corners; 00115 00116 iterRZ.Begin(); 00117 do 00118 { 00119 corn->r = iterRZ.GetA(); 00120 corn->z = iterRZ.GetB(); 00121 corn->x = corn->r*radial.x(); 00122 corn->y = corn->r*radial.y(); 00123 00124 // Add pointer on prev corner 00125 // 00126 if( corn == corners ) 00127 { corn->prev = corners+numEdges-1;} 00128 else 00129 { corn->prev = helper; } 00130 00131 // Add pointer on next corner 00132 // 00133 if( corn < corners+numEdges-1 ) 00134 { corn->next = corn+1;} 00135 else 00136 { corn->next = corners; } 00137 00138 helper = corn; 00139 } while( ++corn, iterRZ.Next() ); 00140 00141 // 00142 // Allocate edges 00143 // 00144 edges = new G4PolyPhiFaceEdge[numEdges]; 00145 00146 // 00147 // Fill them 00148 // 00149 G4double rFact = std::cos(0.5*deltaPhi); 00150 G4double rFactNormalize = 1.0/std::sqrt(1.0+rFact*rFact); 00151 00152 G4PolyPhiFaceVertex *prev = corners+numEdges-1, 00153 *here = corners; 00154 G4PolyPhiFaceEdge *edge = edges; 00155 do 00156 { 00157 G4ThreeVector sideNorm; 00158 00159 edge->v0 = prev; 00160 edge->v1 = here; 00161 00162 G4double dr = here->r - prev->r, 00163 dz = here->z - prev->z; 00164 00165 edge->length = std::sqrt( dr*dr + dz*dz ); 00166 00167 edge->tr = dr/edge->length; 00168 edge->tz = dz/edge->length; 00169 00170 if ((here->r < DBL_MIN) && (prev->r < DBL_MIN)) 00171 { 00172 // 00173 // Sigh! Always exceptions! 00174 // This edge runs at r==0, so its adjoing surface is not a 00175 // PolyconeSide or PolyhedraSide, but the opposite PolyPhiFace. 00176 // 00177 G4double zSignOther = start ? -1 : 1; 00178 sideNorm = G4ThreeVector( zSignOther*std::sin(phiOther), 00179 -zSignOther*std::cos(phiOther), 0 ); 00180 } 00181 else 00182 { 00183 sideNorm = G4ThreeVector( edge->tz*cosMid, 00184 edge->tz*sinMid, 00185 -edge->tr*rFact ); 00186 sideNorm *= rFactNormalize; 00187 } 00188 sideNorm += normal; 00189 00190 edge->norm3D = sideNorm.unit(); 00191 } while( edge++, prev=here, ++here < corners+numEdges ); 00192 00193 // 00194 // Go back and fill in corner "normals" 00195 // 00196 G4PolyPhiFaceEdge *prevEdge = edges+numEdges-1; 00197 edge = edges; 00198 do 00199 { 00200 // 00201 // Calculate vertex 2D normals (on the phi surface) 00202 // 00203 G4double rPart = prevEdge->tr + edge->tr; 00204 G4double zPart = prevEdge->tz + edge->tz; 00205 G4double norm = std::sqrt( rPart*rPart + zPart*zPart ); 00206 G4double rNorm = +zPart/norm; 00207 G4double zNorm = -rPart/norm; 00208 00209 edge->v0->rNorm = rNorm; 00210 edge->v0->zNorm = zNorm; 00211 00212 // 00213 // Calculate the 3D normals. 00214 // 00215 // Find the vector perpendicular to the z axis 00216 // that defines the plane that contains the vertex normal 00217 // 00218 G4ThreeVector xyVector; 00219 00220 if (edge->v0->r < DBL_MIN) 00221 { 00222 // 00223 // This is a vertex at r==0, which is a special 00224 // case. The normal we will construct lays in the 00225 // plane at the center of the phi opening. 00226 // 00227 // We also know that rNorm < 0 00228 // 00229 G4double zSignOther = start ? -1 : 1; 00230 G4ThreeVector normalOther( zSignOther*std::sin(phiOther), 00231 -zSignOther*std::cos(phiOther), 0 ); 00232 00233 xyVector = - normal - normalOther; 00234 } 00235 else 00236 { 00237 // 00238 // This is a vertex at r > 0. The plane 00239 // is the average of the normal and the 00240 // normal of the adjacent phi face 00241 // 00242 xyVector = G4ThreeVector( cosMid, sinMid, 0 ); 00243 if (rNorm < 0) 00244 xyVector -= normal; 00245 else 00246 xyVector += normal; 00247 } 00248 00249 // 00250 // Combine it with the r/z direction from the face 00251 // 00252 edge->v0->norm3D = rNorm*xyVector.unit() + G4ThreeVector( 0, 0, zNorm ); 00253 } while( prevEdge=edge, ++edge < edges+numEdges ); 00254 00255 // 00256 // Build point on surface 00257 // 00258 G4double rAve = 0.5*(rMax-rMin), 00259 zAve = 0.5*(zMax-zMin); 00260 surface = G4ThreeVector( rAve*radial.x(), rAve*radial.y(), zAve ); 00261 }
G4PolyPhiFace::~G4PolyPhiFace | ( | ) | [virtual] |
G4PolyPhiFace::G4PolyPhiFace | ( | const G4PolyPhiFace & | source | ) |
Definition at line 311 of file G4PolyPhiFace.cc.
References CopyStuff().
00312 : G4VCSGface() 00313 { 00314 CopyStuff( source ); 00315 }
G4PolyPhiFace::G4PolyPhiFace | ( | __void__ & | ) |
Definition at line 291 of file G4PolyPhiFace.cc.
00292 : numEdges(0), edges(0), corners(0), rMin(0.), rMax(0.), zMin(0.), zMax(0.), 00293 allBehind(false), kCarTolerance(0.), fSurfaceArea(0.), triangles(0) 00294 { 00295 }
G4double G4PolyPhiFace::Area2 | ( | G4TwoVector | a, | |
G4TwoVector | b, | |||
G4TwoVector | c | |||
) | [protected] |
G4bool G4PolyPhiFace::Between | ( | G4TwoVector | a, | |
G4TwoVector | b, | |||
G4TwoVector | c | |||
) | [protected] |
Definition at line 1024 of file G4PolyPhiFace.cc.
References Collinear().
Referenced by Intersect().
01025 { 01026 if( !Collinear(a,b,c) ) { return false; } 01027 01028 if(a.x()!=b.x()) 01029 { 01030 return ((a.x()<=c.x())&&(c.x()<=b.x()))|| 01031 ((a.x()>=c.x())&&(c.x()>=b.x())); 01032 } 01033 else 01034 { 01035 return ((a.y()<=c.y())&&(c.y()<=b.y()))|| 01036 ((a.y()>=c.y())&&(c.y()>=b.y())); 01037 } 01038 }
void G4PolyPhiFace::CalculateExtent | ( | const EAxis | axis, | |
const G4VoxelLimits & | voxelLimit, | |||
const G4AffineTransform & | tranform, | |||
G4SolidExtentList & | extentList | |||
) | [virtual] |
Implements G4VCSGface.
Definition at line 628 of file G4PolyPhiFace.cc.
References G4SolidExtentList::AddSurface(), G4ClippablePolygon::AddVertexInOrder(), corners, normal, numEdges, G4ClippablePolygon::PartialClip(), G4PolyPhiFaceVertex::r, radial, G4ClippablePolygon::SetNormal(), G4AffineTransform::TransformAxis(), G4AffineTransform::TransformPoint(), and G4PolyPhiFaceVertex::z.
00632 { 00633 // 00634 // Construct a (sometimes big) clippable polygon, 00635 // 00636 // Perform the necessary transformations while doing so 00637 // 00638 G4ClippablePolygon polygon; 00639 00640 G4PolyPhiFaceVertex *corner = corners; 00641 do 00642 { 00643 G4ThreeVector point( 0, 0, corner->z ); 00644 point += radial*corner->r; 00645 00646 polygon.AddVertexInOrder( transform.TransformPoint( point ) ); 00647 } while( ++corner < corners + numEdges ); 00648 00649 // 00650 // Clip away 00651 // 00652 if (polygon.PartialClip( voxelLimit, axis )) 00653 { 00654 // 00655 // Add it to the list 00656 // 00657 polygon.SetNormal( transform.TransformAxis(normal) ); 00658 extentList.AddSurface( polygon ); 00659 } 00660 }
G4VCSGface * G4PolyPhiFace::Clone | ( | ) | [inline, virtual] |
Implements G4VCSGface.
Definition at line 39 of file G4PolyPhiFace.icc.
References G4PolyPhiFace().
00040 { 00041 return new G4PolyPhiFace(*this); 00042 }
G4bool G4PolyPhiFace::Collinear | ( | G4TwoVector | a, | |
G4TwoVector | b, | |||
G4TwoVector | c | |||
) | [protected] |
Definition at line 997 of file G4PolyPhiFace.cc.
References Area2().
Referenced by Between(), and IntersectProp().
01000 { 01001 return Area2(a,b,c)==0; 01002 }
void G4PolyPhiFace::CopyStuff | ( | const G4PolyPhiFace & | source | ) | [protected] |
Definition at line 337 of file G4PolyPhiFace.cc.
References allBehind, corners, edges, fSurfaceArea, kCarTolerance, normal, numEdges, radial, rMax, rMin, surface, triangles, G4PolyPhiFaceEdge::v0, G4PolyPhiFaceEdge::v1, zMax, and zMin.
Referenced by G4PolyPhiFace(), and operator=().
00338 { 00339 // 00340 // The simple stuff 00341 // 00342 numEdges = source.numEdges; 00343 normal = source.normal; 00344 radial = source.radial; 00345 surface = source.surface; 00346 rMin = source.rMin; 00347 rMax = source.rMax; 00348 zMin = source.zMin; 00349 zMax = source.zMax; 00350 allBehind = source.allBehind; 00351 triangles = 0; 00352 00353 kCarTolerance = source.kCarTolerance; 00354 fSurfaceArea = source.fSurfaceArea; 00355 00356 // 00357 // Corner dynamic array 00358 // 00359 corners = new G4PolyPhiFaceVertex[numEdges]; 00360 G4PolyPhiFaceVertex *corn = corners, 00361 *sourceCorn = source.corners; 00362 do 00363 { 00364 *corn = *sourceCorn; 00365 } while( ++sourceCorn, ++corn < corners+numEdges ); 00366 00367 // 00368 // Edge dynamic array 00369 // 00370 edges = new G4PolyPhiFaceEdge[numEdges]; 00371 00372 G4PolyPhiFaceVertex *prev = corners+numEdges-1, 00373 *here = corners; 00374 G4PolyPhiFaceEdge *edge = edges, 00375 *sourceEdge = source.edges; 00376 do 00377 { 00378 *edge = *sourceEdge; 00379 edge->v0 = prev; 00380 edge->v1 = here; 00381 } while( ++sourceEdge, ++edge, prev=here, ++here < corners+numEdges ); 00382 }
void G4PolyPhiFace::Diagnose | ( | G4VSolid * | solid | ) |
Definition at line 272 of file G4PolyPhiFace.cc.
References corners, FatalException, G4Exception(), G4VSolid::Inside(), kInside, G4PolyPhiFaceVertex::norm3D, numEdges, G4PolyPhiFaceVertex::x, G4PolyPhiFaceVertex::y, and G4PolyPhiFaceVertex::z.
00273 { 00274 G4PolyPhiFaceVertex *corner = corners; 00275 do 00276 { 00277 G4ThreeVector test(corner->x, corner->y, corner->z); 00278 test -= 1E-6*corner->norm3D; 00279 00280 if (owner->Inside(test) != kInside) 00281 G4Exception( "G4PolyPhiFace::Diagnose()", "GeomSolids0002", 00282 FatalException, "Bad vertex normal found." ); 00283 } while( ++corner < corners+numEdges ); 00284 }
G4bool G4PolyPhiFace::Diagonal | ( | G4PolyPhiFaceVertex * | a, | |
G4PolyPhiFaceVertex * | b | |||
) | [protected] |
Definition at line 1124 of file G4PolyPhiFace.cc.
References Diagonalie(), and InCone().
Referenced by EarInit(), and Triangulate().
01125 { 01126 return InCone(a,b) && InCone(b,a) && Diagonalie(a,b); 01127 }
G4bool G4PolyPhiFace::Diagonalie | ( | G4PolyPhiFaceVertex * | a, | |
G4PolyPhiFaceVertex * | b | |||
) | [protected] |
Definition at line 1063 of file G4PolyPhiFace.cc.
References Intersect(), G4PolyPhiFaceVertex::next, G4PolyPhiFaceVertex::r, triangles, and G4PolyPhiFaceVertex::z.
Referenced by Diagonal().
01065 { 01066 G4PolyPhiFaceVertex *corner = triangles; 01067 G4PolyPhiFaceVertex *corner_next=triangles; 01068 01069 // For each Edge (corner,corner_next) 01070 do 01071 { 01072 corner_next=corner->next; 01073 01074 // Skip edges incident to a of b 01075 // 01076 if( (corner!=a)&&(corner_next!=a) 01077 &&(corner!=b)&&(corner_next!=b) ) 01078 { 01079 G4TwoVector rz1,rz2,rz3,rz4; 01080 rz1 = G4TwoVector(a->r,a->z); 01081 rz2 = G4TwoVector(b->r,b->z); 01082 rz3 = G4TwoVector(corner->r,corner->z); 01083 rz4 = G4TwoVector(corner_next->r,corner_next->z); 01084 if( Intersect(rz1,rz2,rz3,rz4) ) { return false; } 01085 } 01086 corner=corner->next; 01087 01088 } while( corner != triangles ); 01089 01090 return true; 01091 }
G4double G4PolyPhiFace::Distance | ( | const G4ThreeVector & | p, | |
G4bool | outgoing | |||
) | [virtual] |
Implements G4VCSGface.
Definition at line 445 of file G4PolyPhiFace.cc.
References InsideEdges(), kCarTolerance, normal, radial, and surface.
00446 { 00447 G4double normSign = outgoing ? +1 : -1; 00448 // 00449 // Correct normal? 00450 // 00451 G4ThreeVector ps = p - surface; 00452 G4double distPhi = -normSign*normal.dot(ps); 00453 00454 if (distPhi < -0.5*kCarTolerance) 00455 return kInfinity; 00456 else if (distPhi < 0) 00457 distPhi = 0.0; 00458 00459 // 00460 // Calculate projected point in r,z 00461 // 00462 G4double r = radial.dot(p); 00463 00464 // 00465 // Are we inside the face? 00466 // 00467 G4double distRZ2; 00468 00469 if (InsideEdges( r, p.z(), &distRZ2, 0 )) 00470 { 00471 // 00472 // Yup, answer is just distPhi 00473 // 00474 return distPhi; 00475 } 00476 else 00477 { 00478 // 00479 // Nope. Penalize by distance out 00480 // 00481 return std::sqrt( distPhi*distPhi + distRZ2 ); 00482 } 00483 }
void G4PolyPhiFace::EarInit | ( | ) | [protected] |
Definition at line 1133 of file G4PolyPhiFace.cc.
References Diagonal(), G4PolyPhiFaceVertex::ear, G4PolyPhiFaceVertex::next, G4PolyPhiFaceVertex::prev, and triangles.
Referenced by Triangulate().
01134 { 01135 G4PolyPhiFaceVertex *corner = triangles; 01136 G4PolyPhiFaceVertex *c_prev,*c_next; 01137 01138 do 01139 { 01140 // We need to determine three consecutive vertices 01141 // 01142 c_next=corner->next; 01143 c_prev=corner->prev; 01144 01145 // Calculation of ears 01146 // 01147 corner->ear=Diagonal(c_prev,c_next); 01148 corner=corner->next; 01149 01150 } while( corner!=triangles ); 01151 }
G4double G4PolyPhiFace::ExactZOrder | ( | G4double | z, | |
G4double | qx, | |||
G4double | qy, | |||
G4double | qz, | |||
const G4ThreeVector & | v, | |||
G4double | normSign, | |||
const G4PolyPhiFaceVertex * | vert | |||
) | const [inline, protected] |
Definition at line 57 of file G4PolyPhiFace.icc.
References kCarTolerance, normal, radial, G4PolyPhiFaceVertex::x, G4PolyPhiFaceVertex::y, and G4PolyPhiFaceVertex::z.
Referenced by InsideEdgesExact().
00062 { 00063 G4double answer = vert->z - z; 00064 if (std::fabs(answer) < kCarTolerance) 00065 { 00066 G4ThreeVector qa( qx - vert->x + radial.x(), 00067 qy - vert->y + radial.y(), qz - vert->z ), 00068 qb( qx - vert->x, qy - vert->y, qz - vert->z ); 00069 G4ThreeVector qacb = qa.cross(qb); 00070 00071 answer = normSign*qacb.dot(v)*(normal.y()*radial.x()-normal.x()*radial.y()); 00072 } 00073 00074 return answer; 00075 }
G4double G4PolyPhiFace::Extent | ( | const G4ThreeVector | axis | ) | [virtual] |
Implements G4VCSGface.
Definition at line 606 of file G4PolyPhiFace.cc.
References corners, numEdges, G4PolyPhiFaceVertex::r, radial, and G4PolyPhiFaceVertex::z.
00607 { 00608 G4double max = -kInfinity; 00609 00610 G4PolyPhiFaceVertex *corner = corners; 00611 do 00612 { 00613 G4double here = axis.x()*corner->r*radial.x() 00614 + axis.y()*corner->r*radial.y() 00615 + axis.z()*corner->z; 00616 if (here > max) max = here; 00617 } while( ++corner < corners + numEdges ); 00618 00619 return max; 00620 }
G4ThreeVector G4PolyPhiFace::GetPointOnFace | ( | ) | [virtual] |
Implements G4VCSGface.
Definition at line 953 of file G4PolyPhiFace.cc.
References surface_point, and Triangulate().
00954 { 00955 Triangulate(); 00956 return surface_point; 00957 }
G4bool G4PolyPhiFace::InCone | ( | G4PolyPhiFaceVertex * | a, | |
G4PolyPhiFaceVertex * | b | |||
) | [protected] |
Definition at line 1097 of file G4PolyPhiFace.cc.
References Left(), LeftOn(), G4PolyPhiFaceVertex::next, G4PolyPhiFaceVertex::prev, G4PolyPhiFaceVertex::r, and G4PolyPhiFaceVertex::z.
Referenced by Diagonal().
01098 { 01099 // a0,a and a1 are consecutive vertices 01100 // 01101 G4PolyPhiFaceVertex *a0,*a1; 01102 a1=a->next; 01103 a0=a->prev; 01104 01105 G4TwoVector arz,arz0,arz1,brz; 01106 arz=G4TwoVector(a->r,a->z);arz0=G4TwoVector(a0->r,a0->z); 01107 arz1=G4TwoVector(a1->r,a1->z);brz=G4TwoVector(b->r,b->z); 01108 01109 01110 if(LeftOn(arz,arz1,arz0)) // If a is convex vertex 01111 { 01112 return Left(arz,brz,arz0)&&Left(brz,arz,arz1); 01113 } 01114 else // Else a is reflex 01115 { 01116 return !( LeftOn(arz,brz,arz1)&&LeftOn(brz,arz,arz0)); 01117 } 01118 }
EInside G4PolyPhiFace::Inside | ( | const G4ThreeVector & | p, | |
G4double | tolerance, | |||
G4double * | bestDistance | |||
) | [virtual] |
Implements G4VCSGface.
Definition at line 489 of file G4PolyPhiFace.cc.
References InsideEdges(), kInside, kOutside, kSurface, normal, radial, and surface.
00492 { 00493 // 00494 // Get distance along phi, which if negative means the point 00495 // is nominally inside the shape. 00496 // 00497 G4ThreeVector ps = p - surface; 00498 G4double distPhi = normal.dot(ps); 00499 00500 // 00501 // Calculate projected point in r,z 00502 // 00503 G4double r = radial.dot(p); 00504 00505 // 00506 // Are we inside the face? 00507 // 00508 G4double distRZ2; 00509 G4PolyPhiFaceVertex *base3Dnorm; 00510 G4ThreeVector *head3Dnorm; 00511 00512 if (InsideEdges( r, p.z(), &distRZ2, &base3Dnorm, &head3Dnorm )) 00513 { 00514 // 00515 // Looks like we're inside. Distance is distance in phi. 00516 // 00517 *bestDistance = std::fabs(distPhi); 00518 00519 // 00520 // Use distPhi to decide fate 00521 // 00522 if (distPhi < -tolerance) return kInside; 00523 if (distPhi < tolerance) return kSurface; 00524 return kOutside; 00525 } 00526 else 00527 { 00528 // 00529 // We're outside the extent of the face, 00530 // so the distance is penalized by distance from edges in RZ 00531 // 00532 *bestDistance = std::sqrt( distPhi*distPhi + distRZ2 ); 00533 00534 // 00535 // Use edge normal to decide fate 00536 // 00537 G4ThreeVector cc( base3Dnorm->r*radial.x(), 00538 base3Dnorm->r*radial.y(), 00539 base3Dnorm->z ); 00540 cc = p - cc; 00541 G4double normDist = head3Dnorm->dot(cc); 00542 if ( distRZ2 > tolerance*tolerance ) 00543 { 00544 // 00545 // We're far enough away that kSurface is not possible 00546 // 00547 return normDist < 0 ? kInside : kOutside; 00548 } 00549 00550 if (normDist < -tolerance) return kInside; 00551 if (normDist < tolerance) return kSurface; 00552 return kOutside; 00553 } 00554 }
G4bool G4PolyPhiFace::InsideEdges | ( | G4double | r, | |
G4double | z, | |||
G4double * | distRZ2, | |||
G4PolyPhiFaceVertex ** | base3Dnorm = 0 , |
|||
G4ThreeVector ** | head3Dnorm = 0 | |||
) | [protected] |
Definition at line 844 of file G4PolyPhiFace.cc.
References edges, G4PolyPhiFaceEdge::length, G4PolyPhiFaceEdge::norm3D, G4PolyPhiFaceVertex::norm3D, numEdges, G4PolyPhiFaceVertex::r, G4PolyPhiFaceVertex::rNorm, G4PolyPhiFaceEdge::tr, G4PolyPhiFaceEdge::tz, G4PolyPhiFaceEdge::v0, G4PolyPhiFaceEdge::v1, G4PolyPhiFaceVertex::z, and G4PolyPhiFaceVertex::zNorm.
00848 { 00849 G4double bestDistance2 = kInfinity; 00850 G4bool answer = 0; 00851 00852 G4PolyPhiFaceEdge *edge = edges; 00853 do 00854 { 00855 G4PolyPhiFaceVertex *testMe; 00856 // 00857 // Get distance perpendicular to the edge 00858 // 00859 G4double dr = (r-edge->v0->r), dz = (z-edge->v0->z); 00860 00861 G4double distOut = dr*edge->tz - dz*edge->tr; 00862 G4double distance2 = distOut*distOut; 00863 if (distance2 > bestDistance2) continue; // No hope! 00864 00865 // 00866 // Check to see if normal intersects edge within the edge's boundary 00867 // 00868 G4double q = dr*edge->tr + dz*edge->tz; 00869 00870 // 00871 // If it doesn't, penalize distance2 appropriately 00872 // 00873 if (q < 0) 00874 { 00875 distance2 += q*q; 00876 testMe = edge->v0; 00877 } 00878 else if (q > edge->length) 00879 { 00880 G4double s2 = q-edge->length; 00881 distance2 += s2*s2; 00882 testMe = edge->v1; 00883 } 00884 else 00885 { 00886 testMe = 0; 00887 } 00888 00889 // 00890 // Closest edge so far? 00891 // 00892 if (distance2 < bestDistance2) 00893 { 00894 bestDistance2 = distance2; 00895 if (testMe) 00896 { 00897 G4double distNorm = dr*testMe->rNorm + dz*testMe->zNorm; 00898 answer = (distNorm <= 0); 00899 if (base3Dnorm) 00900 { 00901 *base3Dnorm = testMe; 00902 *head3Dnorm = &testMe->norm3D; 00903 } 00904 } 00905 else 00906 { 00907 answer = (distOut <= 0); 00908 if (base3Dnorm) 00909 { 00910 *base3Dnorm = edge->v0; 00911 *head3Dnorm = &edge->norm3D; 00912 } 00913 } 00914 } 00915 } while( ++edge < edges + numEdges ); 00916 00917 *bestDist2 = bestDistance2; 00918 return answer; 00919 }
Definition at line 822 of file G4PolyPhiFace.cc.
Referenced by Distance(), Inside(), and Normal().
00823 { 00824 // 00825 // Quick check of extent 00826 // 00827 if ( r < rMin || r > rMax ) return false; 00828 if ( z < zMin || z > zMax ) return false; 00829 00830 // 00831 // More thorough check 00832 // 00833 G4double notUsed; 00834 00835 return InsideEdges( r, z, ¬Used, 0 ); 00836 }
G4bool G4PolyPhiFace::InsideEdgesExact | ( | G4double | r, | |
G4double | z, | |||
G4double | normSign, | |||
const G4ThreeVector & | p, | |||
const G4ThreeVector & | v | |||
) | [protected] |
Definition at line 683 of file G4PolyPhiFace.cc.
References corners, ExactZOrder(), kCarTolerance, numEdges, rMax, rMin, G4PolyPhiFaceVertex::x, G4PolyPhiFaceVertex::y, G4PolyPhiFaceVertex::z, zMax, and zMin.
Referenced by Intersect().
00687 { 00688 // 00689 // Quick check of extent 00690 // 00691 if ( (r < rMin-kCarTolerance) 00692 || (r > rMax+kCarTolerance) ) return false; 00693 00694 if ( (z < zMin-kCarTolerance) 00695 || (z > zMax+kCarTolerance) ) return false; 00696 00697 // 00698 // Exact check: loop over all vertices 00699 // 00700 G4double qx = p.x() + v.x(), 00701 qy = p.y() + v.y(), 00702 qz = p.z() + v.z(); 00703 00704 G4int answer = 0; 00705 G4PolyPhiFaceVertex *corn = corners, 00706 *prev = corners+numEdges-1; 00707 00708 G4double cornZ, prevZ; 00709 00710 prevZ = ExactZOrder( z, qx, qy, qz, v, normSign, prev ); 00711 do 00712 { 00713 // 00714 // Get z order of this vertex, and compare to previous vertex 00715 // 00716 cornZ = ExactZOrder( z, qx, qy, qz, v, normSign, corn ); 00717 00718 if (cornZ < 0) 00719 { 00720 if (prevZ < 0) continue; 00721 } 00722 else if (cornZ > 0) 00723 { 00724 if (prevZ > 0) continue; 00725 } 00726 else 00727 { 00728 // 00729 // By chance, we overlap exactly (within precision) with 00730 // the current vertex. Continue if the same happened previously 00731 // (e.g. the previous vertex had the same z value) 00732 // 00733 if (prevZ == 0) continue; 00734 00735 // 00736 // Otherwise, to decide what to do, we need to know what is 00737 // coming up next. Specifically, we need to find the next vertex 00738 // with a non-zero z order. 00739 // 00740 // One might worry about infinite loops, but the above conditional 00741 // should prevent it 00742 // 00743 G4PolyPhiFaceVertex *next = corn; 00744 G4double nextZ; 00745 do 00746 { 00747 next++; 00748 if (next == corners+numEdges) next = corners; 00749 00750 nextZ = ExactZOrder( z, qx, qy, qz, v, normSign, next ); 00751 } while( nextZ == 0 ); 00752 00753 // 00754 // If we won't be changing direction, go to the next vertex 00755 // 00756 if (nextZ*prevZ < 0) continue; 00757 } 00758 00759 00760 // 00761 // We overlap in z with the side of the face that stretches from 00762 // vertex "prev" to "corn". On which side (left or right) do 00763 // we lay with respect to this segment? 00764 // 00765 G4ThreeVector qa( qx - prev->x, qy - prev->y, qz - prev->z ), 00766 qb( qx - corn->x, qy - corn->y, qz - corn->z ); 00767 00768 G4double aboveOrBelow = normSign*qa.cross(qb).dot(v); 00769 00770 if (aboveOrBelow > 0) 00771 answer++; 00772 else if (aboveOrBelow < 0) 00773 answer--; 00774 else 00775 { 00776 // 00777 // A precisely zero answer here means we exactly 00778 // intersect (within roundoff) the edge of the face. 00779 // Return true in this case. 00780 // 00781 return true; 00782 } 00783 } while( prevZ = cornZ, prev=corn, ++corn < corners+numEdges ); 00784 00785 // G4int fanswer = std::abs(answer); 00786 // if (fanswer==1 || fanswer>2) { 00787 // G4cerr << "G4PolyPhiFace::InsideEdgesExact: answer is " 00788 // << answer << G4endl; 00789 // } 00790 00791 return answer!=0; 00792 }
G4bool G4PolyPhiFace::Intersect | ( | G4TwoVector | a, | |
G4TwoVector | b, | |||
G4TwoVector | c, | |||
G4TwoVector | d | |||
) | [protected] |
Definition at line 1044 of file G4PolyPhiFace.cc.
References Between(), and IntersectProp().
01047 { 01048 if( IntersectProp(a,b,c,d) ) 01049 { return true; } 01050 else if( Between(a,b,c)|| 01051 Between(a,b,d)|| 01052 Between(c,d,a)|| 01053 Between(c,d,b) ) 01054 { return true; } 01055 else 01056 { return false; } 01057 }
G4bool G4PolyPhiFace::Intersect | ( | const G4ThreeVector & | p, | |
const G4ThreeVector & | v, | |||
G4bool | outgoing, | |||
G4double | surfTolerance, | |||
G4double & | distance, | |||
G4double & | distFromSurface, | |||
G4ThreeVector & | normal, | |||
G4bool & | allBehind | |||
) | [virtual] |
Implements G4VCSGface.
Definition at line 388 of file G4PolyPhiFace.cc.
References allBehind, InsideEdgesExact(), normal, radial, and surface.
Referenced by Diagonalie().
00396 { 00397 G4double normSign = outgoing ? +1 : -1; 00398 00399 // 00400 // These don't change 00401 // 00402 isAllBehind = allBehind; 00403 aNormal = normal; 00404 00405 // 00406 // Correct normal? Here we have straight sides, and can safely ignore 00407 // intersections where the dot product with the normal is zero. 00408 // 00409 G4double dotProd = normSign*normal.dot(v); 00410 00411 if (dotProd <= 0) return false; 00412 00413 // 00414 // Calculate distance to surface. If the side is too far 00415 // behind the point, we must reject it. 00416 // 00417 G4ThreeVector ps = p - surface; 00418 distFromSurface = -normSign*ps.dot(normal); 00419 00420 if (distFromSurface < -surfTolerance) return false; 00421 00422 // 00423 // Calculate precise distance to intersection with the side 00424 // (along the trajectory, not normal to the surface) 00425 // 00426 distance = distFromSurface/dotProd; 00427 00428 // 00429 // Calculate intersection point in r,z 00430 // 00431 G4ThreeVector ip = p + distance*v; 00432 00433 G4double r = radial.dot(ip); 00434 00435 // 00436 // And is it inside the r/z extent? 00437 // 00438 return InsideEdgesExact( r, ip.z(), normSign, p, v ); 00439 }
G4bool G4PolyPhiFace::IntersectProp | ( | G4TwoVector | a, | |
G4TwoVector | b, | |||
G4TwoVector | c, | |||
G4TwoVector | d | |||
) | [protected] |
Definition at line 1008 of file G4PolyPhiFace.cc.
References Collinear(), and Left().
Referenced by Intersect().
01011 { 01012 if( Collinear(a,b,c) || Collinear(a,b,d)|| 01013 Collinear(c,d,a) || Collinear(c,d,b) ) { return false; } 01014 01015 G4bool Positive; 01016 Positive = !(Left(a,b,c))^!(Left(a,b,d)); 01017 return Positive && (!Left(c,d,a)^!Left(c,d,b)); 01018 }
G4bool G4PolyPhiFace::Left | ( | G4TwoVector | a, | |
G4TwoVector | b, | |||
G4TwoVector | c | |||
) | [protected] |
Definition at line 977 of file G4PolyPhiFace.cc.
References Area2().
Referenced by InCone(), and IntersectProp().
00980 { 00981 return Area2(a,b,c)>0; 00982 }
G4bool G4PolyPhiFace::LeftOn | ( | G4TwoVector | a, | |
G4TwoVector | b, | |||
G4TwoVector | c | |||
) | [protected] |
Definition at line 987 of file G4PolyPhiFace.cc.
References Area2().
Referenced by InCone().
00990 { 00991 return Area2(a,b,c)>=0; 00992 }
G4ThreeVector G4PolyPhiFace::Normal | ( | const G4ThreeVector & | p, | |
G4double * | bestDistance | |||
) | [virtual] |
Implements G4VCSGface.
Definition at line 563 of file G4PolyPhiFace.cc.
References InsideEdges(), normal, and radial.
00565 { 00566 // 00567 // Get distance along phi, which if negative means the point 00568 // is nominally inside the shape. 00569 // 00570 G4double distPhi = normal.dot(p); 00571 00572 // 00573 // Calculate projected point in r,z 00574 // 00575 G4double r = radial.dot(p); 00576 00577 // 00578 // Are we inside the face? 00579 // 00580 G4double distRZ2; 00581 00582 if (InsideEdges( r, p.z(), &distRZ2, 0 )) 00583 { 00584 // 00585 // Yup, answer is just distPhi 00586 // 00587 *bestDistance = std::fabs(distPhi); 00588 } 00589 else 00590 { 00591 // 00592 // Nope. Penalize by distance out 00593 // 00594 *bestDistance = std::sqrt( distPhi*distPhi + distRZ2 ); 00595 } 00596 00597 return normal; 00598 }
G4PolyPhiFace & G4PolyPhiFace::operator= | ( | const G4PolyPhiFace & | source | ) |
Definition at line 321 of file G4PolyPhiFace.cc.
References CopyStuff(), corners, and edges.
00322 { 00323 if (this == &source) { return *this; } 00324 00325 delete [] edges; 00326 delete [] corners; 00327 00328 CopyStuff( source ); 00329 00330 return *this; 00331 }
G4double G4PolyPhiFace::SurfaceArea | ( | ) | [virtual] |
Implements G4VCSGface.
Definition at line 944 of file G4PolyPhiFace.cc.
References fSurfaceArea, and Triangulate().
00945 { 00946 if ( fSurfaceArea==0. ) { Triangulate(); } 00947 return fSurfaceArea; 00948 }
G4double G4PolyPhiFace::SurfaceTriangle | ( | G4ThreeVector | p1, | |
G4ThreeVector | p2, | |||
G4ThreeVector | p3, | |||
G4ThreeVector * | p4 | |||
) |
Definition at line 925 of file G4PolyPhiFace.cc.
References G4UniformRand.
Referenced by Triangulate().
00929 { 00930 G4ThreeVector v, w; 00931 00932 v = p3 - p1; 00933 w = p1 - p2; 00934 G4double lambda1 = G4UniformRand(); 00935 G4double lambda2 = lambda1*G4UniformRand(); 00936 00937 *p4=p2 + lambda1*w + lambda2*v; 00938 return 0.5*(v.cross(w)).mag(); 00939 }
void G4PolyPhiFace::Triangulate | ( | ) | [protected] |
Definition at line 1157 of file G4PolyPhiFace.cc.
References corners, Diagonal(), G4PolyPhiFaceVertex::ear, EarInit(), FatalException, fSurfaceArea, G4Exception(), G4UniformRand, CLHEP::detail::n, G4PolyPhiFaceVertex::next, numEdges, G4PolyPhiFaceVertex::prev, G4PolyPhiFaceVertex::r, surface_point, SurfaceTriangle(), triangles, G4PolyPhiFaceVertex::x, G4PolyPhiFaceVertex::y, and G4PolyPhiFaceVertex::z.
Referenced by GetPointOnFace(), and SurfaceArea().
01158 { 01159 // The copy of Polycone is made and this copy is reordered in order to 01160 // have a list of triangles. This list is used for GetPointOnFace(). 01161 01162 G4PolyPhiFaceVertex *tri_help = new G4PolyPhiFaceVertex[numEdges]; 01163 triangles = tri_help; 01164 G4PolyPhiFaceVertex *triang = triangles; 01165 01166 std::vector<G4double> areas; 01167 std::vector<G4ThreeVector> points; 01168 G4double area=0.; 01169 G4PolyPhiFaceVertex *v0,*v1,*v2,*v3,*v4; 01170 v2=triangles; 01171 01172 // Make copy for prev/next for triang=corners 01173 // 01174 G4PolyPhiFaceVertex *helper = corners; 01175 G4PolyPhiFaceVertex *helper2 = corners; 01176 do 01177 { 01178 triang->r = helper->r; 01179 triang->z = helper->z; 01180 triang->x = helper->x; 01181 triang->y= helper->y; 01182 01183 // add pointer on prev corner 01184 // 01185 if( helper==corners ) 01186 { triang->prev=triangles+numEdges-1; } 01187 else 01188 { triang->prev=helper2; } 01189 01190 // add pointer on next corner 01191 // 01192 if( helper<corners+numEdges-1 ) 01193 { triang->next=triang+1; } 01194 else 01195 { triang->next=triangles; } 01196 helper2=triang; 01197 helper=helper->next; 01198 triang=triang->next; 01199 01200 } while( helper!=corners ); 01201 01202 EarInit(); 01203 01204 G4int n=numEdges; 01205 G4int i=0; 01206 G4ThreeVector p1,p2,p3,p4; 01207 const G4int max_n_loops=numEdges*10000; // protection against infinite loop 01208 01209 // Each step of outer loop removes one ear 01210 // 01211 while(n>3) // Inner loop searches for one ear 01212 { 01213 v2=triangles; 01214 do 01215 { 01216 if(v2->ear) // Ear found. Fill variables 01217 { 01218 // (v1,v3) is diagonal 01219 // 01220 v3=v2->next; v4=v3->next; 01221 v1=v2->prev; v0=v1->prev; 01222 01223 // Calculate areas and points 01224 01225 p1=G4ThreeVector((v2)->x,(v2)->y,(v2)->z); 01226 p2=G4ThreeVector((v1)->x,(v1)->y,(v1)->z); 01227 p3=G4ThreeVector((v3)->x,(v3)->y,(v3)->z); 01228 01229 G4double result1 = SurfaceTriangle(p1,p2,p3,&p4 ); 01230 points.push_back(p4); 01231 areas.push_back(result1); 01232 area=area+result1; 01233 01234 // Update earity of diagonal endpoints 01235 // 01236 v1->ear=Diagonal(v0,v3); 01237 v3->ear=Diagonal(v1,v4); 01238 01239 // Cut off the ear v2 01240 // Has to be done for a copy and not for real PolyPhiFace 01241 // 01242 v1->next=v3; 01243 v3->prev=v1; 01244 triangles=v3; // In case the head was v2 01245 n--; 01246 01247 break; // out of inner loop 01248 } // end if ear found 01249 01250 v2=v2->next; 01251 01252 } while( v2!=triangles ); 01253 01254 i++; 01255 if(i>=max_n_loops) 01256 { 01257 G4Exception( "G4PolyPhiFace::Triangulation()", 01258 "GeomSolids0003", FatalException, 01259 "Maximum number of steps is reached for triangulation!" ); 01260 } 01261 } // end outer while loop 01262 01263 if(v2->next) 01264 { 01265 // add last triangle 01266 // 01267 v2=v2->next; 01268 p1=G4ThreeVector((v2)->x,(v2)->y,(v2)->z); 01269 p2=G4ThreeVector((v2->next)->x,(v2->next)->y,(v2->next)->z); 01270 p3=G4ThreeVector((v2->prev)->x,(v2->prev)->y,(v2->prev)->z); 01271 G4double result1 = SurfaceTriangle(p1,p2,p3,&p4 ); 01272 points.push_back(p4); 01273 areas.push_back(result1); 01274 area=area+result1; 01275 } 01276 01277 // Surface Area is stored 01278 // 01279 fSurfaceArea = area; 01280 01281 // Second Step: choose randomly one surface 01282 // 01283 G4double chose = area*G4UniformRand(); 01284 01285 // Third Step: Get a point on choosen surface 01286 // 01287 G4double Achose1, Achose2; 01288 Achose1=0; Achose2=0.; 01289 i=0; 01290 do 01291 { 01292 Achose2+=areas[i]; 01293 if(chose>=Achose1 && chose<Achose2) 01294 { 01295 G4ThreeVector point; 01296 point=points[i] ; 01297 surface_point=point; 01298 break; 01299 } 01300 i++; Achose1=Achose2; 01301 } while( i<numEdges-2 ); 01302 01303 delete [] tri_help; 01304 tri_help = 0; 01305 }
G4bool G4PolyPhiFace::allBehind [protected] |
Definition at line 231 of file G4PolyPhiFace.hh.
Referenced by CopyStuff(), G4PolyPhiFace(), and Intersect().
G4PolyPhiFaceVertex* G4PolyPhiFace::corners [protected] |
Definition at line 223 of file G4PolyPhiFace.hh.
Referenced by CalculateExtent(), CopyStuff(), Diagnose(), Extent(), G4PolyPhiFace(), InsideEdgesExact(), operator=(), Triangulate(), and ~G4PolyPhiFace().
G4PolyPhiFaceEdge* G4PolyPhiFace::edges [protected] |
Definition at line 222 of file G4PolyPhiFace.hh.
Referenced by CopyStuff(), G4PolyPhiFace(), InsideEdges(), operator=(), and ~G4PolyPhiFace().
G4double G4PolyPhiFace::fSurfaceArea [protected] |
Definition at line 234 of file G4PolyPhiFace.hh.
Referenced by CopyStuff(), SurfaceArea(), and Triangulate().
G4double G4PolyPhiFace::kCarTolerance [protected] |
Definition at line 233 of file G4PolyPhiFace.hh.
Referenced by CopyStuff(), Distance(), ExactZOrder(), G4PolyPhiFace(), and InsideEdgesExact().
G4ThreeVector G4PolyPhiFace::normal [protected] |
Definition at line 224 of file G4PolyPhiFace.hh.
Referenced by CalculateExtent(), CopyStuff(), Distance(), ExactZOrder(), G4PolyPhiFace(), Inside(), Intersect(), and Normal().
G4int G4PolyPhiFace::numEdges [protected] |
Definition at line 221 of file G4PolyPhiFace.hh.
Referenced by CalculateExtent(), CopyStuff(), Diagnose(), Extent(), G4PolyPhiFace(), InsideEdges(), InsideEdgesExact(), and Triangulate().
G4ThreeVector G4PolyPhiFace::radial [protected] |
Definition at line 225 of file G4PolyPhiFace.hh.
Referenced by CalculateExtent(), CopyStuff(), Distance(), ExactZOrder(), Extent(), G4PolyPhiFace(), Inside(), Intersect(), and Normal().
G4double G4PolyPhiFace::rMax [protected] |
Definition at line 229 of file G4PolyPhiFace.hh.
Referenced by CopyStuff(), G4PolyPhiFace(), InsideEdges(), and InsideEdgesExact().
G4double G4PolyPhiFace::rMin [protected] |
Definition at line 229 of file G4PolyPhiFace.hh.
Referenced by CopyStuff(), G4PolyPhiFace(), and InsideEdgesExact().
G4ThreeVector G4PolyPhiFace::surface [protected] |
Definition at line 226 of file G4PolyPhiFace.hh.
Referenced by CopyStuff(), Distance(), G4PolyPhiFace(), Inside(), and Intersect().
G4ThreeVector G4PolyPhiFace::surface_point [protected] |
G4PolyPhiFaceVertex* G4PolyPhiFace::triangles [protected] |
Definition at line 235 of file G4PolyPhiFace.hh.
Referenced by CopyStuff(), Diagonalie(), EarInit(), and Triangulate().
G4double G4PolyPhiFace::zMax [protected] |
Definition at line 229 of file G4PolyPhiFace.hh.
Referenced by CopyStuff(), G4PolyPhiFace(), InsideEdges(), and InsideEdgesExact().
G4double G4PolyPhiFace::zMin [protected] |
Definition at line 229 of file G4PolyPhiFace.hh.
Referenced by CopyStuff(), G4PolyPhiFace(), and InsideEdgesExact().