19 #include "KVPosition.h"
21 #include "Riostream.h"
27 #define ROOT_GEO_DO_NOT_USE(method,retval) \
29 ::Warning(method, "Does not work with ROOT geometries. Do not use."); \
40 Double_t phmax, Double_t dist)
61 if (fTheta_min == -180.) {
63 fTheta_min = fTheta - .5 * (fTheta_max + 180.);
64 fTheta_max = 2. * fTheta - fTheta_min;
85 if (fPhi_min == -180.) {
87 fPhi_min = fPhi - .5 * (fPhi_max + 180.);
88 fPhi_max = 2. * fPhi - fPhi_min;
112 ROOT_GEO_DO_NOT_USE(
"SetPolarWidth",)
115 fTheta_min = fTheta - .5 * pw;
116 fTheta_max = fTheta + .5 * pw;
120 fTheta_max = fTheta_min + pw;
133 ROOT_GEO_DO_NOT_USE(
"SetPolarMinMax",)
136 fTheta = .5 * (min + max);
154 ROOT_GEO_DO_NOT_USE(
"SetAzimuthalWidth",)
156 fPhi_min = fPhi - .5 * aw;
159 fPhi_max = fPhi + .5 * aw;
160 if (fPhi_max >= 360.)
165 fPhi_max = fPhi_min + aw;
178 ROOT_GEO_DO_NOT_USE(
"SetAzimuthalMinMax",)
183 fPhi = .5 * (min + max);
217 Double_t dtor = TMath::DegToRad();
221 dummy.SetMagThetaPhi(1.0, th * dtor, ph * dtor);
250 Double_t dtor = TMath::DegToRad();
255 th = r.Theta() / dtor;
257 if (ph < 0) ph += 360.;
261 Double_t phmin = fPhi_min;
262 Double_t phmax = fPhi_max;
266 Double_t dphi = phmax - phmin;
267 Double_t thmin, thmax, dtheta;
269 if (!strcmp(t,
"random")) {
270 thmin = fTheta_min * dtor;
271 thmax = fTheta_max * dtor;
272 dtheta = thmax - thmin;
273 th = gRandom->Uniform(dtheta) + thmin;
276 thmin = TMath::Cos(fTheta_min * dtor);
277 thmax = TMath::Cos(fTheta_max * dtor);
278 dtheta = thmin - thmax;
279 th = TMath::ACos(gRandom->Uniform(dtheta) + thmax);
281 ph = gRandom->Uniform(dphi) + phmin;
299 fTheta_min=fPhi_min=999;
300 fTheta_max=fPhi_max=-1;
305 auto th = r.Theta() / TMath::RadToDeg();
306 auto ph = r.Phi() / TMath::RadToDeg();
307 if (ph < 0) ph += 360.;
308 fTheta_max = std::max(fTheta_max,th);
309 fPhi_max = std::max(fPhi_max,ph);
310 fTheta_min = std::min(fTheta_min,th);
311 fPhi_min = std::min(fPhi_min,ph);
313 fMaxMisalignment = std::max(fMaxMisalignment,misalign);
328 ROOT_GEO_DO_NOT_USE(
"IsInPhiRange", kFALSE)
330 Double_t phimintest = fPhi_min;
331 Double_t phimaxtest = fPhi_max;
332 if (phimintest > phimaxtest) {
335 if (phi >= phimintest && phi <= phimaxtest) {
338 if ((phi + 360.) >= phimintest && (phi + 360.) <= phimaxtest) {
353 ROOT_GEO_DO_NOT_USE(
"IsInPolarRange", kFALSE)
355 if (theta >= fTheta_min && theta <= fTheta_max)
370 ROOT_GEO_DO_NOT_USE(
"IsSmallerThan", kFALSE)
386 ROOT_GEO_DO_NOT_USE(
"IsAlignedWith", kFALSE)
399 ROOT_GEO_DO_NOT_USE(
"IsOverlappingWith", kFALSE)
438 ROOT_GEO_DO_NOT_USE(
"IsAzimuthallyWiderThan", kFALSE)
455 TVector3 tmp(1.0, 0.0, 0.0);
456 tmp.SetTheta(fTheta * TMath::Pi() / 180.);
457 tmp.SetPhi(fPhi * TMath::Pi() / 180.);
503 ROOT_GEO_DO_NOT_USE(
"GetCornerCoordinates",)
506 Double_t pthR =
GetTheta() * TMath::DegToRad();
507 Double_t pphR =
GetPhi() * TMath::DegToRad();
508 TVector3 normal_to_plane(sin(pthR)*cos(pphR), sin(pthR)*sin(pphR), cos(pthR));
517 for (
int i = 0; i < 4; i++) {
518 Double_t t = corners[i] * normal_to_plane;
519 if (t <= 0.0) corners[i].SetXYZ(0, 0, 0);
520 else corners[i] *= (fDistance + depth) / t;
536 ROOT_GEO_DO_NOT_USE(
"GetCornerCoordinatesInOwnFrame",)
538 TRotation rot_to_frame;
539 rot_to_frame.SetYEulerAngles(-
GetPhi()*TMath::DegToRad(), -
GetTheta()*TMath::DegToRad(), 0.);
540 TVector3 displZ(0, 0, fDistance + depth);
541 for (
int i = 0; i < 4; i++) {
542 corners[i] = rot_to_frame * corners[i] - displZ;
569 fSolidAngle = area / pow(
GetDistance(), 2.) * 1.e3;
574 return (-1.*cos(
GetThetaMax() * TMath::DegToRad()) +
597 ROOT_GEO_DO_NOT_USE(
"GetAzimuthalWidth", 0.)
604 return (phmax - phmin);
606 return (phmax - phmin + 360.);
624 Error(
"GetWidthsFromDimension",
"Distance not set");
628 2. * TMath::RadToDeg() * TMath::ATan(lin_dim /
650 ROOT_GEO_DO_NOT_USE(
"GetRandomIsotropicRotation", rr2)
651 Double_t a1min, a1max, a2min, a2max, a3min, a3max;
653 a1max = 2 * TMath::Pi();
658 a3min += TMath::Pi() / 2.;
659 a3max += TMath::Pi() / 2.;
660 rr2.SetXEulerAngles(gRandom->Uniform(a1min, a1max),
661 TMath::ACos(gRandom->Uniform(cos(a2max), cos(a2min))),
662 gRandom->Uniform(a3min, a3max));
680 void KVPosition::initialize_root_geo()
692 set_surface_centre();
695 SetTheta(centre.Theta()*TMath::RadToDeg());
696 SetPhi(centre.Phi()*TMath::RadToDeg());
702 if (!
GetShape()->InheritsFrom(
"TGeoArb8")) {
703 Double_t area =
GetShape()->GetFacetArea(1) * GetOC_SC_CosAngle();
704 fSolidAngle = area / pow(
GetDistance(), 2.) * 1.e3;
717 fMatrix.reset(
new TGeoHMatrix(*m));
719 initialize_root_geo();
736 initialize_root_geo();
750 return fMatrix.get();
798 ::Error(
"KVPosition::GetRandomPointOnSurface",
799 "ROOT Geometry has not been initialised");
802 Double_t master[3 * 50];
803 Double_t points[3 * 50];
804 const Double_t* origin =
GetShape()->GetOrigin();
807 Bool_t ok1 =
GetShape()->TGeoBBox::GetPointsOnFacet(1, 50, points);
810 points[2] += dz / 100.;
812 for (
int i = 0; i < 3; i++) points[i] += origin[i];
813 Bool_t ok2 =
GetShape()->Contains(points);
815 ::Error(
"KVPosition::GetRandomPoint",
816 "TGeoBBox::GetPointsOnFacet returns kFALSE for shape %s. Returning coordinates of centre.",
GetShape()->ClassName());
824 Double_t* npoint = points + 3 * np;
825 npoint[2] += dz / 100.;
827 for (
int i = 0; i < 3; i++) npoint[i] += origin[i];
833 ::Error(
"KVPosition::GetRandomPointOnSurface",
834 "Cannot generate points for shape %s. Returning coordinates of surface centre.",
GetShape()->ClassName());
838 Double_t* npoint = points + 3 * np;
839 npoint[2] -= dz / 100.;
840 GetMatrix()->LocalToMaster(npoint, master);
841 return TVector3(master);
855 void KVPosition::set_surface_centre()
866 const Double_t* origin =
GetShape()->GetOrigin();
867 Double_t points[] = {origin[0], origin[1], origin[2] -
GetShape()->GetDZ()};
868 GetMatrix()->LocalToMaster(points, master);
869 fSurfaceCentre = TVector3(master);
879 void KVPosition::set_volume_centre()
886 const Double_t* origin =
GetShape()->GetOrigin();
887 Double_t points[] = {origin[0], origin[1], origin[2]};
888 GetMatrix()->LocalToMaster(points, master);
889 fVolumeCentre = TVector3(master);
911 Double_t* points =
new Double_t[3 * npoints];
912 const Double_t* origin =
GetShape()->GetOrigin();
915 Bool_t ok1 =
GetShape()->TGeoBBox::GetPointsOnFacet(1, npoints, points);
917 ::Error(
"KVPosition::GetEntranceWindowArea",
918 "TGeoBBox::GetPointsOnFacet returns kFALSE for shape %s. Returning 0.0",
GetShape()->ClassName());
922 Double_t points_on_facet = 0;
923 for (Int_t np = 0; np < npoints; ++np) {
924 Double_t* npoint = points + 3 * np;
927 npoint[2] += dz / 100.;
929 for (
int i = 0; i < 3; i++) npoint[i] += origin[i];
930 if (
GetShape()->Contains(npoint)) ++points_on_facet;
933 return GetShape()->GetFacetArea(1) * (points_on_facet / Double_t(npoints));
Base class used for handling geometry in a multidetector array.
virtual void GetRandomAngles(Double_t &th, Double_t &ph, Option_t *t="isotropic")
Bool_t IsInPhiRange(const Double_t phi)
virtual void SetAzimuthalWidth(Double_t aw)
virtual TVector3 GetRandomDirection(Option_t *t="isotropic")
Bool_t IsAzimuthallyWiderThan(KVPosition *pos)
virtual void SetShape(TGeoBBox *)
virtual void SetAzimuthalMinMax(Double_t min, Double_t max)
Set min and max azimuthal angles and calculate (mean) phi.
virtual void SetAzimuthalAngle(Double_t ph)
virtual Double_t GetSolidAngle(void) const
virtual Double_t GetTheta() const
void GetCornerCoordinates(TVector3 *, Double_t=0)
virtual TGeoHMatrix * GetMatrix() const
virtual TVector3 GetSurfaceCentre() const
void GetWidthsFromDimension(Double_t lin_dim)
void SetDistance(Double_t d)
TRotation GetRandomIsotropicRotation()
virtual TVector3 GetVolumeCentre() const
virtual void SetPolarAngle(Double_t th)
virtual Double_t GetPhi() const
Double_t GetPhiMax() const
virtual Double_t GetDistance(void) const
Double_t GetPhiMin() const
Bool_t IsSmallerThan(KVPosition *pos)
kTRUE if "this" is entirely contained within "pos"
virtual Double_t GetSurfaceArea(int npoints=100000) const
Double_t GetThetaMin() const
virtual Double_t GetSinTheta() const
virtual TVector3 GetNormalIntoShape() const
Double_t GetAzimuthalWidth(Double_t phmin=-1., Double_t phimax=-1.) const
Bool_t IsInPolarRange(const Double_t theta)
kTRUE if given angle theta is within the polar range of this solid angle element
virtual void SetPolarWidth(Double_t pw)
Bool_t IsAlignedWith(KVPosition *pos)
kTRUE if one of the two solid angle elements is completely contained within the other.
void SetTheta(Double_t t)
void CalculateEstimatedAngularLimits(int N=10000)
virtual void SetPolarMinMax(Double_t min, Double_t max)
Set min and max polar angles and calculate (mean) theta.
virtual void SetMatrix(const TGeoHMatrix *)
Set the global transformation matrix for this volume.
virtual TGeoBBox * GetShape() const
Bool_t IsOverlappingWith(KVPosition *pos)
kTRUE if there is at least partial overlap between two solid angle elements
virtual Bool_t ROOTGeo() const
void GetCornerCoordinatesInOwnFrame(TVector3 *, Double_t=0)
Double_t GetThetaMax() const
virtual TVector3 GetDirection()
virtual TVector3 GetRandomPointOnSurface() const