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