83 Fatal(
"AddNode",
"Cannot add nodes to a closed parallel geometry");
85 Error(
"AddNode",
"Path %s not valid.\nCannot add to parallel world!", path);
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");
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");
215 Info(
"RefreshPhysicalNodes",
"Initializing BVH took %f seconds",
timer.RealTime());
223 Info(
"RefreshPhysicalNodes",
"Voxelization took %f seconds",
timer.RealTime());
238 Fatal(
"FindNode",
"Parallel geometry must be closed first");
241 using Scalar = float;
260 auto contains = [](
const Node &node,
const Vec3 &
p) {
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) {
274 object->MasterToLocal(point,
lpoint);
284 auto root =
mybvh->nodes[0];
311 Fatal(
"FindNode",
"Parallel geometry must be closed first");
328 for (
id = 0;
id <
ncheck;
id++) {
346 Fatal(
"FindNode",
"Parallel geometry must be closed first");
348 for (
int id = 0;
id < nd;
id++) {
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) {
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");
403 if (
fUseOverlaps && !
nav->GetCurrentVolume()->IsOverlappingCandidate()) {
413 using Scalar = float;
422 Error(
"FindNextBoundary",
"Cannot perform safety; No BVH initialized");
427 float epsilon = std::numeric_limits<float>::epsilon() * std::fabs(
orig);
429 return static_cast<float>(
orig + epsilon);
461 Vec3(dir[0], dir[1], dir[2]),
484 object->MasterToLocal(point,
lpoint);
485 object->MasterToLocalVect(dir,
ldir);
512 Fatal(
"FindNextBoundary",
"Parallel geometry must be closed first");
516 if (
fUseOverlaps && !
nav->GetCurrentVolume()->IsOverlappingCandidate())
536 for (i = 0; i < nd; i++) {
571 for (i = 0; i <
ncheck; i++) {
581 if (
snext < step - 1.E-8) {
589 if (!
fUseOverlaps && !
nav->GetCurrentVolume()->IsOverlappingCandidate()) {
608 Fatal(
"FindNextBoundary",
"Parallel geometry must be closed first");
613 if (
fUseOverlaps && !
nav->GetCurrentVolume()->IsOverlappingCandidate()) {
624 for (
int i = 0; i < nd; ++i) {
629 object->MasterToLocal(point,
lpoint);
630 object->MasterToLocalVect(dir,
ldir);
631 auto thisstep =
object->GetVolume()->GetShape()->DistFromOutside(
lpoint,
ldir, 3, 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>,
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);
693 for (
size_t i = 0; i < bboxes.size(); ++i) {
694 const auto &
thisbox = bboxes[i];
700 queue.emplace(BVHPrioElement{i,
safety_sq});
713 if (queue.size() > 0) {
714 auto el = queue.top();
719 if (queue.size() > 0) {
734std::pair<double, double>
743 using Scalar = float;
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);
806 const auto &
thisbbox = node.get_bbox();
816 if (queue.size() > 0) {
854 const std::lock_guard<std::mutex> lock(
g_mutex);
892 if (
fUseOverlaps && !
nav->GetCurrentVolume()->IsOverlappingCandidate()) {
919 for (
int i = 0; i < 3; ++i) {
930 using Scalar = float;
934 auto &bboxes = (*bboxes_ptr);
942 const auto &bbox = bboxes[
cand_id];
970 if (
fUseOverlaps && !
nav->GetCurrentVolume()->IsOverlappingCandidate()) {
978 using Scalar = float;
999 auto cmp = [](BVHPrioElement
a, BVHPrioElement
b) {
return a.value >
b.value; };
1000 static thread_local BVHPrioQueue<
decltype(cmp)> queue(cmp);
1022 auto thissafety =
object->Safety(point,
false);
1048 const auto inside = contains(node.get_bbox(),
testpoint);
1052 queue.push(BVHPrioElement{
childid, -1.});
1063 if (queue.size() > 0) {
1088 if (
fUseOverlaps && !
nav->GetCurrentVolume()->IsOverlappingCandidate())
1100 for (
Int_t id = 0;
id < nd;
id++) {
1150 if (
fUseOverlaps && !
nav->GetCurrentVolume()->IsOverlappingCandidate())
1159 for (
Int_t id = 0;
id < nd;
id++) {
1162 if (current->GetVolume()->GetShape()->Contains(
local)) {
1199 using Scalar = float;
1206 if (
nde.is_leaf()) {
1208 return nde.index.prim_count() > 0;
1253 using Scalar = float;
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];
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;
1307 std::vector<Vec3> centers;
1310 for (
int i = 0; i < nd; ++i) {
1314 centers.emplace_back((bboxes).back().get_center());
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;
1363 static bool done =
false;
1376 for (
int i = 0; i <
NX; ++i) {
1377 for (
int j = 0;
j <
NY; ++
j) {
1378 for (
int k = 0; k <
NZ; ++k) {
1388 double point[3] = {
mp[0],
mp[1],
mp[2]};
1394 std::cerr <<
" i " << i <<
" " <<
j <<
" " << k <<
" RMAX 2 (BVH) " <<
encl_Rmax_sq_1 <<
" CANDSIZE "
const char Option_t
Option string (const char)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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
const_iterator begin() const
const_iterator end() const
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.
Class providing navigation API for TGeo geometries.
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
! stores bounding boxes serving a quick safety candidates (to be ! used with the VoxelGrid and Safety...
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.
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="")
Overlap checking tool. Check for illegal overlaps within a limit OVLP.
void SetOverlappingCandidate(Bool_t flag)
Bool_t IsOverlappingCandidate() const
Finder class handling 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.
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.
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)
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