summaryrefslogtreecommitdiff
path: root/boost/geometry/algorithms/correct.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/algorithms/correct.hpp')
-rw-r--r--boost/geometry/algorithms/correct.hpp268
1 files changed, 126 insertions, 142 deletions
diff --git a/boost/geometry/algorithms/correct.hpp b/boost/geometry/algorithms/correct.hpp
index 3c338916bf..20a94de85c 100644
--- a/boost/geometry/algorithms/correct.hpp
+++ b/boost/geometry/algorithms/correct.hpp
@@ -5,8 +5,9 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017-2020.
-// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2023.
+// Modifications copyright (c) 2017-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -21,33 +22,31 @@
#include <algorithm>
-#include <cstddef>
#include <functional>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
-#include <boost/range/value_type.hpp>
-
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
+#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/correct_closure.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
+#include <boost/geometry/algorithms/detail/multi_modify.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
-#include <boost/geometry/core/closure.hpp>
-#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
-#include <boost/geometry/core/mutable_range.hpp>
-#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/visit.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
-#include <boost/geometry/algorithms/area.hpp>
-#include <boost/geometry/algorithms/detail/multi_modify.hpp>
-#include <boost/geometry/util/order_as_direction.hpp>
+#include <boost/geometry/strategies/area/cartesian.hpp>
+#include <boost/geometry/strategies/area/geographic.hpp>
+#include <boost/geometry/strategies/area/spherical.hpp>
+#include <boost/geometry/strategies/detail.hpp>
+
+#include <boost/geometry/util/algorithm.hpp>
+
namespace boost { namespace geometry
{
@@ -62,92 +61,56 @@ namespace boost { namespace geometry
namespace detail { namespace correct
{
-template <typename Geometry>
struct correct_nop
{
- template <typename Strategy>
+ template <typename Geometry, typename Strategy>
static inline void apply(Geometry& , Strategy const& )
{}
};
-template <typename Box, std::size_t Dimension, std::size_t DimensionCount>
-struct correct_box_loop
-{
- typedef typename coordinate_type<Box>::type coordinate_type;
-
- static inline void apply(Box& box)
- {
- if (get<min_corner, Dimension>(box) > get<max_corner, Dimension>(box))
- {
- // Swap the coordinates
- coordinate_type max_value = get<min_corner, Dimension>(box);
- coordinate_type min_value = get<max_corner, Dimension>(box);
- set<min_corner, Dimension>(box, min_value);
- set<max_corner, Dimension>(box, max_value);
- }
-
- correct_box_loop
- <
- Box, Dimension + 1, DimensionCount
- >::apply(box);
- }
-};
-
-
-
-template <typename Box, std::size_t DimensionCount>
-struct correct_box_loop<Box, DimensionCount, DimensionCount>
-{
- static inline void apply(Box& )
- {}
-
-};
-
-
// Correct a box: make min/max correct
-template <typename Box>
struct correct_box
{
- template <typename Strategy>
+ template <typename Box, typename Strategy>
static inline void apply(Box& box, Strategy const& )
{
+ using coordinate_type = typename geometry::coordinate_type<Box>::type;
+
// Currently only for Cartesian coordinates
// (or spherical without crossing dateline)
// Future version: adapt using strategies
- correct_box_loop
- <
- Box, 0, dimension<Box>::type::value
- >::apply(box);
+ detail::for_each_dimension<Box>([&](auto dimension)
+ {
+ if (get<min_corner, dimension>(box) > get<max_corner, dimension>(box))
+ {
+ // Swap the coordinates
+ coordinate_type max_value = get<min_corner, dimension>(box);
+ coordinate_type min_value = get<max_corner, dimension>(box);
+ set<min_corner, dimension>(box, min_value);
+ set<max_corner, dimension>(box, max_value);
+ }
+ });
}
};
// Close a ring, if not closed
-template <typename Ring, template <typename> class Predicate>
+template <typename Predicate = std::less<>>
struct correct_ring
{
- typedef typename point_type<Ring>::type point_type;
- typedef typename coordinate_type<Ring>::type coordinate_type;
-
- template <typename Strategy>
+ template <typename Ring, typename Strategy>
static inline void apply(Ring& r, Strategy const& strategy)
{
// Correct closure if necessary
- detail::correct_closure::close_or_open_ring<Ring>::apply(r);
+ detail::correct_closure::close_or_open_ring::apply(r);
+
+ // NOTE: calculate_point_order should probably be used here instead.
// Check area
- typedef typename area_result<Ring, Strategy>::type area_result_type;
- Predicate<area_result_type> predicate;
- area_result_type const zero = 0;
- if (predicate(detail::area::ring_area::apply(
- r,
- // TEMP - in the future (umbrella) strategy will be passed
- geometry::strategies::area::services::strategy_converter
- <
- Strategy
- >::get(strategy)),
- zero))
+ using area_t = typename area_result<Ring, Strategy>::type;
+ area_t const zero = 0;
+ if (Predicate()(detail::area::ring_area::apply(r, strategy), zero))
{
std::reverse(boost::begin(r), boost::end(r));
}
@@ -156,30 +119,18 @@ struct correct_ring
// Correct a polygon: normalizes all rings, sets outer ring clockwise, sets all
// inner rings counter clockwise (or vice versa depending on orientation)
-template <typename Polygon>
struct correct_polygon
{
- typedef typename ring_type<Polygon>::type ring_type;
-
- template <typename Strategy>
+ template <typename Polygon, typename Strategy>
static inline void apply(Polygon& poly, Strategy const& strategy)
{
- correct_ring
- <
- ring_type,
- std::less
- >::apply(exterior_ring(poly), strategy);
-
- typename interior_return_type<Polygon>::type
- rings = interior_rings(poly);
- for (typename detail::interior_iterator<Polygon>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ correct_ring<std::less<>>::apply(exterior_ring(poly), strategy);
+
+ auto&& rings = interior_rings(poly);
+ auto const end = boost::end(rings);
+ for (auto it = boost::begin(rings); it != end; ++it)
{
- correct_ring
- <
- ring_type,
- std::greater
- >::apply(*it, strategy);
+ correct_ring<std::greater<>>::apply(*it, strategy);
}
}
};
@@ -199,62 +150,51 @@ struct correct: not_implemented<Tag>
template <typename Point>
struct correct<Point, point_tag>
- : detail::correct::correct_nop<Point>
+ : detail::correct::correct_nop
{};
template <typename LineString>
struct correct<LineString, linestring_tag>
- : detail::correct::correct_nop<LineString>
+ : detail::correct::correct_nop
{};
template <typename Segment>
struct correct<Segment, segment_tag>
- : detail::correct::correct_nop<Segment>
+ : detail::correct::correct_nop
{};
template <typename Box>
struct correct<Box, box_tag>
- : detail::correct::correct_box<Box>
+ : detail::correct::correct_box
{};
template <typename Ring>
struct correct<Ring, ring_tag>
- : detail::correct::correct_ring
- <
- Ring,
- std::less
- >
+ : detail::correct::correct_ring<>
{};
template <typename Polygon>
struct correct<Polygon, polygon_tag>
- : detail::correct::correct_polygon<Polygon>
+ : detail::correct::correct_polygon
{};
template <typename MultiPoint>
struct correct<MultiPoint, multi_point_tag>
- : detail::correct::correct_nop<MultiPoint>
+ : detail::correct::correct_nop
{};
template <typename MultiLineString>
struct correct<MultiLineString, multi_linestring_tag>
- : detail::correct::correct_nop<MultiLineString>
+ : detail::correct::correct_nop
{};
template <typename Geometry>
struct correct<Geometry, multi_polygon_tag>
- : detail::multi_modify
- <
- Geometry,
- detail::correct::correct_polygon
- <
- typename boost::range_value<Geometry>::type
- >
- >
+ : detail::multi_modify<detail::correct::correct_polygon>
{};
@@ -262,45 +202,96 @@ struct correct<Geometry, multi_polygon_tag>
#endif // DOXYGEN_NO_DISPATCH
-namespace resolve_variant {
+namespace resolve_strategy
+{
-template <typename Geometry>
+template
+<
+ typename Strategy,
+ bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
+>
struct correct
{
- template <typename Strategy>
+ template <typename Geometry>
static inline void apply(Geometry& geometry, Strategy const& strategy)
{
- concepts::check<Geometry const>();
dispatch::correct<Geometry>::apply(geometry, strategy);
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct correct<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Strategy>
+struct correct<Strategy, false>
{
- template <typename Strategy>
- struct visitor: boost::static_visitor<void>
+ template <typename Geometry>
+ static inline void apply(Geometry& geometry, Strategy const& strategy)
+ {
+ // NOTE: calculate_point_order strategy should probably be used here instead.
+ using geometry::strategies::area::services::strategy_converter;
+ dispatch::correct<Geometry>::apply(geometry, strategy_converter<Strategy>::get(strategy));
+ }
+};
+
+template <>
+struct correct<default_strategy, false>
+{
+ template <typename Geometry>
+ static inline void apply(Geometry& geometry, default_strategy const& )
{
- Strategy const& m_strategy;
+ // NOTE: calculate_point_order strategy should probably be used here instead.
+ using strategy_type = typename strategies::area::services::default_strategy
+ <
+ Geometry
+ >::type;
+ dispatch::correct<Geometry>::apply(geometry, strategy_type());
+ }
+};
+
+} // namespace resolve_strategy
- visitor(Strategy const& strategy): m_strategy(strategy) {}
- template <typename Geometry>
- void operator()(Geometry& geometry) const
+namespace resolve_dynamic
+{
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct correct
+{
+ template <typename Strategy>
+ static inline void apply(Geometry& geometry, Strategy const& strategy)
+ {
+ concepts::check<Geometry>();
+ resolve_strategy::correct<Strategy>::apply(geometry, strategy);
+ }
+};
+
+template <typename Geometry>
+struct correct<Geometry, dynamic_geometry_tag>
+{
+ template <typename Strategy>
+ static inline void apply(Geometry& geometry, Strategy const& strategy)
+ {
+ traits::visit<Geometry>::apply([&](auto & g)
{
- correct<Geometry>::apply(geometry, m_strategy);
- }
- };
+ correct<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
+ }, geometry);
+ }
+};
+template <typename Geometry>
+struct correct<Geometry, geometry_collection_tag>
+{
template <typename Strategy>
- static inline void
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry, Strategy const& strategy)
+ static inline void apply(Geometry& geometry, Strategy const& strategy)
{
- boost::apply_visitor(visitor<Strategy>(strategy), geometry);
+ detail::visit_breadth_first([&](auto & g)
+ {
+ correct<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
+ return true;
+ }, geometry);
}
};
-} // namespace resolve_variant
+
+} // namespace resolve_dynamic
/*!
@@ -318,14 +309,7 @@ struct correct<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
inline void correct(Geometry& geometry)
{
- typedef typename point_type<Geometry>::type point_type;
-
- typedef typename strategy::area::services::default_strategy
- <
- typename cs_tag<point_type>::type
- >::type strategy_type;
-
- resolve_variant::correct<Geometry>::apply(geometry, strategy_type());
+ resolve_dynamic::correct<Geometry>::apply(geometry, default_strategy());
}
/*!
@@ -347,7 +331,7 @@ inline void correct(Geometry& geometry)
template <typename Geometry, typename Strategy>
inline void correct(Geometry& geometry, Strategy const& strategy)
{
- resolve_variant::correct<Geometry>::apply(geometry, strategy);
+ resolve_dynamic::correct<Geometry>::apply(geometry, strategy);
}
#if defined(_MSC_VER)