From ffa039a8498e214d4e8375d46c04fc11829eab43 Mon Sep 17 00:00:00 2001 From: vng Date: Fri, 10 Jun 2011 23:18:19 +0300 Subject: [PATCH] Minor code fixes for Rect-Point intersection. --- geometry/geometry_tests/intersect_test.cpp | 59 +++++++++++++++++++--- geometry/rect_intersect.hpp | 28 +++++----- 2 files changed, 63 insertions(+), 24 deletions(-) diff --git a/geometry/geometry_tests/intersect_test.cpp b/geometry/geometry_tests/intersect_test.cpp index 803b5a1b33..052e09334a 100644 --- a/geometry/geometry_tests/intersect_test.cpp +++ b/geometry/geometry_tests/intersect_test.cpp @@ -9,8 +9,14 @@ #include "../../base/start_mem_debug.hpp" + using namespace test; +namespace +{ + typedef m2::PointD P; +} + m2::PointD get_point(m2::RectD const & r, int ind) { switch (ind % 4) @@ -25,7 +31,7 @@ m2::PointD get_point(m2::RectD const & r, int ind) } } -void make_section_longer(m2::PointD & p1, m2::PointD & p2, double sm = 10.0) +void make_section_longer(m2::PointD & p1, m2::PointD & p2, double sm) { if (p1.x == p2.x) { @@ -54,20 +60,17 @@ void check_full_equal(m2::RectD const & r, m2::PointD const & p1, m2::PointD con { m2::PointD pp1 = p1; m2::PointD pp2 = p2; - make_section_longer(pp1, pp2); + make_section_longer(pp1, pp2, 1000.0); TEST(m2::Intersect(r, pp1, pp2), ()); TEST(comp(pp1, p1) && comp(pp2, p2), ()); } -void check_inside(m2::RectD const & r, m2::PointD p1, m2::PointD p2) +void check_inside(m2::RectD const & r, m2::PointD const & p1, m2::PointD const & p2) { - double const sm = p1.Length(p2) / 4.0; - make_section_longer(p1, p2, -sm); - m2::PointD pp1 = p1; m2::PointD pp2 = p2; - TEST(m2::Intersect(r, p1, p2), ()); + TEST(m2::Intersect(r, pp1, pp2), ()); TEST((pp1 == p1) && (pp2 == p2), ()); } @@ -120,7 +123,7 @@ void check_eps_boundaries(m2::RectD const & r, double eps = 1.0E-6) check_inside(r, get_point(rr, i), get_point(rr, i+1)); } -UNIT_TEST(IntersectRectSection) +UNIT_TEST(IntersectRect_Section) { m2::RectD r(-1, -1, 2, 2); check_intersect_boundaries(r); @@ -128,3 +131,43 @@ UNIT_TEST(IntersectRectSection) check_sides(r); check_eps_boundaries(r); } + +namespace +{ + void check_point_in_rect(m2::RectD const & r, m2::PointD const & p) + { + m2::PointD p1 = p; + m2::PointD p2 = p; + + TEST(m2::Intersect(r, p1, p2), ()); + TEST(p == p1 && p == p2, ()); + } +} + +UNIT_TEST(IntersectRect_Point) +{ + { + m2::RectD r(-100, -100, 200, 200); + for (int i = 0; i < 4; ++i) + { + check_point_in_rect(r, get_point(r, i)); + check_point_in_rect(r, (get_point(r, i) + get_point(r, i+1)) / 2.0); + } + } + + { + m2::RectD r(-1000, -1000, 1000, 1000); + double const eps = 1.0E-6; + P sm[] = { P(-eps, -eps), P(-eps, eps), P(eps, eps), P(eps, -eps) }; + for (int i = 0; i < 4; ++i) + { + P p1 = get_point(r, i); + P p2 = p1 - sm[i]; + check_inside(r, p1, p2); + + p1 = p1 + sm[i]; + p2 = p1 + sm[i]; + TEST(!m2::Intersect(r, p1, p2), ()); + } + } +} diff --git a/geometry/rect_intersect.hpp b/geometry/rect_intersect.hpp index e3c8e731e8..2897b8f772 100644 --- a/geometry/rect_intersect.hpp +++ b/geometry/rect_intersect.hpp @@ -25,13 +25,12 @@ namespace m2 template bool Intersect(m2::Rect const & r, m2::Point & p1, m2::Point & p2) { - int code1 = detail::vcode(r, p1); - int code2 = detail::vcode(r, p2); + int code[2] = { detail::vcode(r, p1), detail::vcode(r, p2) }; // пока одна из точек отрезка вне прямоугольника - while (code1 || code2) + while (code[0] || code[1]) { - if (code1 & code2) + if (code[0] & code[1]) { // если обе точки с одной стороны прямоугольника, то отрезок не пересекает прямоугольник return false; @@ -39,26 +38,26 @@ namespace m2 // выбираем точку c с ненулевым кодом m2::Point * pp; - int code; - if (code1) + int i; + if (code[0]) { - code = code1; + i = 0; pp = &p1; } else { - code = code2; + i = 1; pp = &p2; } // если pp левее r, то передвигаем pp на прямую x = r->x_min // если pp правее r, то передвигаем pp на прямую x = r->x_max - if (code & detail::LEFT) + if (code[i] & detail::LEFT) { pp->y += (p1.y - p2.y) * (r.minX() - pp->x) / (p1.x - p2.x); pp->x = r.minX(); } - else if (code & detail::RIGHT) + else if (code[i] & detail::RIGHT) { pp->y += (p1.y - p2.y) * (r.maxX() - pp->x) / (p1.x - p2.x); pp->x = r.maxX(); @@ -66,22 +65,19 @@ namespace m2 // если pp ниже r, то передвигаем pp на прямую y = r->y_min // если pp выше r, то передвигаем pp на прямую y = r->y_max - if (code & detail::BOT) + if (code[i] & detail::BOT) { pp->x += (p1.x - p2.x) * (r.minY() - pp->y) / (p1.y - p2.y); pp->y = r.minY(); } - else if (code & detail::TOP) + else if (code[i] & detail::TOP) { pp->x += (p1.x - p2.x) * (r.maxY() - pp->y) / (p1.y - p2.y); pp->y = r.maxY(); } // обновляем код - if (code == code1) - code1 = detail::vcode(r, p1); - else - code2 = detail::vcode(r, p2); + code[i] = detail::vcode(r, *pp); } // оба кода равны 0, следовательно обе точки в прямоугольнике