diff --git a/include/boost/geometry/algorithms/detail/is_valid/ring.hpp b/include/boost/geometry/algorithms/detail/is_valid/ring.hpp new file mode 100644 index 000000000..fe69afb48 --- /dev/null +++ b/include/boost/geometry/algorithms/detail/is_valid/ring.hpp @@ -0,0 +1,172 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// Licensed under the Boost Software License version 1.0. +// http://www.boost.org/users/license.html + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_RING_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_RING_HPP + +#include +#include + +#include +#include + +#include +#include + +#include +#include + + +namespace boost { namespace geometry +{ + + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace is_valid +{ + + +// struct to check whether a ring is topologically closed +template +struct is_topologically_closed +{}; + +template +struct is_topologically_closed +{ + static inline bool apply(Ring const&) + { + return true; + } +}; + +template +struct is_topologically_closed +{ + static inline bool apply(Ring const& ring) + { + return geometry::equals(*boost::begin(ring), *boost::rbegin(ring)); + } +}; + + +// struct to check if the size is above the minimal one +// (3 for open, 4 for closed) +template +struct is_below_minimal_size +{}; + +template +struct is_below_minimal_size +{ + static inline bool apply(Ring const& ring) + { + return boost::size(ring) < 4; + } +}; + +template +struct is_below_minimal_size +{ + static inline bool apply(Ring const& ring) + { + return boost::size(ring) < 3; + } +}; + + + + + + +template +< + typename Ring, + order_selector PointOrder, + closure_selector Closure +> +struct is_valid_ring + : not_implemented +{}; + + +template +struct is_valid_ring +{ + static inline bool apply(Ring const& ring) + { + typedef typename reversible_view + < + Ring, iterate_reverse + >::type reversible_view_type; + + reversible_view_type reversed_ring(const_cast(ring)); + return is_valid_ring::apply(reversed_ring); + } +}; + +template +struct is_valid_ring +{ + static inline bool apply(Ring const& ring) + { + // return invalid if any of the following condition holds: + // (a) the ring's size is below the minimal one + // (b) the ring has less than three distinct points + // (c) the ring is not topologically closed + // (d) the ring has spikes + // + // Note: no need to check if the area is zero. If this is the + // case, then the ring must have at least two spikes, which is + // checked by condition (d). + if ( is_below_minimal_size::apply(ring) + || !has_three_distinct_points::apply(ring) + || !is_topologically_closed::apply(ring) + || has_spikes::apply(ring) ) + { + return false; + } + + // now call self turns to compute self intersections, if any, + // and analyze them + } +}; + + +}} // namespace dispatch +#endif // DOXYGEN_NO_DETAIL + + + +#ifndef DOXYGEN_NO_DISPATCH +namespace dispatch +{ + +// A Ring is a Polygon. +// A Polygon is always a simple geometric object provided that it is valid. +// +// Reference (for polygon validity): OGC 06-103r4 (ยง6.1.11.1) +template +struct is_valid + : detail::is_valid::is_valid_ring + < + Ring, + point_order::value, + closure::value + > +{}; + + +} // namespace dispatch +#endif // DOXYGEN_NO_DISPATCH + + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_RING_HPP