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
64using namespace std;
65using namespace TMath;
66
67ClassImp(TRestMesh);
68
73
77TRestMesh::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
93TRestMesh::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
116Double_t TRestMesh::GetX(Int_t nX) { return GetPosition(nX, 0, 0).X(); }
117
121Double_t TRestMesh::GetY(Int_t nY) { return GetPosition(0, nY, 0).Y(); }
122
126Double_t TRestMesh::GetZ(Int_t nZ) { return GetPosition(0, 0, nZ).Z(); }
127
131TVector3 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
160Int_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
187Int_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
214Int_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
243Int_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
268Int_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
296Int_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
393Int_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
404Int_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
426Int_t TRestMesh::GetGroupId(Int_t index) {
427 if (index > (int)fNodeGroupID.size()) return GROUP_NOT_FOUND;
428
429 return fNodeGroupID[index];
430}
431
435Double_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
448TVector3 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
466Int_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
485Int_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
507void 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
517void 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
527void 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
539void 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
551void 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();
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
580 } else {
581 fEnergy[index] += en;
582 }
583}
584
588void 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();
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
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
633Bool_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
665Bool_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
684TVector3 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
710std::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
794std::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
std::vector< Int_t > fNodeY
A std::vector storing the Y-dimension cell id.
Definition: TRestMesh.h:67
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 fNetSizeZ
The size of the grid in Z dimension.
Definition: TRestMesh.h:48
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 fNodesX
Number of nodes in X-dimension (R in spherical coordinates)
Definition: TRestMesh.h:51
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< Int_t > fNodeZ
A std::vector storing the Z-dimension cell id.
Definition: TRestMesh.h:69
std::vector< Int_t > fNodeX
A std::vector storing the X-dimension cell id.
Definition: TRestMesh.h:65
Int_t fNumberOfGroups
Total number of groups found.
Definition: TRestMesh.h:60
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
Int_t fNumberOfNodes
Total number of nodes filled.
Definition: TRestMesh.h:58
TVector3 GetGroupPosition(Int_t index)
It returns the average position for all nodes weighted with their corresponding energy.
Definition: TRestMesh.cxx:448
Int_t GetNumberOfNodes() const
Returns the total number of nodes added.
Definition: TRestMesh.h:85
Double_t fNetSizeX
The size of the grid in X dimension.
Definition: TRestMesh.h:44
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 IsSpherical()
Returns true if the coordinate system is set to spherical.
Definition: TRestMesh.h:102
Bool_t fIsCylindrical
A flag to indentify if we use cylindrical coordinates.
Definition: TRestMesh.h:75
Int_t fNodesZ
Number of nodes in Z-dimension (Phi in spherical coordinates)
Definition: TRestMesh.h:55
Double_t GetNetSizeZ() const
Returns the net size on Z-dimension.
Definition: TRestMesh.h:159
Bool_t IsInsideBoundingBox(TVector3 pos)
It returns true if the position is found inside the bounding box.
Definition: TRestMesh.cxx:665
Int_t fNodesY
Number of nodes in Y-dimension (Theta in spherical coordinates)
Definition: TRestMesh.h:53
Double_t GetNetSizeX() const
Returns the net size on X-dimension.
Definition: TRestMesh.h:155
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
TVector3 GetNodeByIndex(Int_t index)
Returns a node by its position in the std::vector.
Definition: TRestMesh.h:105
TVector3 fNetOrigin
The bottom-left corner of the bounding-box grid.
Definition: TRestMesh.h:41
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
Bool_t IsCylindrical()
Returns true if the coordinate system is set to cylindrical.
Definition: TRestMesh.h:100
std::vector< Int_t > fNodeGroupID
A std::vector storing the group ID of the corresponding nodes activated.
Definition: TRestMesh.h:63
Int_t GetNumberOfGroups() const
Returns the total number of groups identified.
Definition: TRestMesh.h:87
Double_t fNetSizeY
The size of the grid in Y dimension.
Definition: TRestMesh.h:46
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
Bool_t fIsSpherical
A flag to indentify if we use spherical coordinates.
Definition: TRestMesh.h:77
Double_t GetX(Int_t nX)
Gets the cartesian position of nodeX.
Definition: TRestMesh.cxx:116
std::vector< Double_t > fEnergy
A std::vector storing the total energy inside the cell id.
Definition: TRestMesh.h:72
Double_t GetNetSizeY() const
Returns the net size on Y-dimension.
Definition: TRestMesh.h:157
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...