// Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2008-2011 Bruno Lalande, Paris, France. // Copyright (c) 2009-2011 Mateusz Loskot, London, UK. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. // Use, modification and distribution is subject to the Boost Software License, // Version 1.Dimension. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP #include #include #include #include #include #include #include namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace point_on_border { template struct get_point { static inline bool apply(Point& destination, Point const& source, bool) { destination = source; return true; } }; template struct midpoint_helper { static inline bool apply(Point& p, Point const& p1, Point const& p2) { typename coordinate_type::type const two = 2; set(p, (get(p1) + get(p2)) / two); return midpoint_helper::apply(p, p1, p2); } }; template struct midpoint_helper { static inline bool apply(Point& , Point const& , Point const& ) { return true; } }; template struct point_on_range { static inline bool apply(Point& point, Range const& range, bool midpoint) { const std::size_t n = boost::size(range); if (midpoint && n > 1) { typedef typename boost::range_iterator < Range const >::type iterator; iterator it = boost::begin(range); iterator prev = it++; while (it != boost::end(range) && detail::equals::equals_point_point(*it, *prev)) { prev = it++; } if (it != boost::end(range)) { return midpoint_helper < Point, 0, dimension::value >::apply(point, *prev, *it); } } if (n > 0) { point = *boost::begin(range); return true; } return false; } }; template struct point_on_polygon { static inline bool apply(Point& point, Polygon const& polygon, bool midpoint) { return point_on_range < Point, typename ring_type::type >::apply(point, exterior_ring(polygon), midpoint); } }; template struct point_on_box { static inline bool apply(Point& point, Box const& box, bool midpoint) { if (midpoint) { Point p1, p2; detail::assign::assign_box_2d_corner(box, p1); detail::assign::assign_box_2d_corner(box, p2); midpoint_helper < Point, 0, dimension::value >::apply(point, p1, p2); } else { detail::assign::assign_box_2d_corner(box, point); } return true; } }; }} // namespace detail::point_on_border #endif // DOXYGEN_NO_DETAIL #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { template < typename GeometryTag, typename Point, typename Geometry > struct point_on_border {}; template struct point_on_border : detail::point_on_border::get_point {}; template struct point_on_border : detail::point_on_border::point_on_range {}; template struct point_on_border : detail::point_on_border::point_on_range {}; template struct point_on_border : detail::point_on_border::point_on_polygon {}; template struct point_on_border : detail::point_on_border::point_on_box {}; } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH /*! \brief Take point on a border \ingroup overlay \tparam Geometry geometry type. This also defines the type of the output point \param point to assign \param geometry geometry to take point from \param midpoint boolean flag, true if the point should not be a vertex, but some point in between of two vertices \return TRUE if successful, else false. It is only false if polygon/line have no points \note for a polygon, it is always a point on the exterior ring \note for take_midpoint, it is not taken from two consecutive duplicate vertices, (unless there are no other). */ template inline bool point_on_border(Point& point, Geometry const& geometry, bool midpoint = false) { concept::check(); concept::check(); typedef typename point_type::type point_type; return dispatch::point_on_border < typename tag::type, Point, Geometry >::apply(point, geometry, midpoint); } }} // namespace boost::geometry #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP