Warning, /include/Geant4/tools/sg/path is written in an unsupported language. File is not indexed.
0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003
0004 //
0005 // Helper functions to handle node(s) paths in a scene graph.
0006 //
0007
0008 #ifndef tools_sg_path
0009 #define tools_sg_path
0010
0011 #include "node"
0012 #include "noderef"
0013 #include "../pointer"
0014
0015 namespace tools {
0016 namespace sg {
0017
0018 typedef std::vector<node*> path_t;
0019
0020 inline bool parent_class(const path_t& a_path,std::string& a_class) {
0021 if(a_path.size()<2) {a_class.clear();return false;}
0022 node* parent = a_path[a_path.size()-2];
0023 a_class = parent->s_cls();
0024 return true;
0025 }
0026
0027 template <class NODE>
0028 inline NODE* rfind(const path_t& a_path) {
0029 path_t::const_reverse_iterator it;
0030 for(it=a_path.rbegin();it!=a_path.rend();++it){
0031 if(NODE* par = safe_cast<node,NODE>(*(*it))) return par;
0032 }
0033 return 0;
0034 }
0035
0036 template <class NODE>
0037 inline NODE* tail(const path_t& a_path) {
0038 if(a_path.empty()) return 0;
0039 node* _node = a_path[a_path.size()-1];
0040 return safe_cast<node,NODE>(*_node);
0041 }
0042
0043 inline bool remove_tail(path_t& a_path) {
0044 if(a_path.empty()) return false;
0045 a_path.resize(a_path.size()-1);
0046 return true;
0047 }
0048
0049 template <class CONTAINER>
0050 inline CONTAINER* container(const path_t& a_path) {
0051 if(a_path.size()<2) return 0;
0052 node* parent = a_path[a_path.size()-2];
0053 return safe_cast<node,CONTAINER>(*parent);
0054 }
0055
0056 template <class CONTAINER>
0057 inline CONTAINER* container_container(const path_t& a_path) {
0058 if(a_path.size()<3) return 0;
0059 node* parent = a_path[a_path.size()-3];
0060 return safe_cast<node,CONTAINER>(*parent);
0061 }
0062
0063 inline void dump(std::ostream& a_out,const path_t& a_path) {
0064 a_out << "tools::sg::dump : path size " << a_path.size() << std::endl;
0065 std::string _s;
0066 path_t::const_iterator it;
0067 for(it=a_path.begin();it!=a_path.end();++it){
0068 if(!p2s(*it,_s)) {}
0069 a_out << " " << _s << " " << (*it)->s_cls();
0070 if(noderef* _ref = safe_cast<node,noderef>(*(*it))) {
0071 if(!p2s(&(_ref->node()),_s)) {}
0072 a_out << ", " << _s << " " << _ref->node().s_cls();
0073 }
0074 a_out << std::endl;
0075 }
0076 }
0077
0078 //#define TOOLS_RFIND_DEBUG
0079
0080 template <class WHAT,class CONTAINER>
0081 inline bool rfind(const path_t& a_path,const node& a_from,
0082 CONTAINER*& a_container,WHAT*& a_what,
0083 int& a_container_index){
0084 node* from = (node*)&a_from;
0085 path_t::size_type sz = a_path.size();
0086 #ifdef TOOLS_RFIND_DEBUG
0087 ::printf("debug : rfind : from %s, a_path.size() %d\n",a_from.s_cls().c_str(),sz);
0088 //::printf("debug : rfind : search node of class %s\n",typename WHAT::s_cls().c_str());
0089 #endif
0090 for(size_t index=1;index<sz;index++) {
0091 node* _node = a_path[sz-index-1];
0092 #ifdef TOOLS_RFIND_DEBUG
0093 ::printf("debug : rfind : index %d, node %s\n",index,_node->s_cls().c_str());
0094 #endif
0095 a_container = safe_cast<node,CONTAINER>(*_node);
0096 if(a_container) {
0097 #ifdef TOOLS_RFIND_DEBUG
0098 ::printf("debug : rfind : node is a container of size %d\n",a_container->size());
0099 #endif
0100 //the below does not compile.
0101 //a_what = a_container->rsearch_from<WHAT>(from);
0102 //if(a_what) return true;
0103
0104 void* p = a_container->rsearch_from(from,WHAT::s_class(),false);
0105 if(p) {
0106 #ifdef TOOLS_RFIND_DEBUG
0107 ::printf("debug : rfind : found in container %lu\n",p);
0108 #endif
0109 a_what = (WHAT*)p;
0110 a_container_index = int(sz-index-1);
0111 return true;
0112 }
0113
0114 from = a_container;
0115 } else if(noderef* _ref = safe_cast<node,noderef>(*_node)) {
0116 #ifdef TOOLS_RFIND_DEBUG
0117 ::printf("debug : rfind : node is a noderef with a %s\n",_ref->node().s_cls().c_str());
0118 #endif
0119 from = _ref;
0120 } else { // weird case :
0121 #ifdef TOOLS_RFIND_DEBUG
0122 ::printf("debug : rfind : weird case\n");
0123 #endif
0124 break;
0125 }
0126 }
0127 #ifdef TOOLS_RFIND_DEBUG
0128 ::printf("debug : rfind : failed\n");
0129 #endif
0130 a_what = 0;
0131 a_container = 0;
0132 a_container_index = -1;
0133 return false;
0134 }
0135 #ifdef TOOLS_RFIND_DEBUG
0136 #undef TOOLS_RFIND_DEBUG
0137 #endif
0138
0139 template <class WHAT,class CONTAINER>
0140 inline bool find_top(const path_t& a_path,const node& a_from,
0141 CONTAINER*& a_container,WHAT*& a_what,
0142 int& a_container_index){
0143 a_what = 0;
0144 a_container = 0;
0145 a_container_index = -1;
0146 path_t _path = a_path;
0147 node* from = (node*)&a_from;
0148 while(true) {
0149 CONTAINER* container;
0150 WHAT* what;
0151 int idx; //index in path of container.
0152 if(!sg::rfind<WHAT,CONTAINER>(_path,*from,container,what,idx)) {
0153 break;
0154 }
0155 a_container = container;
0156 a_what = what;
0157 a_container_index = idx;
0158 _path.resize(idx+1);
0159 _path.push_back(what);
0160 from = what;
0161 }
0162 return a_container?true:false;
0163 }
0164
0165 typedef std::vector<path_t> paths_t;
0166
0167 }}
0168
0169 #endif