diff --git a/Polygon/include/CGAL/Polygon_2/Polygon_2_algorithms_impl.h b/Polygon/include/CGAL/Polygon_2/Polygon_2_algorithms_impl.h index 5da65d7fc82..9d37a2a748d 100644 --- a/Polygon/include/CGAL/Polygon_2/Polygon_2_algorithms_impl.h +++ b/Polygon/include/CGAL/Polygon_2/Polygon_2_algorithms_impl.h @@ -23,10 +23,15 @@ // // Author(s) : Wieger Wesselink +#include #include -#include + +#include + #include +#include #include +#include #include #include @@ -34,6 +39,68 @@ namespace CGAL { +namespace internal { +namespace Polygon_2 { + +template +void filter_collinear_points(InputForwardIterator first, + InputForwardIterator beyond, + OutputForwardIterator out, + const typename Kernel::FT tolerance = + std::numeric_limits::epsilon()) +{ + if(std::distance(first, beyond) < 4) + return; + + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_2 Point; + + InputForwardIterator last = boost::prior(beyond); + + InputForwardIterator vit = first, vit_next = vit, vit_next_2 = vit, vend = vit; + ++vit_next; + ++(++vit_next_2); + + bool stop = false; + + do + { + CGAL_assertion(vit != vit_next && vit_next != vit_next_2 && vit != vit_next_2); + + const Point& o = *vit; + const Point& p = *vit_next; + const Point& q = *vit_next_2; + + // Stop when 'p' is the starting point. It does not matter whether we are + // in a collinear case or not. + stop = (vit_next == vend); + + const FT det = CGAL::determinant(o.x() - q.x(), o.y() - q.y(), + p.x() - q.x(), p.y() - q.y()); + + if(CGAL::abs(det) <= tolerance) + { + // Only move 'p' and 'q' to ignore consecutive collinear points + vit_next = (vit_next == last) ? first : ++vit_next; + vit_next_2 = (vit_next_2 == last) ? first : ++vit_next_2; + } + else + { + // 'vit = vit_next' and not '++vit' because we don't necessarily have *(boost::next(vit) == p) + // and collinear points between 'o' and 'p' are ignored + vit = vit_next; + vit_next = (vit_next == last) ? first : ++vit_next; + vit_next_2 = (vit_next_2 == last) ? first : ++vit_next_2; + + *out++ = p; + } + } + while(!stop); +} + +} // namespace Polygon_2 +} // namespace internal + //-----------------------------------------------------------------------// // is_simple_2