43#pragma GCC diagnostic push
44#pragma GCC diagnostic ignored "-Wall"
45#pragma GCC diagnostic ignored "-Wshadow"
46#pragma GCC diagnostic ignored "-Wunknown-pragmas"
95 Fatal(
"AddNode",
"Cannot add nodes to a closed parallel geometry");
97 Error(
"AddNode",
"Path %s not valid.\nCannot add to parallel world!", path);
127 if (!strcmp(vol->
GetName(), volname))
143 Info(
"PrintDetectedOverlaps",
"List of detected volumes overlapping with the PW");
170 Fatal(
"CloseGeometry",
"Main geometry must be closed first");
172 Error(
"CloseGeometry",
"List of paths is empty");
184 Info(
"CloseGeometry",
"Number of declared overlaps: %d", novlp);
186 Info(
"CloseGeometry",
"Parallel world will use declared overlaps");
188 Info(
"CloseGeometry",
"Parallel world will detect overlaps with other volumes");
226 if (verboselevel > 2) {
227 Info(
"RefreshPhysicalNodes",
"Initializing BVH took %f seconds", timer.
RealTime());
234 if (verboselevel > 2) {
235 Info(
"RefreshPhysicalNodes",
"Voxelization took %f seconds", timer.
RealTime());
248 Fatal(
"FindNode",
"Parallel geometry must be closed first");
251 using Scalar = float;
257 auto mybvh = (Bvh *)
fBVH;
260 Vec3 testpoint(point[0], point[1], point[2]);
268 size_t min_contained_object_id = std::numeric_limits<size_t>::max();
270 auto contains = [](
const Node &node,
const Vec3 &
p) {
271 auto box = node.get_bbox();
274 return (
p[0] >= min[0] &&
p[0] <= max[0]) && (
p[1] >= min[1] &&
p[1] <= max[1]) &&
275 (
p[2] >= min[2] &&
p[2] <= max[2]);
278 auto leaf_fn = [&](
size_t begin,
size_t end) {
279 for (
size_t prim_id = begin; prim_id < end; ++prim_id) {
280 auto objectid = mybvh->prim_ids[prim_id];
281 if (min_contained_object_id == std::numeric_limits<size_t>::max() || objectid < min_contained_object_id) {
284 object->MasterToLocal(point, lpoint);
285 if (
object->GetVolume()->Contains(lpoint)) {
287 min_contained_object_id = objectid;
294 auto root = mybvh->nodes[0];
296 if (!contains(root, testpoint)) {
300 constexpr bool earlyExit =
false;
301 mybvh->traverse_top_down<earlyExit>(root.index, stack, leaf_fn, [&](
const Node &left,
const Node &right) {
302 bool follow_left = contains(left, testpoint);
303 bool follow_right = contains(right, testpoint);
304 return std::make_tuple(follow_left, follow_right,
false);
321 Fatal(
"FindNode",
"Parallel geometry must be closed first");
338 for (
id = 0;
id < ncheck;
id++) {
356 Fatal(
"FindNode",
"Parallel geometry must be closed first");
358 for (
int id = 0;
id < nd;
id++) {
362 if (node->GetVolume()->Contains(local)) {
376 using Scalar = float;
381 auto mybvh = (Bvh *)
fBVH;
383 for (
size_t i = 0; i < mybvh->nodes.size(); ++i) {
384 const auto &
n = mybvh->
nodes[i];
385 auto bbox =
n.get_bbox();
389 if (
n.index.prim_count() > 0) {
390 objectid = mybvh->prim_ids[
n.index.first_id()];
392 std::cout <<
"NODE id" << i <<
" "
393 <<
" prim_count: " <<
n.index.prim_count() <<
" first_id " <<
n.index.first_id() <<
" object_id "
394 << objectid <<
" ( " << min[0] <<
" , " << min[1] <<
" , " << min[2] <<
")"
395 <<
" ( " << max[0] <<
" , " << max[1] <<
" , " << max[2] <<
")"
408 Fatal(
"FindNextBoundary",
"Parallel geometry must be closed first");
421 double local_step = stepmax;
423 using Scalar = float;
430 auto mybvh = (Bvh *)
fBVH;
432 Error(
"FindNextBoundary",
"Cannot perform safety; No BVH initialized");
436 auto truncate_roundup = [](
double orig) {
437 float epsilon = std::numeric_limits<float>::epsilon() * std::fabs(orig);
439 return static_cast<float>(orig + epsilon);
443 const auto topnode_bbox = mybvh->get_root().get_bbox();
444 if ((-point[0] + topnode_bbox.min[0]) > stepmax) {
448 if ((-point[1] + topnode_bbox.min[1]) > stepmax) {
452 if ((-point[2] + topnode_bbox.min[2]) > stepmax) {
456 if ((point[0] - topnode_bbox.max[0]) > stepmax) {
460 if ((point[1] - topnode_bbox.max[1]) > stepmax) {
464 if ((point[2] - topnode_bbox.max[2]) > stepmax) {
470 Ray ray(Vec3(point[0], point[1], point[2]),
471 Vec3(dir[0], dir[1], dir[2]),
473 truncate_roundup(local_step));
477 static constexpr bool use_robust_traversal =
true;
481 mybvh->intersect<
false, use_robust_traversal>(ray, mybvh->get_root().index, stack, [&](
size_t begin,
size_t end) {
482 for (
size_t prim_id = begin; prim_id < end; ++prim_id) {
483 auto objectid = mybvh->prim_ids[prim_id];
487 if (pnode->IsMatchingState(nav)) {
494 object->MasterToLocal(point, lpoint);
495 object->MasterToLocalVect(dir, ldir);
496 auto thisstep =
object->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, local_step);
497 if (thisstep < local_step) {
498 local_step = thisstep;
522 Fatal(
"FindNextBoundary",
"Parallel geometry must be closed first");
538 Int_t idaughter = -1;
546 for (i = 0; i < nd; i++) {
564 if (idaughter >= 0) {
573 Int_t sumchecked = 0;
574 Int_t *vlist =
nullptr;
580 while ((sumchecked < nd) && (vlist = voxels->
GetNextVoxel(point, dir, ncheck, info))) {
581 for (i = 0; i < ncheck; i++) {
591 if (snext < step - 1.E-8) {
593 idaughter = vlist[i];
596 if (idaughter >= 0) {
618 Fatal(
"FindNextBoundary",
"Parallel geometry must be closed first");
634 for (
int i = 0; i < nd; ++i) {
639 object->MasterToLocal(point, lpoint);
640 object->MasterToLocalVect(dir, ldir);
641 auto thisstep =
object->GetVolume()->GetShape()->DistFromOutside(lpoint, ldir, 3, step);
642 if (thisstep < step) {
664 return (
p[0] >= min[0] &&
p[0] <= max[0]) && (
p[1] >= min[1] &&
p[1] <= max[1]) &&
665 (
p[2] >= min[2] &&
p[2] <= max[2]);
673 const auto minCorner =
box.min;
674 const auto maxCorner =
box.max;
677 const std::array<bvh::v2::Vec<T, 3>, 8> corners{
678 Vec3{minCorner[0], minCorner[1], minCorner[2]}, Vec3{minCorner[0], minCorner[1], maxCorner[2]},
679 Vec3{minCorner[0], maxCorner[1], minCorner[2]}, Vec3{minCorner[0], maxCorner[1], maxCorner[2]},
680 Vec3{maxCorner[0], minCorner[1], minCorner[2]}, Vec3{maxCorner[0], minCorner[1], maxCorner[2]},
681 Vec3{maxCorner[0], maxCorner[1], minCorner[2]}, Vec3{maxCorner[0], maxCorner[1], maxCorner[2]}};
684 for (
const auto &corner : corners) {
686 const auto dx = corner[0] -
p[0];
688 const auto dy = corner[1] -
p[1];
690 const auto dz = corner[2] -
p[2];
692 Rmax_sq = std::max(Rmax_sq, R_sq);
702 for (
int i = 0; i < 3; i++) {
704 if (
v <
box.min[i]) {
705 sqDist += (
box.min[i] -
v) * (
box.min[i] -
v);
706 }
else if (
v >
box.max[i]) {
707 sqDist += (
v -
box.max[i]) * (
v -
box.max[i]);
716struct BVHPrioElement {
723template <
typename Comparator>
724class BVHPrioQueue :
public std::priority_queue<BVHPrioElement, std::vector<BVHPrioElement>, Comparator> {
726 using std::priority_queue<BVHPrioElement, std::vector<BVHPrioElement>,
727 Comparator>::priority_queue;
730 void clear() { this->
c.clear(); }
739std::pair<double, double>
747 using Scalar = float;
751 auto &bboxes = (*bboxes_ptr);
753 auto cmp = [](BVHPrioElement
a, BVHPrioElement
b) {
return a.value >
b.value; };
754 static thread_local BVHPrioQueue<
decltype(cmp)> queue(cmp);
758 Vec3 testpoint(point[0], point[1], point[2]);
759 float best_enclosing_R_sq = std::numeric_limits<float>::max();
760 for (
size_t i = 0; i < bboxes.size(); ++i) {
761 const auto &thisbox = bboxes[i];
762 auto safety_sq = SafetySqToNode(thisbox, testpoint);
763 const auto this_R_max_sq = RmaxSqToNode(thisbox, testpoint);
764 const auto inside = contains(thisbox, testpoint);
765 safety_sq = inside ? -1.f : safety_sq;
766 best_enclosing_R_sq = std::min(best_enclosing_R_sq, this_R_max_sq);
767 queue.emplace(BVHPrioElement{i, safety_sq});
772 float safety_sq_at_least = -1.f;
776 float best_enclosing_R = std::sqrt(best_enclosing_R_sq) + margin;
777 best_enclosing_R_sq = best_enclosing_R * best_enclosing_R;
780 if (queue.size() > 0) {
781 auto el = queue.top();
783 safety_sq_at_least = el.value;
784 while (el.value < best_enclosing_R_sq) {
785 candidates.emplace_back(el.bvh_node_id);
786 if (queue.size() > 0) {
794 return std::make_pair<double, double>(best_enclosing_R_sq, safety_sq_at_least);
801std::pair<double, double>
809 using Scalar = float;
817 auto mybvh = (Bvh *)
fBVH;
820 Vec3 testpoint(point[0], point[1], point[2]);
823 auto cmp = [](BVHPrioElement
a, BVHPrioElement
b) {
return a.value >
b.value; };
824 static thread_local BVHPrioQueue<
decltype(cmp)> queue(cmp);
826 static thread_local BVHPrioQueue<
decltype(cmp)> leaf_queue(cmp);
829 auto currnode = mybvh->nodes[0];
831 float best_enclosing_R_sq = std::numeric_limits<float>::max();
832 float best_enclosing_R_with_margin_sq = std::numeric_limits<float>::max();
833 float current_safety_sq = 0.f;
835 if (currnode.is_leaf()) {
837 const auto begin_prim_id = currnode.index.first_id();
838 const auto end_prim_id = begin_prim_id + currnode.index.prim_count();
839 for (
auto p_id = begin_prim_id; p_id < end_prim_id; p_id++) {
840 const auto object_id = mybvh->prim_ids[p_id];
843 const auto &leaf_bounding_box = (*bboxes)[object_id];
844 auto this_Rmax_sq = RmaxSqToNode(leaf_bounding_box, testpoint);
845 const bool inside = contains(leaf_bounding_box, testpoint);
846 const auto safety_sq = inside ? -1.f : SafetySqToNode(leaf_bounding_box, testpoint);
849 if (this_Rmax_sq < best_enclosing_R_sq) {
850 best_enclosing_R_sq = this_Rmax_sq;
851 const auto this_Rmax = std::sqrt(this_Rmax_sq);
852 best_enclosing_R_with_margin_sq = (this_Rmax + margin) * (this_Rmax + margin);
856 if (safety_sq <= best_enclosing_R_with_margin_sq) {
858 leaf_queue.emplace(BVHPrioElement{object_id, safety_sq});
864 const auto leftchild_id = currnode.index.first_id();
865 const auto rightchild_id = leftchild_id + 1;
867 for (
size_t childid : {leftchild_id, rightchild_id}) {
868 if (childid >= mybvh->nodes.size()) {
871 const auto &node = mybvh->nodes[childid];
872 const auto &thisbbox = node.get_bbox();
873 auto inside = contains(thisbbox, testpoint);
874 const auto this_safety_sq = inside ? -1.f : SafetySqToNode(thisbbox, testpoint);
875 if (this_safety_sq <= best_enclosing_R_with_margin_sq) {
877 queue.push(BVHPrioElement{childid, this_safety_sq});
882 if (queue.size() > 0) {
883 auto currElement = queue.top();
884 currnode = mybvh->nodes[currElement.bvh_node_id];
885 current_safety_sq = currElement.value;
890 }
while (current_safety_sq <= best_enclosing_R_with_margin_sq);
894 float safety_sq_at_least = -1.f;
895 if (leaf_queue.size() > 0) {
896 auto el = leaf_queue.top();
898 safety_sq_at_least = el.value;
899 while (el.value < best_enclosing_R_with_margin_sq) {
900 candidates.emplace_back(el.bvh_node_id);
901 if (leaf_queue.size() > 0) {
902 el = leaf_queue.top();
909 return std::make_pair<double, double>(best_enclosing_R_sq, safety_sq_at_least);
918 static std::mutex g_mutex;
920 const std::lock_guard<std::mutex> lock(g_mutex);
924 static std::vector<int> candidates;
926 double point[3] = {mpx, mpy, mpz};
927 auto [encl_Rmax_sq, min_safety_sq] =
932 voxelinfo->min_safety = std::sqrt(min_safety_sq);
934 voxelinfo->num_candidates = candidates.size();
969 double bestsafety = safe_max;
971 if (!voxelinfo.isInitialized()) {
976 if (voxelinfo.min_safety > 0) {
985 for (
int i = 0; i < 3; ++i) {
986 const auto d = (point[i] - midpoint[i]);
989 if (r_sq < voxelinfo.min_safety * voxelinfo.min_safety) {
991 return voxelinfo.min_safety - std::sqrt(r_sq);
995 using Scalar = float;
999 auto &bboxes = (*bboxes_ptr);
1000 Vec3 testpoint(point[0], point[1], point[2]);
1002 for (
size_t store_id = voxelinfo.idx_start; store_id < voxelinfo.idx_start + voxelinfo.num_candidates; ++store_id) {
1007 const auto &bbox = bboxes[cand_id];
1008 const auto bbox_safe_sq = SafetySqToNode(bbox, testpoint);
1009 if (bbox_safe_sq > bestsafety * bestsafety) {
1015 const auto thissafety = primitive_node->
Safety(point,
false);
1016 if (thissafety < bestsafety) {
1017 bestsafety = std::max(0., thissafety);
1039 float smallest_safety = safe_max;
1040 float smallest_safety_sq = smallest_safety * smallest_safety;
1042 using Scalar = float;
1048 auto mybvh = (Bvh *)
fBVH;
1051 Vec3 testpoint(point[0], point[1], point[2]);
1053 auto currnode = mybvh->nodes[0];
1055 bool outside_top = !::contains(currnode.get_bbox(), testpoint);
1056 const auto safety_sq_to_top = SafetySqToNode(currnode.get_bbox(), testpoint);
1057 if (outside_top && safety_sq_to_top > smallest_safety_sq) {
1059 return smallest_safety;
1063 auto cmp = [](BVHPrioElement
a, BVHPrioElement
b) {
return a.value >
b.value; };
1064 static thread_local BVHPrioQueue<
decltype(cmp)> queue(cmp);
1068 float current_safety_to_node_sq = outside_top ? safety_sq_to_top : 0.f;
1070 if (currnode.is_leaf()) {
1072 const auto begin_prim_id = currnode.index.first_id();
1073 const auto end_prim_id = begin_prim_id + currnode.index.prim_count();
1075 for (
auto p_id = begin_prim_id; p_id < end_prim_id; p_id++) {
1076 const auto object_id = mybvh->prim_ids[p_id];
1080 if (pnode->IsMatchingState(nav)) {
1086 auto thissafety =
object->
Safety(point,
false);
1095 if (thissafety < smallest_safety) {
1096 smallest_safety = std::max(0., thissafety);
1097 smallest_safety_sq = smallest_safety * smallest_safety;
1103 const auto leftchild_id = currnode.index.first_id();
1104 const auto rightchild_id = leftchild_id + 1;
1106 for (
size_t childid : {leftchild_id, rightchild_id}) {
1107 if (childid >= mybvh->nodes.size()) {
1111 const auto &node = mybvh->nodes[childid];
1112 const auto inside = contains(node.get_bbox(), testpoint);
1116 queue.push(BVHPrioElement{childid, -1.});
1118 auto safety_to_node_square = SafetySqToNode(node.get_bbox(), testpoint);
1119 if (safety_to_node_square <= smallest_safety_sq) {
1121 queue.push(BVHPrioElement{childid, safety_to_node_square});
1127 if (queue.size() > 0) {
1128 auto currElement = queue.top();
1129 currnode = mybvh->nodes[currElement.bvh_node_id];
1130 current_safety_to_node_sq = currElement.value;
1135 }
while (current_safety_to_node_sq <= smallest_safety_sq);
1137 const auto s = std::max(0.,
double(smallest_safety));
1164 for (
Int_t id = 0;
id < nd;
id++) {
1177 dxyz += dxyz0 * dxyz0;
1179 dxyz += dxyz1 * dxyz1;
1181 dxyz += dxyz2 * dxyz2;
1182 if (dxyz >= safe * safe)
1195 if (safnext < tolerance)
1223 for (
Int_t id = 0;
id < nd;
id++) {
1226 if (current->GetVolume()->GetShape()->Contains(local)) {
1230 safnext = current->GetVolume()->GetShape()->Safety(local,
kFALSE);
1232 if (safnext < tolerance) {
1235 if (safnext < safe) {
1263 using Scalar = float;
1266 auto mybvh = (Bvh *)
bvh;
1268 size_t leaf_count = 0;
1269 std::function<
bool(Node
const &)> checkNode = [&](Node
const &nde) ->
bool {
1270 if (nde.is_leaf()) {
1271 leaf_count += nde.index.prim_count();
1272 return nde.index.prim_count() > 0;
1276 auto thisbb = nde.get_bbox();
1278 auto leftindex = nde.index.first_id();
1279 auto rightindex = leftindex + 1;
1281 auto leftnode = mybvh->nodes[leftindex];
1282 auto rightnode = mybvh->nodes[rightindex];
1284 auto leftbb = leftnode.get_bbox();
1285 auto rightbb = rightnode.get_bbox();
1289 auto tmi = thisbb.min;
1290 auto lmi = leftbb.min;
1291 auto rmi = rightbb.min;
1293 auto check1 = lmi[0] >= tmi[0] && lmi[1] >= tmi[1] && lmi[2] >= tmi[2];
1294 auto check2 = rmi[0] >= tmi[0] && rmi[1] >= tmi[1] && rmi[2] >= tmi[2];
1296 auto tma = thisbb.max;
1297 auto lma = leftbb.max;
1298 auto rma = rightbb.max;
1300 auto check3 = lma[0] <= tma[0] && lma[1] <= tma[1] && lma[2] <= tma[2];
1301 auto check4 = rma[0] <= tma[0] && rma[1] <= tma[1] && rma[2] <= tma[2];
1303 auto check = check1 && check2 && check3 && check4;
1305 return checkNode(leftnode) && checkNode(rightnode) && check;
1308 auto check = checkNode(mybvh->nodes[0]);
1309 return check && leaf_count == expected_leaf_count;
1317 using Scalar = float;
1326 memcpy(master, local, 3 *
sizeof(
Double_t));
1333 auto GetBoundingBoxInMother = [DaughterToMother](
TGeoNode const *node) {
1338 box->SetBoxPoints(&vert[0]);
1339 for (
Int_t point = 0; point < 8; point++) {
1340 DaughterToMother(node, &vert[3 * point], &
pt[0]);
1342 xyz[0] = xyz[1] =
pt[0];
1343 xyz[2] = xyz[3] =
pt[1];
1344 xyz[4] = xyz[5] =
pt[2];
1347 for (
Int_t j = 0; j < 3; j++) {
1348 if (
pt[j] < xyz[2 * j]) {
1351 if (
pt[j] > xyz[2 * j + 1]) {
1352 xyz[2 * j + 1] =
pt[j];
1357 bbox.min[0] = std::min(xyz[1], xyz[0]) - 0.001f;
1358 bbox.min[1] = std::min(xyz[3], xyz[2]) - 0.001f;
1359 bbox.min[2] = std::min(xyz[5], xyz[4]) - 0.001f;
1360 bbox.max[0] = std::max(xyz[0], xyz[1]) + 0.001f;
1361 bbox.max[1] = std::max(xyz[2], xyz[3]) + 0.001f;
1362 bbox.max[2] = std::max(xyz[4], xyz[5]) + 0.001f;
1368 auto bboxes_ptr =
new std::vector<BBox>();
1370 auto &bboxes = *bboxes_ptr;
1371 std::vector<Vec3> centers;
1374 for (
int i = 0; i < nd; ++i) {
1377 (bboxes).push_back(GetBoundingBoxInMother(node));
1378 centers.emplace_back((bboxes).back().get_center());
1391 auto bvhptr =
new Bvh;
1392 *bvhptr = std::move(
bvh);
1393 fBVH = (
void *)(bvhptr);
1397 Error(
"BuildBVH",
"BVH corrupted\n");
1399 Info(
"BuildBVH",
"BVH good\n");
1404 const auto &topBB = bvhptr->get_root().get_bbox();
1405 int N = std::cbrt(bboxes.size()) + 1;
1407 double Lx = (topBB.max[0] - topBB.min[0]) /
N;
1408 double Ly = (topBB.max[1] - topBB.min[1]) /
N;
1409 double Lz = (topBB.max[2] - topBB.min[2]) /
N;
1419 topBB.max[1], topBB.max[2], Lx, Ly, Lz);
1427 static bool done =
false;
1437 std::vector<int> candidates1;
1438 std::vector<int> candidates2;
1440 for (
int i = 0; i < NX; ++i) {
1441 for (
int j = 0; j < NY; ++j) {
1442 for (
int k = 0; k < NZ; ++k) {
1450 candidates1.clear();
1451 candidates2.clear();
1452 double point[3] = {mp[0], mp[1], mp[2]};
1453 auto [encl_Rmax_sq_1, min_safety_sq_1] =
1455 auto [encl_Rmax_sq_2, min_safety_sq_2] =
1457 if (candidates1.size() != candidates2.size()) {
1458 std::cerr <<
" i " << i <<
" " << j <<
" " << k <<
" RMAX 2 (BVH) " << encl_Rmax_sq_1 <<
" CANDSIZE "
1459 << candidates1.size() <<
" RMAX (LOOP) " << encl_Rmax_sq_2 <<
" CANDSIZE "
1460 << candidates2.size() <<
"\n";
1464 bool same_test1 =
true;
1465 for (
auto &
id : candidates1) {
1466 auto ok = std::find(candidates2.begin(), candidates2.end(),
id) != candidates2.end();
1472 bool same_test2 =
true;
1473 for (
auto &
id : candidates2) {
1474 auto ok = std::find(candidates1.begin(), candidates1.end(),
id) != candidates1.end();
1480 if (!(same_test1 && same_test2)) {
1481 Error(
"VoxelTest",
"Same test fails %d %d", same_test1, same_test2);
1488#pragma GCC diagnostic pop
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Matrix class used for computing global transformations Should NOT be used for node definition.
The manager class for any TGeo geometry.
TObjArray * GetListOfVolumes() const
TGeoNavigator * GetCurrentNavigator() const
Returns current navigator for the calling thread.
Bool_t CheckPath(const char *path) const
Check if a geometry path is valid without changing the state of the current navigator.
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.
Double_t Safety(const Double_t *point, Bool_t in=kTRUE) const
computes the closest distance from given point to this shape
Base class for a flat parallel geometry.
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
Last PN touched.
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
A regular 3D cache layer for fast point-based safety lookups.
TGeoPhysicalNode * FindNodeBVH(Double_t point[3])
Finds physical node containing the point.
void * fBoundingBoxes
stores bounding boxes serving a quick safety candidates (to be used with the VoxelGrid and SafetyVoxe...
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
BVH helper structure for safety and navigation.
bool CheckBVH(void *, size_t) const
Check/validate the BVH acceleration structure.
~TGeoParallelWorld() override
Destructor.
TGeoVolume * fVolume
Closed flag.
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
helper volume
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)
AccelerationMode fAccMode
to keep the vector of primitive axis aligned bounding boxes
void InitSafetyVoxel(TGeoVoxelGridIndex const &)
Method to initialize the safety voxel at a specific 3D voxel (grid) index.
void * fBVH
array of physical nodes
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
virtual void ComputeBBox()=0
static Double_t Tolerance()
TGeoVolume, TGeoVolumeMulti, TGeoVolumeAssembly are the volume classes.
void Voxelize(Option_t *option)
build the voxels for this volume
Bool_t Contains(const Double_t *point) const
virtual TGeoNode * AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat=nullptr, Option_t *option="")
Add a TGeoNode to the list of nodes.
void Draw(Option_t *option="") override
draw top volume according to option
Int_t GetNdaughters() const
TGeoNode * GetNode(const char *name) const
get the pointer to a daughter node
TGeoVoxelFinder * GetVoxels() const
Getter for optimization structure.
TGeoShape * GetShape() const
void CheckOverlaps(Double_t ovlp=0.1, Option_t *option="") const
Overlap checking tool.
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".
The TNamed class is the base class for all named ROOT classes.
const char * GetName() const override
Returns name of object.
Int_t GetEntriesFast() const
void AddAt(TObject *obj, Int_t idx) override
Add object at position ids.
void Delete(Option_t *option="") override
Remove all objects from the array AND delete all heap based objects.
TObject * At(Int_t idx) const override
TObject * UncheckedAt(Int_t i) const
TObject * Remove(TObject *obj) override
Remove object from array.
void Add(TObject *obj) override
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.
This builder is only a wrapper around all the other builders, which selects the best builder dependin...
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)
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Statefull info for the current geometry level.
std::vector< Node > nodes
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.