1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2014-2021, Oracle and/or its affiliates.
5 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
6 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
7 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
9 // Licensed under the Boost Software License version 1.0.
10 // http://www.boost.org/users/license.html
12 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINEAR_HPP
13 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINEAR_HPP
17 #include <boost/range/begin.hpp>
18 #include <boost/range/empty.hpp>
19 #include <boost/range/end.hpp>
20 #include <boost/range/size.hpp>
22 #include <boost/geometry/algorithms/equals.hpp>
23 #include <boost/geometry/algorithms/validity_failure_type.hpp>
24 #include <boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp>
25 #include <boost/geometry/algorithms/detail/is_valid/has_spikes.hpp>
26 #include <boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp>
28 #include <boost/geometry/algorithms/dispatch/is_valid.hpp>
30 #include <boost/geometry/core/closure.hpp>
31 #include <boost/geometry/core/point_type.hpp>
32 #include <boost/geometry/core/tags.hpp>
34 #include <boost/geometry/util/condition.hpp>
37 namespace boost { namespace geometry
40 #ifndef DOXYGEN_NO_DETAIL
41 namespace detail { namespace is_valid
45 template <typename Linestring>
46 struct is_valid_linestring
48 template <typename VisitPolicy, typename Strategy>
49 static inline bool apply(Linestring const& linestring,
51 Strategy const& strategy)
53 // TODO: Consider checking coordinates based on coordinate system
54 // Right now they are only checked for infinity in all systems.
55 if (has_invalid_coordinate<Linestring>::apply(linestring, visitor))
60 if (boost::size(linestring) < 2)
62 return visitor.template apply<failure_few_points>();
65 std::size_t num_distinct = detail::num_distinct_consecutive_points
68 >::apply(linestring, strategy);
70 if (num_distinct < 2u)
73 visitor.template apply<failure_wrong_topological_dimension>();
76 if (num_distinct == 2u)
78 return visitor.template apply<no_failure>();
81 // TODO: This algorithm iterates over the linestring until a spike is
82 // found and only then the decision about the validity is made. This
83 // is done regardless of VisitPolicy.
84 // An obvious improvement is to avoid calling the algorithm at all if
85 // spikes are allowed which is the default.
86 return ! has_spikes<Linestring>::apply(linestring, visitor, strategy);
91 }} // namespace detail::is_valid
92 #endif // DOXYGEN_NO_DETAIL
97 #ifndef DOXYGEN_NO_DISPATCH
102 // A linestring is a curve.
103 // A curve is 1-dimensional so it has to have at least two distinct
105 // A curve is simple if it does not pass through the same point twice,
106 // with the possible exception of its two endpoints
108 // There is an option here as to whether spikes are allowed for linestrings;
109 // here we pass this as an additional template parameter: allow_spikes
110 // If allow_spikes is set to true, spikes are allowed, false otherwise.
111 // By default, spikes are disallowed
113 // Reference: OGC 06-103r4 (6.1.6.1)
114 template <typename Linestring, bool AllowEmptyMultiGeometries>
117 Linestring, linestring_tag, AllowEmptyMultiGeometries
118 > : detail::is_valid::is_valid_linestring<Linestring>
122 // A MultiLinestring is a MultiCurve
123 // A MultiCurve is simple if all of its elements are simple and the
124 // only intersections between any two elements occur at Points that
125 // are on the boundaries of both elements.
127 // Reference: OGC 06-103r4 (6.1.8.1; Fig. 9)
128 template <typename MultiLinestring, bool AllowEmptyMultiGeometries>
131 MultiLinestring, multi_linestring_tag, AllowEmptyMultiGeometries
134 template <typename VisitPolicy, typename Strategy>
135 struct per_linestring
137 per_linestring(VisitPolicy& policy, Strategy const& strategy)
139 , m_strategy(strategy)
142 template <typename Linestring>
143 inline bool operator()(Linestring const& linestring) const
145 return detail::is_valid::is_valid_linestring
148 >::apply(linestring, m_policy, m_strategy);
151 VisitPolicy& m_policy;
152 Strategy const& m_strategy;
156 template <typename VisitPolicy, typename Strategy>
157 static inline bool apply(MultiLinestring const& multilinestring,
158 VisitPolicy& visitor,
159 Strategy const& strategy)
161 if (BOOST_GEOMETRY_CONDITION(
162 AllowEmptyMultiGeometries && boost::empty(multilinestring)))
164 return visitor.template apply<no_failure>();
167 using per_ls = per_linestring<VisitPolicy, Strategy>;
169 return std::all_of(boost::begin(multilinestring),
170 boost::end(multilinestring),
171 per_ls(visitor, strategy));
176 } // namespace dispatch
177 #endif // DOXYGEN_NO_DISPATCH
180 }} // namespace boost::geometry
183 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINEAR_HPP