ROBAST logo
////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// AGeoUtil                                                                   //
//                                                                            //
// Utility functions to build complex geometries easily                       //
////////////////////////////////////////////////////////////////////////////////

#include "TGeoTube.h"
#include "TMath.h"

#include "AGeoUtil.h"
#if !defined(R__ALPHA) && !defined(R__SOLARIS) && !defined(R__ACC) && \
    !defined(R__FBSD)
NamespaceImp(AGeoUtil)
#endif

    static Double_t SumInRadius(TH2* h2, double x, double y, double r) {
  Double_t r2 = r * r;
  TAxis* xax = h2->GetXaxis();
  TAxis* yax = h2->GetYaxis();
  Int_t nbinsx = xax->GetNbins();
  Int_t nbinsy = yax->GetNbins();

  Double_t total = 0.;

  for (Int_t ix = 1; ix <= nbinsx; ++ix) {
    Double_t cx = xax->GetBinCenter(ix);
    for (Int_t iy = 1; iy <= nbinsy; ++iy) {
      Double_t cy = yax->GetBinCenter(iy);
      Double_t c = h2->GetBinContent(ix, iy);
      if (c <= 0) {
        continue;
      }
      Double_t d2 = (cx - x) * (cx - x) + (cy - y) * (cy - y);
      if (d2 <= r2) {
        total += c;
      }
    }
  }
  return total;
}

namespace AGeoUtil {

//______________________________________________________________________________
void MakePointToPointBBox(const char* name, const TVector3& v1,
                          const TVector3& v2, Double_t dx, Double_t dy,
                          TGeoBBox** box, TGeoCombiTrans** combi) {
  TVector3 v3 = v1 + v2;
  v3 *= 0.5;  // center of the gravity
  TVector3 v4 = v3 - v1;

  Double_t theta = v4.Theta() * TMath::RadToDeg();
  Double_t phi = v4.Phi() * TMath::RadToDeg();

  *box = new TGeoBBox(Form("%sbox", name), dx, dy, v4.Mag());
  *combi = new TGeoCombiTrans(TGeoTranslation(v3.X(), v3.Y(), v3.Z()),
                              TGeoRotation("", phi + 90, theta, 0));
  (*combi)->SetName(Form("%scombi", name));
  (*combi)->RegisterYourself();
}

//______________________________________________________________________________
void MakePointToPointTube(const char* name, const TVector3& v1,
                          const TVector3& v2, Double_t radius, TGeoTube** tube,
                          TGeoCombiTrans** combi) {
  // Create a TGeoTube whose both ends are rotated to locate at v1 or v2 by
  // using combi
  /*
  Begin_Macro(gui, source)
  {
    Double_t m = AOpticsManager::m();
    AOpticsManager manager("manager", "manager");
    TGeoBBox* worldbox = new TGeoBBox("worldbox", 10*m, 10*m, 10*m);
    AOpticalComponent* world = new AOpticalComponent("world", worldbox);
    manager.SetTopVolume(world);

    TGeoTube* tube;
    TGeoCombiTrans* combi;
    TVector3 v1(-1*m, -2*m, 3*m);
    TVector3 v2(4*m, 5*m, -1*m);
    AGeoUtil::MakePointToPointTube("tube", v1, v2, 0.5*m, &tube, &combi);
    ALens* lens = new ALens("lens", tube);
    world->AddNode(lens, 1, combi);
    manager.CloseGeometry();

    world->Draw("ogl");
    TGLViewer* gl = (TGLViewer*)gPad->GetViewer3D();

    return gl;
  }
  End_Macro
  */
  TVector3 v3 = v1 + v2;
  v3 *= 0.5;  // center of the gravity
  TVector3 v4 = v3 - v1;

  Double_t theta = v4.Theta() * TMath::RadToDeg();
  Double_t phi = v4.Phi() * TMath::RadToDeg();

  *tube = new TGeoTube(Form("%stube", name), 0., radius, v4.Mag());
  *combi = new TGeoCombiTrans(TGeoTranslation(v3.X(), v3.Y(), v3.Z()),
                              TGeoRotation("", phi + 90, theta, 0));
  (*combi)->SetName(Form("%scombi", name));
  (*combi)->RegisterYourself();
}

//______________________________________________________________________________
void ContainmentRadius(TH2* h2, Double_t fraction, Double_t& r, Double_t& x,
                       Double_t& y) {
  // compute the radius of containment from a 2D histogram.
  Int_t no_shift = 0;
  Int_t no_stable = 0;

  x = h2->GetMean(1);  // Initial x
  y = h2->GetMean(2);  // Initial y
  r = TMath::Sqrt(h2->GetStdDev(1) * h2->GetStdDev(1) +
                  h2->GetStdDev(2) * h2->GetStdDev(2)) *
      1.5;
  Double_t dr = 0.1 * r;
  Double_t sum_goal = h2->Integral() * fraction;

  for (Int_t i = 0; i < 100 && no_shift < 30; i++) {
    Bool_t stable_r = false, stable_x = true, stable_y = true;
    Double_t sum0 = SumInRadius(h2, x, y, r);
    Double_t next_r = r;
    if (sum0 < sum_goal) {
      Double_t sum1 = SumInRadius(h2, x, y, r + dr);
      if (sum1 == sum0) {
        dr *= 2.;
        continue;
      }
      next_r = r + dr * (sum_goal - sum0) / (sum1 - sum0);
    } else if (sum0 != sum_goal) {
      Double_t sum1 = SumInRadius(h2, x, y, r - dr);
      if (sum1 == sum0) {
        dr *= 2.;
        continue;
      }
      next_r = r - dr * (sum0 - sum_goal) / (sum0 - sum1);
    }
    if (next_r < 0.) next_r = 0.5 * r;
    if (next_r < 0.5 * r) next_r = 0.5 * r;
    if (next_r > 2. * r) next_r = 2. * r;

    stable_r = fabs(next_r - r) < 0.0001 * r;

    r = next_r;

    {
      Double_t sum1 = SumInRadius(h2, x, y, r);

      dr *=
          sum0 != sum_goal ? fabs((sum1 - sum_goal) / (sum0 - sum_goal)) : 0.5;

      if (dr > 0.5 * r) {
        dr = 0.5 * r;
      }
      if (dr < 0.0005 * r) {
        dr = 0.0005 * r;
      }

      no_shift++;

      for (Double_t dx = 0.25 * r; dx > 0.1 * dr; dx *= 0.25) {
        Double_t sum_x1 = SumInRadius(h2, x + dx, y, r);
        Double_t sum_x2 = SumInRadius(h2, x - dx, y, r);
        while (sum_x1 > sum1) {
          no_shift = 0;
          x += dx;
          sum_x2 = sum1;
          sum1 = sum_x1;
          sum_x1 = SumInRadius(h2, x + dx, y, r);
          stable_x = false;
        }
        while (sum_x2 > sum1) {
          no_shift = 0;
          x -= dx;
          sum_x1 = sum1;
          sum1 = sum_x2;
          sum_x2 = SumInRadius(h2, x - dx, y, r);
          stable_x = false;
        }
      }
    }

    for (Double_t dy = 0.1 * r; dy > 0.1 * dr; dy *= 0.25) {
      Double_t sum1 = SumInRadius(h2, x, y, r);
      Double_t sum_y1 = SumInRadius(h2, x, y + dy, r);
      Double_t sum_y2 = SumInRadius(h2, x, y - dy, r);
      while (sum_y1 > sum1) {
        no_shift = 0;
        y += dy;
        sum_y2 = sum1;
        sum1 = sum_y1;
        sum_y1 = SumInRadius(h2, x, y + dy, r);
        stable_y = false;
      }
      while (sum_y2 > sum1) {
        no_shift = 0;
        y -= dy;
        sum_y1 = sum1;
        sum1 = sum_y2;
        sum_y2 = SumInRadius(h2, x, y - dy, r);
        stable_y = false;
      }
    }

    if (stable_r && stable_x && stable_y) {
      no_stable++;
    } else {
      no_stable = 0;
    }
    // Enough rounds without any change in radius and position?
    if (no_stable >= 4) {
      break;
    }
  }
}

}  // namespace AGeoUtil
 AGeoUtil.cxx:1
 AGeoUtil.cxx:2
 AGeoUtil.cxx:3
 AGeoUtil.cxx:4
 AGeoUtil.cxx:5
 AGeoUtil.cxx:6
 AGeoUtil.cxx:7
 AGeoUtil.cxx:8
 AGeoUtil.cxx:9
 AGeoUtil.cxx:10
 AGeoUtil.cxx:11
 AGeoUtil.cxx:12
 AGeoUtil.cxx:13
 AGeoUtil.cxx:14
 AGeoUtil.cxx:15
 AGeoUtil.cxx:16
 AGeoUtil.cxx:17
 AGeoUtil.cxx:18
 AGeoUtil.cxx:19
 AGeoUtil.cxx:20
 AGeoUtil.cxx:21
 AGeoUtil.cxx:22
 AGeoUtil.cxx:23
 AGeoUtil.cxx:24
 AGeoUtil.cxx:25
 AGeoUtil.cxx:26
 AGeoUtil.cxx:27
 AGeoUtil.cxx:28
 AGeoUtil.cxx:29
 AGeoUtil.cxx:30
 AGeoUtil.cxx:31
 AGeoUtil.cxx:32
 AGeoUtil.cxx:33
 AGeoUtil.cxx:34
 AGeoUtil.cxx:35
 AGeoUtil.cxx:36
 AGeoUtil.cxx:37
 AGeoUtil.cxx:38
 AGeoUtil.cxx:39
 AGeoUtil.cxx:40
 AGeoUtil.cxx:41
 AGeoUtil.cxx:42
 AGeoUtil.cxx:43
 AGeoUtil.cxx:44
 AGeoUtil.cxx:45
 AGeoUtil.cxx:46
 AGeoUtil.cxx:47
 AGeoUtil.cxx:48
 AGeoUtil.cxx:49
 AGeoUtil.cxx:50
 AGeoUtil.cxx:51
 AGeoUtil.cxx:52
 AGeoUtil.cxx:53
 AGeoUtil.cxx:54
 AGeoUtil.cxx:55
 AGeoUtil.cxx:56
 AGeoUtil.cxx:57
 AGeoUtil.cxx:58
 AGeoUtil.cxx:59
 AGeoUtil.cxx:60
 AGeoUtil.cxx:61
 AGeoUtil.cxx:62
 AGeoUtil.cxx:63
 AGeoUtil.cxx:64
 AGeoUtil.cxx:65
 AGeoUtil.cxx:66
 AGeoUtil.cxx:67
 AGeoUtil.cxx:68
 AGeoUtil.cxx:69
 AGeoUtil.cxx:70
 AGeoUtil.cxx:71
 AGeoUtil.cxx:72
 AGeoUtil.cxx:73
 AGeoUtil.cxx:74
 AGeoUtil.cxx:75
 AGeoUtil.cxx:76
 AGeoUtil.cxx:77
 AGeoUtil.cxx:78
 AGeoUtil.cxx:79
 AGeoUtil.cxx:80
 AGeoUtil.cxx:81
 AGeoUtil.cxx:82
 AGeoUtil.cxx:83
 AGeoUtil.cxx:84
 AGeoUtil.cxx:85
 AGeoUtil.cxx:86
 AGeoUtil.cxx:87
 AGeoUtil.cxx:88
 AGeoUtil.cxx:89
 AGeoUtil.cxx:90
 AGeoUtil.cxx:91
 AGeoUtil.cxx:92
 AGeoUtil.cxx:93
 AGeoUtil.cxx:94
 AGeoUtil.cxx:95
 AGeoUtil.cxx:96
 AGeoUtil.cxx:97
 AGeoUtil.cxx:98
 AGeoUtil.cxx:99
 AGeoUtil.cxx:100
 AGeoUtil.cxx:101
 AGeoUtil.cxx:102
 AGeoUtil.cxx:103
 AGeoUtil.cxx:104
 AGeoUtil.cxx:105
 AGeoUtil.cxx:106
 AGeoUtil.cxx:107
 AGeoUtil.cxx:108
 AGeoUtil.cxx:109
 AGeoUtil.cxx:110
 AGeoUtil.cxx:111
 AGeoUtil.cxx:112
 AGeoUtil.cxx:113
 AGeoUtil.cxx:114
 AGeoUtil.cxx:115
 AGeoUtil.cxx:116
 AGeoUtil.cxx:117
 AGeoUtil.cxx:118
 AGeoUtil.cxx:119
 AGeoUtil.cxx:120
 AGeoUtil.cxx:121
 AGeoUtil.cxx:122
 AGeoUtil.cxx:123
 AGeoUtil.cxx:124
 AGeoUtil.cxx:125
 AGeoUtil.cxx:126
 AGeoUtil.cxx:127
 AGeoUtil.cxx:128
 AGeoUtil.cxx:129
 AGeoUtil.cxx:130
 AGeoUtil.cxx:131
 AGeoUtil.cxx:132
 AGeoUtil.cxx:133
 AGeoUtil.cxx:134
 AGeoUtil.cxx:135
 AGeoUtil.cxx:136
 AGeoUtil.cxx:137
 AGeoUtil.cxx:138
 AGeoUtil.cxx:139
 AGeoUtil.cxx:140
 AGeoUtil.cxx:141
 AGeoUtil.cxx:142
 AGeoUtil.cxx:143
 AGeoUtil.cxx:144
 AGeoUtil.cxx:145
 AGeoUtil.cxx:146
 AGeoUtil.cxx:147
 AGeoUtil.cxx:148
 AGeoUtil.cxx:149
 AGeoUtil.cxx:150
 AGeoUtil.cxx:151
 AGeoUtil.cxx:152
 AGeoUtil.cxx:153
 AGeoUtil.cxx:154
 AGeoUtil.cxx:155
 AGeoUtil.cxx:156
 AGeoUtil.cxx:157
 AGeoUtil.cxx:158
 AGeoUtil.cxx:159
 AGeoUtil.cxx:160
 AGeoUtil.cxx:161
 AGeoUtil.cxx:162
 AGeoUtil.cxx:163
 AGeoUtil.cxx:164
 AGeoUtil.cxx:165
 AGeoUtil.cxx:166
 AGeoUtil.cxx:167
 AGeoUtil.cxx:168
 AGeoUtil.cxx:169
 AGeoUtil.cxx:170
 AGeoUtil.cxx:171
 AGeoUtil.cxx:172
 AGeoUtil.cxx:173
 AGeoUtil.cxx:174
 AGeoUtil.cxx:175
 AGeoUtil.cxx:176
 AGeoUtil.cxx:177
 AGeoUtil.cxx:178
 AGeoUtil.cxx:179
 AGeoUtil.cxx:180
 AGeoUtil.cxx:181
 AGeoUtil.cxx:182
 AGeoUtil.cxx:183
 AGeoUtil.cxx:184
 AGeoUtil.cxx:185
 AGeoUtil.cxx:186
 AGeoUtil.cxx:187
 AGeoUtil.cxx:188
 AGeoUtil.cxx:189
 AGeoUtil.cxx:190
 AGeoUtil.cxx:191
 AGeoUtil.cxx:192
 AGeoUtil.cxx:193
 AGeoUtil.cxx:194
 AGeoUtil.cxx:195
 AGeoUtil.cxx:196
 AGeoUtil.cxx:197
 AGeoUtil.cxx:198
 AGeoUtil.cxx:199
 AGeoUtil.cxx:200
 AGeoUtil.cxx:201
 AGeoUtil.cxx:202
 AGeoUtil.cxx:203
 AGeoUtil.cxx:204
 AGeoUtil.cxx:205
 AGeoUtil.cxx:206
 AGeoUtil.cxx:207
 AGeoUtil.cxx:208
 AGeoUtil.cxx:209
 AGeoUtil.cxx:210
 AGeoUtil.cxx:211
 AGeoUtil.cxx:212
 AGeoUtil.cxx:213
 AGeoUtil.cxx:214
 AGeoUtil.cxx:215
 AGeoUtil.cxx:216
 AGeoUtil.cxx:217
 AGeoUtil.cxx:218
 AGeoUtil.cxx:219
 AGeoUtil.cxx:220
 AGeoUtil.cxx:221