Homepage Demos Overview Downloads Tutorials 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   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   Shape<_type> _name(find_shape<_type>(_shapevec,#_name));
00033 
00034 //! Create a new vector of shapes of the specified type
00035 #define NEW_SHAPEVEC(_name, _type, _value) \
00036   vector<Shape<_type> > _name((_value));
00037 
00038 //! Create a new vector of shapes of mixed type
00039 #define NEW_SHAPEROOTVEC(_name, _value) \
00040   vector<ShapeRoot> _name((_value));
00041 
00042 //! Iterate over the shapes in a vector; _var is the iterator
00043 #define SHAPEVEC_ITERATE(_shapesvec,_type,_var) \
00044   for ( std::vector<Shape<_type> >::iterator _var##_it = _shapesvec.begin(); \
00045         _var##_it != _shapesvec.end(); _var##_it++ ) { \
00046     Shape<_type> &_var = *_var##_it;
00047 
00048 //! Nested iteration over the shapes in a vector; _var2 begins one past _var1
00049 #define SHAPENEXT_ITERATE(_shapesvec,_type,_var1,_var2) \
00050   for ( std::vector<Shape<_type> >::iterator _var2##_it = ++std::vector<Shape<_type> >::iterator(_var1##_it); \
00051         _var2##_it != _shapesvec.end(); _var2##_it++ ) { \
00052     Shape<_type> &_var2 = *_var2##_it;
00053 
00054 //! Iterate over a vector for shapes of mixed type
00055 #define SHAPEROOTVEC_ITERATE(_shapesvec,_var) \
00056   for ( std::vector<ShapeRoot>::iterator _var##_it = _shapesvec.begin(); \
00057         _var##_it != _shapesvec.end(); _var##_it++ ) { \
00058     ShapeRoot &_var = *_var##_it;
00059 
00060 #define END_ITERATE }
00061 
00062 //! Obsolete: Iterate over the shapes in a vector; _var is the iterator
00063 #define DO_SHAPEVEC(_shapesvec,_type,_var,_body) \
00064   for ( std::vector<Shape<_type> >::iterator _var##_it = _shapesvec.begin(); \
00065         _var##_it != _shapesvec.end(); _var##_it++ ) { \
00066     Shape<_type> &_var = *_var##_it; \
00067     _body } \
00068 
00069 //! Obsolete: nested iteration over the shapes in a vector; _var2 begins one past _var1
00070 #define DO_SHAPENEXT(_shapesvec,_type,_var1,_var2,_body) \
00071   for ( std::vector<Shape<_type> >::iterator _var2##_it = ++std::vector<Shape<_type> >::iterator(_var1##_it); \
00072         _var2##_it != _shapesvec.end(); _var2##_it++ ) { \
00073     Shape<_type> &_var2 = *_var2##_it; \
00074     _body }
00075 
00076 //! Obsolete: Iterate over a vector for shapes of mixed type
00077 #define DO_SHAPEROOTVEC(_shapesvec,_var,_body) \
00078   for ( std::vector<ShapeRoot>::iterator _var##_it = _shapesvec.begin(); \
00079         _var##_it != _shapesvec.end(); _var##_it++ ) { \
00080     ShapeRoot &_var = *_var##_it; \
00081     _body }
00082 
00083 // ================================================================
00084 
00085 //! Unary predicates over ShapeRoot objects
00086 class UnaryShapeRootPred : public unary_function<ShapeRoot, bool> {
00087 public:
00088   virtual ~UnaryShapeRootPred() {} //!< virtual destructor to satisfy warning
00089 };
00090 
00091 //! Binary predicates over ShapeRoot objects
00092 class BinaryShapeRootPred : public binary_function<ShapeRoot, ShapeRoot, bool> {
00093 public:
00094   virtual ~BinaryShapeRootPred() {} //!< virtual destructor to satisfy warning
00095 };
00096 
00097 //! Unary predicates over Shape<T> objects
00098 template <class T>
00099 class UnaryShapePred : public unary_function<Shape<T>, bool> {
00100 public:
00101   virtual ~UnaryShapePred() {} //!< virtual destructor to satisfy warning
00102 };
00103 
00104 //! Binary predicates over Shape<T> objects
00105 template <class T>
00106 class BinaryShapePred : public binary_function<Shape<T>, Shape<T>, bool> {
00107 public:
00108   virtual ~BinaryShapePred() {} //!< virtual destructor to satisfy warning
00109 };
00110 
00111 // ================ Short-Circuit AND and OR
00112 
00113 //! Classes for implementing shortcircuit And and Or predicates.  Don't call directly; use andPred and orPred; use not1 for negation.
00114 //@{
00115 template<typename PredType1, typename PredType2>
00116 class shortcircuit_and : public unary_function<typename PredType1::argument_type,bool> {
00117  public:
00118   PredType1 p1;
00119   PredType2 p2;
00120   shortcircuit_and(PredType1 _p1, PredType2 _p2) :
00121     unary_function<typename PredType1::argument_type,bool>(), p1(_p1), p2(_p2) {}
00122   bool operator() (const typename PredType1::argument_type &shape) const {
00123     if ( p1(shape) )
00124       return p2(shape);
00125     else return false;
00126   }
00127 };
00128 
00129 template<typename PredType1, typename PredType2>
00130 class shortcircuit_or : public unary_function<typename PredType1::argument_type,bool> {
00131  public:
00132   PredType1 p1;
00133   PredType2 p2;
00134   shortcircuit_or(PredType1 _p1, PredType2 _p2) :
00135     unary_function<typename PredType1::argument_type,bool>(), p1(_p1), p2(_p2) {}
00136   bool operator() (const typename PredType1::argument_type &shape) const {
00137     if ( p1(shape) )
00138       return true;
00139     else return p2(shape);
00140   }
00141 };
00142 
00143 /*! Templated functions can pick up type information from their
00144   arguments, but templated class constructors cannot; they expect type
00145   info to be supplied explicitly as template arguments in <>.  So we
00146   define andPred() and orPred() templated functions to pick up the
00147   type info and pass it on to the shortcircuit_and and shortcircuit_or
00148   constructors as explicit template arguments.  The built-in function
00149   adaptors not1 and not2 already use this trick for negation. */
00150 
00151 //@{
00152 
00153 //! Conjunction of two predicates; p2 is called only if p1 returns true
00154 template<typename PredType1, typename PredType2>
00155 shortcircuit_and<PredType1,PredType2> andPred(PredType1 p1, PredType2 p2) {
00156   return shortcircuit_and<PredType1,PredType2>(p1,p2);
00157 }
00158 
00159 //! Disjunction of two predicates; p2 is called only if p1 returns false
00160 template<typename PredType1, typename PredType2>
00161 shortcircuit_or<PredType1,PredType2>  orPred(PredType1 p1, PredType2 p2) {
00162   return shortcircuit_or<PredType1,PredType2>(p1,p2);
00163 }
00164 
00165 //@}
00166 
00167 // ================ Unary ShapeRoot predicates
00168 
00169 class isType : public UnaryShapeRootPred {
00170  public:
00171   ShapeType_t type;
00172   explicit isType(ShapeType_t _type) : UnaryShapeRootPred(), type(_type) {}
00173    bool operator()(const ShapeRoot &shape) const {
00174     return shape->getType() == type; }
00175 };
00176 
00177 class isColor : public UnaryShapeRootPred {
00178  public:
00179   rgb color;
00180   explicit isColor(int colorIndex) : UnaryShapeRootPred(), color(ProjectInterface::getColorRGB(colorIndex)) {}
00181   explicit isColor(rgb _color) : UnaryShapeRootPred(), color(_color) {}
00182   explicit isColor(std::string const &_colorname) : UnaryShapeRootPred(), color(ProjectInterface::getColorRGB(_colorname)) {}
00183    bool operator()(const ShapeRoot &shape) const {
00184     return shape->getColor() == color; }
00185 };
00186 
00187 class isName : public UnaryShapeRootPred {
00188  public:
00189   std::string name;
00190   explicit isName(std::string _name) : UnaryShapeRootPred(), name(_name) {}
00191    bool operator()(const ShapeRoot &shape) const {
00192      //     return strcmp(shape->getName().c_str(),name.c_str()) == 0; }
00193      return shape->getName() == name; }
00194 };
00195 
00196 // ================ find_if, find_shape, subset, max_element, stable_sort, etc.
00197 
00198 template<class T, typename PredType>
00199 Shape<T> find_if(const vector<Shape<T> > &vec, PredType pred) {
00200   typename vector<Shape<T> >::const_iterator result = find_if(vec.begin(),vec.end(),pred);
00201   if ( result != vec.end() )
00202     return *result;
00203   else
00204     return Shape<T>();
00205 }
00206 
00207 //! Return the first ShapeRoot with the specified name, else return an invalid ShapeRoot
00208 template<class T>
00209 Shape<T> find_shape(const vector<ShapeRoot> &vec, const std::string &name) {
00210   for ( vector<ShapeRoot>::const_iterator it = vec.begin();
00211   it != vec.end(); it++ )
00212     if ( (*it)->getType() == T::getStaticType() && (*it)->getName() == name )
00213       return ShapeRootTypeConst(*it,T);
00214   return Shape<T>();
00215 }
00216 
00217 //! Select the Shape<T> elements from a vector of ShapeRoots
00218 template<class T>
00219 std::vector<Shape<T> > select_type(std::vector<ShapeRoot> &vec) {
00220   std::vector<Shape<T> > result(vec.size());
00221   result.clear();
00222   isType tpred(T::getStaticType());
00223   DO_SHAPEROOTVEC(vec, element, {
00224     if ( tpred(element) ) result.push_back(reinterpret_cast<const Shape<T>&>(element));
00225   });
00226   return result;
00227 }
00228 
00229 template<class T, typename PredType>
00230 std::vector<Shape<T> > subset(const std::vector<Shape<T> > &vec, PredType pred) {
00231   std::vector<Shape<T> > result;
00232   remove_copy_if(vec.begin(), vec.end(),
00233      std::back_insert_iterator<std::vector<Shape<T> > >(result),
00234      not1(pred));
00235   return result;
00236 }
00237 
00238 template<class T, typename ComparisonType>
00239 Shape<T> max_element(const vector<Shape<T> > &vec, ComparisonType comp) {
00240   typename vector<Shape<T> >::const_iterator result = max_element(vec.begin(),vec.end(),comp);
00241   if ( result != vec.end() )
00242     return *result;
00243   else
00244     return Shape<T>();
00245 }
00246 
00247 template<class T, typename ComparisonType>
00248 Shape<T> min_element(const vector<Shape<T> > &vec, ComparisonType comp) {
00249   return max_element(vec, not2(comp));
00250 }
00251 
00252 
00253 template<class T, typename PredType>
00254 std::vector<Shape<T> > stable_sort(const std::vector<Shape<T> > &vec, PredType pred) {
00255   std::vector<Shape<T> > result(vec);
00256   stable_sort(result.begin(), result.end(), pred);
00257   return result;
00258 }
00259 
00260 // ================ IsLeftOf / IsRightOf / IsAbove / IsBelow
00261 // ================ IsLeftOfThis / IsRightOfThis / IsAboveThis / IsBelowThis
00262 //
00263 // To enforce consistency, predicates are defined in pairs: isRightOf(x,y)
00264 // is defined as isLeftOf(y,x).
00265 
00266 #define DIRECTION_PAIR(dir, oppdir)                                             \
00267 class Is##dir : public BinaryShapeRootPred {                                    \
00268  public:                                                                        \
00269   Is##dir(float distance=0) : dist(distance) {}                                 \
00270   bool operator() (const ShapeRoot&, const ShapeRoot&) const;                   \
00271  private:                                                                       \
00272   float dist;                                                                   \
00273 };                                                                              \
00274                                                                                 \
00275 class Is##dir##This : public UnaryShapeRootPred {                               \
00276  public:                                                                        \
00277   Is##dir##This(const ShapeRoot &_s2, float distance=0) :                       \
00278      UnaryShapeRootPred(), s2(_s2), dist(distance) {}                           \
00279   bool operator() (const ShapeRoot &s1) const {                                 \
00280     return Is##dir(dist)(s1,s2); }                                             \
00281  private:                                                                       \
00282   ShapeRoot s2;                                                                 \
00283   float dist;                                                                   \
00284 };                                                                              \
00285                                                                                 \
00286 class Is##oppdir : public BinaryShapeRootPred {                                 \
00287  public:                                                                        \
00288   Is##oppdir(float distance=0) : dist(distance) {}                              \
00289   bool operator() (const ShapeRoot &s1, const ShapeRoot &s2) const {            \
00290     return Is##dir(dist) (s2, s1); }                                            \
00291  private:                                                                       \
00292   float dist;                                                                   \
00293 };                                                                              \
00294                                                                                 \
00295 class Is##oppdir##This : public UnaryShapeRootPred {                            \
00296  public:                                                                        \
00297   Is##oppdir##This(const ShapeRoot &_s2, float distance=0) :                    \
00298     UnaryShapeRootPred(), s2(_s2), dist(distance) {}                            \
00299   bool operator() (const ShapeRoot &s1) const {                                 \
00300     return Is##dir(dist) (s2,s1); }                                             \
00301  private:                                                                       \
00302   ShapeRoot s2;                                                                 \
00303   float dist;                                                                   \
00304 };
00305 
00306 
00307 DIRECTION_PAIR(LeftOf, RightOf)
00308 DIRECTION_PAIR(Above, Below)
00309 
00310 #undef DIRECTION_PAIR
00311 
00312 } // namespace
00313 
00314 #endif

DualCoding 3.0beta
Generated Wed Oct 4 00:01:54 2006 by Doxygen 1.4.7