diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b74c633..e46382f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0) cmake_policy(SET CMP0017 NEW) # need include() with .cmake project(pip) set(pip_MAJOR 2) -set(pip_MINOR 33) +set(pip_MINOR 34) set(pip_REVISION 1) set(pip_SUFFIX ) set(pip_COMPANY SHS) diff --git a/README.md b/README.md index 6b6fe825..80da2824 100644 --- a/README.md +++ b/README.md @@ -33,4 +33,6 @@ You should add ${} to your target. ## Documentation -[Online documentation](https://shs.tools/pip/html/index.html) +[Online documentation](https://shs.tools/pip/html/en/index.html) + +[Документация на Русском языке](https://shs.tools/pip/html/ru/index.html) diff --git a/doc/images/pirect.png b/doc/images/pirect.png new file mode 100644 index 00000000..a1b8b105 Binary files /dev/null and b/doc/images/pirect.png differ diff --git a/libs/main/core/pivariant.cpp b/libs/main/core/pivariant.cpp index 9e9da078..470b50a2 100644 --- a/libs/main/core/pivariant.cpp +++ b/libs/main/core/pivariant.cpp @@ -619,6 +619,16 @@ PIRectd PIVariant::toRect() const { } +/** \brief Returns variant content as line + * \details In case of PILined type returns line value. \n + * In case of other types returns empty PILined. */ +PILined PIVariant::toLine() const { + PIByteArray ba(_content); + if (_type == PIVariant::pivLine) {PILined r; ba >> r; return r;} + return PILined(); +} + + /** \brief Returns variant content as math vector * \details In case of PIMathVectord type returns rect value. \n * In case of other types returns empty PIMathVectord. */ diff --git a/libs/main/core/pivariant.h b/libs/main/core/pivariant.h index 77313cf4..9cf38c4c 100644 --- a/libs/main/core/pivariant.h +++ b/libs/main/core/pivariant.h @@ -234,11 +234,12 @@ public: pivFile /** PIVariantTypes::File */ , pivDir /** PIVariantTypes::Dir */ , pivColor /** PIVariantTypes::Color */ , - pivPoint /** PIPoint */ , - pivRect /** PIRect */ , + pivPoint /** PIPoint */ , + pivRect /** PIRect */ , pivIODevice /** PIVariantTypes::IODevice */ , - pivMathVector /** PIMathVectord */ , - pivMathMatrix /** PIMathMatrixd */ , + pivMathVector /** PIMathVector */ , + pivMathMatrix /** PIMathMatrix */ , + pivLine /** PILine */ , pivCustom /** Custom */ = 0xFF }; @@ -333,6 +334,9 @@ public: //! Constructs variant from rect PIVariant(const PIRectd & v) {initType(v);} + //! Constructs variant from line + PIVariant(const PILined & v) {initType(v);} + //! Constructs variant from MathVector PIVariant(const PIMathVectord & v) {initType(v);} @@ -424,6 +428,9 @@ public: //! Set variant content and type to rect void setValue(const PIRectd & v) {initType(v);} + //! Set variant content and type to line + void setValue(const PILined & v) {initType(v);} + //! Set variant content and type to math vector void setValue(const PIMathVectord & v) {initType(v);} @@ -456,6 +463,7 @@ public: PIVariantTypes::IODevice toIODevice() const; PIPointd toPoint() const; PIRectd toRect() const; + PILined toLine() const; PIMathVectord toMathVector() const; PIMathMatrixd toMathMatrix() const; @@ -527,6 +535,8 @@ public: //! Assign operator PIVariant & operator =(const PIRectd & v) {setValue(v); return *this;} //! Assign operator + PIVariant & operator =(const PILined & v) {setValue(v); return *this;} + //! Assign operator PIVariant & operator =(const PIMathVectord & v) {setValue(v); return *this;} //! Assign operator PIVariant & operator =(const PIMathMatrixd & v) {setValue(v); return *this;} @@ -661,6 +671,7 @@ template<> inline PIVariantTypes::Color PIVariant::value() const {return toColor template<> inline PIVariantTypes::IODevice PIVariant::value() const {return toIODevice();} template<> inline PIPointd PIVariant::value() const {return toPoint();} template<> inline PIRectd PIVariant::value() const {return toRect();} +template<> inline PILined PIVariant::value() const {return toLine();} template<> inline PIVariant PIVariant::value() const {return *this;} template<> inline PIVariant PIVariant::fromValue(const bool & v) {return PIVariant(v);} @@ -690,6 +701,7 @@ template<> inline PIVariant PIVariant::fromValue(const PIVariantTypes::Color & v template<> inline PIVariant PIVariant::fromValue(const PIVariantTypes::IODevice & v) {return PIVariant(v);} template<> inline PIVariant PIVariant::fromValue(const PIPointd & v) {return PIVariant(v);} template<> inline PIVariant PIVariant::fromValue(const PIRectd & v) {return PIVariant(v);} +template<> inline PIVariant PIVariant::fromValue(const PILined & v) {return PIVariant(v);} template<> inline PIVariant PIVariant::fromValue(const PIMathVectord & v) {return PIVariant(v);} template<> inline PIVariant PIVariant::fromValue(const PIMathMatrixd & v) {return PIVariant(v);} template<> inline PIVariant PIVariant::fromValue(const PIVariant & v) {return PIVariant(v);} @@ -721,6 +733,7 @@ template<> inline PIVariant::Type PIVariant::getType() {r template<> inline PIVariant::Type PIVariant::getType() {return PIVariant::pivIODevice;} template<> inline PIVariant::Type PIVariant::getType() {return PIVariant::pivPoint;} template<> inline PIVariant::Type PIVariant::getType() {return PIVariant::pivRect;} +template<> inline PIVariant::Type PIVariant::getType() {return PIVariant::pivLine;} template<> inline PIVariant::Type PIVariant::getType() {return PIVariant::pivMathVector;} template<> inline PIVariant::Type PIVariant::getType() {return PIVariant::pivMathMatrix;} @@ -751,6 +764,7 @@ REGISTER_NS_VARIANT(PIVariantTypes, Color) REGISTER_NS_VARIANT(PIVariantTypes, IODevice) REGISTER_VARIANT(PIPointd) REGISTER_VARIANT(PIRectd) +REGISTER_VARIANT(PILined) REGISTER_VARIANT(PIMathVectord) REGISTER_VARIANT(PIMathMatrixd) diff --git a/libs/main/math/pigeometry.h b/libs/main/math/pigeometry.h index 65bf39d1..c3948e95 100644 --- a/libs/main/math/pigeometry.h +++ b/libs/main/math/pigeometry.h @@ -1,10 +1,25 @@ /*! \file pigeometry.h - * \brief Geometry base class + * \ingroup Math + * \brief + * \~english Geometry base classes + * \~russian Базовые геометрические классы + * \~\details + * \~english + * Add \a PIPoint, \a PILine and \a PIRect classes. + * \~russian + * Содержит классы: \a PIPoint, \a PILine и \a PIRect. + * * \~\authors + * \~english + * Ivan Pelipenko peri4ko@yandex.ru; + * Andrey Bychkov work.a.b@yandex.ru; + * \~russian + * Иван Пелипенко peri4ko@yandex.ru; + * Андрей Бычков work.a.b@yandex.ru; */ /* PIP - Platform Independent Primitives - Geometry - Ivan Pelipenko peri4ko@yandex.ru + Geometry base classes + Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -19,130 +34,11 @@ You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ - - #ifndef PIGEOMETRY_H #define PIGEOMETRY_H -#include "pimathbase.h" - -template -class PIP_EXPORT PIPoint { - static_assert(std::is_arithmetic::value, "Type must be arithmetic"); -public: - Type x; - Type y; - - PIPoint() {x = y = Type();} - PIPoint(Type x_, Type y_) {set(x_, y_);} - - PIPoint & set(Type x_, Type y_) {x = x_; y = y_; return *this;} - PIPoint & move(Type x_, Type y_) {x += x_; y += y_; return *this;} - PIPoint & move(const PIPoint & p) {x += p.x; y += p.y; return *this;} - double angleRad() const {return atan2(y, x);} - int angleDeg() const {return round(atan2(y, x) * rad2deg);} - PIPoint toPolar(bool isDeg = false) const {return PIPoint(sqrt(x*x + y*y), isDeg ? angleDeg() : angleRad());} - static PIPoint fromPolar(const PIPoint & p) {return PIPoint(p.y * cos(p.x), p.y * sin(p.x));} - - PIPoint operator +(const PIPoint & p) {return PIPoint(x + p.x, y + p.y);} - PIPoint operator +(const Type & p) {return PIPoint(x + p, y + p);} - PIPoint operator -(const PIPoint & p) {return PIPoint(x - p.x, y - p.y);} - PIPoint operator -(const Type & p) {return PIPoint(x - p, y - p);} - PIPoint operator -() {return PIPoint(-x, -y);} - PIPoint operator *(const Type & d) {return PIPoint(x * d, y * d);} - PIPoint operator /(const Type & d) {return PIPoint(x / d, y / d);} - bool operator ==(const PIPoint & p) const {return (x == p.x && y == p.y);} - bool operator !=(const PIPoint & p) const {return (x != p.x || y != p.y);} - -}; - -template -PICout operator <<(PICout & s, const PIPoint & v) {s.setControl(0, true); s << "Point{" << v.x << ", " << v.y << "}"; s.restoreControl(); return s;} - - -typedef PIPoint PIPointi; -typedef PIPoint PIPointu; -typedef PIPoint PIPointf; -typedef PIPoint PIPointd; - - - - -template -class PIP_EXPORT PIRect { - static_assert(std::is_arithmetic::value, "Type must be arithmetic"); -public: - Type x0; - Type y0; - Type x1; - Type y1; - - PIRect() {x0 = y0 = x1 = y1 = Type();} - PIRect(Type x, Type y, Type w, Type h) {set(x, y, w, h);} - PIRect(const PIPoint & tl, const PIPoint & br) {set(tl.x, tl.y, br.x, br.y);} - PIRect(const PIPoint & p0, const PIPoint & p1, const PIPoint & p2) {set(piMin(p0.x, p1.x, p2.x), piMin(p0.y, p1.y, p2.y), - piMax(p0.x, p1.x, p2.x), piMax(p0.y, p1.y, p2.y));} - - PIRect & set(Type x, Type y, Type w, Type h) {x0 = x; y0 = y; x1 = x + w; y1 = y + h; return *this;} - bool pointIn(Type x, Type y) const {return (x <= x1 && x >= x0 && y <= y1 && y >= y0);} - bool pointIn(const PIPoint & p) const {return pointIn(p.x, p.y);} - bool isEmpty() const {return (x1 - x0 == 0 && y1 - y0 == 0);} - PIRect & translate(Type x, Type y) {x0 += x; x1 += x; y0 += y; y1 += y; return *this;} - PIRect & translate(const PIPoint & p) {x0 += p.x; x1 += p.x; y0 += p.y; y1 += p.y; return *this;} - PIRect translated(Type x, Type y) {PIRect r(*this); r.translate(x, y); return r;} - PIRect translated(const PIPoint & p) {PIRect r(*this); r.translate(p); return r;} - PIRect & scale(Type x, Type y) {setWidth(width() * x); setHeight(height() * y); return *this;} - PIRect & scale(const PIPoint & p) {setWidth(width() * p.x); setHeight(height() * p.y); return *this;} - PIRect scaled(Type x, Type y) {PIRect r(*this); r.scale(x, y); return r;} - PIRect scaled(const PIPoint & p) {PIRect r(*this); r.scale(p); return r;} - PIRect & normalize() {if (x0 > x1) piSwap(x0, x1); if (y0 > y1) piSwap(y0, y1); return *this;} - PIRect normalized() {PIRect r(*this); r.normalize(); return r;} - PIRect & unite(const PIRect & r) {x0 = piMin(x0, r.x0); y0 = piMin(y0, r.y0); x1 = piMax(x1, r.x1); y1 = piMax(y1, r.y1); return *this;} - PIRect united(const PIRect & rect) {PIRect r(*this); r.unite(rect); return r;} - PIRect & intersect(const PIRect & r) {x0 = piMax(x0, r.x0); y0 = piMax(y0, r.y0); x1 = piMin(x1, r.x1); y1 = piMin(y1, r.y1); if (x0 > x1 || y0 > y1) x0 = x1 = y0 = y1 = Type(0); return *this;} - PIRect intersected(const PIRect & rect) {PIRect r(*this); r.intersect(rect); return r;} - Type top() const {return y0;} - Type left() const {return x0;} - Type right() const {return x1;} - Type bottom() const {return y1;} - Type width() const {return x1 - x0;} - Type height() const {return y1 - y0;} - PIPoint topLeft() {return PIPoint(x0, y0);} - PIPoint topRigth() {return PIPoint(x1, y0);} - PIPoint bottomLeft() {return PIPoint(x0, y1);} - PIPoint bottomRight() {return PIPoint(x1, y1);} - void setTop(Type v) {y0 = v;} - void setLeft(Type v) {x0 = v;} - void setRigth(Type v) {x1 = v;} - void setBottom(Type v) {y1 = v;} - void setWidth(Type v) {x1 = x0 + v;} - void setHeight(Type v) {y1 = y0 + v;} - - PIRect operator -() {return PIRect(-x0, -y0, -width(), -height());} - void operator +=(Type x) {translate(x, x);} - void operator +=(const PIPoint & p) {translate(p);} - void operator -=(Type x) {translate(-x, -x);} - void operator -=(const PIPoint & p) {translate(-p);} - void operator *=(Type p) {x0 *= p; x1 *= p; y0 *= p; y1 *= p;} - void operator /=(Type p) {x0 /= p; x1 /= p; y0 /= p; y1 /= p;} - void operator |=(const PIRect & r) {unite(r);} - void operator &=(const PIRect & r) {intersect(r);} - PIRect operator +(const PIPoint & p) {return PIRect(*this).translated(p);} - PIRect operator -(const PIPoint & p) {return PIRect(*this).translated(-p);} - PIRect operator |(const PIRect & r) {return PIRect(*this).united(r);} - PIRect operator &(const PIRect & r) {return PIRect(*this).intersected(r);} - bool operator ==(const PIRect & r) const {return (x0 == r.x0 && y0 == r.y0 && x1 == r.x1 && y1 == r.y10);} - bool operator !=(const PIRect & r) const {return (x0 != r.x0 || y0 != r.y0 || x1 != r.x1 || y1 != r.y10);} - -}; - -template -PICout operator <<(PICout & s, const PIRect & v) {s.setControl(0, true); s << "Rect{" << v.x0 << ", " << v.y0 << "; " << v.x1 - v.x0 << ", " << v.y1 - v.y0 << "}"; s.restoreControl(); return s;} - - -typedef PIRect PIRecti; -typedef PIRect PIRectu; -typedef PIRect PIRectf; -typedef PIRect PIRectd; +#include "pipoint.h" +#include "piline.h" +#include "pirect.h" #endif // PIGEOMETRY_H diff --git a/libs/main/math/piline.h b/libs/main/math/piline.h new file mode 100644 index 00000000..e681f40b --- /dev/null +++ b/libs/main/math/piline.h @@ -0,0 +1,179 @@ +/*! \file pirect.h + * \ingroup Math + * \brief + * \~english Two-dimensional line class + * \~russian Класс отрезка двумерной линии + * * \~\authors + * \~english + * Ivan Pelipenko peri4ko@yandex.ru; + * Andrey Bychkov work.a.b@yandex.ru; + * \~russian + * Иван Пелипенко peri4ko@yandex.ru; + * Андрей Бычков work.a.b@yandex.ru; +*/ +/* + PIP - Platform Independent Primitives + Two-dimensional line class + Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ +#ifndef PILINE_H +#define PILINE_H + +#include "pipoint.h" + + +/*! \brief + * \~english Two-dimensional line class + * \~russian Класс отрезка двумерной линии + * \~\details + * \~russian + * Этот класс описывает линию на плоскости в прямоугольной системе координат + */ +template +class PIP_EXPORT PILine { + static_assert(std::is_arithmetic::value, "Type must be arithmetic"); +public: + PIPoint p0; + PIPoint p1; + + //! + PILine() {} + + //! + PILine(const PIPoint & p0_, const PIPoint & p1_) { + p0 = p0_; + p1 = p1_; + } + + //! + PILine(Type x0, Type y0, Type x1, Type y1) { + p0.set(x0, y0); + p1.set(x1, y1); + } + + //! + PILine & set(const PIPoint & p0_, const PIPoint & p1_) { + p0 = p0_; + p1 = p1_; + return *this; + } + + //! + PILine & set(Type x0, Type y0, Type x1, Type y1) { + p0.set(x0, y0); + p1.set(x1, y1); + return *this; + } + + //! + bool isEmpty() const { + return (p0 == p1); + } + + //! + Type width() const {return piAbs(p1.x - p0.x);} + + //! + Type height() const {return piAbs(p1.y - p0.y);} + + //! + PILine & translate(Type x, Type y) { + p0.translate(x, y); + p1.translate(x, y); + return *this; + } + + //! + PILine & translate(const PIPoint & p) { + p0.translate(p); + p1.translate(p); + return *this; + } + + //! + PILine translated(Type x, Type y) const { + PILine l(*this); + l.translate(x, y); + return l; + } + + //! + PILine translated(const PIPoint & p) const { + PILine l(*this); + l.translate(p); + return l; + } + + //! + PILine & move(Type x, Type y) {return translate(x, y);} + + //! + PILine & move(const PIPoint & p) {return translate(p);} + + //! + PILine moved(Type x, Type y) const { + PILine l(*this); + l.translate(x, y); + return l; + } + + //! + PILine moved(const PIPoint & p) const { + PILine l(*this); + l.translate(p); + return l; + } + + //! + void operator +=(Type x) {translate(x, x);} + + //! + void operator +=(const PIPoint & p) {translate(p);} + + //! + void operator -=(Type x) {translate(-x, -x);} + + //! + void operator -=(const PIPoint & p) {translate(-p);} + + //! + PILine operator +(const PIPoint & p) {return translated(p);} + + //! + PILine operator -(const PIPoint & p) {return translated(-p);} + + //! + bool operator ==(const PILine & r) const {return (p0 == r.p0 && p1 == r.p1);} + + //! + bool operator !=(const PILine & r) const {return (p1 != r.p1 || p1 != r.p1);} +}; + + +template +PICout operator <<(PICout & s, const PILine & v) { + s.setControl(0, true); + s << "Line{" << v.p0 << ", " << v.p1 << "}"; + s.restoreControl(); + return s; +} + +typedef PILine PILinei; +typedef PILine PILineu; +typedef PILine PILinef; +typedef PILine PILined; + +#endif // PILINE_H diff --git a/libs/main/math/pimathbase.cpp b/libs/main/math/pimathbase.cpp index 42fd4acb..74a95f27 100644 --- a/libs/main/math/pimathbase.cpp +++ b/libs/main/math/pimathbase.cpp @@ -471,5 +471,5 @@ double randomn(double dv, double sv) { double randomd() { - return (double) randomi() / RAND_MAX * 2. - 1.; + return (double) rand() / RAND_MAX * 2. - 1.; } diff --git a/libs/main/math/pimathbase.h b/libs/main/math/pimathbase.h index ee845dd8..30f9d605 100644 --- a/libs/main/math/pimathbase.h +++ b/libs/main/math/pimathbase.h @@ -1,10 +1,20 @@ /*! \file pimathbase.h - * \brief Basic mathematical functions and defines + * \defgroup Math + * \brief + * \~english Basic mathematical functions and defines + * \~russian Базовые математические функции и дефайны + * \~\authors + * \~english + * Ivan Pelipenko peri4ko@yandex.ru; + * Andrey Bychkov work.a.b@yandex.ru; + * \~russian + * Иван Пелипенко peri4ko@yandex.ru; + * Андрей Бычков work.a.b@yandex.ru; */ /* PIP - Platform Independent Primitives Basic mathematical functions and defines - Ivan Pelipenko peri4ko@yandex.ru + Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by diff --git a/libs/main/math/pipoint.h b/libs/main/math/pipoint.h new file mode 100644 index 00000000..5b9634b6 --- /dev/null +++ b/libs/main/math/pipoint.h @@ -0,0 +1,164 @@ +//! \file pipoint.h +//! \ingroup Math +//! \brief +//! \~english Two-dimensional point class +//! \~russian Класс двумерной точки +//! \~\authors +//! \~english +//! Ivan Pelipenko peri4ko@yandex.ru; +//! Andrey Bychkov work.a.b@yandex.ru; +//! \~russian +//! Иван Пелипенко peri4ko@yandex.ru; +//! Андрей Бычков work.a.b@yandex.ru; +/* + PIP - Platform Independent Primitives + Two-dimensional point class + Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ +#ifndef PIPOINT_H +#define PIPOINT_H + +#include "pimathbase.h" + + +//! \brief +//! \~english Two-dimensional point class +//! \~russian Класс двумерной точки +template +class PIP_EXPORT PIPoint { + static_assert(std::is_arithmetic::value, "Type must be arithmetic"); +public: + Type x; + Type y; + + //! + PIPoint() {x = y = Type();} + + //! + PIPoint(Type x_, Type y_) {set(x_, y_);} + + //! + PIPoint & set(Type x_, Type y_) { + x = x_; + y = y_; + return *this; + } + + //! + PIPoint & set(const PIPoint & p) { + x = p.x; + y = p.y; + return *this; + } + + //! + PIPoint & translate(Type x_, Type y_) { + x += x_; + y += y_; + return *this; + } + + //! + PIPoint & translate(const PIPoint & p) { + x += p.x; + y += p.y; + return *this; + } + + //! + PIPoint translated(Type x_, Type y_) const { + PIPoint rp(*this); + rp.translate(x_, y_); + return rp; + } + + //! + PIPoint translated(const PIPoint & p) const { + PIPoint rp(*this); + rp.translate(p); + return rp; + } + + //! + PIPoint & move(Type x_, Type y_) {return translate(x_, y_);} + + //! + PIPoint & move(const PIPoint & p) {return translate(p);} + + //! + PIPoint moved(Type x_, Type y_) const { + PIPoint rp(*this); + rp.translate(x_, y_); + return rp; + } + + //! + PIPoint moved(const PIPoint & p) const { + PIPoint rp(*this); + rp.translate(p); + return rp; + } + + //! + double angleRad() const {return atan2(y, x);} + + //! + double angleDeg() const {return toDeg(atan2(y, x));} + + //! + PIPoint toPolar(bool isDeg = false) const {return PIPoint(sqrt(x*x + y*y), isDeg ? angleDeg() : angleRad());} + + //! + static PIPoint fromPolar(const PIPoint & p) {return PIPoint(p.y * cos(p.x), p.y * sin(p.x));} + + //! + void operator +=(const PIPoint & p) {translate(p);} + + //! + PIPoint operator +(const PIPoint & p) {return PIPoint(x + p.x, y + p.y);} + + //! + PIPoint operator +(const Type & p) {return PIPoint(x + p, y + p);} + + //! + PIPoint operator -(const PIPoint & p) {return PIPoint(x - p.x, y - p.y);} + + //! + PIPoint operator -(const Type & p) {return PIPoint(x - p, y - p);} + + //! + PIPoint operator -() {return PIPoint(-x, -y);} + + //! + bool operator ==(const PIPoint & p) const {return (x == p.x && y == p.y);} + + //! + bool operator !=(const PIPoint & p) const {return (x != p.x || y != p.y);} +}; + + +template +PICout operator <<(PICout & s, const PIPoint & v) { + s.setControl(0, true); + s << "Point{" << v.x << ", " << v.y << "}"; + s.restoreControl(); + return s; +} + + +typedef PIPoint PIPointi; +typedef PIPoint PIPointu; +typedef PIPoint PIPointf; +typedef PIPoint PIPointd; + +#endif // PIPOINT_H diff --git a/libs/main/math/pirect.h b/libs/main/math/pirect.h new file mode 100644 index 00000000..91b78b75 --- /dev/null +++ b/libs/main/math/pirect.h @@ -0,0 +1,363 @@ +//! \file pirect.h +//! \ingroup Math +//! \brief +//! \~english Rect class +//! \~russian Класс прямоугольника +//! \~\authors +//! \~english +//! Ivan Pelipenko peri4ko@yandex.ru; +//! Andrey Bychkov work.a.b@yandex.ru; +//! \~russian +//! Иван Пелипенко peri4ko@yandex.ru; +//! Андрей Бычков work.a.b@yandex.ru; +/* + PIP - Platform Independent Primitives + Rect class + Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ +#ifndef PIRECT_H +#define PIRECT_H + +#include "pipoint.h" + + +//! \brief +//! \~english Rect class +//! \~russian Класс прямоугольника +//! \~\details +//! \~russian +//! Этот класс описывает прямоугольник на плоскости в прямоугольной системе координат +template +class PIP_EXPORT PIRect { + static_assert(std::is_arithmetic::value, "Type must be arithmetic"); +public: + //! + PIRect() {} + + //! \brief + //! \~russian Конструктор прямоугольника из координат левого нижнего угла и размеров ширины и высоты + PIRect(Type left_, Type bottom_, Type width_, Type height_) { + set(left_, bottom_, width_, height_); + normalize(); + } + + //! \brief + //! \~russian Конструктор прямоугольника из координат левого нижнего угла и правого верхнего угла + PIRect(const PIPoint & bottom_left, const PIPoint & top_right) { + bl = bottom_left; + tr = top_right; + normalize(); + } + +// PIRect(const PIPoint & p0, const PIPoint & p1, const PIPoint & p2) { +// set(piMin(p0.x, p1.x, p2.x), piMin(p0.y, p1.y, p2.y), +// piMax(p0.x, p1.x, p2.x), piMax(p0.y, p1.y, p2.y)); +// } + + //! + PIRect & set(Type left_, Type bottom_, Type width_, Type height_) { + bl = PIPoint(left_, bottom_); + tr = PIPoint(left_ + width_, bottom_ + height_); + return normalize(); + } + + //! + PIRect & set(const PIPoint & top_left, const PIPoint & bottom_right) { + bl = top_left; + tr = bottom_right; + return normalize(); + } + + //! \brief + //! \~russian Возвращает true если точка с указанными координатами принадлежит прямоугольнику + bool pointIn(Type x, Type y) const { + return (x <= bl.x && x >= tr.x && y <= bl.y && y >= tr.y); + } + + //! \brief + //! \~russian Возвращает true если точка с указанными координатами принадлежит прямоугольнику + bool pointIn(const PIPoint & p) const { + return pointIn(p.x, p.y); + } + + //! + bool isEmpty() const { + return (width() == 0 && height() == 0); + } + + //! + PIRect & translate(Type x, Type y) { + bl.translate(x, y); + tr.translate(x, y); + return *this; + } + + //! + PIRect & translate(const PIPoint & p) { + bl.translate(p); + tr.translate(p); + return *this; + } + + //! + PIRect translated(Type x, Type y) const { + PIRect r(*this); + r.translate(x, y); + return r; + } + + //! + PIRect translated(const PIPoint & p) const { + PIRect r(*this); + r.translate(p); + return r; + } + + //! + PIRect & move(Type x, Type y) {return translate(x, y);} + + //! + PIRect & move(const PIPoint & p) {return translate(p);} + + //! + PIRect moved(Type x, Type y) const { + PIRect r(*this); + r.translate(x, y); + return r; + } + + //! + PIRect moved(const PIPoint & p) const { + PIRect r(*this); + r.translate(p); + return r; + } + + //! + PIRect & scale(Type x, Type y) { + setWidth(width() * x); + setHeight(height() * y); + return normalize(); + } + + //! + PIRect & scale(Type s) {return scale(s, s);} + + //! + PIRect & scale(const PIPoint & p) {return scale(p.x, p.y);} + + //! + PIRect scaled(Type x, Type y) const { + PIRect r(*this); + r.scale(x, y); + return r; + } + + //! + PIRect scaled(Type s) const { + PIRect r(*this); + r.scale(s); + return r; + } + + //! + PIRect scaled(const PIPoint & p) const { + PIRect r(*this); + r.scale(p); + return r; + } + + //! + PIRect & normalize() { + if (bl.x > tr.x) piSwap(bl.x, tr.x); + if (bl.y > tr.y) piSwap(bl.y, tr.y); + return *this; + } + + //! + PIRect normalized() const { + PIRect r(*this); + r.normalize(); + return r; + } + + //! + PIRect & unite(const PIRect & r) { + bl.x = piMax(bl.x, r.left()); + bl.y = piMax(bl.y, r.bottom()); + tr.x = piMin(tr.x, r.right()); + tr.y = piMin(tr.y, r.top()); + return normalize(); + } + + //! + PIRect united(const PIRect & rect) const { + PIRect r(*this); + r.unite(rect); + return r; + } + + //! + PIRect & intersect(const PIRect & r) { + bl.x = piMax(bl.x, r.left()); + bl.y = piMax(bl.y, r.bottom()); + tr.x = piMin(tr.x, r.right()); + tr.y = piMin(tr.y, r.top()); + if (bl.x > tr.x || bl.y > tr.y) bl = tr = PIPoint(); + return *this; + } + + //! + PIRect intersected(const PIRect & rect) const { + PIRect r(*this); + r.intersect(rect); + return r; + } + + //! + Type top() const {return tr.y;} + + //! + Type left() const {return bl.x;} + + //! + Type right() const {return tr.x;} + + //! + Type bottom() const {return bl.y;} + + //! + Type width() const {return tr.x - bl.x;} + + //! + Type height() const {return tr.y - bl.y;} + + //! + PIPoint topLeft() const {return PIPoint(bl.x, tr.y);} + + //! + PIPoint topRigth() const {return tr;} + + //! + PIPoint bottomLeft() const {return bl;} + + //! + PIPoint bottomRight() const {return PIPoint(tr.x, bl.y);} + + //! + PIPoint center() const {return bl.moved(width()/2, height()/2);} + + //! + void setTop(Type v) {tr.y = v; normalize();} + + //! + void setLeft(Type v) {bl.x = v; normalize();} + + //! + void setRigth(Type v) {tr.x = v; normalize();} + + //! + void setBottom(Type v) {bl.y = v; normalize();} + + //! + void setWidth(Type v) {setTop(bl.x + v);} + + //! + void setHeight(Type v) {setRigth(bl.y + v);} + + //! + void setTopLeft(const PIPoint & p) {setLeft(p.x); setTop(p.y);} + + //! + void setBottomRight(const PIPoint & p) {setRigth(p.x); setBottom(p.y);} + + //! + void setBottomLeft(const PIPoint & p) {bl = p; normalize();} + + //! + void setTopRigth(const PIPoint & p) {tr = p; normalize();} + + //! + void setCenter(const PIPoint & p) { + Type w = width(); + Type h = height(); + bl = p.translated(-w/2, -h/2); + tr = PIPoint(bl.x + w, bl.y + h); + } + + //! + void setSize(Type w, Type h) { + tr = PIPoint(bl.x + w, bl.y + h); + normalize(); + } + + //! + void operator +=(Type x) {translate(x, x);} + + //! + void operator +=(const PIPoint & p) {translate(p);} + + //! + void operator -=(Type x) {translate(-x, -x);} + + //! + void operator -=(const PIPoint & p) {translate(-p);} + + //! + void operator |=(const PIRect & r) {unite(r);} + + //! + void operator &=(const PIRect & r) {intersect(r);} + + //! + PIRect operator +(const PIPoint & p) {return translated(p);} + + //! + PIRect operator -(const PIPoint & p) {return translated(-p);} + + //! + PIRect operator |(const PIRect & r) {return united(r);} + + //! + PIRect operator &(const PIRect & r) {return intersected(r);} + + //! + bool operator ==(const PIRect & r) const {return (bl == r.bl && tr == r.tr);} + + //! + bool operator !=(const PIRect & r) const {return (bl != r.bl || tr != r.tr);} + +private: + PIPoint bl; + PIPoint tr; +}; + + +template +PICout operator <<(PICout & s, const PIRect & v) { + s.setControl(0, true); + s << "Rect{" << v.bottomLeft() << ":" << v.width() << "x" << v.height() << "}"; + s.restoreControl(); + return s; +} + + +typedef PIRect PIRecti; +typedef PIRect PIRectu; +typedef PIRect PIRectf; +typedef PIRect PIRectd; + +#endif // PIRECT_H