14 #include <ROOT/RBrowserItem.hxx> 
   36 using namespace std::string_literals;
 
   42 namespace Experimental {
 
   45 class RGeomBrowserIter {
 
   47    REveGeomDescription &fDesc;
 
   52    std::vector<int> fStackParents;
 
   53    std::vector<int> fStackChilds;
 
   57    RGeomBrowserIter(REveGeomDescription &desc) : fDesc(desc) {}
 
   59    const std::string &GetName()
 const { 
return fDesc.fDesc[fNodeId].name; }
 
   61    bool IsValid()
 const { 
return fNodeId >= 0; }
 
   63    int GetNodeId()
 const { 
return fNodeId; }
 
   65    bool HasChilds()
 const { 
return (fNodeId < 0) ? 
true : fDesc.fDesc[fNodeId].chlds.size() > 0; }
 
   67    int NumChilds()
 const { 
return (fNodeId < 0) ? 1 : fDesc.fDesc[fNodeId].chlds.size(); }
 
   77       auto &node = fDesc.fDesc[fNodeId];
 
   78       if (node.chlds.size() == 0) 
return false;
 
   79       fStackParents.emplace_back(fParentId);
 
   80       fStackChilds.emplace_back(fChild);
 
   83       fNodeId = node.chlds[fChild];
 
   89       if (fStackParents.size() == 0) {
 
   93       fParentId = fStackParents.back();
 
   94       fChild = fStackChilds.back();
 
   96       fStackParents.pop_back();
 
   97       fStackChilds.pop_back();
 
  102          fNodeId = fDesc.fDesc[fParentId].chlds[fChild];
 
  110       if ((fNodeId <= 0) || (fParentId < 0)) {
 
  115       auto &prnt = fDesc.fDesc[fParentId];
 
  116       if (++fChild >= prnt.chlds.size()) {
 
  121       fNodeId = prnt.chlds[fChild];
 
  130       fStackParents.clear();
 
  131       fStackChilds.clear();
 
  138       if (Enter()) 
return true;
 
  140       if (Next()) 
return true;
 
  143          if (Next()) 
return true;
 
  151    bool Navigate(
const std::string &path)
 
  153       size_t pos = path.find(
"/");
 
  154       if (pos != 0) 
return false;
 
  158       while (++pos < path.length()) {
 
  161          pos = path.find(
"/", last);
 
  163          if (pos == std::string::npos) pos = path.length();
 
  165          std::string folder = path.substr(last, pos-last);
 
  167          if (!Enter()) 
return false;
 
  172             find = (folder.compare(GetName()) == 0);
 
  173          } 
while (!find && Next());
 
  175          if (!find) 
return false;
 
  182    std::vector<int> CurrentIds()
 const 
  184       std::vector<int> res;
 
  186          for (
unsigned n=1;n<fStackParents.size();++n)
 
  187             res.emplace_back(fStackParents[n]);
 
  188          if (fParentId >= 0) res.emplace_back(fParentId);
 
  189          res.emplace_back(fNodeId);
 
  207 void ROOT::Experimental::REveGeomDescription::PackMatrix(std::vector<float> &vect, TGeoMatrix *matr)
 
  211    if (!matr || matr->IsIdentity()) {
 
  215    auto trans = matr->GetTranslation();
 
  216    auto scale = matr->GetScale();
 
  217    auto rotate = matr->GetRotationMatrix();
 
  219    bool is_translate = matr->IsA() == TGeoTranslation::Class(),
 
  220         is_scale = matr->IsA() == TGeoScale::Class(),
 
  221         is_rotate = matr->IsA() == TGeoRotation::Class();
 
  223    if (!is_translate && !is_scale && !is_rotate) {
 
  226       auto test = [](
double val, 
double chk) { 
return (val==chk) || (TMath::Abs(val-chk) < 1e-20); };
 
  228       bool no_scale = test(scale[0],1) && test(scale[1],1) && test(scale[2],1);
 
  229       bool no_trans = test(trans[0],0) && test(trans[1],0) && test(trans[2],0);
 
  230       bool no_rotate = test(rotate[0],1) && test(rotate[1],0) && test(rotate[2],0) &&
 
  231                        test(rotate[3],0) && test(rotate[4],1) && test(rotate[5],0) &&
 
  232                        test(rotate[6],0) && test(rotate[7],0) && test(rotate[8],1);
 
  234       if (no_scale && no_trans && no_rotate)
 
  237       if (no_scale && no_trans && !no_rotate) {
 
  239       } 
else if (no_scale && !no_trans && no_rotate) {
 
  241       } 
else if (!no_scale && no_trans && no_rotate) {
 
  265       for (
int n=0;n<9;++n)
 
  271    vect[0] = rotate[0]; vect[4] = rotate[1]; vect[8]  = rotate[2]; vect[12] = trans[0];
 
  272    vect[1] = rotate[3]; vect[5] = rotate[4]; vect[9]  = rotate[5]; vect[13] = trans[1];
 
  273    vect[2] = rotate[6]; vect[6] = rotate[7]; vect[10] = rotate[8]; vect[14] = trans[2];
 
  274    vect[3] = 0;         vect[7] = 0;         vect[11] = 0;         vect[15] = 1;
 
  281 void ROOT::Experimental::REveGeomDescription::Build(TGeoManager *mgr, 
const std::string &volname)
 
  291    auto topnode = mgr->GetTopNode();
 
  292    if (!volname.empty()) {
 
  293       auto vol = mgr->GetVolume(volname.c_str());
 
  296          TGeoIterator next(mgr->GetTopVolume());
 
  297          while ((node=next())) {
 
  298             if (node->GetVolume() == vol) 
break;
 
  300          if (node) { topnode = node; printf(
"Find node with volume\n"); }
 
  308    int maxnodes = mgr->GetMaxVisNodes();
 
  310    SetNSegments(mgr->GetNsegments());
 
  311    SetVisLevel(mgr->GetVisLevel());
 
  312    SetMaxVisNodes(maxnodes);
 
  313    SetMaxVisFaces( (maxnodes > 5000 ? 5000 : (maxnodes < 1000 ? 1000 : maxnodes)) * 100);
 
  316    std::vector<int> numbers;
 
  317    int offset = 1000000000;
 
  320    TGeoNode *snode = topnode;
 
  321    TGeoIterator iter(topnode->GetVolume());
 
  324       if (snode->GetNumber() >= offset) {
 
  327          numbers.emplace_back(snode->GetNumber());
 
  328          snode->SetNumber(offset + fNodes.size()); 
 
  329          fNodes.emplace_back(snode);
 
  331    } 
while ((snode = iter()) != 
nullptr);
 
  333    fDesc.reserve(fNodes.size());
 
  334    numbers.reserve(fNodes.size());
 
  335    fSortMap.reserve(fNodes.size());
 
  338    std::vector<REveGeomNode *> sortarr;
 
  339    sortarr.reserve(fNodes.size());
 
  343    for (
auto &node: fNodes) {
 
  345       fDesc.emplace_back(node->GetNumber() - offset);
 
  346       auto &desc = fDesc[cnt++];
 
  348       sortarr.emplace_back(&desc);
 
  350       desc.name = node->GetName();
 
  352       auto shape = 
dynamic_cast<TGeoBBox *
>(node->GetVolume()->GetShape());
 
  354          desc.vol = shape->GetDX()*shape->GetDY()*shape->GetDZ();
 
  358       CopyMaterialProperties(node->GetVolume(), desc);
 
  360       auto chlds = node->GetNodes();
 
  362       PackMatrix(desc.matr, node->GetMatrix());
 
  365          for (
int n = 0; n <= chlds->GetLast(); ++n) {
 
  366             auto chld = 
dynamic_cast<TGeoNode *
> (chlds->At(n));
 
  367             desc.chlds.emplace_back(chld->GetNumber()-offset);
 
  373    for (
auto &node: fNodes)
 
  374       node->SetNumber(numbers[cnt++]);
 
  377    std::sort(sortarr.begin(), sortarr.end(), [](REveGeomNode *a, REveGeomNode * b) { 
return a->vol > b->vol; });
 
  380    for (
auto &elem: sortarr) {
 
  381       fSortMap.emplace_back(elem->id);
 
  382       elem->sortid = cnt++; 
 
  393 int ROOT::Experimental::REveGeomDescription::MarkVisible(
bool on_screen)
 
  395    int res = 0, cnt = 0;
 
  396    for (
auto &node: fNodes) {
 
  397       auto &desc = fDesc[cnt++];
 
  399       desc.nochlds = 
false;
 
  402          if (node->IsOnScreen())
 
  405          auto vol = node->GetVolume();
 
  407          if (vol->IsVisible() && !vol->TestAttBit(TGeoAtt::kVisNone))
 
  410          if (!node->IsVisDaughters())
 
  413          if ((desc.vis > 0) && (desc.chlds.size() > 0) && !desc.nochlds)
 
  417       if (desc.IsVisible() && desc.CanDisplay()) res++;
 
  426 void ROOT::Experimental::REveGeomDescription::ProduceIdShifts()
 
  428    for (
auto &node : fDesc)
 
  431    using ScanFunc_t = std::function<int(REveGeomNode &)>;
 
  433    ScanFunc_t scan_func = [&, 
this](REveGeomNode &node) {
 
  434       if (node.idshift < 0) {
 
  436          for(
auto id : node.chlds)
 
  437             node.idshift += scan_func(fDesc[
id]);
 
  440       return node.idshift + 1;
 
  443    if (fDesc.size() > 0)
 
  450 int ROOT::Experimental::REveGeomDescription::ScanNodes(
bool only_visible, 
int maxlvl, REveGeomScanFunc_t func)
 
  452    std::vector<int> stack;
 
  456    using ScanFunc_t = std::function<int(int, int)>;
 
  458    ScanFunc_t scan_func = [&, 
this](
int nodeid, 
int lvl) {
 
  459       auto &desc = fDesc[nodeid];
 
  462       if (desc.nochlds && (lvl > 0)) lvl = 0;
 
  465       bool is_visible = (lvl >= 0) && (desc.vis > lvl) && desc.CanDisplay();
 
  467       if (is_visible || !only_visible)
 
  468          if (func(desc, stack, is_visible, counter))
 
  473       if ((desc.chlds.size() > 0) && ((lvl > 0) || !only_visible)) {
 
  474          auto pos = stack.size();
 
  475          stack.emplace_back(0);
 
  476          for (
unsigned k = 0; k < desc.chlds.size(); ++k) {
 
  478             res += scan_func(desc.chlds[k], lvl - 1);
 
  482          counter += desc.idshift;
 
  488    if (!maxlvl && (GetVisLevel() > 0)) maxlvl = GetVisLevel();
 
  489    if (!maxlvl) maxlvl = 4;
 
  490    if (maxlvl > 97) maxlvl = 97; 
 
  492    return scan_func(0, maxlvl);
 
  498 void ROOT::Experimental::REveGeomDescription::CollectNodes(REveGeomDrawing &drawing)
 
  501    for (
auto &node : fDesc)
 
  502       node.useflag = 
false;
 
  506    drawing.numnodes = fDesc.size();
 
  508    for (
auto &item : drawing.visibles) {
 
  510       for (
auto &chindx : item.stack) {
 
  511          auto &node = fDesc[nodeid];
 
  514             drawing.nodes.emplace_back(&node);
 
  516          if (chindx >= (
int)node.chlds.size())
 
  518          nodeid = node.chlds[chindx];
 
  521       auto &node = fDesc[nodeid];
 
  524          drawing.nodes.emplace_back(&node);
 
  528    printf(
"SELECT NODES %d\n", (
int) drawing.nodes.size());
 
  535 std::string ROOT::Experimental::REveGeomDescription::ProcessBrowserRequest(
const std::string &msg)
 
  539    auto request = TBufferJSON::FromJSON<RBrowserRequest>(msg);
 
  542       request = std::make_unique<RBrowserRequest>();
 
  545       request->number = 100;
 
  551    if ((request->path.compare(
"/") == 0) && (request->first == 0) && (GetNumNodes() < (IsPreferredOffline() ? 1000000 : 1000))) {
 
  553       std::vector<REveGeomNodeBase *> vect(fDesc.size(), 
nullptr);
 
  556       for (
auto &item : fDesc)
 
  559       res = 
"DESCR:"s + TBufferJSON::ToJSON(&vect,GetJsonComp()).Data();
 
  562       RGeomBrowserIter iter(*
this);
 
  564       while (iter.NextNode())
 
  566       printf(
"Total number of valid nodes %d\n", nelements);
 
  569       std::vector<RBrowserItem> temp_nodes;
 
  570       bool toplevel = (request->path.compare(
"/") == 0);
 
  574       reply.path = request->path;
 
  575       reply.first = request->first;
 
  577       RGeomBrowserIter iter(*
this);
 
  578       if (iter.Navigate(request->path)) {
 
  580          reply.nchilds = iter.NumChilds();
 
  584             while ((request->first > 0) && iter.Next()) {
 
  588             while (iter.IsValid() && (request->number > 0)) {
 
  589                temp_nodes.emplace_back(iter.GetName(), iter.NumChilds());
 
  590                if (toplevel) temp_nodes.back().SetExpanded(
true);
 
  592                if (!iter.Next()) 
break;
 
  597       for (
auto &n : temp_nodes)
 
  598          reply.nodes.emplace_back(&n);
 
  600       res = 
"BREPL:"s + TBufferJSON::ToJSON(&reply, GetJsonComp()).Data();
 
  610 ROOT::Experimental::REveGeomDescription::ShapeDescr &ROOT::Experimental::REveGeomDescription::FindShapeDescr(TGeoShape *shape)
 
  612    for (
auto &descr : fShapes)
 
  613       if (descr.fShape == shape)
 
  616    fShapes.emplace_back(shape);
 
  617    auto &elem = fShapes.back();
 
  618    elem.id = fShapes.size() - 1;
 
  625 ROOT::Experimental::REveGeomDescription::ShapeDescr &
 
  626 ROOT::Experimental::REveGeomDescription::MakeShapeDescr(TGeoShape *shape)
 
  628    auto &elem = FindShapeDescr(shape);
 
  630    if (elem.nfaces == 0) {
 
  632       TGeoCompositeShape *comp = 
nullptr;
 
  635       if (shape->IsComposite()) {
 
  636          comp = 
dynamic_cast<TGeoCompositeShape *
>(shape);
 
  639       } 
else if (!shape->IsCylType()) {
 
  644       if (IsBuildShapes() < boundary) {
 
  646          elem.fShapeInfo.shape = shape;
 
  649          auto poly = std::make_unique<REveGeoPolyShape>();
 
  652             poly->BuildFromComposite(comp, GetNSegments());
 
  654             poly->BuildFromShape(shape, GetNSegments());
 
  659          poly->FillRenderData(rd);
 
  661          elem.nfaces = poly->GetNumFaces();
 
  663          elem.fRawInfo.raw.resize(rd.GetBinarySize());
 
  664          rd.Write( reinterpret_cast<char *>(elem.fRawInfo.raw.data()), elem.fRawInfo.raw.size() );
 
  665          elem.fRawInfo.sz[0] = rd.SizeV();
 
  666          elem.fRawInfo.sz[1] = rd.SizeN();
 
  667          elem.fRawInfo.sz[2] = rd.SizeI();
 
  678 void ROOT::Experimental::REveGeomDescription::CopyMaterialProperties(TGeoVolume *volume, REveGeomNode &node)
 
  682    TColor *col{
nullptr};
 
  684    if ((volume->GetFillColor() > 1) && (volume->GetLineColor() == 1))
 
  685       col = gROOT->GetColor(volume->GetFillColor());
 
  686    else if (volume->GetLineColor() >= 0)
 
  687       col = gROOT->GetColor(volume->GetLineColor());
 
  689    if (volume->GetMedium() && (volume->GetMedium() != TGeoVolume::DummyMedium()) && volume->GetMedium()->GetMaterial()) {
 
  690       auto material = volume->GetMedium()->GetMaterial();
 
  692       auto fillstyle = material->GetFillStyle();
 
  693       if ((fillstyle>=3000) && (fillstyle<=3100)) node.opacity = (3100 - fillstyle) / 100.;
 
  694       if (!col) col = gROOT->GetColor(material->GetFillColor());
 
  698       node.color = std::to_string((
int)(col->GetRed()*255)) + 
"," +
 
  699                    std::to_string((
int)(col->GetGreen()*255)) + 
"," +
 
  700                    std::to_string((
int)(col->GetBlue()*255));
 
  701       if (node.opacity == 1.)
 
  702          node.opacity = col->GetAlpha();
 
  711 void ROOT::Experimental::REveGeomDescription::ResetRndrInfos()
 
  713    for (
auto &s: fShapes)
 
  721 bool ROOT::Experimental::REveGeomDescription::CollectVisibles()
 
  723    std::vector<int> viscnt(fDesc.size(), 0);
 
  725    int level = GetVisLevel();
 
  728    int numnodes = ScanNodes(
true, level, [&viscnt](REveGeomNode &node, std::vector<int> &, 
bool, 
int) {
 
  733    if (GetMaxVisNodes() > 0) {
 
  734       while ((numnodes > GetMaxVisNodes()) && (level > 1)) {
 
  736          viscnt.assign(viscnt.size(), 0);
 
  737          numnodes = ScanNodes(
true, level, [&viscnt](REveGeomNode &node, std::vector<int> &, 
bool, 
int) {
 
  744    fActualLevel = level;
 
  747    int totalnumfaces{0}, totalnumnodes{0};
 
  753    for (
auto &sid: fSortMap) {
 
  755       auto &desc = fDesc[sid];
 
  757       if ((viscnt[sid] <= 0) || (desc.vol <= 0)) 
continue;
 
  759       auto shape = fNodes[sid]->GetVolume()->GetShape();
 
  760       if (!shape) 
continue;
 
  763       auto &shape_descr = MakeShapeDescr(shape);
 
  766       if (shape_descr.nfaces <= 0) {
 
  767          R__ERROR_HERE(
"webeve") << 
"No faces for the shape " << shape->GetName() << 
" class " << shape->ClassName();
 
  772       totalnumfaces += shape_descr.nfaces * viscnt[sid];
 
  773       if ((GetMaxVisFaces() > 0) && (totalnumfaces > GetMaxVisFaces())) 
break;
 
  776       totalnumnodes += viscnt[sid];
 
  777       if ((GetMaxVisNodes() > 0) && (totalnumnodes > GetMaxVisNodes())) 
break;
 
  785    REveGeomDrawing drawing;
 
  787    bool has_shape = 
false;
 
  789    ScanNodes(
true, level, [&, 
this](REveGeomNode &node, std::vector<int> &stack, 
bool, 
int seqid) {
 
  790       if (node.sortid < fDrawIdCut) {
 
  791          drawing.visibles.emplace_back(node.id, seqid, stack);
 
  793          auto &item = drawing.visibles.back();
 
  794          item.color = node.color;
 
  795          item.opacity = node.opacity;
 
  797          auto volume = fNodes[node.id]->GetVolume();
 
  799          auto &sd = MakeShapeDescr(volume->GetShape());
 
  801          item.ri = sd.rndr_info();
 
  802          if (sd.has_shape()) has_shape = 
true;
 
  807    CollectNodes(drawing);
 
  809    fDrawJson = 
"GDRAW:"s + MakeDrawingJson(drawing, has_shape);
 
  817 void ROOT::Experimental::REveGeomDescription::ClearDrawData()
 
  826 bool ROOT::Experimental::REveGeomDescription::IsPrincipalEndNode(
int nodeid)
 
  828    if ((nodeid < 0) || (nodeid >= (
int)fDesc.size()))
 
  831    auto &desc = fDesc[nodeid];
 
  833    return (desc.sortid < fDrawIdCut) && desc.IsVisible() && desc.CanDisplay() && (desc.chlds.size()==0);
 
  842 int ROOT::Experimental::REveGeomDescription::SearchVisibles(
const std::string &find, std::string &hjson, std::string &json)
 
  848       hjson = 
"FOUND:RESET";
 
  852    std::vector<int> nodescnt(fDesc.size(), 0), viscnt(fDesc.size(), 0);
 
  856    auto match_func = [&find](REveGeomNode &node) {
 
  857       return (node.vol > 0) && (node.name.compare(0, find.length(), find) == 0);
 
  861    ScanNodes(
false, 0, [&nodescnt,&viscnt,&match_func,&nmatches](REveGeomNode &node, std::vector<int> &, 
bool is_vis, 
int) {
 
  863       if (match_func(node)) {
 
  866          if (is_vis) viscnt[node.id]++;
 
  877    if (nmatches > 10 * GetMaxVisNodes()) {
 
  878       hjson = 
"FOUND:Too many " + std::to_string(nmatches);
 
  884    int totalnumfaces{0}, totalnumnodes{0}, scnt{0};
 
  885    bool send_rawdata{
true};
 
  888    for (
auto &sid: fSortMap) {
 
  889       if (scnt++ < fDrawIdCut) 
continue; 
 
  891       if (viscnt[sid] == 0) 
continue; 
 
  893       auto &desc = fDesc[sid];
 
  894       if ((viscnt[sid] <= 0) && (desc.vol <= 0)) 
continue;
 
  896       auto shape = fNodes[sid]->GetVolume()->GetShape();
 
  897       if (!shape) 
continue;
 
  900       auto &shape_descr = MakeShapeDescr(shape);
 
  903       if (shape_descr.nfaces <= 0) {
 
  904          R__ERROR_HERE(
"webeve") << 
"No faces for the shape " << shape->GetName() << 
" class " << shape->ClassName();
 
  909       totalnumfaces += shape_descr.nfaces * viscnt[sid];
 
  910       if ((GetMaxVisFaces() > 0) && (totalnumfaces > GetMaxVisFaces())) { send_rawdata = 
false; 
break; }
 
  913       totalnumnodes += viscnt[sid];
 
  914       if ((GetMaxVisNodes() > 0) && (totalnumnodes > GetMaxVisNodes()))  { send_rawdata = 
false; 
break; }
 
  924    std::vector<REveGeomNodeBase> found_desc; 
 
  925    std::vector<int> found_map(fDesc.size(), -1);   
 
  929    found_desc.emplace_back(0);
 
  930    found_desc[0].vis = fDesc[0].vis;
 
  931    found_desc[0].name = fDesc[0].name;
 
  932    found_desc[0].color = fDesc[0].color;
 
  937    REveGeomDrawing drawing;
 
  938    bool has_shape = 
true;
 
  940    ScanNodes(
false, 0, [&, 
this](REveGeomNode &node, std::vector<int> &stack, 
bool is_vis, 
int seqid) {
 
  942       if (!match_func(node))
 
  947       for (
auto &s : stack) {
 
  948          int chldid = fDesc[prntid].chlds[s];
 
  949          if (found_map[chldid] <= 0) {
 
  950             int newid = found_desc.size();
 
  951             found_desc.emplace_back(newid); 
 
  952             found_map[chldid] = newid; 
 
  954             found_desc.back().vis = fDesc[chldid].vis;
 
  955             found_desc.back().name = fDesc[chldid].name;
 
  956             found_desc.back().color = fDesc[chldid].color;
 
  959          auto pid = found_map[prntid];
 
  960          auto cid = found_map[chldid];
 
  963          auto &pchlds = found_desc[pid].chlds;
 
  964          if (std::find(pchlds.begin(), pchlds.end(), cid) == pchlds.end())
 
  965             pchlds.emplace_back(cid);
 
  971       if (!is_vis) 
return true;
 
  973       drawing.visibles.emplace_back(node.id, seqid, stack);
 
  977       if (!send_rawdata || (node.sortid < fDrawIdCut)) {
 
  982       auto &item = drawing.visibles.back();
 
  983       auto volume = fNodes[node.id]->GetVolume();
 
  985       item.color = node.color;
 
  986       item.opacity = node.opacity;
 
  988       auto &sd = MakeShapeDescr(volume->GetShape());
 
  990       item.ri = sd.rndr_info();
 
  991       if (sd.has_shape()) has_shape = 
true;
 
  995    hjson = 
"FESCR:"s + TBufferJSON::ToJSON(&found_desc, GetJsonComp()).Data();
 
  997    CollectNodes(drawing);
 
  999    json = 
"FDRAW:"s + MakeDrawingJson(drawing, has_shape);
 
 1007 int ROOT::Experimental::REveGeomDescription::FindNodeId(
const std::vector<int> &stack)
 
 1011    for (
auto &chindx: stack) {
 
 1012       auto &node = fDesc[nodeid];
 
 1013       if (chindx >= (
int) node.chlds.size()) 
return -1;
 
 1014       nodeid = node.chlds[chindx];
 
 1023 std::vector<int> ROOT::Experimental::REveGeomDescription::MakeStackByIds(
const std::vector<int> &ids)
 
 1025    std::vector<int> stack;
 
 1028       printf(
"Wrong first id\n");
 
 1034    for (
unsigned k = 1; k < ids.size(); ++k) {
 
 1036       int prntid = nodeid;
 
 1039       if (nodeid >= (
int) fDesc.size()) {
 
 1040          printf(
"Wrong node id %d\n", nodeid);
 
 1044       auto &chlds = fDesc[prntid].chlds;
 
 1045       auto pos = std::find(chlds.begin(), chlds.end(), nodeid);
 
 1046       if (pos == chlds.end()) {
 
 1047          printf(
"Wrong id %d not a child of %d - fail to find stack num %d\n", nodeid, prntid, (
int) chlds.size());
 
 1052       stack.emplace_back(std::distance(chlds.begin(), pos));
 
 1062 std::vector<int> ROOT::Experimental::REveGeomDescription::MakeStackByPath(
const std::string &path)
 
 1064    std::vector<int> res;
 
 1066    RGeomBrowserIter iter(*
this);
 
 1068    if (iter.Navigate(path)) {
 
 1074       res = MakeStackByIds(iter.CurrentIds());
 
 1084 std::vector<int> ROOT::Experimental::REveGeomDescription::MakeIdsByStack(
const std::vector<int> &stack)
 
 1086    std::vector<int> ids;
 
 1088    ids.emplace_back(0);
 
 1090    bool failure = 
false;
 
 1092    for (
auto s : stack) {
 
 1093       auto &chlds = fDesc[nodeid].chlds;
 
 1094       if (s >= (
int) chlds.size()) { failure = 
true; 
break; }
 
 1096       ids.emplace_back(chlds[s]);
 
 1102       printf(
"Fail to convert stack into list of nodes\n");
 
 1112 std::string ROOT::Experimental::REveGeomDescription::MakePathByStack(
const std::vector<int> &stack)
 
 1116    auto ids = MakeIdsByStack(stack);
 
 1117    if (ids.size() > 0) {
 
 1119       for (
auto &
id : ids) {
 
 1120          path.append(fDesc[
id].name);
 
 1133 std::string ROOT::Experimental::REveGeomDescription::ProduceModifyReply(
int nodeid)
 
 1135    std::vector<REveGeomNodeBase *> nodes;
 
 1136    auto vol = fNodes[nodeid]->GetVolume();
 
 1142    for (
auto &desc : fDesc)
 
 1143       if (fNodes[
id++]->GetVolume() == vol)
 
 1144          nodes.emplace_back(&desc);
 
 1146    return "MODIF:"s + TBufferJSON::ToJSON(&nodes, GetJsonComp()).Data();
 
 1155 bool ROOT::Experimental::REveGeomDescription::ProduceDrawingFor(
int nodeid, std::string &json, 
bool check_volume)
 
 1159    TGeoVolume *vol = (nodeid < 0) ? 
nullptr : fNodes[nodeid]->GetVolume();
 
 1161    if (!vol || !vol->GetShape()) {
 
 1166    REveGeomDrawing drawing;
 
 1168    ScanNodes(
true, 0, [&, 
this](REveGeomNode &node, std::vector<int> &stack, 
bool, 
int seq_id) {
 
 1172          if (fNodes[node.id]->GetVolume() != vol) 
return true;
 
 1174          if (node.id != nodeid) 
return true;
 
 1177       drawing.visibles.emplace_back(node.id, seq_id, stack);
 
 1179       auto &item = drawing.visibles.back();
 
 1181       item.color = node.color;
 
 1182       item.opacity = node.opacity;
 
 1187    if (drawing.visibles.size()==0) {
 
 1194    bool has_shape = 
false, has_raw = 
false;
 
 1196    auto &sd = MakeShapeDescr(vol->GetShape());
 
 1199    for (
auto &item : drawing.visibles) {
 
 1200       item.ri = sd.rndr_info();
 
 1201       if (sd.has_shape()) has_shape = 
true;
 
 1202       if (sd.has_raw()) has_raw = 
true;
 
 1205    CollectNodes(drawing);
 
 1207    json.append(MakeDrawingJson(drawing, has_shape));
 
 1209    return has_raw || has_shape;
 
 1218 std::string ROOT::Experimental::REveGeomDescription::MakeDrawingJson(REveGeomDrawing &drawing, 
bool has_shapes)
 
 1220    int comp = GetJsonComp();
 
 1222    if (!has_shapes || (comp < TBufferJSON::kSkipTypeInfo))
 
 1223       return TBufferJSON::ToJSON(&drawing, comp).Data();
 
 1225    comp = comp % TBufferJSON::kSkipTypeInfo; 
 
 1228    json.SetCompact(comp);
 
 1229    json.SetSkipClassInfo(TClass::GetClass<REveGeomDrawing>());
 
 1230    json.SetSkipClassInfo(TClass::GetClass<REveGeomNode>());
 
 1231    json.SetSkipClassInfo(TClass::GetClass<REveGeomVisible>());
 
 1232    json.SetSkipClassInfo(TClass::GetClass<RGeomShapeRenderInfo>());
 
 1233    json.SetSkipClassInfo(TClass::GetClass<RGeomRawRenderInfo>());
 
 1235    return json.StoreObject(&drawing, TClass::GetClass<REveGeomDrawing>()).Data();
 
 1242 bool ROOT::Experimental::REveGeomDescription::ChangeNodeVisibility(
int nodeid, 
bool selected)
 
 1244    auto &dnode = fDesc[nodeid];
 
 1246    auto vol = fNodes[nodeid]->GetVolume();
 
 1249    if (vol->IsVisible() == selected)
 
 1252    dnode.vis = selected ? 99 : 0;
 
 1253    vol->SetVisibility(selected);
 
 1254    if (dnode.chlds.size() > 0) {
 
 1255       if (selected) dnode.vis = 1; 
 
 1256       vol->SetVisDaughters(selected);
 
 1260    for (
auto &desc: fDesc)
 
 1261       if (fNodes[
id++]->GetVolume() == vol)
 
 1262          desc.vis = dnode.vis;
 
 1273 std::unique_ptr<ROOT::Experimental::REveGeomNodeInfo> ROOT::Experimental::REveGeomDescription::MakeNodeInfo(
const std::string &path)
 
 1275    std::unique_ptr<REveGeomNodeInfo> res;
 
 1277    RGeomBrowserIter iter(*
this);
 
 1279    if (iter.Navigate(path)) {
 
 1281       auto node = fNodes[iter.GetNodeId()];
 
 1283       auto &desc = fDesc[iter.GetNodeId()];
 
 1285       res = std::make_unique<REveGeomNodeInfo>();
 
 1287       res->fullpath = path;
 
 1288       res->node_name = node->GetName();
 
 1289       res->node_type = node->ClassName();
 
 1291       TGeoShape *shape = node->GetVolume() ? node->GetVolume()->GetShape() : 
nullptr;
 
 1294          res->shape_name = shape->GetName();
 
 1295          res->shape_type = shape->ClassName();
 
 1298       if (shape && desc.CanDisplay()) {
 
 1300          auto &shape_descr = MakeShapeDescr(shape);
 
 1302          res->ri = shape_descr.rndr_info(); 
 
 1313 bool ROOT::Experimental::REveGeomDescription::ChangeConfiguration(
const std::string &json)
 
 1315    auto cfg = TBufferJSON::FromJSON<REveGeomConfig>(json);
 
 1316    if (!cfg) 
return false;
 
 1318    auto json1 = TBufferJSON::ToJSON(cfg.get());
 
 1319    auto json2 = TBufferJSON::ToJSON(&fCfg);