REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestMesh.cxx
1 /*************************************************************************
2  * This file is part of the REST software framework. *
3  * *
4  * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) *
5  * For more information see http://gifna.unizar.es/trex *
6  * *
7  * REST is free software: you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation, either version 3 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * REST is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have a copy of the GNU General Public License along with *
18  * REST in $REST_PATH/LICENSE. *
19  * If not, see http://www.gnu.org/licenses/. *
20  * For the list of contributors see $REST_PATH/CREDITS. *
21  *************************************************************************/
22 
59 
60 #include "TRestMesh.h"
61 
62 #include "TRestPhysics.h"
63 
64 using namespace std;
65 using namespace TMath;
66 
67 ClassImp(TRestMesh);
68 
73 
77 TRestMesh::TRestMesh(Double_t size, Int_t nodes) {
78  fNetSizeX = size;
79  fNetSizeY = size;
80  fNetSizeZ = size;
81 
82  // We will divide the grid in intervals not nodes.
83  fNodesX = nodes;
84  fNodesY = nodes;
85  fNodesZ = nodes;
86 
87  fNetOrigin = TVector3(0, 0, 0);
88 }
89 
93 TRestMesh::TRestMesh(TVector3 size, TVector3 position, Int_t nx, Int_t ny, Int_t nz) {
94  fNetSizeX = size.X();
95  fNetSizeY = size.Y();
96  fNetSizeZ = size.Z();
97 
98  // We will divide the grid in intervals not nodes.
99  fNodesX = nx;
100  fNodesY = ny;
101  fNodesZ = nz;
102 
103  fNetOrigin = position;
104 }
105 
110  // TRestMesh destructor
111 }
112 
116 Double_t TRestMesh::GetX(Int_t nX) { return GetPosition(nX, 0, 0).X(); }
117 
121 Double_t TRestMesh::GetY(Int_t nY) { return GetPosition(0, nY, 0).Y(); }
122 
126 Double_t TRestMesh::GetZ(Int_t nZ) { return GetPosition(0, 0, nZ).Z(); }
127 
131 TVector3 TRestMesh::GetPosition(Int_t nX, Int_t nY, Int_t nZ) {
132  if (fIsSpherical) {
133  Double_t r = (fNetSizeX / (fNodesX - 1)) * nX;
134  Double_t theta = (TMath::Pi() / (fNodesY - 1)) * nY;
135  Double_t phi = (2 * TMath::Pi() / (fNodesY - 1)) * nZ - TMath::Pi();
136 
137  TVector3 v(1, 0, 0);
138  v.SetMag(r);
139  v.SetTheta(theta);
140  v.SetPhi(phi);
141 
142  return v;
143 
144  } else {
145  Double_t x = fNetOrigin.X() + (fNetSizeX / (fNodesX - 1)) * nX;
146  Double_t y = fNetOrigin.Y() + (fNetSizeY / (fNodesY - 1)) * nY;
147  Double_t z = fNetOrigin.Z() + (fNetSizeZ / (fNodesZ - 1)) * nZ;
148  return TVector3(x, y, z);
149  }
150 
151  return TVector3(0, 0, 0);
152 }
153 
160 Int_t TRestMesh::GetNodeX(Double_t x, Bool_t relative) {
161  if (IsNaN(x)) return 0;
162 
163  Double_t xInside = x - fNetOrigin.X();
164  if (relative) xInside = x;
165 
166  if (xInside > fNetSizeX) {
167  cout << "REST WARNING (TRestMesh) : X node (" << x
168  << ") outside boundaries. Setting it to : " << fNodesX - 1 << endl;
169  return fNodesX - 1;
170  }
171 
172  if (xInside < 0) {
173  cout << "REST WARNING (TRestMesh) : X node (" << x << ") outside boundaries. Setting it to : " << 0
174  << endl;
175  return 0;
176  }
177 
178  return (Int_t)(xInside * (fNodesX - 1) / fNetSizeX);
179 }
180 
187 Int_t TRestMesh::GetNodeX(TVector3 v, Bool_t relative) {
188  // If it is cylindrical we still follow the cartesian approach :(
189  if (fIsCylindrical || !fIsSpherical) return GetNodeX(v.X(), relative);
190 
191  // if( fIsSpherical ) {
192 
193  TVector3 posInside = v - fNetOrigin;
194  if (relative) posInside = v;
195 
196  if (posInside.Mag() > fNetSizeX) {
197  cout << "REST WARNING (TRestMesh) : Relative position (" << posInside.X() << ", " << posInside.Y()
198  << ", " << posInside.Z() << ")"
199  << ") outside boundaries. Setting it to : " << fNodesX - 1 << endl;
200  return fNodesX - 1;
201  }
202 
203  // }
204 
205  return (Int_t)(posInside.Mag() * (fNodesX - 1) / fNetSizeX);
206 }
207 
214 Int_t TRestMesh::GetNodeY(Double_t y, Bool_t relative) {
215  if (IsNaN(y)) return 0;
216 
217  Double_t yInside = y - fNetOrigin.Y();
218  if (relative) yInside = y;
219 
220  if (yInside > fNetSizeY) {
221  cout << "REST WARNING (TRestMesh) : Y node (" << y
222  << ") outside boundaries. Setting it to : " << fNodesY - 1 << endl;
223  return fNodesY - 1;
224  }
225 
226  if (yInside < 0) {
227  cout << "REST WARNING (TRestMesh) : Y node (" << y << ") outside boundaries. Setting it to : " << 0
228  << endl;
229  return 0;
230  }
231 
232  Int_t nY = (Int_t)(yInside * (fNodesY - 1) / fNetSizeY);
233 
234  return nY;
235 }
236 
243 Int_t TRestMesh::GetNodeY(TVector3 v, Bool_t relative) {
244  // If it is cylindrical we still follow the cartesian approach :(
245  if (fIsCylindrical || !fIsSpherical) return GetNodeY(v.Y(), relative);
246 
247  // if( fIsSpherical ) {
248 
249  TVector3 posInside = v - fNetOrigin;
250  if (relative) posInside = v;
251 
252  if (posInside.Mag() > fNetSizeX) { // fNetSizeX = fNetSizeY = fNetSizeZ
253  cout << "REST WARNING (TRestMesh) : Relative position (" << posInside.X() << ", " << posInside.Y()
254  << ", " << posInside.Z() << ") outside boundaries. Setting it to : " << fNodesY - 1 << endl;
255  return fNodesY - 1;
256  }
257  // }
258 
259  return (Int_t)(posInside.Theta() * (fNodesY - 1) / TMath::Pi());
260 }
261 
268 Int_t TRestMesh::GetNodeZ(Double_t z, Bool_t relative) {
269  if (IsNaN(z)) return 0;
270 
271  Double_t zInside = z - fNetOrigin.Z();
272  if (relative) zInside = z;
273  if (zInside > fNetSizeZ) {
274  // cout << "REST WARNING (TRestMesh) : Z node (" << z
275  // << ") outside boundaries. Setting it to : " << fNodesZ - 1 << endl;
276  return fNodesZ - 1;
277  }
278 
279  if (zInside < 0) {
280  // cout << "REST WARNING (TRestMesh) : Z node (" << z << ") outside boundaries. Setting it to : " << 0
281  // << endl;
282  return 0;
283  }
284 
285  Int_t nZ = (Int_t)(zInside * (fNodesZ - 1) / fNetSizeZ);
286 
287  return nZ;
288 }
289 
296 Int_t TRestMesh::GetNodeZ(TVector3 v, Bool_t relative) {
297  // If it is cylindrical we still follow the cartesian approach :(
298  if (fIsCylindrical || !fIsSpherical) return GetNodeY(v.Y(), relative);
299 
300  // if( fIsSpherical ) {
301 
302  TVector3 posInside = v - fNetOrigin;
303  if (relative) posInside = v;
304 
305  if (posInside.Mag() > fNetSizeX) { // fNetSizeX = fNetSizeY = fNetSizeZ
306  cout << "REST WARNING (TRestMesh) : Relative position (" << posInside.X() << ", " << posInside.Y()
307  << ", " << posInside.Z() << ") outside boundaries. Setting it to : " << fNodesZ - 1 << endl;
308  return fNodesZ - 1;
309  }
310  // }
311 
312  return (Int_t)((posInside.Phi() + TMath::Pi()) * (fNodesZ - 1) / 2. / TMath::Pi());
313 }
314 
319  double nan = numeric_limits<double>::quiet_NaN();
320  for (unsigned int hit = 0; hit < hits->GetNumberOfHits(); hit++) {
321  if (hits->GetEnergy(hit) <= 0) continue;
322  REST_HitType type = hits->GetType(hit);
323  this->AddNode(type == YZ ? nan : hits->GetX(hit), type == XZ ? nan : hits->GetY(hit), hits->GetZ(hit),
324  hits->GetEnergy(hit));
325  }
326 
327  Regrouping();
328 }
329 
336  if (!fIsSpherical)
337  cout << "TRestMesh::SetNodesFromSphericalHits is only to be used with a spherical mesh!" << endl;
338 
339  for (unsigned int hit = 0; hit < hits->GetNumberOfHits(); hit++) {
340  if (hits->GetEnergy(hit) <= 0) continue;
341  this->AddSphericalNode(hits->GetX(hit), hits->GetY(hit), hits->GetZ(hit), hits->GetEnergy(hit));
342  }
343 
344  Regrouping();
345 }
346 
351  for (int g = 0; g < GetNumberOfGroups(); g++) {
352  Int_t nbIndex = 0;
353  Bool_t change = true;
354  while (change) {
355  change = false;
356  for (int n = 0; n < GetNumberOfNodes(); n++) {
357  if (GetGroupId(n) != g) continue;
358 
359  TVector3 nde = GetNodeByIndex(n);
360  nbIndex = FindForeignNeighbour(nde.X(), nde.Y(), nde.Z());
361 
362  if (nbIndex != GROUP_NOT_FOUND) {
363  fNodeGroupID[nbIndex] = g;
364  change = true;
365  }
366  }
367  }
368  }
369 
370  vector<Int_t> groups;
371  for (int n = 0; n < GetNumberOfNodes(); n++) {
372  Bool_t groupFound = false;
373  for (unsigned int i = 0; i < groups.size(); i++)
374  if (GetGroupId(n) == groups[i]) groupFound = true;
375 
376  if (!groupFound) groups.push_back(GetGroupId(n));
377  }
378 
379  fNumberOfGroups = groups.size();
380 
381  for (int i = 0; i < fNumberOfGroups; i++) {
382  if (i != groups[i]) {
383  for (int n = 0; n < GetNumberOfNodes(); n++)
384  if (GetGroupId(n) == groups[i]) fNodeGroupID[n] = i;
385  }
386  }
387 }
388 
393 Int_t TRestMesh::GetNodeIndex(Int_t nx, Int_t ny, Int_t nz) {
394  for (int i = 0; i < GetNumberOfNodes(); i++)
395  if (fNodeX[i] == nx && fNodeY[i] == ny && fNodeZ[i] == nz) return i;
396  return -1;
397 }
398 
404 Int_t TRestMesh::GetGroupId(Double_t x, Double_t y, Double_t z) {
405  Int_t nx, ny, nz;
406  if (fIsSpherical) {
407  TVector3 v(x, y, z); // Because if one of them is nan, this might cause problems
408  nx = GetNodeX(TVector3(x, y, z));
409  ny = GetNodeY(TVector3(x, y, z));
410  nz = GetNodeZ(TVector3(x, y, z));
411  } else {
412  nx = GetNodeX(x);
413  ny = GetNodeY(y);
414  nz = GetNodeZ(z);
415  }
416 
417  Int_t index = GetNodeIndex(nx, ny, nz);
418  if (index != NODE_NOT_SET) return fNodeGroupID[index];
419 
420  return GROUP_NOT_FOUND;
421 }
422 
426 Int_t TRestMesh::GetGroupId(Int_t index) {
427  if (index > (int)fNodeGroupID.size()) return GROUP_NOT_FOUND;
428 
429  return fNodeGroupID[index];
430 }
431 
435 Double_t TRestMesh::GetGroupEnergy(Int_t index) {
436  if (index > (int)fNodeGroupID.size()) return 0.0;
437 
438  Double_t sum = 0;
439  for (int n = 0; n < GetNumberOfNodes(); n++)
440  if (fNodeGroupID[n] == index) sum += fEnergy[n];
441 
442  return sum;
443 }
444 
448 TVector3 TRestMesh::GetGroupPosition(Int_t index) {
449  double nan = numeric_limits<double>::quiet_NaN();
450 
451  if (index > (int)fNodeGroupID.size()) return TVector3(nan, nan, nan);
452 
453  TVector3 v(0, 0, 0);
454  for (int n = 0; n < GetNumberOfNodes(); n++)
455  if (fNodeGroupID[n] == index) v += fEnergy[n] * GetPosition(fNodeX[n], fNodeY[n], fNodeZ[n]);
456 
457  v *= 1. / GetGroupEnergy(index);
458 
459  return v;
460 }
461 
466 Int_t TRestMesh::FindNeighbourGroup(Int_t nx, Int_t ny, Int_t nz) {
467  Int_t index = NODE_NOT_SET;
468 
469  for (int i = nx - 1; i <= nx + 1; i++)
470  for (int j = ny - 1; j <= ny + 1; j++)
471  for (int k = nz - 1; k <= nz + 1; k++) {
472  if (i != nx || j != ny || k != nz) {
473  index = GetNodeIndex(i, j, k);
474  if (index != NODE_NOT_SET) return fNodeGroupID[index];
475  }
476  }
477  return GROUP_NOT_FOUND;
478 }
479 
485 Int_t TRestMesh::FindForeignNeighbour(Int_t nx, Int_t ny, Int_t nz) {
486  Int_t index = GetNodeIndex(nx, ny, nz);
487 
488  if (index == NODE_NOT_SET) return GROUP_NOT_FOUND;
489 
490  Int_t nodeGroup = fNodeGroupID[index];
491 
492  for (int i = nx - 1; i <= nx + 1; i++)
493  for (int j = ny - 1; j <= ny + 1; j++)
494  for (int k = nz - 1; k <= nz + 1; k++) {
495  if (i != nx || j != ny || k != nz) {
496  index = GetNodeIndex(i, j, k);
497  if (index != NODE_NOT_SET && fNodeGroupID[index] != nodeGroup) return index;
498  }
499  }
500 
501  return GROUP_NOT_FOUND;
502 }
503 
507 void TRestMesh::SetOrigin(Double_t oX, Double_t oY, Double_t oZ) {
508  fNetOrigin = TVector3(oX, oY, oZ);
509  // TODO instead of removing nodes we might need just to re-translate the
510  // existing nodes
511  RemoveNodes();
512 }
513 
517 void TRestMesh::SetOrigin(TVector3 pos) {
518  fNetOrigin = pos;
519  // TODO instead of removing nodes we might need just to re-translate the
520  // existing nodes
521  RemoveNodes();
522 }
523 
527 void TRestMesh::SetSize(Double_t sX, Double_t sY, Double_t sZ) {
528  fNetSizeX = sX;
529  fNetSizeY = sY;
530  fNetSizeZ = sZ;
531  // TODO instead of removing nodes we might need just to re-translate the
532  // existing nodes
533  RemoveNodes();
534 }
535 
539 void TRestMesh::SetNodes(Int_t nX, Int_t nY, Int_t nZ) {
540  fNodesX = nX;
541  fNodesY = nY;
542  fNodesZ = nZ;
543  // TODO instead of removing nodes we might need just to re-translate the
544  // existing nodes
545  RemoveNodes();
546 }
547 
551 void TRestMesh::AddNode(Double_t x, Double_t y, Double_t z, Double_t en) {
552  Int_t nx, ny, nz;
553 
554  if (fIsSpherical) {
555  TVector3 v(x, y, z); // Because if one of them is nan, this might cause problems
556  nx = GetNodeX(v);
557  ny = GetNodeY(v);
558  nz = GetNodeZ(v);
559  } else {
560  nx = GetNodeX(x);
561  ny = GetNodeY(y);
562  nz = GetNodeZ(z);
563  }
564 
565  Int_t index = GetNodeIndex(nx, ny, nz);
566  if (index == NODE_NOT_SET) {
567  Int_t gId = FindNeighbourGroup(nx, ny, nz);
568  if (gId == GROUP_NOT_FOUND) {
569  gId = GetNumberOfGroups();
570  fNumberOfGroups++;
571  }
572 
573  fNodeX.push_back(nx);
574  fNodeY.push_back(ny);
575  fNodeZ.push_back(nz);
576  fNodeGroupID.push_back(gId);
577  fEnergy.push_back(en);
578 
579  fNumberOfNodes++;
580  } else {
581  fEnergy[index] += en;
582  }
583 }
584 
588 void TRestMesh::AddSphericalNode(Double_t r, Double_t theta, Double_t phi, Double_t en) {
589  TVector3 v(1, 0, 0);
590  v.SetMag(r);
591  v.SetTheta(theta);
592  v.SetPhi(phi);
593 
594  Int_t nx = GetNodeX(v);
595  Int_t ny = GetNodeY(v);
596  Int_t nz = GetNodeZ(v);
597 
598  Int_t index = GetNodeIndex(nx, ny, nz);
599  if (index == NODE_NOT_SET) {
600  Int_t gId = FindNeighbourGroup(nx, ny, nz);
601  if (gId == GROUP_NOT_FOUND) {
602  gId = GetNumberOfGroups();
603  fNumberOfGroups++;
604  }
605 
606  fNodeX.push_back(nx);
607  fNodeY.push_back(ny);
608  fNodeZ.push_back(nz);
609  fNodeGroupID.push_back(gId);
610  fEnergy.push_back(en);
611 
612  fNumberOfNodes++;
613  } else {
614  fEnergy[index] += en;
615  }
616 }
617 
622  fNodeGroupID.clear();
623  fNodeX.clear();
624  fNodeY.clear();
625  fNodeZ.clear();
626  fNumberOfNodes = 0;
627  fNumberOfGroups = 0;
628 }
629 
633 Bool_t TRestMesh::IsInside(TVector3 pos) {
634  if (pos.Z() < fNetOrigin.Z() || pos.Z() > fNetOrigin.Z() + fNetSizeZ) return false;
635 
636  if (IsSpherical()) {
637  // By definition we use X coordinate to define sphere radius
638  Double_t R = fNetSizeX / 2.;
639  Double_t posRadius = (GetNetCenter() - pos).Mag();
640 
641  if (posRadius < R)
642  return true;
643  else
644  return false;
645  }
646 
647  if (IsCylindrical()) {
648  // By definition we use X coordinate to define cylinder radius
649  Double_t R2 = fNetSizeX * fNetSizeX / 4.;
650  TVector3 relPos = GetNetCenter() - pos;
651  Double_t radius2 = relPos.X() * relPos.X() + relPos.Y() * relPos.Y();
652 
653  if (radius2 > R2) return false;
654  } else {
655  if (pos.X() < fNetOrigin.X() || pos.X() > fNetOrigin.X() + fNetSizeX) return false;
656  if (pos.Y() < fNetOrigin.Y() || pos.Y() > fNetOrigin.Y() + fNetSizeY) return false;
657  }
658 
659  return true;
660 }
661 
665 Bool_t TRestMesh::IsInsideBoundingBox(TVector3 pos) {
666  if (pos.Z() < fNetOrigin.Z() || pos.Z() > fNetOrigin.Z() + fNetSizeZ) return false;
667  if (pos.X() < fNetOrigin.X() || pos.X() > fNetOrigin.X() + fNetSizeX) return false;
668  if (pos.Y() < fNetOrigin.Y() || pos.Y() > fNetOrigin.Y() + fNetSizeY) return false;
669 
670  return true;
671 }
672 
677  return (TVector3)(fNetOrigin + TVector3(fNetSizeX / 2., fNetSizeY / 2., fNetSizeZ / 2.));
678 }
679 
684 TVector3 TRestMesh::GetVertex(Int_t id) const {
685  if (id == 0) {
686  return fNetOrigin;
687  }
688  if (id == 1) {
689  return fNetOrigin + TVector3(fNetSizeX, fNetSizeY, fNetSizeZ);
690  }
691  return {0, 0, 0};
692 }
693 
710 std::vector<TVector3> TRestMesh::GetTrackBoundaries(TVector3 pos, TVector3 dir, Bool_t particle) {
711  if (IsCylindrical()) return GetTrackBoundariesCylinder(pos, dir, particle);
712 
713  TVector3 netCenter = this->GetNetCenter();
714 
715  Double_t xH = netCenter.X() + GetNetSizeX() / 2.;
716  Double_t xL = netCenter.X() - GetNetSizeX() / 2.;
717 
718  Double_t yH = netCenter.Y() + GetNetSizeY() / 2.;
719  Double_t yL = netCenter.Y() - GetNetSizeY() / 2.;
720 
721  Double_t zH = netCenter.Z() + GetNetSizeZ() / 2.;
722  Double_t zL = netCenter.Z() - GetNetSizeZ() / 2.;
723 
724  TVector3 posAtPlane;
725  std::vector<TVector3> boundaries;
726  boundaries.clear();
727 
728  // We move the vector position at each of the planes defined by the bounding box.
729  // Then we check if it is within the face limits.
730 
731  TVector3 planePosition_BottomZ = TVector3(0, 0, -GetNetSizeZ() / 2.) + netCenter;
732  posAtPlane = REST_Physics::MoveToPlane(pos, dir, TVector3(0, 0, 1), planePosition_BottomZ);
733  if (pos != posAtPlane && posAtPlane.X() > xL && posAtPlane.X() < xH && posAtPlane.Y() > yL &&
734  posAtPlane.Y() < yH) {
735  boundaries.push_back(posAtPlane);
736  }
737 
738  TVector3 planePosition_TopZ = TVector3(0, 0, GetNetSizeZ() / 2.) + netCenter;
739  posAtPlane = REST_Physics::MoveToPlane(pos, dir, TVector3(0, 0, 1), planePosition_TopZ);
740  if (pos != posAtPlane && posAtPlane.X() > xL && posAtPlane.X() < xH && posAtPlane.Y() > yL &&
741  posAtPlane.Y() < yH) {
742  boundaries.push_back(posAtPlane);
743  }
744 
745  TVector3 planePosition_BottomY = TVector3(0, -GetNetSizeY() / 2., 0) + netCenter;
746  posAtPlane = REST_Physics::MoveToPlane(pos, dir, TVector3(0, 1, 0), planePosition_BottomY);
747  if (pos != posAtPlane && posAtPlane.X() > xL && posAtPlane.X() < xH && posAtPlane.Z() > zL &&
748  posAtPlane.Z() < zH) {
749  boundaries.push_back(posAtPlane);
750  }
751 
752  TVector3 planePosition_TopY = TVector3(0, GetNetSizeY() / 2., 0) + netCenter;
753  posAtPlane = REST_Physics::MoveToPlane(pos, dir, TVector3(0, 1, 0), planePosition_TopY);
754  if (pos != posAtPlane && posAtPlane.X() > xL && posAtPlane.X() < xH && posAtPlane.Z() > zL &&
755  posAtPlane.Z() < zH) {
756  boundaries.push_back(posAtPlane);
757  }
758 
759  TVector3 planePosition_BottomX = TVector3(-GetNetSizeX() / 2., 0, 0) + netCenter;
760  posAtPlane = REST_Physics::MoveToPlane(pos, dir, TVector3(1, 0, 0), planePosition_BottomX);
761  if (pos != posAtPlane && posAtPlane.Y() > yL && posAtPlane.Y() < yH && posAtPlane.Z() > zL &&
762  posAtPlane.Z() < zH) {
763  boundaries.push_back(posAtPlane);
764  }
765 
766  TVector3 planePosition_TopX = TVector3(GetNetSizeX() / 2., 0, 0) + netCenter;
767  posAtPlane = REST_Physics::MoveToPlane(pos, dir, TVector3(1, 0, 0), planePosition_TopX);
768  if (pos != posAtPlane && posAtPlane.Y() > yL && posAtPlane.Y() < yH && posAtPlane.Z() > zL &&
769  posAtPlane.Z() < zH) {
770  boundaries.push_back(posAtPlane);
771  }
772 
773  if (boundaries.size() == 2) {
774  if (particle) {
775  // d1 and d2 is the signed distance to the volume boundaries
776  Double_t d1 = (boundaries[0] - pos) * dir;
777  Double_t d2 = (boundaries[1] - pos) * dir;
778 
779  // Both should be positive so that the particle is approaching the volume
780  if (d1 < 0 || d2 < 0) boundaries.clear();
781 
782  // The first boundary will be always related to the closer IN boundary
783  // If it is no the case we exchange them.
784  if (d1 > d2) iter_swap(boundaries.begin(), boundaries.begin() + 1);
785  }
786  }
787 
788  return boundaries;
789 }
790 
794 std::vector<TVector3> TRestMesh::GetTrackBoundariesCylinder(TVector3 pos, TVector3 dir, Bool_t particle) {
795  TVector3 netCenter = this->GetNetCenter();
796 
797  std::vector<TVector3> boundaries;
798  boundaries.clear();
799 
800  // By definition we take the first component as the radius of the cylinder
801  Double_t R2 = fNetSizeX * fNetSizeX / 4.;
802 
803  TVector3 pos2D = TVector3(pos.X() - netCenter.X(), pos.Y() - netCenter.Y(), 0);
804  TVector3 dir2D = TVector3(dir.X(), dir.Y(), 0);
805 
806  Double_t product = pos2D * dir2D;
807  Double_t product2 = product * product;
808 
809  Double_t dirMag2 = dir2D.Mag2();
810  Double_t posMag2 = pos2D.Mag2();
811  Double_t root = product2 - dirMag2 * (posMag2 - R2);
812 
813  // For simplicity we ignore tangencial tracks. Those that produce 1-solution.
814  // If root < 0 there is no real solution to the intersection
815  if (root > 0) {
816  Double_t t1 = (-product - TMath::Sqrt(root)) / dirMag2;
817  Double_t t2 = (-product + TMath::Sqrt(root)) / dirMag2;
818 
819  TVector3 firstVertex = pos + t1 * dir;
820  TVector3 secondVertex = pos + t2 * dir;
821 
822  if (firstVertex.Z() >= GetVertex(0).Z() && firstVertex.Z() <= GetVertex(1).Z())
823  boundaries.push_back(firstVertex);
824  if (secondVertex.Z() >= GetVertex(0).Z() && secondVertex.Z() <= GetVertex(1).Z())
825  boundaries.push_back(secondVertex);
826 
827  if (boundaries.size() == 2) {
828  if (particle) {
829  if (t1 > 0 && t2 > t1) {
830  return boundaries;
831  } else {
832  boundaries.clear();
833  }
834  }
835  return boundaries;
836  }
837  }
838 
839  TVector3 posAtPlane;
840 
841  // We check if the track is entering through one of the cylinder covers.
842  TVector3 planePosition_BottomZ = TVector3(0, 0, -GetNetSizeZ() / 2.) + netCenter;
843  posAtPlane = REST_Physics::MoveToPlane(pos, dir, TVector3(0, 0, 1), planePosition_BottomZ);
844  TVector3 relPosBottom = posAtPlane - netCenter;
845  relPosBottom.SetZ(0);
846  // fNetSizeX is used to define the radius of the cylinder
847  if (relPosBottom.Mag2() < fNetSizeX * fNetSizeX / 4.) boundaries.push_back(posAtPlane);
848 
849  TVector3 planePosition_TopZ = TVector3(0, 0, GetNetSizeZ() / 2.) + netCenter;
850  posAtPlane = REST_Physics::MoveToPlane(pos, dir, TVector3(0, 0, 1), planePosition_TopZ);
851  TVector3 relPosTop = posAtPlane - netCenter;
852  relPosTop.SetZ(0);
853  // fNetSizeX is used to define the radius of the cylinder
854  if (relPosTop.Mag2() < fNetSizeX * fNetSizeX / 4.) boundaries.push_back(posAtPlane);
855 
856  if (boundaries.size() == 2 && particle) {
857  // d1 and d2 is the signed distance to the volume boundaries
858  Double_t d1 = (boundaries[0] - pos) * dir;
859  Double_t d2 = (boundaries[1] - pos) * dir;
860 
861  // Both should be positive so that the particle is approaching the volume
862  if (d1 < 0 || d2 < 0) boundaries.clear();
863 
864  // The first boundary will be always related to the closer IN boundary
865  // If it is no the case we exchange them.
866  if (d1 > d2) iter_swap(boundaries.begin(), boundaries.begin() + 1);
867  }
868 
869  return boundaries;
870 }
871 
876  std::cout << "Mesh. Number of nodes : " << GetNumberOfNodes()
877  << " Number of groups : " << GetNumberOfGroups() << endl;
878  std::cout << "---------------------------------------------" << endl;
879  for (int i = 0; i < GetNumberOfNodes(); i++)
880  std::cout << "Group : " << fNodeGroupID[i] << " X : " << fNodeX[i] << " Y : " << fNodeY[i]
881  << " Z : " << fNodeZ[i] << endl;
882  std::cout << "---------------------------------------------" << endl;
883 }
It saves a 3-coordinate position and an energy for each punctual deposition.
Definition: TRestHits.h:39
A basic class inheriting from TObject to help creating a node grid definition.
Definition: TRestMesh.h:38
void SetSize(Double_t sX, Double_t sY, Double_t sZ)
Sets the origin of the bounding-box and initializes the nodes vector to zero.
Definition: TRestMesh.cxx:527
TVector3 GetVertex(Int_t id) const
It returns the position of both boundary vertex, bottom vertex identified with id = 0 and top vertex ...
Definition: TRestMesh.cxx:684
std::vector< TVector3 > GetTrackBoundaries(TVector3 pos, TVector3 dir, Bool_t particle=true)
Finds the intersection of the straight line (track defined by the input arguments given,...
Definition: TRestMesh.cxx:710
void RemoveNodes()
It initializes all node vectors to zero.
Definition: TRestMesh.cxx:621
Bool_t IsInside(TVector3 pos)
It returns true if the position is found inside the grid (box,sphere or cylinder).
Definition: TRestMesh.cxx:633
Int_t FindNeighbourGroup(Int_t nx, Int_t ny, Int_t nz)
Returns the group id of the first node identified in the neighbour cell from cell=(nx,...
Definition: TRestMesh.cxx:466
Int_t GetNodeY(Double_t y, Bool_t relative=false)
Gets the node index corresponding to the y-coordinate.
Definition: TRestMesh.cxx:214
TRestMesh()
Default constructor.
Definition: TRestMesh.cxx:72
Int_t GetNodeZ(Double_t z, Bool_t relative=false)
Gets the node index corresponding to the z-coordinate.
Definition: TRestMesh.cxx:268
void SetNodesFromSphericalHits(TRestHits *hits)
It initializes the nodes using the hit coordinates found inside a TRestHits structure....
Definition: TRestMesh.cxx:335
Double_t GetY(Int_t nY)
Gets the cartesian position of nodeY.
Definition: TRestMesh.cxx:121
void SetOrigin(Double_t oX, Double_t oY, Double_t oZ)
Sets the origin of the bounding-box and initializes the nodes vector to zero.
Definition: TRestMesh.cxx:507
void Regrouping()
Needs TO BE documented.
Definition: TRestMesh.cxx:350
void AddSphericalNode(Double_t x, Double_t y, Double_t z, Double_t en=0)
If adds corresponding node to xyz-coordinates if not previously defined.
Definition: TRestMesh.cxx:588
Int_t GetNodeIndex(Int_t nx, Int_t ny, Int_t nz)
Returns the vector position for a given node index. If the node is not found, -1 will be returned.
Definition: TRestMesh.cxx:393
std::vector< TVector3 > GetTrackBoundariesCylinder(TVector3 pos, TVector3 dir, Bool_t particle=true)
Needs TO BE documented.
Definition: TRestMesh.cxx:794
void AddNode(Double_t x, Double_t y, Double_t z, Double_t en=0)
If adds corresponding node to xyz-coordinates if not previously defined.
Definition: TRestMesh.cxx:551
TVector3 GetGroupPosition(Int_t index)
It returns the average position for all nodes weighted with their corresponding energy.
Definition: TRestMesh.cxx:448
Int_t FindForeignNeighbour(Int_t nx, Int_t ny, Int_t nz)
It identifies a foreign neighbour. I.e. if the group id of the neighbour cell is different to the cel...
Definition: TRestMesh.cxx:485
Bool_t IsInsideBoundingBox(TVector3 pos)
It returns true if the position is found inside the bounding box.
Definition: TRestMesh.cxx:665
void SetNodesFromHits(TRestHits *hits)
It initializes the nodes using the hit coordinates found inside a TRestHits structure.
Definition: TRestMesh.cxx:318
TVector3 GetNetCenter()
It returns the position of the mesh center.
Definition: TRestMesh.cxx:676
void Print()
Prints the nodes information.
Definition: TRestMesh.cxx:875
Double_t GetGroupEnergy(Int_t index)
It returns the total energy of all nodes corresponding to the group id given by argument.
Definition: TRestMesh.cxx:435
Int_t GetNodeX(Double_t x, Bool_t relative=false)
Gets the node index corresponding to the x-coordinate.
Definition: TRestMesh.cxx:160
Double_t GetZ(Int_t nZ)
Gets the cartesian position of nodeZ.
Definition: TRestMesh.cxx:126
Int_t GetGroupId(Double_t x, Double_t y, Double_t z)
Returns the group id corresponding to the x,y,z coordinate. If the coordinate falls at a non-initiali...
Definition: TRestMesh.cxx:404
void SetNodes(Int_t nX, Int_t nY, Int_t nZ)
Sets the number of nodes and initializes the nodes vector to zero.
Definition: TRestMesh.cxx:539
Double_t GetX(Int_t nX)
Gets the cartesian position of nodeX.
Definition: TRestMesh.cxx:116
TVector3 GetPosition(Int_t nX, Int_t nY, Int_t nZ)
Gets the position of the corresponding node.
Definition: TRestMesh.cxx:131
~TRestMesh()
Default destructor.
Definition: TRestMesh.cxx:109
TVector3 MoveToPlane(const TVector3 &pos, const TVector3 &dir, const TVector3 &n, const TVector3 &a)
This method will translate the vector with direction dir starting at position pos to the plane define...