lemon/xy.h
author alpar
Tue, 21 Feb 2006 12:37:00 +0000
changeset 1977 8ef02f0c4245
parent 1956 a055123339d5
child 1993 2115143eceea
permissions -rw-r--r--
RefPtr: a reference counted pointer class
     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/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 a vector multiplied by a scalar
   155 
   156   ///Returns a vector multiplied by a scalar
   157   ///\relates xy
   158   template<typename T> xy<T> operator*(const T &u,const xy<T> &x) {
   159     return x*u;
   160   }
   161 
   162   ///Read a plainvector from a stream
   163 
   164   ///Read a plainvector from a stream
   165   ///\relates xy
   166   ///
   167   template<typename T>
   168   inline std::istream& operator>>(std::istream &is, xy<T> &z) {
   169     char c;
   170     if (is >> c) {
   171       if (c != '(') is.putback(c);
   172     } else {
   173       is.clear();
   174     }
   175     if (!(is >> z.x)) return is;
   176     if (is >> c) {
   177       if (c != ',') is.putback(c);
   178     } else {
   179       is.clear();
   180     }
   181     if (!(is >> z.y)) return is;
   182     if (is >> c) {
   183       if (c != ')') is.putback(c);
   184     } else {
   185       is.clear();
   186     }
   187     return is;
   188   }
   189 
   190   ///Write a plainvector to a stream
   191 
   192   ///Write a plainvector to a stream
   193   ///\relates xy
   194   ///
   195   template<typename T>
   196   inline std::ostream& operator<<(std::ostream &os, const xy<T>& z)
   197   {
   198     os << "(" << z.x << ", " << z.y << ")";
   199     return os;
   200   }
   201 
   202   ///Rotate by 90 degrees
   203 
   204   ///Returns its parameter rotated by 90 degrees in positive direction.
   205   ///\relates xy
   206   ///
   207   template<typename T>
   208   inline xy<T> rot90(const xy<T> &z)
   209   {
   210     return xy<T>(-z.y,z.x);
   211   }
   212 
   213   ///Rotate by 270 degrees
   214 
   215   ///Returns its parameter rotated by 90 degrees in negative direction.
   216   ///\relates xy
   217   ///
   218   template<typename T>
   219   inline xy<T> rot270(const xy<T> &z)
   220   {
   221     return xy<T>(z.y,-z.x);
   222   }
   223 
   224   
   225 
   226   /// A class to calculate or store the bounding box of plainvectors.
   227 
   228   /// A class to calculate or store the bounding box of plainvectors.
   229   ///
   230   ///\author Attila Bernath
   231   template<typename T>
   232     class BoundingBox {
   233       xy<T> bottom_left, top_right;
   234       bool _empty;
   235     public:
   236       
   237       ///Default constructor: creates an empty bounding box
   238       BoundingBox() { _empty = true; }
   239 
   240       ///Constructing the instance from one point
   241       BoundingBox(xy<T> a) { bottom_left=top_right=a; _empty = false; }
   242 
   243       ///Were any points added?
   244       bool empty() const {
   245         return _empty;
   246       }
   247 
   248       ///Makes the BoundingBox empty
   249       void clear() {
   250         _empty=1;
   251       }
   252 
   253       ///\brief Gives back the bottom left corner
   254       ///(if the bounding box is empty, then the return value is not defined) 
   255       xy<T> bottomLeft() const {
   256         return bottom_left;
   257       }
   258 
   259       ///\brief Sets the bottom left corner
   260       ///(should only bee used for non-empty box) 
   261       void bottomLeft(xy<T> p) {
   262 	bottom_left = p;
   263       }
   264 
   265       ///\brief Gives back the top right corner
   266       ///(if the bounding box is empty, then the return value is not defined) 
   267       xy<T> topRight() const {
   268         return top_right;
   269       }
   270 
   271       ///\brief Sets the top right corner
   272       ///(should only bee used for non-empty box) 
   273       void topRight(xy<T> p) {
   274 	top_right = p;
   275       }
   276 
   277       ///\brief Gives back the bottom right corner
   278       ///(if the bounding box is empty, then the return value is not defined) 
   279       xy<T> bottomRight() const {
   280         return xy<T>(top_right.x,bottom_left.y);
   281       }
   282 
   283       ///\brief Sets the bottom right corner
   284       ///(should only bee used for non-empty box) 
   285       void bottomRight(xy<T> p) {
   286 	top_right.x = p.x;
   287 	bottom_left.y = p.y;
   288       }
   289 
   290       ///\brief Gives back the top left corner
   291       ///(if the bounding box is empty, then the return value is not defined) 
   292       xy<T> topLeft() const {
   293         return xy<T>(bottom_left.x,top_right.y);
   294       }
   295 
   296       ///\brief Sets the top left corner
   297       ///(should only bee used for non-empty box) 
   298       void topLeft(xy<T> p) {
   299 	top_right.y = p.y;
   300 	bottom_left.x = p.x;
   301       }
   302 
   303       ///\brief Gives back the bottom of the box
   304       ///(if the bounding box is empty, then the return value is not defined) 
   305       T bottom() const {
   306         return bottom_left.y;
   307       }
   308 
   309       ///\brief Sets the bottom of the box
   310       ///(should only bee used for non-empty box) 
   311       void bottom(T t) {
   312 	bottom_left.y = t;
   313       }
   314 
   315       ///\brief Gives back the top of the box
   316       ///(if the bounding box is empty, then the return value is not defined) 
   317       T top() const {
   318         return top_right.y;
   319       }
   320 
   321       ///\brief Sets the top of the box
   322       ///(should only bee used for non-empty box) 
   323       void top(T t) {
   324 	top_right.y = t;
   325       }
   326 
   327       ///\brief Gives back the left side of the box
   328       ///(if the bounding box is empty, then the return value is not defined) 
   329       T left() const {
   330         return bottom_left.x;
   331       }
   332 
   333       ///\brief Sets the left side of the box
   334       ///(should only bee used for non-empty box) 
   335       void left(T t) {
   336 	bottom_left.x = t;
   337       }
   338 
   339       ///\brief Gives back the right side of the box
   340       ///(if the bounding box is empty, then the return value is not defined) 
   341       T right() const {
   342         return top_right.x;
   343       }
   344 
   345       ///\brief Sets the right side of the box
   346       ///(should only bee used for non-empty box) 
   347       void right(T t) {
   348 	top_right.x = t;
   349       }
   350 
   351       ///\brief Gives back the height of the box
   352       ///(if the bounding box is empty, then the return value is not defined) 
   353       T height() const {
   354         return top_right.y-bottom_left.y;
   355       }
   356 
   357       ///\brief Gives back the width of the box
   358       ///(if the bounding box is empty, then the return value is not defined) 
   359       T width() const {
   360         return top_right.x-bottom_left.x;
   361       }
   362 
   363       ///Checks whether a point is inside a bounding box
   364       bool inside(const xy<T>& u){
   365         if (_empty)
   366           return false;
   367         else{
   368           return ((u.x-bottom_left.x)*(top_right.x-u.x) >= 0 &&
   369               (u.y-bottom_left.y)*(top_right.y-u.y) >= 0 );
   370         }
   371       }
   372   
   373       ///Increments a bounding box with a point
   374       BoundingBox& add(const xy<T>& u){
   375         if (_empty){
   376           bottom_left=top_right=u;
   377           _empty = false;
   378         }
   379         else{
   380           if (bottom_left.x > u.x) bottom_left.x = u.x;
   381           if (bottom_left.y > u.y) bottom_left.y = u.y;
   382           if (top_right.x < u.x) top_right.x = u.x;
   383           if (top_right.y < u.y) top_right.y = u.y;
   384         }
   385         return *this;
   386       }
   387   
   388 //       ///Sums a bounding box and a point
   389 //       BoundingBox operator +(const xy<T>& u){
   390 //         BoundingBox b = *this;
   391 //         return b += u;
   392 //       }
   393 
   394       ///Increments a bounding box with an other bounding box
   395       BoundingBox& add(const BoundingBox &u){
   396         if ( !u.empty() ){
   397           this->add(u.bottomLeft());
   398 	  this->add(u.topRight());
   399         }
   400         return *this;
   401       }
   402   
   403       ///Sums two bounding boxes
   404       BoundingBox operator +(const BoundingBox& u){
   405         BoundingBox b = *this;
   406         return b.add(u);
   407       }
   408 
   409 
   410       ///Intersection of two bounding boxes
   411       BoundingBox operator &(const BoundingBox& u){
   412         BoundingBox b;
   413 	b.bottom_left.x=std::max(this->bottom_left.x,u.bottom_left.x);
   414 	b.bottom_left.y=std::max(this->bottom_left.y,u.bottom_left.y);
   415 	b.top_right.x=std::min(this->top_right.x,u.top_right.x);
   416 	b.top_right.y=std::min(this->top_right.y,u.top_right.y);
   417 	b._empty = this->_empty || u._empty ||
   418 	  b.bottom_left.x>top_right.x && b.bottom_left.y>top_right.y;
   419         return b;
   420       }
   421 
   422     };//class Boundingbox
   423 
   424 
   425   ///Map of x-coordinates of an xy<>-map
   426 
   427   ///\ingroup maps
   428   ///
   429   template<class M>
   430   class XMap 
   431   {
   432     M& _map;
   433   public:
   434 
   435     typedef typename M::Value::Value Value;
   436     typedef typename M::Key Key;
   437     ///\e
   438     XMap(M& map) : _map(map) {}
   439     Value operator[](Key k) const {return _map[k].x;}
   440     void set(Key k,Value v) {_map.set(k,typename M::Value(v,_map[k].y));}
   441   };
   442     
   443   ///Returns an \ref XMap class
   444 
   445   ///This function just returns an \ref XMap class.
   446   ///
   447   ///\ingroup maps
   448   ///\relates XMap
   449   template<class M> 
   450   inline XMap<M> xMap(M &m) 
   451   {
   452     return XMap<M>(m);
   453   }
   454 
   455   template<class M> 
   456   inline XMap<M> xMap(const M &m) 
   457   {
   458     return XMap<M>(m);
   459   }
   460 
   461   ///Constant (read only) version of \ref XMap
   462 
   463   ///\ingroup maps
   464   ///
   465   template<class M>
   466   class ConstXMap 
   467   {
   468     const M& _map;
   469   public:
   470 
   471     typedef typename M::Value::Value Value;
   472     typedef typename M::Key Key;
   473     ///\e
   474     ConstXMap(const M &map) : _map(map) {}
   475     Value operator[](Key k) const {return _map[k].x;}
   476   };
   477     
   478   ///Returns a \ref ConstXMap class
   479 
   480   ///This function just returns an \ref ConstXMap class.
   481   ///
   482   ///\ingroup maps
   483   ///\relates ConstXMap
   484   template<class M> 
   485   inline ConstXMap<M> xMap(const M &m) 
   486   {
   487     return ConstXMap<M>(m);
   488   }
   489 
   490   ///Map of y-coordinates of an xy<>-map
   491     
   492   ///\ingroup maps
   493   ///
   494   template<class M>
   495   class YMap 
   496   {
   497     M& _map;
   498   public:
   499 
   500     typedef typename M::Value::Value Value;
   501     typedef typename M::Key Key;
   502     ///\e
   503     YMap(M& map) : _map(map) {}
   504     Value operator[](Key k) const {return _map[k].y;}
   505     void set(Key k,Value v) {_map.set(k,typename M::Value(_map[k].x,v));}
   506   };
   507 
   508   ///Returns an \ref YMap class
   509 
   510   ///This function just returns an \ref YMap class.
   511   ///
   512   ///\ingroup maps
   513   ///\relates YMap
   514   template<class M> 
   515   inline YMap<M> yMap(M &m) 
   516   {
   517     return YMap<M>(m);
   518   }
   519 
   520   template<class M> 
   521   inline YMap<M> yMap(const M &m) 
   522   {
   523     return YMap<M>(m);
   524   }
   525 
   526   ///Constant (read only) version of \ref YMap
   527 
   528   ///\ingroup maps
   529   ///
   530   template<class M>
   531   class ConstYMap 
   532   {
   533     const M& _map;
   534   public:
   535 
   536     typedef typename M::Value::Value Value;
   537     typedef typename M::Key Key;
   538     ///\e
   539     ConstYMap(const M &map) : _map(map) {}
   540     Value operator[](Key k) const {return _map[k].y;}
   541   };
   542     
   543   ///Returns a \ref ConstYMap class
   544 
   545   ///This function just returns an \ref ConstYMap class.
   546   ///
   547   ///\ingroup maps
   548   ///\relates ConstYMap
   549   template<class M> 
   550   inline ConstYMap<M> yMap(const M &m) 
   551   {
   552     return ConstYMap<M>(m);
   553   }
   554 
   555 
   556   ///Map of the \ref xy::normSquare() "normSquare()" of an \ref xy "xy"-map
   557 
   558   ///Map of the \ref xy::normSquare() "normSquare()" of an \ref xy "xy"-map
   559   ///\ingroup maps
   560   ///
   561   template<class M>
   562   class NormSquareMap 
   563   {
   564     const M& _map;
   565   public:
   566 
   567     typedef typename M::Value::Value Value;
   568     typedef typename M::Key Key;
   569     ///\e
   570     NormSquareMap(const M &map) : _map(map) {}
   571     Value operator[](Key k) const {return _map[k].normSquare();}
   572   };
   573     
   574   ///Returns a \ref NormSquareMap class
   575 
   576   ///This function just returns an \ref NormSquareMap class.
   577   ///
   578   ///\ingroup maps
   579   ///\relates NormSquareMap
   580   template<class M> 
   581   inline NormSquareMap<M> normSquareMap(const M &m) 
   582   {
   583     return NormSquareMap<M>(m);
   584   }
   585 
   586   /// @}
   587 
   588 
   589 } //namespace lemon
   590 
   591 #endif //LEMON_XY_H