lemon/dim2.h
author Peter Kovacs <kpeter@inf.elte.hu>
Wed, 27 Aug 2008 10:50:04 +0200
changeset 250 d0aae16df1bb
parent 241 92f046dd7f6c
child 253 dbe309b5e855
permissions -rw-r--r--
Stream operators for Point and BoundingBox classes (ticket #126)
- Add operator<< and operator>> for BoundingBox.
- operator<< of Point gives space-less output.
     1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library.
     4  *
     5  * Copyright (C) 2003-2008
     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_DIM2_H
    20 #define LEMON_DIM2_H
    21 
    22 #include <iostream>
    23 
    24 ///\ingroup misc
    25 ///\file
    26 ///\brief A simple two dimensional vector and a bounding box implementation
    27 ///
    28 /// The class \ref lemon::dim2::Point "dim2::Point" implements
    29 /// a two dimensional vector with the usual operations.
    30 ///
    31 /// The class \ref lemon::dim2::BoundingBox "dim2::BoundingBox"
    32 /// can be used to determine
    33 /// the rectangular bounding box of a set of
    34 /// \ref lemon::dim2::Point "dim2::Point"'s.
    35 
    36 namespace lemon {
    37 
    38   ///Tools for handling two dimensional coordinates
    39 
    40   ///This namespace is a storage of several
    41   ///tools for handling two dimensional coordinates
    42   namespace dim2 {
    43 
    44   /// \addtogroup misc
    45   /// @{
    46 
    47   /// A simple two dimensional vector (plain vector) implementation
    48 
    49   /// A simple two dimensional vector (plain vector) implementation
    50   /// with the usual vector operations.
    51   template<typename T>
    52     class Point {
    53 
    54     public:
    55 
    56       typedef T Value;
    57 
    58       ///First coordinate
    59       T x;
    60       ///Second coordinate
    61       T y;
    62 
    63       ///Default constructor
    64       Point() {}
    65 
    66       ///Construct an instance from coordinates
    67       Point(T a, T b) : x(a), y(b) { }
    68 
    69       ///Returns the dimension of the vector (i.e. returns 2).
    70 
    71       ///The dimension of the vector.
    72       ///This function always returns 2.
    73       int size() const { return 2; }
    74 
    75       ///Subscripting operator
    76 
    77       ///\c p[0] is \c p.x and \c p[1] is \c p.y
    78       ///
    79       T& operator[](int idx) { return idx == 0 ? x : y; }
    80 
    81       ///Const subscripting operator
    82 
    83       ///\c p[0] is \c p.x and \c p[1] is \c p.y
    84       ///
    85       const T& operator[](int idx) const { return idx == 0 ? x : y; }
    86 
    87       ///Conversion constructor
    88       template<class TT> Point(const Point<TT> &p) : x(p.x), y(p.y) {}
    89 
    90       ///Give back the square of the norm of the vector
    91       T normSquare() const {
    92         return x*x+y*y;
    93       }
    94 
    95       ///Increment the left hand side by \c u
    96       Point<T>& operator +=(const Point<T>& u) {
    97         x += u.x;
    98         y += u.y;
    99         return *this;
   100       }
   101 
   102       ///Decrement the left hand side by \c u
   103       Point<T>& operator -=(const Point<T>& u) {
   104         x -= u.x;
   105         y -= u.y;
   106         return *this;
   107       }
   108 
   109       ///Multiply the left hand side with a scalar
   110       Point<T>& operator *=(const T &u) {
   111         x *= u;
   112         y *= u;
   113         return *this;
   114       }
   115 
   116       ///Divide the left hand side by a scalar
   117       Point<T>& operator /=(const T &u) {
   118         x /= u;
   119         y /= u;
   120         return *this;
   121       }
   122 
   123       ///Return the scalar product of two vectors
   124       T operator *(const Point<T>& u) const {
   125         return x*u.x+y*u.y;
   126       }
   127 
   128       ///Return the sum of two vectors
   129       Point<T> operator+(const Point<T> &u) const {
   130         Point<T> b=*this;
   131         return b+=u;
   132       }
   133 
   134       ///Return the negative of the vector
   135       Point<T> operator-() const {
   136         Point<T> b=*this;
   137         b.x=-b.x; b.y=-b.y;
   138         return b;
   139       }
   140 
   141       ///Return the difference of two vectors
   142       Point<T> operator-(const Point<T> &u) const {
   143         Point<T> b=*this;
   144         return b-=u;
   145       }
   146 
   147       ///Return a vector multiplied by a scalar
   148       Point<T> operator*(const T &u) const {
   149         Point<T> b=*this;
   150         return b*=u;
   151       }
   152 
   153       ///Return a vector divided by a scalar
   154       Point<T> operator/(const T &u) const {
   155         Point<T> b=*this;
   156         return b/=u;
   157       }
   158 
   159       ///Test equality
   160       bool operator==(const Point<T> &u) const {
   161         return (x==u.x) && (y==u.y);
   162       }
   163 
   164       ///Test inequality
   165       bool operator!=(Point u) const {
   166         return  (x!=u.x) || (y!=u.y);
   167       }
   168 
   169     };
   170 
   171   ///Return a Point
   172 
   173   ///Return a Point.
   174   ///\relates Point
   175   template <typename T>
   176   inline Point<T> makePoint(const T& x, const T& y) {
   177     return Point<T>(x, y);
   178   }
   179 
   180   ///Return a vector multiplied by a scalar
   181 
   182   ///Return a vector multiplied by a scalar.
   183   ///\relates Point
   184   template<typename T> Point<T> operator*(const T &u,const Point<T> &x) {
   185     return x*u;
   186   }
   187 
   188   ///Read a plain vector from a stream
   189 
   190   ///Read a plain vector from a stream.
   191   ///\relates Point
   192   ///
   193   template<typename T>
   194   inline std::istream& operator>>(std::istream &is, Point<T> &z) {
   195     char c;
   196     if (is >> c) {
   197       if (c != '(') is.putback(c);
   198     } else {
   199       is.clear();
   200     }
   201     if (!(is >> z.x)) return is;
   202     if (is >> c) {
   203       if (c != ',') is.putback(c);
   204     } else {
   205       is.clear();
   206     }
   207     if (!(is >> z.y)) return is;
   208     if (is >> c) {
   209       if (c != ')') is.putback(c);
   210     } else {
   211       is.clear();
   212     }
   213     return is;
   214   }
   215 
   216   ///Write a plain vector to a stream
   217 
   218   ///Write a plain vector to a stream.
   219   ///\relates Point
   220   ///
   221   template<typename T>
   222   inline std::ostream& operator<<(std::ostream &os, const Point<T>& z)
   223   {
   224     os << "(" << z.x << "," << z.y << ")";
   225     return os;
   226   }
   227 
   228   ///Rotate by 90 degrees
   229 
   230   ///Returns the parameter rotated by 90 degrees in positive direction.
   231   ///\relates Point
   232   ///
   233   template<typename T>
   234   inline Point<T> rot90(const Point<T> &z)
   235   {
   236     return Point<T>(-z.y,z.x);
   237   }
   238 
   239   ///Rotate by 180 degrees
   240 
   241   ///Returns the parameter rotated by 180 degrees.
   242   ///\relates Point
   243   ///
   244   template<typename T>
   245   inline Point<T> rot180(const Point<T> &z)
   246   {
   247     return Point<T>(-z.x,-z.y);
   248   }
   249 
   250   ///Rotate by 270 degrees
   251 
   252   ///Returns the parameter rotated by 90 degrees in negative direction.
   253   ///\relates Point
   254   ///
   255   template<typename T>
   256   inline Point<T> rot270(const Point<T> &z)
   257   {
   258     return Point<T>(z.y,-z.x);
   259   }
   260 
   261 
   262 
   263     /// A class to calculate or store the bounding box of plain vectors.
   264 
   265     /// A class to calculate or store the bounding box of plain vectors.
   266     ///
   267     template<typename T>
   268     class BoundingBox {
   269       Point<T> _bottom_left, _top_right;
   270       bool _empty;
   271     public:
   272 
   273       ///Default constructor: creates an empty bounding box
   274       BoundingBox() { _empty = true; }
   275 
   276       ///Construct an instance from one point
   277       BoundingBox(Point<T> a) {
   278         _bottom_left = _top_right = a;
   279         _empty = false;
   280       }
   281 
   282       ///Construct an instance from two points
   283 
   284       ///Construct an instance from two points.
   285       ///\param a The bottom left corner.
   286       ///\param b The top right corner.
   287       ///\warning The coordinates of the bottom left corner must be no more
   288       ///than those of the top right one.
   289       BoundingBox(Point<T> a,Point<T> b)
   290       {
   291         _bottom_left = a;
   292         _top_right = b;
   293         _empty = false;
   294       }
   295 
   296       ///Construct an instance from four numbers
   297 
   298       ///Construct an instance from four numbers.
   299       ///\param l The left side of the box.
   300       ///\param b The bottom of the box.
   301       ///\param r The right side of the box.
   302       ///\param t The top of the box.
   303       ///\warning The left side must be no more than the right side and
   304       ///bottom must be no more than the top.
   305       BoundingBox(T l,T b,T r,T t)
   306       {
   307         _bottom_left=Point<T>(l,b);
   308         _top_right=Point<T>(r,t);
   309         _empty = false;
   310       }
   311 
   312       ///Return \c true if the bounding box is empty.
   313 
   314       ///Return \c true if the bounding box is empty (i.e. return \c false
   315       ///if at least one point was added to the box or the coordinates of
   316       ///the box were set).
   317       ///
   318       ///The coordinates of an empty bounding box are not defined.
   319       bool empty() const {
   320         return _empty;
   321       }
   322 
   323       ///Make the BoundingBox empty
   324       void clear() {
   325         _empty = true;
   326       }
   327 
   328       ///Give back the bottom left corner of the box
   329 
   330       ///Give back the bottom left corner of the box.
   331       ///If the bounding box is empty, then the return value is not defined.
   332       Point<T> bottomLeft() const {
   333         return _bottom_left;
   334       }
   335 
   336       ///Set the bottom left corner of the box
   337 
   338       ///Set the bottom left corner of the box.
   339       ///\pre The box must not be empty.
   340       void bottomLeft(Point<T> p) {
   341         _bottom_left = p;
   342       }
   343 
   344       ///Give back the top right corner of the box
   345 
   346       ///Give back the top right corner of the box.
   347       ///If the bounding box is empty, then the return value is not defined.
   348       Point<T> topRight() const {
   349         return _top_right;
   350       }
   351 
   352       ///Set the top right corner of the box
   353 
   354       ///Set the top right corner of the box.
   355       ///\pre The box must not be empty.
   356       void topRight(Point<T> p) {
   357         _top_right = p;
   358       }
   359 
   360       ///Give back the bottom right corner of the box
   361 
   362       ///Give back the bottom right corner of the box.
   363       ///If the bounding box is empty, then the return value is not defined.
   364       Point<T> bottomRight() const {
   365         return Point<T>(_top_right.x,_bottom_left.y);
   366       }
   367 
   368       ///Set the bottom right corner of the box
   369 
   370       ///Set the bottom right corner of the box.
   371       ///\pre The box must not be empty.
   372       void bottomRight(Point<T> p) {
   373         _top_right.x = p.x;
   374         _bottom_left.y = p.y;
   375       }
   376 
   377       ///Give back the top left corner of the box
   378 
   379       ///Give back the top left corner of the box.
   380       ///If the bounding box is empty, then the return value is not defined.
   381       Point<T> topLeft() const {
   382         return Point<T>(_bottom_left.x,_top_right.y);
   383       }
   384 
   385       ///Set the top left corner of the box
   386 
   387       ///Set the top left corner of the box.
   388       ///\pre The box must not be empty.
   389       void topLeft(Point<T> p) {
   390         _top_right.y = p.y;
   391         _bottom_left.x = p.x;
   392       }
   393 
   394       ///Give back the bottom of the box
   395 
   396       ///Give back the bottom of the box.
   397       ///If the bounding box is empty, then the return value is not defined.
   398       T bottom() const {
   399         return _bottom_left.y;
   400       }
   401 
   402       ///Set the bottom of the box
   403 
   404       ///Set the bottom of the box.
   405       ///\pre The box must not be empty.
   406       void bottom(T t) {
   407         _bottom_left.y = t;
   408       }
   409 
   410       ///Give back the top of the box
   411 
   412       ///Give back the top of the box.
   413       ///If the bounding box is empty, then the return value is not defined.
   414       T top() const {
   415         return _top_right.y;
   416       }
   417 
   418       ///Set the top of the box
   419 
   420       ///Set the top of the box.
   421       ///\pre The box must not be empty.
   422       void top(T t) {
   423         _top_right.y = t;
   424       }
   425 
   426       ///Give back the left side of the box
   427 
   428       ///Give back the left side of the box.
   429       ///If the bounding box is empty, then the return value is not defined.
   430       T left() const {
   431         return _bottom_left.x;
   432       }
   433 
   434       ///Set the left side of the box
   435 
   436       ///Set the left side of the box.
   437       ///\pre The box must not be empty.
   438       void left(T t) {
   439         _bottom_left.x = t;
   440       }
   441 
   442       /// Give back the right side of the box
   443 
   444       /// Give back the right side of the box.
   445       ///If the bounding box is empty, then the return value is not defined.
   446       T right() const {
   447         return _top_right.x;
   448       }
   449 
   450       ///Set the right side of the box
   451 
   452       ///Set the right side of the box.
   453       ///\pre The box must not be empty.
   454       void right(T t) {
   455         _top_right.x = t;
   456       }
   457 
   458       ///Give back the height of the box
   459 
   460       ///Give back the height of the box.
   461       ///If the bounding box is empty, then the return value is not defined.
   462       T height() const {
   463         return _top_right.y-_bottom_left.y;
   464       }
   465 
   466       ///Give back the width of the box
   467 
   468       ///Give back the width of the box.
   469       ///If the bounding box is empty, then the return value is not defined.
   470       T width() const {
   471         return _top_right.x-_bottom_left.x;
   472       }
   473 
   474       ///Checks whether a point is inside a bounding box
   475       bool inside(const Point<T>& u) const {
   476         if (_empty)
   477           return false;
   478         else {
   479           return ( (u.x-_bottom_left.x)*(_top_right.x-u.x) >= 0 &&
   480                    (u.y-_bottom_left.y)*(_top_right.y-u.y) >= 0 );
   481         }
   482       }
   483 
   484       ///Increments a bounding box with a point
   485 
   486       ///Increments a bounding box with a point.
   487       ///
   488       BoundingBox& add(const Point<T>& u){
   489         if (_empty) {
   490           _bottom_left = _top_right = u;
   491           _empty = false;
   492         }
   493         else {
   494           if (_bottom_left.x > u.x) _bottom_left.x = u.x;
   495           if (_bottom_left.y > u.y) _bottom_left.y = u.y;
   496           if (_top_right.x < u.x) _top_right.x = u.x;
   497           if (_top_right.y < u.y) _top_right.y = u.y;
   498         }
   499         return *this;
   500       }
   501 
   502       ///Increments a bounding box to contain another bounding box
   503 
   504       ///Increments a bounding box to contain another bounding box.
   505       ///
   506       BoundingBox& add(const BoundingBox &u){
   507         if ( !u.empty() ){
   508           add(u._bottom_left);
   509           add(u._top_right);
   510         }
   511         return *this;
   512       }
   513 
   514       ///Intersection of two bounding boxes
   515 
   516       ///Intersection of two bounding boxes.
   517       ///
   518       BoundingBox operator&(const BoundingBox& u) const {
   519         BoundingBox b;
   520         if (_empty || u._empty) {
   521           b._empty = true;
   522         } else {
   523           b._bottom_left.x = std::max(_bottom_left.x, u._bottom_left.x);
   524           b._bottom_left.y = std::max(_bottom_left.y, u._bottom_left.y);
   525           b._top_right.x = std::min(_top_right.x, u._top_right.x);
   526           b._top_right.y = std::min(_top_right.y, u._top_right.y);
   527           b._empty = b._bottom_left.x > b._top_right.x ||
   528                      b._bottom_left.y > b._top_right.y;
   529         }
   530         return b;
   531       }
   532 
   533     };//class Boundingbox
   534 
   535 
   536   ///Read a bounding box from a stream
   537 
   538   ///Read a bounding box from a stream.
   539   ///\relates BoundingBox
   540   template<typename T>
   541   inline std::istream& operator>>(std::istream &is, BoundingBox<T>& b) {
   542     char c;
   543     Point<T> p;
   544     if (is >> c) {
   545       if (c != '(') is.putback(c);
   546     } else {
   547       is.clear();
   548     }
   549     if (!(is >> p)) return is;
   550     b.bottomLeft(p);
   551     if (is >> c) {
   552       if (c != ',') is.putback(c);
   553     } else {
   554       is.clear();
   555     }
   556     if (!(is >> p)) return is;
   557     b.topRight(p);
   558     if (is >> c) {
   559       if (c != ')') is.putback(c);
   560     } else {
   561       is.clear();
   562     }
   563     return is;
   564   }
   565 
   566   ///Write a bounding box to a stream
   567 
   568   ///Write a bounding box to a stream.
   569   ///\relates BoundingBox
   570   template<typename T>
   571   inline std::ostream& operator<<(std::ostream &os, const BoundingBox<T>& b)
   572   {
   573     os << "(" << b.bottomLeft() << "," << b.topRight() << ")";
   574     return os;
   575   }
   576 
   577   ///Map of x-coordinates of a \ref Point "Point"-map
   578 
   579   ///\ingroup maps
   580   ///Map of x-coordinates of a \ref Point "Point"-map.
   581   ///
   582   template<class M>
   583   class XMap
   584   {
   585     M& _map;
   586   public:
   587 
   588     typedef typename M::Value::Value Value;
   589     typedef typename M::Key Key;
   590     ///\e
   591     XMap(M& map) : _map(map) {}
   592     Value operator[](Key k) const {return _map[k].x;}
   593     void set(Key k,Value v) {_map.set(k,typename M::Value(v,_map[k].y));}
   594   };
   595 
   596   ///Returns an \ref XMap class
   597 
   598   ///This function just returns an \ref XMap class.
   599   ///
   600   ///\ingroup maps
   601   ///\relates XMap
   602   template<class M>
   603   inline XMap<M> xMap(M &m)
   604   {
   605     return XMap<M>(m);
   606   }
   607 
   608   template<class M>
   609   inline XMap<M> xMap(const M &m)
   610   {
   611     return XMap<M>(m);
   612   }
   613 
   614   ///Constant (read only) version of \ref XMap
   615 
   616   ///\ingroup maps
   617   ///Constant (read only) version of \ref XMap
   618   ///
   619   template<class M>
   620   class ConstXMap
   621   {
   622     const M& _map;
   623   public:
   624 
   625     typedef typename M::Value::Value Value;
   626     typedef typename M::Key Key;
   627     ///\e
   628     ConstXMap(const M &map) : _map(map) {}
   629     Value operator[](Key k) const {return _map[k].x;}
   630   };
   631 
   632   ///Returns a \ref ConstXMap class
   633 
   634   ///This function just returns a \ref ConstXMap class.
   635   ///
   636   ///\ingroup maps
   637   ///\relates ConstXMap
   638   template<class M>
   639   inline ConstXMap<M> xMap(const M &m)
   640   {
   641     return ConstXMap<M>(m);
   642   }
   643 
   644   ///Map of y-coordinates of a \ref Point "Point"-map
   645 
   646   ///\ingroup maps
   647   ///Map of y-coordinates of a \ref Point "Point"-map.
   648   ///
   649   template<class M>
   650   class YMap
   651   {
   652     M& _map;
   653   public:
   654 
   655     typedef typename M::Value::Value Value;
   656     typedef typename M::Key Key;
   657     ///\e
   658     YMap(M& map) : _map(map) {}
   659     Value operator[](Key k) const {return _map[k].y;}
   660     void set(Key k,Value v) {_map.set(k,typename M::Value(_map[k].x,v));}
   661   };
   662 
   663   ///Returns a \ref YMap class
   664 
   665   ///This function just returns a \ref YMap class.
   666   ///
   667   ///\ingroup maps
   668   ///\relates YMap
   669   template<class M>
   670   inline YMap<M> yMap(M &m)
   671   {
   672     return YMap<M>(m);
   673   }
   674 
   675   template<class M>
   676   inline YMap<M> yMap(const M &m)
   677   {
   678     return YMap<M>(m);
   679   }
   680 
   681   ///Constant (read only) version of \ref YMap
   682 
   683   ///\ingroup maps
   684   ///Constant (read only) version of \ref YMap
   685   ///
   686   template<class M>
   687   class ConstYMap
   688   {
   689     const M& _map;
   690   public:
   691 
   692     typedef typename M::Value::Value Value;
   693     typedef typename M::Key Key;
   694     ///\e
   695     ConstYMap(const M &map) : _map(map) {}
   696     Value operator[](Key k) const {return _map[k].y;}
   697   };
   698 
   699   ///Returns a \ref ConstYMap class
   700 
   701   ///This function just returns a \ref ConstYMap class.
   702   ///
   703   ///\ingroup maps
   704   ///\relates ConstYMap
   705   template<class M>
   706   inline ConstYMap<M> yMap(const M &m)
   707   {
   708     return ConstYMap<M>(m);
   709   }
   710 
   711 
   712   ///\brief Map of the \ref Point::normSquare() "normSquare()"
   713   ///of a \ref Point "Point"-map
   714   ///
   715   ///Map of the \ref Point::normSquare() "normSquare()"
   716   ///of a \ref Point "Point"-map.
   717   ///\ingroup maps
   718   template<class M>
   719   class NormSquareMap
   720   {
   721     const M& _map;
   722   public:
   723 
   724     typedef typename M::Value::Value Value;
   725     typedef typename M::Key Key;
   726     ///\e
   727     NormSquareMap(const M &map) : _map(map) {}
   728     Value operator[](Key k) const {return _map[k].normSquare();}
   729   };
   730 
   731   ///Returns a \ref NormSquareMap class
   732 
   733   ///This function just returns a \ref NormSquareMap class.
   734   ///
   735   ///\ingroup maps
   736   ///\relates NormSquareMap
   737   template<class M>
   738   inline NormSquareMap<M> normSquareMap(const M &m)
   739   {
   740     return NormSquareMap<M>(m);
   741   }
   742 
   743   /// @}
   744 
   745   } //namespce dim2
   746 
   747 } //namespace lemon
   748 
   749 #endif //LEMON_DIM2_H