cgma
|
00001 #ifndef CUBIT_LOOPS_HPP 00002 #define CUBIT_LOOPS_HPP 00003 00004 #include "CubitDefines.h" 00005 #include <vector> 00006 #include <set> 00007 #include <map> 00008 00009 template <class C, class V> 00010 class CubitLoops 00011 { 00012 public: 00013 struct CoEdge 00014 { 00015 C* curve; 00016 V* start; 00017 V* end; 00018 CubitSense sense; 00019 }; 00020 00021 static bool make_loops(std::vector<CoEdge>& coedges, 00022 std::vector<std::vector<CoEdge*> >& loops); 00023 00024 private: 00025 00026 static bool recursive_make_loop(V* start_vertex, CoEdge* coedge, 00027 std::set<CoEdge* >& used_coedges, 00028 std::multimap<V*, CoEdge*>& start_coedge_map, 00029 std::vector<CoEdge*>& loop); 00030 }; 00031 00032 template <class C, class V> inline 00033 bool CubitLoops<C, V>::recursive_make_loop(V* start_vertex, CoEdge* coedge, 00034 std::set<CoEdge* >& used_coedges, 00035 std::multimap<V*, CoEdge*>& start_coedge_map, 00036 std::vector<CoEdge*>& loop) 00037 { 00038 V* curr_vertex; 00039 if (coedge->sense == CUBIT_FORWARD) 00040 curr_vertex = coedge->end; 00041 else 00042 curr_vertex = coedge->start; 00043 loop.push_back(coedge); 00044 used_coedges.insert(coedge); 00045 00046 while (curr_vertex != start_vertex) 00047 { 00048 typename std::multimap<V*, CoEdge*>::iterator iter; 00049 typename std::multimap<V*, CoEdge*>::iterator last; 00050 00051 iter = start_coedge_map.lower_bound(curr_vertex); 00052 last = start_coedge_map.upper_bound(curr_vertex); 00053 00054 std::vector<CoEdge*> possible_coedges; 00055 for (/*preinitialized*/; iter != last; iter++) 00056 { 00057 if (used_coedges.find(iter->second) == used_coedges.end()) 00058 possible_coedges.push_back(iter->second); 00059 } 00060 00061 if (possible_coedges.size() == 0) 00062 return false; 00063 else if (possible_coedges.size() == 1) 00064 { 00065 coedge = possible_coedges[0]; 00066 loop.push_back(coedge); 00067 used_coedges.insert(coedge); 00068 if (coedge->sense == CUBIT_FORWARD) 00069 curr_vertex = coedge->end; 00070 else 00071 curr_vertex = coedge->start; 00072 } 00073 else 00074 { 00075 for (size_t i=0; i<possible_coedges.size(); i++) 00076 { 00077 std::vector<CoEdge*> sub_loop; 00078 if (recursive_make_loop(curr_vertex, possible_coedges[i], used_coedges, start_coedge_map, sub_loop) ) 00079 { 00080 loop.insert(loop.end(), sub_loop.begin(), sub_loop.end()); 00081 } 00082 else 00083 { 00084 for (size_t j=0; j<sub_loop.size(); j++) 00085 used_coedges.erase(sub_loop[j]); 00086 coedge = possible_coedges[i]; 00087 } 00088 } 00089 loop.push_back(coedge); 00090 used_coedges.insert(coedge); 00091 if (coedge->sense == CUBIT_FORWARD) 00092 curr_vertex = coedge->end; 00093 else 00094 curr_vertex = coedge->start; 00095 } 00096 } 00097 00098 return true; 00099 } 00100 00101 template <class C, class V> inline 00102 bool CubitLoops<C, V>::make_loops(std::vector<CoEdge>& coedges, 00103 std::vector<std::vector<CoEdge*> >& loops) 00104 { 00105 std::multimap<V*, CoEdge*> start_coedge_map; 00106 00107 for (size_t i=0; i<coedges.size(); i++) 00108 { 00109 if (coedges[i].sense == CUBIT_FORWARD) 00110 start_coedge_map.insert(std::make_pair(coedges[i].start, &coedges[i])); 00111 else 00112 start_coedge_map.insert(std::make_pair(coedges[i].end, &coedges[i])); 00113 } 00114 00115 std::set<CoEdge*> used_coedges; 00116 for (size_t i=0; i<coedges.size(); i++) 00117 { 00118 if (used_coedges.find(&coedges[i]) != used_coedges.end()) 00119 continue; 00120 V* start_vertex; 00121 if (coedges[i].sense == CUBIT_FORWARD) 00122 start_vertex = coedges[i].start; 00123 else 00124 start_vertex = coedges[i].end; 00125 00126 typename std::multimap<V*, CoEdge*>::iterator iter; 00127 typename std::multimap<V*, CoEdge*>::iterator last; 00128 iter = start_coedge_map.lower_bound(start_vertex); 00129 last = start_coedge_map.upper_bound(start_vertex); 00130 std::vector<CoEdge*> loop; 00131 00132 for (/*preinitialized*/; iter != last; iter++) 00133 { 00134 std::vector<CoEdge*> sub_loop; 00135 recursive_make_loop(start_vertex, iter->second, used_coedges, 00136 start_coedge_map, loop); 00137 } 00138 00139 if (loop.empty()) 00140 return false; 00141 loops.push_back(std::vector<CoEdge*>(loop.begin(), loop.end()) ); 00142 } 00143 00144 if (coedges.size() != used_coedges.size()) 00145 return false; 00146 00147 return true; 00148 } 00149 00150 #endif