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:
authorrachytski <siarhei.rachytski@gmail.com>2011-10-03 14:31:37 +0400
committerAlex Zolotarev <alex@maps.me>2015-09-23 01:25:21 +0300
commitfd3a3a6d0fc3aeab9e7b0c4724d614dc587cb0ee (patch)
tree0c872119ff85927af83ec5919beea786832ba961 /geometry
parent31279661079d1426c2dac1971fb5bce6d086be32 (diff)
refactored ScreenBase to support GUI rotation.
Diffstat (limited to 'geometry')
-rw-r--r--geometry/aa_rect2d.hpp31
-rw-r--r--geometry/geometry_tests/screen_test.cpp14
-rw-r--r--geometry/screenbase.cpp143
-rw-r--r--geometry/screenbase.hpp106
-rw-r--r--geometry/transformations.hpp9
5 files changed, 177 insertions, 126 deletions
diff --git a/geometry/aa_rect2d.hpp b/geometry/aa_rect2d.hpp
index 53499ec001..e62a9829bd 100644
--- a/geometry/aa_rect2d.hpp
+++ b/geometry/aa_rect2d.hpp
@@ -15,6 +15,7 @@ namespace m2
{
private:
+ ang::Angle<T> m_angle;
Point<T> m_i;
Point<T> m_j;
Point<T> m_zero;
@@ -39,25 +40,32 @@ namespace m2
AARect() : m_i(1, 0), m_j(0, 1), m_zero(0, 0), m_rect(){}
/// creating from regular rect
- AARect(Rect<T> const & r)
- : m_i(1, 0), m_j(0, 1),
+ explicit AARect(Rect<T> const & r)
+ : m_angle(0), m_i(m_angle.cos(), m_angle.sin()), m_j(-m_angle.sin(), m_angle.cos()),
m_zero(r == Rect<T>() ? Point<T>(0, 0) : Point<T>(r.minX(), r.minY())),
m_rect(r == Rect<T>() ? Rect<T>() : Rect<T>(0, 0, r.SizeX(), r.SizeY()))
{
}
AARect(Point<T> const & zero, ang::Angle<T> const & angle, Rect<T> const & r)
- : m_i(angle.cos(), angle.sin()), m_j(-angle.sin(), angle.cos()),
+ : m_angle(angle), m_i(m_angle.cos(), m_angle.sin()), m_j(-m_angle.sin(), m_angle.cos()),
m_zero(Convert(zero, Point<T>(1, 0), Point<T>(0, 1), m_i, m_j)),
m_rect(r)
{
}
- Point<T> const & zero() const
+ Point<T> const & LocalZero() const
{
return m_zero;
}
+ Point<T> const GlobalZero() const
+ {
+ m2::PointD i(1, 0);
+ m2::PointD j(0, 1);
+ return Convert(m_zero, m_i, m_j, i, j);
+ }
+
Point<T> const & i() const
{
return m_i;
@@ -68,6 +76,21 @@ namespace m2
return m_j;
}
+ ang::Angle<T> const & angle() const
+ {
+ return m_angle;
+ }
+
+ Point<T> const GlobalCenter() const
+ {
+ return ConvertFrom(m_rect.Center());
+ }
+
+ Point<T> const LocalCenter() const
+ {
+ return m_rect.Center();
+ }
+
bool IsPointInside(Point<T> const & pt) const
{
return m_rect.IsPointInside(ConvertTo(pt));
diff --git a/geometry/geometry_tests/screen_test.cpp b/geometry/geometry_tests/screen_test.cpp
index b13520bffe..d2bdd9610a 100644
--- a/geometry/geometry_tests/screen_test.cpp
+++ b/geometry/geometry_tests/screen_test.cpp
@@ -16,7 +16,7 @@ namespace
m2::PointD b1(0.0, 0.0);
m2::PointD b2(300.0, 300.0);
- screen.SetFromRect(m2::RectD(b1, b2));
+ screen.SetFromRect(m2::AARectD(m2::RectD(b1, b2)));
b1 = screen.GtoP(b1);
b2 = screen.GtoP(b2);
@@ -37,7 +37,7 @@ UNIT_TEST(ScreenBase_P2G2P)
check_set_from_rect(screen, 500, 1000);
screen.OnSize(0, 0, 640, 480);
- screen.SetFromRect(m2::RectD(-100, -200, 500, 680));
+ screen.SetFromRect(m2::AARectD(m2::RectD(-100, -200, 500, 680)));
/// checking that PtoG(GtoP(p)) == p
@@ -55,7 +55,7 @@ UNIT_TEST(ScreenBase_AxisOrientation)
ScreenBase screen;
screen.OnSize(0, 0, 300, 200);
- screen.SetFromRect(m2::RectD(0, 0, 300, 200));
+ screen.SetFromRect(m2::AARectD(m2::RectD(0, 0, 300, 200)));
TEST(is_equal(m2::PointD(150, 100), screen.GtoP(m2::PointD(150, 100))), ());
TEST(is_equal(m2::PointD(0, 0), screen.GtoP(m2::PointD(0, 200))), ());
@@ -68,7 +68,7 @@ UNIT_TEST(ScreenBase_X0Y0)
{
ScreenBase screen;
screen.OnSize(10, 10, 300, 200);
- screen.SetFromRect(m2::RectD(0, 0, 300, 200));
+ screen.SetFromRect(m2::AARectD(m2::RectD(0, 0, 300, 200)));
m2::PointD pxPt = screen.PtoG(m2::PointD(0, 0));
@@ -79,7 +79,7 @@ UNIT_TEST(ScreenBase_ChoosingMaxScale)
{
ScreenBase screen;
screen.OnSize(10, 10, 300, 200);
- screen.SetFromRect(m2::RectD(0, 0, 200, 400));
+ screen.SetFromRect(m2::AARectD(m2::RectD(0, 0, 200, 400)));
TEST(is_equal(screen.GtoP(m2::PointD(100, 200)), m2::PointD(160, 110)), ());
TEST(is_equal(screen.GtoP(m2::PointD(0, 0)), m2::PointD(110, 210)), ());
@@ -124,11 +124,11 @@ UNIT_TEST(ScreenBase_Rotate)
{
ScreenBase s;
s.OnSize(0, 0, 100, 200);
- s.SetFromRect(m2::RectD(0, 0, 100, 200));
+ s.SetFromRect(m2::AARectD(m2::RectD(0, 0, 100, 200)));
s.Rotate(math::pi / 4);
m2::RectD pxRect = s.PixelRect();
- m2::RectD glbRect = s.GlobalRect();
+ m2::AARectD glbRect = s.GlobalRect();
TEST(pxRect == m2::RectD(0, 0, 100, 200), ());
}
diff --git a/geometry/screenbase.cpp b/geometry/screenbase.cpp
index acabce0e17..bdbaa65c44 100644
--- a/geometry/screenbase.cpp
+++ b/geometry/screenbase.cpp
@@ -10,16 +10,17 @@
ScreenBase::ScreenBase() :
m_PixelRect(0, 0, 640, 480),
- m_GlobalRect(0, 0, 640, 480),
m_Scale(1),
- m_Angle(0.0)
+ m_Angle(0.0),
+ m_Org(320, 240),
+ m_GlobalRect(m2::RectD(0, 0, 640, 480))
{
m_GtoP = math::Identity<double, 3>();
m_PtoG = math::Identity<double, 3>();
// UpdateDependentParameters();
}
-ScreenBase::ScreenBase(m2::RectI const & pxRect, m2::RectD const & glbRect)
+ScreenBase::ScreenBase(m2::RectI const & pxRect, m2::AARectD const & glbRect)
{
OnSize(pxRect);
SetFromRect(glbRect);
@@ -41,71 +42,119 @@ void ScreenBase::UpdateDependentParameters()
m_Scale,
m_Scale
),
- GetAngle()
+ m_Angle.cos(),
+ m_Angle.sin()
),
- m_GlobalRect.Center()
+ m_Org
);
m_GtoP = math::Inverse(m_PtoG);
- PtoG(m_PixelRect, m_ClipRect);
- PtoG(m_PixelRect, m_GlobalRect);
+ double HalfSizeX = PtoG(m2::PointD(m_PixelRect.maxX(), m_PixelRect.Center().y)).Length(PtoG(m2::PointD(m_PixelRect.Center())));
+ double HalfSizeY = PtoG(m2::PointD(m_PixelRect.Center().x, m_PixelRect.minY())).Length(PtoG(m2::PointD(m_PixelRect.Center())));
+
+ m_GlobalRect = m2::AARectD(m_Org, m_Angle, m2::RectD(-HalfSizeX, -HalfSizeY, HalfSizeX, HalfSizeY));
+ m_ClipRect = m_GlobalRect.GetGlobalRect();
}
-void ScreenBase::SetFromRect(m2::RectD const & GlobalRect)
+void ScreenBase::SetFromRect(m2::AARectD const & GlobalRect)
{
- double hScale = GlobalRect.SizeX() / m_PixelRect.SizeX();
- double vScale = GlobalRect.SizeY() / m_PixelRect.SizeY();
+ double hScale = GlobalRect.GetLocalRect().SizeX() / m_PixelRect.SizeX();
+ double vScale = GlobalRect.GetLocalRect().SizeY() / m_PixelRect.SizeY();
m_Scale = max(hScale, vScale);
- m_Angle = 0;
-
- /// Fit the global rect into pixel rect
-
- m2::PointD HalfSize(m_Scale * m_PixelRect.SizeX() / 2,
- m_Scale * m_PixelRect.SizeY() / 2);
-
- m_GlobalRect = m2::RectD(
- GlobalRect.Center() - HalfSize,
- GlobalRect.Center() + HalfSize
- );
+ m_Angle = GlobalRect.angle();
+ m_Org = GlobalRect.GlobalCenter();
UpdateDependentParameters();
}
void ScreenBase::SetOrg(m2::PointD const & p)
{
- m_GlobalRect.Offset(p - m_GlobalRect.Center());
+ m_Org = p;
UpdateDependentParameters();
}
void ScreenBase::Move(double dx, double dy)
{
- m_GlobalRect.Offset(m_GlobalRect.Center() - PtoG(m_PixelRect.Center() + m2::PointD(dx, dy)));
-
+ m_Org = PtoG(GtoP(m_Org) - m2::PointD(dx, dy));
UpdateDependentParameters();
}
-void ScreenBase::MoveG(m2::PointD const & delta)
+void ScreenBase::MoveG(m2::PointD const & p)
{
- m_GlobalRect.Offset(delta);
-
+ m_Org -= p;
UpdateDependentParameters();
}
void ScreenBase::Scale(double scale)
{
- m_GlobalRect.Scale( 1 / scale);
m_Scale /= scale;
UpdateDependentParameters();
}
void ScreenBase::Rotate(double angle)
{
- m_Angle -= angle;
+ m_Angle = ang::AngleD(m_Angle.val() + angle);
UpdateDependentParameters();
}
+void ScreenBase::OnSize(m2::RectI const & r)
+{
+ m_PixelRect = m2::RectD(r);
+ UpdateDependentParameters();
+}
+
+void ScreenBase::OnSize(int x0, int y0, int w, int h)
+{
+ OnSize(m2::RectI(x0, y0, x0 + w, y0 + h));
+}
+
+math::Matrix<double, 3, 3> const & ScreenBase::GtoPMatrix() const
+{
+ return m_GtoP;
+}
+
+math::Matrix<double, 3, 3> const & ScreenBase::PtoGMatrix() const
+{
+ return m_PtoG;
+}
+
+m2::RectD const & ScreenBase::PixelRect() const
+{
+ return m_PixelRect;
+}
+
+m2::AARectD const & ScreenBase::GlobalRect() const
+{
+ return m_GlobalRect;
+}
+
+m2::RectD const & ScreenBase::ClipRect() const
+{
+ return m_ClipRect;
+}
+
+double ScreenBase::GetScale() const
+{
+ return m_Scale;
+}
+
+double ScreenBase::GetAngle() const
+{
+ return m_Angle.val();
+}
+
+int ScreenBase::GetWidth() const
+{
+ return my::rounds(m_PixelRect.SizeX());
+}
+
+int ScreenBase::GetHeight() const
+{
+ return my::rounds(m_PixelRect.SizeY());
+}
+
math::Matrix<double, 3, 3> const ScreenBase::CalcTransform(m2::PointD const & oldPt1, m2::PointD const & oldPt2,
m2::PointD const & newPt1, m2::PointD const & newPt2)
{
@@ -136,34 +185,38 @@ void ScreenBase::SetGtoPMatrix(math::Matrix<double, 3, 3> const & m)
/// Extracting transformation params, assuming that the matrix
/// somehow represent a valid screen transformation
/// into m_PixelRectangle
- double dx, dy;
- ExtractGtoPParams(m, m_Angle, m_Scale, dx, dy);
- m_Scale = 1 / m_Scale;
-
- m_GlobalRect = m_PixelRect;
- m_GlobalRect.Scale(m_Scale);
+ double dx, dy, a, s;
+ ExtractGtoPParams(m, a, s, dx, dy);
+ m_Angle = ang::AngleD(-a);
+ m_Scale = 1 / s;
+ m_Org = PtoG(m_PixelRect.Center());
- m_GlobalRect.Offset(m_PixelRect.Center() * m_PtoG - m_GlobalRect.Center());
+ UpdateDependentParameters();
}
-void ScreenBase::GtoP(m2::RectD const & gr, m2::RectD & sr) const
+void ScreenBase::GtoP(m2::RectD const & glbRect, m2::RectD & pxRect) const
{
- sr = m2::RectD(GtoP(gr.LeftTop()), GtoP(gr.RightBottom()));
+ pxRect = m2::RectD(GtoP(glbRect.LeftTop()), GtoP(glbRect.RightBottom()));
}
-void ScreenBase::PtoG(m2::RectD const & sr, m2::RectD & gr) const
+void ScreenBase::PtoG(m2::RectD const & pxRect, m2::RectD & glbRect) const
{
- gr = m2::RectD(PtoG(sr.LeftTop()), PtoG(sr.RightBottom()));
+ glbRect = m2::RectD(PtoG(pxRect.LeftTop()), PtoG(pxRect.RightBottom()));
}
-bool IsPanning(ScreenBase const & s1, ScreenBase const & s2)
+bool IsPanningAndRotate(ScreenBase const & s1, ScreenBase const & s2)
{
- m2::PointD globPt(s1.GlobalRect().Center().x - s1.GlobalRect().minX(),
- s1.GlobalRect().Center().y - s1.GlobalRect().minY());
+ m2::RectD r1 = s1.GlobalRect().GetLocalRect();
+ m2::RectD r2 = s2.GlobalRect().GetLocalRect();
+
+ m2::PointD c1 = r1.Center();
+ m2::PointD c2 = r2.Center();
- m2::PointD p1 = s1.GtoP(s1.GlobalRect().Center()) - s1.GtoP(s1.GlobalRect().Center() + globPt);
+ m2::PointD globPt(c1.x - r1.minX(),
+ c1.y - r1.minY());
- m2::PointD p2 = s2.GtoP(s2.GlobalRect().Center()) - s2.GtoP(s2.GlobalRect().Center() + globPt);
+ m2::PointD p1 = s1.GtoP(s1.GlobalRect().ConvertFrom(c1)) - s1.GtoP(s1.GlobalRect().ConvertFrom(c1 + globPt));
+ m2::PointD p2 = s2.GtoP(s2.GlobalRect().ConvertFrom(c2)) - s2.GtoP(s2.GlobalRect().ConvertFrom(c2 + globPt));
return p1.EqualDxDy(p2, 0.00001);
}
diff --git a/geometry/screenbase.hpp b/geometry/screenbase.hpp
index 1aee190597..a50ce0deb7 100644
--- a/geometry/screenbase.hpp
+++ b/geometry/screenbase.hpp
@@ -2,6 +2,7 @@
#include "point2d.hpp"
#include "rect2d.hpp"
+#include "aa_rect2d.hpp"
#include "../base/math.hpp"
@@ -18,9 +19,10 @@ enum EOrientation
class ScreenBase
{
m2::RectD m_PixelRect;
- m2::RectD m_GlobalRect;
+
double m_Scale;
- double m_Angle;
+ ang::AngleD m_Angle;
+ m2::PointD m_Org;
protected:
@@ -32,9 +34,12 @@ protected:
/// @{
math::Matrix<double, 3, 3> m_GtoP;
- /// Pixel to Global conversion matrix. GtoP inverted
+ /// Pixel to Global conversion matrix. Inverted GtoP matrix.
math::Matrix<double, 3, 3> m_PtoG;
+ /// Global Rect
+ m2::AARectD m_GlobalRect;
+
/// X-axis aligned global rect used for clipping
m2::RectD m_ClipRect;
@@ -47,57 +52,35 @@ protected:
public:
ScreenBase();
- ScreenBase(m2::RectI const & pxRect, m2::RectD const & glbRect);
+ ScreenBase(m2::RectI const & pxRect, m2::AARectD const & glbRect);
- void SetFromRect(m2::RectD const & rect);
+ void SetFromRect(m2::AARectD const & rect);
void SetOrg(m2::PointD const & p);
void Move(double dx, double dy);
- void MoveG(m2::PointD const & delta);
+ void MoveG(m2::PointD const & p);
+
void Scale(double scale);
void Rotate(double angle);
- void ReverseTransformInPixelCoords(double s, double a, double dx, double dy);
-
- void OnSize(m2::RectI const & r)
- {
- m_PixelRect = m2::RectD(r);
- UpdateDependentParameters();
- }
- void OnSize(int x0, int y0, int w, int h)
- {
- m_PixelRect = m2::RectD(x0, y0, x0 + w, y0 + h);
- UpdateDependentParameters();
- }
+ void OnSize(m2::RectI const & r);
+ void OnSize(int x0, int y0, int w, int h);
public:
- inline double GetScale() const { return m_Scale; };
-
- inline double GetAngle() const
- {
- return m_Angle;
- }
-
- inline int GetWidth() const
- {
- return my::rounds(m_PixelRect.SizeX());
- }
-
- inline int GetHeight() const
- {
- return my::rounds(m_PixelRect.SizeY());
- }
+ double GetScale() const;
+ double GetAngle() const;
+ int GetWidth() const;
+ int GetHeight() const;
- /// @warning ClipRect() returns a PtoG(m_PixelRect) rect.
- inline m2::RectD const & ClipRect() const
+ inline m2::PointD GtoP(m2::PointD const & pt) const
{
- return m_ClipRect;
+ return pt * m_GtoP;
}
- inline m2::PointD GtoP(m2::PointD const & pt) const
+ inline m2::PointD PtoG(m2::PointD const & pt) const
{
- return pt * m_GtoP;
+ return pt * m_PtoG;
}
inline void GtoP(double & x, double & y) const
@@ -107,51 +90,33 @@ public:
y = tempX * m_GtoP(1, 0) + y * m_GtoP(1, 1) + m_GtoP(2, 1);
}
- void GtoP(m2::RectD const & gr, m2::RectD & sr) const;
- void PtoG(m2::RectD const & sr, m2::RectD & gr) const;
-
- math::Matrix<double, 3, 3> const GtoPMatrix() const
+ inline void PtoG(double & x, double & y) const
{
- return m_GtoP;
+ double tempX = x;
+ x = tempX * m_PtoG(0, 0) + y * m_PtoG(1, 0) + m_PtoG(2, 0);
+ y = tempX * m_PtoG(0, 1) + y * m_PtoG(1, 1) + m_PtoG(2, 1);
}
- math::Matrix<double, 3, 3> const PtoGMatrix() const
- {
- return m_PtoG;
- }
+ void GtoP(m2::RectD const & gr, m2::RectD & sr) const;
+ void PtoG(m2::RectD const & pr, m2::RectD & gr) const;
- m2::RectD const & PixelRect() const
- {
- return m_PixelRect;
- }
+ math::Matrix<double, 3, 3> const & GtoPMatrix() const;
+ math::Matrix<double, 3, 3> const & PtoGMatrix() const;
- m2::RectD const & GlobalRect() const
- {
- return m_GlobalRect;
- }
+ m2::RectD const & PixelRect() const;
+ m2::AARectD const & GlobalRect() const;
+ m2::RectD const & ClipRect() const;
/// Compute arbitrary pixel transformation, that translates the (oldPt1, oldPt2) -> (newPt1, newPt2)
static math::Matrix<double, 3, 3> const CalcTransform(m2::PointD const & oldPt1, m2::PointD const & oldPt2,
m2::PointD const & newPt1, m2::PointD const & newPt2);
- /// Setting GtoP matrix extracts the Angle and GlobalRect, leaving PixelRect intact
+ /// Setting GtoP matrix extracts the Angle and m_Org parameters, leaving PixelRect intact
void SetGtoPMatrix(math::Matrix<double, 3, 3> const & m);
/// Extracting parameters from matrix, that is supposed to represent GtoP transformation
static void ExtractGtoPParams(math::Matrix<double, 3, 3> const & m, double & a, double & s, double & dx, double & dy);
- inline m2::PointD PtoG(m2::PointD const & pt) const
- {
- return pt * m_PtoG;
- }
-
- inline void PtoG(double & x, double & y) const
- {
- double tempX = x;
- x = tempX * m_PtoG(0, 0) + y * m_PtoG(1, 0) + m_PtoG(2, 0);
- y = tempX * m_PtoG(0, 1) + y * m_PtoG(1, 1) + m_PtoG(2, 1);
- }
-
bool operator != (ScreenBase const & src) const
{
return !(*this == src);
@@ -163,6 +128,7 @@ public:
}
};
-bool IsPanning(ScreenBase const & s1, ScreenBase const & s2);
+/// checking whether the s1 transforms into s2 without scaling, only with shift and rotation
+bool IsPanningAndRotate(ScreenBase const & s1, ScreenBase const & s2);
#include "../base/stop_mem_debug.hpp"
diff --git a/geometry/transformations.hpp b/geometry/transformations.hpp
index 8ba0743da2..6b1a58fd00 100644
--- a/geometry/transformations.hpp
+++ b/geometry/transformations.hpp
@@ -17,6 +17,15 @@ namespace math
}
template <typename T, typename U>
+ Matrix<T, 3, 3> const Rotate(Matrix<T, 3, 3> const & m, U const & cos, U const & sin)
+ {
+ Matrix<T, 3, 3> m1 = Identity<T, 3>();
+ m1(0, 0) = cos; m1(0, 1) = sin;
+ m1(1, 0) = -sin; m1(1, 1) = cos;
+ return m * m1;
+ }
+
+ template <typename T, typename U>
Matrix<T, 3, 3> const Shift(Matrix<T, 3, 3> const & m, U const & dx, U const & dy)
{
Matrix<T, 3, 3> m1 = Identity<T, 3>();