linear.hpp 5.6 KB

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