00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "calcpaths.h"
00019
00020 #include "../objects/object_calcer.h"
00021 #include "../objects/object_imp.h"
00022
00023 #include <algorithm>
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #define NEWCALCPATH
00043 #ifdef NEWCALCPATH
00044 void localdfs( ObjectCalcer* obj,
00045 std::vector<ObjectCalcer*>& visited,
00046 std::vector<ObjectCalcer*>& all);
00047
00048 std::vector<ObjectCalcer*> calcPath( const std::vector<ObjectCalcer*>& os )
00049 {
00050
00051 std::vector<ObjectCalcer*> visited;
00052 std::vector<ObjectCalcer*> all;
00053
00054 for ( std::vector<ObjectCalcer*>::const_iterator i = os.begin(); i != os.end(); ++i )
00055 {
00056 if ( std::find( visited.begin(), visited.end(), *i ) == visited.end() )
00057 {
00058 localdfs( *i, visited, all );
00059 }
00060 }
00061
00062
00063
00064 std::vector<ObjectCalcer*> ret;
00065 for ( std::vector<ObjectCalcer*>::reverse_iterator i = all.rbegin(); i != all.rend(); ++i )
00066 {
00067
00068 if ( std::find( os.begin(), os.end(), *i ) != os.end() ) ret.push_back( *i );
00069 };
00070 return ret;
00071 }
00072
00073 void localdfs( ObjectCalcer* obj,
00074 std::vector<ObjectCalcer*>& visited,
00075 std::vector<ObjectCalcer*>& all)
00076 {
00077 visited.push_back( obj );
00078 const std::vector<ObjectCalcer*> o = obj->children();
00079 for ( std::vector<ObjectCalcer*>::const_iterator i = o.begin(); i != o.end(); ++i )
00080 {
00081 if ( std::find( visited.begin(), visited.end(), *i ) == visited.end() )
00082 localdfs( *i, visited, all );
00083 }
00084 all.push_back( obj );
00085 }
00086
00087
00088
00089 #else
00090
00091
00092
00093
00094 std::vector<ObjectCalcer*> calcPath( const std::vector<ObjectCalcer*>& os )
00095 {
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 std::vector<ObjectCalcer*> all = os;
00106
00107
00108
00109 std::vector<ObjectCalcer*> tmp = os;
00110
00111
00112
00113 std::vector<ObjectCalcer*> tmp2;
00114 while ( ! tmp.empty() )
00115 {
00116 for ( std::vector<ObjectCalcer*>::const_iterator i = tmp.begin(); i != tmp.end(); ++i )
00117 {
00118 const std::vector<ObjectCalcer*> o = (*i)->children();
00119 std::copy( o.begin(), o.end(), std::back_inserter( all ) );
00120 std::copy( o.begin(), o.end(), std::back_inserter( tmp2 ) );
00121 };
00122 tmp = tmp2;
00123 tmp2.clear();
00124 };
00125
00126
00127
00128
00129 std::vector<ObjectCalcer*> ret;
00130 ret.reserve( os.size() );
00131 for ( std::vector<ObjectCalcer*>::reverse_iterator i = all.rbegin(); i != all.rend(); ++i )
00132 {
00133
00134
00135 if ( std::find( ret.begin(), ret.end(), *i ) == ret.end() &&
00136 std::find( os.begin(), os.end(), *i ) != os.end() ) ret.push_back( *i );
00137 };
00138 std::reverse( ret.begin(), ret.end() );
00139 return ret;
00140 }
00141 #endif
00142
00143 bool addBranch( const std::vector<ObjectCalcer*>& o, const ObjectCalcer* to, std::vector<ObjectCalcer*>& ret )
00144 {
00145 bool rb = false;
00146 for ( std::vector<ObjectCalcer*>::const_iterator i = o.begin(); i != o.end(); ++i )
00147 {
00148 if ( *i == to )
00149 rb = true;
00150 else
00151 if ( addBranch( (*i)->children(), to, ret ) )
00152 {
00153 rb = true;
00154 ret.push_back( *i );
00155 };
00156 };
00157 return rb;
00158 }
00159
00160 std::vector<ObjectCalcer*> calcPath( const std::vector<ObjectCalcer*>& from, const ObjectCalcer* to )
00161 {
00162 std::vector<ObjectCalcer*> all;
00163
00164 for ( std::vector<ObjectCalcer*>::const_iterator i = from.begin(); i != from.end(); ++i )
00165 {
00166 (void) addBranch( (*i)->children(), to, all );
00167 };
00168
00169 std::vector<ObjectCalcer*> ret;
00170 for ( std::vector<ObjectCalcer*>::iterator i = all.begin(); i != all.end(); ++i )
00171 {
00172 if ( std::find( ret.begin(), ret.end(), *i ) == ret.end() )
00173 ret.push_back( *i );
00174 };
00175 return std::vector<ObjectCalcer*>( ret.rbegin(), ret.rend() );
00176 }
00177
00178 static void addNonCache( ObjectCalcer* o, std::vector<ObjectCalcer*>& ret )
00179 {
00180 if ( ! o->imp()->isCache() )
00181 if ( std::find( ret.begin(), ret.end(), o ) == ret.end() )
00182 ret.push_back( o );
00183 else
00184 {
00185 std::vector<ObjectCalcer*> parents = o->parents();
00186 for ( uint i = 0; i < parents.size(); ++i )
00187 addNonCache( parents[i], ret );
00188 };
00189 }
00190
00191 static bool visit( const ObjectCalcer* o, const std::vector<ObjectCalcer*>& from, std::vector<ObjectCalcer*>& ret )
00192 {
00193
00194
00195
00196
00197 if ( std::find( from.begin(), from.end(), o ) != from.end() ) return true;
00198
00199 std::vector<bool> deps( o->parents().size(), false );
00200 bool somedepend = false;
00201 bool alldepend = true;
00202 std::vector<ObjectCalcer*> parents = o->parents();
00203 for ( uint i = 0; i < parents.size(); ++i )
00204 {
00205 bool v = visit( parents[i], from, ret );
00206 somedepend |= v;
00207 alldepend &= v;
00208 deps[i] = v;
00209 };
00210 if ( somedepend && ! alldepend )
00211 {
00212 for ( uint i = 0; i < deps.size(); ++i )
00213 if ( ! deps[i] )
00214 addNonCache( parents[i], ret );
00215 };
00216
00217 return somedepend;
00218 }
00219
00220 std::vector<ObjectCalcer*> sideOfTreePath( const std::vector<ObjectCalcer*>& from, const ObjectCalcer* to )
00221 {
00222 std::vector<ObjectCalcer*> ret;
00223 visit( to, from, ret );
00224 return ret;
00225 }
00226
00227 std::vector<ObjectCalcer*> getAllParents( const std::vector<ObjectCalcer*>& objs )
00228 {
00229 using namespace std;
00230 std::set<ObjectCalcer*> ret( objs.begin(),objs.end() );
00231 std::set<ObjectCalcer*> cur = ret;
00232 while ( ! cur.empty() )
00233 {
00234 std::set<ObjectCalcer*> next;
00235 for ( std::set<ObjectCalcer*>::const_iterator i = cur.begin(); i != cur.end(); ++i )
00236 {
00237 std::vector<ObjectCalcer*> parents = (*i)->parents();
00238 next.insert( parents.begin(), parents.end() );
00239 };
00240
00241 ret.insert( next.begin(), next.end() );
00242 cur = next;
00243 };
00244 return std::vector<ObjectCalcer*>( ret.begin(), ret.end() );
00245 }
00246
00247 std::vector<ObjectCalcer*> getAllParents( ObjectCalcer* obj )
00248 {
00249 std::vector<ObjectCalcer*> objs;
00250 objs.push_back( obj );
00251 return getAllParents( objs );
00252 }
00253
00254 bool isChild( const ObjectCalcer* o, ObjectCalcer* op )
00255 {
00256 std::vector<ObjectCalcer*> os;
00257 os.push_back( op );
00258 return isChild( o, os );
00259 }
00260
00261 bool isChild( const ObjectCalcer* o, const std::vector<ObjectCalcer*>& os )
00262 {
00263 std::vector<ObjectCalcer*> parents = o->parents();
00264 std::set<ObjectCalcer*> cur( parents.begin(), parents.end() );
00265 while ( ! cur.empty() )
00266 {
00267 std::set<ObjectCalcer*> next;
00268 for ( std::set<ObjectCalcer*>::const_iterator i = cur.begin(); i != cur.end(); ++i )
00269 {
00270 if ( std::find( os.begin(), os.end(), *i ) != os.end() ) return true;
00271 std::vector<ObjectCalcer*> parents = (*i)->parents();
00272 next.insert( parents.begin(), parents.end() );
00273 };
00274 cur = next;
00275 };
00276 return false;
00277 }
00278
00279 std::set<ObjectCalcer*> getAllChildren( ObjectCalcer* obj )
00280 {
00281 std::vector<ObjectCalcer*> objs;
00282 objs.push_back( obj );
00283 return getAllChildren( objs );
00284 }
00285
00286 std::set<ObjectCalcer*> getAllChildren( const std::vector<ObjectCalcer*> objs )
00287 {
00288 std::set<ObjectCalcer*> ret;
00289
00290 std::set<ObjectCalcer*> cur( objs.begin(), objs.end() );
00291 while( !cur.empty() )
00292 {
00293
00294 std::set<ObjectCalcer*> next;
00295 for( std::set<ObjectCalcer*>::iterator i = cur.begin();
00296 i != cur.end(); ++i )
00297 {
00298 ret.insert( *i );
00299 std::vector<ObjectCalcer*> children = (*i)->children();
00300 next.insert( children.begin(), children.end() );
00301 };
00302 cur = next;
00303 };
00304 return ret;
00305 }
00306
00307 bool isPointOnCurve( const ObjectCalcer* point, const ObjectCalcer* curve )
00308 {
00309 return point->isDefinedOnOrThrough( curve ) || curve->isDefinedOnOrThrough( point );
00310 }