lemon/xy.h
author ladanyi
Thu, 27 Apr 2006 13:10:23 +0000
changeset 2066 b72fe5e2631a
parent 1999 2ff283124dfc
child 2157 f9171bfc7ebb
permissions -rw-r--r--
added scrollbars to the canvas
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2006
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 #ifndef LEMON_XY_H
    20 #define LEMON_XY_H
    21 
    22 #include <iostream>
    23 #include <lemon/bits/utility.h>
    24 
    25 ///\ingroup misc
    26 ///\file
    27 ///\brief A simple two dimensional vector and a bounding box implementation 
    28 ///
    29 /// The class \ref lemon::xy "xy" implements
    30 ///a two dimensional vector with the usual
    31 /// operations.
    32 ///
    33 /// The class \ref lemon::BoundingBox "BoundingBox" can be used to determine
    34 /// the rectangular bounding box of a set of \ref lemon::xy "xy"'s.
    35 ///
    36 ///\author Attila Bernath
    37 
    38 
    39 namespace lemon {
    40 
    41   /// \addtogroup misc
    42   /// @{
    43 
    44   /// A simple two dimensional vector (plainvector) implementation
    45 
    46   /// A simple two dimensional vector (plainvector) implementation
    47   ///with the usual vector
    48   /// operators.
    49   ///
    50   ///\author Attila Bernath
    51   template<typename T>
    52     class xy {
    53 
    54     public:
    55 
    56       typedef T Value;
    57 
    58       ///First co-ordinate
    59       T x;
    60       ///Second co-ordinate
    61       T y;     
    62       
    63       ///Default constructor
    64       xy() {}
    65 
    66       ///Constructing the instance from coordinates
    67       xy(T a, T b) : x(a), y(b) { }
    68 
    69 
    70       ///Conversion constructor
    71       template<class TT> xy(const xy<TT> &p) : x(p.x), y(p.y) {}
    72 
    73       ///Gives back the square of the norm of the vector
    74       T normSquare() const {
    75         return x*x+y*y;
    76       }
    77   
    78       ///Increments the left hand side by u
    79       xy<T>& operator +=(const xy<T>& u) {
    80         x += u.x;
    81         y += u.y;
    82         return *this;
    83       }
    84   
    85       ///Decrements the left hand side by u
    86       xy<T>& operator -=(const xy<T>& u) {
    87         x -= u.x;
    88         y -= u.y;
    89         return *this;
    90       }
    91 
    92       ///Multiplying the left hand side with a scalar
    93       xy<T>& operator *=(const T &u) {
    94         x *= u;
    95         y *= u;
    96         return *this;
    97       }
    98 
    99       ///Dividing the left hand side by a scalar
   100       xy<T>& operator /=(const T &u) {
   101         x /= u;
   102         y /= u;
   103         return *this;
   104       }
   105   
   106       ///Returns the scalar product of two vectors
   107       T operator *(const xy<T>& u) const {
   108         return x*u.x+y*u.y;
   109       }
   110   
   111       ///Returns the sum of two vectors
   112       xy<T> operator+(const xy<T> &u) const {
   113         xy<T> b=*this;
   114         return b+=u;
   115       }
   116 
   117       ///Returns the neg of the vectors
   118       xy<T> operator-() const {
   119         xy<T> b=*this;
   120         b.x=-b.x; b.y=-b.y;
   121         return b;
   122       }
   123 
   124       ///Returns the difference of two vectors
   125       xy<T> operator-(const xy<T> &u) const {
   126         xy<T> b=*this;
   127         return b-=u;
   128       }
   129 
   130       ///Returns a vector multiplied by a scalar
   131       xy<T> operator*(const T &u) const {
   132         xy<T> b=*this;
   133         return b*=u;
   134       }
   135 
   136       ///Returns a vector divided by a scalar
   137       xy<T> operator/(const T &u) const {
   138         xy<T> b=*this;
   139         return b/=u;
   140       }
   141 
   142       ///Testing equality
   143       bool operator==(const xy<T> &u) const {
   144         return (x==u.x) && (y==u.y);
   145       }
   146 
   147       ///Testing inequality
   148       bool operator!=(xy u) const {
   149         return  (x!=u.x) || (y!=u.y);
   150       }
   151 
   152     };
   153 
   154   ///Returns an xy 
   155 
   156   ///Returns an xy
   157   ///\relates xy
   158   template <typename T>
   159   inline xy<T> make_xy(const T& x, const T& y) {
   160     return xy<T>(x, y);
   161   }
   162 
   163   ///Returns a vector multiplied by a scalar
   164 
   165   ///Returns a vector multiplied by a scalar
   166   ///\relates xy
   167   template<typename T> xy<T> operator*(const T &u,const xy<T> &x) {
   168     return x*u;
   169   }
   170 
   171   ///Read a plainvector from a stream
   172 
   173   ///Read a plainvector from a stream
   174   ///\relates xy
   175   ///
   176   template<typename T>
   177   inline std::istream& operator>>(std::istream &is, xy<T> &z) {
   178     char c;
   179     if (is >> c) {
   180       if (c != '(') is.putback(c);
   181     } else {
   182       is.clear();
   183     }
   184     if (!(is >> z.x)) return is;
   185     if (is >> c) {
   186       if (c != ',') is.putback(c);
   187     } else {
   188       is.clear();
   189     }
   190     if (!(is >> z.y)) return is;
   191     if (is >> c) {
   192       if (c != ')') is.putback(c);
   193     } else {
   194       is.clear();
   195     }
   196     return is;
   197   }
   198 
   199   ///Write a plainvector to a stream
   200 
   201   ///Write a plainvector to a stream
   202   ///\relates xy
   203   ///
   204   template<typename T>
   205   inline std::ostream& operator<<(std::ostream &os, const xy<T>& z)
   206   {
   207     os << "(" << z.x << ", " << z.y << ")";
   208     return os;
   209   }
   210 
   211   ///Rotate by 90 degrees
   212 
   213   ///Returns its parameter rotated by 90 degrees in positive direction.
   214   ///\relates xy
   215   ///
   216   template<typename T>
   217   inline xy<T> rot90(const xy<T> &z)
   218   {
   219     return xy<T>(-z.y,z.x);
   220   }
   221 
   222   ///Rotate by 270 degrees
   223 
   224   ///Returns its parameter rotated by 90 degrees in negative direction.
   225   ///\relates xy
   226   ///
   227   template<typename T>
   228   inline xy<T> rot270(const xy<T> &z)
   229   {
   230     return xy<T>(z.y,-z.x);
   231   }
   232 
   233   
   234 
   235   /// A class to calculate or store the bounding box of plainvectors.
   236 
   237   /// A class to calculate or store the bounding box of plainvectors.
   238   ///
   239   ///\author Attila Bernath
   240   template<typename T>
   241     class BoundingBox {
   242       xy<T> bottom_left, top_right;
   243       bool _empty;
   244     public:
   245       
   246       ///Default constructor: creates an empty bounding box
   247       BoundingBox() { _empty = true; }
   248 
   249       ///Constructing the instance from one point
   250       BoundingBox(xy<T> a) { bottom_left=top_right=a; _empty = false; }
   251 
   252       ///Were any points added?
   253       bool empty() const {
   254         return _empty;
   255       }
   256 
   257       ///Makes the BoundingBox empty
   258       void clear() {
   259         _empty=1;
   260       }
   261 
   262       ///\brief Gives back the bottom left corner
   263       ///(if the bounding box is empty, then the return value is not defined) 
   264       xy<T> bottomLeft() const {
   265         return bottom_left;
   266       }
   267 
   268       ///\brief Sets the bottom left corner
   269       ///(should only bee used for non-empty box) 
   270       void bottomLeft(xy<T> p) {
   271 	bottom_left = p;
   272       }
   273 
   274       ///\brief Gives back the top right corner
   275       ///(if the bounding box is empty, then the return value is not defined) 
   276       xy<T> topRight() const {
   277         return top_right;
   278       }
   279 
   280       ///\brief Sets the top right corner
   281       ///(should only bee used for non-empty box) 
   282       void topRight(xy<T> p) {
   283 	top_right = p;
   284       }
   285 
   286       ///\brief Gives back the bottom right corner
   287       ///(if the bounding box is empty, then the return value is not defined) 
   288       xy<T> bottomRight() const {
   289         return xy<T>(top_right.x,bottom_left.y);
   290       }
   291 
   292       ///\brief Sets the bottom right corner
   293       ///(should only bee used for non-empty box) 
   294       void bottomRight(xy<T> p) {
   295 	top_right.x = p.x;
   296 	bottom_left.y = p.y;
   297       }
   298 
   299       ///\brief Gives back the top left corner
   300       ///(if the bounding box is empty, then the return value is not defined) 
   301       xy<T> topLeft() const {
   302         return xy<T>(bottom_left.x,top_right.y);
   303       }
   304 
   305       ///\brief Sets the top left corner
   306       ///(should only bee used for non-empty box) 
   307       void topLeft(xy<T> p) {
   308 	top_right.y = p.y;
   309 	bottom_left.x = p.x;
   310       }
   311 
   312       ///\brief Gives back the bottom of the box
   313       ///(if the bounding box is empty, then the return value is not defined) 
   314       T bottom() const {
   315         return bottom_left.y;
   316       }
   317 
   318       ///\brief Sets the bottom of the box
   319       ///(should only bee used for non-empty box) 
   320       void bottom(T t) {
   321 	bottom_left.y = t;
   322       }
   323 
   324       ///\brief Gives back the top of the box
   325       ///(if the bounding box is empty, then the return value is not defined) 
   326       T top() const {
   327         return top_right.y;
   328       }
   329 
   330       ///\brief Sets the top of the box
   331       ///(should only bee used for non-empty box) 
   332       void top(T t) {
   333 	top_right.y = t;
   334       }
   335 
   336       ///\brief Gives back the left side of the box
   337       ///(if the bounding box is empty, then the return value is not defined) 
   338       T left() const {
   339         return bottom_left.x;
   340       }
   341 
   342       ///\brief Sets the left side of the box
   343       ///(should only bee used for non-empty box) 
   344       void left(T t) {
   345 	bottom_left.x = t;
   346       }
   347 
   348       ///\brief Gives back the right side of the box
   349       ///(if the bounding box is empty, then the return value is not defined) 
   350       T right() const {
   351         return top_right.x;
   352       }
   353 
   354       ///\brief Sets the right side of the box
   355       ///(should only bee used for non-empty box) 
   356       void right(T t) {
   357 	top_right.x = t;
   358       }
   359 
   360       ///\brief Gives back the height of the box
   361       ///(if the bounding box is empty, then the return value is not defined) 
   362       T height() const {
   363         return top_right.y-bottom_left.y;
   364       }
   365 
   366       ///\brief Gives back the width of the box
   367       ///(if the bounding box is empty, then the return value is not defined) 
   368       T width() const {
   369         return top_right.x-bottom_left.x;
   370       }
   371 
   372       ///Checks whether a point is inside a bounding box
   373       bool inside(const xy<T>& u){
   374         if (_empty)
   375           return false;
   376         else{
   377           return ((u.x-bottom_left.x)*(top_right.x-u.x) >= 0 &&
   378               (u.y-bottom_left.y)*(top_right.y-u.y) >= 0 );
   379         }
   380       }
   381   
   382       ///Increments a bounding box with a point
   383       BoundingBox& add(const xy<T>& u){
   384         if (_empty){
   385           bottom_left=top_right=u;
   386           _empty = false;
   387         }
   388         else{
   389           if (bottom_left.x > u.x) bottom_left.x = u.x;
   390           if (bottom_left.y > u.y) bottom_left.y = u.y;
   391           if (top_right.x < u.x) top_right.x = u.x;
   392           if (top_right.y < u.y) top_right.y = u.y;
   393         }
   394         return *this;
   395       }
   396   
   397 //       ///Sums a bounding box and a point
   398 //       BoundingBox operator +(const xy<T>& u){
   399 //         BoundingBox b = *this;
   400 //         return b += u;
   401 //       }
   402 
   403       ///Increments a bounding box with another bounding box
   404       BoundingBox& add(const BoundingBox &u){
   405         if ( !u.empty() ){
   406           this->add(u.bottomLeft());
   407 	  this->add(u.topRight());
   408         }
   409         return *this;
   410       }
   411   
   412       ///Sums two bounding boxes
   413       BoundingBox operator +(const BoundingBox& u){
   414         BoundingBox b = *this;
   415         return b.add(u);
   416       }
   417 
   418 
   419       ///Intersection of two bounding boxes
   420       BoundingBox operator &(const BoundingBox& u){
   421         BoundingBox b;
   422 	b.bottom_left.x=std::max(this->bottom_left.x,u.bottom_left.x);
   423 	b.bottom_left.y=std::max(this->bottom_left.y,u.bottom_left.y);
   424 	b.top_right.x=std::min(this->top_right.x,u.top_right.x);
   425 	b.top_right.y=std::min(this->top_right.y,u.top_right.y);
   426 	b._empty = this->_empty || u._empty ||
   427 	  b.bottom_left.x>top_right.x && b.bottom_left.y>top_right.y;
   428         return b;
   429       }
   430 
   431     };//class Boundingbox
   432 
   433 
   434   ///Map of x-coordinates of an xy<>-map
   435 
   436   ///\ingroup maps
   437   ///
   438   template<class M>
   439   class XMap 
   440   {
   441     M& _map;
   442   public:
   443 
   444     typedef typename M::Value::Value Value;
   445     typedef typename M::Key Key;
   446     ///\e
   447     XMap(M& map) : _map(map) {}
   448     Value operator[](Key k) const {return _map[k].x;}
   449     void set(Key k,Value v) {_map.set(k,typename M::Value(v,_map[k].y));}
   450   };
   451     
   452   ///Returns an \ref XMap class
   453 
   454   ///This function just returns an \ref XMap class.
   455   ///
   456   ///\ingroup maps
   457   ///\relates XMap
   458   template<class M> 
   459   inline XMap<M> xMap(M &m) 
   460   {
   461     return XMap<M>(m);
   462   }
   463 
   464   template<class M> 
   465   inline XMap<M> xMap(const M &m) 
   466   {
   467     return XMap<M>(m);
   468   }
   469 
   470   ///Constant (read only) version of \ref XMap
   471 
   472   ///\ingroup maps
   473   ///
   474   template<class M>
   475   class ConstXMap 
   476   {
   477     const M& _map;
   478   public:
   479 
   480     typedef typename M::Value::Value Value;
   481     typedef typename M::Key Key;
   482     ///\e
   483     ConstXMap(const M &map) : _map(map) {}
   484     Value operator[](Key k) const {return _map[k].x;}
   485   };
   486     
   487   ///Returns a \ref ConstXMap class
   488 
   489   ///This function just returns an \ref ConstXMap class.
   490   ///
   491   ///\ingroup maps
   492   ///\relates ConstXMap
   493   template<class M> 
   494   inline ConstXMap<M> xMap(const M &m) 
   495   {
   496     return ConstXMap<M>(m);
   497   }
   498 
   499   ///Map of y-coordinates of an xy<>-map
   500     
   501   ///\ingroup maps
   502   ///
   503   template<class M>
   504   class YMap 
   505   {
   506     M& _map;
   507   public:
   508 
   509     typedef typename M::Value::Value Value;
   510     typedef typename M::Key Key;
   511     ///\e
   512     YMap(M& map) : _map(map) {}
   513     Value operator[](Key k) const {return _map[k].y;}
   514     void set(Key k,Value v) {_map.set(k,typename M::Value(_map[k].x,v));}
   515   };
   516 
   517   ///Returns an \ref YMap class
   518 
   519   ///This function just returns an \ref YMap class.
   520   ///
   521   ///\ingroup maps
   522   ///\relates YMap
   523   template<class M> 
   524   inline YMap<M> yMap(M &m) 
   525   {
   526     return YMap<M>(m);
   527   }
   528 
   529   template<class M> 
   530   inline YMap<M> yMap(const M &m) 
   531   {
   532     return YMap<M>(m);
   533   }
   534 
   535   ///Constant (read only) version of \ref YMap
   536 
   537   ///\ingroup maps
   538   ///
   539   template<class M>
   540   class ConstYMap 
   541   {
   542     const M& _map;
   543   public:
   544 
   545     typedef typename M::Value::Value Value;
   546     typedef typename M::Key Key;
   547     ///\e
   548     ConstYMap(const M &map) : _map(map) {}
   549     Value operator[](Key k) const {return _map[k].y;}
   550   };
   551     
   552   ///Returns a \ref ConstYMap class
   553 
   554   ///This function just returns an \ref ConstYMap class.
   555   ///
   556   ///\ingroup maps
   557   ///\relates ConstYMap
   558   template<class M> 
   559   inline ConstYMap<M> yMap(const M &m) 
   560   {
   561     return ConstYMap<M>(m);
   562   }
   563 
   564 
   565   ///Map of the \ref xy::normSquare() "normSquare()" of an \ref xy "xy"-map
   566 
   567   ///Map of the \ref xy::normSquare() "normSquare()" of an \ref xy "xy"-map
   568   ///\ingroup maps
   569   ///
   570   template<class M>
   571   class NormSquareMap 
   572   {
   573     const M& _map;
   574   public:
   575 
   576     typedef typename M::Value::Value Value;
   577     typedef typename M::Key Key;
   578     ///\e
   579     NormSquareMap(const M &map) : _map(map) {}
   580     Value operator[](Key k) const {return _map[k].normSquare();}
   581   };
   582     
   583   ///Returns a \ref NormSquareMap class
   584 
   585   ///This function just returns an \ref NormSquareMap class.
   586   ///
   587   ///\ingroup maps
   588   ///\relates NormSquareMap
   589   template<class M> 
   590   inline NormSquareMap<M> normSquareMap(const M &m) 
   591   {
   592     return NormSquareMap<M>(m);
   593   }
   594 
   595   /// @}
   596 
   597 
   598 } //namespace lemon
   599 
   600 #endif //LEMON_XY_H