KaliVeda  1.12/06
Heavy-Ion Analysis Toolkit
KVPosition.cpp
Go to the documentation of this file.
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  //kTRUE if given angle phi is within the azimuthal range of this solid
339  //angle element
340 
341  ROOT_GEO_DO_NOT_USE("IsInPhiRange", kFALSE)
342 
343  Double_t phimintest = fPhi_min;
344  Double_t phimaxtest = fPhi_max;
345  if (phimintest > phimaxtest) {
346  phimaxtest += 360.;
347  }
348  if (phi >= phimintest && phi <= phimaxtest) {
349  return kTRUE;
350  }
351  if ((phi + 360.) >= phimintest && (phi + 360.) <= phimaxtest) {
352  return kTRUE;
353  }
354  return kFALSE;
355 }
356 
357 
358 
361 
363 {
364  //kTRUE if given angle theta is within the polar range of this solid angle element
365 
366  ROOT_GEO_DO_NOT_USE("IsInPolarRange", kFALSE)
367 
368  if (theta >= fTheta_min && theta <= fTheta_max)
369  return kTRUE;
370  else
371  return kFALSE;
372 }
373 
374 
375 
378 
380 {
381  // kTRUE if "this" is entirely contained within "pos"
382 
383  ROOT_GEO_DO_NOT_USE("IsSmallerThan", kFALSE)
384  return (pos->IsInPolarRange(GetThetaMin())
385  && pos->IsInPolarRange(GetThetaMax())
386  && pos->IsInPhiRange(GetPhiMin())
387  && pos->IsInPhiRange(GetPhiMax()));
388 }
389 
390 
391 
394 
396 {
397  //kTRUE if one of the two solid angle elements is completely contained within the other.
398 
399  ROOT_GEO_DO_NOT_USE("IsAlignedWith", kFALSE)
400  return (IsSmallerThan(pos) || pos->IsSmallerThan(this));
401 }
402 
403 
404 
407 
409 {
410  //kTRUE if there is at least partial overlap between two solid angle elements
411 
412  ROOT_GEO_DO_NOT_USE("IsOverlappingWith", kFALSE)
413  return (
414  //overlapping corners - case 1
415  (IsInPolarRange(other->GetThetaMin())
416  || IsInPolarRange(other->GetThetaMax()))
417  && (IsInPhiRange(other->GetPhiMin())
418  || IsInPhiRange(other->GetPhiMax()))
419  ) || (
420  //overlapping corners - case 2
421  (other->IsInPolarRange(GetThetaMin())
422  || other->IsInPolarRange(GetThetaMax()))
423  && (other->IsInPhiRange(GetPhiMin())
424  || other->IsInPhiRange(GetPhiMax()))
425  ) || (
426  //case where this is phi-contained by the other, but the other is theta-contained by this
427  (other->IsInPolarRange(GetThetaMin())
428  || other->IsInPolarRange(GetThetaMax()))
429  && (IsInPhiRange(other->GetPhiMin())
430  || IsInPhiRange(other->GetPhiMax()))
431  ) || (
432  //case where this is phi-contained by the other, but the other is theta-contained by this
433  (IsInPolarRange(other->GetThetaMin())
434  || IsInPolarRange(other->GetThetaMax()))
435  && (other->IsInPhiRange(GetPhiMin())
436  || other->IsInPhiRange(GetPhiMax()))
437  );
438 }
439 
440 
441 
445 
447 {
448  //kTRUE if "this" has larger azimuthal width than "pos".
449  //Takes care of cases where the solid angle straddles 0 degrees
450 
451  ROOT_GEO_DO_NOT_USE("IsAzimuthallyWiderThan", kFALSE)
452  if (GetAzimuthalWidth() > pos->GetAzimuthalWidth())
453  return kTRUE;
454  return kFALSE;
455 }
456 
457 
458 
462 
464 {
465  //Returns a unit vector corresponding to the direction of fTheta, fPhi
466  //i.e. the centre of the solid angle element.
467 
468  TVector3 tmp(1.0, 0.0, 0.0);
469  tmp.SetTheta(fTheta * TMath::Pi() / 180.);
470  tmp.SetPhi(fPhi * TMath::Pi() / 180.);
471  return tmp;
472 }
473 
474 
475 
476 
495 
497 {
498  // Fill the array (TVector3 corner[4]) with the coordinates of the 4 'corners' of the solid angle element.
499  //
500  // These 'corners' are the points of intersection between the plane defined by the normal
501  // to the centre of the solid angle (direction: theta,phi), at a distance fDistance [cm] from the
502  // origin, and the four lines starting at the origin with directions (thetamin,phimin),
503  // (thetamax,phimin), (thetamax,phimax), (thetamin,phimax).
504  //
505  // If optional argument 'depth' [cm] is given, the coordinates are calculated for the plane
506  // situated at distance (fDistance+depth) from the origin.
507  //
508  // The order of the 4 corners is as follows:
509  // corners[3] : theta-min, phi-min
510  // corners[2] : theta-max, phi-min
511  // corners[1] : theta-max, phi-max
512  // corners[0] : theta-min, phi-max
513  //
514  // Coordinates are in CENTIMETRES
515 
516  ROOT_GEO_DO_NOT_USE("GetCornerCoordinates",)
517 
518  // calculate unit vector normal to solid angle
519  Double_t pthR = GetTheta() * TMath::DegToRad();
520  Double_t pphR = GetPhi() * TMath::DegToRad();
521  TVector3 normal_to_plane(sin(pthR)*cos(pphR), sin(pthR)*sin(pphR), cos(pthR));
522 
523  // the four directions/lines
528 
529  // calculate intersection points
530  for (int i = 0; i < 4; i++) {
531  Double_t t = corners[i] * normal_to_plane;
532  if (t <= 0.0) corners[i].SetXYZ(0, 0, 0);
533  else corners[i] *= (fDistance + depth) / t;
534  }
535 }
536 
537 
538 
539 
543 
545 {
546  // Like GetCornerCoordinates(), except that the coordinates correspond to a reference frame
547  // in which the +ve z-axis goes through the centre of the solid angle
548 
549  ROOT_GEO_DO_NOT_USE("GetCornerCoordinatesInOwnFrame",)
550  GetCornerCoordinates(corners, depth);
551  TRotation rot_to_frame;
552  rot_to_frame.SetYEulerAngles(-GetPhi()*TMath::DegToRad(), -GetTheta()*TMath::DegToRad(), 0.);
553  TVector3 displZ(0, 0, fDistance + depth);
554  for (int i = 0; i < 4; i++) {
555  corners[i] = rot_to_frame * corners[i] - displZ;
556  }
557 }
558 
559 
560 
566 
568 {
569  // Return values of the solid angle (in msr) seen by the geometric ensemble
570  // For simple geometries defined by theta_min/max etc., this is exact.
571  // For ROOT geometries we calculate the area of the entrance window and divide
572  // it by the square of the distance to the detector.
573 
574  if (ROOTGeo()) {
575  if (!fSolidAngle) {
576  // TGeoArb8 shapes' solid angles calculated on demand as this requires
577  // a monte carlo calculation
578  // this takes into account any eventual "misalignment" i.e. if the vector from the
579  // origin to the centre of the volume is not perpendicular to the entrance surface,
580  // which reduces the effective area "seen" from the target
582  fSolidAngle = area / pow(GetDistance(), 2.) * 1.e3;
583  }
584  return fSolidAngle;
585  }
586 
587  return (-1.*cos(GetThetaMax() * TMath::DegToRad()) +
589  * (GetAzimuthalWidth() * TMath::DegToRad()) * 1.e3;
590 
591 }
592 
593 
594 
597 
599 {
600  // Returns kTRUE if ROOT geometry is used, kFALSE if not
601  return (fMatrix && fShape);
602 }
603 
604 
605 
611 
613 {
614  //Calculate azimuthal width taking phi-min as the most anticlockwise point of the
615  //element and phi-max the most clockwise.
616  //If no arguments are given, width calculated for this object
617  //Otherwise, width calculated for given phi-min and phi-max
618 
619  ROOT_GEO_DO_NOT_USE("GetAzimuthalWidth", 0.)
620 
621  if (phmin == -1.)
622  phmin = GetPhiMin();
623  if (phmax == -1.)
624  phmax = GetPhiMax();
625  if (phmin < phmax)
626  return (phmax - phmin);
627  else
628  return (phmax - phmin + 360.);
629 }
630 
631 
632 
633 
638 
640 {
641  //Calculate azimuthal and polar widths for a square element placed at a
642  //given distance from the origin with linear dimension 'lin_dim' (in mm).
643  //SetDistance, SetTheta and SetPhi must already have been called.
644 
645  if (GetDistance() <= 0.0) {
646  Error("GetWidthsFromDimension", "Distance not set");
647  return;
648  }
649  Double_t d__th =
650  2. * TMath::RadToDeg() * TMath::ATan(lin_dim /
651  (2. * GetDistance()));
652  Double_t d__ph =
653  TMath::RadToDeg() * lin_dim / (GetDistance() * GetSinTheta());
654  SetPolarWidth(d__th);
655  SetAzimuthalWidth(d__ph);
656 }
657 
658 
659 
664 
666 {
667  // Generates a rotation which, if applied to a unit vector in the Z-direction,
668  // will transform it into an isotropically-distributed vector in this
669  // angular range.
670 
671  TRotation rr2;
672  ROOT_GEO_DO_NOT_USE("GetRandomIsotropicRotation", rr2)
673  Double_t a1min, a1max, a2min, a2max, a3min, a3max;
674  a1min = 0;
675  a1max = 2 * TMath::Pi();
676  a2min = GetThetaMin() * TMath::DegToRad();
677  a2max = GetThetaMax() * TMath::DegToRad();
678  a3min = GetPhiMin() * TMath::DegToRad();
679  a3max = GetPhiMax() * TMath::DegToRad();
680  a3min += TMath::Pi() / 2.;
681  a3max += TMath::Pi() / 2.;
682  rr2.SetXEulerAngles(gRandom->Uniform(a1min, a1max),
683  TMath::ACos(gRandom->Uniform(cos(a2max), cos(a2min))),
684  gRandom->Uniform(a3min, a3max));
685  return rr2;
686 }
687 
688 
690 
691 
701 
703 {
704  // * ROOT Geometry *
705  // Set the global transformation matrix for this volume
706  // If shape has been set, we set the (theta,phi) angles
707  // corresponding to the centre of the volume, and
708  // the distance from the target corresponding to the distance
709  // along (theta,phi) to the entrance surface of the volume
710  // (not necessarily the same as the distance from the target to
711  // the centre of the entrance surface)
712 
713  if (fMatrix) delete fMatrix;
714  fMatrix = new TGeoHMatrix(*m);
715  if (ROOTGeo()) {
716  TVector3 centre = GetVolumeCentre();
717  SetTheta(centre.Theta()*TMath::RadToDeg());
718  SetPhi(centre.Phi()*TMath::RadToDeg());
720  // solid angle calculated and set here only for non-TGeoArb8 shapes
721  // this takes into account any eventual "misalignment" i.e. if the vector from the
722  // origin to the centre of the volume is not perpendicular to the entrance surface,
723  // which reduces the effective area "seen" from the target
724  if (!GetShape()->InheritsFrom("TGeoArb8")) {
726  fSolidAngle = area / pow(GetDistance(), 2.) * 1.e3;
727  }
728  }
729 }
730 
731 
732 
742 
744 {
745  // * ROOT Geometry *
746  // Set the shape of this detector
747  // If matrix has been set, we set the (theta,phi) angles
748  // corresponding to the centre of the volume, and
749  // the distance from the target corresponding to the distance
750  // along (theta,phi) to the entrance surface of the volume
751  // (not necessarily the same as the distance from the target to
752  // the centre of the entrance surface)
753 
754  fShape = b;
755  if (ROOTGeo()) {
756  TVector3 centre = GetVolumeCentre();
757  SetTheta(centre.Theta()*TMath::RadToDeg());
758  SetPhi(centre.Phi()*TMath::RadToDeg());
760  // solid angle calculated and set here only for non-TGeoArb8 shapes
761  // this takes into account any eventual "misalignment" i.e. if the vector from the
762  // origin to the centre of the volume is not perpendicular to the entrance surface,
763  // which reduces the effective area "seen" from the target
764  if (!GetShape()->InheritsFrom("TGeoArb8")) {
766  fSolidAngle = area / pow(GetDistance(), 2.) * 1.e3;
767  }
768  }
769 }
770 
771 
772 
776 
778 {
779  // * ROOT Geometry *
780  // Return global transformation matrix for this detector
781  return fMatrix;
782 }
783 
784 
785 
789 
791 {
792  // * ROOT Geometry *
793  // Return shape of this detector
794  return fShape;
795 }
796 
797 
798 
812 
814 {
815  // * ROOT Geometry *
816  // Generate a vector in the world (laboratory) frame from the origin
817  // to a random point on the entrance surface of this volume.
818  //
819  // It is assumed that the volume was defined in such a way
820  // that the entrance window corresponds to the facet in the X-Y plane
821  // placed at -dZ.
822  //
823  // NOTE: we force the use of TGeoBBox::GetPointsOnFacet.
824  // For TGeoArb8, the method has been overridden and does nothing.
825  // We use the TGeoBBox method, and then use TGeoShape::Contains
826  // to check that the point does actually correspond to the TGeoArb8.
827 
828  if (!ROOTGeo()) {
829  ::Error("KVPosition::GetRandomPointOnSurface",
830  "ROOT Geometry has not been initialised");
831  return TVector3();
832  }
833  Double_t master[3 * 50];
834  Double_t points[3 * 50];
835  const Double_t* origin = GetShape()->GetOrigin();
836  Double_t dz = GetShape()->GetDZ();
837  // This will generate a point on the (-DZ) face of the bounding box of the shape
838  Bool_t ok1 = GetShape()->TGeoBBox::GetPointsOnFacet(1, 50, points);
839  // We move the point slightly inside the volume to test if it actually corresponds
840  // to a point on the shape's facet
841  points[2] += dz / 100.;
842  // Correct for offset of centre of shape
843  for (int i = 0; i < 3; i++) points[i] += origin[i];
844  Bool_t ok2 = GetShape()->Contains(points);
845  if (!ok1) {
846  ::Error("KVPosition::GetRandomPoint",
847  "TGeoBBox::GetPointsOnFacet returns kFALSE for shape %s. Returning coordinates of centre.", GetShape()->ClassName());
848  return GetSurfaceCentre();
849  }
850  Int_t np = 0;
851  if (!ok2) {
852  // try to find a point that works
853  np++;
854  while (np < 50) {
855  Double_t* npoint = points + 3 * np;
856  npoint[2] += dz / 100.;
857  // Correct for offset of centre of shape
858  for (int i = 0; i < 3; i++) npoint[i] += origin[i];
859  ok2 = GetShape()->Contains(npoint);
860  if (ok2) break;
861  np++;
862  }
863  if (!ok2) {
864  ::Error("KVPosition::GetRandomPointOnSurface",
865  "Cannot generate points for shape %s. Returning coordinates of surface centre.", GetShape()->ClassName());
866  return GetSurfaceCentre();
867  }
868  }
869  Double_t* npoint = points + 3 * np;
870  npoint[2] -= dz / 100.;
871  GetMatrix()->LocalToMaster(npoint, master);
872  return TVector3(master);
873 }
874 
875 
876 
885 
887 {
888  // * ROOT Geometry *
889  // Generate a vector in the world (laboratory) frame from the origin
890  // to the centre of the entrance surface of the volume.
891  //
892  // It is assumed that the volume was defined in such a way
893  // that the entrance surface corresponds to the facet in the X-Y plane
894  // placed at -dZ.
895 
896  if (!ROOTGeo()) {
897  ::Error("KVPosition::GetSurfaceCentre",
898  "ROOT Geometry has not been initialised");
899  return TVector3();
900  }
901  Double_t master[3];
902  const Double_t* origin = GetShape()->GetOrigin();
903  Double_t points[] = {origin[0], origin[1], origin[2] - GetShape()->GetDZ()};
904  GetMatrix()->LocalToMaster(points, master);
905  return TVector3(master);
906 }
907 
908 
909 
914 
916 {
917  // * ROOT Geometry *
918  // Generate a vector in the world (laboratory) frame from the origin
919  // to the centre of the volume.
920 
921  if (!ROOTGeo()) {
922  ::Error("KVPosition::GetVolumeCentre",
923  "ROOT Geometry has not been initialised");
924  return TVector3();
925  }
926  Double_t master[3];
927  const Double_t* origin = GetShape()->GetOrigin();
928  Double_t points[] = {origin[0], origin[1], origin[2]};
929  GetMatrix()->LocalToMaster(points, master);
930  return TVector3(master);
931 }
932 
933 
934 
944 
946 {
947  // * ROOT Geometry *
948  // Generate a vector in the world (laboratory) frame representing
949  // the normal to the entrance surface of the volume (pointing away
950  // from the target, i.e. towards the inside of the volume)
951  //
952  // It is assumed that the volume was defined in such a way
953  // that the entrance surface corresponds to the facet in the X-Y plane
954  // placed at -dZ.
955 
956  if (!ROOTGeo()) {
957  ::Error("KVPosition::GetSurfaceNormal",
958  "ROOT Geometry has not been initialised");
959  return TVector3();
960  }
961  return GetSCVector().Unit();
962 }
963 
964 
965 
973 
975 {
976  // Monte Carlo calculation of entrance surface area for TGeoArb8 shapes
977  // Area is calculated as area of bounding box facet multiplied by the ratio between
978  // number of random points actually on the shape surface to the number of points
979  // npoints generated over the surface of the bounding box facet
980  //
981  // npoints is the number of points to test
982 
983  Double_t* points = new Double_t[3 * npoints];
984  const Double_t* origin = GetShape()->GetOrigin();
985  Double_t dz = GetShape()->GetDZ();
986  // This will generate npoints points on the (-DZ) face of the bounding box of the shape
987  Bool_t ok1 = GetShape()->TGeoBBox::GetPointsOnFacet(1, npoints, points);
988  if (!ok1) {
989  ::Error("KVPosition::GetEntranceWindowArea",
990  "TGeoBBox::GetPointsOnFacet returns kFALSE for shape %s. Returning 0.0", GetShape()->ClassName());
991  delete [] points;
992  return 0.0;
993  }
994  Double_t points_on_facet = 0;
995  for (Int_t np = 0; np < npoints; ++np) {
996  Double_t* npoint = points + 3 * np;
997  // We move the point slightly inside the volume to test if it actually corresponds
998  // to a point on the shape's facet
999  npoint[2] += dz / 100.;
1000  // Correct for offset of centre of shape
1001  for (int i = 0; i < 3; i++) npoint[i] += origin[i];
1002  if (GetShape()->Contains(npoint)) ++points_on_facet;
1003  }
1004  delete [] points;
1005  return GetShape()->GetFacetArea(1) * (points_on_facet / Double_t(npoints));
1006 }
1007 
1008 
1009 
1013 
1015 {
1016  // Return angle (in deg.) between the vector from the target to the volume centre
1017  // and the normal to the volume surface
1019 }
1020 
1021 
int Int_t
ClassImp(KVPartitionList) void KVPartitionList
Initialisation.
#define ROOT_GEO_DO_NOT_USE(method, retval)
Definition: KVPosition.cpp:29
ROOT::R::TRInterface & r
#define b(i)
const Bool_t kFALSE
bool Bool_t
double Double_t
const Bool_t kTRUE
const char Option_t
double cos(double)
double pow(double, double)
double sin(double)
R__EXTERN TRandom * gRandom
point * points
Base class used for handling geometry in a multidetector array.
Definition: KVPosition.h:90
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:336
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:446
virtual void SetShape(TGeoBBox *)
Definition: KVPosition.cpp:743
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:567
virtual Double_t GetTheta() const
Definition: KVPosition.h:159
Bool_t ROOTGeo() const
Returns kTRUE if ROOT geometry is used, kFALSE if not.
Definition: KVPosition.cpp:598
void GetCornerCoordinates(TVector3 *, Double_t=0)
Definition: KVPosition.cpp:496
Double_t fTheta
polar angle in degrees with respect to beam axis, corresponds to centre of telescope
Definition: KVPosition.h:92
virtual TVector3 GetSurfaceCentre() const
Definition: KVPosition.cpp:886
virtual TGeoHMatrix * GetMatrix() const
Definition: KVPosition.cpp:777
void GetWidthsFromDimension(Double_t lin_dim)
Definition: KVPosition.cpp:639
void SetDistance(Double_t d)
Definition: KVPosition.h:185
TRotation GetRandomIsotropicRotation()
Definition: KVPosition.cpp:665
virtual void SetPolarAngle(Double_t th)
Definition: KVPosition.cpp:96
virtual Double_t GetPhi() const
Definition: KVPosition.h:171
Double_t GetPhiMax() const
Definition: KVPosition.h:145
virtual Double_t GetDistance(void) const
Definition: KVPosition.h:189
Double_t fSolidAngle
solid angle = area of entrance window / distance**2
Definition: KVPosition.h:103
TGeoHMatrix * fMatrix
transform world<->detector coordinates
Definition: KVPosition.h:101
Double_t GetPhiMin() const
Definition: KVPosition.h:141
Bool_t IsSmallerThan(KVPosition *pos)
kTRUE if "this" is entirely contained within "pos"
Definition: KVPosition.cpp:379
virtual TVector3 GetVolumeCentre() const
Definition: KVPosition.cpp:915
virtual Double_t GetSurfaceArea(int npoints=100000) const
Definition: KVPosition.cpp:974
TVector3 GetSCVector() const
Definition: KVPosition.h:105
Double_t GetThetaMin() const
Definition: KVPosition.h:149
virtual Double_t GetSinTheta() const
Definition: KVPosition.h:163
Double_t GetOC_SC_CosAngle() const
Definition: KVPosition.h:109
virtual TVector3 GetSurfaceNormal() const
Definition: KVPosition.cpp:945
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:94
Double_t GetAzimuthalWidth(Double_t phmin=-1., Double_t phimax=-1.) const
Definition: KVPosition.cpp:612
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:362
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:395
Double_t fTheta_max
polar angle in degrees of the edge furthest from the beam axis
Definition: KVPosition.h:95
void SetTheta(Double_t t)
Definition: KVPosition.h:177
Double_t fPhi
azimuthal angle in degrees with respect to 12 o'clock (=0 deg.), corresponds to centre of telescope
Definition: KVPosition.h:93
TGeoBBox * fShape
shape of detector volume
Definition: KVPosition.h:102
void SetPhi(Double_t p)
Definition: KVPosition.h:181
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:702
virtual TGeoBBox * GetShape() const
Definition: KVPosition.cpp:790
Double_t fPhi_max
azimuthal angle in degrees corresponding to most clockwise edge of telescope
Definition: KVPosition.h:97
Double_t fPhi_min
azimuthal angle in degrees corresponding to most anticlockwise edge of telescope
Definition: KVPosition.h:96
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:408
Double_t fDistance
distance in cm from centre of solid angle element to coordinate system origin (target)
Definition: KVPosition.h:98
void GetCornerCoordinatesInOwnFrame(TVector3 *, Double_t=0)
Definition: KVPosition.cpp:544
void init()
default initialiser
Definition: KVPosition.cpp:43
Double_t GetThetaMax() const
Definition: KVPosition.h:153
virtual TVector3 GetDirection()
Definition: KVPosition.cpp:463
virtual TVector3 GetRandomPointOnSurface() const
Definition: KVPosition.cpp:813
virtual Double_t GetFacetArea(Int_t index=0) const
virtual const Double_t * GetOrigin() const
virtual Double_t GetDZ() const
virtual Bool_t Contains(const Double_t *point) const
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)
const long double m
Definition: KVUnits.h:70
double dist(AxisAngle const &r1, AxisAngle const &r2)
void Error(const char *location, const char *va_(fmt),...)
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()