Files
pip/libs/main/math/pirect.h
2022-03-21 12:20:11 +03:00

364 lines
8.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! \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 <http://www.gnu.org/licenses/>.
*/
#ifndef PIRECT_H
#define PIRECT_H
#include "pipoint.h"
//! \brief
//! \~english Rect class
//! \~russian Класс прямоугольника
//! \~\details
//! \~russian
//! Этот класс описывает прямоугольник на плоскости в прямоугольной системе координат
template<typename Type>
class PIP_EXPORT PIRect {
static_assert(std::is_arithmetic<Type>::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<Type> & bottom_left, const PIPoint<Type> & top_right) {
bl = bottom_left;
tr = top_right;
normalize();
}
// PIRect(const PIPoint<Type> & p0, const PIPoint<Type> & p1, const PIPoint<Type> & p2) {
// set(piMin<Type>(p0.x, p1.x, p2.x), piMin<Type>(p0.y, p1.y, p2.y),
// piMax<Type>(p0.x, p1.x, p2.x), piMax<Type>(p0.y, p1.y, p2.y));
// }
//!
PIRect<Type> & set(Type left_, Type bottom_, Type width_, Type height_) {
bl = PIPoint<Type>(left_, bottom_);
tr = PIPoint<Type>(left_ + width_, bottom_ + height_);
return normalize();
}
//!
PIRect<Type> & set(const PIPoint<Type> & top_left, const PIPoint<Type> & 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<Type> & p) const {
return pointIn(p.x, p.y);
}
//!
bool isEmpty() const {
return (width() == 0 && height() == 0);
}
//!
PIRect<Type> & translate(Type x, Type y) {
bl.translate(x, y);
tr.translate(x, y);
return *this;
}
//!
PIRect<Type> & translate(const PIPoint<Type> & p) {
bl.translate(p);
tr.translate(p);
return *this;
}
//!
PIRect<Type> translated(Type x, Type y) const {
PIRect<Type> r(*this);
r.translate(x, y);
return r;
}
//!
PIRect<Type> translated(const PIPoint<Type> & p) const {
PIRect<Type> r(*this);
r.translate(p);
return r;
}
//!
PIRect<Type> & move(Type x, Type y) {return translate(x, y);}
//!
PIRect<Type> & move(const PIPoint<Type> & p) {return translate(p);}
//!
PIRect<Type> moved(Type x, Type y) const {
PIRect<Type> r(*this);
r.translate(x, y);
return r;
}
//!
PIRect<Type> moved(const PIPoint<Type> & p) const {
PIRect<Type> r(*this);
r.translate(p);
return r;
}
//!
PIRect<Type> & scale(Type x, Type y) {
setWidth(width() * x);
setHeight(height() * y);
return normalize();
}
//!
PIRect<Type> & scale(Type s) {return scale(s, s);}
//!
PIRect<Type> & scale(const PIPoint<Type> & p) {return scale(p.x, p.y);}
//!
PIRect<Type> scaled(Type x, Type y) const {
PIRect<Type> r(*this);
r.scale(x, y);
return r;
}
//!
PIRect<Type> scaled(Type s) const {
PIRect<Type> r(*this);
r.scale(s);
return r;
}
//!
PIRect<Type> scaled(const PIPoint<Type> & p) const {
PIRect<Type> r(*this);
r.scale(p);
return r;
}
//!
PIRect<Type> & normalize() {
if (bl.x > tr.x) piSwap<Type>(bl.x, tr.x);
if (bl.y > tr.y) piSwap<Type>(bl.y, tr.y);
return *this;
}
//!
PIRect<Type> normalized() const {
PIRect<Type> r(*this);
r.normalize();
return r;
}
//!
PIRect<Type> & unite(const PIRect<Type> & r) {
bl.x = piMax<Type>(bl.x, r.left());
bl.y = piMax<Type>(bl.y, r.bottom());
tr.x = piMin<Type>(tr.x, r.right());
tr.y = piMin<Type>(tr.y, r.top());
return normalize();
}
//!
PIRect<Type> united(const PIRect<Type> & rect) const {
PIRect<Type> r(*this);
r.unite(rect);
return r;
}
//!
PIRect<Type> & intersect(const PIRect<Type> & r) {
bl.x = piMax<Type>(bl.x, r.left());
bl.y = piMax<Type>(bl.y, r.bottom());
tr.x = piMin<Type>(tr.x, r.right());
tr.y = piMin<Type>(tr.y, r.top());
if (bl.x > tr.x || bl.y > tr.y) bl = tr = PIPoint<Type>();
return *this;
}
//!
PIRect<Type> intersected(const PIRect<Type> & rect) const {
PIRect<Type> 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<Type> topLeft() const {return PIPoint<Type>(bl.x, tr.y);}
//!
PIPoint<Type> topRigth() const {return tr;}
//!
PIPoint<Type> bottomLeft() const {return bl;}
//!
PIPoint<Type> bottomRight() const {return PIPoint<Type>(tr.x, bl.y);}
//!
PIPoint<Type> 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<Type> & p) {setLeft(p.x); setTop(p.y);}
//!
void setBottomRight(const PIPoint<Type> & p) {setRigth(p.x); setBottom(p.y);}
//!
void setBottomLeft(const PIPoint<Type> & p) {bl = p; normalize();}
//!
void setTopRigth(const PIPoint<Type> & p) {tr = p; normalize();}
//!
void setCenter(const PIPoint<Type> & p) {
Type w = width();
Type h = height();
bl = p.translated(-w/2, -h/2);
tr = PIPoint<Type>(bl.x + w, bl.y + h);
}
//!
void setSize(Type w, Type h) {
tr = PIPoint<Type>(bl.x + w, bl.y + h);
normalize();
}
//!
void operator +=(Type x) {translate(x, x);}
//!
void operator +=(const PIPoint<Type> & p) {translate(p);}
//!
void operator -=(Type x) {translate(-x, -x);}
//!
void operator -=(const PIPoint<Type> & p) {translate(-p);}
//!
void operator |=(const PIRect<Type> & r) {unite(r);}
//!
void operator &=(const PIRect<Type> & r) {intersect(r);}
//!
PIRect<Type> operator +(const PIPoint<Type> & p) {return translated(p);}
//!
PIRect<Type> operator -(const PIPoint<Type> & p) {return translated(-p);}
//!
PIRect<Type> operator |(const PIRect<Type> & r) {return united(r);}
//!
PIRect<Type> operator &(const PIRect<Type> & r) {return intersected(r);}
//!
bool operator ==(const PIRect<Type> & r) const {return (bl == r.bl && tr == r.tr);}
//!
bool operator !=(const PIRect<Type> & r) const {return (bl != r.bl || tr != r.tr);}
private:
PIPoint<Type> bl;
PIPoint<Type> tr;
};
template<typename Type>
PICout operator <<(PICout & s, const PIRect<Type> & v) {
s.setControl(0, true);
s << "Rect{" << v.bottomLeft() << ":" << v.width() << "x" << v.height() << "}";
s.restoreControl();
return s;
}
typedef PIRect<int> PIRecti;
typedef PIRect<uint> PIRectu;
typedef PIRect<float> PIRectf;
typedef PIRect<double> PIRectd;
#endif // PIRECT_H