KaliVeda
Toolkit for HIC analysis
KVPosition.cpp
1 /***************************************************************************
2 $Id: KVPosition.cpp,v 1.21 2008/12/17 13:01:26 franklan Exp $
3  kvposition.cpp - description
4  -------------------
5  begin : Sun May 19 2002
6  copyright : (C) 2002 by J.D. Frankland
7  email : frankland@ganil.fr
8  ***************************************************************************/
9 
10 /***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
19 #include "KVPosition.h"
20 #include "TRandom3.h"
21 #include "Riostream.h"
22 #include "TMath.h"
23 #include "TGeoMatrix.h"
24 #include "TGeoBBox.h"
25 
26 
28 
29 #define ROOT_GEO_DO_NOT_USE(method,retval) \
30  if(ROOTGeo()){ \
31  ::Warning(method, "Does not work with ROOT geometries. Do not use."); \
32  return retval; \
33  }
34 
35 
37 
38 
39 
42 
44 {
45  //default initialiser
46 
47  fTheta = fPhi = -1.0;
49  fMatrix = 0;
50  fShape = 0;
51  fSolidAngle = 0;
52 }
53 
54 
55 
57 
59 {
60  if (fMatrix) {
61  delete fMatrix;
62  fMatrix = 0;
63  }
64 }
65 
66 
67 
69 
71 {
72  init();
73 }
74 
75 
76 
78 
80  Double_t phmax, Double_t dist)
81 {
82  init();
83  SetPolarMinMax(thmin, thmax);
84  SetAzimuthalMinMax(phmin, phmax);
86 };
87 
88 
89 
90 
95 
97 {
98  //Sets the polar angle corresponding to the centre of this telescope/solid angle element/etc.
99  //If the polar width has been set already (KVPosition::SetPolarWidth),
100  //the limits theta-min and theta-max are calculated.
101 
102  fTheta = th;
103  if (fTheta_min == -180.) { // polar width of detector already set, calculate theta_min
104  // and theta_max
105  fTheta_min = fTheta - .5 * (fTheta_max + 180.);
106  fTheta_max = 2. * fTheta - fTheta_min;
107  }
108 }
109 
110 
111 
116 
118 {
119  //Sets the azimuthal angle corresponding to the centre of this telescope/solid angle element/etc.
120  //If the azimuthal width has been set already (KVPosition::SetAzimuthalWidth),
121  //the limits phi-min and phi-max are calculated.
122 
123  fPhi = ph;
124  //make sure phi between 0 and 360
125  if (fPhi < 0.)
126  fPhi += 360.;
127  if (fPhi_min == -180.) { // azimuthal width of detector already set, calculate phi_min
128  // and phi_max
129  fPhi_min = fPhi - .5 * (fPhi_max + 180.);
130  fPhi_max = 2. * fPhi - fPhi_min;
131  //make sure phimin and phimax are between 0 and 360
132  if (fPhi_min < 0.)
133  fPhi_min += 360.;
134  if (fPhi_max >= 360.)
135  fPhi_max -= 360.;
136  }
137 }
138 
139 
140 
146 
148 {
149  //Set theta_min and theta_max from width (in degrees).
150  //If theta is already known, use to set theta_min and theta_max.
151  //If not, keep relative values (negative) of theta_min and theta_max,
152  //to be used when theta is set
153 
154  ROOT_GEO_DO_NOT_USE("SetPolarWidth",)
155 
156  if (fTheta > -1.0) {
157  fTheta_min = fTheta - .5 * pw;
158  fTheta_max = fTheta + .5 * pw;
159  }
160  else {
161  fTheta_min = -180.;
162  fTheta_max = fTheta_min + pw;
163  }
164 }
165 
166 
167 
170 
172 {
173  //Set min and max polar angles and calculate (mean) theta
174 
175  ROOT_GEO_DO_NOT_USE("SetPolarMinMax",)
176  fTheta_min = min;
177  fTheta_max = max;
178  fTheta = .5 * (min + max);
179 }
180 
181 
182 
188 
190 {
191  //Set phi_min and phi_max from width (in degrees)
192  // If phi is already known, use to set phi_min and phi_max
193  // If not, keep relative values (negative) of phi_min and phi_max,
194  // to be used when phi is set
195 
196  ROOT_GEO_DO_NOT_USE("SetAzimuthalWidth",)
197  if (fPhi > -1.0) {
198  fPhi_min = fPhi - .5 * aw;
199  if (fPhi_min < 0.)
200  fPhi_min += 360.;
201  fPhi_max = fPhi + .5 * aw;
202  if (fPhi_max >= 360.)
203  fPhi_max -= 360.;
204  }
205  else {
206  fPhi_min = -180.;
207  fPhi_max = fPhi_min + aw;
208  }
209 }
210 
211 
212 
215 
217 {
218  //Set min and max azimuthal angles and calculate (mean) phi
219 
220  ROOT_GEO_DO_NOT_USE("SetAzimuthalMinMax",)
221  fPhi_min = min;
222  fPhi_max = max;
223  if (min > max)
224  max += 360;
225  fPhi = .5 * (min + max);
226  if (fPhi >= 360.)
227  fPhi -= 360.;
228 }
229 
230 
231 
241 
243 {
244  // Returns a unit vector in a random direction corresponding to this detector.
245  // Depending on the optional option string, the direction is either drawn at
246  // "random" among the corresponding angles, or "isotropic".
247  // By default, the direction is "isotropic".
248  //
249  // * ROOT Geometry *
250  // Direction corresponds to a random position on the entrance surface of the volume.
251  // The "isotropic" option has no effect.
252 
253  if (ROOTGeo()) {
254  // * ROOT Geometry *
256  return r.Unit();
257  }
258 
259  Double_t dtor = TMath::DegToRad();
260  Double_t th, ph;
261  GetRandomAngles(th, ph, t);
262  TVector3 dummy;
263  dummy.SetMagThetaPhi(1.0, th * dtor, ph * dtor); // a unit vector
264 
265  return dummy;
266 }
267 
268 
279 
281 {
282  // Set th and ph to random values between the max and min limits defining the
283  // solid angle element.
284  // Depending on the optional option string, the direction is either drawn at
285  // "random" among the corresponding angles, or "isotropic".
286  // By default, the direction is "isotropic".
287  //
288  // * ROOT Geometry *
289  // th and ph correspond to a random position on the detector's entrance window.
290  // The "isotropic" option has no effect.
291 
292  Double_t dtor = TMath::DegToRad();
293 
294  if (ROOTGeo()) {
295  // * ROOT Geometry *
297  th = r.Theta() / dtor;
298  ph = r.Phi() / dtor;
299  if (ph < 0) ph += 360.;
300  return;
301  }
302 
303  Double_t phmin = fPhi_min; //phimin in radians
304  Double_t phmax = fPhi_max; //phimax in radians
305  if (phmax < phmin)
306  phmax += 360;
307 
308  Double_t dphi = phmax - phmin;
309  Double_t thmin, thmax, dtheta;
310 
311  if (!strcmp(t, "random")) {
312  thmin = fTheta_min * dtor;
313  thmax = fTheta_max * dtor;
314  dtheta = thmax - thmin;
315  th = gRandom->Uniform(dtheta) + thmin;
316  }
317  else {
318  thmin = TMath::Cos(fTheta_min * dtor);
319  thmax = TMath::Cos(fTheta_max * dtor);
320  dtheta = thmin - thmax;
321  th = TMath::ACos(gRandom->Uniform(dtheta) + thmax);
322  }
323  ph = gRandom->Uniform(dphi) + phmin;
324  if (ph > 360)
325  ph -= 360;
326  th /= dtor;
327 
328 }
329 
330 
331 
335 
337 {
338  // For ROOT geometries, perform a Monte-Carlo sampling in order to estimate the min/max
339  // polar and azimuthal angles of this volume
340 
341  fTheta_min=fPhi_min=999;
342  fTheta_max=fPhi_max=-1;
343  while(N--)
344  {
345  double th,ph;
346  GetRandomAngles(th,ph);
347  fTheta_max = std::max(fTheta_max,th);
348  fPhi_max = std::max(fPhi_max,ph);
349  fTheta_min = std::min(fTheta_min,th);
350  fPhi_min = std::min(fPhi_min,ph);
351  }
352 }
353 
354 
355 
359 
361 {
362  //kTRUE if given angle phi is within the azimuthal range of this solid
363  //angle element
364 
365  ROOT_GEO_DO_NOT_USE("IsInPhiRange", kFALSE)
366 
367  Double_t phimintest = fPhi_min;
368  Double_t phimaxtest = fPhi_max;
369  if (phimintest > phimaxtest) {
370  phimaxtest += 360.;
371  }
372  if (phi >= phimintest && phi <= phimaxtest) {
373  return kTRUE;
374  }
375  if ((phi + 360.) >= phimintest && (phi + 360.) <= phimaxtest) {
376  return kTRUE;
377  }
378  return kFALSE;
379 }
380 
381 
382 
385 
387 {
388  //kTRUE if given angle theta is within the polar range of this solid angle element
389 
390  ROOT_GEO_DO_NOT_USE("IsInPolarRange", kFALSE)
391 
392  if (theta >= fTheta_min && theta <= fTheta_max)
393  return kTRUE;
394  else
395  return kFALSE;
396 }
397 
398 
399 
402 
404 {
405  // kTRUE if "this" is entirely contained within "pos"
406 
407  ROOT_GEO_DO_NOT_USE("IsSmallerThan", kFALSE)
408  return (pos->IsInPolarRange(GetThetaMin())
409  && pos->IsInPolarRange(GetThetaMax())
410  && pos->IsInPhiRange(GetPhiMin())
411  && pos->IsInPhiRange(GetPhiMax()));
412 }
413 
414 
415 
418 
420 {
421  //kTRUE if one of the two solid angle elements is completely contained within the other.
422 
423  ROOT_GEO_DO_NOT_USE("IsAlignedWith", kFALSE)
424  return (IsSmallerThan(pos) || pos->IsSmallerThan(this));
425 }
426 
427 
428 
431 
433 {
434  //kTRUE if there is at least partial overlap between two solid angle elements
435 
436  ROOT_GEO_DO_NOT_USE("IsOverlappingWith", kFALSE)
437  return (
438  //overlapping corners - case 1
439  (IsInPolarRange(other->GetThetaMin())
440  || IsInPolarRange(other->GetThetaMax()))
441  && (IsInPhiRange(other->GetPhiMin())
442  || IsInPhiRange(other->GetPhiMax()))
443  ) || (
444  //overlapping corners - case 2
445  (other->IsInPolarRange(GetThetaMin())
446  || other->IsInPolarRange(GetThetaMax()))
447  && (other->IsInPhiRange(GetPhiMin())
448  || other->IsInPhiRange(GetPhiMax()))
449  ) || (
450  //case where this is phi-contained by the other, but the other is theta-contained by this
451  (other->IsInPolarRange(GetThetaMin())
452  || other->IsInPolarRange(GetThetaMax()))
453  && (IsInPhiRange(other->GetPhiMin())
454  || IsInPhiRange(other->GetPhiMax()))
455  ) || (
456  //case where this is phi-contained by the other, but the other is theta-contained by this
457  (IsInPolarRange(other->GetThetaMin())
458  || IsInPolarRange(other->GetThetaMax()))
459  && (other->IsInPhiRange(GetPhiMin())
460  || other->IsInPhiRange(GetPhiMax()))
461  );
462 }
463 
464 
465 
469 
471 {
472  //kTRUE if "this" has larger azimuthal width than "pos".
473  //Takes care of cases where the solid angle straddles 0 degrees
474 
475  ROOT_GEO_DO_NOT_USE("IsAzimuthallyWiderThan", kFALSE)
476  if (GetAzimuthalWidth() > pos->GetAzimuthalWidth())
477  return kTRUE;
478  return kFALSE;
479 }
480 
481 
482 
486 
488 {
489  //Returns a unit vector corresponding to the direction of fTheta, fPhi
490  //i.e. the centre of the solid angle element.
491 
492  TVector3 tmp(1.0, 0.0, 0.0);
493  tmp.SetTheta(fTheta * TMath::Pi() / 180.);
494  tmp.SetPhi(fPhi * TMath::Pi() / 180.);
495  return tmp;
496 }
497 
498 
499 
500 
519 
521 {
522  // Fill the array (TVector3 corner[4]) with the coordinates of the 4 'corners' of the solid angle element.
523  //
524  // These 'corners' are the points of intersection between the plane defined by the normal
525  // to the centre of the solid angle (direction: theta,phi), at a distance fDistance [cm] from the
526  // origin, and the four lines starting at the origin with directions (thetamin,phimin),
527  // (thetamax,phimin), (thetamax,phimax), (thetamin,phimax).
528  //
529  // If optional argument 'depth' [cm] is given, the coordinates are calculated for the plane
530  // situated at distance (fDistance+depth) from the origin.
531  //
532  // The order of the 4 corners is as follows:
533  // corners[3] : theta-min, phi-min
534  // corners[2] : theta-max, phi-min
535  // corners[1] : theta-max, phi-max
536  // corners[0] : theta-min, phi-max
537  //
538  // Coordinates are in CENTIMETRES
539 
540  ROOT_GEO_DO_NOT_USE("GetCornerCoordinates",)
541 
542  // calculate unit vector normal to solid angle
543  Double_t pthR = GetTheta() * TMath::DegToRad();
544  Double_t pphR = GetPhi() * TMath::DegToRad();
545  TVector3 normal_to_plane(sin(pthR)*cos(pphR), sin(pthR)*sin(pphR), cos(pthR));
546 
547  // the four directions/lines
552 
553  // calculate intersection points
554  for (int i = 0; i < 4; i++) {
555  Double_t t = corners[i] * normal_to_plane;
556  if (t <= 0.0) corners[i].SetXYZ(0, 0, 0);
557  else corners[i] *= (fDistance + depth) / t;
558  }
559 }
560 
561 
562 
563 
567 
569 {
570  // Like GetCornerCoordinates(), except that the coordinates correspond to a reference frame
571  // in which the +ve z-axis goes through the centre of the solid angle
572 
573  ROOT_GEO_DO_NOT_USE("GetCornerCoordinatesInOwnFrame",)
574  GetCornerCoordinates(corners, depth);
575  TRotation rot_to_frame;
576  rot_to_frame.SetYEulerAngles(-GetPhi()*TMath::DegToRad(), -GetTheta()*TMath::DegToRad(), 0.);
577  TVector3 displZ(0, 0, fDistance + depth);
578  for (int i = 0; i < 4; i++) {
579  corners[i] = rot_to_frame * corners[i] - displZ;
580  }
581 }
582 
583 
584 
590 
592 {
593  // Return values of the solid angle (in msr) seen by the geometric ensemble
594  // For simple geometries defined by theta_min/max etc., this is exact.
595  // For ROOT geometries we calculate the area of the entrance window and divide
596  // it by the square of the distance to the detector.
597 
598  if (ROOTGeo()) {
599  if (!fSolidAngle) {
600  // TGeoArb8 shapes' solid angles calculated on demand as this requires
601  // a monte carlo calculation
602  // this takes into account any eventual "misalignment" i.e. if the vector from the
603  // origin to the centre of the volume is not perpendicular to the entrance surface,
604  // which reduces the effective area "seen" from the target
606  fSolidAngle = area / pow(GetDistance(), 2.) * 1.e3;
607  }
608  return fSolidAngle;
609  }
610 
611  return (-1.*cos(GetThetaMax() * TMath::DegToRad()) +
613  * (GetAzimuthalWidth() * TMath::DegToRad()) * 1.e3;
614 
615 }
616 
617 
618 
619 
620 
626 
628 {
629  //Calculate azimuthal width taking phi-min as the most anticlockwise point of the
630  //element and phi-max the most clockwise.
631  //If no arguments are given, width calculated for this object
632  //Otherwise, width calculated for given phi-min and phi-max
633 
634  ROOT_GEO_DO_NOT_USE("GetAzimuthalWidth", 0.)
635 
636  if (phmin == -1.)
637  phmin = GetPhiMin();
638  if (phmax == -1.)
639  phmax = GetPhiMax();
640  if (phmin < phmax)
641  return (phmax - phmin);
642  else
643  return (phmax - phmin + 360.);
644 }
645 
646 
647 
648 
653 
655 {
656  //Calculate azimuthal and polar widths for a square element placed at a
657  //given distance from the origin with linear dimension 'lin_dim' (in mm).
658  //SetDistance, SetTheta and SetPhi must already have been called.
659 
660  if (GetDistance() <= 0.0) {
661  Error("GetWidthsFromDimension", "Distance not set");
662  return;
663  }
664  Double_t d__th =
665  2. * TMath::RadToDeg() * TMath::ATan(lin_dim /
666  (2. * GetDistance()));
667  Double_t d__ph =
668  TMath::RadToDeg() * lin_dim / (GetDistance() * GetSinTheta());
669  SetPolarWidth(d__th);
670  SetAzimuthalWidth(d__ph);
671 }
672 
673 
674 
679 
681 {
682  // Generates a rotation which, if applied to a unit vector in the Z-direction,
683  // will transform it into an isotropically-distributed vector in this
684  // angular range.
685 
686  TRotation rr2;
687  ROOT_GEO_DO_NOT_USE("GetRandomIsotropicRotation", rr2)
688  Double_t a1min, a1max, a2min, a2max, a3min, a3max;
689  a1min = 0;
690  a1max = 2 * TMath::Pi();
691  a2min = GetThetaMin() * TMath::DegToRad();
692  a2max = GetThetaMax() * TMath::DegToRad();
693  a3min = GetPhiMin() * TMath::DegToRad();
694  a3max = GetPhiMax() * TMath::DegToRad();
695  a3min += TMath::Pi() / 2.;
696  a3max += TMath::Pi() / 2.;
697  rr2.SetXEulerAngles(gRandom->Uniform(a1min, a1max),
698  TMath::ACos(gRandom->Uniform(cos(a2max), cos(a2min))),
699  gRandom->Uniform(a3min, a3max));
700  return rr2;
701 }
702 
703 
705 
706 
716 
718 {
719  // * ROOT Geometry *
720  // Set the global transformation matrix for this volume
721  // If shape has been set, we set the (theta,phi) angles
722  // corresponding to the centre of the volume, and
723  // the distance from the target corresponding to the distance
724  // along (theta,phi) to the entrance surface of the volume
725  // (not necessarily the same as the distance from the target to
726  // the centre of the entrance surface)
727 
728  if (fMatrix) delete fMatrix;
729  fMatrix = new TGeoHMatrix(*m);
730  if (ROOTGeo()) {
731  TVector3 centre = GetVolumeCentre();
732  SetTheta(centre.Theta()*TMath::RadToDeg());
733  SetPhi(centre.Phi()*TMath::RadToDeg());
735  // solid angle calculated and set here only for non-TGeoArb8 shapes
736  // this takes into account any eventual "misalignment" i.e. if the vector from the
737  // origin to the centre of the volume is not perpendicular to the entrance surface,
738  // which reduces the effective area "seen" from the target
739  if (!GetShape()->InheritsFrom("TGeoArb8")) {
741  fSolidAngle = area / pow(GetDistance(), 2.) * 1.e3;
742  }
743  }
744 }
745 
746 
747 
757 
759 {
760  // * ROOT Geometry *
761  // Set the shape of this detector
762  // If matrix has been set, we set the (theta,phi) angles
763  // corresponding to the centre of the volume, and
764  // the distance from the target corresponding to the distance
765  // along (theta,phi) to the entrance surface of the volume
766  // (not necessarily the same as the distance from the target to
767  // the centre of the entrance surface)
768 
769  fShape = b;
770  if (ROOTGeo()) {
771  TVector3 centre = GetVolumeCentre();
772  SetTheta(centre.Theta()*TMath::RadToDeg());
773  SetPhi(centre.Phi()*TMath::RadToDeg());
775  // solid angle calculated and set here only for non-TGeoArb8 shapes
776  // this takes into account any eventual "misalignment" i.e. if the vector from the
777  // origin to the centre of the volume is not perpendicular to the entrance surface,
778  // which reduces the effective area "seen" from the target
779  if (!GetShape()->InheritsFrom("TGeoArb8")) {
781  fSolidAngle = area / pow(GetDistance(), 2.) * 1.e3;
782  }
783  }
784 }
785 
786 
787 
791 
793 {
794  // * ROOT Geometry *
795  // Return global transformation matrix for this detector
796  return fMatrix;
797 }
798 
799 
800 
804 
806 {
807  // * ROOT Geometry *
808  // Return shape of this detector
809  return fShape;
810 }
811 
812 
813 
827 
829 {
830  // * ROOT Geometry *
831  // Generate a vector in the world (laboratory) frame from the origin
832  // to a random point on the entrance surface of this volume.
833  //
834  // It is assumed that the volume was defined in such a way
835  // that the entrance window corresponds to the facet in the X-Y plane
836  // placed at -dZ.
837  //
838  // NOTE: we force the use of TGeoBBox::GetPointsOnFacet.
839  // For TGeoArb8, the method has been overridden and does nothing.
840  // We use the TGeoBBox method, and then use TGeoShape::Contains
841  // to check that the point does actually correspond to the TGeoArb8.
842 
843  if (!ROOTGeo()) {
844  ::Error("KVPosition::GetRandomPointOnSurface",
845  "ROOT Geometry has not been initialised");
846  return TVector3();
847  }
848  Double_t master[3 * 50];
849  Double_t points[3 * 50];
850  const Double_t* origin = GetShape()->GetOrigin();
851  Double_t dz = GetShape()->GetDZ();
852  // This will generate a point on the (-DZ) face of the bounding box of the shape
853  Bool_t ok1 = GetShape()->TGeoBBox::GetPointsOnFacet(1, 50, points);
854  // We move the point slightly inside the volume to test if it actually corresponds
855  // to a point on the shape's facet
856  points[2] += dz / 100.;
857  // Correct for offset of centre of shape
858  for (int i = 0; i < 3; i++) points[i] += origin[i];
859  Bool_t ok2 = GetShape()->Contains(points);
860  if (!ok1) {
861  ::Error("KVPosition::GetRandomPoint",
862  "TGeoBBox::GetPointsOnFacet returns kFALSE for shape %s. Returning coordinates of centre.", GetShape()->ClassName());
863  return GetSurfaceCentre();
864  }
865  Int_t np = 0;
866  if (!ok2) {
867  // try to find a point that works
868  np++;
869  while (np < 50) {
870  Double_t* npoint = points + 3 * np;
871  npoint[2] += dz / 100.;
872  // Correct for offset of centre of shape
873  for (int i = 0; i < 3; i++) npoint[i] += origin[i];
874  ok2 = GetShape()->Contains(npoint);
875  if (ok2) break;
876  np++;
877  }
878  if (!ok2) {
879  ::Error("KVPosition::GetRandomPointOnSurface",
880  "Cannot generate points for shape %s. Returning coordinates of surface centre.", GetShape()->ClassName());
881  return GetSurfaceCentre();
882  }
883  }
884  Double_t* npoint = points + 3 * np;
885  npoint[2] -= dz / 100.;
886  GetMatrix()->LocalToMaster(npoint, master);
887  return TVector3(master);
888 }
889 
890 
891 
900 
902 {
903  // * ROOT Geometry *
904  // Generate a vector in the world (laboratory) frame from the origin
905  // to the centre of the entrance surface of the volume.
906  //
907  // It is assumed that the volume was defined in such a way
908  // that the entrance surface corresponds to the facet in the X-Y plane
909  // placed at -dZ.
910 
911  if (!ROOTGeo()) {
912  ::Error("KVPosition::GetSurfaceCentre",
913  "ROOT Geometry has not been initialised");
914  return TVector3();
915  }
916  Double_t master[3];
917  const Double_t* origin = GetShape()->GetOrigin();
918  Double_t points[] = {origin[0], origin[1], origin[2] - GetShape()->GetDZ()};
919  GetMatrix()->LocalToMaster(points, master);
920  return TVector3(master);
921 }
922 
923 
924 
929 
931 {
932  // * ROOT Geometry *
933  // Generate a vector in the world (laboratory) frame from the origin
934  // to the centre of the volume.
935 
936  if (!ROOTGeo()) {
937  ::Error("KVPosition::GetVolumeCentre",
938  "ROOT Geometry has not been initialised");
939  return TVector3();
940  }
941  Double_t master[3];
942  const Double_t* origin = GetShape()->GetOrigin();
943  Double_t points[] = {origin[0], origin[1], origin[2]};
944  GetMatrix()->LocalToMaster(points, master);
945  return TVector3(master);
946 }
947 
948 
949 
959 
961 {
962  // * ROOT Geometry *
963  // Generate a vector in the world (laboratory) frame representing
964  // the normal to the entrance surface of the volume (pointing away
965  // from the target, i.e. towards the inside of the volume)
966  //
967  // It is assumed that the volume was defined in such a way
968  // that the entrance surface corresponds to the facet in the X-Y plane
969  // placed at -dZ.
970 
971  if (!ROOTGeo()) {
972  ::Error("KVPosition::GetSurfaceNormal",
973  "ROOT Geometry has not been initialised");
974  return TVector3();
975  }
976  return GetSCVector().Unit();
977 }
978 
979 
980 
988 
990 {
991  // Monte Carlo calculation of entrance surface area for TGeoArb8 shapes
992  // Area is calculated as area of bounding box facet multiplied by the ratio between
993  // number of random points actually on the shape surface to the number of points
994  // npoints generated over the surface of the bounding box facet
995  //
996  // npoints is the number of points to test
997 
998  Double_t* points = new Double_t[3 * npoints];
999  const Double_t* origin = GetShape()->GetOrigin();
1000  Double_t dz = GetShape()->GetDZ();
1001  // This will generate npoints points on the (-DZ) face of the bounding box of the shape
1002  Bool_t ok1 = GetShape()->TGeoBBox::GetPointsOnFacet(1, npoints, points);
1003  if (!ok1) {
1004  ::Error("KVPosition::GetEntranceWindowArea",
1005  "TGeoBBox::GetPointsOnFacet returns kFALSE for shape %s. Returning 0.0", GetShape()->ClassName());
1006  delete [] points;
1007  return 0.0;
1008  }
1009  Double_t points_on_facet = 0;
1010  for (Int_t np = 0; np < npoints; ++np) {
1011  Double_t* npoint = points + 3 * np;
1012  // We move the point slightly inside the volume to test if it actually corresponds
1013  // to a point on the shape's facet
1014  npoint[2] += dz / 100.;
1015  // Correct for offset of centre of shape
1016  for (int i = 0; i < 3; i++) npoint[i] += origin[i];
1017  if (GetShape()->Contains(npoint)) ++points_on_facet;
1018  }
1019  delete [] points;
1020  return GetShape()->GetFacetArea(1) * (points_on_facet / Double_t(npoints));
1021 }
1022 
1023 
1024 
1028 
1030 {
1031  // Return angle (in deg.) between the vector from the target to the volume centre
1032  // and the normal to the volume surface
1034 }
1035 
1036 
int Int_t
ROOT::R::TRInterface & r
bool Bool_t
constexpr Bool_t kFALSE
double Double_t
constexpr Bool_t kTRUE
const char Option_t
#define N
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t b
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t points
R__EXTERN TRandom * gRandom
Base class used for handling geometry in a multidetector array.
Definition: KVPosition.h:91
virtual void GetRandomAngles(Double_t &th, Double_t &ph, Option_t *t="isotropic")
Definition: KVPosition.cpp:280
Bool_t IsInPhiRange(const Double_t phi)
Definition: KVPosition.cpp:360
virtual void SetAzimuthalWidth(Double_t aw)
Definition: KVPosition.cpp:189
virtual TVector3 GetRandomDirection(Option_t *t="isotropic")
Definition: KVPosition.cpp:242
Bool_t IsAzimuthallyWiderThan(KVPosition *pos)
Definition: KVPosition.cpp:470
virtual void SetShape(TGeoBBox *)
Definition: KVPosition.cpp:758
virtual void SetAzimuthalMinMax(Double_t min, Double_t max)
Set min and max azimuthal angles and calculate (mean) phi.
Definition: KVPosition.cpp:216
virtual void SetAzimuthalAngle(Double_t ph)
Definition: KVPosition.cpp:117
virtual Double_t GetSolidAngle(void) const
Definition: KVPosition.cpp:591
virtual Double_t GetTheta() const
Definition: KVPosition.h:169
void GetCornerCoordinates(TVector3 *, Double_t=0)
Definition: KVPosition.cpp:520
Double_t fTheta
polar angle in degrees with respect to beam axis, corresponds to centre of telescope
Definition: KVPosition.h:93
virtual TVector3 GetSurfaceCentre() const
Definition: KVPosition.cpp:901
virtual TGeoHMatrix * GetMatrix() const
Definition: KVPosition.cpp:792
void GetWidthsFromDimension(Double_t lin_dim)
Definition: KVPosition.cpp:654
void SetDistance(Double_t d)
Definition: KVPosition.h:195
TRotation GetRandomIsotropicRotation()
Definition: KVPosition.cpp:680
virtual void SetPolarAngle(Double_t th)
Definition: KVPosition.cpp:96
virtual Double_t GetPhi() const
Definition: KVPosition.h:181
Double_t GetPhiMax() const
Definition: KVPosition.h:149
virtual Double_t GetDistance(void) const
Definition: KVPosition.h:199
Double_t fSolidAngle
solid angle = area of entrance window / distance**2
Definition: KVPosition.h:104
TGeoHMatrix * fMatrix
transform world<->detector coordinates
Definition: KVPosition.h:102
Double_t GetPhiMin() const
Definition: KVPosition.h:143
Bool_t IsSmallerThan(KVPosition *pos)
kTRUE if "this" is entirely contained within "pos"
Definition: KVPosition.cpp:403
virtual TVector3 GetVolumeCentre() const
Definition: KVPosition.cpp:930
virtual Double_t GetSurfaceArea(int npoints=100000) const
Definition: KVPosition.cpp:989
TVector3 GetSCVector() const
Definition: KVPosition.h:106
Double_t GetThetaMin() const
Definition: KVPosition.h:155
virtual Double_t GetSinTheta() const
Definition: KVPosition.h:173
Double_t GetOC_SC_CosAngle() const
Definition: KVPosition.h:110
virtual TVector3 GetSurfaceNormal() const
Definition: KVPosition.cpp:960
virtual Double_t GetMisalignmentAngle() const
Double_t fTheta_min
polar angle in degrees corresponding to edge of telescope closest to beam axis
Definition: KVPosition.h:95
Double_t GetAzimuthalWidth(Double_t phmin=-1., Double_t phimax=-1.) const
Definition: KVPosition.cpp:627
Bool_t IsInPolarRange(const Double_t theta)
kTRUE if given angle theta is within the polar range of this solid angle element
Definition: KVPosition.cpp:386
virtual void SetPolarWidth(Double_t pw)
Definition: KVPosition.cpp:147
Bool_t IsAlignedWith(KVPosition *pos)
kTRUE if one of the two solid angle elements is completely contained within the other.
Definition: KVPosition.cpp:419
Double_t fTheta_max
polar angle in degrees of the edge furthest from the beam axis
Definition: KVPosition.h:96
void SetTheta(Double_t t)
Definition: KVPosition.h:187
void CalculateEstimatedAngularLimits(int N=10000)
Definition: KVPosition.cpp:336
Double_t fPhi
azimuthal angle in degrees with respect to 12 o'clock (=0 deg.), corresponds to centre of telescope
Definition: KVPosition.h:94
TGeoBBox * fShape
shape of detector volume
Definition: KVPosition.h:103
void SetPhi(Double_t p)
Definition: KVPosition.h:191
virtual void SetPolarMinMax(Double_t min, Double_t max)
Set min and max polar angles and calculate (mean) theta.
Definition: KVPosition.cpp:171
virtual void SetMatrix(const TGeoHMatrix *)
Definition: KVPosition.cpp:717
virtual TGeoBBox * GetShape() const
Definition: KVPosition.cpp:805
Double_t fPhi_max
azimuthal angle in degrees corresponding to most clockwise edge of telescope
Definition: KVPosition.h:98
Double_t fPhi_min
azimuthal angle in degrees corresponding to most anticlockwise edge of telescope
Definition: KVPosition.h:97
virtual ~KVPosition()
Definition: KVPosition.cpp:58
Bool_t IsOverlappingWith(KVPosition *pos)
kTRUE if there is at least partial overlap between two solid angle elements
Definition: KVPosition.cpp:432
virtual Bool_t ROOTGeo() const
Definition: KVPosition.h:210
Double_t fDistance
distance in cm from centre of solid angle element to coordinate system origin (target)
Definition: KVPosition.h:99
void GetCornerCoordinatesInOwnFrame(TVector3 *, Double_t=0)
Definition: KVPosition.cpp:568
void init()
default initialiser
Definition: KVPosition.cpp:43
Double_t GetThetaMax() const
Definition: KVPosition.h:161
virtual TVector3 GetDirection()
Definition: KVPosition.cpp:487
virtual TVector3 GetRandomPointOnSurface() const
Definition: KVPosition.cpp:828
virtual const Double_t * GetOrigin() const
virtual Double_t GetFacetArea(Int_t index=0) const
virtual Double_t GetDZ() const
Bool_t Contains(const Double_t *point) const override
virtual void LocalToMaster(const Double_t *local, Double_t *master) const
virtual Double_t Uniform(Double_t x1, Double_t x2)
TRotation & SetXEulerAngles(Double_t phi, Double_t theta, Double_t psi)
TRotation & SetYEulerAngles(Double_t phi, Double_t theta, Double_t psi)
void SetMagThetaPhi(Double_t mag, Double_t theta, Double_t phi)
void SetXYZ(Double_t x, Double_t y, Double_t z)
void SetPhi(Double_t)
Double_t Phi() const
TVector3 Unit() const
Double_t Theta() const
void SetTheta(Double_t)
RooCmdArg ClassName(const char *name)
T Mag(const SVector< T, D > &rhs)
RVec< PromoteType< T > > cos(const RVec< T > &v)
RVec< PromoteTypes< T0, T1 > > pow(const T0 &x, const RVec< T1 > &v)
RVec< PromoteType< T > > sin(const RVec< T > &v)
double dist(AxisAngle const &r1, AxisAngle const &r2)
void Error(const char *location, const char *fmt,...)
double min(double x, double y)
double max(double x, double y)
Double_t ACos(Double_t)
Double_t ATan(Double_t)
constexpr Double_t DegToRad()
Double_t Cos(Double_t)
constexpr Double_t Pi()
constexpr Double_t RadToDeg()
TMarker m
ClassImp(TPyArg)