1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2014-2017, Oracle and/or its affiliates.
5 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
6 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
8 // Licensed under the Boost Software License version 1.0.
9 // http://www.boost.org/users/license.html
11 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINEAR_HPP
12 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINEAR_HPP
16 #include <boost/range.hpp>
18 #include <boost/geometry/core/closure.hpp>
19 #include <boost/geometry/core/point_type.hpp>
20 #include <boost/geometry/core/tags.hpp>
22 #include <boost/geometry/util/condition.hpp>
23 #include <boost/geometry/util/range.hpp>
25 #include <boost/geometry/algorithms/equals.hpp>
26 #include <boost/geometry/algorithms/validity_failure_type.hpp>
27 #include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
28 #include <boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp>
29 #include <boost/geometry/algorithms/detail/is_valid/has_spikes.hpp>
30 #include <boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp>
32 #include <boost/geometry/algorithms/dispatch/is_valid.hpp>
35 namespace boost { namespace geometry
38 #ifndef DOXYGEN_NO_DETAIL
39 namespace detail { namespace is_valid
43 template <typename Linestring>
44 struct is_valid_linestring
46 template <typename VisitPolicy, typename Strategy>
47 static inline bool apply(Linestring const& linestring,
49 Strategy const& strategy)
51 if (has_invalid_coordinate<Linestring>::apply(linestring, visitor))
56 if (boost::size(linestring) < 2)
58 return visitor.template apply<failure_few_points>();
61 std::size_t num_distinct = detail::num_distinct_consecutive_points
66 not_equal_to<typename point_type<Linestring>::type>
69 if (num_distinct < 2u)
72 visitor.template apply<failure_wrong_topological_dimension>();
75 if (num_distinct == 2u)
77 return visitor.template apply<no_failure>();
83 >::apply(linestring, visitor,
84 strategy.get_side_strategy());
89 }} // namespace detail::is_valid
90 #endif // DOXYGEN_NO_DETAIL
95 #ifndef DOXYGEN_NO_DISPATCH
100 // A linestring is a curve.
101 // A curve is 1-dimensional so it has to have at least two distinct
103 // A curve is simple if it does not pass through the same point twice,
104 // with the possible exception of its two endpoints
106 // There is an option here as to whether spikes are allowed for linestrings;
107 // here we pass this as an additional template parameter: allow_spikes
108 // If allow_spikes is set to true, spikes are allowed, false otherwise.
109 // By default, spikes are disallowed
111 // Reference: OGC 06-103r4 (6.1.6.1)
112 template <typename Linestring, bool AllowEmptyMultiGeometries>
115 Linestring, linestring_tag, AllowEmptyMultiGeometries
116 > : detail::is_valid::is_valid_linestring<Linestring>
120 // A MultiLinestring is a MultiCurve
121 // A MultiCurve is simple if all of its elements are simple and the
122 // only intersections between any two elements occur at Points that
123 // are on the boundaries of both elements.
125 // Reference: OGC 06-103r4 (6.1.8.1; Fig. 9)
126 template <typename MultiLinestring, bool AllowEmptyMultiGeometries>
129 MultiLinestring, multi_linestring_tag, AllowEmptyMultiGeometries
133 template <typename VisitPolicy, typename Strategy>
134 struct per_linestring
136 per_linestring(VisitPolicy& policy, Strategy const& strategy)
138 , m_strategy(strategy)
141 template <typename Linestring>
142 inline bool apply(Linestring const& linestring) const
144 return detail::is_valid::is_valid_linestring
147 >::apply(linestring, m_policy, m_strategy);
150 VisitPolicy& m_policy;
151 Strategy const& m_strategy;
155 template <typename VisitPolicy, typename Strategy>
156 static inline bool apply(MultiLinestring const& multilinestring,
157 VisitPolicy& visitor,
158 Strategy const& strategy)
160 if (BOOST_GEOMETRY_CONDITION(
161 AllowEmptyMultiGeometries && boost::empty(multilinestring)))
163 return visitor.template apply<no_failure>();
166 typedef per_linestring<VisitPolicy, Strategy> per_ls;
168 return detail::check_iterator_range
171 false // do not check for empty multilinestring (done above)
172 >::apply(boost::begin(multilinestring),
173 boost::end(multilinestring),
174 per_ls(visitor, strategy));
179 } // namespace dispatch
180 #endif // DOXYGEN_NO_DISPATCH
183 }} // namespace boost::geometry
186 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINEAR_HPP