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;
79 double pdy2,
double pdz )
88 double safe, zbase, tanxz, xdist, saf1, tanyz, ydist, saf2;
93 int oldprc = std::cout.precision(16) ;
94 std::cout << std::endl ;
96 std::cout <<
"Position:" << std::endl << std::endl ;
97 std::cout <<
"p.x() = " << p.
x() /
mm <<
" mm" << std::endl ;
98 std::cout <<
"p.y() = " << p.
y() /
mm <<
" mm" << std::endl ;
99 std::cout <<
"p.z() = " << p.
z() /
mm <<
" mm" << std::endl << std::endl ;
100 std::cout.precision(oldprc) ;
102 "Point p is outside !?");
106 safe =
fDz - std::fabs(p.
z());
114 xdist =
fDx1 + tanxz * zbase - std::fabs(p.
x());
115 saf1 = xdist / std::sqrt(1.0 + tanxz * tanxz);
119 ydist =
fDy1 + tanyz * zbase - std::fabs(p.
y());
120 saf2 = ydist / std::sqrt(1.0 + tanyz * tanyz);
124 if (safe > saf1) safe = saf1;
125 if (safe > saf2) safe = saf2;
127 if (safe < 0) safe = 0;
141 saf[0] =
fDz - std::abs(p.
z());
143 double calf = 1. / std::sqrt(1.0 + fx * fx);
145 double distx = 0.5 * (
fDx1 +
fDx2) - fx * p.
z();
147 else saf[1] = (distx - std::abs(p.
x())) * calf;
150 calf = 1. / std::sqrt(1.0 + fy * fy);
152 distx = 0.5 * (
fDy1 +
fDy2) - fy * p.
z();
154 else saf[2] = (distx - std::abs(p.
y())) * calf;
176 double tanxz, distx, safx;
177 double tanyz, disty, safy;
180 safe = std::abs(p.
z()) -
fDz;
181 if (safe < 0) safe = 0;
190 distx = std::abs(p.
x()) - (
fDx1 + tanxz * zbase);
193 safx = distx / std::sqrt(1.0 + tanxz * tanxz);
194 if (safx > safe) safe = safx;
201 disty = std::abs(p.
y()) - (
fDy1 + tanyz * zbase);
204 safy = disty / std::sqrt(1.0 + tanyz * tanyz);
205 if (safy > safe) safe = safy;
218 saf[0] =
fDz - std::abs(p.
z());
220 double calf = 1. / std::sqrt(1.0 + fx * fx);
222 double distx = 0.5 * (
fDx1 +
fDx2) - fx * p.
z();
224 else saf[1] = (distx - std::abs(p.
x())) * calf;
227 calf = 1. / std::sqrt(1.0 + fy * fy);
229 distx = 0.5 * (
fDy1 +
fDy2) - fy * p.
z();
231 else saf[2] = (distx - std::abs(p.
y())) * calf;
233 for (
int i = 0; i < 3; i++) saf[i] = -saf[i];
259 double x, y, zbase1, zbase2;
263 zbase1 = p.
z() +
fDz;
264 zbase2 =
fDz - p.
z();
269 if (std::abs(p.
x()) <= x)
272 if (std::abs(p.
y()) <= y)
286 if (std::abs(p.
y()) <= y)
296 zbase1 = p.
z() +
fDz;
297 zbase2 =
fDz - p.
z();
302 if (std::abs(p.
x()) <= x)
329 double s1, s2, tanxz, tanyz, ds1, ds2;
330 double ss1, ss2, sn1 = 0., sn2 = 0., dist;
341 smin = -(
fDz + p.
z()) / v.
z();
351 smax = -dist / v.
z();
352 smin = (
fDz - p.
z()) / v.
z();
356 if (smin < 0) smin = 0 ;
360 if (std::abs(p.
z()) >=
fDz)
return snxt ;
373 s1 = 0.5 * (
fDx1 +
fDx2) + tanxz * p.
z() ;
374 ds1 = v.
x() - tanxz * v.
z() ;
375 ds2 = v.
x() + tanxz * v.
z() ;
380 if (ss1 < 0 && ss2 <= 0)
386 if (ds2 < 0) sn2 = ss2 / ds2 ;
391 else if (ss1 >= 0 && ss2 > 0)
397 if (ds1 > 0) sn2 = ss1 / ds1 ;
403 else if (ss1 >= 0 && ss2 <= 0)
423 if (dist < sn2) sn2 = dist ;
428 else if (ss1 < 0 && ss2 > 0)
432 if (ds1 >= 0 || ds2 <= 0)
440 if (dist > sn1) sn1 = dist ;
447 if (sn1 > smin) smin = sn1 ;
448 if (sn2 < smax) smax = sn2 ;
453 if (smax < smin)
return snxt ;
459 s2 = 0.5 * (
fDy1 +
fDy2) + tanyz * p.
z();
460 ds1 = v.
y() - tanyz * v.
z();
461 ds2 = v.
y() + tanyz * v.
z();
465 if (ss1 < 0 && ss2 <= 0)
470 if (ds2 < 0) sn2 = ss2 / ds2 ;
475 else if (ss1 >= 0 && ss2 > 0)
480 if (ds1 > 0) sn2 = ss1 / ds1 ;
485 else if (ss1 >= 0 && ss2 <= 0)
505 if (dist < sn2) sn2 = dist;
510 else if (ss1 < 0 && ss2 > 0)
514 if (ds1 >= 0 || ds2 <= 0)
522 if (dist > sn1) sn1 = dist ;
529 if (sn1 > smin) smin = sn1 ;
530 if (sn2 < smax) smax = sn2 ;
535 if (smax > smin) snxt = smin ;
557 UVector3&
n,
bool& aConvex,
double )
const
562 double central, ss1, ss2, ds1, ds2, sn = 0., sn2 = 0.;
563 double tanxz = 0., cosxz = 0., tanyz = 0., cosyz = 0.;
571 snxt = pdist / v.
z();
585 snxt = -pdist / v.
z();
610 ss1 = central + tanxz * p.
z() - p.
x();
612 ds1 = v.
x() - tanxz * v.
z();
616 ss2 = -tanxz * p.
z() - p.
x() - central;
618 ds2 = tanxz * v.
z() + v.
x();
620 if (ss1 > 0 && ss2 < 0)
623 if (ds1 <= 0 && ds2 < 0)
636 else if (ds1 > 0 && ds2 >= 0)
649 else if (ds1 > 0 && ds2 < 0)
687 else if (ss1 <= 0 && ss2 < 0)
714 else if (ss1 > 0 && ss2 >= 0)
757 ss1 = central + tanyz * p.
z() - p.
y();
759 ds1 = v.
y() - tanyz * v.
z();
763 ss2 = -tanyz * p.
z() - p.
y() - central;
765 ds2 = tanyz * v.
z() + v.
y();
767 if (ss1 > 0 && ss2 < 0)
771 if (ds1 <= 0 && ds2 < 0)
784 else if (ds1 > 0 && ds2 >= 0)
797 else if (ds1 > 0 && ds2 < 0)
835 else if (ss1 <= 0 && ss2 < 0)
862 else if (ss1 > 0 && ss2 >= 0)
902 cosxz = 1.0 / std::sqrt(1.0 + tanxz * tanxz);
903 n.
Set(cosxz, 0, -tanxz * cosxz);
906 cosxz = -1.0 / std::sqrt(1.0 + tanxz * tanxz);
907 n.
Set(cosxz, 0, tanxz * cosxz);
910 cosyz = 1.0 / std::sqrt(1.0 + tanyz * tanyz);
911 n.
Set(0, cosyz, -tanyz * cosyz);
914 cosyz = -1.0 / std::sqrt(1.0 + tanyz * tanyz);
915 n.
Set(0, cosyz, tanyz * cosyz);
925 UWarning, 1,
"Undefined side for valid surface normal to solid.");
938 double z = 2.0 *
fDz;
942 double secx = std::sqrt(1.0 + tanx * tanx);
943 double newpx = std::abs(p.
x()) - p.
z() * tanx;
944 double widx =
fDx2 -
fDz * tanx;
947 double secy = std::sqrt(1.0 + tany * tany);
948 double newpy = std::abs(p.
y()) - p.
z() * tany;
949 double widy =
fDy2 -
fDz * tany;
951 double distx = std::abs(newpx - widx) / secx;
952 double disty = std::abs(newpy - widy) / secy;
953 double distz = std::abs(std::abs(p.
z()) -
fDz);
957 double fcos = 1.0 / secx;
959 if (p.
x() >= 0.) sumnorm.
x() +=
fcos;
960 else sumnorm.
x() -=
fcos;
961 sumnorm.
z() -= tanx *
fcos;
965 double fcos = 1.0 / secy;
967 if (p.
y() >= 0.) sumnorm.
y() +=
fcos;
968 else sumnorm.
y() -=
fcos;
969 sumnorm.
z() -= tany *
fcos;
974 sumnorm.
z() += (p.
z() >= 0.) ? 1.0 : -1.0;
980 UWarning, 1,
"Point p is not on surface !?");
998 norm =
UVector3(fcos, 0, -tanx * fcos);
1000 norm =
UVector3(-fcos, 0, -tanx * fcos);
1020 norm =
UVector3(0, fcos, -tany * fcos);
1022 norm =
UVector3(0, -fcos, -tany * fcos);
1041 return noSurfaces > 0;
1053 double z, tanx, secx, newpx, widx;
1054 double tany, secy, newpy, widy;
1055 double distx, disty, distz,
fcos;
1060 secx = std::sqrt(1.0 + tanx * tanx);
1061 newpx = std::abs(p.
x()) - p.
z() * tanx;
1065 secy = std::sqrt(1.0 + tany * tany);
1066 newpy = std::abs(p.
y()) - p.
z() * tany;
1069 distx = std::abs(newpx - widx) / secx;
1070 disty = std::abs(newpy - widy) / secy;
1071 distz = std::abs(std::abs(p.
z()) -
fDz);
1084 norm =
UVector3(fcos, 0, -tanx * fcos);
1086 norm =
UVector3(-fcos, 0, -tanx * fcos);
1106 norm =
UVector3(0, fcos, -tany * fcos);
1108 norm =
UVector3(0, -fcos, -tany * fcos);
1142 int oldprc = os.precision(16);
1143 os <<
"-----------------------------------------------------------\n"
1144 <<
" *** Dump for solid - " <<
GetName() <<
" ***\n"
1145 <<
" ===================================================\n"
1146 <<
" Solid type: UTrd\n"
1147 <<
" Parameters: \n"
1148 <<
" half length X, surface -dZ: " <<
fDx1 <<
" mm \n"
1149 <<
" half length X, surface +dZ: " <<
fDx2 <<
" mm \n"
1150 <<
" half length Y, surface -dZ: " <<
fDy1 <<
" mm \n"
1151 <<
" half length Y, surface +dZ: " <<
fDy2 <<
" mm \n"
1152 <<
" half length Z : " <<
fDz <<
" mm \n"
1153 <<
"-----------------------------------------------------------\n";
1154 os.precision(oldprc);
1168 double px, py, pz, tgX, tgY, secX, secY, select, sumS, tmp;
1169 double Sxy1, Sxy2, Sxy, Sxz, Syz;
1172 secX = std::sqrt(1 + tgX * tgX);
1174 secY = std::sqrt(1 + tgY * tgY);
1182 Syz = (fDy1 +
fDy2) *
fDz * secX;
1183 sumS = Sxy + Sxz + Syz;
1202 else if ((select - Sxy) < Sxz)
1205 tmp =
fDx1 + (pz +
fDz) * tgX;
1207 tmp = fDy1 + (pz +
fDz) * tgY;
1209 if (UUtils::Random() > 0.5)
1221 tmp = fDy1 + (pz +
fDz) * tgY;
1223 tmp =
fDx1 + (pz +
fDz) * tgX;
1225 if (UUtils::Random() > 0.5)
1242 :
VUSolid(rhs), fDx1(rhs.fDx1), fDx2(rhs.fDx2),
1243 fDy1(rhs.fDy1), fDy2(rhs.fDy2), fDz(rhs.fDz),
1244 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea)
1293 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