35#if !defined(G4GEOM_USE_UGENERICTRAP)
59const G4int G4GenericTrap::fgkNofVertices = 8;
60const G4double G4GenericTrap::fgkTolerance = 1E-3;
65 const std::vector<G4TwoVector>& vertices )
66 :
G4VSolid(name), fDz(halfZ), fVertices(),
73 G4String errorDescription =
"InvalidSetup in \" ";
74 errorDescription += name;
75 errorDescription +=
"\"";
81 if (
G4int(vertices.size()) != fgkNofVertices )
83 G4Exception(
"G4GenericTrap::G4GenericTrap()",
"GeomSolids0002",
84 FatalErrorInArgument,
"Number of vertices != 8");
91 G4Exception(
"G4GenericTrap::G4GenericTrap()",
"GeomSolids0002",
97 if(CheckOrder(vertices))
99 for (
G4int i=0; i<fgkNofVertices; ++i) {fVertices.push_back(vertices[i]);}
103 for (
auto i=0; i <4; ++i) {fVertices.push_back(vertices[3-i]);}
104 for (
auto i=0; i <4; ++i) {fVertices.push_back(vertices[7-i]);}
109 for (
auto j=0; j<2; ++j)
111 for (
auto i=1; i<4; ++i)
114 length = (fVertices[k]-fVertices[k-1]).mag();
117 std::ostringstream message;
118 message <<
"Length segment is too small." <<
G4endl
119 <<
"Distance between " << fVertices[k-1] <<
" and "
120 << fVertices[k] <<
" is only " << length <<
" mm !";
121 G4Exception(
"G4GenericTrap::G4GenericTrap()",
"GeomSolids1001",
122 JustWarning, message,
"Vertices will be collapsed.");
123 fVertices[k]=fVertices[k-1];
130 for(
G4double & i : fTwist) { i=0.; }
131 fIsTwisted = ComputeIsTwisted();
141 if ( !fIsTwisted ) { fTessellatedSolid = CreateTessellatedSolid(); }
148 :
G4VSolid(a), halfCarTolerance(0.), fDz(0.), fVertices(),
159 delete fTessellatedSolid;
166 halfCarTolerance(rhs.halfCarTolerance),
167 fDz(rhs.fDz), fVertices(rhs.fVertices),
168 fIsTwisted(rhs.fIsTwisted),
169 fMinBBoxVector(rhs.fMinBBoxVector), fMaxBBoxVector(rhs.fMaxBBoxVector),
170 fVisSubdivisions(rhs.fVisSubdivisions),
171 fSurfaceArea(rhs.fSurfaceArea), fCubicVolume(rhs.fCubicVolume)
173 for (
auto i=0; i<4; ++i) { fTwist[i] = rhs.fTwist[i]; }
175 if (rhs.fTessellatedSolid && !fIsTwisted )
176 { fTessellatedSolid = CreateTessellatedSolid(); }
186 if (
this == &rhs) {
return *
this; }
194 halfCarTolerance = rhs.halfCarTolerance;
195 fDz = rhs.fDz; fVertices = rhs.fVertices;
196 fIsTwisted = rhs.fIsTwisted; fTessellatedSolid =
nullptr;
197 fMinBBoxVector = rhs.fMinBBoxVector; fMaxBBoxVector = rhs.fMaxBBoxVector;
198 fVisSubdivisions = rhs.fVisSubdivisions;
199 fSurfaceArea = rhs.fSurfaceArea; fCubicVolume = rhs.fCubicVolume;
201 for (
auto i=0; i<4; ++i) { fTwist[i] = rhs.fTwist[i]; }
203 if (rhs.fTessellatedSolid && !fIsTwisted )
204 {
delete fTessellatedSolid; fTessellatedSolid = CreateTessellatedSolid(); }
216 const std::vector<G4TwoVector>& poly)
const
222 for (
G4int i=0; i<4; ++i)
226 cross = (p.
x()-poly[i].x())*(poly[j].y()-poly[i].y())-
227 (p.
y()-poly[i].y())*(poly[j].x()-poly[i].x());
229 len2=(poly[i]-poly[j]).mag2();
232 if(cross*cross<=len2*halfCarTolerance*halfCarTolerance)
241 if (poly[j].x() > poly[i].x())
250 if ( p.
x() > poly[iMax].x()+halfCarTolerance
251 || p.
x() < poly[iMin].x()-halfCarTolerance )
256 if (poly[j].y() > poly[i].y())
266 if ( p.
y() > poly[iMax].y()+halfCarTolerance
267 || p.
y() < poly[iMin].y()-halfCarTolerance )
272 if ( poly[iMax].x() != poly[iMin].x() )
274 test = (p.
x()-poly[iMin].x())/(poly[iMax].x()-poly[iMin].x())
275 * (poly[iMax].y()-poly[iMin].y())+poly[iMin].y();
284 if( (test>=(poly[iMin].y()-halfCarTolerance))
285 && (test<=(poly[iMax].y()+halfCarTolerance)) )
294 else if (cross<0.) {
return kOutside; }
306 if ( (std::fabs(p.
x()-poly[0].x())
307 +std::fabs(p.
y()-poly[0].y())) > halfCarTolerance )
322 if ( fTessellatedSolid )
324 return fTessellatedSolid->
Inside(p);
329 std::vector<G4TwoVector> xy;
331 if (std::fabs(p.
z()) <= fDz+halfCarTolerance)
336 for (
auto i=0; i<4; ++i)
338 xy.push_back(fVertices[i+4]+cf*( fVertices[i]-fVertices[i+4]));
341 innew=InsidePolygone(p,xy);
345 if(std::fabs(p.
z()) > fDz-halfCarTolerance) { innew=
kSurface; }
359 if ( fTessellatedSolid )
366 p0, p1, p2, r1, r2, r3, r4;
367 G4int noSurfaces = 0;
371 distz = fDz-std::fabs(p.
z());
372 if (distz < halfCarTolerance)
388 std:: vector<G4TwoVector> vertices;
390 for (
auto i=0; i<4; ++i)
392 vertices.push_back(fVertices[i+4]+cf*(fVertices[i]-fVertices[i+4]));
397 for (
G4int q=0; q<4; ++q)
408 p2=
G4ThreeVector(vertices[(q+1)%4].x(),vertices[(q+1)%4].y(),p.
z());
416 p2=
G4ThreeVector(fVertices[(q+1)%4].x(),fVertices[(q+1)%4].y(),-fDz);
420 p2=
G4ThreeVector(fVertices[(q+1)%4+4].x(),fVertices[(q+1)%4+4].y(),fDz);
423 lnorm = (p1-p0).cross(p2-p0);
424 lnorm = lnorm.
unit();
425 if(zPlusSide) { lnorm=-lnorm; }
434 G4double proj=(p-p0).dot(p2-p0)/normP;
435 if(proj<0) { proj=0; }
436 if(proj>normP) { proj=normP; }
442 r1=r1+proj*(r2-r1)/normP;
443 r3=r3+proj*(r4-r3)/normP;
450 distxy=std::fabs((p0-p).dot(lnorm));
451 if ( distxy<halfCarTolerance )
457 sumnorm=sumnorm+lnorm;
471 if ( noSurfaces == 0 )
474 G4Exception(
"G4GenericTrap::SurfaceNormal(p)",
"GeomSolids1002",
480 else if ( noSurfaces == 1 ) { ; }
481 else { sumnorm = sumnorm.unit(); }
489 const G4int ipl )
const
494 if ( fTessellatedSolid )
510 u=fVertices[i+4]+cf*(fVertices[i]-fVertices[i+4]);
511 v=fVertices[j+4]+cf*(fVertices[j]-fVertices[j+4]);
517 if (std::fabs(distz)<halfCarTolerance)
532 if ( std::fabs(p.
z()+fDz) > halfCarTolerance )
541 lnorm=-(p1-p0).cross(p2-p0);
542 if (distz>-halfCarTolerance) { lnorm=-lnorm.
unit(); }
543 else { lnorm=lnorm.
unit(); }
552 G4double proj=(p-p0).dot(p2-p0)/normP;
553 if (proj<0) { proj=0; }
554 if (proj>normP) { proj=normP; }
560 r1=r1+proj*(r2-r1)/normP;
561 r3=r3+proj*(r4-r3)/normP;
575 const G4int ipl)
const
587 xa=fVertices[ipl].x();
588 ya=fVertices[ipl].y();
589 xb=fVertices[ipl+4].x();
590 yb=fVertices[ipl+4].y();
593 xd=fVertices[4+j].x();
594 yd=fVertices[4+j].y();
611 G4double a = (dtx*v.
y()-dty*v.
x()+(tx1*ty2-tx2*ty1)*v.
z())*v.
z();
612 G4double b = dxs*v.
y()-dys*v.
x()+(dtx*p.
y()-dty*p.
x()+ty2*xs1-ty1*xs2
613 + tx1*ys2-tx2*ys1)*v.
z();
614 G4double c=dxs*p.
y()-dys*p.
x()+xs1*ys2-xs2*ys1;
625 if (q>-halfCarTolerance)
627 if (q<halfCarTolerance)
629 if (NormalToPlane(p,ipl).dot(v)<=0)
632 {
return kInfinity; }
638 if (std::fabs(zi)<fDz)
646 zi = (xp-x1)*(xp-x2)+(yp-y1)*(yp-y2);
647 if (zi<=halfCarTolerance) {
return q; }
655 if (a>0) { q=0.5*(-b-std::sqrt(d))/a; }
656 else { q=0.5*(-b+std::sqrt(d))/a; }
660 if (q>-halfCarTolerance)
662 if(q<halfCarTolerance)
664 if (NormalToPlane(p,ipl).dot(v)<=0)
670 if (a>0) { q=0.5*(-b+std::sqrt(d))/a; }
671 else { q=0.5*(-b-std::sqrt(d))/a; }
672 if (q<=halfCarTolerance) {
return kInfinity; }
678 if (std::fabs(zi)<fDz)
686 zi = (xp-x1)*(xp-x2)+(yp-y1)*(yp-y2);
687 if (zi<=halfCarTolerance) {
return q; }
690 if (a>0) { q=0.5*(-b+std::sqrt(d))/a; }
691 else { q=0.5*(-b-std::sqrt(d))/a; }
695 if (q>-halfCarTolerance)
697 if(q<halfCarTolerance)
699 if (NormalToPlane(p,ipl).dot(v)<=0)
705 if (a>0) { q=0.5*(-b-std::sqrt(d))/a; }
706 else { q=0.5*(-b+std::sqrt(d))/a; }
707 if (q<=halfCarTolerance) {
return kInfinity; }
713 if (std::fabs(zi)<fDz)
721 zi = (xp-x1)*(xp-x2)+(yp-y1)*(yp-y2);
722 if (zi<=halfCarTolerance) {
return q; }
735 if ( fTessellatedSolid )
749 dist[i]=DistToPlane(p, v, i);
755 if (std::fabs(p.
z())>fDz-halfCarTolerance)
762 dist[4] = (fDz-p.
z())/v.
z();
766 dist[4] = (-fDz-p.
z())/v.
z();
768 if (dist[4]<-halfCarTolerance)
774 if(dist[4]<halfCarTolerance)
778 if (n.dot(v)<0) { dist[4]=0.; }
779 else { dist[4]=kInfinity; }
789 if (dist[i] < distmin) { distmin = dist[i]; }
792 if (distmin<halfCarTolerance) { distmin=0.; }
804 if ( fTessellatedSolid )
811 if(safz<0) { safz=0; }
817 for (iseg=0; iseg<4; ++iseg)
819 safxy = SafetyToFace(p,iseg);
820 if (safxy>safe) { safe=safxy; }
837 p1=
G4ThreeVector(fVertices[iseg].x(),fVertices[iseg].y(),-fDz);
839 norm=NormalToPlane(p,iseg);
840 safe = (p-p1).dot(norm);
861 if ( (std::fabs(xa-xc)+std::fabs(ya-yc)) < halfCarTolerance )
863 xc=fVertices[j+4].x();
864 yc=fVertices[j+4].y();
870 if ( (std::fabs(xb-xc)+std::fabs(yb-yc)) < halfCarTolerance )
877 G4double c=(xb-xa)*(yc-ya)-(xc-xa)*(yb-ya);
883 t=-(a*p.
x()+b*p.
y()+c*p.
z()+d)/t;
885 if ( (t<halfCarTolerance) && (t>-halfCarTolerance) )
910 if ( fTessellatedSolid )
912 return fTessellatedSolid->
DistanceToOut(p, v, calcNorm, validNorm, n);
917 G4bool lateral_cross =
false;
920 if (calcNorm) { *validNorm =
true; }
924 distmin=(-fDz-p.
z())/v.
z();
931 distmin = (fDz-p.
z())/v.
z();
934 else { distmin = kInfinity; }
941 for (
G4int ipl=0; ipl<4; ++ipl)
944 xa=fVertices[ipl].x();
945 ya=fVertices[ipl].y();
946 xb=fVertices[ipl+4].x();
947 yb=fVertices[ipl+4].y();
950 xd=fVertices[4+j].x();
951 yd=fVertices[4+j].y();
953 if ( ((std::fabs(xb-xd)+std::fabs(yb-yd))<halfCarTolerance)
954 || ((std::fabs(xa-xc)+std::fabs(ya-yc))<halfCarTolerance) )
956 G4double q=DistToTriangle(p,v,ipl) ;
957 if ( (q>=0) && (q<distmin) )
978 G4double a = (dtx*v.
y()-dty*v.
x()+(tx1*ty2-tx2*ty1)*v.
z())*v.
z();
979 G4double b = dxs*v.
y()-dys*v.
x()+(dtx*p.
y()-dty*p.
x()+ty2*xs1-ty1*xs2
980 + tx1*ys2-tx2*ys1)*v.
z();
981 G4double c=dxs*p.
y()-dys*p.
x()+xs1*ys2-xs2*ys1;
991 if ((q > -halfCarTolerance) && (q < distmin))
993 if (q < halfCarTolerance)
995 if (NormalToPlane(p,ipl).dot(v)<0.) {
continue; }
1006 if (a > 0) { q=0.5*(-b-std::sqrt(d))/a; }
1007 else { q=0.5*(-b+std::sqrt(d))/a; }
1011 if (q > -halfCarTolerance )
1015 if(q < halfCarTolerance)
1017 if (NormalToPlane(p,ipl).dot(v)<0.)
1019 if (a > 0) { q=0.5*(-b+std::sqrt(d))/a; }
1020 else { q=0.5*(-b-std::sqrt(d))/a; }
1021 if (( q > halfCarTolerance) && (q < distmin))
1024 lateral_cross =
true;
1031 lateral_cross =
true;
1037 if (a > 0) { q=0.5*(-b+std::sqrt(d))/a; }
1038 else { q=0.5*(-b-std::sqrt(d))/a; }
1042 if ((q > -halfCarTolerance) && (q < distmin))
1044 if (q < halfCarTolerance)
1046 if (NormalToPlane(p,ipl).dot(v)<0.)
1048 if (a > 0) { q=0.5*(-b-std::sqrt(d))/a; }
1049 else { q=0.5*(-b+std::sqrt(d))/a; }
1050 if ( ( q > halfCarTolerance) && (q < distmin) )
1053 lateral_cross =
true;
1060 lateral_cross =
true;
1074 if (v.z()>0.) { i=4; }
1075 std::vector<G4TwoVector> xy;
1076 for (
G4int j=0; j<4; j++) { xy.push_back(fVertices[i+j]); }
1080 if (InsidePolygone(pt,xy)==
kOutside)
1091 if(v.z()>0) {side=kPZ;}
1102 *n=NormalToPlane(pt,0);
1105 *n=NormalToPlane(pt,1);
1108 *n=NormalToPlane(pt,2);
1111 *n=NormalToPlane(pt,3);
1121 std::ostringstream message;
1122 G4long oldprc = message.precision(16);
1123 message <<
"Undefined side for valid surface normal to solid." <<
G4endl
1125 <<
" p.x() = " << p.
x()/mm <<
" mm" <<
G4endl
1126 <<
" p.y() = " << p.
y()/mm <<
" mm" <<
G4endl
1127 <<
" p.z() = " << p.
z()/mm <<
" mm" <<
G4endl
1128 <<
"Direction:" <<
G4endl
1129 <<
" v.x() = " << v.
x() <<
G4endl
1130 <<
" v.y() = " << v.
y() <<
G4endl
1131 <<
" v.z() = " << v.
z() <<
G4endl
1132 <<
"Proposed distance :" <<
G4endl
1133 <<
" distmin = " << distmin/mm <<
" mm";
1134 message.precision(oldprc);
1135 G4Exception(
"G4GenericTrap::DistanceToOut(p,v,..)",
1141 if (distmin<halfCarTolerance) { distmin=0.; }
1152 if ( fTessellatedSolid )
1159 if (safz<0) { safz = 0; }
1164 for (
G4int iseg=0; iseg<4; ++iseg)
1166 safxy = std::fabs(SafetyToFace(p,iseg));
1167 if (safxy < safe) { safe = safxy; }
1178 pMin = GetMinimumBBox();
1179 pMax = GetMaximumBBox();
1183 if (pMin.
x() >= pMax.
x() || pMin.
y() >= pMax.
y() || pMin.
z() >= pMax.
z())
1185 std::ostringstream message;
1186 message <<
"Bad bounding box (min >= max) for solid: "
1188 <<
"\npMin = " << pMin
1189 <<
"\npMax = " << pMax;
1190 G4Exception(
"G4GenericTrap::BoundingLimits()",
"GeomMgt0001",
1216 return exist = pMin < pMax;
1228 for (
G4int i=0; i<4; ++i)
1232 baseA[2*i].set(va.
x(),va.
y(),-dz);
1233 baseB[2*i].set(vb.
x(),vb.
y(), dz);
1235 for (
G4int i=0; i<4; ++i)
1237 G4int k1=2*i, k2=(2*i+2)%8;
1238 G4double ax = (baseA[k2].x()-baseA[k1].x());
1239 G4double ay = (baseA[k2].y()-baseA[k1].y());
1240 G4double bx = (baseB[k2].x()-baseB[k1].x());
1241 G4double by = (baseB[k2].y()-baseB[k1].y());
1243 baseA[k1+1] = (znorm < 0.0) ? baseA[k2] : baseA[k1];
1244 baseB[k1+1] = (znorm < 0.0) ? baseB[k1] : baseB[k2];
1247 std::vector<const G4ThreeVectorList *> polygons(2);
1248 polygons[0] = &baseA;
1249 polygons[1] = &baseB;
1260 return {
"G4GenericTrap"};
1274 G4long oldprc = os.precision(16);
1275 os <<
"-----------------------------------------------------------\n"
1276 <<
" *** Dump for solid - " <<
GetName() <<
" *** \n"
1277 <<
" =================================================== \n"
1279 <<
" half length Z: " << fDz/mm <<
" mm \n"
1280 <<
" list of vertices:\n";
1282 for (
G4int i=0; i<fgkNofVertices; ++i )
1284 os << std::setw(5) <<
"#" << i
1285 <<
" vx = " << fVertices[i].x()/mm <<
" mm"
1286 <<
" vy = " << fVertices[i].y()/mm <<
" mm" <<
G4endl;
1288 os.precision(oldprc);
1299 if ( fTessellatedSolid )
1307 G4double rand,area,chose,cf,lambda0,lambda1,alfa,beta,zp;
1310 std::vector<G4ThreeVector> vertices;
1311 for (
auto i=0; i<4; ++i)
1313 vertices.emplace_back(fVertices[i].x(),fVertices[i].y(),-fDz);
1315 for (
auto i=4; i<8; ++i)
1317 vertices.emplace_back(fVertices[i].x(),fVertices[i].y(),fDz);
1327 G4double Surface1 = GetLateralFaceArea(0);
1328 G4double Surface2 = GetLateralFaceArea(1);
1329 G4double Surface3 = GetLateralFaceArea(2);
1330 G4double Surface4 = GetLateralFaceArea(3);
1334 area = Surface0+Surface1+Surface2+Surface3+Surface4+Surface5;
1337 if ( ( chose < Surface0)
1338 || ( chose > (Surface0+Surface1+Surface2+Surface3+Surface4)) )
1342 if(chose < Surface0)
1345 u = fVertices[ipl]; v = fVertices[j];
1346 w = fVertices[(ipl+3)%4];
1351 u = fVertices[ipl+4]; v = fVertices[j+4];
1352 w = fVertices[(ipl+3)%4+4];
1357 lambda0=alfa-lambda1;
1360 v = u+lambda0*v+lambda1*w;
1364 if (chose < Surface0+Surface1) { ipl=0; }
1365 else if (chose < Surface0+Surface1+Surface2) { ipl=1; }
1366 else if (chose < Surface0+Surface1+Surface2+Surface3) { ipl=2; }
1370 cf = 0.5*(fDz-zp)/fDz;
1371 u = fVertices[ipl+4]+cf*( fVertices[ipl]-fVertices[ipl+4]);
1372 v = fVertices[j+4]+cf*(fVertices[j]-fVertices[j+4]);
1384 if (fCubicVolume == 0.0)
1398 fCubicVolume = ((AB + CD)/3. + (AD + CB)/6.)*fDz;
1400 return fCubicVolume;
1405G4double G4GenericTrap::GetLateralFaceArea(
G4int iface)
const
1407 constexpr G4int NSTEP = 250;
1410 G4int i1 = iface, i2 = (iface + 1)%4;
1411 G4int i3 = i1 + 4, i4 = i2 + 4;
1413 G4double x21 = fVertices[i2].x() - fVertices[i1].x();
1414 G4double y21 = fVertices[i2].y() - fVertices[i1].y();
1415 G4double x31 = fVertices[i3].x() - fVertices[i1].x();
1416 G4double y31 = fVertices[i3].y() - fVertices[i1].y();
1417 G4double x42 = fVertices[i4].x() - fVertices[i2].x();
1418 G4double y42 = fVertices[i4].y() - fVertices[i2].y();
1419 G4double x43 = fVertices[i4].x() - fVertices[i3].x();
1420 G4double y43 = fVertices[i4].y() - fVertices[i3].y();
1423 G4double lmax = std::max(std::max(std::abs(x21),std::abs(y21)),
1424 std::max(std::abs(x43),std::abs(y43)));
1426 if (std::abs(
A) < eps)
1428 G4ThreeVector p1(fVertices[i1].x(), fVertices[i1].y(),-fDz);
1429 G4ThreeVector p2(fVertices[i2].x(), fVertices[i2].y(),-fDz);
1430 G4ThreeVector p3(fVertices[i3].x(), fVertices[i3].y(), fDz);
1431 G4ThreeVector p4(fVertices[i4].x(), fVertices[i4].y(), fDz);
1432 return ((p4 - p1).cross(p3 - p2)).mag()*0.5;
1444 for (
G4int i = 0; i < NSTEP; ++i)
1456 G4double R1 = std::sqrt(aa + bb + cc);
1458 G4double log1 = std::log(std::abs(sqrtAA*R1 + 2.*aa + bb));
1459 G4double log0 = std::log(std::abs(sqrtAA*R0 + bb));
1461 area += 0.5*R1 + 0.25*bb*invAA*(R1 - R0) + IIJJ*invSqrtAA*(log1 - log0);
1470 if (fSurfaceArea == 0.0)
1478 fSurfaceArea = S_bot + S_top +
1479 GetLateralFaceArea(0) +
1480 GetLateralFaceArea(1) +
1481 GetLateralFaceArea(2) +
1482 GetLateralFaceArea(3);
1484 return fSurfaceArea;
1489G4bool G4GenericTrap::ComputeIsTwisted()
1496 G4int nv = fgkNofVertices/2;
1498 for (
G4int i=0; i<4; ++i )
1500 dx1 = fVertices[(i+1)%nv].x()-fVertices[i].x();
1501 dy1 = fVertices[(i+1)%nv].y()-fVertices[i].y();
1502 if ( (dx1 == 0) && (dy1 == 0) ) {
continue; }
1504 dx2 = fVertices[nv+(i+1)%nv].x()-fVertices[nv+i].x();
1505 dy2 = fVertices[nv+(i+1)%nv].y()-fVertices[nv+i].y();
1507 if ( dx2 == 0 && dy2 == 0 ) {
continue; }
1508 G4double twist_angle = std::fabs(dy1*dx2 - dx1*dy2);
1509 if ( twist_angle < fgkTolerance ) {
continue; }
1511 SetTwistAngle(i,twist_angle);
1515 twist_angle = std::acos( (dx1*dx2 + dy1*dy2)
1516 / (std::sqrt(dx1*dx1+dy1*dy1)
1517 * std::sqrt(dx2*dx2+dy2*dy2)) );
1521 std::ostringstream message;
1522 message <<
"Twisted Angle is bigger than 90 degrees - " <<
GetName()
1524 <<
" Potential problem of malformed Solid !" <<
G4endl
1525 <<
" TwistANGLE = " << twist_angle
1526 <<
"*rad for lateral plane N= " << i;
1527 G4Exception(
"G4GenericTrap::ComputeIsTwisted()",
"GeomSolids1002",
1537G4bool G4GenericTrap::CheckOrder(
const std::vector<G4TwoVector>& vertices)
const
1542 G4bool clockwise_order=
true;
1547 for (
G4int i=0; i<4; ++i)
1550 sum1 += vertices[i].x()*vertices[j].y() - vertices[j].x()*vertices[i].y();
1551 sum2 += vertices[i+4].x()*vertices[j+4].y()
1552 - vertices[j+4].x()*vertices[i+4].y();
1554 if (sum1*sum2 < -fgkTolerance)
1556 std::ostringstream message;
1557 message <<
"Lower/upper faces defined with opposite clockwise - "
1559 G4Exception(
"G4GenericTrap::CheckOrder()",
"GeomSolids0002",
1563 if ((sum1 > 0.)||(sum2 > 0.))
1565 std::ostringstream message;
1566 message <<
"Vertices must be defined in clockwise XY planes - "
1568 G4Exception(
"G4GenericTrap::CheckOrder()",
"GeomSolids1001",
1570 clockwise_order =
false;
1575 G4bool illegal_cross =
false;
1576 illegal_cross = IsSegCrossingZ(vertices[0],vertices[4],
1577 vertices[1],vertices[5]);
1581 illegal_cross = IsSegCrossingZ(vertices[2],vertices[6],
1582 vertices[3],vertices[7]);
1587 illegal_cross = IsSegCrossing(vertices[0],vertices[1],
1588 vertices[2],vertices[3]);
1592 illegal_cross = IsSegCrossing(vertices[0],vertices[3],
1593 vertices[1],vertices[2]);
1597 illegal_cross = IsSegCrossing(vertices[4],vertices[5],
1598 vertices[6],vertices[7]);
1602 illegal_cross = IsSegCrossing(vertices[4],vertices[7],
1603 vertices[5],vertices[6]);
1608 std::ostringstream message;
1609 message <<
"Malformed polygone with opposite sides - " <<
GetName();
1610 G4Exception(
"G4GenericTrap::CheckOrderAndSetup()",
1613 return clockwise_order;
1618void G4GenericTrap::ReorderVertices(std::vector<G4ThreeVector>& vertices)
const
1622 std::vector<G4ThreeVector> oldVertices(vertices);
1624 for ( std::size_t i=0; i<oldVertices.size(); ++i )
1626 vertices[i] = oldVertices[oldVertices.size()-1-i];
1640 G4double dx1,dx2,xm=0.,ym=0.,a1=0.,a2=0.,b1=0.,b2=0.;
1644 if( std::fabs(dx1) < fgkTolerance ) { stand1 =
true; }
1645 if( std::fabs(dx2) < fgkTolerance ) { stand2 =
true; }
1648 a1 = (b.
x()*a.
y()-a.
x()*b.
y())/dx1;
1653 a2 = (d.
x()*c.
y()-c.
x()*d.
y())/dx2;
1656 if (stand1 && stand2)
1660 if (std::fabs(a.
x()-c.
x())<fgkTolerance)
1664 return ((c.
y()-a.
y())*(c.
y()-b.
y())<-fgkTolerance)
1665 || ((d.
y()-a.
y())*(d.
y()-b.
y())<-fgkTolerance)
1666 || ((a.
y()-c.
y())*(a.
y()-d.
y())<-fgkTolerance)
1667 || ((b.
y()-c.
y())*(b.
y()-d.
y())<-fgkTolerance);
1688 if (std::fabs(b1-b2) < fgkTolerance)
1692 if (std::fabs(c.
y()-(a1+b1*c.
x())) > fgkTolerance) {
return false; }
1696 if ( ((c.
x()-a.
x())*(c.
x()-b.
x())<-fgkTolerance)
1697 || ((d.
x()-a.
x())*(d.
x()-b.
x())<-fgkTolerance)
1698 || ((a.
x()-c.
x())*(a.
x()-d.
x())<-fgkTolerance)
1699 || ((b.
x()-c.
x())*(b.
x()-d.
x())<-fgkTolerance) ) {
return true; }
1703 xm = (a1-a2)/(b2-b1);
1704 ym = (a1*b2-a2*b1)/(b2-b1);
1710 G4double check = (xm-a.
x())*(xm-b.
x())+(ym-a.
y())*(ym-b.
y());
1711 if (check > -fgkTolerance) {
return false; }
1712 check = (xm-c.
x())*(xm-d.
x())+(ym-c.
y())*(ym-d.
y());
1713 return check <= -fgkTolerance;
1744 (std::fabs((p4-p3).y()) <
kCarTolerance ) ) {
return false; }
1748 det = dv.
x()*v1.
y()*v2.
z()+dv.
y()*v1.
z()*v2.
x()
1749 - dv.
x()*v1.
z()*v2.
y()-dv.
y()*v1.
x()*v2.
z();
1753 temp1 = v1.
cross(v2);
1754 temp2 = (p2-p1).cross(v2);
1755 if (temp1.
dot(temp2) < 0) {
return false; }
1759 q = ((dv).cross(v2)).mag()/q;
1769G4GenericTrap::MakeDownFacet(
const std::vector<G4ThreeVector>& fromVertices,
1776 if ( (fromVertices[ind1] == fromVertices[ind2]) ||
1777 (fromVertices[ind2] == fromVertices[ind3]) ||
1778 (fromVertices[ind1] == fromVertices[ind3]) ) {
return nullptr; }
1780 std::vector<G4ThreeVector> vertices;
1781 vertices.push_back(fromVertices[ind1]);
1782 vertices.push_back(fromVertices[ind2]);
1783 vertices.push_back(fromVertices[ind3]);
1787 G4ThreeVector cross=(vertices[1]-vertices[0]).cross(vertices[2]-vertices[1]);
1789 if ( cross.
z() > 0.0 )
1793 std::ostringstream message;
1794 message <<
"Vertices in wrong order - " <<
GetName();
1795 G4Exception(
"G4GenericTrap::MakeDownFacet",
"GeomSolids0002",
1805G4GenericTrap::MakeUpFacet(
const std::vector<G4ThreeVector>& fromVertices,
1813 if ( (fromVertices[ind1] == fromVertices[ind2]) ||
1814 (fromVertices[ind2] == fromVertices[ind3]) ||
1815 (fromVertices[ind1] == fromVertices[ind3]) ) {
return nullptr; }
1817 std::vector<G4ThreeVector> vertices;
1818 vertices.push_back(fromVertices[ind1]);
1819 vertices.push_back(fromVertices[ind2]);
1820 vertices.push_back(fromVertices[ind3]);
1824 G4ThreeVector cross=(vertices[1]-vertices[0]).cross(vertices[2]-vertices[1]);
1826 if ( cross.
z() < 0.0 )
1830 std::ostringstream message;
1831 message <<
"Vertices in wrong order - " <<
GetName();
1832 G4Exception(
"G4GenericTrap::MakeUpFacet",
"GeomSolids0002",
1842G4GenericTrap::MakeSideFacet(
const G4ThreeVector& downVertex0,
1850 if ( (downVertex0 == downVertex1) && (upVertex0 == upVertex1) )
1855 if ( downVertex0 == downVertex1 )
1860 if ( upVertex0 == upVertex1 )
1875 G4int nv = fgkNofVertices/2;
1876 std::vector<G4ThreeVector> downVertices;
1877 for (
G4int i=0; i<nv; ++i )
1879 downVertices.emplace_back(fVertices[i].x(), fVertices[i].y(), -fDz);
1882 std::vector<G4ThreeVector> upVertices;
1883 for (
G4int i=nv; i<2*nv; ++i )
1885 upVertices.emplace_back(fVertices[i].x(), fVertices[i].y(), fDz);
1891 = (downVertices[1]-downVertices[0]).cross(downVertices[2]-downVertices[1]);
1893 = (upVertices[1]-upVertices[0]).cross(upVertices[2]-upVertices[1]);
1894 if ( (cross.
z() > 0.0) || (cross1.
z() > 0.0) )
1896 ReorderVertices(downVertices);
1897 ReorderVertices(upVertices);
1903 facet = MakeDownFacet(downVertices, 0, 1, 2);
1904 if (facet !=
nullptr) { tessellatedSolid->AddFacet( facet ); }
1905 facet = MakeDownFacet(downVertices, 0, 2, 3);
1906 if (facet !=
nullptr) { tessellatedSolid->AddFacet( facet ); }
1907 facet = MakeUpFacet(upVertices, 0, 2, 1);
1908 if (facet !=
nullptr) { tessellatedSolid->AddFacet( facet ); }
1909 facet = MakeUpFacet(upVertices, 0, 3, 2);
1910 if (facet !=
nullptr) { tessellatedSolid->AddFacet( facet ); }
1914 for (
G4int i = 0; i < nv; ++i )
1916 G4int j = (i+1) % nv;
1917 facet = MakeSideFacet(downVertices[j], downVertices[i],
1918 upVertices[i], upVertices[j]);
1920 if ( facet !=
nullptr ) { tessellatedSolid->AddFacet( facet ); }
1923 tessellatedSolid->SetSolidClosed(
true);
1925 return tessellatedSolid;
1930void G4GenericTrap::ComputeBBox()
1935 minX = maxX = fVertices[0].x();
1936 minY = maxY = fVertices[0].y();
1938 for (
G4int i=1; i< fgkNofVertices; i++)
1940 if (minX>fVertices[i].x()) { minX=fVertices[i].x(); }
1941 if (maxX<fVertices[i].x()) { maxX=fVertices[i].x(); }
1942 if (minY>fVertices[i].y()) { minY=fVertices[i].y(); }
1943 if (maxY<fVertices[i].y()) { maxY=fVertices[i].y(); }
1955 if ( fTessellatedSolid )
1981 if ( fTessellatedSolid )
1997 if ( fTessellatedSolid !=
nullptr )
2005 return { minVec.
x(), maxVec.
x(),
2006 minVec.
y(), maxVec.
y(),
2007 minVec.
z(), maxVec.
z() };
2016 if ( fTessellatedSolid !=
nullptr )
2026 G4int nVertices, nFacets;
2028 G4int subdivisions = 0;
2040 for(
G4int i = 0; i < 4; ++i)
2050 Dx = 0.5*(maxVec.
x() - minVec.
y());
2051 Dy = 0.5*(maxVec.
y() - minVec.
y());
2052 if (Dy > Dx) { Dx = Dy; }
2054 subdivisions = 8*
G4int(maxTwist/(Dx*Dx*Dx)*fDz);
2055 if (subdivisions < 4) { subdivisions = 4; }
2056 if (subdivisions > 30) { subdivisions = 30; }
2059 G4int sub4 = 4*subdivisions;
2060 nVertices = 8 + subdivisions*4;
2061 nFacets = 6 + subdivisions*4;
2062 G4double cf = 1./(subdivisions + 1);
2068 for (
G4int i = 0; i < 4; ++i)
2073 for (
G4int i = 0; i < subdivisions; ++i)
2075 for (
G4int j = 0; j < 4; ++j)
2077 G4TwoVector u = fVertices[j]+cf*(i+1)*(fVertices[j+4]-fVertices[j]);
2082 for (
G4int i = 4; i < 8; ++i)
2091 polyhedron->
SetFacet(++icur, 1, 4, 3, 2);
2092 for (
G4int i = 0; i < subdivisions + 1; ++i)
2095 polyhedron->
SetFacet(++icur, 5+is, 8+is, 4+is, 1+is);
2096 polyhedron->
SetFacet(++icur, 8+is, 7+is, 3+is, 4+is);
2097 polyhedron->
SetFacet(++icur, 7+is, 6+is, 2+is, 3+is);
2098 polyhedron->
SetFacet(++icur, 6+is, 5+is, 1+is, 2+is);
2100 polyhedron->
SetFacet(++icur, 5+sub4, 6+sub4, 7+sub4, 8+sub4);
std::vector< G4ThreeVector > G4ThreeVectorList
G4double C(G4double temp)
G4double B(G4double temperature)
G4double D(G4double temp)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
Hep3Vector cross(const Hep3Vector &) const
double dot(const Hep3Vector &) const
G4bool BoundingBoxVsVoxelLimits(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
G4GenericTrap & operator=(const G4GenericTrap &rhs)
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcNorm=false, G4bool *validNorm=nullptr, G4ThreeVector *n=nullptr) const override
G4double GetZHalfLength() const
std::ostream & StreamInfo(std::ostream &os) const override
G4TwoVector GetVertex(G4int index) const
G4GeometryType GetEntityType() const override
G4Polyhedron * GetPolyhedron() const override
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const override
G4bool fRebuildPolyhedron
G4double GetTwistAngle(G4int index) const
G4double GetCubicVolume() override
G4VisExtent GetExtent() const override
G4VSolid * Clone() const override
G4int GetVisSubdivisions() const
~G4GenericTrap() override
EInside Inside(const G4ThreeVector &p) const override
G4Polyhedron * CreatePolyhedron() const override
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pmin, G4double &pmax) const override
G4GenericTrap(const G4String &name, G4double halfZ, const std::vector< G4TwoVector > &vertices)
G4double GetSurfaceArea() override
G4ThreeVector GetPointOnSurface() const override
G4Polyhedron * fpPolyhedron
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
G4int GetNumberOfRotationStepsAtTimeOfCreation() const
EInside Inside(const G4ThreeVector &p) const override
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
G4Polyhedron * GetPolyhedron() const override
G4double DistanceToOut(const G4ThreeVector &p) const override
G4ThreeVector GetPointOnSurface() const override
G4VisExtent GetExtent() const override
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const override
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
G4Polyhedron * CreatePolyhedron() const override
virtual void AddSolid(const G4Box &)=0
G4VSolid & operator=(const G4VSolid &rhs)
static G4int GetNumberOfRotationSteps()
void SetVertex(G4int index, const G4Point3D &v)
void SetFacet(G4int index, G4int iv1, G4int iv2, G4int iv3, G4int iv4=0)