COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/xy.h @ 1933:a876a3d6a4c7

Last change on this file since 1933:a876a3d6a4c7 was 1927:12f289d6187f, checked in by Alpar Juttner, 18 years ago

Functions added to set the edges/corners of the bounding box directly.

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