Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

ShapeFuns.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_ShapeFuns_h_
00003 #define INCLUDED_ShapeFuns_h_
00004 
00005 #include <vector>
00006 
00007 #include "Shared/ProjectInterface.h"
00008 
00009 #include "ShapeTypes.h"
00010 #include "ShapeRoot.h"
00011 
00012 namespace DualCoding {
00013 
00014 // Note: the double parens in _name((_value)) are needed to keep the
00015 // compiler from confusing a copy constructor call with a function
00016 // description in certain cases, such as this one:
00017 //
00018 //    NEW_SHAPE(foo, LineData, Shape<LineData>(newline))
00019 
00020 //! Create a new shape and make it visible in the SketchGUI
00021 #define NEW_SHAPE(_name, _type, _value) \
00022   DualCoding::Shape<_type> _name((_value)); \
00023   if ( _name.isValid() ) _name->V(#_name);
00024 
00025 //! Create a new shape but hide it from the SketchGUI
00026 #define NEW_SHAPE_N(_name, _type, _value) \
00027   NEW_SHAPE(_name, _type, _value); \
00028   if ( _name.isValid() ) _name->N(#_name);
00029 
00030 //! Retrieve a shape based on its name
00031 #define GET_SHAPE(_name, _type, _shapevec) \
00032   DualCoding::Shape<_type> _name(find_shape<_type>(_shapevec,#_name));
00033 
00034 //! Retrieve a shape based on its name, but bind to a new name
00035 #define GET_RENAMED(_new_name, _old_name, _type, _shapevec) \
00036   DualCoding::Shape<_type> _new_name(find_shape<_type>(_shapevec,#_old_name));
00037 
00038 //! Create a new vector of shapes of the specified type
00039 #define NEW_SHAPEVEC(_name, _type, _value) \
00040   std::vector<DualCoding::Shape<_type> > _name((_value));
00041 
00042 //! Create a new vector of shapes of mixed type
00043 #define NEW_SHAPEROOTVEC(_name, _value) \
00044   std::vector<DualCoding::ShapeRoot> _name((_value));
00045 
00046 //! Iterate over the shapes in a vector; _var is the iterator
00047 #define SHAPEVEC_ITERATE(_shapesvec,_type,_var) \
00048   for ( std::vector<DualCoding::Shape<_type> >::iterator _var##_it = _shapesvec.begin(); \
00049         _var##_it != _shapesvec.end(); _var##_it++ ) { \
00050     DualCoding::Shape<_type> &_var = *_var##_it;
00051 
00052 //! Nested iteration over the shapes in a vector; _var2 begins one past _var1
00053 #define SHAPENEXT_ITERATE(_shapesvec,_type,_var1,_var2) \
00054   for ( std::vector<DualCoding::Shape<_type> >::iterator _var2##_it = ++std::vector<DualCoding::Shape<_type> >::iterator(_var1##_it); \
00055         _var2##_it != _shapesvec.end(); _var2##_it++ ) { \
00056     DualCoding::Shape<_type> &_var2 = *_var2##_it;
00057 
00058 //! Iterate over a vector for shapes of mixed type
00059 #define SHAPEROOTVEC_ITERATE(_shapesvec,_var) \
00060   for ( std::vector<DualCoding::ShapeRoot>::iterator _var##_it = _shapesvec.begin(); \
00061         _var##_it != _shapesvec.end(); _var##_it++ ) { \
00062     DualCoding::ShapeRoot &_var = *_var##_it;
00063 
00064 #define END_ITERATE }
00065 
00066 //! Obsolete: Iterate over the shapes in a vector; _var is the iterator
00067 #define DO_SHAPEVEC(_shapesvec,_type,_var,_body) \
00068   for ( std::vector<DualCoding::Shape<_type> >::iterator _var##_it = _shapesvec.begin(); \
00069         _var##_it != _shapesvec.end(); _var##_it++ ) { \
00070     DualCoding::Shape<_type> &_var = *_var##_it; \
00071     _body } \
00072 
00073 //! Obsolete: nested iteration over the shapes in a vector; _var2 begins one past _var1
00074 #define DO_SHAPENEXT(_shapesvec,_type,_var1,_var2,_body) \
00075   for ( std::vector<DualCoding::Shape<_type> >::iterator _var2##_it = ++std::vector<DualCoding::Shape<_type> >::iterator(_var1##_it); \
00076         _var2##_it != _shapesvec.end(); _var2##_it++ ) { \
00077     DualCoding::Shape<_type> &_var2 = *_var2##_it; \
00078     _body }
00079 
00080 //! Obsolete: Iterate over a vector for shapes of mixed type
00081 #define DO_SHAPEROOTVEC(_shapesvec,_var,_body) \
00082   for ( std::vector<DualCoding::ShapeRoot>::iterator _var##_it = _shapesvec.begin(); \
00083         _var##_it != _shapesvec.end(); _var##_it++ ) { \
00084     DualCoding::ShapeRoot &_var = *_var##_it; \
00085     _body }
00086 
00087 // ================================================================
00088 
00089 //! Unary predicates over ShapeRoot objects
00090 class UnaryShapeRootPred : public std::unary_function<ShapeRoot, bool> {
00091 public:
00092   virtual ~UnaryShapeRootPred() {} //!< virtual destructor to satisfy warning
00093 };
00094 
00095 //! Binary predicates over ShapeRoot objects
00096 class BinaryShapeRootPred : public std::binary_function<ShapeRoot, ShapeRoot, bool> {
00097 public:
00098   virtual ~BinaryShapeRootPred() {} //!< virtual destructor to satisfy warning
00099 };
00100 
00101 //! Unary predicates over Shape<T> objects
00102 template <class T>
00103 class UnaryShapePred : public std::unary_function<Shape<T>, bool> {
00104 public:
00105   virtual ~UnaryShapePred() {} //!< virtual destructor to satisfy warning
00106 };
00107 
00108 //! Binary predicates over Shape<T> objects
00109 template <class T>
00110 class BinaryShapePred : public std::binary_function<Shape<T>, Shape<T>, bool> {
00111 public:
00112   virtual ~BinaryShapePred() {} //!< virtual destructor to satisfy warning
00113 };
00114 
00115 // ================ Short-Circuit AND and OR
00116 
00117 //! Classes for implementing shortcircuit And and Or predicates.  Don't call directly; use AndPred and OrPred; use not1 for negation.
00118 //@{
00119 template<typename PredType1, typename PredType2>
00120 class shortcircuit_and : public std::unary_function<typename PredType1::argument_type,bool> {
00121  public:
00122   PredType1 p1;
00123   PredType2 p2;
00124   shortcircuit_and(PredType1 _p1, PredType2 _p2) :
00125     std::unary_function<typename PredType1::argument_type,bool>(), p1(_p1), p2(_p2) {}
00126   bool operator() (const typename PredType1::argument_type &shape) const {
00127     if ( p1(shape) )
00128       return p2(shape);
00129     else return false;
00130   }
00131 };
00132 
00133 template<typename PredType1, typename PredType2>
00134 class shortcircuit_or : public std::unary_function<typename PredType1::argument_type,bool> {
00135  public:
00136   PredType1 p1;
00137   PredType2 p2;
00138   shortcircuit_or(PredType1 _p1, PredType2 _p2) :
00139     std::unary_function<typename PredType1::argument_type,bool>(), p1(_p1), p2(_p2) {}
00140   bool operator() (const typename PredType1::argument_type &shape) const {
00141     if ( p1(shape) )
00142       return true;
00143     else return p2(shape);
00144   }
00145 };
00146 
00147 /*! Templated functions can pick up type information from their
00148   arguments, but templated class constructors cannot; they expect type
00149   info to be supplied explicitly as template arguments in <>.  So we
00150   define AndPred() and OrPred() templated functions to pick up the
00151   type info and pass it on to the shortcircuit_and and shortcircuit_or
00152   constructors as explicit template arguments.  The built-in function
00153   adaptors not1 and not2 already use this trick for negation. */
00154 
00155 //@{
00156 
00157 //! Conjunction of two predicates; p2 is called only if p1 returns true
00158 template<typename PredType1, typename PredType2>
00159 shortcircuit_and<PredType1,PredType2> AndPred(PredType1 p1, PredType2 p2) {
00160   return shortcircuit_and<PredType1,PredType2>(p1,p2);
00161 }
00162 
00163 //! Disjunction of two predicates; p2 is called only if p1 returns false
00164 template<typename PredType1, typename PredType2>
00165 shortcircuit_or<PredType1,PredType2>  OrPred(PredType1 p1, PredType2 p2) {
00166   return shortcircuit_or<PredType1,PredType2>(p1,p2);
00167 }
00168 
00169 //@}
00170 
00171 // ================ Unary ShapeRoot predicates
00172 
00173 class IsType : public UnaryShapeRootPred {
00174  public:
00175   ShapeType_t type;
00176   explicit IsType(ShapeType_t _type) : UnaryShapeRootPred(), type(_type) {}
00177    bool operator()(const ShapeRoot &shape) const {
00178     return shape->getType() == type; }
00179 };
00180 
00181 class IsColor : public UnaryShapeRootPred {
00182  public:
00183   rgb color;
00184   explicit IsColor(int colorIndex) : UnaryShapeRootPred(), color(ProjectInterface::getColorRGB(colorIndex)) {}
00185   explicit IsColor(rgb _color) : UnaryShapeRootPred(), color(_color) {}
00186   explicit IsColor(std::string const &_colorname) : UnaryShapeRootPred(), color(ProjectInterface::getColorRGB(_colorname)) {}
00187    bool operator()(const ShapeRoot &shape) const {
00188     return shape->getColor() == color; }
00189 };
00190 
00191 class IsName : public UnaryShapeRootPred {
00192  public:
00193   std::string name;
00194   explicit IsName(std::string _name) : UnaryShapeRootPred(), name(_name) {}
00195    bool operator()(const ShapeRoot &shape) const {
00196      //     return strcmp(shape->getName().c_str(),name.c_str()) == 0; }
00197      return shape->getName() == name; }
00198 };
00199 
00200 // ================ find_if, find_shape, subset, max_element, stable_sort, etc.
00201 
00202 //! Find a ShapeRoot satisfying pred
00203 template<typename PredType>
00204 ShapeRoot find_if(const std::vector<ShapeRoot> &vec, PredType pred) {
00205   typename std::vector<ShapeRoot>::const_iterator result = find_if(vec.begin(),vec.end(),pred);
00206   if ( result != vec.end() )
00207     return *result;
00208   else
00209     return ShapeRoot();
00210 }
00211 
00212 //! Find a Shape<T> in a vector of ShapeRoot satisfying pred
00213 template<class T, typename PredType>
00214 Shape<T> find_if(const std::vector<ShapeRoot> &vec, PredType pred) {
00215   shortcircuit_and<IsType,PredType> tpred(AndPred(IsType(T::getStaticType()),pred));
00216   typename std::vector<ShapeRoot>::const_iterator result = find_if(vec.begin(),vec.end(),tpred);
00217   if ( result != vec.end() )
00218     return ShapeRootTypeConst(*result,T);
00219   else
00220     return Shape<T>();
00221 }
00222 
00223 //! Find a Shape<T> satisfying pred
00224 template<class T, typename PredType>
00225 Shape<T> find_if(const std::vector<Shape<T> > &vec, PredType pred) {
00226   typename std::vector<Shape<T> >::const_iterator result = find_if(vec.begin(),vec.end(),pred);
00227   if ( result != vec.end() )
00228     return *result;
00229   else
00230     return Shape<T>();
00231 }
00232 
00233 //! Find a Shape<T> in a vector of ShapeRoot
00234 template<class T>
00235 Shape<T> find_if(const std::vector<ShapeRoot> &vec) {
00236   typename std::vector<ShapeRoot>::const_iterator result = find_if(vec.begin(),vec.end(),IsType(T::getStaticType()));
00237   if ( result != vec.end() )
00238     return ShapeRootTypeConst(*result,T);
00239   else
00240     return Shape<T>();
00241 }
00242 
00243 //! Return the first ShapeRoot with the specified name, else return an invalid ShapeRoot
00244 template<class T>
00245 Shape<T> find_shape(const std::vector<ShapeRoot> &vec, const std::string &name) {
00246   for ( std::vector<ShapeRoot>::const_iterator it = vec.begin();
00247   it != vec.end(); it++ )
00248     if ( (*it)->getType() == T::getStaticType() && (*it)->getName() == name )
00249       return ShapeRootTypeConst(*it,T);
00250   return Shape<T>();
00251 }
00252 
00253 //! Select the Shape<T> elements from a vector of ShapeRoots
00254 template<class T>
00255 std::vector<Shape<T> > select_type(std::vector<ShapeRoot> &vec) {
00256   std::vector<Shape<T> > result(vec.size());
00257   result.clear();
00258   IsType tpred(T::getStaticType());
00259   DO_SHAPEROOTVEC(vec, element, {
00260     if ( tpred(element) ) result.push_back(reinterpret_cast<const Shape<T>&>(element));
00261   });
00262   return result;
00263 }
00264 
00265 //! Find all elements in a vector of Shape<T> satisfying pred
00266 template<class T, typename PredType>
00267 std::vector<Shape<T> > subset(const std::vector<Shape<T> > &vec, PredType pred) {
00268   std::vector<Shape<T> > result;
00269   remove_copy_if(vec.begin(), vec.end(),
00270      std::back_insert_iterator<std::vector<Shape<T> > >(result),
00271      not1(pred));
00272   return result;
00273 }
00274 
00275 //! Find all elements in a vector of ShapeRoot satisfying pred
00276 template<typename PredType>
00277 std::vector<ShapeRoot> subset(const std::vector<ShapeRoot> &vec, PredType pred) {
00278   std::vector<ShapeRoot> result;
00279   remove_copy_if(vec.begin(), vec.end(),
00280      std::back_insert_iterator<std::vector<ShapeRoot> >(result),
00281      not1(pred));
00282   return result;
00283 }
00284 
00285 //! Find all elements of type T in a vector of ShapeRoot satisfying pred
00286 template<class T, typename PredType>
00287 std::vector<T> subset(const std::vector<ShapeRoot> &vec, PredType pred) {
00288   std::vector<Shape<T> > result;
00289   shortcircuit_and<IsType,PredType> tpred(AndPred(IsType(T::getStaticType()),pred));
00290   remove_copy_if(vec.begin(), vec.end(),
00291      std::back_insert_iterator<std::vector<Shape<T> > >(result),
00292      not1(tpred));
00293   return result;
00294 }
00295 
00296 template<class T, typename ComparisonType>
00297 Shape<T> max_element(const std::vector<Shape<T> > &vec, ComparisonType comp) {
00298   typename std::vector<Shape<T> >::const_iterator result = max_element(vec.begin(),vec.end(),comp);
00299   if ( result != vec.end() )
00300     return *result;
00301   else
00302     return Shape<T>();
00303 }
00304 
00305 template<typename ComparisonType>
00306 ShapeRoot max_element(const std::vector<ShapeRoot> &vec, ComparisonType comp) {
00307   typename std::vector<ShapeRoot>::const_iterator result = max_element(vec.begin(),vec.end(),comp);
00308   if ( result != vec.end() )
00309     return *result;
00310   else
00311     return ShapeRoot();
00312 }
00313 
00314 template<class T, typename ComparisonType>
00315 Shape<T> min_element(const std::vector<Shape<T> > &vec, ComparisonType comp) {
00316   return max_element(vec, not2(comp));
00317 }
00318 
00319 
00320 template<typename ComparisonType>
00321 ShapeRoot min_element(const std::vector<ShapeRoot> &vec, ComparisonType comp) {
00322   return max_element(vec, not2(comp));
00323 }
00324 
00325 template<class T, typename PredType>
00326 std::vector<Shape<T> > stable_sort(const std::vector<Shape<T> > &vec, PredType pred) {
00327   std::vector<Shape<T> > result(vec);
00328   stable_sort(result.begin(), result.end(), pred);
00329   return result;
00330 }
00331 
00332 template<typename PredType>
00333 std::vector<ShapeRoot> stable_sort(const std::vector<ShapeRoot> &vec, PredType pred) {
00334   std::vector<ShapeRoot> result(vec);
00335   stable_sort(result.begin(), result.end(), pred);
00336   return result;
00337 }
00338 
00339 // ================ IsLeftOf / IsRightOf / IsAbove / IsBelow
00340 // ================ IsLeftOfThis / IsRightOfThis / IsAboveThis / IsBelowThis
00341 //
00342 // To enforce consistency, predicates are defined in pairs: IsRightOf(x,y)
00343 // is defined as IsLeftOf(y,x).
00344 
00345 #define DIRECTION_PAIR(dir, oppdir)                                             \
00346 class Is##dir : public BinaryShapeRootPred {                                    \
00347  public:                                                                        \
00348   Is##dir(float distance=0) : dist(distance) {}                                 \
00349   bool operator() (const ShapeRoot&, const ShapeRoot&) const;                   \
00350  private:                                                                       \
00351   float dist;                                                                   \
00352 };                                                                              \
00353                                                                                 \
00354 class Is##dir##This : public UnaryShapeRootPred {                               \
00355  public:                                                                        \
00356   Is##dir##This(const ShapeRoot &_s2, float distance=0) :                       \
00357      UnaryShapeRootPred(), s2(_s2), dist(distance) {}                           \
00358   bool operator() (const ShapeRoot &s1) const {                                 \
00359     return Is##dir(dist)(s1,s2); }                                             \
00360  private:                                                                       \
00361   ShapeRoot s2;                                                                 \
00362   float dist;                                                                   \
00363 };                                                                              \
00364                                                                                 \
00365 class Is##oppdir : public BinaryShapeRootPred {                                 \
00366  public:                                                                        \
00367   Is##oppdir(float distance=0) : dist(distance) {}                              \
00368   bool operator() (const ShapeRoot &s1, const ShapeRoot &s2) const {            \
00369     return Is##dir(dist) (s2, s1); }                                            \
00370  private:                                                                       \
00371   float dist;                                                                   \
00372 };                                                                              \
00373                                                                                 \
00374 class Is##oppdir##This : public UnaryShapeRootPred {                            \
00375  public:                                                                        \
00376   Is##oppdir##This(const ShapeRoot &_s2, float distance=0) :                    \
00377     UnaryShapeRootPred(), s2(_s2), dist(distance) {}                            \
00378   bool operator() (const ShapeRoot &s1) const {                                 \
00379     return Is##dir(dist) (s2,s1); }                                             \
00380  private:                                                                       \
00381   ShapeRoot s2;                                                                 \
00382   float dist;                                                                   \
00383 };
00384 
00385 
00386 DIRECTION_PAIR(LeftOf, RightOf)
00387 DIRECTION_PAIR(Above, Below)
00388 
00389 #undef DIRECTION_PAIR
00390 
00391 } // namespace
00392 
00393 #endif

DualCoding 4.0
Generated Thu Nov 22 00:52:36 2007 by Doxygen 1.5.4