1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
|
/// \file NavStateIndex.cpp
/// \author Andrei Gheata (andrei.gheata@cern.ch)
/// \date 14.05.2020
#include "VecGeom/navigation/NavStateIndex.h"
#include <iostream>
#include <list>
#include <sstream>
#ifdef VECGEOM_ROOT
#include "VecGeom/management/RootGeoManager.h"
#include "TGeoBranchArray.h"
#include "TGeoNode.h"
#include "TGeoManager.h"
#endif
namespace vecgeom {
inline namespace VECGEOM_IMPL_NAMESPACE {
// returning a "delta" transformation that can transform
// coordinates given in reference frame of this->Top() to the reference frame of other->Top()
// simply with otherlocalcoordinate = delta.Transform( thislocalcoordinate )
VECCORE_ATT_HOST_DEVICE
void NavStateIndex::DeltaTransformation(NavStateIndex const &other, Transformation3D &delta) const
{
Transformation3D g2;
Transformation3D g1;
other.TopMatrix(g2);
this->TopMatrix(g1);
g1.Inverse(delta);
// Trans/rot properties already correctly set
// g2.SetProperties();
// delta.SetProperties();
delta.FixZeroes();
delta.MultiplyFromRight(g2);
delta.FixZeroes();
}
void NavStateIndex::GetPathAsListOfIndices(std::list<uint> &indices) const
{
indices.clear();
if (IsOutside()) return;
auto nav_ind = fNavInd;
while (nav_ind > 1) {
auto pvol = TopImpl(nav_ind);
indices.push_front(pvol->GetChildId());
nav_ind = PopImpl(nav_ind);
}
// Paths start always with 0
indices.push_front(0);
}
VECCORE_ATT_HOST_DEVICE
void NavStateIndex::Print() const
{
if (IsOutside()) {
printf("NavStateIndex: Outside setup\n");
return;
}
auto level = GetLevel();
printf("NavStateIndex: navInd=%u, level=%u/%u, onBoundary=%s, path=<", fNavInd, level, GetMaxLevel(),
(fOnBoundary ? "true" : "false"));
for (int i = 0; i < level + 1; ++i) {
#ifndef VECCORE_CUDA
auto vol = At(i);
printf("/%s", vol ? vol->GetLabel().c_str() : "NULL");
#else
auto nav_ind = GetNavIndexImpl(fNavInd, i);
printf("/%u", nav_ind);
#endif
}
printf(">\n");
}
void NavStateIndex::ResetPathFromListOfIndices(VPlacedVolume const *world, std::list<uint> const &indices)
{
// clear current nav state
Clear();
auto vol = world;
int counter = 0;
for (auto id : indices) {
if (counter > 0) vol = vol->GetDaughters().operator[](id);
Push(vol);
counter++;
}
}
std::string NavStateIndex::RelativePath(NavStateIndex const &other) const
{
int lastcommonlevel = -1;
int thislevel = GetLevel();
int otherlevel = other.GetLevel();
int maxlevel = Min(thislevel, otherlevel);
std::stringstream str;
// algorithm: start on top and go down until paths split
for (int i = 0; i < maxlevel + 1; i++) {
if (this->At(i) == other.At(i)) {
lastcommonlevel = i;
} else {
break;
}
}
// paths are the same
if (thislevel == lastcommonlevel && otherlevel == lastcommonlevel) {
return std::string("");
}
// emit only ups
if (thislevel > lastcommonlevel && otherlevel == lastcommonlevel) {
for (int i = 0; i < thislevel - lastcommonlevel; ++i) {
str << "/up";
}
return str.str();
}
// emit only downs
if (thislevel == lastcommonlevel && otherlevel > lastcommonlevel) {
for (int i = lastcommonlevel + 1; i <= otherlevel; ++i) {
str << "/down";
str << "/" << other.ValueAt(i);
}
return str.str();
}
// mixed case: first up; then down
if (thislevel > lastcommonlevel && otherlevel > lastcommonlevel) {
// emit ups
int level = thislevel;
for (; level > lastcommonlevel + 1; --level) {
str << "/up";
}
level = lastcommonlevel + 1;
// emit horiz ( exists when there is a turning point )
int delta = other.ValueAt(level) - this->ValueAt(level);
if (delta != 0) str << "/horiz/" << delta;
level++;
// emit downs with index
for (; level <= otherlevel; ++level) {
str << "/down/" << other.ValueAt(level);
}
}
return str.str();
}
VECCORE_ATT_HOST_DEVICE
int NavStateIndex::Distance(NavStateIndex const &other) const
{
int lastcommonlevel = -1;
int thislevel = GetLevel();
int otherlevel = other.GetLevel();
int maxlevel = Min(thislevel, otherlevel);
// algorithm: start on top and go down until paths split
for (int i = 0; i < maxlevel + 1; i++) {
if (this->At(i) == other.At(i)) {
lastcommonlevel = i;
} else {
break;
}
}
return (thislevel - lastcommonlevel) + (otherlevel - lastcommonlevel);
}
#ifdef VECGEOM_ROOT
TGeoBranchArray *NavStateIndex::ToTGeoBranchArray() const
{
// attention: the counting of levels is different: fLevel=0 means that
// this is a branch which is filled at level zero
// my counting is a bit different: it tells the NUMBER of levels which are filled
#if ROOT_VERSION_CODE >= ROOT_VERSION(5, 34, 23)
TGeoBranchArray *tmp = TGeoBranchArray::MakeInstance(GetMaxLevel());
#else
TGeoBranchArray *tmp = new TGeoBranchArray(GetMaxLevel());
#endif
// gain access to array
TGeoNode **array = tmp->GetArray();
RootGeoManager &mg = RootGeoManager::Instance();
TGeoNavigator *nav = gGeoManager->GetCurrentNavigator();
tmp->InitFromNavigator(nav);
// tmp->
int level = GetLevel();
for (int i = 0; i < level + 1; ++i)
array[i] = const_cast<TGeoNode *>(mg.tgeonode(At(level)));
return tmp;
}
NavStateIndex &NavStateIndex::operator=(TGeoBranchArray const &other)
{
// attention: the counting of levels is different: fLevel=0 means that
// this is a branch which is filled at level zero
Clear();
RootGeoManager &mg = RootGeoManager::Instance();
assert(other.GetLevel() <= GetMaxLevel());
for (size_t i = 0; i < other.GetLevel(); ++i) {
Push(mg.GetPlacedVolume(other.GetNode(i)));
}
return *this;
}
#endif
} // namespace VECGEOM_IMPL_NAMESPACE
} // namespace vecgeom
|