linear.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2014-2019, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  4. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  5. // Licensed under the Boost Software License version 1.0.
  6. // http://www.boost.org/users/license.html
  7. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINEAR_HPP
  8. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINEAR_HPP
  9. #include <cstddef>
  10. #include <boost/range.hpp>
  11. #include <boost/geometry/core/closure.hpp>
  12. #include <boost/geometry/core/point_type.hpp>
  13. #include <boost/geometry/core/tags.hpp>
  14. #include <boost/geometry/util/condition.hpp>
  15. #include <boost/geometry/util/range.hpp>
  16. #include <boost/geometry/algorithms/equals.hpp>
  17. #include <boost/geometry/algorithms/validity_failure_type.hpp>
  18. #include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
  19. #include <boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp>
  20. #include <boost/geometry/algorithms/detail/is_valid/has_spikes.hpp>
  21. #include <boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp>
  22. #include <boost/geometry/algorithms/dispatch/is_valid.hpp>
  23. namespace boost { namespace geometry
  24. {
  25. #ifndef DOXYGEN_NO_DETAIL
  26. namespace detail { namespace is_valid
  27. {
  28. template <typename Linestring>
  29. struct is_valid_linestring
  30. {
  31. template <typename VisitPolicy, typename Strategy>
  32. static inline bool apply(Linestring const& linestring,
  33. VisitPolicy& visitor,
  34. Strategy const& strategy)
  35. {
  36. if (has_invalid_coordinate<Linestring>::apply(linestring, visitor))
  37. {
  38. return false;
  39. }
  40. if (boost::size(linestring) < 2)
  41. {
  42. return visitor.template apply<failure_few_points>();
  43. }
  44. std::size_t num_distinct = detail::num_distinct_consecutive_points
  45. <
  46. Linestring,
  47. 3u,
  48. true,
  49. not_equal_to
  50. <
  51. typename point_type<Linestring>::type,
  52. typename Strategy::equals_point_point_strategy_type
  53. >
  54. >::apply(linestring);
  55. if (num_distinct < 2u)
  56. {
  57. return
  58. visitor.template apply<failure_wrong_topological_dimension>();
  59. }
  60. if (num_distinct == 2u)
  61. {
  62. return visitor.template apply<no_failure>();
  63. }
  64. return ! has_spikes
  65. <
  66. Linestring, closed
  67. >::apply(linestring, visitor,
  68. strategy.get_side_strategy());
  69. }
  70. };
  71. }} // namespace detail::is_valid
  72. #endif // DOXYGEN_NO_DETAIL
  73. #ifndef DOXYGEN_NO_DISPATCH
  74. namespace dispatch
  75. {
  76. // A linestring is a curve.
  77. // A curve is 1-dimensional so it has to have at least two distinct
  78. // points.
  79. // A curve is simple if it does not pass through the same point twice,
  80. // with the possible exception of its two endpoints
  81. //
  82. // There is an option here as to whether spikes are allowed for linestrings;
  83. // here we pass this as an additional template parameter: allow_spikes
  84. // If allow_spikes is set to true, spikes are allowed, false otherwise.
  85. // By default, spikes are disallowed
  86. //
  87. // Reference: OGC 06-103r4 (6.1.6.1)
  88. template <typename Linestring, bool AllowEmptyMultiGeometries>
  89. struct is_valid
  90. <
  91. Linestring, linestring_tag, AllowEmptyMultiGeometries
  92. > : detail::is_valid::is_valid_linestring<Linestring>
  93. {};
  94. // A MultiLinestring is a MultiCurve
  95. // A MultiCurve is simple if all of its elements are simple and the
  96. // only intersections between any two elements occur at Points that
  97. // are on the boundaries of both elements.
  98. //
  99. // Reference: OGC 06-103r4 (6.1.8.1; Fig. 9)
  100. template <typename MultiLinestring, bool AllowEmptyMultiGeometries>
  101. class is_valid
  102. <
  103. MultiLinestring, multi_linestring_tag, AllowEmptyMultiGeometries
  104. >
  105. {
  106. private:
  107. template <typename VisitPolicy, typename Strategy>
  108. struct per_linestring
  109. {
  110. per_linestring(VisitPolicy& policy, Strategy const& strategy)
  111. : m_policy(policy)
  112. , m_strategy(strategy)
  113. {}
  114. template <typename Linestring>
  115. inline bool apply(Linestring const& linestring) const
  116. {
  117. return detail::is_valid::is_valid_linestring
  118. <
  119. Linestring
  120. >::apply(linestring, m_policy, m_strategy);
  121. }
  122. VisitPolicy& m_policy;
  123. Strategy const& m_strategy;
  124. };
  125. public:
  126. template <typename VisitPolicy, typename Strategy>
  127. static inline bool apply(MultiLinestring const& multilinestring,
  128. VisitPolicy& visitor,
  129. Strategy const& strategy)
  130. {
  131. if (BOOST_GEOMETRY_CONDITION(
  132. AllowEmptyMultiGeometries && boost::empty(multilinestring)))
  133. {
  134. return visitor.template apply<no_failure>();
  135. }
  136. typedef per_linestring<VisitPolicy, Strategy> per_ls;
  137. return detail::check_iterator_range
  138. <
  139. per_ls,
  140. false // do not check for empty multilinestring (done above)
  141. >::apply(boost::begin(multilinestring),
  142. boost::end(multilinestring),
  143. per_ls(visitor, strategy));
  144. }
  145. };
  146. } // namespace dispatch
  147. #endif // DOXYGEN_NO_DISPATCH
  148. }} // namespace boost::geometry
  149. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_LINEAR_HPP