• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdeedu
  • Sitemap
  • Contact Us
 

kig

calcpaths.cc

Go to the documentation of this file.
00001 // Copyright (C)  2002  Dominique Devriese <devriese@kde.org>
00002 
00003 // This program is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU General Public License
00005 // as published by the Free Software Foundation; either version 2
00006 // of the License, or (at your option) any later version.
00007 
00008 // This program is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 // GNU General Public License for more details.
00012 
00013 // You should have received a copy of the GNU General Public License
00014 // along with this program; if not, write to the Free Software
00015 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00016 // 02110-1301, USA.
00017 
00018 #include "calcpaths.h"
00019 
00020 #include "../objects/object_calcer.h"
00021 #include "../objects/object_imp.h"
00022 
00023 #include <algorithm>
00024 
00025 // mp:
00026 // The previous algorithm by Dominique had an exponential complexity
00027 // for some constructions (e.g. a sequence of "n" triangles each inscribed
00028 // into the previous).
00029 // The new version is directly taken from a book of Alan Bertossi
00030 // "Algoritmi e strutture dati"
00031 
00032 // temporarily disabling the new algorithm due to the freeze:
00033 // I previously misunderstood the semantics of this function
00034 // and thought that the os vector had to be completed with all
00035 // the subtree generated by it.  On the contrary, the os vector
00036 // contains *all* the objects that we want, we only have to
00037 // reorder them.  Now it *should* work, however we postpone 
00038 // activating this to a more proper moment
00039 
00040 // to deactivate the new algorithm change "define" into "undef"
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   // "all" is the Objects var we're building, in reverse ordering
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   // now, we need to remove all objects that are not in os
00063   // (forgot to do this in previous fix :-( )
00064   std::vector<ObjectCalcer*> ret;
00065   for ( std::vector<ObjectCalcer*>::reverse_iterator i = all.rbegin(); i != all.rend(); ++i )
00066   {
00067     // we only add objects that appear in os
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 // old calcPath commented out...
00088 
00089 #else
00090 // these first two functions were written before i read stuff about
00091 // graph theory and algorithms, so I'm sure they're far from optimal.
00092 // However, they seem to work fine, and i don't think there's a real
00093 // need for optimization here..
00094 std::vector<ObjectCalcer*> calcPath( const std::vector<ObjectCalcer*>& os )
00095 {
00096   // this is a little experiment of mine, i don't know if it is the
00097   // fastest way to do it, but it seems logical to me...
00098 
00099   // the general idea here:
00100   // first we build a new Objects variable.  For every object in os,
00101   // we put all of its children at the end of it, and we do the same
00102   // for the ones we add..
00103 
00104   // "all" is the Objects var we're building...
00105   std::vector<ObjectCalcer*> all = os;
00106   // tmp is the var containing the objects we're iterating over.  The
00107   // first time around this is the os variable, the next time, this
00108   // contains the variables we added in the first round...
00109   std::vector<ObjectCalcer*> tmp = os;
00110   // tmp2 is a temporary var.  During a round, it receives all the
00111   // variables we add ( to "all" ) in that round, and at the end of
00112   // the round, it is assigned to tmp.
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   // now we know that if all objects appear at least once after all of
00127   // their parents.  So, we take all, and of every object, we remove
00128   // every reference except the last one...
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     // we only add objects that appear in os and only if they are not
00134     // already in ret..
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   // this function returns true if the visited object depends on one
00194   // of the objects in from.  If we encounter objects that are on the
00195   // side of the tree path ( they do not depend on from themselves,
00196   // but their direct children do ), then we add them to ret.
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   // objects to iterate over...
00290   std::set<ObjectCalcer*> cur( objs.begin(), objs.end() );
00291   while( !cur.empty() )
00292   {
00293     // contains the objects to iterate over the next time around...
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 }

kig

Skip menu "kig"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

kdeedu

Skip menu "kdeedu"
  • kalzium
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  •   docs
  •   src
  • parley
  •   stepcore
Generated for kdeedu by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal