30 double pdx1,
double pdx2,
31 double pdy1,
double pdy2,
33 :
VUSolid(pName), fCubicVolume(0), fSurfaceArea(0)
39 double pdy1,
double pdy2,
42 if (pdx1 > 0 && pdx2 > 0 && pdy1 > 0 && pdy2 > 0 && pdz > 0)
52 if (pdx1 >= 0 && pdx2 >= 0 && pdy1 >= 0 && pdy2 >= 0 && pdz >= 0)
66 std::cout <<
"ERROR - UTrd()::CheckAndSetAllParameters(): " <<
GetName()
68 <<
" Invalid dimensions, some are < 0 !" << std::endl
69 <<
" X - " << pdx1 <<
", " << pdx2 << std::endl
70 <<
" Y - " << pdy1 <<
", " << pdy2 << std::endl
71 <<
" Z - " << pdz << std::endl;
78 double pdy2,
double pdz )
87 double safe, zbase, tanxz, xdist, saf1, tanyz, ydist, saf2;
92 int oldprc = std::cout.precision(16) ;
93 std::cout << std::endl ;
95 std::cout <<
"Position:" << std::endl << std::endl ;
96 std::cout <<
"p.x() = " << p.
x() /
mm <<
" mm" << std::endl ;
97 std::cout <<
"p.y() = " << p.
y() /
mm <<
" mm" << std::endl ;
98 std::cout <<
"p.z() = " << p.
z() /
mm <<
" mm" << std::endl << std::endl ;
99 std::cout.precision(oldprc) ;
101 "Point p is outside !?");
105 safe =
fDz - std::fabs(p.
z);
113 xdist =
fDx1 + tanxz * zbase - std::fabs(p.
x);
114 saf1 = xdist / std::sqrt(1.0 + tanxz * tanxz);
118 ydist =
fDy1 + tanyz * zbase - std::fabs(p.
y);
119 saf2 = ydist / std::sqrt(1.0 + tanyz * tanyz);
123 if (safe > saf1) safe = saf1;
124 if (safe > saf2) safe = saf2;
126 if (safe < 0) safe = 0;
140 saf[0] =
fDz - std::abs(p.
z);
142 double calf = 1. / std::sqrt(1.0 + fx * fx);
144 double distx = 0.5 * (
fDx1 +
fDx2) - fx * p.
z;
146 else saf[1] = (distx - std::abs(p.
x)) * calf;
149 calf = 1. / std::sqrt(1.0 + fy * fy);
153 else saf[2] = (distx - std::abs(p.
y)) * calf;
175 double tanxz, distx, safx;
176 double tanyz, disty, safy;
179 safe = std::abs(p.
z) -
fDz;
180 if (safe < 0) safe = 0;
189 distx = std::abs(p.
x) - (
fDx1 + tanxz * zbase);
192 safx = distx / std::sqrt(1.0 + tanxz * tanxz);
193 if (safx > safe) safe = safx;
200 disty = std::abs(p.
y) - (
fDy1 + tanyz * zbase);
203 safy = disty / std::sqrt(1.0 + tanyz * tanyz);
204 if (safy > safe) safe = safy;
217 saf[0] =
fDz - std::abs(p.
z);
219 double calf = 1. / std::sqrt(1.0 + fx * fx);
221 double distx = 0.5 * (
fDx1 +
fDx2) - fx * p.
z;
223 else saf[1] = (distx - std::abs(p.
x)) * calf;
226 calf = 1. / std::sqrt(1.0 + fy * fy);
230 else saf[2] = (distx - std::abs(p.
y)) * calf;
232 for (
int i = 0; i < 3; i++) saf[i] = -saf[i];
258 double x, y, zbase1, zbase2;
268 if (std::abs(p.
x) <= x)
271 if (std::abs(p.
y) <= y)
285 if (std::abs(p.
y) <= y)
301 if (std::abs(p.
x) <= x)
328 double s1, s2, tanxz, tanyz, ds1, ds2;
329 double ss1, ss2, sn1 = 0., sn2 = 0., dist;
340 smin = -(
fDz + p.
z) / v.
z;
351 smin = (
fDz - p.
z) / v.
z;
355 if (smin < 0) smin = 0 ;
359 if (std::abs(p.
z) >=
fDz)
return snxt ;
373 ds1 = v.
x - tanxz * v.
z ;
374 ds2 = v.
x + tanxz * v.
z ;
379 if (ss1 < 0 && ss2 <= 0)
385 if (ds2 < 0) sn2 = ss2 / ds2 ;
390 else if (ss1 >= 0 && ss2 > 0)
396 if (ds1 > 0) sn2 = ss1 / ds1 ;
402 else if (ss1 >= 0 && ss2 <= 0)
422 if (dist < sn2) sn2 = dist ;
427 else if (ss1 < 0 && ss2 > 0)
431 if (ds1 >= 0 || ds2 <= 0)
439 if (dist > sn1) sn1 = dist ;
446 if (sn1 > smin) smin = sn1 ;
447 if (sn2 < smax) smax = sn2 ;
452 if (smax < smin)
return snxt ;
459 ds1 = v.
y - tanyz * v.
z;
460 ds2 = v.
y + tanyz * v.
z;
464 if (ss1 < 0 && ss2 <= 0)
469 if (ds2 < 0) sn2 = ss2 / ds2 ;
474 else if (ss1 >= 0 && ss2 > 0)
479 if (ds1 > 0) sn2 = ss1 / ds1 ;
484 else if (ss1 >= 0 && ss2 <= 0)
504 if (dist < sn2) sn2 = dist;
509 else if (ss1 < 0 && ss2 > 0)
513 if (ds1 >= 0 || ds2 <= 0)
521 if (dist > sn1) sn1 = dist ;
528 if (sn1 > smin) smin = sn1 ;
529 if (sn2 < smax) smax = sn2 ;
534 if (smax > smin) snxt = smin ;
556 UVector3&
n,
bool& aConvex,
double )
const
561 double central, ss1, ss2, ds1, ds2, sn = 0., sn2 = 0.;
562 double tanxz = 0., cosxz = 0., tanyz = 0., cosyz = 0.;
609 ss1 = central + tanxz * p.
z - p.
x;
611 ds1 = v.
x - tanxz * v.
z;
615 ss2 = -tanxz * p.
z - p.
x - central;
617 ds2 = tanxz * v.
z + v.
x;
619 if (ss1 > 0 && ss2 < 0)
622 if (ds1 <= 0 && ds2 < 0)
635 else if (ds1 > 0 && ds2 >= 0)
648 else if (ds1 > 0 && ds2 < 0)
686 else if (ss1 <= 0 && ss2 < 0)
713 else if (ss1 > 0 && ss2 >= 0)
756 ss1 = central + tanyz * p.
z - p.
y;
758 ds1 = v.
y - tanyz * v.
z;
762 ss2 = -tanyz * p.
z - p.
y - central;
764 ds2 = tanyz * v.
z + v.
y;
766 if (ss1 > 0 && ss2 < 0)
770 if (ds1 <= 0 && ds2 < 0)
783 else if (ds1 > 0 && ds2 >= 0)
796 else if (ds1 > 0 && ds2 < 0)
834 else if (ss1 <= 0 && ss2 < 0)
861 else if (ss1 > 0 && ss2 >= 0)
901 cosxz = 1.0 / std::sqrt(1.0 + tanxz * tanxz);
902 n.
Set(cosxz, 0, -tanxz * cosxz);
905 cosxz = -1.0 / std::sqrt(1.0 + tanxz * tanxz);
906 n.
Set(cosxz, 0, tanxz * cosxz);
909 cosyz = 1.0 / std::sqrt(1.0 + tanyz * tanyz);
910 n.
Set(0, cosyz, -tanyz * cosyz);
913 cosyz = -1.0 / std::sqrt(1.0 + tanyz * tanyz);
914 n.
Set(0, cosyz, tanyz * cosyz);
923 UUtils::Exception(
"UTrd::DistanceToOut(p,v,..)",
"Notification",
Warning, 1,
"Undefined side for valid surface normal to solid.");
936 double z = 2.0 *
fDz;
940 double secx = std::sqrt(1.0 + tanx * tanx);
941 double newpx = std::abs(p.
x) - p.
z * tanx;
942 double widx =
fDx2 -
fDz * tanx;
945 double secy = std::sqrt(1.0 + tany * tany);
946 double newpy = std::abs(p.
y) - p.
z * tany;
947 double widy =
fDy2 -
fDz * tany;
949 double distx = std::abs(newpx - widx) / secx;
950 double disty = std::abs(newpy - widy) / secy;
951 double distz = std::abs(std::abs(p.
z) -
fDz);
955 double fcos = 1.0 / secx;
957 if (p.
x >= 0.) sumnorm.
x +=
fcos;
958 else sumnorm.
x -=
fcos;
959 sumnorm.
z -= tanx *
fcos;
963 double fcos = 1.0 / secy;
965 if (p.
y >= 0.) sumnorm.
y +=
fcos;
966 else sumnorm.
y -=
fcos;
967 sumnorm.
z -= tany *
fcos;
972 sumnorm.
z += (p.
z >= 0.) ? 1.0 : -1.0;
995 norm =
UVector3(fcos, 0, -tanx * fcos);
997 norm =
UVector3(-fcos, 0, -tanx * fcos);
1017 norm =
UVector3(0, fcos, -tany * fcos);
1019 norm =
UVector3(0, -fcos, -tany * fcos);
1038 return noSurfaces > 0;
1050 double z, tanx, secx, newpx, widx;
1051 double tany, secy, newpy, widy;
1052 double distx, disty, distz,
fcos;
1057 secx = std::sqrt(1.0 + tanx * tanx);
1058 newpx = std::abs(p.
x) - p.
z * tanx;
1062 secy = std::sqrt(1.0 + tany * tany);
1063 newpy = std::abs(p.
y) - p.
z * tany;
1066 distx = std::abs(newpx - widx) / secx;
1067 disty = std::abs(newpy - widy) / secy;
1068 distz = std::abs(std::abs(p.
z) -
fDz);
1081 norm =
UVector3(fcos, 0, -tanx * fcos);
1083 norm =
UVector3(-fcos, 0, -tanx * fcos);
1103 norm =
UVector3(0, fcos, -tany * fcos);
1105 norm =
UVector3(0, -fcos, -tany * fcos);
1139 int oldprc = os.precision(16);
1140 os <<
"-----------------------------------------------------------\n"
1141 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1142 <<
" ===================================================\n"
1143 <<
" Solid type: UTrd\n"
1144 <<
" Parameters: \n"
1145 <<
" half length X, surface -dZ: " <<
fDx1 <<
" mm \n"
1146 <<
" half length X, surface +dZ: " <<
fDx2 <<
" mm \n"
1147 <<
" half length Y, surface -dZ: " <<
fDy1 <<
" mm \n"
1148 <<
" half length Y, surface +dZ: " <<
fDy2 <<
" mm \n"
1149 <<
" half length Z : " <<
fDz <<
" mm \n"
1150 <<
"-----------------------------------------------------------\n";
1151 os.precision(oldprc);
1165 double px, py, pz, tgX, tgY, secX, secY, select, sumS, tmp;
1166 double Sxy1, Sxy2, Sxy, Sxz, Syz;
1169 secX = std::sqrt(1 + tgX * tgX);
1171 secY = std::sqrt(1 + tgY * tgY);
1179 Syz = (fDy1 +
fDy2) *
fDz * secX;
1180 sumS = Sxy + Sxz + Syz;
1199 else if ((select - Sxy) < Sxz)
1202 tmp =
fDx1 + (pz +
fDz) * tgX;
1204 tmp = fDy1 + (pz +
fDz) * tgY;
1206 if (UUtils::Random() > 0.5)
1218 tmp = fDy1 + (pz +
fDz) * tgY;
1220 tmp =
fDx1 + (pz +
fDz) * tgX;
1222 if (UUtils::Random() > 0.5)
1239 :
VUSolid(rhs), fDx1(rhs.fDx1), fDx2(rhs.fDx2),
1240 fDy1(rhs.fDy1), fDy2(rhs.fDy2), fDz(rhs.fDz),
1241 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea)
1290 return new UTrd(*
this);
virtual double SafetyFromInside(const UVector3 &aPoint, bool aAccurate=false) const
double GetZHalfLength() const
virtual bool Normal(const UVector3 &aPoint, UVector3 &aNormal) const
const std::string & GetName() const
double SafetyFromOutsideAccurate(const UVector3 &aPoint) const
static double fgTolerance
UVector3 GetPointOnSurface() const
double GetXHalfLength2() const
UVector3 ApproxSurfaceNormal(const UVector3 &p) const
virtual void GetParametersList(int, double *) const
G4double fcos(G4double arg)
double SafetyFromInsideAccurate(const UVector3 &aPoint) const
void CheckAndSetAllParameters(double pdx1, double pdx2, double pdy1, double pdy2, double pdz)
double amax(int n, const double *a) const
static const double kInfinity
double GetYHalfLength2() const
void SetAllParameters(double pdx1, double pdx2, double pdy1, double pdy2, double pdz)
double amin(int n, const double *a) const
double GetYHalfLength1() const
EnumInside Inside(const UVector3 &aPoint) const
Return whether point inside/outside/on surface Split into radius checks.
void Exception(const char *originOfException, const char *exceptionCode, UExceptionSeverity severity, int level, const char *description)
void Set(double xx, double yy, double zz)
void Extent(UVector3 &aMin, UVector3 &aMax) const
Returns the full 3D cartesian extent of the solid.
UTrd & operator=(const UTrd &rhs)
T max(const T t1, const T t2)
brief Return the largest of the two arguments
double GetXHalfLength1() const
std::string UGeometryType
UGeometryType GetEntityType() const
virtual double DistanceToOut(const UVector3 &aPoint, const UVector3 &aDirection, UVector3 &aNormalVector, bool &aConvex, double aPstep=UUtils::kInfinity) const
std::ostream & StreamInfo(std::ostream &os) const
virtual double SafetyFromOutside(const UVector3 &aPoint, bool aAccurate=false) const
double Random(double min=0.0, double max=1.0)
virtual double DistanceToIn(const UVector3 &aPoint, const UVector3 &aDirection, double aPstep=UUtils::kInfinity) const