Files
geant4/source/externals/g4tools/include/tools/sg/path
T
2025-12-05 08:54:02 +01:00

127 lines
3.1 KiB
Plaintext

// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
//
// Helper functions to handle node(s) paths in a scene graph.
//
#ifndef tools_sg_path
#define tools_sg_path
#include "node"
#include "noderef"
namespace tools {
namespace sg {
typedef std::vector<node*> path_t;
inline bool parent_class(const path_t& a_path,std::string& a_class) {
if(a_path.size()<2) {a_class.clear();return false;}
node* parent = a_path[a_path.size()-2];
a_class = parent->s_cls();
return true;
}
template <class NODE>
inline NODE* rfind(const path_t& a_path) {
path_t::const_reverse_iterator it;
for(it=a_path.rbegin();it!=a_path.rend();++it){
if(NODE* par = safe_cast<node,NODE>(*(*it))) return par;
}
return 0;
}
template <class NODE>
inline NODE* tail(const path_t& a_path) {
if(a_path.empty()) return 0;
node* _node = a_path[a_path.size()-1];
return safe_cast<node,NODE>(*_node);
}
inline bool remove_tail(path_t& a_path) {
if(a_path.empty()) return false;
a_path.resize(a_path.size()-1);
return true;
}
template <class CONTAINER>
inline CONTAINER* container(const path_t& a_path) {
if(a_path.size()<2) return 0;
node* parent = a_path[a_path.size()-2];
return safe_cast<node,CONTAINER>(*parent);
}
template <class CONTAINER>
inline CONTAINER* container_container(const path_t& a_path) {
if(a_path.size()<3) return 0;
node* parent = a_path[a_path.size()-3];
return safe_cast<node,CONTAINER>(*parent);
}
template <class WHAT,class CONTAINER>
inline bool rfind(const path_t& a_path,const node& a_from,
CONTAINER*& a_container,WHAT*& a_what,
int& a_container_index){
node* from = (node*)&a_from;
path_t::size_type sz = a_path.size();
for(size_t index=1;index<sz;index++) {
node* _node = a_path[sz-index-1];
a_container = safe_cast<node,CONTAINER>(*_node);
if(a_container) {
//the below does not compile.
//a_what = a_container->rsearch_from<WHAT>(from);
//if(a_what) return true;
void* p = a_container->rsearch_from(from,WHAT::s_class(),false);
if(p) {
a_what = (WHAT*)p;
a_container_index = int(sz-index-1);
return true;
}
from = a_container;
} else if(noderef* _ref = safe_cast<node,noderef>(*_node)) {
from = _ref;
} else { // weird case :
break;
}
}
a_what = 0;
a_container = 0;
a_container_index = -1;
return false;
}
template <class WHAT,class CONTAINER>
inline bool find_top(const path_t& a_path,const node& a_from,
CONTAINER*& a_container,WHAT*& a_what,
int& a_container_index){
a_what = 0;
a_container = 0;
a_container_index = -1;
path_t _path = a_path;
node* from = (node*)&a_from;
while(true) {
CONTAINER* container;
WHAT* what;
int idx; //index in path of container.
if(!sg::rfind<WHAT,CONTAINER>(_path,*from,container,what,idx)) {
break;
}
a_container = container;
a_what = what;
a_container_index = idx;
_path.resize(idx+1);
_path.push_back(what);
from = what;
}
return a_container?true:false;
}
typedef std::vector<path_t> paths_t;
}}
#endif