diff options
author | Vladimir Byko-Ianko <v.bykoianko@corp.mail.ru> | 2015-01-16 18:00:47 +0300 |
---|---|---|
committer | Alex Zolotarev <alex@maps.me> | 2015-09-23 02:36:29 +0300 |
commit | df256d265d532446b83e2297f49bb6abb35a1ef5 (patch) | |
tree | d56a22a1a8e31677f984ff8c6f273b42ae2a2771 /geometry | |
parent | 45ddd3714cd6d108444f27579532ee677e49dfa2 (diff) |
Drawing turn-arrows under the navigation route was implemented.
Diffstat (limited to 'geometry')
-rw-r--r-- | geometry/geometry_tests/point_test.cpp | 28 | ||||
-rw-r--r-- | geometry/point2d.hpp | 35 |
2 files changed, 63 insertions, 0 deletions
diff --git a/geometry/geometry_tests/point_test.cpp b/geometry/geometry_tests/point_test.cpp index 609ce8c84d..71eaa24964 100644 --- a/geometry/geometry_tests/point_test.cpp +++ b/geometry/geometry_tests/point_test.cpp @@ -57,3 +57,31 @@ UNIT_TEST(PointInTriangle_EmptyTriangle) m2::PointD pt(27, 31); TEST(!m2::IsPointStrictlyInsideTriangle(m2::PointD(0, 16), pt, pt, pt), ()); } + +/// @todo add more tests +UNIT_TEST(ArrowPoints) +{ + m2::PointF p1, p2, p3; + + m2::ArrowPoints(m2::PointF(0, 0), m2::PointF(1, 0), 1.f, 1.f, p1, p2, p3); + TEST(m2::AlmostEqual(p1, m2::PointF(1.f, 1.f)), ()); + TEST(m2::AlmostEqual(p2, m2::PointF(2.f, 0.f)), ()); + TEST(m2::AlmostEqual(p3, m2::PointF(1.f, -1.f)), ()); + + m2::PointD d1, d2, d3; + m2::ArrowPoints(m2::PointD(-1., 2.), m2::PointD(-1., 100.), 2., 5., d1, d2, d3); + TEST(m2::AlmostEqual(d1, m2::PointD(-3.f, 100.f)), ()); + TEST(m2::AlmostEqual(d2, m2::PointD(-1.f, 105.f)), ()); + TEST(m2::AlmostEqual(d3, m2::PointD(1.f, 100.f)), ()); +} + +UNIT_TEST(PointAtSegment) +{ + m2::PointF p1, p2, p3; + + TEST(m2::AlmostEqual(m2::PointAtSegment(m2::PointF(0, 0), m2::PointF(1, 0), 0.5f), m2::PointF(0.5f, 0.f)), ()); + TEST(m2::AlmostEqual(m2::PointAtSegment(m2::PointF(0, 0), m2::PointF(0, 1), 0.3f), m2::PointF(0.f, 0.3f)), ()); + TEST(m2::AlmostEqual(m2::PointAtSegment(m2::PointD(0., 0.), m2::PointD(30., 40.), 5.), m2::PointD(3., 4.)), ()); + TEST(m2::AlmostEqual(m2::PointAtSegment(m2::PointF(-3, -4), m2::PointF(-30, -40), 5.f), m2::PointF(-6.f, -8.f)), ()); + TEST(m2::AlmostEqual(m2::PointAtSegment(m2::PointD(14., -48.), m2::PointD(70., -240.), 25.), m2::PointD(21., -72.)), ()); +} diff --git a/geometry/point2d.hpp b/geometry/point2d.hpp index c75ca2667e..f37195b4bf 100644 --- a/geometry/point2d.hpp +++ b/geometry/point2d.hpp @@ -142,6 +142,14 @@ namespace m2 double const module = this->Length(); return Point<T>(x / module, y / module); } + + pair<Point<T>, Point<T> > Normals(T prolongationFactor = 1) const + { + T const prolongatedX = prolongationFactor * x; + T const prolongatedY = prolongationFactor * y; + return pair<Point<T>, Point<T> >(Point<T>(static_cast<T>(-prolongatedY), static_cast<T>(prolongatedX)), + Point<T>(static_cast<T>(prolongatedY), static_cast<T>(-prolongatedX))); + } // @} m2::Point<T> const & operator *= (math::Matrix<T, 3, 3> const & m) @@ -311,6 +319,33 @@ namespace m2 return my::AlmostEqual(a.x, b.x, maxULPs) && my::AlmostEqual(a.y, b.y, maxULPs); } + /// Calculate three point of a triangle (p1, p2 and p3) which gives a arrow at the end of segment s, f + /// with respect to w - arrow's width and l - arrow's length + template <typename T> + void ArrowPoints(Point<T> const & b, Point<T> const & e, T w, T l, + Point<T> & p1, Point<T> & p2, Point<T> & p3) + { + ASSERT(!m2::AlmostEqual(b, e), ()); + Point<T> const beVec = e - b; + Point<T> beNormalizedVec = beVec.Normalize(); + pair<Point<T>, Point<T> > beNormVecs = beNormalizedVec.Normals(w); + + p1 = e + beNormVecs.first; + p2 = e + beNormalizedVec * l; + p3 = e + beNormVecs.second; + } + + /// Returns a point which is belonged to the segment p1, p2 with respet the indent shiftFromP1 from p1. + /// If shiftFromP1 is more the distance between (p1, p2) it returns p2. + /// If shiftFromP1 is less or equal zero it returns p1. + template <typename T> + Point<T> PointAtSegment(Point<T> const & p1, Point<T> const & p2, T shiftFromP1) + { + Point<T> p12 = p2 - p1; + shiftFromP1 = my::clamp(shiftFromP1, 0.0, p12.Length()); + return p1 + p12.Normalize() * shiftFromP1; + } + template <class TArchive, class PointT> TArchive & operator >> (TArchive & ar, m2::Point<PointT> & pt) { |