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

DualCoding 5.1CVS
Generated Mon May 9 04:56:27 2016 by Doxygen 1.6.3