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 // ================ find_if, find_shape, subset, max_element, stable_sort, etc.
00202 
00203 //! Find a ShapeRoot satisfying pred
00204 template<typename PredType>
00205 ShapeRoot find_if(const std::vector<ShapeRoot> &vec, PredType pred) {
00206   typename std::vector<ShapeRoot>::const_iterator result = find_if(vec.begin(),vec.end(),pred);
00207   if ( result != vec.end() )
00208     return *result;
00209   else
00210     return ShapeRoot();
00211 }
00212 
00213 //! Find a Shape<T> in a vector of ShapeRoot satisfying pred
00214 template<class T, typename PredType>
00215 Shape<T> find_if(const std::vector<ShapeRoot> &vec, PredType pred) {
00216   shortcircuit_and<IsType,PredType> tpred(AndPred(IsType(T::getStaticType()),pred));
00217   typename std::vector<ShapeRoot>::const_iterator result = find_if(vec.begin(),vec.end(),tpred);
00218   if ( result != vec.end() )
00219     return ShapeRootTypeConst(*result,T);
00220   else
00221     return Shape<T>();
00222 }
00223 
00224 //! Find a Shape<T> satisfying pred
00225 template<class T, typename PredType>
00226 Shape<T> find_if(const std::vector<Shape<T> > &vec, PredType pred) {
00227   typename std::vector<Shape<T> >::const_iterator result = find_if(vec.begin(),vec.end(),pred);
00228   if ( result != vec.end() )
00229     return *result;
00230   else
00231     return Shape<T>();
00232 }
00233 
00234 //! Find a Shape<T> in a vector of ShapeRoot
00235 template<class T>
00236 Shape<T> find_if(const std::vector<ShapeRoot> &vec) {
00237   typename std::vector<ShapeRoot>::const_iterator result = find_if(vec.begin(),vec.end(),IsType(T::getStaticType()));
00238   if ( result != vec.end() )
00239     return ShapeRootTypeConst(*result,T);
00240   else
00241     return Shape<T>();
00242 }
00243 
00244 //! Return the first ShapeRoot with the specified name, else return an invalid ShapeRoot
00245 template<class T>
00246 Shape<T> find_shape(const std::vector<ShapeRoot> &vec, const std::string &name) {
00247   for ( std::vector<ShapeRoot>::const_iterator it = vec.begin();
00248   it != vec.end(); it++ )
00249     if ( (*it)->getType() == T::getStaticType() && (*it)->getName() == name )
00250       return ShapeRootTypeConst(*it,T);
00251   return Shape<T>();
00252 }
00253 
00254 //! Select the Shape<T> elements from a vector of ShapeRoots
00255 template<class T>
00256 std::vector<Shape<T> > select_type(std::vector<ShapeRoot> &vec) {
00257   std::vector<Shape<T> > result(vec.size());
00258   result.clear();
00259   IsType tpred(T::getStaticType());
00260   DO_SHAPEROOTVEC(vec, element, {
00261     if ( tpred(element) ) result.push_back(reinterpret_cast<const Shape<T>&>(element));
00262   });
00263   return result;
00264 }
00265 
00266 //! Find all elements in a vector of Shape<T> satisfying pred
00267 template<class T, typename PredType>
00268 std::vector<Shape<T> > subset(const std::vector<Shape<T> > &vec, PredType pred) {
00269   std::vector<Shape<T> > result;
00270   remove_copy_if(vec.begin(), vec.end(),
00271      std::back_insert_iterator<std::vector<Shape<T> > >(result),
00272      not1(pred));
00273   return result;
00274 }
00275 
00276 //! Find all elements in a vector of ShapeRoot satisfying pred
00277 template<typename PredType>
00278 std::vector<ShapeRoot> subset(const std::vector<ShapeRoot> &vec, PredType pred) {
00279   std::vector<ShapeRoot> result;
00280   remove_copy_if(vec.begin(), vec.end(),
00281      std::back_insert_iterator<std::vector<ShapeRoot> >(result),
00282      not1(pred));
00283   return result;
00284 }
00285 
00286 //! Find all elements of type T in a vector of ShapeRoot satisfying pred
00287 template<class T, typename PredType>
00288 std::vector<T> subset(const std::vector<ShapeRoot> &vec, PredType pred) {
00289   std::vector<Shape<T> > result;
00290   shortcircuit_and<IsType,PredType> tpred(AndPred(IsType(T::getStaticType()),pred));
00291   remove_copy_if(vec.begin(), vec.end(),
00292      std::back_insert_iterator<std::vector<Shape<T> > >(result),
00293      not1(tpred));
00294   return result;
00295 }
00296 
00297 template<class T, typename ComparisonType>
00298 Shape<T> max_element(const std::vector<Shape<T> > &vec, ComparisonType comp) {
00299   typename std::vector<Shape<T> >::const_iterator result = max_element(vec.begin(),vec.end(),comp);
00300   if ( result != vec.end() )
00301     return *result;
00302   else
00303     return Shape<T>();
00304 }
00305 
00306 template<typename ComparisonType>
00307 ShapeRoot max_element(const std::vector<ShapeRoot> &vec, ComparisonType comp) {
00308   typename std::vector<ShapeRoot>::const_iterator result = max_element(vec.begin(),vec.end(),comp);
00309   if ( result != vec.end() )
00310     return *result;
00311   else
00312     return ShapeRoot();
00313 }
00314 
00315 template<class T, typename ComparisonType>
00316 Shape<T> min_element(const std::vector<Shape<T> > &vec, ComparisonType comp) {
00317   return max_element(vec, not2(comp));
00318 }
00319 
00320 
00321 template<typename ComparisonType>
00322 ShapeRoot min_element(const std::vector<ShapeRoot> &vec, ComparisonType comp) {
00323   return max_element(vec, not2(comp));
00324 }
00325 
00326 template<class T, typename PredType>
00327 std::vector<Shape<T> > stable_sort(const std::vector<Shape<T> > &vec, const PredType& pred) {
00328   std::vector<Shape<T> > result(vec);
00329   stable_sort(result.begin(), result.end(), pred);
00330   return result;
00331 }
00332 
00333 template<typename PredType>
00334 std::vector<ShapeRoot> stable_sort(const std::vector<ShapeRoot> &vec, const PredType& pred) {
00335   std::vector<ShapeRoot> result(vec);
00336   stable_sort(result.begin(), result.end(), pred);
00337   return result;
00338 }
00339 
00340 // ================ IsLeftOf / IsRightOf / IsAbove / IsBelow
00341 // ================ IsLeftOfThis / IsRightOfThis / IsAboveThis / IsBelowThis
00342 //
00343 // To enforce consistency, predicates are defined in pairs: IsRightOf(x,y)
00344 // is defined as IsLeftOf(y,x).
00345 
00346 #define DIRECTION_PAIR(dir, oppdir)                                             \
00347 class Is##dir : public BinaryShapeRootPred {                                    \
00348  public:                                                                        \
00349   Is##dir(float distance=0) : dist(distance) {}                                 \
00350   bool operator() (const ShapeRoot&, const ShapeRoot&) const;                   \
00351  private:                                                                       \
00352   float dist;                                                                   \
00353 };                                                                              \
00354                                                                                 \
00355 class Is##dir##This : public UnaryShapeRootPred {                               \
00356  public:                                                                        \
00357   Is##dir##This(const ShapeRoot &_s2, float distance=0) :                       \
00358      UnaryShapeRootPred(), s2(_s2), dist(distance) {}                           \
00359   bool operator() (const ShapeRoot &s1) const {                                 \
00360     return Is##dir(dist)(s1,s2); }                                             \
00361  private:                                                                       \
00362   ShapeRoot s2;                                                                 \
00363   float dist;                                                                   \
00364 };                                                                              \
00365                                                                                 \
00366 class Is##oppdir : public BinaryShapeRootPred {                                 \
00367  public:                                                                        \
00368   Is##oppdir(float distance=0) : dist(distance) {}                              \
00369   bool operator() (const ShapeRoot &s1, const ShapeRoot &s2) const {            \
00370     return Is##dir(dist) (s2, s1); }                                            \
00371  private:                                                                       \
00372   float dist;                                                                   \
00373 };                                                                              \
00374                                                                                 \
00375 class Is##oppdir##This : public UnaryShapeRootPred {                            \
00376  public:                                                                        \
00377   Is##oppdir##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) (s2,s1); }                                             \
00381  private:                                                                       \
00382   ShapeRoot s2;                                                                 \
00383   float dist;                                                                   \
00384 };
00385 
00386 
00387 DIRECTION_PAIR(LeftOf, RightOf)
00388 DIRECTION_PAIR(Above, Below)
00389 
00390 #undef DIRECTION_PAIR
00391 
00392 } // namespace
00393 
00394 #endif

DualCoding 5.1CVS
Generated Fri Mar 16 05:23:47 2012 by Doxygen 1.6.3