1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2014-2020, 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/begin.hpp>
17 #include <boost/range/empty.hpp>
18 #include <boost/range/end.hpp>
19 #include <boost/range/size.hpp>
21 #include <boost/geometry/algorithms/equals.hpp>
22 #include <boost/geometry/algorithms/validity_failure_type.hpp>
23 #include <boost/geometry/algorithms/detail/check_iterator_range.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
72 typename point_type<Linestring>::type,
73 typename Strategy::equals_point_point_strategy_type
77 if (num_distinct < 2u)
80 visitor.template apply<failure_wrong_topological_dimension>();
83 if (num_distinct == 2u)
85 return visitor.template apply<no_failure>();
88 // TODO: This algorithm iterates over the linestring until a spike is
89 // found and only then the decision about the validity is made. This
90 // is done regardless of VisitPolicy.
91 // An obvious improvement is to avoid calling the algorithm at all if
92 // spikes are allowed which is the default.
96 >::apply(linestring, visitor,
97 strategy.get_side_strategy());
102 }} // namespace detail::is_valid
103 #endif // DOXYGEN_NO_DETAIL
108 #ifndef DOXYGEN_NO_DISPATCH
113 // A linestring is a curve.
114 // A curve is 1-dimensional so it has to have at least two distinct
116 // A curve is simple if it does not pass through the same point twice,
117 // with the possible exception of its two endpoints
119 // There is an option here as to whether spikes are allowed for linestrings;
120 // here we pass this as an additional template parameter: allow_spikes
121 // If allow_spikes is set to true, spikes are allowed, false otherwise.
122 // By default, spikes are disallowed
124 // Reference: OGC 06-103r4 (6.1.6.1)
125 template <typename Linestring, bool AllowEmptyMultiGeometries>
128 Linestring, linestring_tag, AllowEmptyMultiGeometries
129 > : detail::is_valid::is_valid_linestring<Linestring>
133 // A MultiLinestring is a MultiCurve
134 // A MultiCurve is simple if all of its elements are simple and the
135 // only intersections between any two elements occur at Points that
136 // are on the boundaries of both elements.
138 // Reference: OGC 06-103r4 (6.1.8.1; Fig. 9)
139 template <typename MultiLinestring, bool AllowEmptyMultiGeometries>
142 MultiLinestring, multi_linestring_tag, AllowEmptyMultiGeometries
146 template <typename VisitPolicy, typename Strategy>
147 struct per_linestring
149 per_linestring(VisitPolicy& policy, Strategy const& strategy)
151 , m_strategy(strategy)
154 template <typename Linestring>
155 inline bool apply(Linestring const& linestring) const
157 return detail::is_valid::is_valid_linestring
160 >::apply(linestring, m_policy, m_strategy);
163 VisitPolicy& m_policy;
164 Strategy const& m_strategy;
168 template <typename VisitPolicy, typename Strategy>
169 static inline bool apply(MultiLinestring const& multilinestring,
170 VisitPolicy& visitor,
171 Strategy const& strategy)
173 if (BOOST_GEOMETRY_CONDITION(
174 AllowEmptyMultiGeometries && boost::empty(multilinestring)))
176 return visitor.template apply<no_failure>();
179 typedef per_linestring<VisitPolicy, Strategy> per_ls;
181 return detail::check_iterator_range
184 false // do not check for empty multilinestring (done above)
185 >::apply(boost::begin(multilinestring),
186 boost::end(multilinestring),
187 per_ls(visitor, strategy));
192 } // namespace dispatch
193 #endif // DOXYGEN_NO_DISPATCH
196 }} // namespace boost::geometry
199 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINEAR_HPP