60 #include "TRestMesh.h"
62 #include "TRestPhysics.h"
65 using namespace TMath;
87 fNetOrigin = TVector3(0, 0, 0);
103 fNetOrigin = position;
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();
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);
151 return TVector3(0, 0, 0);
161 if (IsNaN(x))
return 0;
163 Double_t xInside = x - fNetOrigin.X();
164 if (relative) xInside = x;
166 if (xInside > fNetSizeX) {
167 cout <<
"REST WARNING (TRestMesh) : X node (" << x
168 <<
") outside boundaries. Setting it to : " << fNodesX - 1 << endl;
173 cout <<
"REST WARNING (TRestMesh) : X node (" << x <<
") outside boundaries. Setting it to : " << 0
178 return (Int_t)(xInside * (fNodesX - 1) / fNetSizeX);
189 if (fIsCylindrical || !fIsSpherical)
return GetNodeX(v.X(), relative);
193 TVector3 posInside = v - fNetOrigin;
194 if (relative) posInside = v;
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;
205 return (Int_t)(posInside.Mag() * (fNodesX - 1) / fNetSizeX);
215 if (IsNaN(y))
return 0;
217 Double_t yInside = y - fNetOrigin.Y();
218 if (relative) yInside = y;
220 if (yInside > fNetSizeY) {
221 cout <<
"REST WARNING (TRestMesh) : Y node (" << y
222 <<
") outside boundaries. Setting it to : " << fNodesY - 1 << endl;
227 cout <<
"REST WARNING (TRestMesh) : Y node (" << y <<
") outside boundaries. Setting it to : " << 0
232 Int_t nY = (Int_t)(yInside * (fNodesY - 1) / fNetSizeY);
245 if (fIsCylindrical || !fIsSpherical)
return GetNodeY(v.Y(), relative);
249 TVector3 posInside = v - fNetOrigin;
250 if (relative) posInside = v;
252 if (posInside.Mag() > fNetSizeX) {
253 cout <<
"REST WARNING (TRestMesh) : Relative position (" << posInside.X() <<
", " << posInside.Y()
254 <<
", " << posInside.Z() <<
") outside boundaries. Setting it to : " << fNodesY - 1 << endl;
259 return (Int_t)(posInside.Theta() * (fNodesY - 1) / TMath::Pi());
269 if (IsNaN(z))
return 0;
271 Double_t zInside = z - fNetOrigin.Z();
272 if (relative) zInside = z;
273 if (zInside > fNetSizeZ) {
285 Int_t nZ = (Int_t)(zInside * (fNodesZ - 1) / fNetSizeZ);
298 if (fIsCylindrical || !fIsSpherical)
return GetNodeY(v.Y(), relative);
302 TVector3 posInside = v - fNetOrigin;
303 if (relative) posInside = v;
305 if (posInside.Mag() > fNetSizeX) {
306 cout <<
"REST WARNING (TRestMesh) : Relative position (" << posInside.X() <<
", " << posInside.Y()
307 <<
", " << posInside.Z() <<
") outside boundaries. Setting it to : " << fNodesZ - 1 << endl;
312 return (Int_t)((posInside.Phi() + TMath::Pi()) * (fNodesZ - 1) / 2. / TMath::Pi());
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));
337 cout <<
"TRestMesh::SetNodesFromSphericalHits is only to be used with a spherical mesh!" << endl;
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));
351 for (
int g = 0; g < GetNumberOfGroups(); g++) {
353 Bool_t change =
true;
356 for (
int n = 0; n < GetNumberOfNodes(); n++) {
357 if (GetGroupId(n) != g)
continue;
359 TVector3 nde = GetNodeByIndex(n);
360 nbIndex = FindForeignNeighbour(nde.X(), nde.Y(), nde.Z());
362 if (nbIndex != GROUP_NOT_FOUND) {
363 fNodeGroupID[nbIndex] = g;
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;
376 if (!groupFound) groups.push_back(GetGroupId(n));
379 fNumberOfGroups = groups.size();
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;
394 for (
int i = 0; i < GetNumberOfNodes(); i++)
395 if (fNodeX[i] == nx && fNodeY[i] == ny && fNodeZ[i] == nz)
return i;
408 nx = GetNodeX(TVector3(x, y, z));
409 ny = GetNodeY(TVector3(x, y, z));
410 nz = GetNodeZ(TVector3(x, y, z));
417 Int_t index = GetNodeIndex(nx, ny, nz);
418 if (index != NODE_NOT_SET)
return fNodeGroupID[index];
420 return GROUP_NOT_FOUND;
427 if (index > (
int)fNodeGroupID.size())
return GROUP_NOT_FOUND;
429 return fNodeGroupID[index];
436 if (index > (
int)fNodeGroupID.size())
return 0.0;
439 for (
int n = 0; n < GetNumberOfNodes(); n++)
440 if (fNodeGroupID[n] == index) sum += fEnergy[n];
449 double nan = numeric_limits<double>::quiet_NaN();
451 if (index > (
int)fNodeGroupID.size())
return TVector3(nan, nan, nan);
454 for (
int n = 0; n < GetNumberOfNodes(); n++)
455 if (fNodeGroupID[n] == index) v += fEnergy[n] * GetPosition(fNodeX[n], fNodeY[n], fNodeZ[n]);
457 v *= 1. / GetGroupEnergy(index);
467 Int_t index = NODE_NOT_SET;
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];
477 return GROUP_NOT_FOUND;
486 Int_t index = GetNodeIndex(nx, ny, nz);
488 if (index == NODE_NOT_SET)
return GROUP_NOT_FOUND;
490 Int_t nodeGroup = fNodeGroupID[index];
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;
501 return GROUP_NOT_FOUND;
508 fNetOrigin = TVector3(oX, oY, oZ);
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();
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);
581 fEnergy[index] += en;
594 Int_t nx = GetNodeX(v);
595 Int_t ny = GetNodeY(v);
596 Int_t nz = GetNodeZ(v);
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();
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);
614 fEnergy[index] += en;
622 fNodeGroupID.clear();
634 if (pos.Z() < fNetOrigin.Z() || pos.Z() > fNetOrigin.Z() + fNetSizeZ)
return false;
638 Double_t R = fNetSizeX / 2.;
639 Double_t posRadius = (GetNetCenter() - pos).Mag();
647 if (IsCylindrical()) {
649 Double_t R2 = fNetSizeX * fNetSizeX / 4.;
650 TVector3 relPos = GetNetCenter() - pos;
651 Double_t radius2 = relPos.X() * relPos.X() + relPos.Y() * relPos.Y();
653 if (radius2 > R2)
return false;
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;
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;
677 return (TVector3)(fNetOrigin + TVector3(fNetSizeX / 2., fNetSizeY / 2., fNetSizeZ / 2.));
689 return fNetOrigin + TVector3(fNetSizeX, fNetSizeY, fNetSizeZ);
711 if (IsCylindrical())
return GetTrackBoundariesCylinder(pos, dir, particle);
713 TVector3 netCenter = this->GetNetCenter();
715 Double_t xH = netCenter.X() + GetNetSizeX() / 2.;
716 Double_t xL = netCenter.X() - GetNetSizeX() / 2.;
718 Double_t yH = netCenter.Y() + GetNetSizeY() / 2.;
719 Double_t yL = netCenter.Y() - GetNetSizeY() / 2.;
721 Double_t zH = netCenter.Z() + GetNetSizeZ() / 2.;
722 Double_t zL = netCenter.Z() - GetNetSizeZ() / 2.;
725 std::vector<TVector3> boundaries;
731 TVector3 planePosition_BottomZ = TVector3(0, 0, -GetNetSizeZ() / 2.) + netCenter;
733 if (pos != posAtPlane && posAtPlane.X() > xL && posAtPlane.X() < xH && posAtPlane.Y() > yL &&
734 posAtPlane.Y() < yH) {
735 boundaries.push_back(posAtPlane);
738 TVector3 planePosition_TopZ = TVector3(0, 0, GetNetSizeZ() / 2.) + netCenter;
740 if (pos != posAtPlane && posAtPlane.X() > xL && posAtPlane.X() < xH && posAtPlane.Y() > yL &&
741 posAtPlane.Y() < yH) {
742 boundaries.push_back(posAtPlane);
745 TVector3 planePosition_BottomY = TVector3(0, -GetNetSizeY() / 2., 0) + netCenter;
747 if (pos != posAtPlane && posAtPlane.X() > xL && posAtPlane.X() < xH && posAtPlane.Z() > zL &&
748 posAtPlane.Z() < zH) {
749 boundaries.push_back(posAtPlane);
752 TVector3 planePosition_TopY = TVector3(0, GetNetSizeY() / 2., 0) + netCenter;
754 if (pos != posAtPlane && posAtPlane.X() > xL && posAtPlane.X() < xH && posAtPlane.Z() > zL &&
755 posAtPlane.Z() < zH) {
756 boundaries.push_back(posAtPlane);
759 TVector3 planePosition_BottomX = TVector3(-GetNetSizeX() / 2., 0, 0) + netCenter;
761 if (pos != posAtPlane && posAtPlane.Y() > yL && posAtPlane.Y() < yH && posAtPlane.Z() > zL &&
762 posAtPlane.Z() < zH) {
763 boundaries.push_back(posAtPlane);
766 TVector3 planePosition_TopX = TVector3(GetNetSizeX() / 2., 0, 0) + netCenter;
768 if (pos != posAtPlane && posAtPlane.Y() > yL && posAtPlane.Y() < yH && posAtPlane.Z() > zL &&
769 posAtPlane.Z() < zH) {
770 boundaries.push_back(posAtPlane);
773 if (boundaries.size() == 2) {
776 Double_t d1 = (boundaries[0] - pos) * dir;
777 Double_t d2 = (boundaries[1] - pos) * dir;
780 if (d1 < 0 || d2 < 0) boundaries.clear();
784 if (d1 > d2) iter_swap(boundaries.begin(), boundaries.begin() + 1);
795 TVector3 netCenter = this->GetNetCenter();
797 std::vector<TVector3> boundaries;
801 Double_t R2 = fNetSizeX * fNetSizeX / 4.;
803 TVector3 pos2D = TVector3(pos.X() - netCenter.X(), pos.Y() - netCenter.Y(), 0);
804 TVector3 dir2D = TVector3(dir.X(), dir.Y(), 0);
806 Double_t product = pos2D * dir2D;
807 Double_t product2 = product * product;
809 Double_t dirMag2 = dir2D.Mag2();
810 Double_t posMag2 = pos2D.Mag2();
811 Double_t root = product2 - dirMag2 * (posMag2 - R2);
816 Double_t t1 = (-product - TMath::Sqrt(root)) / dirMag2;
817 Double_t t2 = (-product + TMath::Sqrt(root)) / dirMag2;
819 TVector3 firstVertex = pos + t1 * dir;
820 TVector3 secondVertex = pos + t2 * dir;
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);
827 if (boundaries.size() == 2) {
829 if (t1 > 0 && t2 > t1) {
842 TVector3 planePosition_BottomZ = TVector3(0, 0, -GetNetSizeZ() / 2.) + netCenter;
844 TVector3 relPosBottom = posAtPlane - netCenter;
845 relPosBottom.SetZ(0);
847 if (relPosBottom.Mag2() < fNetSizeX * fNetSizeX / 4.) boundaries.push_back(posAtPlane);
849 TVector3 planePosition_TopZ = TVector3(0, 0, GetNetSizeZ() / 2.) + netCenter;
851 TVector3 relPosTop = posAtPlane - netCenter;
854 if (relPosTop.Mag2() < fNetSizeX * fNetSizeX / 4.) boundaries.push_back(posAtPlane);
856 if (boundaries.size() == 2 && particle) {
858 Double_t d1 = (boundaries[0] - pos) * dir;
859 Double_t d2 = (boundaries[1] - pos) * dir;
862 if (d1 < 0 || d2 < 0) boundaries.clear();
866 if (d1 > d2) iter_swap(boundaries.begin(), boundaries.begin() + 1);
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;
It saves a 3-coordinate position and an energy for each punctual deposition.
A basic class inheriting from TObject to help creating a node grid definition.
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.
TVector3 GetVertex(Int_t id) const
It returns the position of both boundary vertex, bottom vertex identified with id = 0 and top vertex ...
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,...
void RemoveNodes()
It initializes all node vectors to zero.
Bool_t IsInside(TVector3 pos)
It returns true if the position is found inside the grid (box,sphere or cylinder).
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,...
Int_t GetNodeY(Double_t y, Bool_t relative=false)
Gets the node index corresponding to the y-coordinate.
TRestMesh()
Default constructor.
Int_t GetNodeZ(Double_t z, Bool_t relative=false)
Gets the node index corresponding to the z-coordinate.
void SetNodesFromSphericalHits(TRestHits *hits)
It initializes the nodes using the hit coordinates found inside a TRestHits structure....
Double_t GetY(Int_t nY)
Gets the cartesian position of nodeY.
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.
void Regrouping()
Needs TO BE documented.
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.
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.
std::vector< TVector3 > GetTrackBoundariesCylinder(TVector3 pos, TVector3 dir, Bool_t particle=true)
Needs TO BE documented.
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.
TVector3 GetGroupPosition(Int_t index)
It returns the average position for all nodes weighted with their corresponding energy.
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...
Bool_t IsInsideBoundingBox(TVector3 pos)
It returns true if the position is found inside the bounding box.
void SetNodesFromHits(TRestHits *hits)
It initializes the nodes using the hit coordinates found inside a TRestHits structure.
TVector3 GetNetCenter()
It returns the position of the mesh center.
void Print()
Prints the nodes information.
Double_t GetGroupEnergy(Int_t index)
It returns the total energy of all nodes corresponding to the group id given by argument.
Int_t GetNodeX(Double_t x, Bool_t relative=false)
Gets the node index corresponding to the x-coordinate.
Double_t GetZ(Int_t nZ)
Gets the cartesian position of nodeZ.
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...
void SetNodes(Int_t nX, Int_t nY, Int_t nZ)
Sets the number of nodes and initializes the nodes vector to zero.
Double_t GetX(Int_t nX)
Gets the cartesian position of nodeX.
TVector3 GetPosition(Int_t nX, Int_t nY, Int_t nZ)
Gets the position of the corresponding node.
~TRestMesh()
Default destructor.
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...