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

kig

  • sources
  • kde-4.12
  • kdeedu
  • kig
  • misc
calcpaths.cc
Go to the documentation of this file.
1 // Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
2 
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License
5 // as published by the Free Software Foundation; either version 2
6 // of the License, or (at your option) any later version.
7 
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 // 02110-1301, USA.
17 
18 #include "calcpaths.h"
19 
20 #include "../objects/object_calcer.h"
21 #include "../objects/object_imp.h"
22 
23 #include <algorithm>
24 
25 // mp:
26 // The previous algorithm by Dominique had an exponential complexity
27 // for some constructions (e.g. a sequence of "n" triangles each inscribed
28 // into the previous).
29 // The new version is directly taken from a book of Alan Bertossi
30 // "Algoritmi e strutture dati"
31 
32 // temporarily disabling the new algorithm due to the freeze:
33 // I previously misunderstood the semantics of this function
34 // and thought that the os vector had to be completed with all
35 // the subtree generated by it. On the contrary, the os vector
36 // contains *all* the objects that we want, we only have to
37 // reorder them. Now it *should* work, however we postpone
38 // activating this to a more proper moment
39 
40 // to deactivate the new algorithm change "define" into "undef"
41 
42 #define NEWCALCPATH
43 #ifdef NEWCALCPATH
44 void localdfs( ObjectCalcer* obj,
45  std::vector<ObjectCalcer*>& visited,
46  std::vector<ObjectCalcer*>& all);
47 
48 std::vector<ObjectCalcer*> calcPath( const std::vector<ObjectCalcer*>& os )
49 {
50  // "all" is the Objects var we're building, in reverse ordering
51  std::vector<ObjectCalcer*> visited;
52  std::vector<ObjectCalcer*> all;
53 
54  for ( std::vector<ObjectCalcer*>::const_iterator i = os.begin(); i != os.end(); ++i )
55  {
56  if ( std::find( visited.begin(), visited.end(), *i ) == visited.end() )
57  {
58  localdfs( *i, visited, all );
59  }
60  }
61 
62  // now, we need to remove all objects that are not in os
63  // (forgot to do this in previous fix :-( )
64  std::vector<ObjectCalcer*> ret;
65  for ( std::vector<ObjectCalcer*>::reverse_iterator i = all.rbegin(); i != all.rend(); ++i )
66  {
67  // we only add objects that appear in os
68  if ( std::find( os.begin(), os.end(), *i ) != os.end() ) ret.push_back( *i );
69  };
70  return ret;
71 }
72 
73 void localdfs( ObjectCalcer* obj,
74  std::vector<ObjectCalcer*>& visited,
75  std::vector<ObjectCalcer*>& all)
76 {
77  visited.push_back( obj );
78  const std::vector<ObjectCalcer*> o = obj->children();
79  for ( std::vector<ObjectCalcer*>::const_iterator i = o.begin(); i != o.end(); ++i )
80  {
81  if ( std::find( visited.begin(), visited.end(), *i ) == visited.end() )
82  localdfs( *i, visited, all );
83  }
84  all.push_back( obj );
85 }
86 
87 // old calcPath commented out...
88 
89 #else
90 // these first two functions were written before i read stuff about
91 // graph theory and algorithms, so I'm sure they're far from optimal.
92 // However, they seem to work fine, and i don't think there's a real
93 // need for optimization here..
94 std::vector<ObjectCalcer*> calcPath( const std::vector<ObjectCalcer*>& os )
95 {
96  // this is a little experiment of mine, i don't know if it is the
97  // fastest way to do it, but it seems logical to me...
98 
99  // the general idea here:
100  // first we build a new Objects variable. For every object in os,
101  // we put all of its children at the end of it, and we do the same
102  // for the ones we add..
103 
104  // "all" is the Objects var we're building...
105  std::vector<ObjectCalcer*> all = os;
106  // tmp is the var containing the objects we're iterating over. The
107  // first time around this is the os variable, the next time, this
108  // contains the variables we added in the first round...
109  std::vector<ObjectCalcer*> tmp = os;
110  // tmp2 is a temporary var. During a round, it receives all the
111  // variables we add ( to "all" ) in that round, and at the end of
112  // the round, it is assigned to tmp.
113  std::vector<ObjectCalcer*> tmp2;
114  while ( ! tmp.empty() )
115  {
116  for ( std::vector<ObjectCalcer*>::const_iterator i = tmp.begin(); i != tmp.end(); ++i )
117  {
118  const std::vector<ObjectCalcer*> o = (*i)->children();
119  std::copy( o.begin(), o.end(), std::back_inserter( all ) );
120  std::copy( o.begin(), o.end(), std::back_inserter( tmp2 ) );
121  };
122  tmp = tmp2;
123  tmp2.clear();
124  };
125 
126  // now we know that if all objects appear at least once after all of
127  // their parents. So, we take all, and of every object, we remove
128  // every reference except the last one...
129  std::vector<ObjectCalcer*> ret;
130  ret.reserve( os.size() );
131  for ( std::vector<ObjectCalcer*>::reverse_iterator i = all.rbegin(); i != all.rend(); ++i )
132  {
133  // we only add objects that appear in os and only if they are not
134  // already in ret..
135  if ( std::find( ret.begin(), ret.end(), *i ) == ret.end() &&
136  std::find( os.begin(), os.end(), *i ) != os.end() ) ret.push_back( *i );
137  };
138  std::reverse( ret.begin(), ret.end() );
139  return ret;
140 }
141 #endif
142 
143 bool addBranch( const std::vector<ObjectCalcer*>& o, const ObjectCalcer* to, std::vector<ObjectCalcer*>& ret )
144 {
145  bool rb = false;
146  for ( std::vector<ObjectCalcer*>::const_iterator i = o.begin(); i != o.end(); ++i )
147  {
148  if ( *i == to )
149  rb = true;
150  else
151  if ( addBranch( (*i)->children(), to, ret ) )
152  {
153  rb = true;
154  ret.push_back( *i );
155  };
156  };
157  return rb;
158 }
159 
160 std::vector<ObjectCalcer*> calcPath( const std::vector<ObjectCalcer*>& from, const ObjectCalcer* to )
161 {
162  std::vector<ObjectCalcer*> all;
163 
164  for ( std::vector<ObjectCalcer*>::const_iterator i = from.begin(); i != from.end(); ++i )
165  {
166  (void) addBranch( (*i)->children(), to, all );
167  };
168 
169  std::vector<ObjectCalcer*> ret;
170  for ( std::vector<ObjectCalcer*>::iterator i = all.begin(); i != all.end(); ++i )
171  {
172  if ( std::find( ret.begin(), ret.end(), *i ) == ret.end() )
173  ret.push_back( *i );
174  };
175  return std::vector<ObjectCalcer*>( ret.rbegin(), ret.rend() );
176 }
177 
178 static void addNonCache( ObjectCalcer* o, std::vector<ObjectCalcer*>& ret )
179 {
180  if ( ! o->imp()->isCache() )
181  {
182  if ( std::find( ret.begin(), ret.end(), o ) == ret.end() )
183  ret.push_back( o );
184  else
185  {
186  std::vector<ObjectCalcer*> parents = o->parents();
187  for ( uint i = 0; i < parents.size(); ++i )
188  addNonCache( parents[i], ret );
189  };
190  }
191 }
192 
193 static bool visit( const ObjectCalcer* o, const std::vector<ObjectCalcer*>& from, std::vector<ObjectCalcer*>& ret )
194 {
195  // this function returns true if the visited object depends on one
196  // of the objects in from. If we encounter objects that are on the
197  // side of the tree path ( they do not depend on from themselves,
198  // but their direct children do ), then we add them to ret.
199  if ( std::find( from.begin(), from.end(), o ) != from.end() ) return true;
200 
201  std::vector<bool> deps( o->parents().size(), false );
202  bool somedepend = false;
203  bool alldepend = true;
204  std::vector<ObjectCalcer*> parents = o->parents();
205  for ( uint i = 0; i < parents.size(); ++i )
206  {
207  bool v = visit( parents[i], from, ret );
208  somedepend |= v;
209  alldepend &= v;
210  deps[i] = v;
211  };
212  if ( somedepend && ! alldepend )
213  {
214  for ( uint i = 0; i < deps.size(); ++i )
215  if ( ! deps[i] )
216  addNonCache( parents[i], ret );
217  };
218 
219  return somedepend;
220 }
221 
222 std::vector<ObjectCalcer*> sideOfTreePath( const std::vector<ObjectCalcer*>& from, const ObjectCalcer* to )
223 {
224  std::vector<ObjectCalcer*> ret;
225  visit( to, from, ret );
226  return ret;
227 }
228 
229 std::vector<ObjectCalcer*> getAllParents( const std::vector<ObjectCalcer*>& objs )
230 {
231  using namespace std;
232  std::set<ObjectCalcer*> ret( objs.begin(),objs.end() );
233  std::set<ObjectCalcer*> cur = ret;
234  while ( ! cur.empty() )
235  {
236  std::set<ObjectCalcer*> next;
237  for ( std::set<ObjectCalcer*>::const_iterator i = cur.begin(); i != cur.end(); ++i )
238  {
239  std::vector<ObjectCalcer*> parents = (*i)->parents();
240  next.insert( parents.begin(), parents.end() );
241  };
242 
243  ret.insert( next.begin(), next.end() );
244  cur = next;
245  };
246  return std::vector<ObjectCalcer*>( ret.begin(), ret.end() );
247 }
248 
249 std::vector<ObjectCalcer*> getAllParents( ObjectCalcer* obj )
250 {
251  std::vector<ObjectCalcer*> objs;
252  objs.push_back( obj );
253  return getAllParents( objs );
254 }
255 
256 bool isChild( const ObjectCalcer* o, ObjectCalcer* op )
257 {
258  std::vector<ObjectCalcer*> os;
259  os.push_back( op );
260  return isChild( o, os );
261 }
262 
263 bool isChild( const ObjectCalcer* o, const std::vector<ObjectCalcer*>& os )
264 {
265  std::vector<ObjectCalcer*> parents = o->parents();
266  std::set<ObjectCalcer*> cur( parents.begin(), parents.end() );
267  while ( ! cur.empty() )
268  {
269  std::set<ObjectCalcer*> next;
270  for ( std::set<ObjectCalcer*>::const_iterator i = cur.begin(); i != cur.end(); ++i )
271  {
272  if ( std::find( os.begin(), os.end(), *i ) != os.end() ) return true;
273  std::vector<ObjectCalcer*> parents = (*i)->parents();
274  next.insert( parents.begin(), parents.end() );
275  };
276  cur = next;
277  };
278  return false;
279 }
280 
281 std::set<ObjectCalcer*> getAllChildren( ObjectCalcer* obj )
282 {
283  std::vector<ObjectCalcer*> objs;
284  objs.push_back( obj );
285  return getAllChildren( objs );
286 }
287 
288 std::set<ObjectCalcer*> getAllChildren( const std::vector<ObjectCalcer*> objs )
289 {
290  std::set<ObjectCalcer*> ret;
291  // objects to iterate over...
292  std::set<ObjectCalcer*> cur( objs.begin(), objs.end() );
293  while( !cur.empty() )
294  {
295  // contains the objects to iterate over the next time around...
296  std::set<ObjectCalcer*> next;
297  for( std::set<ObjectCalcer*>::iterator i = cur.begin();
298  i != cur.end(); ++i )
299  {
300  ret.insert( *i );
301  std::vector<ObjectCalcer*> children = (*i)->children();
302  next.insert( children.begin(), children.end() );
303  };
304  cur = next;
305  };
306  return ret;
307 }
308 
309 bool isPointOnCurve( const ObjectCalcer* point, const ObjectCalcer* curve )
310 {
311  return point->isDefinedOnOrThrough( curve ) || curve->isDefinedOnOrThrough( point );
312 }
calcpaths.h
addNonCache
static void addNonCache(ObjectCalcer *o, std::vector< ObjectCalcer * > &ret)
Definition: calcpaths.cc:178
getAllParents
std::vector< ObjectCalcer * > getAllParents(const std::vector< ObjectCalcer * > &objs)
This function returns all objects above the given in the dependency graph.
Definition: calcpaths.cc:229
calcPath
std::vector< ObjectCalcer * > calcPath(const std::vector< ObjectCalcer * > &os)
This function sorts os such that they're in the right order for calc()-ing.
Definition: calcpaths.cc:48
ObjectCalcer
An ObjectCalcer is an object that represents an algorithm for calculating an ObjectImp from other Obj...
Definition: object_calcer.h:66
isPointOnCurve
bool isPointOnCurve(const ObjectCalcer *point, const ObjectCalcer *curve)
Return true if the given point is ( by construction ) on the given curve.
Definition: calcpaths.cc:309
sideOfTreePath
std::vector< ObjectCalcer * > sideOfTreePath(const std::vector< ObjectCalcer * > &from, const ObjectCalcer *to)
This function returns all objects on the side of the path through the dependency tree from from down ...
Definition: calcpaths.cc:222
addBranch
bool addBranch(const std::vector< ObjectCalcer * > &o, const ObjectCalcer *to, std::vector< ObjectCalcer * > &ret)
Definition: calcpaths.cc:143
isChild
bool isChild(const ObjectCalcer *o, ObjectCalcer *op)
Definition: calcpaths.cc:256
visit
static bool visit(const ObjectCalcer *o, const std::vector< ObjectCalcer * > &from, std::vector< ObjectCalcer * > &ret)
Definition: calcpaths.cc:193
localdfs
void localdfs(ObjectCalcer *obj, std::vector< ObjectCalcer * > &visited, std::vector< ObjectCalcer * > &all)
Definition: calcpaths.cc:73
ObjectCalcer::imp
virtual const ObjectImp * imp() const =0
Returns the ObjectImp of this ObjectCalcer.
ObjectCalcer::children
std::vector< ObjectCalcer * > children() const
Returns the child ObjectCalcer's of this ObjectCalcer.
Definition: object_calcer.cc:209
ObjectImp::isCache
virtual bool isCache() const
Definition: object_imp.cc:306
ObjectCalcer::parents
virtual std::vector< ObjectCalcer * > parents() const =0
Returns the parent ObjectCalcer's of this ObjectCalcer.
getAllChildren
std::set< ObjectCalcer * > getAllChildren(ObjectCalcer *obj)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: calcpaths.cc:281
uint
unsigned int uint
Definition: object_imp.h:87
ObjectCalcer::isDefinedOnOrThrough
virtual bool isDefinedOnOrThrough(const ObjectCalcer *o) const =0
If this ObjectCalcer represents a curve, return true if the given point is by construction on this cu...
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:35:39 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kig

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

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal