alpar@906: /* -*- C++ -*- alpar@921: * src/lemon/xy.h - Part of LEMON, a generic C++ optimization library alpar@906: * alpar@1164: * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport alpar@1359: * (Egervary Research Group on Combinatorial Optimization, EGRES). alpar@906: * alpar@906: * Permission to use, modify and distribute this software is granted alpar@906: * provided that this copyright notice appears in all copies. For alpar@906: * precise terms see the accompanying LICENSE file. alpar@906: * alpar@906: * This software is provided "AS IS" with no warranty of any kind, alpar@906: * express or implied, and with no claim as to its suitability for any alpar@906: * purpose. alpar@906: * alpar@906: */ alpar@906: alpar@921: #ifndef LEMON_XY_H alpar@921: #define LEMON_XY_H athos@201: athos@201: #include athos@201: klao@491: ///\ingroup misc alpar@249: ///\file alpar@249: ///\brief A simple two dimensional vector and a bounding box implementation alpar@249: /// alpar@921: /// The class \ref lemon::xy "xy" implements alpar@249: ///a two dimensional vector with the usual alpar@249: /// operations. alpar@249: /// alpar@921: /// The class \ref lemon::BoundingBox "BoundingBox" can be used to determine alpar@921: /// the rectangular bounding box a set of \ref lemon::xy "xy"'s. alpar@458: /// alpar@458: ///\author Attila Bernath alpar@249: alpar@249: alpar@921: namespace lemon { alpar@431: alpar@431: /// \addtogroup misc alpar@431: /// @{ alpar@431: alpar@1257: /// A simple two dimensional vector (plainvector) implementation alpar@242: alpar@1257: /// A simple two dimensional vector (plainvector) implementation alpar@458: ///with the usual vector alpar@458: /// operators. alpar@458: /// alpar@458: ///\author Attila Bernath athos@207: template athos@207: class xy { athos@201: athos@207: public: athos@240: alpar@987: typedef T Value; alpar@964: athos@240: T x,y; athos@207: alpar@1257: ///Default constructor alpar@1257: xy() {} athos@201: athos@240: ///Constructing the instance from coordinates athos@514: xy(T a, T b) : x(a), y(b) { } athos@201: athos@201: alpar@1049: ///Conversion constructor alpar@1049: template xy(const xy &p) : x(p.x), y(p.y) {} alpar@1049: athos@207: ///Gives back the square of the norm of the vector alpar@1257: T normSquare() const { athos@240: return x*x+y*y; athos@207: }; athos@201: athos@207: ///Increments the left hand side by u alpar@1257: xy& operator +=(const xy& u) { athos@240: x += u.x; athos@240: y += u.y; athos@207: return *this; athos@207: }; athos@201: athos@207: ///Decrements the left hand side by u alpar@1257: xy& operator -=(const xy& u) { athos@240: x -= u.x; athos@240: y -= u.y; athos@207: return *this; athos@207: }; athos@201: athos@207: ///Multiplying the left hand side with a scalar alpar@1257: xy& operator *=(const T &u) { athos@240: x *= u; athos@240: y *= u; athos@207: return *this; athos@207: }; athos@207: athos@207: ///Dividing the left hand side by a scalar alpar@1257: xy& operator /=(const T &u) { athos@240: x /= u; athos@240: y /= u; athos@207: return *this; athos@207: }; athos@201: athos@207: ///Returns the scalar product of two vectors alpar@1257: T operator *(const xy& u) const { athos@240: return x*u.x+y*u.y; athos@207: }; athos@201: athos@207: ///Returns the sum of two vectors athos@207: xy operator+(const xy &u) const { athos@207: xy b=*this; athos@207: return b+=u; athos@207: }; athos@201: alpar@1049: ///Returns the neg of the vectors alpar@1049: xy operator-() const { alpar@1049: xy b=*this; alpar@1049: b.x=-b.x; b.y=-b.y; alpar@1049: return b; alpar@1049: }; alpar@1049: athos@207: ///Returns the difference of two vectors athos@207: xy operator-(const xy &u) const { athos@207: xy b=*this; athos@207: return b-=u; athos@207: }; athos@201: athos@207: ///Returns a vector multiplied by a scalar athos@207: xy operator*(const T &u) const { athos@207: xy b=*this; athos@207: return b*=u; athos@207: }; athos@201: athos@207: ///Returns a vector divided by a scalar athos@207: xy operator/(const T &u) const { athos@207: xy b=*this; athos@207: return b/=u; athos@207: }; athos@201: athos@207: ///Testing equality alpar@1257: bool operator==(const xy &u) const { athos@240: return (x==u.x) && (y==u.y); athos@207: }; athos@201: athos@207: ///Testing inequality alpar@1257: bool operator!=(xy u) const { athos@240: return (x!=u.x) || (y!=u.y); athos@207: }; athos@201: athos@207: }; athos@201: alpar@1071: ///Returns a vector multiplied by a scalar alpar@1083: alpar@1083: ///Returns a vector multiplied by a scalar alpar@1083: ///\relates xy alpar@1071: template xy operator*(const T &u,const xy &x) { alpar@1071: return x*u; alpar@1071: }; alpar@1071: alpar@814: ///Read a plainvector from a stream alpar@814: alpar@967: ///Read a plainvector from a stream alpar@814: ///\relates xy alpar@814: /// athos@207: template athos@207: inline athos@207: std::istream& operator>>(std::istream &is, xy &z) athos@207: { athos@240: athos@240: is >> z.x >> z.y; athos@207: return is; athos@207: } athos@201: alpar@814: ///Write a plainvector to a stream alpar@814: alpar@967: ///Write a plainvector to a stream alpar@814: ///\relates xy alpar@814: /// athos@207: template athos@207: inline athos@207: std::ostream& operator<<(std::ostream &os, xy z) athos@207: { athos@240: os << "(" << z.x << ", " << z.y << ")"; athos@207: return os; athos@207: } athos@207: alpar@1202: ///Rotate by 90 degrees alpar@1202: alpar@1202: ///Returns its parameter rotated by 90 degrees in positive direction. alpar@1202: ///\relates xy alpar@1202: /// alpar@1202: template alpar@1202: inline xy rot90(const xy &z) alpar@1202: { alpar@1202: return xy(-z.y,z.x); alpar@1202: } alpar@1202: alpar@1202: ///Rotate by 270 degrees alpar@1202: alpar@1202: ///Returns its parameter rotated by 90 degrees in negative direction. alpar@1202: ///\relates xy alpar@1202: /// alpar@1202: template alpar@1202: inline xy rot270(const xy &z) alpar@1202: { alpar@1202: return xy(z.y,-z.x); alpar@1202: } alpar@1202: alpar@1202: athos@244: alpar@458: /// A class to calculate or store the bounding box of plainvectors. alpar@458: alpar@458: /// A class to calculate or store the bounding box of plainvectors. alpar@458: /// alpar@458: ///\author Attila Bernath athos@244: template athos@244: class BoundingBox { athos@244: xy bottom_left, top_right; athos@244: bool _empty; athos@244: public: athos@244: athos@244: ///Default constructor: an empty bounding box athos@244: BoundingBox() { _empty = true; } athos@244: athos@244: ///Constructing the instance from one point athos@244: BoundingBox(xy a) { bottom_left=top_right=a; _empty = false; } athos@244: athos@244: ///Is there any point added athos@244: bool empty() const { athos@244: return _empty; athos@244: } athos@244: athos@244: ///Gives back the bottom left corner (if the bounding box is empty, then the return value is not defined) athos@244: xy bottomLeft() const { athos@244: return bottom_left; athos@244: }; athos@244: athos@244: ///Gives back the top right corner (if the bounding box is empty, then the return value is not defined) athos@244: xy topRight() const { athos@244: return top_right; athos@244: }; athos@244: alpar@1045: ///Gives back the bottom right corner (if the bounding box is empty, then the return value is not defined) alpar@1045: xy bottomRight() const { alpar@1045: return xy(top_right.x,bottom_left.y); alpar@1045: }; alpar@1045: alpar@1045: ///Gives back the top left corner (if the bounding box is empty, then the return value is not defined) alpar@1045: xy topLeft() const { alpar@1045: return xy(bottom_left.x,top_right.y); alpar@1045: }; alpar@1045: alpar@1045: ///Gives back the bottom of the box (if the bounding box is empty, then the return value is not defined) alpar@1045: T bottom() const { alpar@1045: return bottom_left.y; alpar@1045: }; alpar@1045: alpar@1045: ///Gives back the top of the box (if the bounding box is empty, then the return value is not defined) alpar@1045: T top() const { alpar@1045: return top_right.y; alpar@1045: }; alpar@1045: alpar@1045: ///Gives back the left side of the box (if the bounding box is empty, then the return value is not defined) alpar@1045: T left() const { alpar@1045: return bottom_left.x; alpar@1045: }; alpar@1045: alpar@1045: ///Gives back the right side of the box (if the bounding box is empty, then the return value is not defined) alpar@1045: T right() const { alpar@1045: return top_right.x; alpar@1045: }; alpar@1045: alpar@1102: ///Gives back the height of the box (if the bounding box is empty, then the return value is not defined) alpar@1102: T height() const { alpar@1102: return top_right.y-bottom_left.y; alpar@1102: }; alpar@1102: alpar@1102: ///Gives back the width of the box (if the bounding box is empty, then the return value is not defined) alpar@1102: T width() const { alpar@1102: return top_right.x-bottom_left.x; alpar@1102: }; alpar@1102: athos@244: ///Checks whether a point is inside a bounding box athos@244: bool inside(const xy& u){ athos@244: if (_empty) athos@244: return false; athos@244: else{ athos@244: return ((u.x-bottom_left.x)*(top_right.x-u.x) >= 0 && athos@244: (u.y-bottom_left.y)*(top_right.y-u.y) >= 0 ); athos@244: } athos@244: } athos@244: athos@244: ///Increments a bounding box with a point athos@244: BoundingBox& operator +=(const xy& u){ athos@244: if (_empty){ athos@244: bottom_left=top_right=u; athos@244: _empty = false; athos@244: } athos@244: else{ athos@244: if (bottom_left.x > u.x) bottom_left.x = u.x; athos@244: if (bottom_left.y > u.y) bottom_left.y = u.y; athos@244: if (top_right.x < u.x) top_right.x = u.x; athos@244: if (top_right.y < u.y) top_right.y = u.y; athos@244: } athos@244: return *this; athos@244: }; athos@244: athos@244: ///Sums a bounding box and a point athos@244: BoundingBox operator +(const xy& u){ athos@244: BoundingBox b = *this; athos@244: return b += u; athos@244: }; athos@244: athos@244: ///Increments a bounding box with an other bounding box athos@244: BoundingBox& operator +=(const BoundingBox &u){ athos@244: if ( !u.empty() ){ athos@244: *this += u.bottomLeft(); athos@244: *this += u.topRight(); athos@244: } athos@244: return *this; athos@244: }; athos@244: athos@244: ///Sums two bounding boxes athos@244: BoundingBox operator +(const BoundingBox& u){ athos@244: BoundingBox b = *this; athos@244: return b += u; athos@244: }; athos@244: athos@244: };//class Boundingbox athos@244: athos@244: alpar@1317: ///Map of x-coordinates of an xy<>-map alpar@1317: alpar@1317: ///\ingroup maps alpar@1317: /// alpar@1317: template alpar@1317: class XMap alpar@1317: { alpar@1317: M &_map; alpar@1317: public: alpar@1317: typedef typename M::Value::Value Value; alpar@1317: typedef typename M::Key Key; alpar@1317: ///\e alpar@1317: XMap(M &map) : _map(map) {} alpar@1317: Value operator[](Key k) const {return _map[k].x;} alpar@1352: void set(Key k,Value v) {_map.set(k,typename M::Value(v,_map[k].y));} alpar@1317: }; alpar@1317: alpar@1317: ///Returns an \ref XMap class alpar@1317: alpar@1317: ///This function just returns an \ref XMap class. alpar@1317: /// alpar@1317: ///\ingroup maps alpar@1317: ///\relates XMap alpar@1317: template alpar@1317: inline XMap xMap(M &m) alpar@1317: { alpar@1317: return XMap(m); alpar@1317: } alpar@1317: alpar@1317: ///Constant (read only) version of \ref XMap alpar@1317: alpar@1317: ///\ingroup maps alpar@1317: /// alpar@1317: template alpar@1317: class ConstXMap alpar@1317: { alpar@1317: const M &_map; alpar@1317: public: alpar@1317: typedef typename M::Value::Value Value; alpar@1317: typedef typename M::Key Key; alpar@1317: ///\e alpar@1317: ConstXMap(const M &map) : _map(map) {} alpar@1317: Value operator[](Key k) const {return _map[k].x;} alpar@1317: }; alpar@1317: alpar@1317: ///Returns a \ref ConstXMap class alpar@1317: alpar@1317: ///This function just returns an \ref ConstXMap class. alpar@1317: /// alpar@1317: ///\ingroup maps alpar@1317: ///\relates ConstXMap alpar@1317: template alpar@1317: inline ConstXMap xMap(const M &m) alpar@1317: { alpar@1317: return ConstXMap(m); alpar@1317: } alpar@1317: alpar@1317: ///Map of y-coordinates of an xy<>-map alpar@1317: alpar@1317: ///\ingroup maps alpar@1317: /// alpar@1317: template alpar@1317: class YMap alpar@1317: { alpar@1317: M &_map; alpar@1317: public: alpar@1317: typedef typename M::Value::Value Value; alpar@1317: typedef typename M::Key Key; alpar@1317: ///\e alpar@1317: YMap(M &map) : _map(map) {} alpar@1317: Value operator[](Key k) const {return _map[k].y;} alpar@1352: void set(Key k,Value v) {_map.set(k,typename M::Value(_map[k].x,v));} alpar@1317: }; alpar@1317: alpar@1317: ///Returns an \ref YMap class alpar@1317: alpar@1317: ///This function just returns an \ref YMap class. alpar@1317: /// alpar@1317: ///\ingroup maps alpar@1317: ///\relates YMap alpar@1317: template alpar@1317: inline YMap yMap(M &m) alpar@1317: { alpar@1317: return YMap(m); alpar@1317: } alpar@1317: alpar@1317: ///Constant (read only) version of \ref YMap alpar@1317: alpar@1317: ///\ingroup maps alpar@1317: /// alpar@1317: template alpar@1317: class ConstYMap alpar@1317: { alpar@1317: const M &_map; alpar@1317: public: alpar@1317: typedef typename M::Value::Value Value; alpar@1317: typedef typename M::Key Key; alpar@1317: ///\e alpar@1317: ConstYMap(const M &map) : _map(map) {} alpar@1317: Value operator[](Key k) const {return _map[k].y;} alpar@1317: }; alpar@1317: alpar@1317: ///Returns a \ref ConstYMap class alpar@1317: alpar@1317: ///This function just returns an \ref ConstYMap class. alpar@1317: /// alpar@1317: ///\ingroup maps alpar@1317: ///\relates ConstYMap alpar@1317: template alpar@1317: inline ConstYMap yMap(const M &m) alpar@1317: { alpar@1317: return ConstYMap(m); alpar@1317: } alpar@1317: alpar@1317: alpar@1352: ///Map of the \ref xy::normSquare() "normSquare()" of an \ref xy "xy"-map alpar@1352: alpar@1352: ///Map of the \ref xy::normSquare() "normSquare()" of an \ref xy "xy"-map alpar@1352: ///\ingroup maps alpar@1352: /// alpar@1352: template alpar@1352: class NormSquareMap alpar@1352: { alpar@1352: const M &_map; alpar@1352: public: alpar@1352: typedef typename M::Value::Value Value; alpar@1352: typedef typename M::Key Key; alpar@1352: ///\e alpar@1352: NormSquareMap(const M &map) : _map(map) {} alpar@1352: Value operator[](Key k) const {return _map[k].normSquare();} alpar@1352: }; alpar@1352: alpar@1352: ///Returns a \ref NormSquareMap class alpar@1352: alpar@1352: ///This function just returns an \ref NormSquareMap class. alpar@1352: /// alpar@1352: ///\ingroup maps alpar@1352: ///\relates NormSquareMap alpar@1352: template alpar@1352: inline NormSquareMap normSquareMap(const M &m) alpar@1352: { alpar@1352: return NormSquareMap(m); alpar@1352: } alpar@1352: alpar@431: /// @} athos@244: athos@244: alpar@921: } //namespace lemon athos@201: alpar@921: #endif //LEMON_XY_H