Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Zolotarev <deathbaba@gmail.com>2010-12-05 19:24:16 +0300
committerAlex Zolotarev <alex@maps.me>2015-09-22 22:33:57 +0300
commitd6e12b7ce4bcbf0ccd1c07eb25de143422913c34 (patch)
treea7e910c330ce4da9b4f2d8be76067adece2561c4 /geometry/rect2d.hpp
One Month In Minsk. Made in Belarus.
Diffstat (limited to 'geometry/rect2d.hpp')
-rw-r--r--geometry/rect2d.hpp289
1 files changed, 289 insertions, 0 deletions
diff --git a/geometry/rect2d.hpp b/geometry/rect2d.hpp
new file mode 100644
index 0000000000..40109415bf
--- /dev/null
+++ b/geometry/rect2d.hpp
@@ -0,0 +1,289 @@
+#pragma once
+
+#include "point2d.hpp"
+#include "../base/assert.hpp"
+#include "../base/internal/message.hpp"
+
+#include "../std/algorithm.hpp"
+#include "../std/limits.hpp"
+
+#include "../base/start_mem_debug.hpp"
+
+namespace m2
+{
+ namespace impl
+ {
+ template <typename T, bool has_sign> struct min_max_value;
+ template <typename T> struct min_max_value<T, true>
+ {
+ T get_min() { return numeric_limits<T>::max(); }
+ T get_max() { return -get_min(); }
+ };
+ template <typename T> struct min_max_value<T, false>
+ {
+ T get_min() { return numeric_limits<T>::max(); }
+ T get_max() { return numeric_limits<T>::min(); }
+ };
+ }
+
+
+ template <typename T>
+ class Rect
+ {
+ T m_minX, m_minY, m_maxX, m_maxY;
+
+ public:
+ Rect() { MakeEmpty(); }
+ Rect(T minX, T minY, T maxX, T maxY)
+ : m_minX(minX), m_minY(minY), m_maxX(maxX), m_maxY(maxY)
+ {
+ ASSERT ( minX <= maxX, (minX, maxX) );
+ ASSERT ( minY <= maxY, (minY, maxY) );
+ }
+ Rect(Point<T> const & p1, Point<T> const & p2)
+ : m_minX(min(p1.x, p2.x)), m_minY(min(p1.y, p2.y)),
+ m_maxX(max(p1.x, p2.x)), m_maxY(max(p1.y, p2.y))
+ {
+ }
+
+ template <typename U>
+ explicit Rect(Rect<U> const & src)
+ : m_minX(src.minX()), m_minY(src.minY()), m_maxX(src.maxX()), m_maxY(src.maxY())
+ {
+ }
+
+ void MakeEmpty()
+ {
+ m_minX = m_minY = impl::min_max_value<T, numeric_limits<T>::is_signed>().get_min();
+ m_maxX = m_maxY = impl::min_max_value<T, numeric_limits<T>::is_signed>().get_max();
+ }
+
+ void Add(m2::Point<T> const & p)
+ {
+ m_minX = min(p.x, m_minX);
+ m_minY = min(p.y, m_minY);
+ m_maxX = max(p.x, m_maxX);
+ m_maxY = max(p.y, m_maxY);
+ }
+
+ void Add(m2::Rect<T> const & r)
+ {
+ m_minX = min(r.m_minX, m_minX);
+ m_minY = min(r.m_minY, m_minY);
+ m_maxX = max(r.m_maxX, m_maxX);
+ m_maxY = max(r.m_maxY, m_maxY);
+ }
+
+ void Offset(m2::Point<T> const & p)
+ {
+ m_minX += p.x;
+ m_minY += p.y;
+ m_maxX += p.x;
+ m_maxY += p.y;
+ }
+
+ void Offset(T const & dx, T const & dy)
+ {
+ m_minX += dx;
+ m_minY += dy;
+ m_maxX += dx;
+ m_maxY += dy;
+ }
+
+ Point<T> LeftTop() const { return Point<T>(m_minX, m_maxY); }
+ Point<T> RightTop() const { return Point<T>(m_maxX, m_maxY); }
+ Point<T> RightBottom() const { return Point<T>(m_maxX, m_minY); }
+ Point<T> LeftBottom() const { return Point<T>(m_minX, m_minY); }
+
+ bool IsIntersect(Rect const & r) const
+ {
+ return !((m_maxX < r.m_minX) || (m_minX > r.m_maxX) ||
+ (m_maxY < r.m_minY) || (m_minY > r.m_maxY));
+ }
+
+ bool IsPointInside(Point<T> const & pt) const
+ {
+ return !(m_minX > pt.x || pt.x > m_maxX || m_minY > pt.y || pt.y > m_maxY);
+ }
+
+ Point<T> Center() const { return Point<T>((m_minX + m_maxX) / 2.0, (m_minY + m_maxY) / 2.0); }
+ T SizeX() const { return (m_maxX - m_minX); }
+ T SizeY() const { return (m_maxY - m_minY); }
+
+ void DivideByGreaterSize(Rect & r1, Rect & r2) const
+ {
+ if (SizeX() > SizeY())
+ {
+ T const pivot = (m_minX + m_maxX) / 2;
+ r1 = Rect<T>(m_minX, m_minY, pivot, m_maxY);
+ r2 = Rect<T>(pivot, m_minY, m_maxX, m_maxY);
+ }
+ else
+ {
+ T const pivot = (m_minY + m_maxY) / 2;
+ r1 = Rect<T>(m_minX, m_minY, m_maxX, pivot);
+ r2 = Rect<T>(m_minX, pivot, m_maxX, m_maxY);
+ }
+ }
+
+ T minX() const { return m_minX; }
+ T minY() const { return m_minY; }
+ T maxX() const { return m_maxX; }
+ T maxY() const { return m_maxY; }
+
+ void setMinX(T minX) { m_minX = minX; }
+ void setMinY(T minY) { m_minY = minY; }
+ void setMaxX(T maxX) { m_maxX = maxX; }
+ void setMaxY(T maxY) { m_maxY = maxY; }
+
+ void Move(Point<T> const & d)
+ {
+ m_minX += d.x;
+ m_minY += d.y;
+ m_maxX += d.x;
+ m_maxY += d.y;
+ }
+
+ void Scale(T scale)
+ {
+ scale *= 0.5;
+
+ m2::Point<T> const center = Center();
+ T const halfSizeX = SizeX() * scale;
+ T const halfSizeY = SizeY() * scale;
+ m_minX = center.x - halfSizeX;
+ m_minY = center.y - halfSizeY;
+ m_maxX = center.x + halfSizeX;
+ m_maxY = center.y + halfSizeY;
+ }
+
+ void Inflate(T dx, T dy)
+ {
+ m_minX -= dx; m_maxX += dx;
+ m_minY -= dy; m_maxY += dy;
+ }
+
+ bool Intersect(m2::Rect<T> const & r)
+ {
+ T newMinX = max(m_minX, r.minX());
+ T newMaxX = min(m_maxX, r.maxX());
+
+ if (newMinX > newMaxX)
+ return false;
+
+ T newMinY = max(m_minY, r.minY());
+ T newMaxY = min(m_maxY, r.maxY());
+
+ if (newMinY > newMaxY)
+ return false;
+
+ m_minX = newMinX;
+ m_minY = newMinY;
+ m_maxX = newMaxX;
+ m_maxY = newMaxY;
+
+ return true;
+ }
+
+ bool operator < (m2::Rect<T> const & r) const
+ {
+ if (m_minX != r.m_minX)
+ return m_minX < r.m_minX;
+ if (m_minY != r.m_minY)
+ return m_minY < r.m_minY;
+ if (m_maxX != r.m_maxX)
+ return m_maxX < r.m_maxX;
+ if (m_maxY != r.m_maxY)
+ return m_maxY < r.m_maxY;
+
+ return false;
+ }
+
+ bool operator == (m2::Rect<T> const & r) const
+ {
+ return m_minX == r.m_minX && m_minY == r.m_minY && m_maxX == r.m_maxX && m_maxY == r.m_maxY;
+ }
+
+ bool operator != (m2::Rect<T> const & r) const
+ {
+ return !(*this == r);
+ }
+ };
+
+ template <typename T>
+ inline m2::Rect<T> const Add(m2::Rect<T> const & r, m2::Point<T> const & p)
+ {
+ return m2::Rect<T>(
+ min(p.x, r.minX()),
+ min(p.y, r.minY()),
+ max(p.x, r.maxX()),
+ max(p.y, r.maxY())
+ );
+ }
+
+ template <typename T>
+ inline m2::Rect<T> const Add(m2::Rect<T> const & r1, m2::Rect<T> const & r2)
+ {
+ return m2::Rect<T>(
+ min(r2.minX(), r1.minX()),
+ min(r2.minY(), r1.minY()),
+ max(r2.maxX(), r1.maxX()),
+ max(r2.maxY(), r1.maxY())
+ );
+ }
+
+ template <typename T>
+ inline m2::Rect<T> const Offset(m2::Rect<T> const & r1, m2::Point<T> const & p)
+ {
+ return m2::Rect<T>(
+ r1.minX() + p.x,
+ r1.minY() + p.y,
+ r1.maxX() + p.x,
+ r1.maxY() + p.y
+ );
+ }
+
+ template <typename T>
+ inline m2::Rect<T> const Inflate(m2::Rect<T> const & r, T const & dx, T const & dy)
+ {
+ return m2::Rect<T>(
+ r.minX() - dx,
+ r.minY() - dy,
+ r.maxX() + dx,
+ r.maxY() + dy
+ );
+ }
+
+ template <typename T>
+ inline m2::Rect<T> const Inflate(m2::Rect<T> const & r, m2::Point<T> const & p)
+ {
+ return Inflate(r, p.x, p.y);
+ }
+
+ template <typename T>
+ inline m2::Rect<T> const Offset(m2::Rect<T> const & r1, T const & dx, T const & dy)
+ {
+ return m2::Rect<T>(
+ r1.minX() + dx,
+ r1.minY() + dy,
+ r1.maxX() + dx,
+ r1.maxY() + dy
+ );
+ }
+
+ typedef Rect<float> RectF;
+ typedef Rect<double> RectD;
+ typedef Rect<unsigned> RectU;
+ typedef Rect<int> RectI;
+
+ template <typename T>
+ inline string debug_print(m2::Rect<T> const & r)
+ {
+ ostringstream out;
+ out << "m2::Rect("
+ << r.minX() << ", " << r.minY() << ", " << r.maxX() << ", " << r.maxY() << ")";
+ return out.str();
+ }
+}
+
+#include "../base/stop_mem_debug.hpp"