37#if !defined(G4GEOM_USE_UGENERICTRAP)
68 const std::vector<G4TwoVector>& vertices)
72 CheckParameters(halfZ, vertices);
73 ComputeLateralSurfaces();
75 ComputeScratchLength();
93 halfTolerance(rhs.halfTolerance), fScratch(rhs.fScratch),
94 fDz(rhs.fDz), fVertices(rhs.fVertices), fIsTwisted(rhs.fIsTwisted),
95 fMinBBox(rhs.fMinBBox), fMaxBBox(rhs.fMaxBBox),
96 fVisSubdivisions(rhs.fVisSubdivisions),
97 fSurfaceArea(rhs.fSurfaceArea), fCubicVolume(rhs.fCubicVolume)
99 for (
auto i = 0; i < 5; ++i) { fTwist[i] = rhs.fTwist[i]; }
100 for (
auto i = 0; i < 4; ++i) { fDelta[i] = rhs.fDelta[i]; }
101 for (
auto i = 0; i < 8; ++i) { fPlane[i] = rhs.fPlane[i]; }
102 for (
auto i = 0; i < 4; ++i) { fSurf[i] = rhs.fSurf[i]; }
103 for (
auto i = 0; i < 4; ++i) { f4k[i] = rhs.f4k[i]; }
104 for (
auto i = 0; i < 4; ++i) { fArea[i] = rhs.fArea[i]; }
114 if (
this == &rhs) {
return *
this; }
120 halfTolerance = rhs.halfTolerance; fScratch = rhs.fScratch;
121 fDz = rhs.fDz; fVertices = rhs.fVertices; fIsTwisted = rhs.fIsTwisted;
122 fMinBBox = rhs.fMinBBox; fMaxBBox = rhs.fMaxBBox;
123 fVisSubdivisions = rhs.fVisSubdivisions;
124 fSurfaceArea = rhs.fSurfaceArea; fCubicVolume = rhs.fCubicVolume;
126 for (
auto i = 0; i < 8; ++i) { fVertices[i] = rhs.fVertices[i]; }
127 for (
auto i = 0; i < 5; ++i) { fTwist[i] = rhs.fTwist[i]; }
128 for (
auto i = 0; i < 4; ++i) { fDelta[i] = rhs.fDelta[i]; }
129 for (
auto i = 0; i < 8; ++i) { fPlane[i] = rhs.fPlane[i]; }
130 for (
auto i = 0; i < 4; ++i) { fSurf[i] = rhs.fSurf[i]; }
131 for (
auto i = 0; i < 4; ++i) { f4k[i] = rhs.f4k[i]; }
132 for (
auto i = 0; i < 4; ++i) { fArea[i] = rhs.fArea[i]; }
134 fRebuildPolyhedron =
false;
135 delete fpPolyhedron; fpPolyhedron =
nullptr;
151 for (
auto i = 0; i < 4; ++i)
153 pp[i] = fVertices[i] + fDelta[i]*z;
158 for (
auto i = 0; i < 4; ++i)
162 G4double dd = fSurf[i].D*px + fSurf[i].E*py + fSurf[i].F*pz + fSurf[i].G;
163 dist = std::max(dd, dist);
172 G4double leng = std::sqrt(dx*dx + dy*dy);
173 G4double dd = (dx*(py - a.
y()) - dy*(px - a.
x()))/leng;
174 dist = std::max(dd, dist);
177 return (dist > halfTolerance) ?
kOutside :
187 G4double halfToleranceSquared = halfTolerance*halfTolerance;
194 for (
auto i = 0; i < 4; ++i)
196 pp[i] = fVertices[i] + fDelta[i]*tz;
201 nz = std::copysign(
G4double(std::abs(dz) <= halfTolerance), pz);
204 for (
auto i = 0; i < 4; ++i)
208 G4double dd = fSurf[i].D*px + fSurf[i].E*py + fSurf[i].F*pz + fSurf[i].G;
209 if (std::abs(dd) <= halfTolerance)
224 G4double dd = dx*(py - a.
y()) - dy*(px - a.
x());
225 if (dd*dd <= halfToleranceSquared*ll)
227 G4double x = fSurf[i].A*pz + fSurf[i].D;
228 G4double y = fSurf[i].B*pz + fSurf[i].E;
229 G4double z = fSurf[i].A*px + fSurf[i].B*py + 2.*fSurf[i].C*pz + fSurf[i].F;
230 G4double inv = 1./std::sqrt(x*x + y*y + z*z);
239 G4double mag2 = nx*nx + ny*ny + nz*nz;
242 return ApproxSurfaceNormal(p);
245 G4double inv = (mag == 1.) ? 1. : 1./mag;
246 return { nx*inv, ny*inv, nz*inv };
257 std::ostringstream message;
258 message.precision(16);
259 message <<
"Point p is not on surface of solid: " <<
GetName() <<
" !?\n"
260 <<
"Position: " << p <<
" is "
263 G4Exception(
"G4GenericTrap::ApproxSurfaceNormal(p)",
"GeomSolids1002",
273 for (
auto i = 0; i < 4; ++i)
275 pp[i] = fVertices[i] + fDelta[i]*tz;
279 for (
auto i = 0; i < 4; ++i)
283 G4double d = fSurf[i].D*px + fSurf[i].E*py + fSurf[i].F*pz + fSurf[i].G;
284 if (d > dist) { dist = d; iside = i; }
293 G4double leng = std::sqrt(dx*dx + dy*dy);
294 G4double d = (dx*(py - a.
y()) - dy*(px - a.
x()))/leng;
295 if (d > dist) { dist = d; iside = i; }
299 G4double distz = std::abs(pz) - fDz;
300 if (distz >= dist) {
return { 0., 0., std::copysign(1., pz) };
303 G4double x = fSurf[iside].A*pz + fSurf[iside].D;
304 G4double y = fSurf[iside].B*pz + fSurf[iside].E;
305 G4double z = fSurf[iside].A*px + fSurf[iside].B*py + 2.*fSurf[iside].C*pz + fSurf[iside].F;
306 G4double inv = 1./std::sqrt(x*x + y*y + z*z);
307 return { x*inv, y*inv, z*inv };
323 if (std::abs(pz) - fDz >= -halfTolerance && pz*vz >= 0) {
return kInfinity; }
324 G4double invz = (vz == 0) ? kInfinity : -1./vz;
325 G4double dz = std::copysign(fDz,invz);
330 for (
auto k = 0; k < 4; ++k)
332 if (fTwist[k] != 0) {
continue; }
333 const G4GenericTrapPlane& surf = fPlane[2*k];
334 G4double cosa = surf.A*vx + surf.B*vy + surf.C*vz;
335 G4double dist = surf.A*px + surf.B*py + surf.C*pz + surf.D;
336 if (dist >= -halfTolerance)
338 if (cosa >= 0.) {
return kInfinity; }
340 xin = std::max(tmp, xin);
344 if (cosa > 0) { xout = std::min(-dist/cosa, xout); }
345 if (cosa < 0) { xin = std::max(-dist/cosa, xin); }
352 for (
auto i = 0; i < 4; ++i)
354 if (fTwist[i] == 0) {
continue; }
357 const G4GenericTrapPlane& surf1 = fPlane[2*i];
358 G4double cosa = surf1.A*vx + surf1.B*vy + surf1.C*vz;
359 G4double dist = surf1.A*px + surf1.B*py + surf1.C*pz + surf1.D;
360 if (dist >= -halfTolerance)
362 if (cosa >= 0.) {
return kInfinity; }
364 tin = std::max(tmp, tin);
368 if (cosa > 0) { tout = std::min(-dist/cosa, tout); }
369 if (cosa < 0) { tin = std::max(-dist/cosa, tin); }
373 const G4GenericTrapPlane& surf2 = fPlane[2*i + 1];
374 cosa = surf2.A*vx + surf2.B*vy + surf2.C*vz;
375 dist = surf2.A*px + surf2.B*py + surf2.C*pz + surf2.D;
376 if (dist >= -halfTolerance)
378 if (cosa >= 0.) {
return kInfinity; }
380 tin = std::max(tmp, tin);
384 if (cosa > 0) { tout = std::min(-dist/cosa, tout); }
385 if (cosa < 0) { tin = std::max(-dist/cosa, tin); }
388 if (tout - tin <= halfTolerance) {
return kInfinity; }
392 G4double t0 = 0., x0 = px, y0 = py, z0 = pz;
393 if (x0 < fMinBBox.x() - halfTolerance ||
394 y0 < fMinBBox.y() - halfTolerance ||
395 z0 < fMinBBox.z() - halfTolerance ||
396 x0 > fMaxBBox.x() + halfTolerance ||
397 y0 > fMaxBBox.y() + halfTolerance ||
398 z0 > fMaxBBox.z() + halfTolerance)
411 if (tin - xin < halfTolerance) { ttin[0] = xin; }
412 if (xout - tout < halfTolerance) { ttout[0] = xout; }
413 G4double tminimal = tin - halfTolerance;
414 G4double tmaximal = tout + halfTolerance;
417 for (
auto i = 0; i < 4; ++i)
419 if (fTwist[i] == 0) {
continue; }
422 G4double ABC = fSurf[i].A*vx + fSurf[i].B*vy + fSurf[i].C*vz;
423 G4double ABCF = fSurf[i].A*x0 + fSurf[i].B*y0 + fSurf[i].C*z0 + fSurf[i].F;
425 G4double B = 0.5*(fSurf[i].D*vx + fSurf[i].E*vy + ABCF*vz + ABC*z0);
426 G4double C = fSurf[i].D*x0 + fSurf[i].E*y0 + ABCF*z0 + fSurf[i].G;
427 if (std::abs(
A) <= EPSILON)
430 if (std::abs(
B) <= EPSILON)
440 G4double leng = std::sqrt(dx*dx + dy*dy);
441 G4double dist = dx*(y0 - a.
y()) - dy*(x0 - a.
x());
442 if (dist >= -halfTolerance*leng) {
return kInfinity; }
452 const G4GenericTrapSurface& surf = fSurf[i];
455 G4double nz = surf.A*x + surf.B*y + 2.*surf.C*z + surf.F;
457 if (nx*vx + ny*vy + nz*vz >= 0.)
459 auto k = (i == 3) ? 0 : i + 1;
465 G4double leng = std::sqrt(dx*dx + dy*dy);
466 G4double dist = dx*(py - a.
y()) - dy*(px - a.
x());
467 if (dist >= -halfTolerance*leng) {
return kInfinity; }
469 if (tmp < tminimal || tmp > tmaximal) {
continue; }
470 if (std::abs(tmp - ttout[0]) < halfTolerance) {
continue; }
476 else { ttout[1] = std::min(tmp, ttout[1]); }
480 if (tmp < tminimal || tmp > tmaximal) {
continue; }
481 if (std::abs(tmp - ttin[0]) < halfTolerance) {
continue; }
487 else { ttin[1] = std::min(tmp, ttin[1]); }
494 if (
D < 0.25*fScratch*fScratch*
A*
A)
496 if (
A > 0) {
return kInfinity; }
501 G4double tmp = -
B - std::copysign(std::sqrt(
D),
B);
504 G4double tsurfin = std::min(t1, t2);
505 G4double tsurfout = std::max(t1, t2);
506 if (
A < 0) { std::swap(tsurfin, tsurfout); }
508 if (tsurfin >= tminimal && tsurfin <= tmaximal)
510 if (std::abs(tsurfin - ttin[0]) >= halfTolerance)
512 if (tsurfin < ttin[0])
517 else { ttin[1] = std::min(tsurfin, ttin[1]); }
520 if (tsurfout >= tminimal && tsurfout <= tmaximal)
522 if (std::abs(tsurfout - ttout[0]) >= halfTolerance)
524 if (tsurfout < ttout[0])
529 else { ttout[1] = std::min(tsurfout, ttout[1]); }
536 if (ttin[0] ==
DBL_MAX) {
return kInfinity; }
542 G4double distout = (distin >= ttout[0] - halfTolerance) ? ttout[1] : ttout[0];
543 G4double dist = (distout <= halfTolerance || distout - distin <= halfTolerance) ? kInfinity : distin;
544 return (dist < halfTolerance) ? 0. : dist;
548 if (ttin[1] < ttout[0])
550 G4double distin = ttin[1], distout = ttout[0];
551 G4double dist = (distout <= halfTolerance || distout - distin <= halfTolerance) ? kInfinity : distin;
552 return (dist < halfTolerance) ? 0. : dist;
556 G4double distin1 = ttin[0], distout1 = ttout[0];
557 G4double dist1 = (distout1 <= halfTolerance || distout1 - distin1 <= halfTolerance) ? kInfinity : distin1;
558 if (dist1 != kInfinity) {
return (dist1 < halfTolerance) ? 0. : dist1; }
561 G4double distin2 = ttin[1], distout2 = ttout[1];
562 G4double dist2 = (distout2 <= halfTolerance || distout2 - distin2 <= halfTolerance) ? kInfinity : distin2;
563 return (dist2 < halfTolerance) ? 0. : dist2;
574 for (
auto i = 0; i < 4; ++i)
578 G4double distPlane = fSurf[i].D*x + fSurf[i].E*y + fSurf[i].F*z + fSurf[i].G;
579 dist = std::max(distPlane, dist);
591 G4double fun = gradx*x + grady*y + CzF*z + fSurf[i].G;
592 G4double grad2 = gradx*gradx + grady*grady + gradz*gradz;
593 G4double divisor = std::sqrt(grad2) + std::sqrt(grad2 + f4k[i]*std::abs(fun));
595 dist = std::max(distSurf, dist);
598 return (dist > 0.) ? dist : 0.;
616 if ((std::abs(pz) - fDz) >= -halfTolerance && pz*vz > 0.)
621 n->set(0., 0., std::copysign(1., pz));
625 G4double tout = (vz == 0) ?
DBL_MAX : (std::copysign(fDz, vz) - pz)/vz;
626 G4int iface = (vz < 0) ? -4 : -2;
628 for (
auto i = 0; i < 4; ++i)
630 if (fTwist[i] != 0) {
continue; }
631 const G4GenericTrapPlane& surf = fPlane[2*i];
632 G4double cosa = surf.A*vx + surf.B*vy + surf.C*vz;
635 G4double dist = surf.A*px + surf.B*py + surf.C*pz + surf.D;
636 if (dist >= -halfTolerance)
641 n->set(surf.A, surf.B, surf.C);
646 if (tout > tmp) { tout = tmp; iface = i; }
653 for (
auto i = 0; i < 4; ++i)
655 if (fTwist[i] == 0) {
continue; }
658 const G4GenericTrapSurface& surf = fSurf[i];
659 G4double ABC = surf.A*vx + surf.B*vy + surf.C*vz;
660 G4double ABCF = surf.A*px + surf.B*py + surf.C*pz + surf.F;
662 G4double B = 0.5*(surf.D*vx + surf.E*vy + ABCF*vz + ABC*pz);
663 G4double C = surf.D*px + surf.E*py + ABCF*pz + surf.G;
665 if (std::abs(
A) <= EPSILON)
668 if (std::abs(
B) <= EPSILON) {
continue; }
678 G4double nz = surf.A*x + surf.B*y + 2.*surf.C*z + surf.F;
680 if (nx*vx + ny*vy + nz*vz > 0.)
688 G4double leng = std::sqrt(dx*dx + dy*dy);
689 G4double dist = dx*(py - a.
y()) - dy*(px - a.
x());
690 if (dist >= -halfTolerance*leng)
695 G4double normx = surf.A*pz + surf.D;
696 G4double normy = surf.B*pz + surf.E;
697 G4double normz = surf.A*px + surf.B*py + 2.*surf.C*pz + surf.F;
698 G4double inv = 1./std::sqrt(normx*normx + normy*normy + normz*normz);
699 n->set(normx*inv, normy*inv, normz*inv);
703 if (tout > tmp) { tout = tmp; iface = i; }
710 if (
D < 0.25*fScratch*fScratch*
A*
A)
719 G4double leng = std::sqrt(dx*dx + dy*dy);
720 G4double dist = dx*(py - a.
y()) - dy*(px - a.
x());
721 if (dist <= -halfTolerance*leng) {
continue; }
722 if (
A > 0 || dist > halfTolerance*leng)
729 G4double nz = surf.A*px + surf.B*py + 2.*surf.C*pz + surf.F;
730 G4double inv = 1./std::sqrt(nx*nx + ny*ny + nz*nz);
731 n->set(nx*inv, ny*inv, nz*inv);
739 G4double tmp = -
B - std::copysign(std::sqrt(
D),
B);
747 if (std::abs(tmax) < std::abs(tmin)) {
continue; }
748 if (tmin <= halfTolerance)
761 G4double leng = std::sqrt(dx*dx + dy*dy);
762 G4double dist = dx*(y - a.
y()) - dy*(x - a.
x());
763 if (dist <= -halfTolerance*leng) {
continue; }
769 G4double nz = surf.A*px + surf.B*py + 2.*surf.C*pz + surf.F;
770 G4double inv = 1./std::sqrt(nx*nx + ny*ny + nz*nz);
771 n->set(nx*inv, ny*inv, nz*inv);
775 if (tout > tmin) { tout = tmin; iface = i; }
779 if (tmax < halfTolerance)
786 G4double nz = surf.A*px + surf.B*py + 2.*surf.C*pz + surf.F;
787 G4double inv = 1./std::sqrt(nx*nx + ny*ny + nz*nz);
788 n->set(nx*inv, ny*inv, nz*inv);
792 if (tout > tmax) { tout = tmax; iface = i; }
798 if (tout < halfTolerance) { tout = 0.; }
804 n->set(0, 0, iface + 3);
808 const G4GenericTrapSurface& surf = fSurf[iface];
809 if (fTwist[iface] == 0)
812 n->set(surf.D, surf.E, surf.F);
822 G4double nz = surf.A*x + surf.B*y + 2.*surf.C*z + surf.F;
823 G4double inv = 1./std::sqrt(nx*nx + ny*ny + nz*nz);
824 n->set(nx*inv, ny*inv, nz*inv);
839 for (
auto i = 0; i < 4; ++i)
843 G4double distPlane = fSurf[i].D*x + fSurf[i].E*y + fSurf[i].F*z + fSurf[i].G;
844 dist = std::max(distPlane, dist);
856 G4double fun = gradx*x + grady*y + CzF*z + fSurf[i].G;
857 G4double grad2 = gradx*gradx + grady*grady + gradz*gradz;
858 G4double divisor = std::sqrt(grad2) + std::sqrt(grad2 + f4k[i]*std::abs(fun));
860 dist = std::max(distSurf, dist);
863 return (dist < 0.) ? -dist : 0.;
899 return exist = pMin < pMax;
911 for (
G4int i = 0; i < 4; ++i)
915 baseA[2*i].set(va.
x(), va.
y(),-dz);
916 baseB[2*i].set(vb.
x(), vb.
y(), dz);
918 for (
G4int i = 0; i < 4; ++i)
920 G4int k1 = 2*i, k2 = (2*i + 2)%8;
921 G4double ax = (baseA[k2].x() - baseA[k1].x());
922 G4double ay = (baseA[k2].y() - baseA[k1].y());
923 G4double bx = (baseB[k2].x() - baseB[k1].x());
924 G4double by = (baseB[k2].y() - baseB[k1].y());
926 baseA[k1+1] = (znorm < 0.0) ? baseA[k2] : baseA[k1];
927 baseB[k1+1] = (znorm < 0.0) ? baseB[k1] : baseB[k2];
930 std::vector<const G4ThreeVectorList *> polygons(2);
931 polygons[0] = &baseA;
932 polygons[1] = &baseB;
945 return {
"G4GenericTrap" };
954 return (!fIsTwisted);
972 G4long oldprc = os.precision(16);
973 os <<
"-----------------------------------------------------------\n"
974 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
975 <<
" ===================================================\n"
977 <<
" half length Z: " << fDz/mm <<
"\n"
978 <<
" list of vertices:\n";
979 for (
G4int i = 0; i < 8; ++i)
981 os <<
" #" << i <<
" " << fVertices[i] <<
"\n";
983 os <<
"-----------------------------------------------------------\n";
984 os.precision(oldprc);
994 if (fArea[0] + fArea[1] + fArea[2] + fArea[3] == 0.)
997 fArea[0] = GetLateralFaceArea(0);
998 fArea[1] = GetLateralFaceArea(1);
999 fArea[2] = GetLateralFaceArea(2);
1000 fArea[3] = GetLateralFaceArea(3);
1004 constexpr G4int iface[6][4] =
1005 { {0,1,2,3}, {0,4,5,1}, {1,5,6,2}, {2,6,7,3}, {3,7,4,0}, {4,5,6,7} };
1007 G4bool isTwisted[6] = {
false};
1008 for (
auto i = 0; i < 4; ++i)
1010 isTwisted[i + 1] = (fTwist[i] != 0.0);
1018 ssurf[0] = (
A.x()*
B.y() -
A.y()*
B.x())*0.5;
1019 ssurf[1] = ssurf[0] + fArea[0];
1020 ssurf[2] = ssurf[1] + fArea[1];
1021 ssurf[3] = ssurf[2] + fArea[2];
1022 ssurf[4] = ssurf[3] + fArea[3];
1023 ssurf[5] = ssurf[4] + (
C.x()*
D.y() -
C.y()*
D.x())*.5;
1027 for (k = 0; k < 5; ++k)
1029 if (select <= ssurf[k]) {
break; }
1032 G4int i0 = iface[k][0];
1033 G4int i1 = iface[k][1];
1034 G4int i2 = iface[k][2];
1035 G4int i3 = iface[k][3];
1037 pp[0].set(fVertices[i0].x(), fVertices[i0].y(), ((k == 5) ? fDz : -fDz));
1038 pp[1].set(fVertices[i1].x(), fVertices[i1].y(), ((k == 0) ? -fDz : fDz));
1039 pp[2].set(fVertices[i2].x(), fVertices[i2].y(), ((k == 0) ? -fDz : fDz));
1040 pp[3].set(fVertices[i3].x(), fVertices[i3].y(), ((k == 5) ? fDz : -fDz));
1045 G4double maxlength = std::max((pp[2] - pp[1]).mag(), (pp[3] - pp[0]).mag());
1046 point = (pp[0] + pp[1] + pp[2] + pp[3])*0.25;
1047 for (
auto i = 0; i < 10000; ++i)
1053 if (v >= 1.) {
continue; }
1054 point = p0 + (p1 - p0)*v;
1062 if (u + v > 1.) { u = 1. - u; v = 1. - v; }
1063 G4double ss = (((pp[2] - pp[0]).cross(pp[3] - pp[0])).mag())*0.5;
1064 G4int j = (select > ssurf[k] - ss) ? 3 : 1;
1065 point = pp[0] + (pp[2] - pp[0])*u + (pp[j] - pp[0])*v;
1074G4double G4GenericTrap::GetLateralFaceArea(
G4int iface)
const
1076 G4int i1 = iface, i2 = (i1 + 1)%4, i3 = i1 + 4, i4 = i2 + 4;
1079 if (fTwist[iface] == 0.0)
1081 G4ThreeVector p1(fVertices[i1].x(), fVertices[i1].y(),-fDz);
1082 G4ThreeVector p2(fVertices[i2].x(), fVertices[i2].y(),-fDz);
1083 G4ThreeVector p3(fVertices[i3].x(), fVertices[i3].y(), fDz);
1084 G4ThreeVector p4(fVertices[i4].x(), fVertices[i4].y(), fDz);
1085 return ((p4 - p1).cross(p3 - p2)).mag()*0.5;
1089 constexpr G4int NSTEP = 250;
1092 G4double x21 = fVertices[i2].x() - fVertices[i1].x();
1093 G4double y21 = fVertices[i2].y() - fVertices[i1].y();
1094 G4double x31 = fVertices[i3].x() - fVertices[i1].x();
1095 G4double y31 = fVertices[i3].y() - fVertices[i1].y();
1096 G4double x42 = fVertices[i4].x() - fVertices[i2].x();
1097 G4double y42 = fVertices[i4].y() - fVertices[i2].y();
1098 G4double x43 = fVertices[i4].x() - fVertices[i3].x();
1099 G4double y43 = fVertices[i4].y() - fVertices[i3].y();
1110 for (
G4int i = 0; i < NSTEP; ++i)
1122 G4double R1 = std::sqrt(aa + bb + cc);
1124 G4double log1 = std::log(std::abs(sqrtAA*R1 + 2.*aa + bb));
1125 G4double log0 = std::log(std::abs(sqrtAA*R0 + bb));
1127 area += 0.5*R1 + 0.25*bb*invAA*(R1 - R0) + IIJJ*invSqrtAA*(log1 - log0);
1138 if (fCubicVolume == 0)
1153 fCubicVolume = ((AB + CD)/3. + (AD + CB)/6.)*fDz;
1156 return fCubicVolume;
1165 if (fSurfaceArea == 0)
1174 fArea[0] = GetLateralFaceArea(0);
1175 fArea[1] = GetLateralFaceArea(1);
1176 fArea[2] = GetLateralFaceArea(2);
1177 fArea[3] = GetLateralFaceArea(3);
1178 fSurfaceArea = S_bot + S_top + fArea[0] + fArea[1] + fArea[2] + fArea[3];
1181 return fSurfaceArea;
1189G4GenericTrap::CheckParameters(
G4double halfZ,
1190 const std::vector<G4TwoVector>& vertices)
1194 if (vertices.size() != 8)
1196 std::ostringstream message;
1197 message <<
"Number of vertices is " << vertices.size()
1198 <<
" instead of 8 for Solid: " <<
GetName() <<
" !";
1199 G4Exception(
"G4GenericTrap::CheckParameters()",
"GeomSolids0002",
1207 std::ostringstream message;
1208 message <<
"Z-dimension is too small or negative (dZ = " << fDz <<
" mm)"
1209 <<
" for Solid: " <<
GetName() <<
" !";
1210 G4Exception(
"G4GenericTrap::CheckParameters()",
"GeomSolids0002",
1216 for (
auto i = 0; i < 8; ++i) { fVertices.at(i) = vertices[i]; }
1222 G4double zbot = diag1.
x()*diag2.
y() - diag1.
y()*diag2.
x();
1229 G4double ztop = diag3.
x()*diag4.
y() - diag3.
y()*diag4.
x();
1234 std::ostringstream message;
1235 message <<
"Vertices of the bottom and top polygons are defined in opposite directions !\n";
1237 G4Exception(
"G4GenericTrap::CheckParameters()",
"GeomSolids0002",
1240 if ((zbot > 0.) || (ztop > 0.))
1242 std::swap(fVertices[1], fVertices[3]);
1243 std::swap(fVertices[5], fVertices[7]);
1244 std::ostringstream message;
1245 message <<
"Vertices re-ordered in Solid: " <<
GetName() <<
" !\n"
1246 <<
"Vertices of the bottom and top polygons must be defined in a clockwise direction.";
1247 G4Exception(
"G4GenericTrap::CheckParameters()",
"GeomSolids1001",
1253 G4int ndegenerated = 0;
1254 for (
auto i = 0; i < 4; ++i)
1257 G4double lbot = (fVertices[j] - fVertices[i]).mag();
1258 G4double ltop = (fVertices[j + 4] - fVertices[i + 4]).mag();
1259 ndegenerated +=
static_cast<int>(std::max(lbot, ltop) <
kCarTolerance);
1261 if (ndegenerated > 1 ||
1264 std::ostringstream message;
1265 message <<
"Degenerated solid !\n";
1267 G4Exception(
"G4GenericTrap::CheckParameters()",
"GeomSolids0002",
1274 for (
auto i = 0; i < 4; ++i)
1281 if (!isConvex) {
break; }
1282 G4TwoVector edge3 = fVertices[j + 4] - fVertices[i + 4];
1283 G4TwoVector edge4 = fVertices[k + 4] - fVertices[j + 4];
1285 if (!isConvex) {
break; }
1289 std::ostringstream message;
1290 message <<
"The bottom and top faces must be convex polygons !\n";
1292 G4Exception(
"G4GenericTrap::CheckParameters()",
"GeomSolids0002",
1301void G4GenericTrap::ComputeLateralSurfaces()
1303 for (
auto i = 0; i < 4; ++i)
1308 G4ThreeVector p3(fVertices[j + 4].x(), fVertices[j + 4].y(), fDz);
1309 G4ThreeVector p4(fVertices[i + 4].x(), fVertices[i + 4].y(), fDz);
1314 G4double zcross = ebot.
x()*etop.
y() - ebot.
y()*etop.
x();
1316 if (std::min(lbot, ltop) <
kCarTolerance || std::abs(zcross) < eps)
1327 G4TwoVector vij = (vi - vl).unit() + (vj - vk).unit();
1334 normal = ((p4 - p1).cross(p3 - p2)).
unit();
1336 fSurf[i].D = fPlane[2*i].A = fPlane[2*i + 1].A = normal.
x();
1337 fSurf[i].E = fPlane[2*i].B = fPlane[2*i + 1].B = normal.
y();
1338 fSurf[i].F = fPlane[2*i].C = fPlane[2*i + 1].C = normal.
z();
1339 fSurf[i].G = fPlane[2*i].D = fPlane[2*i + 1].D = -normal.
dot((p1 + p2 + p3 + p4)/4.);
1344 G4double angle = std::acos(ebot.
dot(etop)/(lbot*ltop));
1345 if (angle > CLHEP::halfpi)
1347 std::ostringstream message;
1348 message <<
"Twist on " << angle/CLHEP::deg
1349 <<
" degrees, should not be more than 90 degrees !";
1351 G4Exception(
"G4GenericTrap::ComputeLateralSurfaces()",
"GeomSolids0002",
1354 fTwist[i] = std::copysign(angle, zcross);
1356 fSurf[i].A = 2.*fDz*(p4.y() - p3.y() - p2.y() + p1.y());
1357 fSurf[i].B =-2.*fDz*(p4.x() - p3.x() - p2.x() + p1.x());
1358 fSurf[i].C = ((p4.x() - p2.x())*(p3.y() - p1.y()) - (p4.y() - p2.y())*(p3.x() - p1.x()));
1359 fSurf[i].D = 2.*fDz*fDz*(p4.y() - p3.y() + p2.y() - p1.y());
1360 fSurf[i].E =-2.*fDz*fDz*(p4.x() - p3.x() + p2.x() - p1.x());
1361 fSurf[i].F = 2.*fDz*(p4.x()*p3.y() - p3.x()*p4.y() - p2.x()*p1.y() + p1.x()*p2.y());
1362 fSurf[i].G = fDz*fDz*((p4.x() + p2.x())*(p3.y() + p1.y()) - (p3.x() + p1.x())*(p4.y() + p2.y()));
1365 fSurf[i].A /= magnitude;
1366 fSurf[i].B /= magnitude;
1367 fSurf[i].C /= magnitude;
1368 fSurf[i].D /= magnitude;
1369 fSurf[i].E /= magnitude;
1370 fSurf[i].F /= magnitude;
1371 fSurf[i].G /= magnitude;
1380 normal1 = ((p2 - p1).cross(p4 - p1)).
unit();
1381 normal2 = ((p3 - p4).cross(p1 - p4)).
unit();
1387 normal1 = ((p3 - p2).cross(p1 - p2)).
unit();
1388 normal2 = ((p2 - p3).cross(p4 - p3)).
unit();
1392 fPlane[2*i].A = normal1.
x();
1393 fPlane[2*i].B = normal1.
y();
1394 fPlane[2*i].C = normal1.
z();
1395 fPlane[2*i].D = -normal1.
dot(c1);
1396 fPlane[2*i + 1].A = normal2.
x();
1397 fPlane[2*i + 1].B = normal2.
y();
1398 fPlane[2*i + 1].C = normal2.
z();
1399 fPlane[2*i + 1].D = -normal2.
dot(c2);
1401 fDelta[i] = (fVertices[i + 4] - fVertices[i])/(2*fDz);
1409void G4GenericTrap::ComputeBoundingBox()
1412 minX = maxX = fVertices[0].x();
1413 minY = maxY = fVertices[0].y();
1414 for (
auto i = 1; i < 8; ++i)
1416 minX = std::min(minX, fVertices[i].x());
1417 maxX = std::max(maxX, fVertices[i].x());
1418 minY = std::min(minY, fVertices[i].y());
1419 maxY = std::max(maxY, fVertices[i].y());
1426 if (minX >= maxX || minY >= maxY || -fDz >= fDz)
1428 std::ostringstream message;
1429 message <<
"Bad bounding box (min >= max) for solid: "
1431 <<
"\npMin = " << fMinBBox
1432 <<
"\npMax = " << fMaxBBox;
1433 G4Exception(
"G4GenericTrap::ComputeBoundingBox()",
"GeomSolids1001",
1443void G4GenericTrap::ComputeScratchLength()
1446 for (
auto i = 0; i < 4; ++i)
1448 if (fTwist[i] == 0.) {
continue; }
1452 G4ThreeVector p3(fVertices[i + 4].x(), fVertices[i + 4].y(), fDz);
1453 G4ThreeVector p4(fVertices[k + 4].x(), fVertices[k + 4].y(), fDz);
1457 pp[0] = p0 - norm * halfTolerance;
1458 pp[1] = p0 + norm * halfTolerance;
1460 vv[0] = (p4 - p1).unit();
1461 vv[1] = (p3 - p2).unit();
1463 for (
const auto & ip : pp)
1468 for (
const auto & iv : vv)
1474 G4double ABC = fSurf[i].A*vx + fSurf[i].B*vy + fSurf[i].C*vz;
1475 G4double ABCF = fSurf[i].A*px + fSurf[i].B*py + fSurf[i].C*pz + fSurf[i].F;
1477 G4double B = 0.5*(fSurf[i].D*vx + fSurf[i].E*vy + ABCF*vz + ABC*pz);
1478 G4double C = fSurf[i].D*px + fSurf[i].E*py + ABCF*pz + fSurf[i].G;
1480 if (
D < 0) {
continue; }
1482 scratch = std::min(leng, scratch);
1495 if ( (fpPolyhedron ==
nullptr)
1496 || fRebuildPolyhedron
1497 || (fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
1498 fpPolyhedron->GetNumberOfRotationSteps()) )
1501 delete fpPolyhedron;
1503 fRebuildPolyhedron =
false;
1506 return fpPolyhedron;
1524 return { fMinBBox.x(), fMaxBBox.x(),
1525 fMinBBox.y(), fMaxBBox.y(),
1526 fMinBBox.z(), fMaxBBox.z() };
1537 G4int nVertices, nFacets;
1539 G4int subdivisions = 0;
1551 for(
G4int i = 0; i < 4; ++i)
1559 Dx = 0.5*(fMaxBBox.x() - fMinBBox.y());
1560 Dy = 0.5*(fMaxBBox.y() - fMinBBox.y());
1561 if (Dy > Dx) { Dx = Dy; }
1563 subdivisions = 8*
G4int(maxTwist/(Dx*Dx*Dx)*fDz);
1564 if (subdivisions < 4) { subdivisions = 4; }
1565 if (subdivisions > 30) { subdivisions = 30; }
1568 G4int sub4 = 4*subdivisions;
1569 nVertices = 8 + subdivisions*4;
1570 nFacets = 6 + subdivisions*4;
1571 G4double cf = 1./(subdivisions + 1);
1577 for (
G4int i = 0; i < 4; ++i)
1582 for (
G4int i = 0; i < subdivisions; ++i)
1584 for (
G4int j = 0; j < 4; ++j)
1586 G4TwoVector u = fVertices[j]+cf*(i+1)*(fVertices[j+4]-fVertices[j]);
1591 for (
G4int i = 4; i < 8; ++i)
1600 polyhedron->
SetFacet(++icur, 1, 4, 3, 2);
1601 for (
G4int i = 0; i < subdivisions + 1; ++i)
1604 polyhedron->
SetFacet(++icur, 5+is, 8+is, 4+is, 1+is);
1605 polyhedron->
SetFacet(++icur, 8+is, 7+is, 3+is, 4+is);
1606 polyhedron->
SetFacet(++icur, 7+is, 6+is, 2+is, 3+is);
1607 polyhedron->
SetFacet(++icur, 6+is, 5+is, 1+is, 2+is);
1609 polyhedron->
SetFacet(++icur, 5+sub4, 6+sub4, 7+sub4, 8+sub4);
1624 std::ostringstream message;
1625 message.precision(16);
1626 message << icase <<
" in " <<
GetName() <<
"\n"
1627 <<
" p" << p <<
"\n"
1628 <<
" v" << v <<
"\n"
1629 <<
" A = " <<
A <<
" (is "
1630 << ((
A < 0) ?
"negative, instead of positive)" :
"positive, instead of negative)") <<
" !?\n";
1640void G4GenericTrap::WarningSignB(
const G4String& method,
const G4String& icase,
1644 std::ostringstream message;
1645 message.precision(16);
1646 message << icase <<
" in " <<
GetName() <<
"\n"
1647 <<
" p" << p <<
"\n"
1648 <<
" v" << v <<
"\n"
1649 <<
" f = " << f <<
" B = " <<
B <<
" (is "
1650 << ((
B < 0) ?
"negative, instead of positive)" :
"positive, instead of negative)") <<
" !?\n";
1652 const G4String
function =
"G4GenericTrap::DistanceTo" + method +
"(p,v)";
1664 G4String check =
"";
1667 G4double tcheck = 0.5*(ttout[0] + ttin[1]);
1670 check =
"\n !!! check point 0.5*(ttout[0] + ttin[1]) is NOT outside !!!";
1674 auto position =
Inside(p);
1675 std::ostringstream message;
1676 message.precision(16);
1677 message << k <<
"_Unexpected sequence of intersections in solid: " <<
GetName() <<
" !?\n"
1678 <<
" position = " << ((position ==
kInside) ?
"kInside" : ((position ==
kOutside) ?
"kOutside" :
"kSurface")) <<
"\n"
1679 <<
" p" << p <<
"\n"
1680 <<
" v" << v <<
"\n"
1681 <<
" range : [" << tmin <<
", " << tmax <<
"]\n"
1683 << ((ttin[0] ==
DBL_MAX) ? kInfinity : ttin[0]) <<
", "
1684 << ((ttin[1] ==
DBL_MAX) ? kInfinity : ttin[1]) <<
"\n"
1686 << ((ttout[0] ==
DBL_MAX) ? kInfinity : ttout[0]) <<
", "
1687 << ((ttout[1] ==
DBL_MAX) ? kInfinity : ttout[1]) << check <<
"\n";
1689 G4Exception(
"G4GenericTrap::DistanceToIn(p,v)",
"GeomSolids1002",
1697void G4GenericTrap::WarningDistanceToOut(
const G4ThreeVector& p,
1701 auto position =
Inside(p);
1702 std::ostringstream message;
1703 message.precision(16);
1704 message <<
"Unexpected final tout = " << tout <<
" in solid: " <<
GetName() <<
" !?\n"
1705 <<
" position = " << ((position ==
kInside) ?
"kInside" : ((position ==
kOutside) ?
"kOutside" :
"kSurface")) <<
"\n"
1706 <<
" p" << p <<
"\n"
1707 <<
" v" << v <<
"\n";
1709 G4Exception(
"G4GenericTrap::DistanceToOut(p,v)",
"GeomSolids1002",
G4TemplateAutoLock< G4Mutex > G4AutoLock
std::vector< G4ThreeVector > G4ThreeVectorList
G4double(*)(G4double) function
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)
G4double G4QuickRand(uint32_t seed=0)
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
CLHEP::Hep2Vector G4TwoVector
Hep3Vector cross(const Hep3Vector &) const
double dot(const Hep3Vector &) const
G4BoundingEnvelope is a helper class to facilitate calculation of the extent of a solid within the li...
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
G4double GetTwistAngle(G4int index) const
G4double GetCubicVolume() override
G4VisExtent GetExtent() const override
G4VSolid * Clone() const override
G4int GetVisSubdivisions() const
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
G4bool IsFaceted() const override
G4GenericTrap(const G4String &name, G4double halfZ, const std::vector< G4TwoVector > &vertices)
G4double GetSurfaceArea() override
G4ThreeVector GetPointOnSurface() const override
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
virtual void AddSolid(const G4Box &)=0
G4VSolid(const G4String &name)
G4VSolid & operator=(const G4VSolid &rhs)
G4VoxelLimits represents limitation/restrictions of space, where restrictions are only made perpendic...
void SetVertex(G4int index, const G4Point3D &v)
void SetFacet(G4int index, G4int iv1, G4int iv2, G4int iv3, G4int iv4=0)