From c3c4add792484f0c9f9807f3d7868538b8cc1128 Mon Sep 17 00:00:00 2001 From: vng Date: Sat, 13 Jul 2013 12:55:29 +0300 Subject: [PATCH] Cleanup code for angles.hpp/cpp --- geometry/angles.cpp | 48 +++++++++++++++++++ geometry/angles.hpp | 66 +++++--------------------- geometry/geometry.pro | 1 + geometry/geometry_tests/angle_test.cpp | 30 ++++++------ graphics/glyph_layout.cpp | 2 +- map/compass_filter.cpp | 2 +- map/location_state.cpp | 4 +- 7 files changed, 81 insertions(+), 72 deletions(-) create mode 100644 geometry/angles.cpp diff --git a/geometry/angles.cpp b/geometry/angles.cpp new file mode 100644 index 0000000000..172a948c60 --- /dev/null +++ b/geometry/angles.cpp @@ -0,0 +1,48 @@ +#include "angles.hpp" + + +namespace ang +{ + +double AngleIn2PI(double ang) +{ + double const period = 2.0 * math::pi; + ang = fmod(ang, period); + if (ang < 0.0) + ang += period; + return ang; +} + +double GetShortestDistance(double rad1, double rad2) +{ + double const period = 2.0 * math::pi; + rad1 = fmod(rad1, period); + rad2 = fmod(rad2, period); + + double res = rad2 - rad1; + if (fabs(res) > math::pi) + { + if (res < 0.0) + res = period + res; + else + res = - period + res; + } + return res; +} + +double GetMiddleAngle(double a1, double a2) +{ + double ang = (a1 + a2) / 2.0; + + if (fabs(a1 - a2) > math::pi) + { + if (ang > 0.0) + ang -= math::pi; + else + ang += math::pi; + + } + return ang; +} + +} diff --git a/geometry/angles.hpp b/geometry/angles.hpp index 23d8729883..c7c1abaa78 100644 --- a/geometry/angles.hpp +++ b/geometry/angles.hpp @@ -10,7 +10,7 @@ namespace ang { template - struct Angle + class Angle { T m_val; T m_sin; @@ -45,10 +45,10 @@ namespace ang pt0 *= m; m_val = atan2(pt1.y - pt0.y, pt1.x - pt0.x); - m_sin = sin(m_val); - m_cos = cos(m_val); + m_sin = ::sin(m_val); + m_cos = ::cos(m_val); - return this; + return *this; } }; @@ -58,13 +58,9 @@ namespace ang template Angle const operator*(Angle const & a, math::Matrix const & m) { - m2::Point pt0(0, 0); - m2::Point pt1(a.cos(), a.sin()); - - pt1 *= m; - pt0 *= m; - - return Angle(atan2(pt1.y - pt0.y, pt1.x - pt0.x)); + Angle ret(a); + ret *= m; + return ret; } /// Returns an angle of vector [p1, p2] from x-axis directed to y-axis. @@ -75,51 +71,13 @@ namespace ang return atan2(p2.y - p1.y, p2.x - p1.x); } - inline double RadToDegree(double rad) - { - return rad / math::pi * 180.0; - } + double AngleIn2PI(double ang); - inline double DegreeToRad(double degree) - { - return degree / 180.0 * math::pi; - } + /// @return Oriented angle (<= PI) from rad1 to rad2. + /// >0 - clockwise, <0 - counterclockwise + double GetShortestDistance(double rad1, double rad2); - inline double GetShortestDistance(double rad1, double rad2) - { - double period = 2 * math::pi; - rad1 = fmod(rad1, period); - rad2 = fmod(rad2, period); - - double res = 0; - - if (fabs(rad1 - rad2) > math::pi) - { - if (rad1 > rad2) - res = 2 * math::pi - (rad1 - rad2); - else - res = - 2 * math::pi + (rad2 - rad1); - } - else - res = rad2 - rad1; - - return res; - } - - inline double GetMiddleAngle(double a1, double a2) - { - double ang = (a1 + a2) / 2.0; - - if (fabs(a1 - a2) > math::pi) - { - if (ang > 0.0) - ang -= math::pi; - else - ang += math::pi; - - } - return ang; - } + double GetMiddleAngle(double a1, double a2); /// Average angle calcker. Can't find any suitable solution, so decided to do like this: /// Avg(i) = Avg(Avg(i-1), Ai); diff --git a/geometry/geometry.pro b/geometry/geometry.pro index 2156e0a9e5..478f9ce0bd 100644 --- a/geometry/geometry.pro +++ b/geometry/geometry.pro @@ -15,6 +15,7 @@ SOURCES += \ packer.cpp \ robust_orientation.cpp \ region2d/binary_operators.cpp \ + angles.cpp \ HEADERS += \ rect2d.hpp \ diff --git a/geometry/geometry_tests/angle_test.cpp b/geometry/geometry_tests/angle_test.cpp index a762aa0a5e..b77f30e351 100644 --- a/geometry/geometry_tests/angle_test.cpp +++ b/geometry/geometry_tests/angle_test.cpp @@ -8,7 +8,9 @@ #include "../angles.hpp" + using namespace test; +using math::pi; UNIT_TEST(Atan) { @@ -27,6 +29,16 @@ UNIT_TEST(Atan) TEST(is_equal_atan(2, -1, -hh), ()); } +UNIT_TEST(Atan2) +{ + TEST_ALMOST_EQUAL(atan2(1, 0), pi/2.0, ()); + TEST_ALMOST_EQUAL(atan2(-1, 0), -pi/2.0, ()); + TEST_ALMOST_EQUAL(atan2(0, 1), 0.0, ()); + TEST_ALMOST_EQUAL(atan2(0, -1), pi, ()); + + TEST_ALMOST_EQUAL(atan2(1, 1), pi/4.0, ()); +} + namespace { void check_avg(double arr[], size_t n, double v) @@ -53,21 +65,11 @@ UNIT_TEST(Average) check_avg(arr2, ARRAY_SIZE(arr2), 0.0); } -namespace -{ - bool is_equal(double val0, double val1, double eps) - { - return fabs(val0 - val1) < eps; - } -} - UNIT_TEST(ShortestDistance) { - double const eps = 1.0E-3; + TEST_ALMOST_EQUAL(ang::GetShortestDistance(0, math::pi), math::pi, ()); + TEST_ALMOST_EQUAL(ang::GetShortestDistance(0, math::pi + 1), -math::pi + 1, ()); - TEST(is_equal(ang::GetShortestDistance(0, math::pi), math::pi, eps), ()); - TEST(is_equal(ang::GetShortestDistance(0, math::pi + 1), -math::pi + 1, eps), ()); - - TEST(is_equal(ang::GetShortestDistance(math::pi - 1, 0), -math::pi + 1, eps), ()); - TEST(is_equal(ang::GetShortestDistance(math::pi + 1, 0), math::pi - 1, eps), ()); + TEST_ALMOST_EQUAL(ang::GetShortestDistance(math::pi - 1, 0), -math::pi + 1, ()); + TEST_ALMOST_EQUAL(ang::GetShortestDistance(math::pi + 1, 0), math::pi - 1, ()); } diff --git a/graphics/glyph_layout.cpp b/graphics/glyph_layout.cpp index 071c2ca44d..61c3b7defb 100644 --- a/graphics/glyph_layout.cpp +++ b/graphics/glyph_layout.cpp @@ -291,7 +291,7 @@ namespace graphics entry.m_angle = pivotPt.m_angle; // is path too bended to be shown at all? - if (hasPrevElem && (ang::GetShortestDistance(prevElem.m_angle.m_val, entry.m_angle.m_val) > 0.5)) + if (hasPrevElem && (ang::GetShortestDistance(prevElem.m_angle.val(), entry.m_angle.val()) > 0.5)) break; double const centerOffset = metrics.m_xOffset + metrics.m_width / 2.0; diff --git a/map/compass_filter.cpp b/map/compass_filter.cpp index fefec77a7c..d9d1a9b295 100644 --- a/map/compass_filter.cpp +++ b/map/compass_filter.cpp @@ -18,7 +18,7 @@ CompassFilter::CompassFilter() // We can't assign it from location::CompassInfo::accuracy, because actually it's a // declination between magnetic and true north in Android // (and it may be very large in particular places on the Earth). - m_smoothingThreshold = ang::DegreeToRad(10); + m_smoothingThreshold = my::DegToRad(10); } void CompassFilter::OnCompassUpdate(location::CompassInfo const & info) diff --git a/map/location_state.cpp b/map/location_state.cpp index c02434ee25..2f43429724 100644 --- a/map/location_state.cpp +++ b/map/location_state.cpp @@ -472,7 +472,7 @@ namespace location if (isRunning) headingDelta = fabs(ang::GetShortestDistance(m_headingInterpolation->EndAngle(), m_compassFilter.GetHeadingRad())); - if (floor(ang::RadToDegree(headingDelta)) > 0) + if (floor(my::RadToDeg(headingDelta)) > 0) m_headingInterpolation->SetEndAngle(m_compassFilter.GetHeadingRad()); else { @@ -480,7 +480,7 @@ namespace location { headingDelta = fabs(ang::GetShortestDistance(m_drawHeading, m_compassFilter.GetHeadingRad())); - if (my::rounds(ang::RadToDegree(headingDelta)) > 0) + if (my::rounds(my::RadToDeg(headingDelta)) > 0) { if (m_headingInterpolation && !m_headingInterpolation->IsCancelled()