83 Fatal(
"AddNode",
"Cannot add nodes to a closed parallel geometry");
85 Error(
"AddNode",
"Path %s not valid.\nCannot add to parallel world!", path);
115 if (!strcmp(vol->
GetName(), volname))
131 Info(
"PrintDetectedOverlaps",
"List of detected volumes overlapping with the PW");
158 Fatal(
"CloseGeometry",
"Main geometry must be closed first");
160 Error(
"CloseGeometry",
"List of paths is empty");
165 Info(
"CloseGeometry",
"Parallel world %s contains %d prioritised objects",
GetName(),
fPaths->GetEntriesFast());
172 Info(
"CloseGeometry",
"Number of declared overlaps: %d", novlp);
174 Info(
"CloseGeometry",
"Parallel world will use declared overlaps");
176 Info(
"CloseGeometry",
"Parallel world will detect overlaps with other volumes");
178 Info(
"CloseGeometry",
"Parallel world has %d volumes",
fVolume->GetNdaughters());
207 fVolume->GetShape()->ComputeBBox();
214 if (verboselevel > 2) {
215 Info(
"RefreshPhysicalNodes",
"Initializing BVH took %f seconds", timer.
RealTime());
222 if (verboselevel > 2) {
223 Info(
"RefreshPhysicalNodes",
"Voxelization took %f seconds", timer.
RealTime());
238 Fatal(
"FindNode",
"Parallel geometry must be closed first");
241 using Scalar = float;
250 Vec3 testpoint(point[0], point[1], point[2]);
258 size_t min_contained_object_id = std::numeric_limits<size_t>::max();
264 return (p[0] >= min[0] && p[0] <= max[0]) && (p[1] >= min[1] && p[1] <= max[1]) &&
265 (p[2] >= min[2] && p[2] <= max[2]);
268 auto leaf_fn = [&](
size_t begin,
size_t end) {
269 for (
size_t prim_id = begin; prim_id < end; ++prim_id) {
270 auto objectid = mybvh->prim_ids[prim_id];
271 if (min_contained_object_id == std::numeric_limits<size_t>::max() || objectid < min_contained_object_id) {
272 auto object =
fVolume->GetNode(objectid);
274 object->MasterToLocal(point, lpoint);
275 if (
object->GetVolume()->Contains(lpoint)) {
277 min_contained_object_id = objectid;
284 auto root = mybvh->nodes[0];
290 constexpr bool earlyExit =
false;
291 mybvh->traverse_top_down<earlyExit>(root.index, stack, leaf_fn, [&](
const Node &left,
const Node &right) {
292 bool follow_left =
contains(left, testpoint);
293 bool follow_right =
contains(right, testpoint);
294 return std::make_tuple(follow_left, follow_right,
false);
311 Fatal(
"FindNode",
"Parallel geometry must be closed first");
328 for (
id = 0;
id < ncheck;
id++) {
329 node =
fVolume->GetNode(check_list[
id]);
346 Fatal(
"FindNode",
"Parallel geometry must be closed first");
348 for (
int id = 0;
id < nd;
id++) {
350 auto node =
fVolume->GetNode(
id);
351 node->MasterToLocal(point, local);
352 if (node->GetVolume()->Contains(local)) {
366 using Scalar = float;
373 for (
size_t i = 0; i < mybvh->nodes.size(); ++i) {
374 const auto &
n = mybvh->nodes[i];
375 auto bbox =
n.get_bbox();
379 if (
n.index.prim_count() > 0) {
380 objectid = mybvh->prim_ids[
n.index.first_id()];
382 std::cout <<
"NODE id" << i <<
" "
383 <<
" prim_count: " <<
n.index.prim_count() <<
" first_id " <<
n.index.first_id() <<
" object_id "
384 << objectid <<
" ( " << min[0] <<
" , " << min[1] <<
" , " << min[2] <<
")"
385 <<
" ( " << max[0] <<
" , " << max[1] <<
" , " << max[2] <<
")"
398 Fatal(
"FindNextBoundary",
"Parallel geometry must be closed first");
411 double local_step = stepmax;
413 using Scalar = float;
422 Error(
"FindNextBoundary",
"Cannot perform safety; No BVH initialized");
426 auto truncate_roundup = [](
double orig) {
427 float epsilon = std::numeric_limits<float>::epsilon() * std::fabs(orig);
429 return static_cast<float>(orig + epsilon);
433 const auto topnode_bbox = mybvh->get_root().get_bbox();
434 if ((-point[0] + topnode_bbox.min[0]) > stepmax) {
438 if ((-point[1] + topnode_bbox.min[1]) > stepmax) {
442 if ((-point[2] + topnode_bbox.min[2]) > stepmax) {
446 if ((point[0] - topnode_bbox.max[0]) > stepmax) {
450 if ((point[1] - topnode_bbox.max[1]) > stepmax) {
454 if ((point[2] - topnode_bbox.max[2]) > stepmax) {
460 Ray ray(Vec3(point[0], point[1], point[2]),
461 Vec3(dir[0], dir[1], dir[2]),
463 truncate_roundup(local_step));
467 static constexpr bool use_robust_traversal =
true;
471 mybvh->intersect<
false, use_robust_traversal>(ray, mybvh->get_root().index, stack, [&](
size_t begin,
size_t end) {
472 for (
size_t prim_id = begin; prim_id < end; ++prim_id) {
473 auto objectid = mybvh->prim_ids[prim_id];
474 auto object =
fVolume->GetNode(objectid);
477 if (pnode->IsMatchingState(nav)) {
484 object->MasterToLocal(point, lpoint);
485 object->MasterToLocalVect(dir, ldir);
486 auto thisstep =
object->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, local_step);
487 if (thisstep < local_step) {
488 local_step = thisstep;
512 Fatal(
"FindNextBoundary",
"Parallel geometry must be closed first");
528 Int_t idaughter = -1;
536 for (i = 0; i < nd; i++) {
554 if (idaughter >= 0) {
563 Int_t sumchecked = 0;
564 Int_t *vlist =
nullptr;
570 while ((sumchecked < nd) && (vlist = voxels->
GetNextVoxel(point, dir, ncheck, info))) {
571 for (i = 0; i < ncheck; i++) {
577 current =
fVolume->GetNode(vlist[i]);
581 if (snext < step - 1.E-8) {
583 idaughter = vlist[i];
586 if (idaughter >= 0) {
608 Fatal(
"FindNextBoundary",
"Parallel geometry must be closed first");
622 int nd =
fVolume->GetNdaughters();
624 for (
int i = 0; i < nd; ++i) {
625 auto object =
fVolume->GetNode(i);
629 object->MasterToLocal(point, lpoint);
630 object->MasterToLocalVect(dir, ldir);
631 auto thisstep =
object->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, step);
632 if (thisstep < step) {
648struct BVHPrioElement {
655template <
typename Comparator>
656class BVHPrioQueue :
public std::priority_queue<BVHPrioElement, std::vector<BVHPrioElement>, Comparator> {
658 using std::priority_queue<BVHPrioElement, std::vector<BVHPrioElement>,
659 Comparator>::priority_queue;
662 void clear() { this->
c.clear(); }
671std::pair<double, double>
680 using Scalar = float;
684 auto &bboxes = (*bboxes_ptr);
686 auto cmp = [](BVHPrioElement
a, BVHPrioElement
b) {
return a.value >
b.value; };
687 static thread_local BVHPrioQueue<
decltype(cmp)> queue(cmp);
691 Vec3 testpoint(point[0], point[1], point[2]);
692 float best_enclosing_R_sq = std::numeric_limits<float>::max();
693 for (
size_t i = 0; i < bboxes.size(); ++i) {
694 const auto &thisbox = bboxes[i];
696 const auto this_R_max_sq =
RmaxSqToNode(thisbox, testpoint);
697 const auto inside =
contains(thisbox, testpoint);
698 safety_sq = inside ? -1.f : safety_sq;
699 best_enclosing_R_sq = std::min(best_enclosing_R_sq, this_R_max_sq);
700 queue.emplace(BVHPrioElement{i, safety_sq});
705 float safety_sq_at_least = -1.f;
709 float best_enclosing_R = std::sqrt(best_enclosing_R_sq) + margin;
710 best_enclosing_R_sq = best_enclosing_R * best_enclosing_R;
713 if (queue.size() > 0) {
714 auto el = queue.top();
716 safety_sq_at_least = el.value;
717 while (el.value < best_enclosing_R_sq) {
718 candidates.emplace_back(el.bvh_node_id);
719 if (queue.size() > 0) {
727 return std::make_pair<double, double>(best_enclosing_R_sq, safety_sq_at_least);
734std::pair<double, double>
743 using Scalar = float;
754 Vec3 testpoint(point[0], point[1], point[2]);
757 auto cmp = [](BVHPrioElement
a, BVHPrioElement
b) {
return a.value >
b.value; };
758 static thread_local BVHPrioQueue<
decltype(cmp)> queue(cmp);
760 static thread_local BVHPrioQueue<
decltype(cmp)> leaf_queue(cmp);
763 auto currnode = mybvh->nodes[0];
765 float best_enclosing_R_sq = std::numeric_limits<float>::max();
766 float best_enclosing_R_with_margin_sq = std::numeric_limits<float>::max();
767 float current_safety_sq = 0.f;
769 if (currnode.is_leaf()) {
771 const auto begin_prim_id = currnode.index.first_id();
772 const auto end_prim_id = begin_prim_id + currnode.index.prim_count();
773 for (
auto p_id = begin_prim_id; p_id < end_prim_id; p_id++) {
774 const auto object_id = mybvh->prim_ids[p_id];
777 const auto &leaf_bounding_box = (*bboxes)[object_id];
778 auto this_Rmax_sq =
RmaxSqToNode(leaf_bounding_box, testpoint);
779 const bool inside =
contains(leaf_bounding_box, testpoint);
780 const auto safety_sq = inside ? -1.f :
SafetySqToNode(leaf_bounding_box, testpoint);
783 if (this_Rmax_sq < best_enclosing_R_sq) {
784 best_enclosing_R_sq = this_Rmax_sq;
785 const auto this_Rmax = std::sqrt(this_Rmax_sq);
786 best_enclosing_R_with_margin_sq = (this_Rmax + margin) * (this_Rmax + margin);
790 if (safety_sq <= best_enclosing_R_with_margin_sq) {
792 leaf_queue.emplace(BVHPrioElement{object_id, safety_sq});
798 const auto leftchild_id = currnode.index.first_id();
799 const auto rightchild_id = leftchild_id + 1;
801 for (
size_t childid : {leftchild_id, rightchild_id}) {
802 if (childid >= mybvh->nodes.size()) {
805 const auto &node = mybvh->nodes[childid];
806 const auto &thisbbox = node.get_bbox();
807 auto inside =
contains(thisbbox, testpoint);
808 const auto this_safety_sq = inside ? -1.f :
SafetySqToNode(thisbbox, testpoint);
809 if (this_safety_sq <= best_enclosing_R_with_margin_sq) {
811 queue.push(BVHPrioElement{childid, this_safety_sq});
816 if (queue.size() > 0) {
817 auto currElement = queue.top();
818 currnode = mybvh->nodes[currElement.bvh_node_id];
819 current_safety_sq = currElement.value;
824 }
while (current_safety_sq <= best_enclosing_R_with_margin_sq);
828 float safety_sq_at_least = -1.f;
829 if (leaf_queue.size() > 0) {
830 auto el = leaf_queue.top();
832 safety_sq_at_least = el.value;
833 while (el.value < best_enclosing_R_with_margin_sq) {
834 candidates.emplace_back(el.bvh_node_id);
835 if (leaf_queue.size() > 0) {
836 el = leaf_queue.top();
843 return std::make_pair<double, double>(best_enclosing_R_sq, safety_sq_at_least);
852 static std::mutex g_mutex;
854 const std::lock_guard<std::mutex> lock(g_mutex);
858 static std::vector<int> candidates;
860 double point[3] = {mpx, mpy, mpz};
861 auto [encl_Rmax_sq, min_safety_sq] =
866 voxelinfo->min_safety = std::sqrt(min_safety_sq);
868 voxelinfo->num_candidates = candidates.size();
903 double bestsafety = safe_max;
905 if (!voxelinfo.isInitialized()) {
910 if (voxelinfo.min_safety > 0) {
919 for (
int i = 0; i < 3; ++i) {
920 const auto d = (point[i] - midpoint[i]);
923 if (r_sq < voxelinfo.min_safety * voxelinfo.min_safety) {
925 return voxelinfo.min_safety - std::sqrt(r_sq);
930 using Scalar = float;
934 auto &bboxes = (*bboxes_ptr);
935 Vec3 testpoint(point[0], point[1], point[2]);
937 for (
size_t store_id = voxelinfo.idx_start; store_id < voxelinfo.idx_start + voxelinfo.num_candidates; ++store_id) {
942 const auto &bbox = bboxes[cand_id];
944 if (bbox_safe_sq > bestsafety * bestsafety) {
949 const auto primitive_node =
fVolume->GetNode(cand_id);
950 const auto thissafety = primitive_node->Safety(point,
false);
951 if (thissafety < bestsafety) {
952 bestsafety = std::max(0., thissafety);
974 float smallest_safety = safe_max;
975 float smallest_safety_sq = smallest_safety * smallest_safety;
978 using Scalar = float;
987 Vec3 testpoint(point[0], point[1], point[2]);
989 auto currnode = mybvh->nodes[0];
991 bool outside_top = !
contains(currnode.get_bbox(), testpoint);
992 const auto safety_sq_to_top =
SafetySqToNode(currnode.get_bbox(), testpoint);
993 if (outside_top && safety_sq_to_top > smallest_safety_sq) {
995 return smallest_safety;
999 auto cmp = [](BVHPrioElement
a, BVHPrioElement
b) {
return a.value >
b.value; };
1000 static thread_local BVHPrioQueue<
decltype(cmp)> queue(cmp);
1004 float current_safety_to_node_sq = outside_top ? safety_sq_to_top : 0.f;
1006 if (currnode.is_leaf()) {
1008 const auto begin_prim_id = currnode.index.first_id();
1009 const auto end_prim_id = begin_prim_id + currnode.index.prim_count();
1011 for (
auto p_id = begin_prim_id; p_id < end_prim_id; p_id++) {
1012 const auto object_id = mybvh->prim_ids[p_id];
1016 if (pnode->IsMatchingState(nav)) {
1020 auto object =
fVolume->GetNode(object_id);
1022 auto thissafety =
object->Safety(point,
false);
1031 if (thissafety < smallest_safety) {
1032 smallest_safety = std::max(0., thissafety);
1033 smallest_safety_sq = smallest_safety * smallest_safety;
1039 const auto leftchild_id = currnode.index.first_id();
1040 const auto rightchild_id = leftchild_id + 1;
1042 for (
size_t childid : {leftchild_id, rightchild_id}) {
1043 if (childid >= mybvh->nodes.size()) {
1047 const auto &node = mybvh->nodes[childid];
1048 const auto inside =
contains(node.get_bbox(), testpoint);
1052 queue.push(BVHPrioElement{childid, -1.});
1054 auto safety_to_node_square =
SafetySqToNode(node.get_bbox(), testpoint);
1055 if (safety_to_node_square <= smallest_safety_sq) {
1057 queue.push(BVHPrioElement{childid, safety_to_node_square});
1063 if (queue.size() > 0) {
1064 auto currElement = queue.top();
1065 currnode = mybvh->nodes[currElement.bvh_node_id];
1066 current_safety_to_node_sq = currElement.value;
1071 }
while (current_safety_to_node_sq <= smallest_safety_sq);
1073 const auto s = std::max(0.,
double(smallest_safety));
1100 for (
Int_t id = 0;
id < nd;
id++) {
1103 Double_t dxyz0 = std::abs(point[0] - boxes[ist + 3]) - boxes[ist];
1106 Double_t dxyz1 = std::abs(point[1] - boxes[ist + 4]) - boxes[ist + 1];
1109 Double_t dxyz2 = std::abs(point[2] - boxes[ist + 5]) - boxes[ist + 2];
1113 dxyz += dxyz0 * dxyz0;
1115 dxyz += dxyz1 * dxyz1;
1117 dxyz += dxyz2 * dxyz2;
1118 if (dxyz >= safe * safe)
1127 current =
fVolume->GetNode(
id);
1131 if (safnext < tolerance)
1159 for (
Int_t id = 0;
id < nd;
id++) {
1160 auto current =
fVolume->GetNode(
id);
1161 current->MasterToLocal(point, local);
1162 if (current->GetVolume()->GetShape()->Contains(local)) {
1166 safnext = current->GetVolume()->GetShape()->Safety(local,
kFALSE);
1168 if (safnext < tolerance) {
1171 if (safnext < safe) {
1199 using Scalar = float;
1204 size_t leaf_count = 0;
1205 std::function<
bool(
Node const &)> checkNode = [&](
Node const &nde) ->
bool {
1206 if (nde.is_leaf()) {
1207 leaf_count += nde.index.prim_count();
1208 return nde.index.prim_count() > 0;
1212 auto thisbb = nde.get_bbox();
1214 auto leftindex = nde.index.first_id();
1215 auto rightindex = leftindex + 1;
1217 auto leftnode = mybvh->nodes[leftindex];
1218 auto rightnode = mybvh->nodes[rightindex];
1220 auto leftbb = leftnode.get_bbox();
1221 auto rightbb = rightnode.get_bbox();
1225 auto tmi = thisbb.min;
1226 auto lmi = leftbb.min;
1227 auto rmi = rightbb.min;
1229 auto check1 = lmi[0] >= tmi[0] && lmi[1] >= tmi[1] && lmi[2] >= tmi[2];
1230 auto check2 = rmi[0] >= tmi[0] && rmi[1] >= tmi[1] && rmi[2] >= tmi[2];
1232 auto tma = thisbb.max;
1233 auto lma = leftbb.max;
1234 auto rma = rightbb.max;
1236 auto check3 = lma[0] <= tma[0] && lma[1] <= tma[1] && lma[2] <= tma[2];
1237 auto check4 = rma[0] <= tma[0] && rma[1] <= tma[1] && rma[2] <= tma[2];
1239 auto check = check1 && check2 && check3 && check4;
1241 return checkNode(leftnode) && checkNode(rightnode) && check;
1244 auto check = checkNode(mybvh->nodes[0]);
1245 return check && leaf_count == expected_leaf_count;
1253 using Scalar = float;
1262 memcpy(master, local, 3 *
sizeof(
Double_t));
1269 auto GetBoundingBoxInMother = [DaughterToMother](
TGeoNode const *node) {
1274 box->SetBoxPoints(&vert[0]);
1275 for (
Int_t point = 0; point < 8; point++) {
1276 DaughterToMother(node, &vert[3 * point], &
pt[0]);
1278 xyz[0] = xyz[1] =
pt[0];
1279 xyz[2] = xyz[3] =
pt[1];
1280 xyz[4] = xyz[5] =
pt[2];
1283 for (
Int_t j = 0; j < 3; j++) {
1284 if (
pt[j] < xyz[2 * j]) {
1287 if (
pt[j] > xyz[2 * j + 1]) {
1288 xyz[2 * j + 1] =
pt[j];
1293 bbox.min[0] = std::min(xyz[1], xyz[0]) - 0.001f;
1294 bbox.min[1] = std::min(xyz[3], xyz[2]) - 0.001f;
1295 bbox.min[2] = std::min(xyz[5], xyz[4]) - 0.001f;
1296 bbox.max[0] = std::max(xyz[0], xyz[1]) + 0.001f;
1297 bbox.max[1] = std::max(xyz[2], xyz[3]) + 0.001f;
1298 bbox.max[2] = std::max(xyz[4], xyz[5]) + 0.001f;
1304 auto bboxes_ptr =
new std::vector<BBox>();
1306 auto &bboxes = *bboxes_ptr;
1307 std::vector<Vec3> centers;
1309 int nd =
fVolume->GetNdaughters();
1310 for (
int i = 0; i < nd; ++i) {
1311 auto node =
fVolume->GetNode(i);
1313 (bboxes).push_back(GetBoundingBoxInMother(node));
1314 centers.emplace_back((bboxes).back().get_center());
1327 auto bvhptr =
new Bvh;
1328 *bvhptr = std::move(
bvh);
1329 fBVH = (
void *)(bvhptr);
1333 Error(
"BuildBVH",
"BVH corrupted\n");
1335 Info(
"BuildBVH",
"BVH good\n");
1340 const auto &topBB = bvhptr->get_root().get_bbox();
1341 int N = std::cbrt(bboxes.size()) + 1;
1343 double Lx = (topBB.max[0] - topBB.min[0]) /
N;
1344 double Ly = (topBB.max[1] - topBB.min[1]) /
N;
1345 double Lz = (topBB.max[2] - topBB.min[2]) /
N;
1355 topBB.max[1], topBB.max[2], Lx, Ly, Lz);
1363 static bool done =
false;
1373 std::vector<int> candidates1;
1374 std::vector<int> candidates2;
1376 for (
int i = 0; i < NX; ++i) {
1377 for (
int j = 0; j < NY; ++j) {
1378 for (
int k = 0; k < NZ; ++k) {
1386 candidates1.clear();
1387 candidates2.clear();
1388 double point[3] = {mp[0], mp[1], mp[2]};
1389 auto [encl_Rmax_sq_1, min_safety_sq_1] =
1391 auto [encl_Rmax_sq_2, min_safety_sq_2] =
1393 if (candidates1.size() != candidates2.size()) {
1394 std::cerr <<
" i " << i <<
" " << j <<
" " << k <<
" RMAX 2 (BVH) " << encl_Rmax_sq_1 <<
" CANDSIZE "
1395 << candidates1.size() <<
" RMAX (LOOP) " << encl_Rmax_sq_2 <<
" CANDSIZE "
1396 << candidates2.size() <<
"\n";
1400 bool same_test1 =
true;
1401 for (
auto &
id : candidates1) {
1402 auto ok = std::find(candidates2.begin(), candidates2.end(),
id) != candidates2.end();
1408 bool same_test2 =
true;
1409 for (
auto &
id : candidates2) {
1410 auto ok = std::find(candidates1.begin(), candidates1.end(),
id) != candidates1.end();
1416 if (!(same_test1 && same_test2)) {
1417 Error(
"VoxelTest",
"Same test fails %d %d", same_test1, same_test2);
int Int_t
Signed integer 4 bytes (int).
bool Bool_t
Boolean (0=false, 1=true) (bool).
double Double_t
Double 8 bytes.
const char Option_t
Option string (const char).
Matrix class used for computing global transformations Should NOT be used for node definition.
The manager class for any TGeo geometry.
static Int_t GetVerboseLevel()
Set verbosity level (static function).
Geometrical transformation package.
virtual void LocalToMaster(const Double_t *local, Double_t *master) const
convert a point by multiplying its column vector (x, y, z, 1) to matrix inverse
Class providing navigation API for TGeo geometries.
TGeoVolume * GetCurrentVolume() const
TGeoNodeCache * GetCache() const
Special pool of reusable nodes.
TGeoStateInfo * GetMakePWInfo(Int_t nd)
Get the PW info, if none create one.
A node represent a volume positioned inside another.They store links to both volumes and to the TGeoM...
TGeoVolume * GetVolume() const
virtual TGeoMatrix * GetMatrix() const =0
virtual void MasterToLocal(const Double_t *master, Double_t *local) const
Convert the point coordinates from mother reference to local reference system.
virtual void MasterToLocalVect(const Double_t *master, Double_t *local) const
Convert a vector from mother reference to local reference system.
TGeoManager * fGeoManager
Double_t SafetyBVH(Double_t point[3], Double_t safmax=1.E30)
Compute safety for the parallel world (using pure BVH traversal, mainly for debugging/fallback since ...
std::pair< double, double > GetBVHSafetyCandidates(double point[3], std::vector< int > &candidates, double margin=0.) const
Method to find potentially relevant candidate bounding boxes for safety calculation given a point.
void Draw(Option_t *option) override
Draw the parallel world.
TObjArray * fPhysical
! array of physical nodes
TGeoPhysicalNode * FindNodeOrig(Double_t point[3])
Finds physical node containing the point (original version based on TGeoVoxelFinder).
Bool_t CloseGeometry()
The main geometry must be closed.
void AddNode(const char *path)
Add a node normally to this world. Overlapping nodes not allowed.
void ResetOverlaps() const
Reset overlapflag for all volumes in geometry.
std::vector< unsigned int > fSafetyCandidateStore
!
TGeoPhysicalNode * FindNodeBVH(Double_t point[3])
Finds physical node containing the point.
void * fBoundingBoxes
! to keep the vector of primitive axis aligned bounding boxes
TGeoPhysicalNode * FindNextBoundaryLoop(Double_t point[3], Double_t dir[3], Double_t &step, Double_t stepmax=1.E30)
Same functionality as TGeoNavigator::FindNextDaughterBoundary for the parallel world in a trivial loo...
TGeoVoxelGrid< SafetyVoxelInfo > * fSafetyVoxelCache
! A regular 3D cache layer for fast point-based safety lookups
bool CheckBVH(void *, size_t) const
Check/validate the BVH acceleration structure.
~TGeoParallelWorld() override
Destructor.
TGeoVolume * fVolume
! helper volume
Double_t SafetyLoop(Double_t point[3], Double_t safmax=1.E30)
Compute safety for the parallel world (trivial loop version for comparison/debugging).
Int_t PrintDetectedOverlaps() const
Print the overlaps which were detected during real tracking.
TGeoPhysicalNode * FindNextBoundaryBVH(Double_t point[3], Double_t dir[3], Double_t &step, Double_t stepmax=1.E30)
Same functionality as TGeoNavigator::FindNextDaughterBoundary for the parallel world.
void CheckOverlaps(Double_t ovlp=0.001)
Check overlaps within a tolerance value.
std::pair< double, double > GetLoopSafetyCandidates(double point[3], std::vector< int > &candidates, double margin=0.) const
Method to find potentially relevant candidate bounding boxes for safety calculation given a point.
TGeoPhysicalNode * fLastState
! Last PN touched
Double_t SafetyOrig(Double_t point[3], Double_t safmax=1.E30)
Compute safety for the parallel world (original version based on TGeoVoxelFinder).
void AddOverlap(TGeoVolume *vol, Bool_t activate=kTRUE)
To use this optimization, the user should declare the full list of volumes which may overlap with any...
void RefreshPhysicalNodes()
Refresh the node pointers and re-voxelize.
TGeoPhysicalNode * FindNodeLoop(Double_t point[3])
Finds physical node containing the point using simple algorithm (for debugging).
Bool_t fIsClosed
! Closed flag
AccelerationMode fAccMode
! switch between different algorithm implementations
void InitSafetyVoxel(TGeoVoxelGridIndex const &)
Method to initialize the safety voxel at a specific 3D voxel (grid) index.
void * fBVH
! BVH helper structure for safety and navigation
void BuildBVH()
Build the BVH acceleration structure.
Double_t VoxelSafety(Double_t point[3], Double_t safmax=1.E30)
Compute safety for the parallel world used BVH structure with addiditional on-the-fly 3D grid/voxel c...
TGeoPhysicalNode * FindNextBoundaryOrig(Double_t point[3], Double_t dir[3], Double_t &step, Double_t stepmax=1.E30)
Same functionality as TGeoNavigator::FindNextDaughterBoundary for the parallel world.
void PrintBVH() const
Prints the BVH.
Physical nodes are the actual 'touchable' objects in the geometry, representing a path of positioned ...
Bool_t IsMatchingState(TGeoNavigator *nav) const
Checks if a given navigator state matches this physical node.
TGeoHMatrix * GetMatrix(Int_t level=-1) const
Return global matrix for node at LEVEL.
TGeoVolume * GetVolume(Int_t level=-1) const
Return volume associated with node at LEVEL in the branch.
virtual Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const =0
virtual Double_t DistFromOutside(const Double_t *point, const Double_t *dir, Int_t iact=1, Double_t step=TGeoShape::Big(), Double_t *safe=nullptr) const =0
static Double_t Tolerance()
TGeoVolume, TGeoVolumeMulti, TGeoVolumeAssembly are the volume classes.
Bool_t Contains(const Double_t *point) const
TGeoShape * GetShape() const
void SetOverlappingCandidate(Bool_t flag)
Bool_t IsOverlappingCandidate() const
Finder class handling voxels.
Double_t * GetBoxes() const
virtual Int_t * GetCheckList(const Double_t *point, Int_t &nelem, TGeoStateInfo &td)
get the list of daughter indices for which point is inside their bbox
virtual Int_t * GetNextVoxel(const Double_t *point, const Double_t *dir, Int_t &ncheck, TGeoStateInfo &td)
get the list of new candidates for the next voxel crossed by current ray printf("### GetNextVoxel\n")...
Bool_t IsSafeVoxel(const Double_t *point, Int_t inode, Double_t minsafe) const
Computes squared distance from POINT to the voxel(s) containing node INODE.
virtual void SortCrossedVoxels(const Double_t *point, const Double_t *dir, TGeoStateInfo &td)
get the list in the next voxel crossed by a ray
A finite 3D grid structure, mapping/binning arbitrary 3D cartesian points onto discrete "voxels".
const char * GetName() const override
Returns name of object.
Collectable string class.
const char * GetName() const override
Returns name of object.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Double_t RealTime()
Stop the stopwatch (if it is running) and return the realtime (in seconds) passed between the start a...
void Start(Bool_t reset=kTRUE)
Start the stopwatch.
void Stop()
Stop the stopwatch.
static BVH_ALWAYS_INLINE Bvh< Node > build(ThreadPool &thread_pool, std::span< const BBox > bboxes, std::span< const Vec > centers, const Config &config={})
Build a BVH in parallel using the given thread pool.
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Statefull info for the current geometry level.
Quality quality
The quality of the BVH produced by the builder.
Growing stack that can be used for BVH traversal.
Binary BVH node, containing its bounds and an index into its children or the primitives it contains.
BVH_ALWAYS_INLINE BBox< T, Dim > get_bbox() const