File indexing completed on 2025-01-18 09:35:21
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef BOOST_GEOMETRY_ALGORITHMS_IS_CONVEX_HPP
0015 #define BOOST_GEOMETRY_ALGORITHMS_IS_CONVEX_HPP
0016
0017
0018 #include <boost/range/empty.hpp>
0019 #include <boost/range/size.hpp>
0020
0021 #include <boost/geometry/algorithms/detail/equals/point_point.hpp>
0022 #include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
0023 #include <boost/geometry/algorithms/detail/visit.hpp>
0024 #include <boost/geometry/core/closure.hpp>
0025 #include <boost/geometry/core/exterior_ring.hpp>
0026 #include <boost/geometry/core/interior_rings.hpp>
0027 #include <boost/geometry/core/visit.hpp>
0028 #include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
0029 #include <boost/geometry/geometries/concepts/check.hpp>
0030 #include <boost/geometry/iterators/ever_circling_iterator.hpp>
0031 #include <boost/geometry/strategies/default_strategy.hpp>
0032 #include <boost/geometry/strategies/is_convex/cartesian.hpp>
0033 #include <boost/geometry/strategies/is_convex/geographic.hpp>
0034 #include <boost/geometry/strategies/is_convex/spherical.hpp>
0035 #include <boost/geometry/views/detail/closed_clockwise_view.hpp>
0036
0037
0038 namespace boost { namespace geometry
0039 {
0040
0041
0042 #ifndef DOXYGEN_NO_DETAIL
0043 namespace detail { namespace is_convex
0044 {
0045
0046 struct ring_is_convex
0047 {
0048 template <typename Ring, typename Strategies>
0049 static inline bool apply(Ring const& ring, Strategies const& strategies)
0050 {
0051 std::size_t n = boost::size(ring);
0052 if (n < detail::minimum_ring_size<Ring>::value)
0053 {
0054
0055 return true;
0056 }
0057
0058
0059
0060
0061 using view_type = detail::closed_clockwise_view<Ring const>;
0062 view_type const view(ring);
0063
0064 using it_type = geometry::ever_circling_range_iterator<view_type const>;
0065 it_type previous(view);
0066 it_type current(view);
0067 current++;
0068
0069 auto const equals_strategy = strategies.relate(dummy_point(), dummy_point());
0070
0071 std::size_t index = 1;
0072 while (equals::equals_point_point(*current, *previous, equals_strategy)
0073 && index < n)
0074 {
0075 current++;
0076 index++;
0077 }
0078
0079 if (index == n)
0080 {
0081
0082 return true;
0083 }
0084
0085 it_type next = current;
0086 next++;
0087 while (equals::equals_point_point(*current, *next, equals_strategy))
0088 {
0089 next++;
0090 }
0091
0092 auto const side_strategy = strategies.side();
0093
0094
0095
0096
0097 for (std::size_t i = 0; i < n; i++)
0098 {
0099 int const side = side_strategy.apply(*previous, *current, *next);
0100 if (side == 1)
0101 {
0102
0103
0104 return false;
0105 }
0106
0107 previous = current;
0108 current = next;
0109
0110
0111
0112 next++;
0113 while (equals::equals_point_point(*current, *next, equals_strategy))
0114 {
0115 next++;
0116 }
0117 }
0118 return true;
0119 }
0120 };
0121
0122
0123 struct polygon_is_convex
0124 {
0125 template <typename Polygon, typename Strategies>
0126 static inline bool apply(Polygon const& polygon, Strategies const& strategies)
0127 {
0128 return boost::empty(interior_rings(polygon))
0129 && ring_is_convex::apply(exterior_ring(polygon), strategies);
0130 }
0131 };
0132
0133 struct multi_polygon_is_convex
0134 {
0135 template <typename MultiPolygon, typename Strategies>
0136 static inline bool apply(MultiPolygon const& multi_polygon, Strategies const& strategies)
0137 {
0138 auto const size = boost::size(multi_polygon);
0139
0140 return size == 0
0141 || (size == 1 && polygon_is_convex::apply(range::front(multi_polygon), strategies));
0142 }
0143 };
0144
0145
0146 }}
0147 #endif
0148
0149
0150 #ifndef DOXYGEN_NO_DISPATCH
0151 namespace dispatch
0152 {
0153
0154 template
0155 <
0156 typename Geometry,
0157 typename Tag = typename tag<Geometry>::type
0158 >
0159 struct is_convex
0160 {
0161 template <typename Strategies>
0162 static inline bool apply(Geometry const&, Strategies const&)
0163 {
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173 return false;
0174 }
0175 };
0176
0177 template <typename Box>
0178 struct is_convex<Box, box_tag>
0179 {
0180 template <typename Strategies>
0181 static inline bool apply(Box const& , Strategies const& )
0182 {
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198 return true;
0199 }
0200 };
0201
0202 template <typename Ring>
0203 struct is_convex<Ring, ring_tag> : detail::is_convex::ring_is_convex
0204 {};
0205
0206 template <typename Polygon>
0207 struct is_convex<Polygon, polygon_tag> : detail::is_convex::polygon_is_convex
0208 {};
0209
0210 template <typename MultiPolygon>
0211 struct is_convex<MultiPolygon, multi_polygon_tag> : detail::is_convex::multi_polygon_is_convex
0212 {};
0213
0214
0215 }
0216 #endif
0217
0218 namespace resolve_strategy {
0219
0220 template
0221 <
0222 typename Strategies,
0223 bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
0224 >
0225 struct is_convex
0226 {
0227 template <typename Geometry>
0228 static bool apply(Geometry const& geometry, Strategies const& strategies)
0229 {
0230 return dispatch::is_convex<Geometry>::apply(geometry, strategies);
0231 }
0232 };
0233
0234 template <typename Strategy>
0235 struct is_convex<Strategy, false>
0236 {
0237 template <typename Geometry>
0238 static bool apply(Geometry const& geometry, Strategy const& strategy)
0239 {
0240 using strategies::is_convex::services::strategy_converter;
0241 return dispatch::is_convex
0242 <
0243 Geometry
0244 >::apply(geometry, strategy_converter<Strategy>::get(strategy));
0245 }
0246 };
0247
0248 template <>
0249 struct is_convex<default_strategy, false>
0250 {
0251 template <typename Geometry>
0252 static bool apply(Geometry const& geometry, default_strategy const& )
0253 {
0254 typedef typename strategies::is_convex::services::default_strategy
0255 <
0256 Geometry
0257 >::type strategy_type;
0258
0259 return dispatch::is_convex<Geometry>::apply(geometry, strategy_type());
0260 }
0261 };
0262
0263 }
0264
0265 namespace resolve_dynamic {
0266
0267 template <typename Geometry, typename Tag = typename tag<Geometry>::type>
0268 struct is_convex
0269 {
0270 template <typename Strategy>
0271 static bool apply(Geometry const& geometry, Strategy const& strategy)
0272 {
0273 concepts::check<Geometry const>();
0274 return resolve_strategy::is_convex<Strategy>::apply(geometry, strategy);
0275 }
0276 };
0277
0278 template <typename Geometry>
0279 struct is_convex<Geometry, dynamic_geometry_tag>
0280 {
0281 template <typename Strategy>
0282 static inline bool apply(Geometry const& geometry, Strategy const& strategy)
0283 {
0284 bool result = false;
0285 traits::visit<Geometry>::apply([&](auto const& g)
0286 {
0287 result = is_convex<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
0288 }, geometry);
0289 return result;
0290 }
0291 };
0292
0293
0294
0295
0296 template <typename Geometry>
0297 struct is_convex<Geometry, geometry_collection_tag>
0298 {
0299 template <typename Strategy>
0300 static inline bool apply(Geometry const& geometry, Strategy const& strategy)
0301 {
0302 bool result = false;
0303 bool is_first = true;
0304 detail::visit_breadth_first([&](auto const& g)
0305 {
0306 result = is_first
0307 && is_convex<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
0308 is_first = false;
0309 return result;
0310 }, geometry);
0311 return result;
0312 }
0313 };
0314
0315 }
0316
0317
0318 template<typename Geometry>
0319 inline bool is_convex(Geometry const& geometry)
0320 {
0321 return resolve_dynamic::is_convex
0322 <
0323 Geometry
0324 >::apply(geometry, geometry::default_strategy());
0325 }
0326
0327
0328 template<typename Geometry, typename Strategy>
0329 inline bool is_convex(Geometry const& geometry, Strategy const& strategy)
0330 {
0331 return resolve_dynamic::is_convex<Geometry>::apply(geometry, strategy);
0332 }
0333
0334
0335 }}
0336
0337
0338 #endif