// // Classes supporting the 2-dimensional graphics // #ifndef R2GRAPH_H #define R2GRAPH_H // Contains the definitions of following classes: // R2Vector, R2Point, R2Rectangle, // I2Vector, I2Point, I2Rectangle // The "R2" prefix means that the object has real coordinates, // "I2" means integer coordinates. // // In case of real coordinates, we use the normal "mathematical" // coordinate system, where Y-axis goes up. In case of integer // coordinates, the Y axis goes down, so that the y-coordinate // of the bottom of rectangle is greater than the y-coordinate // of the top. Such integer coordinates are used by default in // any window system (so called "Text" mode). #include class R2Vector { public: double x; double y; R2Vector(): // Default constructor x(0.), y(0.) {} R2Vector(const R2Vector& v): // Copy-constructor x(v.x), y(v.y) {} R2Vector(double xx, double yy): x(xx), y(yy) {} R2Vector& operator=(const R2Vector& v) { // Copy-operator x = v.x; y = v.y; return *this; } ~R2Vector() {} // Destructor R2Vector operator+(const R2Vector& v) const { return R2Vector(x+v.x, y+v.y); } R2Vector& operator+=(const R2Vector& v) { x += v.x; y += v.y; return *this; } R2Vector operator-(const R2Vector& v) const { return R2Vector(x-v.x, y-v.y); } R2Vector& operator-=(const R2Vector& v) { x -= v.x; y -= v.y; return *this; } R2Vector operator*(double c) const { return R2Vector(x*c, y*c); } friend R2Vector operator*(double c, const R2Vector& v); R2Vector& operator*=(double c) { x *= c; y *= c; return *this; } double operator*(const R2Vector& v) const { // Scalar product return x*v.x + y*v.y; } double length() const { return sqrt(x*x + y*y); } R2Vector& normalize() { // Make length = 1 if (x != 0. || y != 0.) { double l = length(); x /= l; y /= l; } return *this; } R2Vector normal() const { // Normal to this vector return R2Vector(-y, x); } double angle(const R2Vector& v) const { // Angle from this vector to v double xx = (*this) * v; double yy = (*this) * normal(); return atan2(yy, xx); } // Comparings bool operator==(const R2Vector& v) const { return (x == v.x && y == v.y); } bool operator!=(const R2Vector& v) const { return !operator==(v); } bool operator>=(const R2Vector& v) const { return (x > v.x || (x == v.x && y >= v.y)); } bool operator>(const R2Vector& v) const { return (x > v.x || (x == v.x && y > v.y)); } bool operator<(const R2Vector& v) const { return !operator>=(v); } bool operator<=(const R2Vector& v) const { return !operator>(v); } }; inline R2Vector operator*(double c, const R2Vector& v) { return R2Vector(c*v.x, c*v.y); } class R2Point { public: double x; double y; R2Point(): // Default constructor x(0.), y(0.) {} R2Point(const R2Point& p): // Copy-constructor x(p.x), y(p.y) {} R2Point(double xx, double yy): x(xx), y(yy) {} R2Point& operator=(const R2Point& p) { // Copy-operator x = p.x; y = p.y; return *this; } ~R2Point() {} // Destructor R2Point operator+(const R2Point& p) const { return R2Point(x+p.x, y+p.y); } R2Point operator+(const R2Vector& v) const { return R2Point(x+v.x, y+v.y); } R2Point& operator+=(const R2Point& p) { x += p.x; y += p.y; return *this; } R2Point& operator+=(const R2Vector& v) { x += v.x; y += v.y; return *this; } R2Vector operator-(const R2Point& p) const { return R2Vector(x-p.x, y-p.y); } R2Point operator-(const R2Vector& v) const { return R2Point(x-v.x, y-v.y); } R2Point& operator-=(const R2Vector& v) { x -= v.x; y -= v.y; return *this; } R2Point& operator-=(const R2Point& p) { x -= p.x; y -= p.y; return *this; } R2Point operator*(double c) const { return R2Point(x*c, y*c); } friend R2Point operator*(double c, const R2Point& p); R2Point& operator*=(double c) { x *= c; y *= c; return *this; } // Comparings bool operator==(const R2Point& p) const { return (x == p.x && y == p.y); } bool operator!=(const R2Point& p) const { return !operator==(p); } bool operator>=(const R2Point& p) const { return (x > p.x || (x == p.x && y >= p.y)); } bool operator>(const R2Point& p) const { return (x > p.x || (x == p.x && y > p.y)); } bool operator<(const R2Point& p) const { return !operator>=(p); } bool operator<=(const R2Point& p) const { return !operator>(p); } }; inline R2Point operator*(double c, const R2Point& p) { return R2Point(c*p.x, c*p.y); } class R2Rectangle { double l; // left double b; // bottom double w; // width double h; // height public: R2Rectangle(): l(0.), b(0.), w(0.), h(0.) {} R2Rectangle(double left, double bottom, double width, double height): l(left), b(bottom), w(width), h(height) {} R2Rectangle(const R2Point& leftBottom, double width, double height): l(leftBottom.x), b(leftBottom.y), w(width), h(height) {} R2Rectangle(const R2Rectangle& r): l(r.l), b(r.b), w(r.w), h(r.h) {} ~R2Rectangle() {} R2Rectangle& operator=(const R2Rectangle& r) { l = r.l; b = r.b; w = r.w; h = r.h; return *this; } double left() const { return l; } double right() const { return l + w; } double bottom() const { return b; } double top() const { return b + h; } double width() const { return w; } double height() const { return h; } R2Point leftBottom() const { return R2Point(l, b); } R2Point rightTop() const { return R2Point(l + w, b + h); } void setLeft(double left) { l = left; } void setBottom(double bottom) { b = bottom; } void setWidth(double width) { w = width; } void setHeight(double height) { h = height; } double getXMin() const { return l; } double getXMax() const { return l + w; } double getYMin() const { return b; } double getYMax() const { return b + h; } bool contains(const R2Point& p) const { return ( l <= p.x && p.x < l + w && b <= p.y && p.y < b + h ); } R2Rectangle& shift(const R2Vector& v) { l += v.x; b += v.y; return *this; } R2Rectangle& extend(const R2Vector& v) { w += v.x; h += v.y; return *this; } bool empty() const { return (w < 0. || h < 0.); } R2Rectangle& intersect(const R2Rectangle r) { double newLeft = left(); if (r.left() > newLeft) newLeft = r.left(); double newRight = right(); if (r.right() < newRight) newRight = r.right(); double newBottom = bottom(); if (r.bottom() > newBottom) newBottom = r.bottom(); double newTop = top(); if (r.top() < newTop) newTop = r.top(); l = newLeft; b = newBottom; w = newRight - newLeft; h = newTop - newBottom; return *this; } R2Rectangle& add(const R2Rectangle r) { double newLeft = left(); if (r.left() < newLeft) newLeft = r.left(); double newRight = right(); if (r.right() > newRight) newRight = r.right(); double newBottom = bottom(); if (r.bottom() < newBottom) newBottom = r.bottom(); double newTop = top(); if (r.top() > newTop) newTop = r.top(); l = newLeft; b = newBottom; w = newRight - newLeft; h = newTop - newBottom; return *this; } }; class I2Vector { public: int x; int y; I2Vector(): // Default constructor x(0), y(0) {} I2Vector(const I2Vector& v): // Copy-constructor x(v.x), y(v.y) {} I2Vector(int xx, int yy): x(xx), y(yy) {} I2Vector& operator=(const I2Vector& v) { // Copy-operator x = v.x; y = v.y; return *this; } ~I2Vector() {} // Destructor I2Vector operator+(const I2Vector& v) const { return I2Vector(x+v.x, y+v.y); } I2Vector& operator+=(const I2Vector& v) { x += v.x; y += v.y; return *this; } I2Vector operator-(const I2Vector& v) const { return I2Vector(x-v.x, y-v.y); } I2Vector& operator-=(const I2Vector& v) { x -= v.x; y -= v.y; return *this; } I2Vector operator*(int c) const { return I2Vector(x*c, y*c); } friend I2Vector operator*(int c, const I2Vector& v); I2Vector& operator*=(int c) { x *= c; y *= c; return *this; } int operator*(const I2Vector& v) const { // Scalar product return x*v.x + y*v.y; } double length() const { return sqrt(x*x + y*y); } I2Vector normal() const { // Normal to this vector return I2Vector(-y, x); } double angle(const I2Vector& v) const { // Angle from this vector to v double xx = (*this) * v; double yy = (*this) * normal(); return atan2(yy, xx); } // Comparings bool operator==(const I2Vector& v) const { return (x == v.x && y == v.y); } bool operator!=(const I2Vector& v) const { return !operator==(v); } bool operator>=(const I2Vector& v) const { return (x > v.x || (x == v.x && y >= v.y)); } bool operator>(const I2Vector& v) const { return (x > v.x || (x == v.x && y > v.y)); } bool operator<(const I2Vector& v) const { return !operator>=(v); } bool operator<=(const I2Vector& v) const { return !operator>(v); } }; inline I2Vector operator*(int c, const I2Vector& v) { return I2Vector(c*v.x, c*v.y); } class I2Point { public: int x; int y; I2Point(): // Default constructor x(0), y(0) {} I2Point(const I2Point& p): // Copy-constructor x(p.x), y(p.y) {} I2Point(int xx, int yy): x(xx), y(yy) {} I2Point& operator=(const I2Point& p) { // Copy-operator x = p.x; y = p.y; return *this; } ~I2Point() {} // Destructor I2Point operator+(const I2Point& p) const { return I2Point(x+p.x, y+p.y); } I2Point operator+(const I2Vector& v) const { return I2Point(x+v.x, y+v.y); } I2Point& operator+=(const I2Point& p) { x += p.x; y += p.y; return *this; } I2Point& operator+=(const I2Vector& v) { x += v.x; y += v.y; return *this; } I2Vector operator-(const I2Point& p) const { return I2Vector(x-p.x, y-p.y); } I2Point operator-(const I2Vector& v) const { return I2Point(x-v.x, y-v.y); } I2Point& operator-=(const I2Vector& v) { x -= v.x; y -= v.y; return *this; } I2Point& operator-=(const I2Point& p) { x -= p.x; y -= p.y; return *this; } I2Point operator*(int c) const { return I2Point(x*c, y*c); } friend I2Point operator*(int c, const I2Point& p); I2Point& operator*=(int c) { x *= c; y *= c; return *this; } // Comparings bool operator==(const I2Point& p) const { return (x == p.x && y == p.y); } bool operator!=(const I2Point& p) const { return !operator==(p); } bool operator>=(const I2Point& p) const { return (x > p.x || (x == p.x && y >= p.y)); } bool operator>(const I2Point& p) const { return (x > p.x || (x == p.x && y > p.y)); } bool operator<(const I2Point& p) const { return !operator>=(p); } bool operator<=(const I2Point& p) const { return !operator>(p); } }; inline I2Point operator*(int c, const I2Point& p) { return I2Point(c*p.x, c*p.y); } class I2Rectangle { // Y-coordinate axis in case of I2Rectangle goes down, so that // y-coordinate of top is less than y-coordinate of bottom int l; // left int t; // top int w; // width int h; // height public: I2Rectangle(): l(0), t(0), w(0), h(0) {} I2Rectangle(int left, int top, int width, int height): l(left), t(top), w(width), h(height) {} I2Rectangle(const I2Point& leftTop, int width, int height): l(leftTop.x), t(leftTop.y), w(width), h(height) {} I2Rectangle(const I2Rectangle& r): l(r.l), t(r.t), w(r.w), h(r.h) {} ~I2Rectangle() {} I2Rectangle& operator=(const I2Rectangle& r) { l = r.l; t = r.t; w = r.w; h = r.h; return *this; } int left() const { return l; } int right() const { return l + w; } int top() const { return t; } int bottom() const { return t + h; } int width() const { return w; } int height() const { return h; } I2Point leftTop() const { return I2Point(l, t); } I2Point rightBottom() const { return I2Point(l + w, t + h); } void setLeft(int left) { l = left; } void setTop(int top) { t = top; } void setWidth(int width) { w = width; } void setHeight(int height) { h = height; } double getXMin() const { return l; } double getXMax() const { return l + w; } double getYMin() const { return t; } double getYMax() const { return t + h; } bool contains(const I2Point& p) const { return ( l <= p.x && p.x < l + w && t <= p.y && p.y < t + h ); } I2Rectangle& shift(const I2Vector& v) { l += v.x; t += v.y; return *this; } I2Rectangle& extend(const I2Vector& v) { w += v.x; h += v.y; return *this; } bool empty() const { return (w < 0. || h < 0.); } I2Rectangle& intersect(const I2Rectangle r) { int newLeft = left(); if (r.left() > newLeft) newLeft = r.left(); int newRight = right(); if (r.right() < newRight) newRight = r.right(); int newTop = top(); if (r.top() > newTop) newTop = r.top(); int newBottom = bottom(); if (r.bottom() < newBottom) newBottom = r.bottom(); l = newLeft; t = newTop; w = newRight - newLeft; h = newBottom - newTop; return *this; } I2Rectangle& add(const I2Rectangle r) { int newLeft = left(); if (r.left() < newLeft) newLeft = r.left(); int newRight = right(); if (r.right() > newRight) newRight = r.right(); int newTop = top(); if (r.top() < newTop) newTop = r.top(); int newBottom = bottom(); if (r.bottom() > newBottom) newBottom = r.bottom(); l = newLeft; t = newTop; w = newRight - newLeft; h = newBottom - newTop; return *this; } }; #endif