summaryrefslogtreecommitdiff
path: root/boost/geometry/algorithms/detail
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/algorithms/detail')
-rw-r--r--boost/geometry/algorithms/detail/as_range.hpp91
-rw-r--r--[-rwxr-xr-x]boost/geometry/algorithms/detail/buffer/buffer_box.hpp0
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp84
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffer_policies.hpp2
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp228
-rw-r--r--boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp17
-rw-r--r--boost/geometry/algorithms/detail/buffer/implementation.hpp214
-rw-r--r--boost/geometry/algorithms/detail/buffer/interface.hpp279
-rw-r--r--boost/geometry/algorithms/detail/buffer/piece_border.hpp63
-rw-r--r--boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp21
-rw-r--r--boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp55
-rw-r--r--boost/geometry/algorithms/detail/calculate_point_order.hpp45
-rw-r--r--boost/geometry/algorithms/detail/calculate_sum.hpp3
-rw-r--r--boost/geometry/algorithms/detail/centroid/translating_transformer.hpp2
-rw-r--r--boost/geometry/algorithms/detail/check_iterator_range.hpp71
-rw-r--r--boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp4
-rw-r--r--boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp2
-rw-r--r--boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp2
-rw-r--r--boost/geometry/algorithms/detail/closest_points/implementation.hpp28
-rw-r--r--boost/geometry/algorithms/detail/closest_points/interface.hpp225
-rw-r--r--boost/geometry/algorithms/detail/closest_points/linear_or_areal_to_areal.hpp261
-rw-r--r--boost/geometry/algorithms/detail/closest_points/linear_to_linear.hpp155
-rw-r--r--boost/geometry/algorithms/detail/closest_points/multipoint_to_geometry.hpp325
-rw-r--r--boost/geometry/algorithms/detail/closest_points/point_to_geometry.hpp456
-rw-r--r--boost/geometry/algorithms/detail/closest_points/range_to_geometry_rtree.hpp110
-rw-r--r--boost/geometry/algorithms/detail/closest_points/segment_to_segment.hpp145
-rw-r--r--boost/geometry/algorithms/detail/closest_points/utilities.hpp69
-rw-r--r--boost/geometry/algorithms/detail/comparable_distance/interface.hpp278
-rw-r--r--boost/geometry/algorithms/detail/convert_point_to_point.hpp6
-rw-r--r--boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp131
-rw-r--r--boost/geometry/algorithms/detail/convex_hull/interface.hpp619
-rw-r--r--boost/geometry/algorithms/detail/counting.hpp15
-rw-r--r--boost/geometry/algorithms/detail/covered_by/implementation.hpp129
-rw-r--r--boost/geometry/algorithms/detail/covered_by/implementation_gc.hpp46
-rw-r--r--boost/geometry/algorithms/detail/covered_by/interface.hpp146
-rw-r--r--boost/geometry/algorithms/detail/direction_code.hpp134
-rw-r--r--boost/geometry/algorithms/detail/disjoint/areal_areal.hpp11
-rw-r--r--boost/geometry/algorithms/detail/disjoint/linear_areal.hpp41
-rw-r--r--boost/geometry/algorithms/detail/disjoint/linear_linear.hpp17
-rw-r--r--boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp57
-rw-r--r--boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp21
-rw-r--r--boost/geometry/algorithms/detail/disjoint/point_geometry.hpp6
-rw-r--r--boost/geometry/algorithms/detail/disjoint/segment_box.hpp5
-rw-r--r--boost/geometry/algorithms/detail/distance/geometry_collection.hpp237
-rw-r--r--boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp48
-rw-r--r--boost/geometry/algorithms/detail/distance/implementation.hpp3
-rw-r--r--boost/geometry/algorithms/detail/distance/interface.hpp254
-rw-r--r--boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp6
-rw-r--r--boost/geometry/algorithms/detail/distance/linear_to_linear.hpp2
-rw-r--r--boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp23
-rw-r--r--boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp2
-rw-r--r--boost/geometry/algorithms/detail/distance/segment_to_box.hpp12
-rw-r--r--boost/geometry/algorithms/detail/envelope/areal.hpp29
-rw-r--r--boost/geometry/algorithms/detail/envelope/geometry_collection.hpp62
-rw-r--r--boost/geometry/algorithms/detail/envelope/implementation.hpp3
-rw-r--r--boost/geometry/algorithms/detail/envelope/interface.hpp53
-rw-r--r--boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp4
-rw-r--r--boost/geometry/algorithms/detail/envelope/range.hpp73
-rw-r--r--boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp40
-rw-r--r--boost/geometry/algorithms/detail/equals/collect_vectors.hpp173
-rw-r--r--boost/geometry/algorithms/detail/equals/implementation.hpp117
-rw-r--r--boost/geometry/algorithms/detail/equals/implementation_gc.hpp114
-rw-r--r--boost/geometry/algorithms/detail/equals/interface.hpp159
-rw-r--r--boost/geometry/algorithms/detail/expand/indexed.hpp2
-rw-r--r--boost/geometry/algorithms/detail/expand/interface.hpp85
-rw-r--r--boost/geometry/algorithms/detail/expand_by_epsilon.hpp2
-rw-r--r--boost/geometry/algorithms/detail/extreme_points.hpp18
-rw-r--r--boost/geometry/algorithms/detail/gc_group_elements.hpp196
-rw-r--r--boost/geometry/algorithms/detail/gc_make_rtree.hpp118
-rw-r--r--boost/geometry/algorithms/detail/gc_topological_dimension.hpp51
-rw-r--r--boost/geometry/algorithms/detail/has_self_intersections.hpp4
-rw-r--r--boost/geometry/algorithms/detail/interior_iterator.hpp2
-rw-r--r--boost/geometry/algorithms/detail/intersection/areal_areal.hpp2
-rw-r--r--boost/geometry/algorithms/detail/intersection/gc.hpp329
-rw-r--r--boost/geometry/algorithms/detail/intersection/implementation.hpp5
-rw-r--r--boost/geometry/algorithms/detail/intersection/interface.hpp226
-rw-r--r--boost/geometry/algorithms/detail/intersection/multi.hpp73
-rw-r--r--boost/geometry/algorithms/detail/is_simple/areal.hpp23
-rw-r--r--boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp10
-rw-r--r--boost/geometry/algorithms/detail/is_simple/linear.hpp29
-rw-r--r--boost/geometry/algorithms/detail/is_simple/multipoint.hpp6
-rw-r--r--boost/geometry/algorithms/detail/is_valid/complement_graph.hpp16
-rw-r--r--boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp19
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp29
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_spikes.hpp21
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp18
-rw-r--r--boost/geometry/algorithms/detail/is_valid/interface.hpp72
-rw-r--r--boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp2
-rw-r--r--boost/geometry/algorithms/detail/is_valid/linear.hpp32
-rw-r--r--boost/geometry/algorithms/detail/is_valid/multipolygon.hpp42
-rw-r--r--boost/geometry/algorithms/detail/is_valid/polygon.hpp34
-rw-r--r--boost/geometry/algorithms/detail/make/make.hpp14
-rw-r--r--boost/geometry/algorithms/detail/max_interval_gap.hpp2
-rw-r--r--boost/geometry/algorithms/detail/multi_modify.hpp21
-rw-r--r--boost/geometry/algorithms/detail/multi_modify_with_predicate.hpp5
-rw-r--r--boost/geometry/algorithms/detail/multi_sum.hpp9
-rw-r--r--boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp13
-rw-r--r--boost/geometry/algorithms/detail/overlaps/implementation.hpp78
-rw-r--r--boost/geometry/algorithms/detail/overlaps/interface.hpp103
-rw-r--r--boost/geometry/algorithms/detail/overlay/add_rings.hpp24
-rw-r--r--boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp21
-rw-r--r--boost/geometry/algorithms/detail/overlay/approximately_equals.hpp4
-rw-r--r--boost/geometry/algorithms/detail/overlay/assign_parents.hpp60
-rw-r--r--boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp16
-rw-r--r--boost/geometry/algorithms/detail/overlay/check_enrich.hpp27
-rw-r--r--boost/geometry/algorithms/detail/overlay/clip_linestring.hpp5
-rw-r--r--boost/geometry/algorithms/detail/overlay/cluster_exits.hpp32
-rw-r--r--boost/geometry/algorithms/detail/overlay/colocate_clusters.hpp107
-rw-r--r--boost/geometry/algorithms/detail/overlay/convert_ring.hpp1
-rw-r--r--boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp6
-rw-r--r--boost/geometry/algorithms/detail/overlay/copy_segments.hpp10
-rw-r--r--boost/geometry/algorithms/detail/overlay/discard_duplicate_turns.hpp6
-rw-r--r--boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp335
-rw-r--r--boost/geometry/algorithms/detail/overlay/follow.hpp46
-rw-r--r--boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp10
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_clusters.hpp18
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp87
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info.hpp420
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp8
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp44
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp38
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp61
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turns.hpp56
-rw-r--r--boost/geometry/algorithms/detail/overlay/handle_colocations.hpp118
-rw-r--r--boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp55
-rw-r--r--boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp2
-rw-r--r--boost/geometry/algorithms/detail/overlay/intersection_insert.hpp38
-rw-r--r--boost/geometry/algorithms/detail/overlay/is_self_turn.hpp3
-rw-r--r--boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp21
-rw-r--r--boost/geometry/algorithms/detail/overlay/linear_linear.hpp10
-rw-r--r--boost/geometry/algorithms/detail/overlay/overlay.hpp31
-rw-r--r--boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp2
-rw-r--r--boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp5
-rw-r--r--boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp29
-rw-r--r--boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp6
-rw-r--r--boost/geometry/algorithms/detail/overlay/ring_properties.hpp6
-rw-r--r--boost/geometry/algorithms/detail/overlay/select_rings.hpp44
-rw-r--r--boost/geometry/algorithms/detail/overlay/self_turn_points.hpp111
-rw-r--r--boost/geometry/algorithms/detail/overlay/sort_by_side.hpp36
-rw-r--r--boost/geometry/algorithms/detail/overlay/traversal.hpp175
-rw-r--r--boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp143
-rw-r--r--boost/geometry/algorithms/detail/overlay/traverse.hpp9
-rw-r--r--boost/geometry/algorithms/detail/overlay/turn_info.hpp10
-rw-r--r--boost/geometry/algorithms/detail/partition.hpp169
-rw-r--r--boost/geometry/algorithms/detail/point_on_border.hpp53
-rw-r--r--boost/geometry/algorithms/detail/recalculate.hpp7
-rw-r--r--boost/geometry/algorithms/detail/relate/areal_areal.hpp63
-rw-r--r--boost/geometry/algorithms/detail/relate/boundary_checker.hpp175
-rw-r--r--boost/geometry/algorithms/detail/relate/box_areal.hpp70
-rw-r--r--boost/geometry/algorithms/detail/relate/de9im.hpp39
-rw-r--r--boost/geometry/algorithms/detail/relate/follow_helpers.hpp130
-rw-r--r--boost/geometry/algorithms/detail/relate/implementation.hpp36
-rw-r--r--boost/geometry/algorithms/detail/relate/implementation_gc.hpp696
-rw-r--r--boost/geometry/algorithms/detail/relate/interface.hpp157
-rw-r--r--boost/geometry/algorithms/detail/relate/linear_areal.hpp513
-rw-r--r--boost/geometry/algorithms/detail/relate/linear_linear.hpp169
-rw-r--r--boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp69
-rw-r--r--boost/geometry/algorithms/detail/relate/point_geometry.hpp33
-rw-r--r--boost/geometry/algorithms/detail/relate/point_point.hpp89
-rw-r--r--boost/geometry/algorithms/detail/relate/result.hpp284
-rw-r--r--boost/geometry/algorithms/detail/relate/topology_check.hpp26
-rw-r--r--boost/geometry/algorithms/detail/relate/turns.hpp39
-rw-r--r--boost/geometry/algorithms/detail/relation/interface.hpp138
-rw-r--r--boost/geometry/algorithms/detail/sections/section_functions.hpp25
-rw-r--r--boost/geometry/algorithms/detail/sections/sectionalize.hpp200
-rw-r--r--boost/geometry/algorithms/detail/select_geometry_type.hpp78
-rw-r--r--boost/geometry/algorithms/detail/sweep.hpp7
-rw-r--r--boost/geometry/algorithms/detail/touches/implementation.hpp141
-rw-r--r--boost/geometry/algorithms/detail/touches/interface.hpp165
-rw-r--r--boost/geometry/algorithms/detail/tupled_output.hpp5
-rw-r--r--boost/geometry/algorithms/detail/turns/remove_duplicate_turns.hpp43
-rw-r--r--boost/geometry/algorithms/detail/visit.hpp70
-rw-r--r--boost/geometry/algorithms/detail/within/implementation.hpp16
-rw-r--r--boost/geometry/algorithms/detail/within/implementation_gc.hpp46
-rw-r--r--boost/geometry/algorithms/detail/within/interface.hpp151
-rw-r--r--boost/geometry/algorithms/detail/within/multi_point.hpp26
-rw-r--r--boost/geometry/algorithms/detail/within/point_in_geometry.hpp55
-rw-r--r--boost/geometry/algorithms/detail/within/within_no_turns.hpp93
178 files changed, 9045 insertions, 5071 deletions
diff --git a/boost/geometry/algorithms/detail/as_range.hpp b/boost/geometry/algorithms/detail/as_range.hpp
deleted file mode 100644
index fe2016be5e..0000000000
--- a/boost/geometry/algorithms/detail/as_range.hpp
+++ /dev/null
@@ -1,91 +0,0 @@
-// Boost.Geometry (aka GGL, Generic Geometry Library)
-
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-
-// This file was modified by Oracle on 2020-2021.
-// Modifications copyright (c) 2020-2021 Oracle and/or its affiliates.
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
-// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
-// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
-
-// Use, modification and distribution is subject to the Boost Software License,
-// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP
-#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP
-
-
-#include <boost/geometry/algorithms/not_implemented.hpp>
-
-#include <boost/geometry/core/exterior_ring.hpp>
-#include <boost/geometry/core/ring_type.hpp>
-#include <boost/geometry/core/tag.hpp>
-#include <boost/geometry/core/tags.hpp>
-
-
-namespace boost { namespace geometry
-{
-
-
-#ifndef DOXYGEN_NO_DISPATCH
-namespace dispatch
-{
-
-
-template <typename Geometry, typename Tag = typename tag<Geometry>::type>
-struct as_range : not_implemented<Geometry, Tag>
-{};
-
-template <typename Geometry>
-struct as_range<Geometry, linestring_tag>
-{
- static inline typename ring_return_type<Geometry>::type get(Geometry& geometry)
- {
- return geometry;
- }
-};
-
-template <typename Geometry>
-struct as_range<Geometry, ring_tag>
- : as_range<Geometry, linestring_tag>
-{};
-
-template <typename Geometry>
-struct as_range<Geometry, polygon_tag>
-{
- static inline typename ring_return_type<Geometry>::type get(Geometry& geometry)
- {
- return exterior_ring(geometry);
- }
-};
-
-
-} // namespace dispatch
-#endif // DOXYGEN_NO_DISPATCH
-
-// Will probably be replaced by the more generic "view_as", therefore in detail
-namespace detail
-{
-
-/*!
-\brief Function getting either the range (ring, linestring) itself
-or the outer ring (polygon)
-\details Utility to handle polygon's outer ring as a range
-\ingroup utility
-*/
-template <typename Geometry>
-inline typename ring_return_type<Geometry>::type as_range(Geometry& geometry)
-{
- return dispatch::as_range<Geometry>::get(geometry);
-}
-
-}
-
-}} // namespace boost::geometry
-
-
-#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP
diff --git a/boost/geometry/algorithms/detail/buffer/buffer_box.hpp b/boost/geometry/algorithms/detail/buffer/buffer_box.hpp
index f19a91d6ba..f19a91d6ba 100755..100644
--- a/boost/geometry/algorithms/detail/buffer/buffer_box.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffer_box.hpp
diff --git a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
index cc5c41d11b..5e8635c3d7 100644
--- a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
@@ -1,9 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2020 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2022-2023 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017-2021.
-// Modifications copyright (c) 2017-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2022.
+// Modifications copyright (c) 2017-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -37,10 +38,13 @@
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/geometries/linestring.hpp>
+#include <boost/geometry/geometries/ring.hpp>
+
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/strategies/side.hpp>
-#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/constexpr.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/type_traits.hpp>
@@ -54,11 +58,11 @@ namespace boost { namespace geometry
namespace detail { namespace buffer
{
-template <typename Range, typename DistanceStrategy, typename Strategies>
-inline void simplify_input(Range const& range,
- DistanceStrategy const& distance,
- Range& simplified,
- Strategies const& strategies)
+template <typename RangeIn, typename DistanceStrategy, typename RangeOut, typename Strategies>
+inline void simplify_input(RangeIn const& range,
+ DistanceStrategy const& distance,
+ RangeOut& simplified,
+ Strategies const& strategies)
{
// We have to simplify the ring before to avoid very small-scaled
// features in the original (convex/concave/convex) being enlarged
@@ -291,7 +295,7 @@ struct buffer_range
robust_policy, strategies);
}
- collection.add_side_piece(*prev, *it, generated_side, first);
+ collection.add_side_piece(*prev, *it, generated_side, first, distance_strategy.empty(side));
if (first && mark_flat)
{
@@ -350,10 +354,7 @@ struct buffer_multi
RobustPolicy const& robust_policy,
Strategies const& strategies)
{
- for (typename boost::range_iterator<Multi const>::type
- it = boost::begin(multi);
- it != boost::end(multi);
- ++it)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
Policy::apply(*it, collection,
distance_strategy, segment_strategy,
@@ -453,7 +454,7 @@ template
>
struct buffer_inserter_ring
{
- typedef typename point_type<RingOutput>::type output_point_type;
+ using output_point_type = typename point_type<RingOutput>::type;
template
<
@@ -524,7 +525,14 @@ struct buffer_inserter_ring
RobustPolicy const& robust_policy,
Strategies const& strategies)
{
- RingInput simplified;
+ // Use helper geometry to support non-mutable input Rings
+ using simplified_ring_t = model::ring
+ <
+ output_point_type,
+ point_order<RingInput>::value != counterclockwise,
+ closure<RingInput>::value != open
+ >;
+ simplified_ring_t simplified;
detail::buffer::simplify_input(ring, distance, simplified, strategies);
geometry::strategy::buffer::result_code code = geometry::strategy::buffer::result_no_output;
@@ -532,12 +540,12 @@ struct buffer_inserter_ring
std::size_t n = boost::size(simplified);
std::size_t const min_points = core_detail::closure::minimum_ring_size
<
- geometry::closure<RingInput>::value
+ geometry::closure<simplified_ring_t>::value
>::value;
if (n >= min_points)
{
- detail::closed_clockwise_view<RingInput const> view(simplified);
+ detail::closed_clockwise_view<simplified_ring_t const> view(simplified);
if (distance.negative())
{
// Walk backwards (rings will be reversed afterwards)
@@ -615,9 +623,8 @@ template
>
struct buffer_inserter<linestring_tag, Linestring, Polygon>
{
- typedef typename ring_type<Polygon>::type output_ring_type;
- typedef typename point_type<output_ring_type>::type output_point_type;
- typedef typename point_type<Linestring>::type input_point_type;
+ using output_ring_type = typename ring_type<Polygon>::type;
+ using output_point_type = typename point_type<output_ring_type>::type;
template
<
@@ -641,8 +648,8 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
Strategies const& strategies,
output_point_type& first_p1)
{
- input_point_type const& ultimate_point = *(end - 1);
- input_point_type const& penultimate_point = *(end - 2);
+ output_point_type const& ultimate_point = *(end - 1);
+ output_point_type const& penultimate_point = *(end - 2);
// For the end-cap, we need to have the last perpendicular point on the
// other side of the linestring. If it is the second pass (right),
@@ -708,7 +715,8 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
RobustPolicy const& robust_policy,
Strategies const& strategies)
{
- Linestring simplified;
+ // Use helper geometry to support non-mutable input Linestrings
+ model::linestring<output_point_type> simplified;
detail::buffer::simplify_input(linestring, distance, simplified, strategies);
geometry::strategy::buffer::result_code code = geometry::strategy::buffer::result_no_output;
@@ -934,17 +942,17 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
{
boost::ignore_unused(visit_pieces_policy);
- typedef detail::buffer::buffered_piece_collection
- <
- typename geometry::ring_type<GeometryOutput>::type,
- Strategies,
- DistanceStrategy,
- RobustPolicy
- > collection_type;
+ using collection_type = detail::buffer::buffered_piece_collection
+ <
+ typename geometry::ring_type<GeometryOutput>::type,
+ Strategies,
+ DistanceStrategy,
+ RobustPolicy
+ >;
collection_type collection(strategies, distance_strategy, robust_policy);
collection_type const& const_collection = collection;
- bool const areal = util::is_areal<GeometryInput>::value;
+ static constexpr bool areal = util::is_areal<GeometryInput>::value;
dispatch::buffer_inserter
<
@@ -961,7 +969,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
robust_policy, strategies);
collection.get_turns();
- if (BOOST_GEOMETRY_CONDITION(areal))
+ if BOOST_GEOMETRY_CONSTEXPR (areal)
{
collection.check_turn_in_original();
}
@@ -981,7 +989,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
// phase 1: turns (after enrichment/clustering)
visit_pieces_policy.apply(const_collection, 1);
- if (BOOST_GEOMETRY_CONDITION(areal))
+ if BOOST_GEOMETRY_CONSTEXPR (areal)
{
collection.deflate_check_turns();
}
@@ -993,8 +1001,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
// - the output is counter clockwise
// and avoid reversing twice
bool reverse = distance_strategy.negative() && areal;
- if (BOOST_GEOMETRY_CONDITION(
- geometry::point_order<GeometryOutput>::value == counterclockwise))
+ if BOOST_GEOMETRY_CONSTEXPR (geometry::point_order<GeometryOutput>::value == counterclockwise)
{
reverse = ! reverse;
}
@@ -1003,9 +1010,12 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
collection.reverse();
}
- if (BOOST_GEOMETRY_CONDITION(distance_strategy.negative() && areal))
+ if BOOST_GEOMETRY_CONSTEXPR (areal)
{
- collection.discard_nonintersecting_deflated_rings();
+ if (distance_strategy.negative())
+ {
+ collection.discard_nonintersecting_deflated_rings();
+ }
}
collection.template assign<GeometryOutput>(out);
diff --git a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
index 05d5c6fdac..e75532c3f3 100644
--- a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
@@ -158,7 +158,6 @@ struct buffer_turn_info
// or (for deflate) if there are not enough points to traverse it.
bool is_turn_traversable;
- bool close_to_offset;
bool is_linear_end_point;
bool within_original;
signed_size_type count_in_original; // increased by +1 for in ext.ring, -1 for int.ring
@@ -166,7 +165,6 @@ struct buffer_turn_info
inline buffer_turn_info()
: turn_index(0)
, is_turn_traversable(true)
- , close_to_offset(false)
, is_linear_end_point(false)
, within_original(false)
, count_in_original(0)
diff --git a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
index 65571c9211..8aa9493420 100644
--- a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
@@ -1,10 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2017-2023 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2016-2021.
-// Modifications copyright (c) 2016-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2016-2022.
+// Modifications copyright (c) 2016-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -59,6 +59,7 @@
#include <boost/geometry/algorithms/detail/sections/section_box_policies.hpp>
#include <boost/geometry/views/detail/closed_clockwise_view.hpp>
+#include <boost/geometry/util/for_each_with_index.hpp>
#include <boost/geometry/util/range.hpp>
@@ -289,77 +290,15 @@ struct buffered_piece_collection
, m_robust_policy(robust_policy)
{}
- inline bool is_following(buffer_turn_info_type const& turn,
- buffer_turn_operation_type const& op)
- {
- return turn.operations[0].seg_id.segment_index == op.seg_id.segment_index
- || turn.operations[1].seg_id.segment_index == op.seg_id.segment_index;
- }
-
- // Verify if turns which are classified as OK (outside or on border of
- // offsetted ring) do not traverse through other turns which are classified
- // as WITHIN (inside a piece). This can happen if turns are nearly colocated
- // and due to floating point precision just classified as within, while
- // they should not be within.
- // In those cases the turns are fine to travel through (and should),
- // but they are not made startable.
- template <typename Vector>
- inline void pretraverse(Vector const& indexed_operations)
- {
- // Verify if the turns which are OK don't skip segments
- typedef typename boost::range_value<Vector>::type indexed_type;
- buffer_turn_operation_type last_traversable_operation;
- buffer_turn_info_type last_traversable_turn;
- bool first = true;
- for (std::size_t i = 0; i < indexed_operations.size(); i++)
- {
- indexed_type const & itop = indexed_operations[i];
- buffer_turn_info_type const& turn = m_turns[itop.turn_index];
-
- if (turn.is_turn_traversable && ! first)
- {
- // Check previous and next turns. The first is handled
- BOOST_GEOMETRY_ASSERT(i > 0);
- indexed_type const& previous_itop = indexed_operations[i - 1];
- std::size_t const next_index = i + 1 < indexed_operations.size() ? i + 1 : 0;
- indexed_type const& next_itop = indexed_operations[next_index];
-
- buffer_turn_info_type& previous_turn = m_turns[previous_itop.turn_index];
- buffer_turn_info_type& next_turn = m_turns[next_itop.turn_index];
-
- if (previous_turn.close_to_offset
- && is_following(previous_turn, last_traversable_operation))
- {
- previous_turn.is_turn_traversable = true;
- }
- else if (next_turn.close_to_offset
- && is_following(next_turn, last_traversable_operation))
- {
- next_turn.is_turn_traversable = true;
- }
- }
-
- if (turn.is_turn_traversable)
- {
- first = false;
- last_traversable_operation = *itop.subject;
- last_traversable_turn = turn;
- }
- }
- }
-
inline void check_linear_endpoints(buffer_turn_info_type& turn) const
{
// TODO this is quadratic. But the #endpoints, expected, is low,
// and only applicable for linear features
// (in a multi linestring with many short lines, the #endpoints can be
// much higher)
- for (typename boost::range_iterator<std::vector<point_type> const>::type it
- = boost::begin(m_linear_end_points);
- it != boost::end(m_linear_end_points);
- ++it)
+ for (auto const& p : m_linear_end_points)
{
- if (detail::equals::equals_point_point(turn.point, *it, m_strategy))
+ if (detail::equals::equals_point_point(turn.point, p, m_strategy))
{
turn.is_linear_end_point = true;
}
@@ -383,20 +322,9 @@ struct buffered_piece_collection
enriched_map_buffer_include_policy());
// Sort turns over offsetted ring(s)
- for (typename mapped_vector_type::iterator mit
- = mapped_vector.begin();
- mit != mapped_vector.end();
- ++mit)
- {
- std::sort(mit->second.begin(), mit->second.end(), buffer_less());
- }
-
- for (typename mapped_vector_type::iterator mit
- = mapped_vector.begin();
- mit != mapped_vector.end();
- ++mit)
+ for (auto& pair : mapped_vector)
{
- pretraverse(mit->second);
+ std::sort(pair.second.begin(), pair.second.end(), buffer_less());
}
}
@@ -409,17 +337,14 @@ struct buffered_piece_collection
// Deflated rings may not travel to themselves, there should at least
// be three turns (which cannot be checked here - TODO: add to traverse)
- for (typename boost::range_iterator<turn_vector_type>::type it =
- boost::begin(m_turns); it != boost::end(m_turns); ++it)
+ for (auto& turn : m_turns)
{
- buffer_turn_info_type& turn = *it;
if (! turn.is_turn_traversable)
{
continue;
}
- for (int i = 0; i < 2; i++)
+ for (auto& op : turn.operations)
{
- buffer_turn_operation_type& op = turn.operations[i];
if (op.enriched.get_next_turn_index() == static_cast<signed_size_type>(turn.turn_index)
&& m_pieces[op.seg_id.piece_index].is_deflated)
{
@@ -452,10 +377,8 @@ struct buffered_piece_collection
bool const deflate = m_distance_strategy.negative();
- for (typename boost::range_iterator<turn_vector_type>::type it =
- boost::begin(m_turns); it != boost::end(m_turns); ++it)
+ for (auto& turn : m_turns)
{
- buffer_turn_info_type& turn = *it;
if (turn.is_turn_traversable)
{
if (deflate && turn.count_in_original <= 0)
@@ -475,21 +398,16 @@ struct buffered_piece_collection
inline void update_turn_administration()
{
- std::size_t index = 0;
- for (typename boost::range_iterator<turn_vector_type>::type it =
- boost::begin(m_turns); it != boost::end(m_turns); ++it, ++index)
+ for_each_with_index(m_turns, [this](std::size_t index, auto& turn)
{
- buffer_turn_info_type& turn = *it;
-
- // Update member used
turn.turn_index = index;
// Verify if a turn is a linear endpoint
if (! turn.is_linear_end_point)
{
- check_linear_endpoints(turn);
+ this->check_linear_endpoints(turn);
}
- }
+ });
}
// Calculate properties of piece borders which are not influenced
@@ -501,11 +419,8 @@ struct buffered_piece_collection
// - (if pieces are reversed)
inline void update_piece_administration()
{
- for (typename piece_vector_type::iterator it = boost::begin(m_pieces);
- it != boost::end(m_pieces);
- ++it)
+ for (auto& pc : m_pieces)
{
- piece& pc = *it;
piece_border_type& border = pc.m_piece_border;
buffered_ring<Ring> const& ring = offsetted_rings[pc.first_seg_id.multi_index];
@@ -561,8 +476,8 @@ struct buffered_piece_collection
turn_in_piece_visitor
<
typename geometry::cs_tag<point_type>::type,
- turn_vector_type, piece_vector_type, DistanceStrategy
- > visitor(m_turns, m_pieces, m_distance_strategy);
+ turn_vector_type, piece_vector_type, DistanceStrategy, Strategy
+ > visitor(m_turns, m_pieces, m_distance_strategy, m_strategy);
geometry::partition
<
@@ -694,7 +609,7 @@ struct buffered_piece_collection
return;
}
- if (! input_ring.empty())
+ if (! boost::empty(input_ring))
{
// Assign the ring to the original_ring collection
// For rescaling, it is recalculated. Without rescaling, it
@@ -705,8 +620,7 @@ struct buffered_piece_collection
using view_type = detail::closed_clockwise_view<InputRing const>;
view_type const view(input_ring);
- for (typename boost::range_iterator<view_type const>::type it =
- boost::begin(view); it != boost::end(view); ++it)
+ for (auto it = boost::begin(view); it != boost::end(view); ++it)
{
clockwise_ring.push_back(*it);
}
@@ -798,11 +712,10 @@ struct buffered_piece_collection
inline void sectionalize(piece const& pc, buffered_ring<Ring> const& ring)
{
- typedef geometry::detail::sectionalize::sectionalize_part
+ using sectionalizer = geometry::detail::sectionalize::sectionalize_part
<
- point_type,
std::integer_sequence<std::size_t, 0, 1> // x,y dimension
- > sectionalizer;
+ >;
// Create a ring-identifier. The source-index is the piece index
// The multi_index is as in this collection (the ring), but not used here
@@ -860,7 +773,7 @@ struct buffered_piece_collection
{
BOOST_GEOMETRY_ASSERT(boost::size(range) != 0u);
- typename Range::const_iterator it = boost::begin(range);
+ auto it = boost::begin(range);
// If it follows a non-join (so basically the same piece-type) point b1 should be added.
// There should be two intersections later and it should be discarded.
@@ -918,12 +831,16 @@ struct buffered_piece_collection
template <typename Range>
inline void add_side_piece(point_type const& original_point1,
point_type const& original_point2,
- Range const& range, bool first)
+ Range const& range, bool is_first, bool is_empty)
{
BOOST_GEOMETRY_ASSERT(boost::size(range) >= 2u);
- piece& pc = create_piece(strategy::buffer::buffered_segment, ! first);
- add_range_to_piece(pc, range, first);
+ auto const piece_type = is_empty
+ ? strategy::buffer::buffered_empty_side
+ : strategy::buffer::buffered_segment;
+
+ piece& pc = create_piece(piece_type, ! is_first);
+ add_range_to_piece(pc, range, is_first);
// Add the four points of the side, starting with the last point of the
// range, and reversing the order of the originals to keep it clockwise
@@ -993,18 +910,17 @@ struct buffered_piece_collection
// Those can never be traversed and should not be part of the output.
inline void discard_rings()
{
- for (typename boost::range_iterator<turn_vector_type const>::type it =
- boost::begin(m_turns); it != boost::end(m_turns); ++it)
+ for (auto const& turn : m_turns)
{
- if (it->is_turn_traversable)
+ if (turn.is_turn_traversable)
{
- offsetted_rings[it->operations[0].seg_id.multi_index].has_accepted_intersections = true;
- offsetted_rings[it->operations[1].seg_id.multi_index].has_accepted_intersections = true;
+ offsetted_rings[turn.operations[0].seg_id.multi_index].has_accepted_intersections = true;
+ offsetted_rings[turn.operations[1].seg_id.multi_index].has_accepted_intersections = true;
}
else
{
- offsetted_rings[it->operations[0].seg_id.multi_index].has_discarded_intersections = true;
- offsetted_rings[it->operations[1].seg_id.multi_index].has_discarded_intersections = true;
+ offsetted_rings[turn.operations[0].seg_id.multi_index].has_discarded_intersections = true;
+ offsetted_rings[turn.operations[1].seg_id.multi_index].has_discarded_intersections = true;
}
}
}
@@ -1017,12 +933,8 @@ struct buffered_piece_collection
// any of the robust original rings
// This can go quadratic if the input has many rings, and there
// are many untouched deflated rings around
- for (typename std::vector<original_ring>::const_iterator it
- = original_rings.begin();
- it != original_rings.end();
- ++it)
+ for (auto const& original : original_rings)
{
- original_ring const& original = *it;
if (original.m_ring.empty())
{
continue;
@@ -1064,12 +976,8 @@ struct buffered_piece_collection
// be discarded
inline void discard_nonintersecting_deflated_rings()
{
- for(typename buffered_ring_collection<buffered_ring<Ring> >::iterator it
- = boost::begin(offsetted_rings);
- it != boost::end(offsetted_rings);
- ++it)
+ for (auto& ring : offsetted_rings)
{
- buffered_ring<Ring>& ring = *it;
if (! ring.has_intersections()
&& boost::size(ring) > 0u
&& geometry::area(ring, m_strategy) < 0)
@@ -1084,10 +992,8 @@ struct buffered_piece_collection
inline void block_turns()
{
- for (typename boost::range_iterator<turn_vector_type>::type it =
- boost::begin(m_turns); it != boost::end(m_turns); ++it)
+ for (auto& turn : m_turns)
{
- buffer_turn_info_type& turn = *it;
if (! turn.is_turn_traversable)
{
// Discard this turn (don't set it to blocked to avoid colocated
@@ -1120,21 +1026,16 @@ struct buffered_piece_collection
inline void reverse()
{
- for(typename buffered_ring_collection<buffered_ring<Ring> >::iterator it = boost::begin(offsetted_rings);
- it != boost::end(offsetted_rings);
- ++it)
+ for (auto& ring : offsetted_rings)
{
- if (! it->has_intersections())
+ if (! ring.has_intersections())
{
- std::reverse(it->begin(), it->end());
+ std::reverse(ring.begin(), ring.end());
}
}
- for (typename boost::range_iterator<buffered_ring_collection<Ring> >::type
- it = boost::begin(traversed_rings);
- it != boost::end(traversed_rings);
- ++it)
+ for (auto& ring : traversed_rings)
{
- std::reverse(it->begin(), it->end());
+ std::reverse(ring.begin(), ring.end());
}
}
@@ -1156,37 +1057,30 @@ struct buffered_piece_collection
// Inner rings, for deflate, which do not have intersections, and
// which are outside originals, are skipped
// (other ones should be traversed)
- signed_size_type index = 0;
- for(typename buffered_ring_collection<buffered_ring<Ring> >::const_iterator it = boost::begin(offsetted_rings);
- it != boost::end(offsetted_rings);
- ++it, ++index)
- {
- if (! it->has_intersections()
- && ! it->is_untouched_outside_original)
+ for_each_with_index(offsetted_rings, [&](std::size_t index, auto const& ring)
{
- properties p = properties(*it, m_strategy);
- if (p.valid)
+ if (! ring.has_intersections()
+ && ! ring.is_untouched_outside_original)
{
- ring_identifier id(0, index, -1);
- selected[id] = p;
+ properties p = properties(ring, m_strategy);
+ if (p.valid)
+ {
+ ring_identifier id(0, index, -1);
+ selected[id] = p;
+ }
}
- }
- }
+ });
// Select all created rings
- index = 0;
- for (typename boost::range_iterator<buffered_ring_collection<Ring> const>::type
- it = boost::begin(traversed_rings);
- it != boost::end(traversed_rings);
- ++it, ++index)
- {
- properties p = properties(*it, m_strategy);
- if (p.valid)
+ for_each_with_index(traversed_rings, [&](std::size_t index, auto const& ring)
{
- ring_identifier id(2, index, -1);
- selected[id] = p;
- }
- }
+ properties p = properties(ring, m_strategy);
+ if (p.valid)
+ {
+ ring_identifier id(2, index, -1);
+ selected[id] = p;
+ }
+ });
detail::overlay::assign_parents<overlay_buffer>(offsetted_rings, traversed_rings,
selected, m_strategy);
diff --git a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
index 09fef75185..c5b0aedc75 100644
--- a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
+++ b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
@@ -194,7 +194,6 @@ class piece_turn_visitor
{
typedef typename boost::range_value<Rings const>::type ring_type;
typedef typename boost::range_value<Turns const>::type turn_type;
- typedef typename boost::range_iterator<ring_type const>::type iterator;
signed_size_type const piece1_first_index = piece1.first_seg_id.segment_index;
signed_size_type const piece2_first_index = piece2.first_seg_id.segment_index;
@@ -213,12 +212,12 @@ class piece_turn_visitor
// get geometry and iterators over these sections
ring_type const& ring1 = m_rings[piece1.first_seg_id.multi_index];
- iterator it1_first = boost::begin(ring1) + sec1_first_index;
- iterator it1_beyond = boost::begin(ring1) + sec1_last_index + 1;
+ auto it1_first = boost::begin(ring1) + sec1_first_index;
+ auto it1_beyond = boost::begin(ring1) + sec1_last_index + 1;
ring_type const& ring2 = m_rings[piece2.first_seg_id.multi_index];
- iterator it2_first = boost::begin(ring2) + sec2_first_index;
- iterator it2_beyond = boost::begin(ring2) + sec2_last_index + 1;
+ auto it2_first = boost::begin(ring2) + sec2_first_index;
+ auto it2_beyond = boost::begin(ring2) + sec2_last_index + 1;
// Set begin/end of monotonic ranges, in both x/y directions
signed_size_type index1 = sec1_first_index;
@@ -246,8 +245,8 @@ class piece_turn_visitor
the_model.operations[0].seg_id = piece1.first_seg_id;
the_model.operations[0].seg_id.segment_index = index1; // override
- iterator it1 = it1_first;
- for (iterator prev1 = it1++;
+ auto it1 = it1_first;
+ for (auto prev1 = it1++;
it1 != it1_beyond;
prev1 = it1++, the_model.operations[0].seg_id.segment_index++)
{
@@ -257,8 +256,8 @@ class piece_turn_visitor
unique_sub_range_from_piece<ring_type> unique_sub_range1(ring1, prev1, it1);
- iterator it2 = it2_first;
- for (iterator prev2 = it2++;
+ auto it2 = it2_first;
+ for (auto prev2 = it2++;
it2 != it2_beyond;
prev2 = it2++, the_model.operations[1].seg_id.segment_index++)
{
diff --git a/boost/geometry/algorithms/detail/buffer/implementation.hpp b/boost/geometry/algorithms/detail/buffer/implementation.hpp
new file mode 100644
index 0000000000..8b820e8f71
--- /dev/null
+++ b/boost/geometry/algorithms/detail/buffer/implementation.hpp
@@ -0,0 +1,214 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// This file was modified by Oracle on 2017-2022.
+// Modifications copyright (c) 2017-2022 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_IMPLEMENTATION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_IMPLEMENTATION_HPP
+
+#include <boost/range/value_type.hpp>
+
+#include <boost/geometry/algorithms/detail/buffer/buffer_box.hpp>
+#include <boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp>
+#include <boost/geometry/algorithms/detail/buffer/interface.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp> // for GC
+#include <boost/geometry/algorithms/envelope.hpp>
+#include <boost/geometry/algorithms/is_empty.hpp>
+#include <boost/geometry/algorithms/union.hpp> // for GC
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/geometries/box.hpp>
+#include <boost/geometry/strategies/buffer/cartesian.hpp>
+#include <boost/geometry/strategies/buffer/geographic.hpp>
+#include <boost/geometry/strategies/buffer/spherical.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/range.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename BoxIn, typename BoxOut>
+struct buffer_dc<BoxIn, BoxOut, box_tag, box_tag>
+{
+ template <typename Distance>
+ static inline void apply(BoxIn const& box_in, BoxOut& box_out,
+ Distance const& distance, Distance const& )
+ {
+ detail::buffer::buffer_box(box_in, distance, box_out);
+ }
+};
+
+
+template <typename Input, typename Output, typename TagIn>
+struct buffer_all<Input, Output, TagIn, multi_polygon_tag>
+{
+ template
+ <
+ typename DistanceStrategy,
+ typename SideStrategy,
+ typename JoinStrategy,
+ typename EndStrategy,
+ typename PointStrategy,
+ typename Strategies
+ >
+ static inline void apply(Input const& geometry_in,
+ Output& geometry_out,
+ DistanceStrategy const& distance_strategy,
+ SideStrategy const& side_strategy,
+ JoinStrategy const& join_strategy,
+ EndStrategy const& end_strategy,
+ PointStrategy const& point_strategy,
+ Strategies const& strategies)
+ {
+ typedef typename boost::range_value<Output>::type polygon_type;
+
+ typedef typename point_type<Input>::type point_type;
+ typedef typename rescale_policy_type
+ <
+ point_type,
+ typename geometry::cs_tag<point_type>::type
+ >::type rescale_policy_type;
+
+ if (geometry::is_empty(geometry_in))
+ {
+ // Then output geometry is kept empty as well
+ return;
+ }
+
+ model::box<point_type> box;
+ geometry::envelope(geometry_in, box);
+ geometry::buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy));
+
+ rescale_policy_type rescale_policy
+ = boost::geometry::get_rescale_policy<rescale_policy_type>(
+ box, strategies);
+
+ detail::buffer::buffer_inserter<polygon_type>(geometry_in,
+ range::back_inserter(geometry_out),
+ distance_strategy,
+ side_strategy,
+ join_strategy,
+ end_strategy,
+ point_strategy,
+ strategies,
+ rescale_policy);
+ }
+};
+
+
+template <typename Input, typename Output>
+struct buffer_all<Input, Output, geometry_collection_tag, multi_polygon_tag>
+{
+ template
+ <
+ typename DistanceStrategy,
+ typename SideStrategy,
+ typename JoinStrategy,
+ typename EndStrategy,
+ typename PointStrategy,
+ typename Strategies
+ >
+ static inline void apply(Input const& geometry_in,
+ Output& geometry_out,
+ DistanceStrategy const& distance_strategy,
+ SideStrategy const& side_strategy,
+ JoinStrategy const& join_strategy,
+ EndStrategy const& end_strategy,
+ PointStrategy const& point_strategy,
+ Strategies const& strategies)
+ {
+ // NOTE: The buffer normally calculates everything at once (by pieces) and traverses all
+ // of them to apply the union operation. Not even by merging elements. But that is
+ // complex and has led to issues as well. Here intermediate results are calculated
+ // with buffer and the results are merged afterwards.
+ // NOTE: This algorithm merges partial results iteratively.
+ // We could first gather all of the results and after that
+ // use some more optimal method like merge_elements().
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ Output buffer_result;
+ buffer_all
+ <
+ util::remove_cref_t<decltype(g)>, Output
+ >::apply(g, buffer_result, distance_strategy, side_strategy,
+ join_strategy, end_strategy, point_strategy, strategies);
+
+ if (! geometry::is_empty(buffer_result))
+ {
+ Output union_result;
+ geometry::union_(geometry_out, buffer_result, union_result, strategies);
+ geometry_out = std::move(union_result);
+ }
+
+ return true;
+ }, geometry_in);
+ }
+};
+
+template <typename Input, typename Output>
+struct buffer_all<Input, Output, geometry_collection_tag, geometry_collection_tag>
+{
+ template
+ <
+ typename DistanceStrategy,
+ typename SideStrategy,
+ typename JoinStrategy,
+ typename EndStrategy,
+ typename PointStrategy,
+ typename Strategies
+ >
+ static inline void apply(Input const& geometry_in,
+ Output& geometry_out,
+ DistanceStrategy const& distance_strategy,
+ SideStrategy const& side_strategy,
+ JoinStrategy const& join_strategy,
+ EndStrategy const& end_strategy,
+ PointStrategy const& point_strategy,
+ Strategies const& strategies)
+ {
+ // NOTE: We could also allow returning GC containing only polygons.
+ // We'd have to wrap them in model::multi_polygon and then
+ // iteratively emplace_back() into the GC.
+ using mpo_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Output>::type,
+ util::is_multi_polygon
+ >::type;
+ mpo_t result;
+ buffer_all
+ <
+ Input, mpo_t
+ >::apply(geometry_in, result, distance_strategy, side_strategy,
+ join_strategy, end_strategy, point_strategy, strategies);
+ range::emplace_back(geometry_out, std::move(result));
+ }
+};
+
+template <typename Input, typename Output, typename TagIn>
+struct buffer_all<Input, Output, TagIn, geometry_collection_tag>
+ : buffer_all<Input, Output, geometry_collection_tag, geometry_collection_tag>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_IMPLEMENTATION_HPP
diff --git a/boost/geometry/algorithms/detail/buffer/interface.hpp b/boost/geometry/algorithms/detail/buffer/interface.hpp
new file mode 100644
index 0000000000..d19abd6efe
--- /dev/null
+++ b/boost/geometry/algorithms/detail/buffer/interface.hpp
@@ -0,0 +1,279 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// This file was modified by Oracle on 2017-2022.
+// Modifications copyright (c) 2017-2022 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_INTERFACE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_INTERFACE_HPP
+
+#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/core/visit.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/strategies/buffer/services.hpp>
+#include <boost/geometry/util/type_traits_std.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Input,
+ typename Output,
+ typename TagIn = typename tag<Input>::type,
+ typename TagOut = typename tag<Output>::type
+>
+struct buffer_dc : not_implemented<TagIn, TagOut>
+{};
+
+template
+<
+ typename Input,
+ typename Output,
+ typename TagIn = typename tag<Input>::type,
+ typename TagOut = typename tag<Output>::type
+>
+struct buffer_all : not_implemented<TagIn, TagOut>
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+namespace resolve_dynamic
+{
+
+template
+<
+ typename Input,
+ typename TagIn = typename geometry::tag<Input>::type
+>
+struct buffer_dc
+{
+ template <typename Output, typename Distance>
+ static inline void apply(Input const& geometry_in,
+ Output& geometry_out,
+ Distance const& distance,
+ Distance const& chord_length)
+ {
+ dispatch::buffer_dc<Input, Output>::apply(geometry_in, geometry_out, distance, chord_length);
+ }
+};
+
+template <typename Input>
+struct buffer_dc<Input, dynamic_geometry_tag>
+{
+ template <typename Output, typename Distance>
+ static inline void apply(Input const& geometry_in,
+ Output& geometry_out,
+ Distance const& distance,
+ Distance const& chord_length)
+ {
+ traits::visit<Input>::apply([&](auto const& g)
+ {
+ dispatch::buffer_dc
+ <
+ util::remove_cref_t<decltype(g)>, Output
+ >::apply(g, geometry_out, distance, chord_length);
+ }, geometry_in);
+ }
+};
+
+
+template
+<
+ typename Input,
+ typename TagIn = typename geometry::tag<Input>::type
+>
+struct buffer_all
+{
+ template
+ <
+ typename Output,
+ typename DistanceStrategy,
+ typename SideStrategy,
+ typename JoinStrategy,
+ typename EndStrategy,
+ typename PointStrategy
+ >
+ static inline void apply(Input const& geometry_in,
+ Output& geometry_out,
+ DistanceStrategy const& distance_strategy,
+ SideStrategy const& side_strategy,
+ JoinStrategy const& join_strategy,
+ EndStrategy const& end_strategy,
+ PointStrategy const& point_strategy)
+ {
+ typename strategies::buffer::services::default_strategy
+ <
+ Input
+ >::type strategies;
+
+ dispatch::buffer_all
+ <
+ Input, Output
+ >::apply(geometry_in, geometry_out, distance_strategy, side_strategy,
+ join_strategy, end_strategy, point_strategy, strategies);
+ }
+};
+
+template <typename Input>
+struct buffer_all<Input, dynamic_geometry_tag>
+{
+ template
+ <
+ typename Output,
+ typename DistanceStrategy,
+ typename SideStrategy,
+ typename JoinStrategy,
+ typename EndStrategy,
+ typename PointStrategy
+ >
+ static inline void apply(Input const& geometry_in,
+ Output& geometry_out,
+ DistanceStrategy const& distance_strategy,
+ SideStrategy const& side_strategy,
+ JoinStrategy const& join_strategy,
+ EndStrategy const& end_strategy,
+ PointStrategy const& point_strategy)
+ {
+ traits::visit<Input>::apply([&](auto const& g)
+ {
+ buffer_all
+ <
+ util::remove_cref_t<decltype(g)>
+ >::apply(g, geometry_out, distance_strategy, side_strategy,
+ join_strategy, end_strategy, point_strategy);
+ }, geometry_in);
+ }
+};
+
+} // namespace resolve_dynamic
+
+
+/*!
+\brief \brief_calc{buffer}
+\ingroup buffer
+\details \details_calc{buffer, \det_buffer}.
+\tparam Input \tparam_geometry
+\tparam Output \tparam_geometry
+\tparam Distance \tparam_numeric
+\param geometry_in \param_geometry
+\param geometry_out \param_geometry
+\param distance The distance to be used for the buffer
+\param chord_length (optional) The length of the chord's in the generated arcs around points or bends
+
+\qbk{[include reference/algorithms/buffer.qbk]}
+ */
+template <typename Input, typename Output, typename Distance>
+inline void buffer(Input const& geometry_in, Output& geometry_out,
+ Distance const& distance, Distance const& chord_length = -1)
+{
+ concepts::check<Input const>();
+ concepts::check<Output>();
+
+ resolve_dynamic::buffer_dc<Input>::apply(geometry_in, geometry_out, distance, chord_length);
+}
+
+/*!
+\brief \brief_calc{buffer}
+\ingroup buffer
+\details \details_calc{return_buffer, \det_buffer}. \details_return{buffer}.
+\tparam Input \tparam_geometry
+\tparam Output \tparam_geometry
+\tparam Distance \tparam_numeric
+\param geometry \param_geometry
+\param distance The distance to be used for the buffer
+\param chord_length (optional) The length of the chord's in the generated arcs
+ around points or bends (RESERVED, NOT YET USED)
+\return \return_calc{buffer}
+ */
+template <typename Output, typename Input, typename Distance>
+inline Output return_buffer(Input const& geometry, Distance const& distance,
+ Distance const& chord_length = -1)
+{
+ concepts::check<Input const>();
+ concepts::check<Output>();
+
+ Output geometry_out;
+
+ resolve_dynamic::buffer_dc<Input>::apply(geometry, geometry_out, distance, chord_length);
+
+ return geometry_out;
+}
+
+/*!
+\brief \brief_calc{buffer}
+\ingroup buffer
+\details \details_calc{buffer, \det_buffer}.
+\tparam GeometryIn \tparam_geometry
+\tparam GeometryOut \tparam_geometry{GeometryOut}
+\tparam DistanceStrategy A strategy defining distance (or radius)
+\tparam SideStrategy A strategy defining creation along sides
+\tparam JoinStrategy A strategy defining creation around convex corners
+\tparam EndStrategy A strategy defining creation at linestring ends
+\tparam PointStrategy A strategy defining creation around points
+\param geometry_in \param_geometry
+\param geometry_out output geometry, e.g. multi polygon,
+ will contain a buffered version of the input geometry
+\param distance_strategy The distance strategy to be used
+\param side_strategy The side strategy to be used
+\param join_strategy The join strategy to be used
+\param end_strategy The end strategy to be used
+\param point_strategy The point strategy to be used
+
+\qbk{distinguish,with strategies}
+\qbk{[include reference/algorithms/buffer_with_strategies.qbk]}
+ */
+template
+<
+ typename GeometryIn,
+ typename GeometryOut,
+ typename DistanceStrategy,
+ typename SideStrategy,
+ typename JoinStrategy,
+ typename EndStrategy,
+ typename PointStrategy
+>
+inline void buffer(GeometryIn const& geometry_in,
+ GeometryOut& geometry_out,
+ DistanceStrategy const& distance_strategy,
+ SideStrategy const& side_strategy,
+ JoinStrategy const& join_strategy,
+ EndStrategy const& end_strategy,
+ PointStrategy const& point_strategy)
+{
+ concepts::check<GeometryIn const>();
+ concepts::check<GeometryOut>();
+
+ geometry::clear(geometry_out);
+
+ resolve_dynamic::buffer_all
+ <
+ GeometryIn, GeometryOut
+ >::apply(geometry_in, geometry_out, distance_strategy, side_strategy,
+ join_strategy, end_strategy, point_strategy);
+}
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_INTERFACE_HPP
diff --git a/boost/geometry/algorithms/detail/buffer/piece_border.hpp b/boost/geometry/algorithms/detail/buffer/piece_border.hpp
index ecd03d9c82..d773d32c36 100644
--- a/boost/geometry/algorithms/detail/buffer/piece_border.hpp
+++ b/boost/geometry/algorithms/detail/buffer/piece_border.hpp
@@ -1,9 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2020 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2020-2021 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2020.
-// Modifications copyright (c) 2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2022.
+// Modifications copyright (c) 2020-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -14,7 +15,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_PIECE_BORDER_HPP
-#include <boost/array.hpp>
+#include <array>
+
#include <boost/core/addressof.hpp>
#include <boost/geometry/core/assert.hpp>
@@ -24,7 +26,6 @@
#include <boost/geometry/algorithms/comparable_distance.hpp>
#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/algorithms/expand.hpp>
-#include <boost/geometry/algorithms/detail/buffer/buffer_box.hpp>
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
#include <boost/geometry/strategies/cartesian/turn_in_ring_winding.hpp>
@@ -116,7 +117,7 @@ struct piece_border
// Points from the original (one or two, depending on piece shape)
// Note, if there are 2 points, they are REVERSED w.r.t. the original
// Therefore here we can walk in its order.
- boost::array<Point, 2> m_originals;
+ std::array<Point, 2> m_originals;
std::size_t m_original_size;
geometry::model::box<Point> m_envelope;
@@ -262,16 +263,21 @@ struct piece_border
if (m_original_size == 1)
{
// One point. Walk from last offsetted to point, and from point to first offsetted
- continue_processing = step(point, offsetted_back, m_originals[0], tir, por_from_offsetted, state)
- && step(point, m_originals[0], offsetted_front, tir, por_to_offsetted, state);
+ continue_processing = step(point, offsetted_back, m_originals[0],
+ tir, por_from_offsetted, state)
+ && step(point, m_originals[0], offsetted_front,
+ tir, por_to_offsetted, state);
}
else if (m_original_size == 2)
{
// Two original points. Walk from last offsetted point to first original point,
// then along original, then from second oginal to first offsetted point
- continue_processing = step(point, offsetted_back, m_originals[0], tir, por_from_offsetted, state)
- && step(point, m_originals[0], m_originals[1], tir, por_original, state)
- && step(point, m_originals[1], offsetted_front, tir, por_to_offsetted, state);
+ continue_processing = step(point, offsetted_back, m_originals[0],
+ tir, por_from_offsetted, state)
+ && step(point, m_originals[0], m_originals[1],
+ tir, por_original, state)
+ && step(point, m_originals[1], offsetted_front,
+ tir, por_to_offsetted, state);
}
if (continue_processing)
@@ -302,8 +308,15 @@ private :
: target;
}
- template <typename TurnPoint, typename Iterator, typename Strategy, typename State>
- bool walk_offsetted(TurnPoint const& point, Iterator begin, Iterator end, Strategy const & strategy, State& state) const
+ template
+ <
+ typename TurnPoint, typename Iterator,
+ typename TiRStrategy,
+ typename State
+ >
+ bool walk_offsetted(TurnPoint const& point, Iterator begin, Iterator end,
+ TiRStrategy const & strategy,
+ State& state) const
{
Iterator it = begin;
Iterator beyond = end;
@@ -327,7 +340,7 @@ private :
for (Iterator previous = it++ ; it != beyond ; ++previous, ++it )
{
if (! step(point, *previous, *it, strategy,
- geometry::strategy::buffer::place_on_ring_offsetted, state))
+ geometry::strategy::buffer::place_on_ring_offsetted, state))
{
return false;
}
@@ -336,27 +349,11 @@ private :
}
template <typename TurnPoint, typename TiRStrategy, typename State>
- bool step(TurnPoint const& point, Point const& p1, Point const& p2, TiRStrategy const & strategy,
+ bool step(TurnPoint const& point, Point const& p1, Point const& p2,
+ TiRStrategy const& strategy,
geometry::strategy::buffer::place_on_ring_type place_on_ring, State& state) const
{
- // A step between original/offsetted ring is always convex
- // (unless the join strategy generates points left of it -
- // future: convexity might be added to the buffer-join-strategy)
- // Therefore, if the state count > 0, it means the point is left of it,
- // and because it is convex, we can stop
-
- typedef typename geometry::coordinate_type<Point>::type coordinate_type;
- typedef geometry::detail::distance_measure<coordinate_type> dm_type;
- dm_type const dm = geometry::detail::get_distance_measure(point, p1, p2);
- if (m_is_convex && dm.measure > 0)
- {
- // The point is left of this segment of a convex piece
- state.m_count = 0;
- return false;
- }
- // Call strategy, and if it is on the border, return false
- // to stop further processing.
- return strategy.apply(point, p1, p2, dm, place_on_ring, state);
+ return strategy.apply(point, p1, p2, place_on_ring, m_is_convex, state);
}
template <typename It, typename Box, typename Strategy>
diff --git a/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp b/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp
index b1930dc0c4..daa59b618b 100644
--- a/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp
+++ b/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp
@@ -2,8 +2,9 @@
// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2016-2020.
-// Modifications copyright (c) 2016-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2016-2023.
+// Modifications copyright (c) 2016-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
// Use, modification and distribution is subject to the Boost Software License,
@@ -18,6 +19,7 @@
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/interface.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/buffer.hpp>
@@ -32,7 +34,7 @@ namespace detail { namespace buffer
{
-template <typename Strategy>
+template <typename Strategy>
struct original_get_box
{
explicit original_get_box(Strategy const& strategy)
@@ -190,20 +192,11 @@ inline int point_in_original(Point const& point, Original const& original,
return strategy.result(state);
}
- typedef typename Original::sections_type sections_type;
- typedef typename boost::range_iterator<sections_type const>::type iterator_type;
- typedef typename boost::range_value<sections_type const>::type section_type;
- typedef typename geometry::coordinate_type<Point>::type coordinate_type;
-
- coordinate_type const point_x = geometry::get<0>(point);
+ auto const point_x = geometry::get<0>(point);
// Walk through all monotonic sections of this original
- for (iterator_type it = boost::begin(original.m_sections);
- it != boost::end(original.m_sections);
- ++it)
+ for (auto const& section : original.m_sections)
{
- section_type const& section = *it;
-
if (! section.duplicate
&& section.begin_index < section.end_index
&& point_x >= geometry::get<min_corner, 0>(section.bounding_box)
diff --git a/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp b/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp
index f51bd29007..bb7019c089 100644
--- a/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp
+++ b/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp
@@ -3,8 +3,8 @@
// Copyright (c) 2012-2020 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2016, 2018.
-// Modifications copyright (c) 2016-2018 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2016-2022.
+// Modifications copyright (c) 2016-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -21,6 +21,7 @@
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
+#include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
#include <boost/geometry/geometries/box.hpp>
@@ -38,7 +39,8 @@ template
typename CsTag,
typename Turns,
typename Pieces,
- typename DistanceStrategy
+ typename DistanceStrategy,
+ typename UmbrellaStrategy
>
class turn_in_piece_visitor
@@ -46,6 +48,7 @@ class turn_in_piece_visitor
Turns& m_turns; // because partition is currently operating on const input only
Pieces const& m_pieces; // to check for piece-type
DistanceStrategy const& m_distance_strategy; // to check if point is on original or one_sided
+ UmbrellaStrategy const& m_umbrella_strategy;
template <typename Operation, typename Piece>
inline bool skip(Operation const& op, Piece const& piece) const
@@ -94,10 +97,12 @@ class turn_in_piece_visitor
public:
inline turn_in_piece_visitor(Turns& turns, Pieces const& pieces,
- DistanceStrategy const& distance_strategy)
+ DistanceStrategy const& distance_strategy,
+ UmbrellaStrategy const& umbrella_strategy)
: m_turns(turns)
, m_pieces(pieces)
, m_distance_strategy(distance_strategy)
+ , m_umbrella_strategy(umbrella_strategy)
{}
template <typename Turn, typename Piece>
@@ -127,20 +132,24 @@ public:
template <typename Turn, typename Piece, typename Border>
inline bool apply(Turn const& turn, Piece const& piece, Border const& border)
{
- if (! geometry::covered_by(turn.point, border.m_envelope))
+ if (! geometry::covered_by(turn.point, border.m_envelope, m_umbrella_strategy))
{
// Easy check: if turn is not in the (expanded) envelope
return true;
}
+ if (piece.type == geometry::strategy::buffer::buffered_empty_side)
+ {
+ return false;
+ }
+
if (piece.type == geometry::strategy::buffer::buffered_point)
{
// Optimization for a buffer around points: if distance from center
// is not between min/max radius, it is either inside or outside,
// and more expensive checks are not necessary.
- typedef typename Border::radius_type radius_type;
-
- radius_type const d = geometry::comparable_distance(piece.m_center, turn.point);
+ auto const d = geometry::comparable_distance(piece.m_center, turn.point,
+ m_umbrella_strategy);
if (d < border.m_min_comparable_radius)
{
@@ -155,38 +164,20 @@ public:
}
// Check if buffer is one-sided (at this point), because then a point
- // on the original is not considered as within.
+ // on the original border is not considered as within.
bool const one_sided = has_zero_distance_at(turn.point);
typename Border::state_type state;
- if (! border.point_on_piece(turn.point, one_sided, turn.is_linear_end_point, state))
+ if (! border.point_on_piece(turn.point, one_sided,
+ turn.is_linear_end_point, state))
{
return true;
}
- if (state.code() == 1)
+ if (state.is_inside() && ! state.is_on_boundary())
{
- // It is WITHIN a piece, or on the piece border, but not
- // on the offsetted part of it.
-
- // TODO - at further removing rescaling, this threshold can be
- // adapted, or ideally, go.
- // This threshold is minimized to the point where fragile
- // unit tests of hard cases start to fail (5 in multi_polygon)
- // But it is acknowlegded that such a threshold depends on the
- // scale of the input.
- if (state.m_min_distance > 1.0e-5 || ! state.m_close_to_offset)
- {
- Turn& mutable_turn = m_turns[turn.turn_index];
- mutable_turn.is_turn_traversable = false;
-
- // Keep track of the information if this turn was close
- // to an offset (without threshold). Because if it was,
- // it might have been classified incorrectly and in the
- // pretraversal step, it can in hindsight be classified
- // as "outside".
- mutable_turn.close_to_offset = state.m_close_to_offset;
- }
+ Turn& mutable_turn = m_turns[turn.turn_index];
+ mutable_turn.is_turn_traversable = false;
}
return true;
diff --git a/boost/geometry/algorithms/detail/calculate_point_order.hpp b/boost/geometry/algorithms/detail/calculate_point_order.hpp
index a9362b3613..191f71f3d8 100644
--- a/boost/geometry/algorithms/detail/calculate_point_order.hpp
+++ b/boost/geometry/algorithms/detail/calculate_point_order.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry
-// Copyright (c) 2019-2021, Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2019-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
@@ -36,7 +37,7 @@ struct clean_point
, m_is_azi_valid(false), m_is_azi_diff_valid(false)
{}
- typename boost::iterators::iterator_reference<Iter>::type ref() const
+ decltype(auto) ref() const
{
return *m_iter;
}
@@ -108,8 +109,6 @@ struct calculate_point_order_by_azimuth
typedef typename boost::range_iterator<Ring const>::type iter_t;
typedef typename Strategy::template result_type<Ring>::type calc_t;
typedef clean_point<iter_t, calc_t> clean_point_t;
- typedef std::vector<clean_point_t> cleaned_container_t;
- typedef typename cleaned_container_t::iterator cleaned_iter_t;
calc_t const zero = 0;
calc_t const pi = math::pi<calc_t>();
@@ -121,21 +120,21 @@ struct calculate_point_order_by_azimuth
}
// non-duplicated, non-spike points
- cleaned_container_t cleaned;
+ std::vector<clean_point_t> cleaned;
cleaned.reserve(count);
for (iter_t it = boost::begin(ring); it != boost::end(ring); ++it)
{
// Add point
cleaned.push_back(clean_point_t(it));
-
+
while (cleaned.size() >= 3)
{
- cleaned_iter_t it0 = cleaned.end() - 3;
- cleaned_iter_t it1 = cleaned.end() - 2;
- cleaned_iter_t it2 = cleaned.end() - 1;
+ auto it0 = cleaned.end() - 3;
+ auto it1 = cleaned.end() - 2;
+ auto it2 = cleaned.end() - 1;
- calc_t diff;
+ calc_t diff;
if (get_or_calculate_azimuths_difference(*it0, *it1, *it2, diff, strategy)
&& ! math::equals(math::abs(diff), pi))
{
@@ -148,7 +147,7 @@ struct calculate_point_order_by_azimuth
// TODO: angles have to be invalidated only if spike is detected
// for duplicates it'd be ok to leave them
it0->set_azimuth_invalid();
- it0->set_azimuth_difference_invalid();
+ it0->set_azimuth_difference_invalid();
it2->set_azimuth_difference_invalid();
cleaned.erase(it1);
}
@@ -156,8 +155,8 @@ struct calculate_point_order_by_azimuth
}
// filter-out duplicates and spikes at the front and back of cleaned
- cleaned_iter_t cleaned_b = cleaned.begin();
- cleaned_iter_t cleaned_e = cleaned.end();
+ auto cleaned_b = cleaned.begin();
+ auto cleaned_e = cleaned.end();
std::size_t cleaned_count = cleaned.size();
bool found = false;
do
@@ -165,10 +164,10 @@ struct calculate_point_order_by_azimuth
found = false;
while(cleaned_count >= 3)
{
- cleaned_iter_t it0 = cleaned_e - 2;
- cleaned_iter_t it1 = cleaned_e - 1;
- cleaned_iter_t it2 = cleaned_b;
- cleaned_iter_t it3 = cleaned_b + 1;
+ auto it0 = cleaned_e - 2;
+ auto it1 = cleaned_e - 1;
+ auto it2 = cleaned_b;
+ auto it3 = cleaned_b + 1;
calc_t diff = 0;
if (! get_or_calculate_azimuths_difference(*it0, *it1, *it2, diff, strategy)
@@ -212,10 +211,10 @@ struct calculate_point_order_by_azimuth
// calculate the sum of external angles
calc_t angles_sum = zero;
- for (cleaned_iter_t it = cleaned_b; it != cleaned_e; ++it)
+ for (auto it = cleaned_b; it != cleaned_e; ++it)
{
- cleaned_iter_t it0 = (it == cleaned_b ? cleaned_e - 1 : it - 1);
- cleaned_iter_t it2 = (it == cleaned_e - 1 ? cleaned_b : it + 1);
+ auto it0 = (it == cleaned_b ? cleaned_e - 1 : it - 1);
+ auto it2 = (it == cleaned_e - 1 ? cleaned_b : it + 1);
calc_t diff = 0;
get_or_calculate_azimuths_difference(*it0, *it, *it2, diff, strategy);
@@ -269,7 +268,7 @@ private:
razi = p0.reverse_azimuth();
return true;
}
-
+
if (strategy.apply(p0.ref(), p1.ref(), azi, razi))
{
p0.set_azimuths(azi, razi);
@@ -336,7 +335,7 @@ namespace detail
template <typename Ring, typename Strategy>
inline geometry::order_selector calculate_point_order(Ring const& ring, Strategy const& strategy)
{
- concepts::check<Ring>();
+ concepts::check<Ring const>();
return dispatch::calculate_point_order<Strategy>::apply(ring, strategy);
}
@@ -349,7 +348,7 @@ inline geometry::order_selector calculate_point_order(Ring const& ring)
typename geometry::cs_tag<Ring>::type
>::type strategy_type;
- concepts::check<Ring>();
+ concepts::check<Ring const>();
return dispatch::calculate_point_order<strategy_type>::apply(ring, strategy_type());
}
diff --git a/boost/geometry/algorithms/detail/calculate_sum.hpp b/boost/geometry/algorithms/detail/calculate_sum.hpp
index 4af986fb62..4296d88e61 100644
--- a/boost/geometry/algorithms/detail/calculate_sum.hpp
+++ b/boost/geometry/algorithms/detail/calculate_sum.hpp
@@ -37,8 +37,7 @@ class calculate_polygon_sum
static inline ReturnType sum_interior_rings(Rings const& rings, Strategy const& strategy)
{
ReturnType sum = ReturnType(0);
- for (typename boost::range_iterator<Rings const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
sum += Policy::apply(*it, strategy);
}
diff --git a/boost/geometry/algorithms/detail/centroid/translating_transformer.hpp b/boost/geometry/algorithms/detail/centroid/translating_transformer.hpp
index 56a7e3ec91..042891e6e2 100644
--- a/boost/geometry/algorithms/detail/centroid/translating_transformer.hpp
+++ b/boost/geometry/algorithms/detail/centroid/translating_transformer.hpp
@@ -75,7 +75,7 @@ struct translating_transformer<Geometry, areal_tag, cartesian_tag>
{
typedef typename geometry::point_type<Geometry>::type point_type;
typedef point_type result_type;
-
+
explicit translating_transformer(Geometry const& geom)
: m_origin(NULL)
{
diff --git a/boost/geometry/algorithms/detail/check_iterator_range.hpp b/boost/geometry/algorithms/detail/check_iterator_range.hpp
deleted file mode 100644
index 9bd1d7ae27..0000000000
--- a/boost/geometry/algorithms/detail/check_iterator_range.hpp
+++ /dev/null
@@ -1,71 +0,0 @@
-// Boost.Geometry (aka GGL, Generic Geometry Library)
-
-// Copyright (c) 2014, Oracle and/or its affiliates.
-
-// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
-
-// Licensed under the Boost Software License version 1.0.
-// http://www.boost.org/users/license.html
-
-#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CHECK_ITERATOR_RANGE_HPP
-#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CHECK_ITERATOR_RANGE_HPP
-
-#include <boost/core/ignore_unused.hpp>
-
-
-namespace boost { namespace geometry
-{
-
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail
-{
-
-// Check whether (each element of) an iterator range satisfies a given
-// predicate.
-// The predicate must be implemented as having a static apply unary
-// method that returns a bool.
-// By default an empty range is accepted
-template <typename Predicate, bool AllowEmptyRange = true>
-struct check_iterator_range
-{
- template <typename InputIterator>
- static inline bool apply(InputIterator first, InputIterator beyond)
- {
- for (InputIterator it = first; it != beyond; ++it)
- {
- if (! Predicate::apply(*it))
- {
- return false;
- }
- }
- return AllowEmptyRange || first != beyond;
- }
-
-
- // version where we can pass a predicate object
- template <typename InputIterator>
- static inline bool apply(InputIterator first,
- InputIterator beyond,
- Predicate const& predicate)
- {
- // in case predicate's apply method is static, MSVC will
- // complain that predicate is not used
- boost::ignore_unused(predicate);
-
- for (InputIterator it = first; it != beyond; ++it)
- {
- if (! predicate.apply(*it))
- {
- return false;
- }
- }
- return AllowEmptyRange || first != beyond;
- }
-};
-
-} // namespace detail
-#endif // DOXYGEN_NO_DETAIL
-
-}} // namespace boost::geometry
-
-#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CHECK_ITERATOR_RANGE_HPP
diff --git a/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp b/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp
index 4ac5ac6976..c5d331aaf3 100644
--- a/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp
+++ b/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp
@@ -92,7 +92,7 @@ public:
typename RangeIterator,
typename Strategy,
typename Distance
- >
+ >
static inline RangeIterator apply(Geometry const& geometry,
RangeIterator first,
RangeIterator last,
@@ -111,7 +111,7 @@ public:
typename Geometry,
typename RangeIterator,
typename Strategy
- >
+ >
static inline RangeIterator apply(Geometry const& geometry,
RangeIterator first,
RangeIterator last,
diff --git a/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp b/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp
index 8ca0b3a7b9..ed2efd6fce 100644
--- a/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp
+++ b/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp
@@ -189,7 +189,7 @@ private:
it_min1 = it_back;
it_min2 = first;
}
- }
+ }
public:
typedef typename std::pair<iterator_type, iterator_type> return_type;
diff --git a/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp b/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp
index 52b2495d12..be1729a86f 100644
--- a/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp
+++ b/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp
@@ -150,7 +150,7 @@ public:
apply(rtree_first, rtree_last, queries_first, queries_last,
strategy, rtree_min, qit_min, dist_min);
- return std::make_pair(rtree_min, qit_min);
+ return std::make_pair(rtree_min, qit_min);
}
diff --git a/boost/geometry/algorithms/detail/closest_points/implementation.hpp b/boost/geometry/algorithms/detail/closest_points/implementation.hpp
new file mode 100644
index 0000000000..4accfa21b1
--- /dev/null
+++ b/boost/geometry/algorithms/detail/closest_points/implementation.hpp
@@ -0,0 +1,28 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_IMPLEMENTATION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_IMPLEMENTATION_HPP
+
+#include <boost/geometry/algorithms/detail/distance/implementation.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/point_to_geometry.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/multipoint_to_geometry.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/linear_to_linear.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/linear_or_areal_to_areal.hpp>
+//#include <boost/geometry/algorithms/detail/closest_points/linear_to_box.hpp>
+//#include <boost/geometry/algorithms/detail/closest_points/geometry_to_segment_or_box.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/segment_to_segment.hpp>
+//#include <boost/geometry/algorithms/detail/closest_points/segment_to_box.hpp>
+//#include <boost/geometry/algorithms/detail/closest_points/box_to_box.hpp>
+
+#include <boost/geometry/strategies/closest_points/cartesian.hpp>
+#include <boost/geometry/strategies/closest_points/geographic.hpp>
+#include <boost/geometry/strategies/closest_points/spherical.hpp>
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_IMPLEMENTATION_HPP
diff --git a/boost/geometry/algorithms/detail/closest_points/interface.hpp b/boost/geometry/algorithms/detail/closest_points/interface.hpp
new file mode 100644
index 0000000000..622c47ba7f
--- /dev/null
+++ b/boost/geometry/algorithms/detail/closest_points/interface.hpp
@@ -0,0 +1,225 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_INTERFACE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_INTERFACE_HPP
+
+#include <boost/concept_check.hpp>
+
+#include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
+
+#include <boost/geometry/algorithms/dispatch/closest_points.hpp>
+
+#include <boost/geometry/algorithms/detail/distance/interface.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/strategies/detail.hpp>
+#include <boost/geometry/strategies/closest_points/services.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+// If reversal is needed, perform it
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Tag1,
+ typename Tag2
+>
+struct closest_points
+<
+ Geometry1, Geometry2,
+ Tag1, Tag2, true
+>
+ : closest_points<Geometry2, Geometry1, Tag2, Tag1, false>
+{
+ template <typename Segment, typename Strategy>
+ static inline void apply(Geometry1 const& g1, Geometry2 const& g2,
+ Segment& shortest_seg, Strategy const& strategy)
+ {
+ closest_points
+ <
+ Geometry2, Geometry1, Tag2, Tag1, false
+ >::apply(g2, g1, shortest_seg, strategy);
+
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+namespace resolve_strategy
+{
+
+template<typename Strategy>
+struct closest_points
+{
+ template <typename Geometry1, typename Geometry2, typename Segment>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Segment& shortest_seg,
+ Strategy const& strategy)
+ {
+ dispatch::closest_points
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, shortest_seg, strategy);
+ }
+};
+
+template <>
+struct closest_points<default_strategy>
+{
+ template <typename Geometry1, typename Geometry2, typename Segment>
+ static inline void
+ apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Segment& shortest_seg,
+ default_strategy)
+ {
+ using strategy_type = typename strategies::closest_points::services::default_strategy
+ <
+ Geometry1, Geometry2
+ >::type;
+
+ dispatch::closest_points
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, shortest_seg, strategy_type());
+ }
+};
+
+} // namespace resolve_strategy
+
+
+namespace resolve_variant
+{
+
+
+template <typename Geometry1, typename Geometry2>
+struct closest_points
+{
+ template <typename Segment, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Segment& shortest_seg,
+ Strategy const& strategy)
+ {
+ resolve_strategy::closest_points
+ <
+ Strategy
+ >::apply(geometry1, geometry2, shortest_seg, strategy);
+ }
+};
+
+//TODO: Add support for DG/GC
+
+} // namespace resolve_variant
+
+
+/*!
+\brief Calculate the closest points between two geometries \brief_strategy
+\ingroup closest_points
+\details
+\details The free function closest_points calculates the distance between two geometries \brief_strategy. \details_strategy_reasons
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Segment Any type fulfilling a Segment Concept
+\tparam Strategy \tparam_strategy{Closest Points}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param shortest_seg Output segment containing the closest points
+\param strategy \param_strategy{closest_points}
+\note The strategy can be a point-point strategy. In case of distance point-line/point-polygon
+ it may also be a point-segment strategy.
+
+\qbk{distinguish,with strategy}
+
+\qbk{
+
+[heading Example]
+[closest_points_strategy]
+[closest_points_strategy_output]
+
+[heading See also]
+\* [link geometry.reference.algorithms.distance distance]
+}
+*/
+
+template <typename Geometry1, typename Geometry2, typename Segment, typename Strategy>
+inline void closest_points(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Segment& shortest_seg,
+ Strategy const& strategy)
+{
+ concepts::check<Geometry1 const>();
+ concepts::check<Geometry2 const>();
+
+ detail::throw_on_empty_input(geometry1);
+ detail::throw_on_empty_input(geometry2);
+
+ resolve_variant::closest_points
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, shortest_seg, strategy);
+}
+
+
+/*!
+\brief Compute the closest points between two geometries.
+\ingroup closest_points
+\details The free function closest_points calculates the closest points between two geometries. \details_default_strategy
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Segment Any type fulfilling a Segment Concept
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param shortest_seg Output segment containing the closest points
+
+\qbk{
+
+[heading Example]
+[closest_points]
+[closest_points_output]
+
+[heading See also]
+\* [link geometry.reference.algorithms.distance distance]
+}
+*/
+
+template <typename Geometry1, typename Geometry2, typename Segment>
+inline void closest_points(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Segment& shortest_seg)
+{
+ closest_points(geometry1, geometry2, shortest_seg, default_strategy());
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_INTERFACE_HPP
diff --git a/boost/geometry/algorithms/detail/closest_points/linear_or_areal_to_areal.hpp b/boost/geometry/algorithms/detail/closest_points/linear_or_areal_to_areal.hpp
new file mode 100644
index 0000000000..6d643e1aca
--- /dev/null
+++ b/boost/geometry/algorithms/detail/closest_points/linear_or_areal_to_areal.hpp
@@ -0,0 +1,261 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_LINEAR_OR_AREAL_TO_AREAL_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_LINEAR_OR_AREAL_TO_AREAL_HPP
+
+#include <boost/geometry/algorithms/detail/closest_points/linear_to_linear.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
+
+#include <boost/geometry/algorithms/intersection.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/geometries/geometries.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace closest_points
+{
+
+struct linear_to_areal
+{
+ template <typename Linear, typename Areal, typename Segment, typename Strategies>
+ static inline void apply(Linear const& linear,
+ Areal const& areal,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ using most_precise_type = typename select_coordinate_type<Linear, Areal>::type;
+
+ using point_type = typename std::conditional
+ <
+ std::is_same<typename coordinate_type<Linear>::type, most_precise_type>::value,
+ typename point_type<Linear>::type,
+ typename point_type<Areal>::type
+ >::type;
+
+ using linestring_type = geometry::model::linestring<point_type>;
+
+ /* TODO: currently intersection does not support some cases of tupled input
+ * such as linestring - multipolygon
+ * this could be implemented directly with dynamic geometries
+ using polygon_type = geometry::model::polygon<point_type>;
+ std::tuple
+ <
+ geometry::model::multi_point<point_type>,
+ geometry::model::multi_linestring<linestring_type>,
+ geometry::model::multi_polygon<polygon_type>
+ > tp;
+ bool intersect_tp = geometry::intersection(linear, areal, tp, strategies);
+ */
+
+ geometry::model::multi_point<point_type> mp_out;
+ geometry::intersection(linear, areal, mp_out, strategies);
+
+ if (! boost::empty(mp_out))
+ {
+ set_segment_from_points::apply(*boost::begin(mp_out),
+ *boost::begin(mp_out),
+ shortest_seg);
+ return;
+ }
+
+ // if there are no intersection points then check if the linear geometry
+ // (or part of it) is inside the areal and return any point of this part
+ geometry::model::multi_linestring<linestring_type> ln_out;
+ geometry::intersection(linear, areal, ln_out, strategies);
+
+ if (! boost::empty(ln_out))
+ {
+ set_segment_from_points::apply(*boost::begin(*boost::begin(ln_out)),
+ *boost::begin(*boost::begin(ln_out)),
+ shortest_seg);
+ return;
+ }
+
+ linear_to_linear::apply(linear, areal, shortest_seg, strategies, false);
+ }
+};
+
+struct areal_to_linear
+{
+ template <typename Linear, typename Areal, typename Segment, typename Strategies>
+ static inline void apply(Areal const& areal,
+ Linear const& linear,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ linear_to_areal::apply(linear, areal, shortest_seg, strategies);
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ }
+};
+
+struct segment_to_areal
+{
+ template <typename Segment, typename Areal, typename OutSegment, typename Strategies>
+ static inline void apply(Segment const& segment,
+ Areal const& areal,
+ OutSegment& shortest_seg,
+ Strategies const& strategies,
+ bool = false)
+ {
+ using linestring_type = geometry::model::linestring<typename point_type<Segment>::type>;
+ linestring_type linestring;
+ convert(segment, linestring);
+ linear_to_areal::apply(linestring, areal, shortest_seg, strategies);
+ }
+};
+
+struct areal_to_segment
+{
+ template <typename Areal, typename Segment, typename OutSegment, typename Strategies>
+ static inline void apply(Areal const& areal,
+ Segment const& segment,
+ OutSegment& shortest_seg,
+ Strategies const& strategies,
+ bool = false)
+ {
+ segment_to_areal::apply(segment, areal, shortest_seg, strategies);
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ }
+};
+
+struct areal_to_areal
+{
+ template <typename Areal1, typename Areal2, typename Segment, typename Strategies>
+ static inline void apply(Areal1 const& areal1,
+ Areal2 const& areal2,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ using most_precise_type = typename select_coordinate_type<Areal1, Areal2>::type;
+
+ using point_type = typename std::conditional
+ <
+ std::is_same<typename coordinate_type<Areal1>::type, most_precise_type>::value,
+ typename point_type<Areal1>::type,
+ typename point_type<Areal2>::type
+ >::type;
+
+ using linestring_type = geometry::model::linestring<point_type>;
+ using polygon_type = geometry::model::polygon<point_type>;
+
+ /* TODO: currently intersection does not support tupled input
+ * this should be implemented directly with dynamic geometries
+ */
+
+ geometry::model::multi_point<point_type> mp_out;
+ geometry::intersection(areal1, areal2, mp_out, strategies);
+
+ if (! boost::empty(mp_out))
+ {
+ set_segment_from_points::apply(*boost::begin(mp_out),
+ *boost::begin(mp_out),
+ shortest_seg);
+ return;
+ }
+
+ // if there are no intersection points then the linear geometry (or part of it)
+ // is inside the areal; return any point of this part
+ geometry::model::multi_linestring<linestring_type> ln_out;
+ geometry::intersection(areal1, areal2, ln_out, strategies);
+
+ if (! boost::empty(ln_out))
+ {
+ set_segment_from_points::apply(*boost::begin(*boost::begin(ln_out)),
+ *boost::begin(*boost::begin(ln_out)),
+ shortest_seg);
+ return;
+ }
+
+ geometry::model::multi_polygon<polygon_type> pl_out;
+ geometry::intersection(areal1, areal2, pl_out, strategies);
+
+ if (! boost::empty(pl_out))
+ {
+ set_segment_from_points::apply(
+ *boost::begin(boost::geometry::exterior_ring(*boost::begin(pl_out))),
+ *boost::begin(boost::geometry::exterior_ring(*boost::begin(pl_out))),
+ shortest_seg);
+ return;
+ }
+
+ linear_to_linear::apply(areal1, areal2, shortest_seg, strategies, false);
+ }
+};
+
+
+}} // namespace detail::closest_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Linear, typename Areal>
+struct closest_points
+ <
+ Linear, Areal,
+ linear_tag, areal_tag,
+ false
+ >
+ : detail::closest_points::linear_to_areal
+{};
+
+template <typename Areal, typename Linear>
+struct closest_points
+ <
+ Areal, Linear,
+ areal_tag, linear_tag,
+ false
+ >
+ : detail::closest_points::areal_to_linear
+{};
+
+template <typename Segment, typename Areal>
+struct closest_points
+ <
+ Segment, Areal,
+ segment_tag, areal_tag,
+ false
+ >
+ : detail::closest_points::segment_to_areal
+{};
+
+template <typename Areal, typename Segment>
+struct closest_points
+ <
+ Areal, Segment,
+ areal_tag, segment_tag,
+ false
+ >
+ : detail::closest_points::areal_to_segment
+{};
+
+template <typename Areal1, typename Areal2>
+struct closest_points
+ <
+ Areal1, Areal2,
+ areal_tag, areal_tag,
+ false
+ >
+ : detail::closest_points::areal_to_areal
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_LINEAR_OR_AREAL_TO_AREAL_HPP
diff --git a/boost/geometry/algorithms/detail/closest_points/linear_to_linear.hpp b/boost/geometry/algorithms/detail/closest_points/linear_to_linear.hpp
new file mode 100644
index 0000000000..d2927a6d39
--- /dev/null
+++ b/boost/geometry/algorithms/detail/closest_points/linear_to_linear.hpp
@@ -0,0 +1,155 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_LINEAR_TO_LINEAR_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_LINEAR_TO_LINEAR_HPP
+
+#include <boost/geometry/algorithms/detail/closest_points/range_to_geometry_rtree.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
+
+#include <boost/geometry/algorithms/num_points.hpp>
+#include <boost/geometry/algorithms/num_segments.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/iterators/point_iterator.hpp>
+#include <boost/geometry/iterators/segment_iterator.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace closest_points
+{
+
+
+struct linear_to_linear
+{
+ template <typename Linear1, typename Linear2, typename Segment, typename Strategies>
+ static inline void apply(Linear1 const& linear1,
+ Linear2 const& linear2,
+ Segment& shortest_seg,
+ Strategies const& strategies,
+ bool = false)
+ {
+ if (geometry::num_points(linear1) == 1)
+ {
+ dispatch::closest_points
+ <
+ typename point_type<Linear1>::type,
+ Linear2
+ >::apply(*points_begin(linear1), linear2, shortest_seg, strategies);
+ return;
+ }
+
+ if (geometry::num_points(linear2) == 1)
+ {
+ dispatch::closest_points
+ <
+ typename point_type<Linear2>::type,
+ Linear1
+ >::apply(*points_begin(linear2), linear1, shortest_seg, strategies);
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ return;
+ }
+
+ if (geometry::num_segments(linear1) < geometry::num_segments(linear2))
+ {
+ point_or_segment_range_to_geometry_rtree::apply(
+ geometry::segments_begin(linear2),
+ geometry::segments_end(linear2),
+ linear1,
+ shortest_seg,
+ strategies);
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ return;
+ }
+
+ point_or_segment_range_to_geometry_rtree::apply(
+ geometry::segments_begin(linear1),
+ geometry::segments_end(linear1),
+ linear2,
+ shortest_seg,
+ strategies);
+ }
+};
+
+struct segment_to_linear
+{
+ template <typename Segment, typename Linear, typename OutSegment, typename Strategies>
+ static inline void apply(Segment const& segment,
+ Linear const& linear,
+ OutSegment& shortest_seg,
+ Strategies const& strategies,
+ bool = false)
+ {
+ using linestring_type = geometry::model::linestring
+ <typename point_type<Segment>::type>;
+ linestring_type linestring;
+ convert(segment, linestring);
+ linear_to_linear::apply(linestring, linear, shortest_seg, strategies);
+ }
+};
+
+struct linear_to_segment
+{
+ template <typename Linear, typename Segment, typename OutSegment, typename Strategies>
+ static inline void apply(Linear const& linear,
+ Segment const& segment,
+ OutSegment& shortest_seg,
+ Strategies const& strategies,
+ bool = false)
+ {
+ segment_to_linear::apply(segment, linear, shortest_seg, strategies);
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ }
+};
+
+}} // namespace detail::closest_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Linear1, typename Linear2>
+struct closest_points
+ <
+ Linear1, Linear2,
+ linear_tag, linear_tag,
+ false
+ > : detail::closest_points::linear_to_linear
+{};
+
+template <typename Segment, typename Linear>
+struct closest_points
+ <
+ Segment, Linear,
+ segment_tag, linear_tag,
+ false
+ > : detail::closest_points::segment_to_linear
+{};
+
+template <typename Linear, typename Segment>
+struct closest_points
+ <
+ Linear, Segment,
+ linear_tag, segment_tag,
+ false
+ > : detail::closest_points::linear_to_segment
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_LINEAR_TO_LINEAR_HPP
diff --git a/boost/geometry/algorithms/detail/closest_points/multipoint_to_geometry.hpp b/boost/geometry/algorithms/detail/closest_points/multipoint_to_geometry.hpp
new file mode 100644
index 0000000000..f59c85a9b5
--- /dev/null
+++ b/boost/geometry/algorithms/detail/closest_points/multipoint_to_geometry.hpp
@@ -0,0 +1,325 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_MULTIPOINT_TO_GEOMETRY_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_MULTIPOINT_TO_GEOMETRY_HPP
+
+#include <iterator>
+
+#include <boost/geometry/algorithms/covered_by.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/range_to_geometry_rtree.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
+#include <boost/geometry/algorithms/dispatch/closest_points.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/geometries/linestring.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace closest_points
+{
+
+
+struct multipoint_to_multipoint
+{
+ template
+ <
+ typename MultiPoint1,
+ typename MultiPoint2,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(MultiPoint1 const& multipoint1,
+ MultiPoint2 const& multipoint2,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ if (boost::size(multipoint1) < boost::size(multipoint2))
+ {
+ point_or_segment_range_to_geometry_rtree::apply(
+ boost::begin(multipoint2),
+ boost::end(multipoint2),
+ multipoint1,
+ shortest_seg,
+ strategies);
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ return;
+ }
+ point_or_segment_range_to_geometry_rtree::apply(
+ boost::begin(multipoint1),
+ boost::end(multipoint1),
+ multipoint2,
+ shortest_seg,
+ strategies);
+ }
+};
+
+struct multipoint_to_linear
+{
+ template
+ <
+ typename MultiPoint,
+ typename Linear,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(MultiPoint const& multipoint,
+ Linear const& linear,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ point_or_segment_range_to_geometry_rtree::apply(
+ boost::begin(multipoint),
+ boost::end(multipoint),
+ linear,
+ shortest_seg,
+ strategies);
+ }
+};
+
+struct linear_to_multipoint
+{
+ template
+ <
+ typename Linear,
+ typename MultiPoint,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(Linear const& linear,
+ MultiPoint const& multipoint,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ multipoint_to_linear::apply(multipoint, linear, shortest_seg, strategies);
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ }
+};
+
+struct segment_to_multipoint
+{
+ template
+ <
+ typename Segment,
+ typename MultiPoint,
+ typename OutSegment,
+ typename Strategies
+ >
+ static inline void apply(Segment const& segment,
+ MultiPoint const& multipoint,
+ OutSegment& shortest_seg,
+ Strategies const& strategies)
+ {
+ using linestring_type = geometry::model::linestring
+ <
+ typename point_type<Segment>::type
+ >;
+ linestring_type linestring;
+ convert(segment, linestring);
+ multipoint_to_linear::apply(multipoint, linestring, shortest_seg, strategies);
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ }
+};
+
+struct multipoint_to_segment
+{
+ template
+ <
+ typename MultiPoint,
+ typename Segment,
+ typename OutSegment,
+ typename Strategies
+ >
+ static inline void apply(MultiPoint const& multipoint,
+ Segment const& segment,
+ OutSegment& shortest_seg,
+ Strategies const& strategies)
+ {
+ using linestring_type = geometry::model::linestring
+ <
+ typename point_type<Segment>::type
+ >;
+ linestring_type linestring;
+ convert(segment, linestring);
+ multipoint_to_linear::apply(multipoint, linestring, shortest_seg,
+ strategies);
+ }
+};
+
+
+struct multipoint_to_areal
+{
+
+private:
+
+ template <typename Areal, typename Strategies>
+ struct covered_by_areal
+ {
+ covered_by_areal(Areal const& areal, Strategies const& strategy)
+ : m_areal(areal), m_strategy(strategy)
+ {}
+
+ template <typename Point>
+ inline bool operator()(Point const& point) const
+ {
+ return geometry::covered_by(point, m_areal, m_strategy);
+ }
+
+ Areal const& m_areal;
+ Strategies const& m_strategy;
+ };
+
+public:
+
+ template
+ <
+ typename MultiPoint,
+ typename Areal,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(MultiPoint const& multipoint,
+ Areal const& areal,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ covered_by_areal<Areal, Strategies> predicate(areal, strategies);
+
+ auto it = std::find_if(
+ boost::begin(multipoint),
+ boost::end(multipoint),
+ predicate);
+
+ if (it != boost::end(multipoint))
+ {
+ return set_segment_from_points::apply(*it, *it, shortest_seg);
+
+ }
+
+ point_or_segment_range_to_geometry_rtree::apply(
+ boost::begin(multipoint),
+ boost::end(multipoint),
+ areal,
+ shortest_seg,
+ strategies);
+ }
+};
+
+struct areal_to_multipoint
+{
+ template
+ <
+ typename Areal,
+ typename MultiPoint,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(Areal const& areal,
+ MultiPoint const& multipoint,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ multipoint_to_areal::apply(multipoint, areal, shortest_seg, strategies);
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ }
+};
+
+}} // namespace detail::closest_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename MultiPoint1, typename MultiPoint2>
+struct closest_points
+ <
+ MultiPoint1, MultiPoint2,
+ multi_point_tag, multi_point_tag,
+ false
+ > : detail::closest_points::multipoint_to_multipoint
+{};
+
+
+template <typename MultiPoint, typename Linear>
+struct closest_points
+ <
+ MultiPoint, Linear,
+ multi_point_tag, linear_tag,
+ false
+ > : detail::closest_points::multipoint_to_linear
+{};
+
+
+template <typename Linear, typename MultiPoint>
+struct closest_points
+ <
+ Linear, MultiPoint,
+ linear_tag, multi_point_tag,
+ false
+ > : detail::closest_points::linear_to_multipoint
+{};
+
+
+template <typename MultiPoint, typename Segment>
+struct closest_points
+ <
+ MultiPoint, Segment,
+ multi_point_tag, segment_tag,
+ false
+ > : detail::closest_points::multipoint_to_segment
+{};
+
+
+template <typename Segment, typename MultiPoint>
+struct closest_points
+ <
+ Segment, MultiPoint,
+ segment_tag, multi_point_tag,
+ false
+ > : detail::closest_points::segment_to_multipoint
+{};
+
+
+template <typename MultiPoint, typename Areal>
+struct closest_points
+ <
+ MultiPoint, Areal,
+ multi_point_tag, areal_tag,
+ false
+ > : detail::closest_points::multipoint_to_areal
+{};
+
+
+template <typename Areal, typename MultiPoint>
+struct closest_points
+ <
+ Areal, MultiPoint,
+ areal_tag, multi_point_tag,
+ false
+ > : detail::closest_points::areal_to_multipoint
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_MULTIPOINT_TO_GEOMETRY_HPP
diff --git a/boost/geometry/algorithms/detail/closest_points/point_to_geometry.hpp b/boost/geometry/algorithms/detail/closest_points/point_to_geometry.hpp
new file mode 100644
index 0000000000..5771858518
--- /dev/null
+++ b/boost/geometry/algorithms/detail/closest_points/point_to_geometry.hpp
@@ -0,0 +1,456 @@
+// Boost.Geometry
+
+// Copyright (c) 2021-2023, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_POINT_TO_GEOMETRY_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_POINT_TO_GEOMETRY_HPP
+
+#include <iterator>
+#include <type_traits>
+
+#include <boost/core/ignore_unused.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/size.hpp>
+#include <boost/range/value_type.hpp>
+
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp>
+#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
+#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
+#include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>
+#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
+#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
+#include <boost/geometry/algorithms/dispatch/closest_points.hpp>
+#include <boost/geometry/algorithms/dispatch/distance.hpp>
+
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/relate/services.hpp>
+#include <boost/geometry/strategies/tags.hpp>
+
+#include <boost/geometry/util/math.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace closest_points
+{
+
+struct point_to_point
+{
+ template <typename P1, typename P2, typename Segment, typename Strategies>
+ static inline void apply(P1 const& p1, P2 const& p2,
+ Segment& shortest_seg, Strategies const&)
+ {
+ set_segment_from_points::apply(p1, p2, shortest_seg);
+ }
+};
+
+struct point_to_segment
+{
+ template <typename Point, typename Segment, typename OutputSegment, typename Strategies>
+ static inline void apply(Point const& point, Segment const& segment,
+ OutputSegment& shortest_seg, Strategies const& strategies)
+ {
+ typename point_type<Segment>::type p[2];
+ geometry::detail::assign_point_from_index<0>(segment, p[0]);
+ geometry::detail::assign_point_from_index<1>(segment, p[1]);
+
+ boost::ignore_unused(strategies);
+
+ auto closest_point = strategies.closest_points(point, segment)
+ .apply(point, p[0], p[1]);
+
+ set_segment_from_points::apply(point, closest_point, shortest_seg);
+ }
+};
+
+/*
+struct point_to_box
+{
+ template<typename Point, typename Box, typename Strategies>
+static inline auto apply(Point const& point, Box const& box,
+ Strategies const& strategies)
+ {
+ boost::ignore_unused(strategies);
+ return strategies.closest_points(point, box).apply(point, box);
+ }
+};
+*/
+
+template <closure_selector Closure>
+class point_to_range
+{
+public:
+
+ template <typename Point, typename Range, typename Segment, typename Strategies>
+ static inline void apply(Point const& point, Range const& range,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ using point_to_point_range = detail::closest_feature::point_to_point_range
+ <
+ Point, Range, Closure
+ >;
+
+ if (boost::size(range) == 0)
+ {
+ set_segment_from_points::apply(point, point, shortest_seg);
+ return;
+ }
+
+ closest_points::creturn_t<Point, Range, Strategies> cd_min;
+
+ auto comparable_distance = strategy::distance::services::get_comparable
+ <
+ decltype(strategies.distance(point, range))
+ >::apply(strategies.distance(point, range));
+
+ auto closest_segment = point_to_point_range::apply(point,
+ boost::begin(range),
+ boost::end(range),
+ comparable_distance,
+ cd_min);
+
+ auto closest_point = strategies.closest_points(point, range)
+ .apply(point, *closest_segment.first, *closest_segment.second);
+
+ set_segment_from_points::apply(point, closest_point, shortest_seg);
+ }
+};
+
+
+template<closure_selector Closure>
+struct point_to_ring
+{
+ template <typename Point, typename Ring, typename Segment, typename Strategies>
+ static inline auto apply(Point const& point,
+ Ring const& ring,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ if (within::within_point_geometry(point, ring, strategies))
+ {
+ set_segment_from_points::apply(point, point, shortest_seg);
+ }
+ else
+ {
+ point_to_range
+ <
+ closure<Ring>::value
+ >::apply(point, ring, shortest_seg, strategies);
+ }
+
+ }
+};
+
+
+template <closure_selector Closure>
+class point_to_polygon
+{
+ template <typename Polygon>
+ struct distance_to_interior_rings
+ {
+ template
+ <
+ typename Point,
+ typename InteriorRingIterator,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(Point const& point,
+ InteriorRingIterator first,
+ InteriorRingIterator last,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ using per_ring = point_to_range<Closure>;
+
+ for (InteriorRingIterator it = first; it != last; ++it)
+ {
+ if (within::within_point_geometry(point, *it, strategies))
+ {
+ // the point is inside a polygon hole, so its distance
+ // to the polygon is its distance to the polygon's
+ // hole boundary
+ per_ring::apply(point, *it, shortest_seg, strategies);
+ return;
+ }
+ }
+ set_segment_from_points::apply(point, point, shortest_seg);
+ }
+
+ template
+ <
+ typename Point,
+ typename InteriorRings,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(Point const& point, InteriorRings const& interior_rings,
+ Segment& shortest_seg, Strategies const& strategies)
+ {
+ apply(point,
+ boost::begin(interior_rings),
+ boost::end(interior_rings),
+ shortest_seg,
+ strategies);
+ }
+ };
+
+
+public:
+ template
+ <
+ typename Point,
+ typename Polygon,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(Point const& point,
+ Polygon const& polygon,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ using per_ring = point_to_range<Closure>;
+
+ if (! within::covered_by_point_geometry(point, exterior_ring(polygon),
+ strategies))
+ {
+ // the point is outside the exterior ring, so its distance
+ // to the polygon is its distance to the polygon's exterior ring
+ per_ring::apply(point, exterior_ring(polygon), shortest_seg, strategies);
+ return;
+ }
+
+ // Check interior rings
+ distance_to_interior_rings<Polygon>::apply(point,
+ interior_rings(polygon),
+ shortest_seg,
+ strategies);
+ }
+};
+
+
+template
+<
+ typename MultiGeometry,
+ bool CheckCoveredBy = std::is_same
+ <
+ typename tag<MultiGeometry>::type, multi_polygon_tag
+ >::value
+>
+class point_to_multigeometry
+{
+private:
+ using geometry_to_range = detail::closest_feature::geometry_to_range;
+
+public:
+
+ template
+ <
+ typename Point,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(Point const& point,
+ MultiGeometry const& multigeometry,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ using selector_type = distance::iterator_selector<MultiGeometry const>;
+
+ closest_points::creturn_t<Point, MultiGeometry, Strategies> cd;
+
+ auto comparable_distance = strategy::distance::services::get_comparable
+ <
+ decltype(strategies.distance(point, multigeometry))
+ >::apply(strategies.distance(point, multigeometry));
+
+ typename selector_type::iterator_type it_min
+ = geometry_to_range::apply(point,
+ selector_type::begin(multigeometry),
+ selector_type::end(multigeometry),
+ comparable_distance,
+ cd);
+
+ dispatch::closest_points
+ <
+ Point,
+ typename std::iterator_traits
+ <
+ typename selector_type::iterator_type
+ >::value_type
+ >::apply(point, *it_min, shortest_seg, strategies);
+ }
+};
+
+
+// this is called only for multipolygons, hence the change in the
+// template parameter name MultiGeometry to MultiPolygon
+template <typename MultiPolygon>
+struct point_to_multigeometry<MultiPolygon, true>
+{
+ template
+ <
+ typename Point,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(Point const& point,
+ MultiPolygon const& multipolygon,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ if (within::covered_by_point_geometry(point, multipolygon, strategies))
+ {
+ set_segment_from_points::apply(point, point, shortest_seg);
+ return;
+ }
+
+ return point_to_multigeometry
+ <
+ MultiPolygon, false
+ >::apply(point, multipolygon, shortest_seg, strategies);
+ }
+};
+
+
+}} // namespace detail::closest_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename P1, typename P2>
+struct closest_points
+ <
+ P1, P2, point_tag, point_tag, false
+ > : detail::closest_points::point_to_point
+{};
+
+
+template <typename Point, typename Linestring>
+struct closest_points
+ <
+ Point, Linestring, point_tag, linestring_tag, false
+ > : detail::closest_points::point_to_range<closed>
+{};
+
+
+template <typename Point, typename Ring>
+struct closest_points
+ <
+ Point, Ring, point_tag, ring_tag, false
+ > : detail::closest_points::point_to_ring
+ <
+ closure<Ring>::value
+ >
+{};
+
+
+template <typename Point, typename Polygon>
+struct closest_points
+ <
+ Point, Polygon, point_tag, polygon_tag, false
+ > : detail::closest_points::point_to_polygon
+ <
+ closure<Polygon>::value
+ >
+{};
+
+
+template <typename Point, typename Segment>
+struct closest_points
+ <
+ Point, Segment, point_tag, segment_tag, false
+ > : detail::closest_points::point_to_segment
+{};
+
+/*
+template <typename Point, typename Box>
+struct closest_points
+ <
+ Point, Box, point_tag, box_tag,
+ strategy_tag_distance_point_box, false
+ > : detail::closest_points::point_to_box<Point, Box>
+{};
+*/
+
+template<typename Point, typename MultiPoint>
+struct closest_points
+ <
+ Point, MultiPoint, point_tag, multi_point_tag, false
+ > : detail::closest_points::point_to_multigeometry<MultiPoint>
+{};
+
+
+template<typename Point, typename MultiLinestring>
+struct closest_points
+ <
+ Point, MultiLinestring, point_tag, multi_linestring_tag, false
+ > : detail::closest_points::point_to_multigeometry<MultiLinestring>
+{};
+
+
+template<typename Point, typename MultiPolygon>
+struct closest_points
+ <
+ Point, MultiPolygon, point_tag, multi_polygon_tag, false
+ > : detail::closest_points::point_to_multigeometry<MultiPolygon>
+{};
+
+
+template <typename Point, typename Linear>
+struct closest_points
+ <
+ Point, Linear, point_tag, linear_tag, false
+ > : closest_points
+ <
+ Point, Linear,
+ point_tag, typename tag<Linear>::type, false
+ >
+{};
+
+
+template <typename Point, typename Areal>
+struct closest_points
+ <
+ Point, Areal, point_tag, areal_tag, false
+ > : closest_points
+ <
+ Point, Areal,
+ point_tag, typename tag<Areal>::type, false
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_POINT_TO_GEOMETRY_HPP
diff --git a/boost/geometry/algorithms/detail/closest_points/range_to_geometry_rtree.hpp b/boost/geometry/algorithms/detail/closest_points/range_to_geometry_rtree.hpp
new file mode 100644
index 0000000000..1bb44b53cd
--- /dev/null
+++ b/boost/geometry/algorithms/detail/closest_points/range_to_geometry_rtree.hpp
@@ -0,0 +1,110 @@
+// Boost.Geometry
+
+// Copyright (c) 2021-2023, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_RANGE_TO_GEOMETRY_RTREE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_RANGE_TO_GEOMETRY_RTREE_HPP
+
+#include <iterator>
+#include <utility>
+
+#include <boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
+#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
+#include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>
+#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
+#include <boost/geometry/algorithms/dispatch/closest_points.hpp>
+
+#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/iterators/detail/has_one_element.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace closest_points
+{
+
+class point_or_segment_range_to_geometry_rtree
+{
+public:
+
+ template
+ <
+ typename PointOrSegmentIterator,
+ typename Geometry,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(PointOrSegmentIterator first,
+ PointOrSegmentIterator last,
+ Geometry const& geometry,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ typedef typename std::iterator_traits
+ <
+ PointOrSegmentIterator
+ >::value_type point_or_segment_type;
+
+ typedef distance::iterator_selector<Geometry const> selector_type;
+
+ typedef detail::closest_feature::range_to_range_rtree range_to_range;
+
+ BOOST_GEOMETRY_ASSERT( first != last );
+
+ //TODO: Is this special case needed?
+ //if ( detail::has_one_element(first, last) )
+ //{
+ // dispatch::closest_points
+ // <
+ // point_or_segment_type, Geometry
+ // >::apply(*first, geometry, shortest_seg, strategies);
+ //}
+
+ closest_points::creturn_t<point_or_segment_type, Geometry, Strategies> cd;
+
+ std::pair
+ <
+ point_or_segment_type,
+ typename selector_type::iterator_type
+ > closest_features
+ = range_to_range::apply(first,
+ last,
+ selector_type::begin(geometry),
+ selector_type::end(geometry),
+ strategies,
+ cd);
+ dispatch::closest_points
+ <
+ point_or_segment_type,
+ typename std::iterator_traits
+ <
+ typename selector_type::iterator_type
+ >::value_type
+ >::apply(closest_features.first,
+ *closest_features.second,
+ shortest_seg,
+ strategies);
+ }
+};
+
+
+}} // namespace detail::closest_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_RANGE_TO_GEOMETRY_RTREE_HPP
diff --git a/boost/geometry/algorithms/detail/closest_points/segment_to_segment.hpp b/boost/geometry/algorithms/detail/closest_points/segment_to_segment.hpp
new file mode 100644
index 0000000000..15d28cd690
--- /dev/null
+++ b/boost/geometry/algorithms/detail/closest_points/segment_to_segment.hpp
@@ -0,0 +1,145 @@
+// Boost.Geometry
+
+// Copyright (c) 2021-2023, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_SEGMENT_TO_SEGMENT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_SEGMENT_TO_SEGMENT_HPP
+
+#include <algorithm>
+#include <iterator>
+
+#include <boost/core/addressof.hpp>
+
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
+#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
+#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
+#include <boost/geometry/algorithms/dispatch/closest_points.hpp>
+#include <boost/geometry/algorithms/dispatch/distance.hpp>
+#include <boost/geometry/algorithms/intersects.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/tags.hpp>
+
+#include <boost/geometry/util/condition.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace closest_points
+{
+
+
+
+// compute segment-segment closest-points
+class segment_to_segment
+{
+public:
+
+ template <typename Segment1, typename Segment2, typename OutputSegment, typename Strategies>
+ static inline void apply(Segment1 const& segment1, Segment2 const& segment2,
+ OutputSegment& shortest_seg,
+ Strategies const& strategies)
+ {
+ using intersection_return_type = segment_intersection_points
+ <
+ typename point_type<Segment1>::type
+ >;
+
+ using intersection_policy = policies::relate::segments_intersection_points
+ <
+ intersection_return_type
+ >;
+
+ detail::segment_as_subrange<Segment1> sub_range1(segment1);
+ detail::segment_as_subrange<Segment2> sub_range2(segment2);
+ auto is = strategies.relate().apply(sub_range1, sub_range2,
+ intersection_policy());
+ if (is.count > 0)
+ {
+ set_segment_from_points::apply(is.intersections[0],
+ is.intersections[0],
+ shortest_seg);
+ return;
+ }
+
+ typename point_type<Segment1>::type p[2];
+ detail::assign_point_from_index<0>(segment1, p[0]);
+ detail::assign_point_from_index<1>(segment1, p[1]);
+
+ typename point_type<Segment2>::type q[2];
+ detail::assign_point_from_index<0>(segment2, q[0]);
+ detail::assign_point_from_index<1>(segment2, q[1]);
+
+ auto cp0 = strategies.closest_points(q[0], segment1).apply(q[0], p[0], p[1]);
+ auto cp1 = strategies.closest_points(q[1], segment1).apply(q[1], p[0], p[1]);
+ auto cp2 = strategies.closest_points(p[0], segment2).apply(p[0], q[0], q[1]);
+ auto cp3 = strategies.closest_points(p[1], segment2).apply(p[1], q[0], q[1]);
+
+ closest_points::creturn_t<Segment1, Segment2, Strategies> d[4];
+
+ auto const cds = strategies::distance::detail::make_comparable(strategies)
+ .distance(detail::dummy_point(), detail::dummy_point());
+
+ d[0] = cds.apply(cp0, q[0]);
+ d[1] = cds.apply(cp1, q[1]);
+ d[2] = cds.apply(p[0], cp2);
+ d[3] = cds.apply(p[1], cp3);
+
+ std::size_t imin = std::distance(boost::addressof(d[0]), std::min_element(d, d + 4));
+
+ switch (imin)
+ {
+ case 0:
+ set_segment_from_points::apply(cp0, q[0], shortest_seg);
+ return;
+ case 1:
+ set_segment_from_points::apply(cp1, q[1], shortest_seg);
+ return;
+ case 2:
+ set_segment_from_points::apply(p[0], cp2, shortest_seg);
+ return;
+ default:
+ set_segment_from_points::apply(p[1], cp3, shortest_seg);
+ return;
+ }
+ }
+};
+
+
+}} // namespace detail::closest_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+// segment-segment
+template <typename Segment1, typename Segment2>
+struct closest_points
+ <
+ Segment1, Segment2, segment_tag, segment_tag, false
+ > : detail::closest_points::segment_to_segment
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_SEGMENT_TO_SEGMENT_HPP
diff --git a/boost/geometry/algorithms/detail/closest_points/utilities.hpp b/boost/geometry/algorithms/detail/closest_points/utilities.hpp
new file mode 100644
index 0000000000..858c86efb8
--- /dev/null
+++ b/boost/geometry/algorithms/detail/closest_points/utilities.hpp
@@ -0,0 +1,69 @@
+// Boost.Geometry
+
+// Copyright (c) 2021-2023, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_UTILITIES_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_UTILITIES_HPP
+
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
+#include <boost/geometry/util/algorithm.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace detail { namespace closest_points
+{
+
+struct set_segment_from_points
+{
+ template <typename Point1, typename Point2, typename Segment>
+ static inline void apply(Point1 const& p1, Point2 const& p2, Segment& segment)
+ {
+ assign_point_to_index<0>(p1, segment);
+ assign_point_to_index<1>(p2, segment);
+ }
+};
+
+
+struct swap_segment_points
+{
+ template <typename Segment>
+ static inline void apply(Segment& segment)
+ {
+ geometry::detail::for_each_dimension<Segment>([&](auto index)
+ {
+ auto temp = get<0,index>(segment);
+ set<0,index>(segment, get<1,index>(segment));
+ set<1,index>(segment, temp);
+ });
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Strategies>
+using distance_strategy_t = decltype(
+ std::declval<Strategies>().distance(std::declval<Geometry1>(), std::declval<Geometry2>()));
+
+template <typename Geometry1, typename Geometry2, typename Strategies>
+using creturn_t = typename strategy::distance::services::return_type
+ <
+ typename strategy::distance::services::comparable_type
+ <
+ distance_strategy_t<Geometry1, Geometry2, Strategies>
+ >::type,
+ typename point_type<Geometry1>::type,
+ typename point_type<Geometry2>::type
+ >::type;
+
+
+}} // namespace detail::closest_points
+
+}} // namespace boost::geometry
+
+#endif //BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_UTILITIES_HPP
diff --git a/boost/geometry/algorithms/detail/comparable_distance/interface.hpp b/boost/geometry/algorithms/detail/comparable_distance/interface.hpp
index 14e2940d3b..d582dc9254 100644
--- a/boost/geometry/algorithms/detail/comparable_distance/interface.hpp
+++ b/boost/geometry/algorithms/detail/comparable_distance/interface.hpp
@@ -3,6 +3,7 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
@@ -50,11 +51,9 @@ template
struct comparable_distance
{
template <typename Geometry1, typename Geometry2>
- static inline
- typename comparable_distance_result<Geometry1, Geometry2, Strategies>::type
- apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategies const& strategies)
+ static inline auto apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategies const& strategies)
{
return dispatch::distance
<
@@ -70,21 +69,17 @@ template <typename Strategy>
struct comparable_distance<Strategy, false>
{
template <typename Geometry1, typename Geometry2>
- static inline
- typename comparable_distance_result<Geometry1, Geometry2, Strategy>::type
- apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
+ static inline auto apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
using strategies::distance::services::strategy_converter;
- typedef decltype(strategy_converter<Strategy>::get(strategy))
- strategies_type;
- typedef strategies::distance::detail::comparable
+ using comparable_strategies_type = strategies::distance::detail::comparable
<
- strategies_type
- > comparable_strategies_type;
-
+ decltype(strategy_converter<Strategy>::get(strategy))
+ >;
+
return dispatch::distance
<
Geometry1, Geometry2,
@@ -100,21 +95,17 @@ template <>
struct comparable_distance<default_strategy, false>
{
template <typename Geometry1, typename Geometry2>
- static inline typename comparable_distance_result
- <
- Geometry1, Geometry2, default_strategy
- >::type
- apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- default_strategy)
+ static inline auto apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ default_strategy)
{
- typedef strategies::distance::detail::comparable
+ using comparable_strategy_type = strategies::distance::detail::comparable
<
typename strategies::distance::services::default_strategy
<
Geometry1, Geometry2
>::type
- > comparable_strategy_type;
+ >;
return dispatch::distance
<
@@ -126,19 +117,22 @@ struct comparable_distance<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant
+namespace resolve_dynamic
{
-template <typename Geometry1, typename Geometry2>
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct comparable_distance
{
template <typename Strategy>
- static inline
- typename comparable_distance_result<Geometry1, Geometry2, Strategy>::type
- apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
+ static inline auto apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
return resolve_strategy::comparable_distance
<
@@ -148,190 +142,85 @@ struct comparable_distance
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct comparable_distance
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
- Geometry2
- >
+template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
+struct comparable_distance<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Strategy>
- struct visitor: static_visitor
- <
- typename comparable_distance_result
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
- Geometry2,
- Strategy
- >::type
- >
+ static inline auto apply(DynamicGeometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2,
- Strategy const& strategy)
- : m_geometry2(geometry2),
- m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- typename comparable_distance_result
+ using result_t = typename geometry::comparable_distance_result
<
- Geometry1, Geometry2, Strategy
- >::type
- operator()(Geometry1 const& geometry1) const
+ DynamicGeometry1, Geometry2, Strategy
+ >::type;
+ result_t result = 0;
+ traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
{
- return comparable_distance
- <
- Geometry1,
- Geometry2
- >::template apply
- <
- Strategy
- >(geometry1, m_geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline typename comparable_distance_result
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
- Geometry2,
- Strategy
- >::type
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
+ result = resolve_strategy::comparable_distance
+ <
+ Strategy
+ >::apply(g1, geometry2, strategy);
+ }, geometry1);
+ return result;
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct comparable_distance
- <
- Geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>
- >
+template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
+struct comparable_distance<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: static_visitor
- <
- typename comparable_distance_result
- <
- Geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
- Strategy
- >::type
- >
+ static inline auto apply(Geometry1 const& geometry1,
+ DynamicGeometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1,
- Strategy const& strategy)
- : m_geometry1(geometry1),
- m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- typename comparable_distance_result
+ using result_t = typename geometry::comparable_distance_result
<
- Geometry1, Geometry2, Strategy
- >::type
- operator()(Geometry2 const& geometry2) const
+ Geometry1, DynamicGeometry2, Strategy
+ >::type;
+ result_t result = 0;
+ traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
{
- return comparable_distance
- <
- Geometry1,
- Geometry2
- >::template apply
- <
- Strategy
- >(m_geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline typename comparable_distance_result
- <
- Geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
- Strategy
- >::type
- apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
+ result = resolve_strategy::comparable_distance
+ <
+ Strategy
+ >::apply(geometry1, g2, strategy);
+ }, geometry2);
+ return result;
}
};
-template
-<
- BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)
->
+template <typename DynamicGeometry1, typename DynamicGeometry2>
struct comparable_distance
<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
+ DynamicGeometry1, DynamicGeometry2,
+ dynamic_geometry_tag, dynamic_geometry_tag
>
{
template <typename Strategy>
- struct visitor: static_visitor
- <
- typename comparable_distance_result
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
- Strategy
- >::type
- >
+ static inline auto apply(DynamicGeometry1 const& geometry1,
+ DynamicGeometry2 const& geometry2,
+ Strategy const& strategy)
{
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy)
- : m_strategy(strategy)
- {}
-
- template <typename Geometry1, typename Geometry2>
- typename comparable_distance_result
+ using result_t = typename geometry::comparable_distance_result
<
- Geometry1, Geometry2, Strategy
- >::type
- operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const
+ DynamicGeometry1, DynamicGeometry2, Strategy
+ >::type;
+ result_t result = 0;
+ traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
{
- return comparable_distance
- <
- Geometry1,
- Geometry2
- >::template apply
- <
- Strategy
- >(geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline typename comparable_distance_result
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
- Strategy
- >::type
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
+ result = resolve_strategy::comparable_distance
+ <
+ Strategy
+ >::apply(g1, g2, strategy);
+ }, geometry1, geometry2);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
@@ -354,14 +243,14 @@ struct comparable_distance
\qbk{distinguish,with strategy}
*/
template <typename Geometry1, typename Geometry2, typename Strategy>
-inline typename comparable_distance_result<Geometry1, Geometry2, Strategy>::type
-comparable_distance(Geometry1 const& geometry1, Geometry2 const& geometry2,
- Strategy const& strategy)
+inline auto comparable_distance(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
- return resolve_variant::comparable_distance
+ return resolve_dynamic::comparable_distance
<
Geometry1,
Geometry2
@@ -387,12 +276,9 @@ comparable_distance(Geometry1 const& geometry1, Geometry2 const& geometry2,
\qbk{[include reference/algorithms/comparable_distance.qbk]}
*/
template <typename Geometry1, typename Geometry2>
-inline typename default_comparable_distance_result<Geometry1, Geometry2>::type
-comparable_distance(Geometry1 const& geometry1, Geometry2 const& geometry2)
+inline auto comparable_distance(Geometry1 const& geometry1,
+ Geometry2 const& geometry2)
{
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
-
return geometry::comparable_distance(geometry1, geometry2, default_strategy());
}
diff --git a/boost/geometry/algorithms/detail/convert_point_to_point.hpp b/boost/geometry/algorithms/detail/convert_point_to_point.hpp
index c7d37b6ca4..8762cd6687 100644
--- a/boost/geometry/algorithms/detail/convert_point_to_point.hpp
+++ b/boost/geometry/algorithms/detail/convert_point_to_point.hpp
@@ -32,6 +32,12 @@ namespace detail { namespace conversion
{
+// TODO: Use assignment if possible.
+// WARNING: This utility is called in various places for a subset of dimensions.
+// In such cases only some of the coordinates should be copied. Alternatively
+// there should be a different utility for that called differently than
+// convert_xxx, e.g. set_coordinates.
+
template <typename Source, typename Destination, std::size_t Dimension, std::size_t DimensionCount>
struct point_to_point
{
diff --git a/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp b/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp
index 9584f6a2f1..64d81054e8 100644
--- a/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp
+++ b/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2023.
+// Modifications copyright (c) 2014-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
@@ -23,20 +23,19 @@
#include <algorithm>
#include <vector>
-#include <boost/range/begin.hpp>
-#include <boost/range/empty.hpp>
-#include <boost/range/end.hpp>
-#include <boost/range/size.hpp>
-
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/strategies/convex_hull/cartesian.hpp>
#include <boost/geometry/strategies/convex_hull/geographic.hpp>
#include <boost/geometry/strategies/convex_hull/spherical.hpp>
+#include <boost/geometry/util/range.hpp>
+
namespace boost { namespace geometry
{
@@ -45,13 +44,15 @@ namespace boost { namespace geometry
namespace detail { namespace convex_hull
{
-template <typename Geometry, typename Point, typename Less>
-inline void get_extremes(Geometry const& geometry,
+// TODO: All of the copies could be avoided if this function stored pointers to points.
+// But would it be possible considering that a range can return proxy reference?
+template <typename InputProxy, typename Point, typename Less>
+inline void get_extremes(InputProxy const& in_proxy,
Point& left, Point& right,
Less const& less)
{
bool first = true;
- geometry::detail::for_each_range(geometry, [&](auto const& range)
+ in_proxy.for_each_range([&](auto const& range)
{
if (boost::empty(range))
{
@@ -107,19 +108,13 @@ inline void get_extremes(Geometry const& geometry,
}
-template
-<
- typename Geometry,
- typename Point,
- typename Container,
- typename SideStrategy
->
-inline void assign_ranges(Geometry const& geometry,
+template <typename InputProxy, typename Point, typename Container, typename SideStrategy>
+inline void assign_ranges(InputProxy const& in_proxy,
Point const& most_left, Point const& most_right,
Container& lower_points, Container& upper_points,
SideStrategy const& side)
{
- geometry::detail::for_each_range(geometry, [&](auto const& range)
+ in_proxy.for_each_range([&](auto const& range)
{
// Put points in one of the two output sequences
for (auto it = boost::begin(range); it != boost::end(range); ++it)
@@ -145,33 +140,14 @@ inline void assign_ranges(Geometry const& geometry,
}
-template <typename Range, typename Less>
-inline void sort(Range& range, Less const& less)
-{
- std::sort(boost::begin(range), boost::end(range), less);
-}
-
-} // namespace convex_hull
-
-
/*!
\brief Graham scan algorithm to calculate convex hull
*/
-template <typename InputGeometry, typename OutputPoint>
+template <typename InputPoint>
class graham_andrew
{
-public :
- typedef OutputPoint point_type;
- typedef InputGeometry geometry_type;
-
-private:
-
- typedef typename cs_tag<point_type>::type cs_tag;
-
+ typedef InputPoint point_type;
typedef typename std::vector<point_type> container_type;
- typedef typename std::vector<point_type>::const_iterator iterator;
- typedef typename std::vector<point_type>::const_reverse_iterator rev_iterator;
-
class partitions
{
@@ -182,14 +158,23 @@ private:
container_type m_copied_input;
};
-
public:
- typedef partitions state_type;
+ template <typename InputProxy, typename OutputRing, typename Strategy>
+ static void apply(InputProxy const& in_proxy, OutputRing & out_ring, Strategy& strategy)
+ {
+ partitions state;
+
+ apply(in_proxy, state, strategy);
- template <typename Strategy>
- inline void apply(InputGeometry const& geometry,
- partitions& state,
- Strategy& strategy) const
+ result(state,
+ range::back_inserter(out_ring),
+ geometry::point_order<OutputRing>::value == clockwise,
+ geometry::closure<OutputRing>::value != open);
+ }
+
+private:
+ template <typename InputProxy, typename Strategy>
+ static void apply(InputProxy const& in_proxy, partitions& state, Strategy& strategy)
{
// First pass.
// Get min/max (in most cases left / right) points
@@ -203,14 +188,11 @@ public:
// For symmetry and to get often more balanced lower/upper halves
// we keep it.
- typedef typename geometry::point_type<InputGeometry>::type point_type;
-
point_type most_left, most_right;
- // TODO: User-defined CS-specific less-compare
- geometry::less<point_type> less;
+ geometry::less_exact<point_type, -1, Strategy> less;
- detail::convex_hull::get_extremes(geometry, most_left, most_right, less);
+ detail::convex_hull::get_extremes(in_proxy, most_left, most_right, less);
container_type lower_points, upper_points;
@@ -219,13 +201,13 @@ public:
// Bounding left/right points
// Second pass, now that extremes are found, assign all points
// in either lower, either upper
- detail::convex_hull::assign_ranges(geometry, most_left, most_right,
+ detail::convex_hull::assign_ranges(in_proxy, most_left, most_right,
lower_points, upper_points,
side_strategy);
// Sort both collections, first on x(, then on y)
- detail::convex_hull::sort(lower_points, less);
- detail::convex_hull::sort(upper_points, less);
+ std::sort(boost::begin(lower_points), boost::end(lower_points), less);
+ std::sort(boost::begin(upper_points), boost::end(upper_points), less);
// And decide which point should be in the final hull
build_half_hull<-1>(lower_points, state.m_lower_hull,
@@ -236,26 +218,6 @@ public:
side_strategy);
}
-
- template <typename OutputIterator>
- inline void result(partitions const& state,
- OutputIterator out,
- bool clockwise,
- bool closed) const
- {
- if (clockwise)
- {
- output_ranges(state.m_upper_hull, state.m_lower_hull, out, closed);
- }
- else
- {
- output_ranges(state.m_lower_hull, state.m_upper_hull, out, closed);
- }
- }
-
-
-private:
-
template <int Factor, typename SideStrategy>
static inline void build_half_hull(container_type const& input,
container_type& output,
@@ -263,9 +225,9 @@ private:
SideStrategy const& side)
{
output.push_back(left);
- for(iterator it = input.begin(); it != input.end(); ++it)
+ for (auto const& i : input)
{
- add_to_hull<Factor>(*it, output, side);
+ add_to_hull<Factor>(i, output, side);
}
add_to_hull<Factor>(right, output, side);
}
@@ -279,7 +241,7 @@ private:
std::size_t output_size = output.size();
while (output_size >= 3)
{
- rev_iterator rit = output.rbegin();
+ auto rit = output.rbegin();
point_type const last = *rit++;
point_type const& last2 = *rit++;
@@ -301,6 +263,19 @@ private:
template <typename OutputIterator>
+ static void result(partitions const& state, OutputIterator out, bool clockwise, bool closed)
+ {
+ if (clockwise)
+ {
+ output_ranges(state.m_upper_hull, state.m_lower_hull, out, closed);
+ }
+ else
+ {
+ output_ranges(state.m_lower_hull, state.m_upper_hull, out, closed);
+ }
+ }
+
+ template <typename OutputIterator>
static inline void output_ranges(container_type const& first,
container_type const& second,
OutputIterator out,
@@ -327,7 +302,7 @@ private:
};
-} // namespace detail
+}} // namespace detail::convex_hull
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/convex_hull/interface.hpp b/boost/geometry/algorithms/detail/convex_hull/interface.hpp
index ce61c99802..b820cc4bf4 100644
--- a/boost/geometry/algorithms/detail/convex_hull/interface.hpp
+++ b/boost/geometry/algorithms/detail/convex_hull/interface.hpp
@@ -3,6 +3,7 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
@@ -21,86 +22,171 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_INTERFACE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_INTERFACE_HPP
-#include <boost/array.hpp>
+#include <array>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
-#include <boost/geometry/algorithms/detail/as_range.hpp>
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
#include <boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp>
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
+#include <boost/geometry/algorithms/detail/for_each_range.hpp>
+#include <boost/geometry/algorithms/detail/select_geometry_type.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/geometry_types.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/tag.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/geometries/ring.hpp>
-#include <boost/geometry/strategies/convex_hull/services.hpp>
+#include <boost/geometry/strategies/convex_hull/cartesian.hpp>
+#include <boost/geometry/strategies/convex_hull/geographic.hpp>
+#include <boost/geometry/strategies/convex_hull/spherical.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/range.hpp>
+#include <boost/geometry/util/sequence.hpp>
+#include <boost/geometry/util/type_traits.hpp>
namespace boost { namespace geometry
{
+// TODO: This file is named interface.hpp but the code below is not the interface.
+// It's the implementation of the algorithm.
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace convex_hull
{
-template <order_selector Order, closure_selector Closure>
-struct hull_insert
+// Abstraction representing ranges/rings of a geometry
+template <typename Geometry>
+struct input_geometry_proxy
{
- // Member template function (to avoid inconvenient declaration
- // of output-iterator-type, from hull_to_geometry)
- template <typename Geometry, typename OutputIterator, typename Strategy>
- static inline OutputIterator apply(Geometry const& geometry,
- OutputIterator out,
- Strategy const& strategy)
+ input_geometry_proxy(Geometry const& geometry)
+ : m_geometry(geometry)
+ {}
+
+ template <typename UnaryFunction>
+ inline void for_each_range(UnaryFunction fun) const
{
- typedef graham_andrew
- <
- Geometry,
- typename point_type<Geometry>::type
- > ConvexHullAlgorithm;
+ geometry::detail::for_each_range(m_geometry, fun);
+ }
- ConvexHullAlgorithm algorithm;
- typename ConvexHullAlgorithm::state_type state;
+ Geometry const& m_geometry;
+};
- algorithm.apply(geometry, state, strategy);
- algorithm.result(state, out, Order == clockwise, Closure != open);
+// Abstraction representing ranges/rings of subgeometries of geometry collection
+// with boxes converted to rings
+template <typename Geometry, typename BoxRings>
+struct input_geometry_collection_proxy
+{
+ input_geometry_collection_proxy(Geometry const& geometry, BoxRings const& box_rings)
+ : m_geometry(geometry)
+ , m_box_rings(box_rings)
+ {}
+
+ template <typename UnaryFunction>
+ inline void for_each_range(UnaryFunction fun) const
+ {
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ input_geometry_collection_proxy::call_for_non_boxes(g, fun);
+ return true;
+ }, m_geometry);
- return out;
+ for (auto const& r : m_box_rings)
+ {
+ geometry::detail::for_each_range(r, fun);
+ }
}
-};
-struct hull_to_geometry
-{
- template <typename Geometry, typename OutputGeometry, typename Strategy>
- static inline void apply(Geometry const& geometry, OutputGeometry& out,
- Strategy const& strategy)
+private:
+ template <typename G, typename F, std::enable_if_t<! util::is_box<G>::value, int> = 0>
+ static inline void call_for_non_boxes(G const& g, F & f)
{
- // TODO: Why not handle multi-polygon here?
- // TODO: detail::as_range() is only used in this place in the whole library
- // it should probably be located here.
- // NOTE: A variable is created here because this can be a proxy range
- // and back_insert_iterator<> can store a pointer to it.
- // Handle linestring, ring and polygon the same:
- auto&& range = detail::as_range(out);
- hull_insert
- <
- geometry::point_order<OutputGeometry>::value,
- geometry::closure<OutputGeometry>::value
- >::apply(geometry, range::back_inserter(range), strategy);
+ geometry::detail::for_each_range(g, f);
}
+ template <typename G, typename F, std::enable_if_t<util::is_box<G>::value, int> = 0>
+ static inline void call_for_non_boxes(G const&, F &)
+ {}
+
+ Geometry const& m_geometry;
+ BoxRings const& m_box_rings;
+};
+
+
+// TODO: Or just implement point_type<> for GeometryCollection
+// and enforce the same point_type used in the whole sequence in check().
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct default_strategy
+{
+ using type = typename strategies::convex_hull::services::default_strategy
+ <
+ Geometry
+ >::type;
+};
+
+template <typename Geometry>
+struct default_strategy<Geometry, geometry_collection_tag>
+ : default_strategy<typename detail::first_geometry_type<Geometry>::type>
+{};
+
+
+// Utilities for output GC and DG
+template <typename G1, typename G2>
+struct output_polygonal_less
+{
+ template <typename G>
+ using priority = std::integral_constant
+ <
+ int,
+ (util::is_ring<G>::value ? 0 :
+ util::is_polygon<G>::value ? 1 :
+ util::is_multi_polygon<G>::value ? 2 : 3)
+ >;
+
+ static const bool value = priority<G1>::value < priority<G2>::value;
};
+template <typename G1, typename G2>
+struct output_linear_less
+{
+ template <typename G>
+ using priority = std::integral_constant
+ <
+ int,
+ (util::is_segment<G>::value ? 0 :
+ util::is_linestring<G>::value ? 1 :
+ util::is_multi_linestring<G>::value ? 2 : 3)
+ >;
+
+ static const bool value = priority<G1>::value < priority<G2>::value;
+};
+
+template <typename G1, typename G2>
+struct output_pointlike_less
+{
+ template <typename G>
+ using priority = std::integral_constant
+ <
+ int,
+ (util::is_point<G>::value ? 0 :
+ util::is_multi_point<G>::value ? 1 : 2)
+ >;
+
+ static const bool value = priority<G1>::value < priority<G2>::value;
+};
+
+
}} // namespace detail::convex_hull
#endif // DOXYGEN_NO_DETAIL
@@ -116,10 +202,23 @@ template
typename Tag = typename tag<Geometry>::type
>
struct convex_hull
- : detail::convex_hull::hull_to_geometry
-{};
+{
+ template <typename OutputGeometry, typename Strategy>
+ static inline void apply(Geometry const& geometry,
+ OutputGeometry& out,
+ Strategy const& strategy)
+ {
+ detail::convex_hull::input_geometry_proxy<Geometry> in_proxy(geometry);
+ detail::convex_hull::graham_andrew
+ <
+ typename point_type<Geometry>::type
+ >::apply(in_proxy, out, strategy);
+ }
+};
-// TODO: This is not correct in spherical and geographic CS
+
+// A hull for boxes is trivial. Any strategy is (currently) skipped.
+// TODO: This is not correct in spherical and geographic CS.
template <typename Box>
struct convex_hull<Box, box_tag>
{
@@ -133,185 +232,337 @@ struct convex_hull<Box, box_tag>
static bool const Reverse
= geometry::point_order<OutputGeometry>::value == counterclockwise;
- // A hull for boxes is trivial. Any strategy is (currently) skipped.
- boost::array<typename point_type<Box>::type, 4> range;
- geometry::detail::assign_box_corners_oriented<Reverse>(box, range);
- geometry::append(out, range);
+ std::array<typename point_type<OutputGeometry>::type, 4> arr;
+ // TODO: This assigns only 2d cooridnates!
+ // And it is also used in box_view<>!
+ geometry::detail::assign_box_corners_oriented<Reverse>(box, arr);
+
+ std::move(arr.begin(), arr.end(), range::back_inserter(out));
if (BOOST_GEOMETRY_CONDITION(Close))
{
- geometry::append(out, *boost::begin(range));
+ range::push_back(out, range::front(out));
}
}
};
+template <typename GeometryCollection>
+struct convex_hull<GeometryCollection, geometry_collection_tag>
+{
+ template <typename OutputGeometry, typename Strategy>
+ static inline void apply(GeometryCollection const& geometry,
+ OutputGeometry& out,
+ Strategy const& strategy)
+ {
+ // Assuming that single point_type is used by the GeometryCollection
+ using subgeometry_type = typename detail::first_geometry_type<GeometryCollection>::type;
+ using point_type = typename geometry::point_type<subgeometry_type>::type;
+ using ring_type = model::ring<point_type, true, false>;
+
+ // Calculate box rings once
+ std::vector<ring_type> box_rings;
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ convex_hull::add_ring_for_box(box_rings, g, strategy);
+ return true;
+ }, geometry);
-template <order_selector Order, closure_selector Closure>
-struct convex_hull_insert
- : detail::convex_hull::hull_insert<Order, Closure>
-{};
+ detail::convex_hull::input_geometry_collection_proxy
+ <
+ GeometryCollection, std::vector<ring_type>
+ > in_proxy(geometry, box_rings);
+ detail::convex_hull::graham_andrew
+ <
+ point_type
+ >::apply(in_proxy, out, strategy);
+ }
-} // namespace dispatch
-#endif // DOXYGEN_NO_DISPATCH
+private:
+ template
+ <
+ typename Ring, typename SubGeometry, typename Strategy,
+ std::enable_if_t<util::is_box<SubGeometry>::value, int> = 0
+ >
+ static inline void add_ring_for_box(std::vector<Ring> & rings, SubGeometry const& box,
+ Strategy const& strategy)
+ {
+ Ring ring;
+ convex_hull<SubGeometry>::apply(box, ring, strategy);
+ rings.push_back(std::move(ring));
+ }
+ template
+ <
+ typename Ring, typename SubGeometry, typename Strategy,
+ std::enable_if_t<! util::is_box<SubGeometry>::value, int> = 0
+ >
+ static inline void add_ring_for_box(std::vector<Ring> & , SubGeometry const& ,
+ Strategy const& )
+ {}
+};
-namespace resolve_strategy {
+template <typename OutputGeometry, typename Tag = typename tag<OutputGeometry>::type>
+struct convex_hull_out
+{
+ BOOST_GEOMETRY_STATIC_ASSERT_FALSE("This OutputGeometry is not supported.", OutputGeometry, Tag);
+};
-struct convex_hull
+template <typename OutputGeometry>
+struct convex_hull_out<OutputGeometry, ring_tag>
{
- template <typename Geometry, typename OutputGeometry, typename Strategy>
+ template <typename Geometry, typename Strategies>
static inline void apply(Geometry const& geometry,
OutputGeometry& out,
- Strategy const& strategy)
+ Strategies const& strategies)
{
- //BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy<Strategy>) );
- dispatch::convex_hull<Geometry>::apply(geometry, out, strategy);
+ dispatch::convex_hull<Geometry>::apply(geometry, out, strategies);
}
+};
- template <typename Geometry, typename OutputGeometry>
+template <typename OutputGeometry>
+struct convex_hull_out<OutputGeometry, polygon_tag>
+{
+ template <typename Geometry, typename Strategies>
static inline void apply(Geometry const& geometry,
OutputGeometry& out,
- default_strategy)
+ Strategies const& strategies)
{
- typedef typename strategies::convex_hull::services::default_strategy
- <
- Geometry
- >::type strategy_type;
+ auto&& ring = exterior_ring(out);
+ dispatch::convex_hull<Geometry>::apply(geometry, ring, strategies);
+ }
+};
- apply(geometry, out, strategy_type());
+template <typename OutputGeometry>
+struct convex_hull_out<OutputGeometry, multi_polygon_tag>
+{
+ template <typename Geometry, typename Strategies>
+ static inline void apply(Geometry const& geometry,
+ OutputGeometry& out,
+ Strategies const& strategies)
+ {
+ typename boost::range_value<OutputGeometry>::type polygon;
+ auto&& ring = exterior_ring(polygon);
+ dispatch::convex_hull<Geometry>::apply(geometry, ring, strategies);
+ // Empty input is checked so the output shouldn't be empty
+ range::push_back(out, std::move(polygon));
}
};
-struct convex_hull_insert
+template <typename OutputGeometry>
+struct convex_hull_out<OutputGeometry, geometry_collection_tag>
{
- template <typename Geometry, typename OutputIterator, typename Strategy>
- static inline OutputIterator apply(Geometry const& geometry,
- OutputIterator& out,
- Strategy const& strategy)
+ using polygonal_t = typename util::sequence_min_element
+ <
+ typename traits::geometry_types<OutputGeometry>::type,
+ detail::convex_hull::output_polygonal_less
+ >::type;
+ using linear_t = typename util::sequence_min_element
+ <
+ typename traits::geometry_types<OutputGeometry>::type,
+ detail::convex_hull::output_linear_less
+ >::type;
+ using pointlike_t = typename util::sequence_min_element
+ <
+ typename traits::geometry_types<OutputGeometry>::type,
+ detail::convex_hull::output_pointlike_less
+ >::type;
+
+ // select_element may define different kind of geometry than the one that is desired
+ BOOST_GEOMETRY_STATIC_ASSERT(util::is_polygonal<polygonal_t>::value,
+ "It must be possible to store polygonal geometry in OutputGeometry.", polygonal_t);
+ BOOST_GEOMETRY_STATIC_ASSERT(util::is_linear<linear_t>::value,
+ "It must be possible to store linear geometry in OutputGeometry.", linear_t);
+ BOOST_GEOMETRY_STATIC_ASSERT(util::is_pointlike<pointlike_t>::value,
+ "It must be possible to store pointlike geometry in OutputGeometry.", pointlike_t);
+
+ template <typename Geometry, typename Strategies>
+ static inline void apply(Geometry const& geometry,
+ OutputGeometry& out,
+ Strategies const& strategies)
{
- //BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy<Strategy>) );
+ polygonal_t polygonal;
+ convex_hull_out<polygonal_t>::apply(geometry, polygonal, strategies);
+ // Empty input is checked so the output shouldn't be empty
+ auto&& out_ring = ring(polygonal);
+
+ if (boost::size(out_ring) == detail::minimum_ring_size<polygonal_t>::value)
+ {
+ using detail::equals::equals_point_point;
+ if (equals_point_point(range::front(out_ring), range::at(out_ring, 1), strategies))
+ {
+ pointlike_t pointlike;
+ move_to_pointlike(out_ring, pointlike);
+ move_to_out(pointlike, out);
+ return;
+ }
+ if (equals_point_point(range::front(out_ring), range::at(out_ring, 2), strategies))
+ {
+ linear_t linear;
+ move_to_linear(out_ring, linear);
+ move_to_out(linear, out);
+ return;
+ }
+ }
- return dispatch::convex_hull_insert<
- geometry::point_order<Geometry>::value,
- geometry::closure<Geometry>::value
- >::apply(geometry, out, strategy);
+ move_to_out(polygonal, out);
}
- template <typename Geometry, typename OutputIterator>
- static inline OutputIterator apply(Geometry const& geometry,
- OutputIterator& out,
- default_strategy)
+private:
+ template <typename Polygonal, util::enable_if_ring_t<Polygonal, int> = 0>
+ static decltype(auto) ring(Polygonal const& polygonal)
{
- typedef typename strategies::convex_hull::services::default_strategy
- <
- Geometry
- >::type strategy_type;
+ return polygonal;
+ }
+ template <typename Polygonal, util::enable_if_polygon_t<Polygonal, int> = 0>
+ static decltype(auto) ring(Polygonal const& polygonal)
+ {
+ return exterior_ring(polygonal);
+ }
+ template <typename Polygonal, util::enable_if_multi_polygon_t<Polygonal, int> = 0>
+ static decltype(auto) ring(Polygonal const& polygonal)
+ {
+ return exterior_ring(range::front(polygonal));
+ }
- return apply(geometry, out, strategy_type());
+ template <typename Range, typename Linear, util::enable_if_segment_t<Linear, int> = 0>
+ static void move_to_linear(Range & out_range, Linear & seg)
+ {
+ detail::assign_point_to_index<0>(range::front(out_range), seg);
+ detail::assign_point_to_index<1>(range::at(out_range, 1), seg);
+ }
+ template <typename Range, typename Linear, util::enable_if_linestring_t<Linear, int> = 0>
+ static void move_to_linear(Range & out_range, Linear & ls)
+ {
+ std::move(boost::begin(out_range), boost::begin(out_range) + 2, range::back_inserter(ls));
+ }
+ template <typename Range, typename Linear, util::enable_if_multi_linestring_t<Linear, int> = 0>
+ static void move_to_linear(Range & out_range, Linear & mls)
+ {
+ typename boost::range_value<Linear>::type ls;
+ std::move(boost::begin(out_range), boost::begin(out_range) + 2, range::back_inserter(ls));
+ range::push_back(mls, std::move(ls));
+ }
+
+ template <typename Range, typename PointLike, util::enable_if_point_t<PointLike, int> = 0>
+ static void move_to_pointlike(Range & out_range, PointLike & pt)
+ {
+ pt = range::front(out_range);
+ }
+ template <typename Range, typename PointLike, util::enable_if_multi_point_t<PointLike, int> = 0>
+ static void move_to_pointlike(Range & out_range, PointLike & mpt)
+ {
+ range::push_back(mpt, std::move(range::front(out_range)));
+ }
+
+ template
+ <
+ typename Geometry, typename OutputGeometry_,
+ util::enable_if_geometry_collection_t<OutputGeometry_, int> = 0
+ >
+ static void move_to_out(Geometry & g, OutputGeometry_ & out)
+ {
+ range::emplace_back(out, std::move(g));
+ }
+ template
+ <
+ typename Geometry, typename OutputGeometry_,
+ util::enable_if_dynamic_geometry_t<OutputGeometry_, int> = 0
+ >
+ static void move_to_out(Geometry & g, OutputGeometry_ & out)
+ {
+ out = std::move(g);
}
};
-} // namespace resolve_strategy
+template <typename OutputGeometry>
+struct convex_hull_out<OutputGeometry, dynamic_geometry_tag>
+ : convex_hull_out<OutputGeometry, geometry_collection_tag>
+{};
-namespace resolve_variant {
+// For backward compatibility
+template <typename OutputGeometry>
+struct convex_hull_out<OutputGeometry, linestring_tag>
+ : convex_hull_out<OutputGeometry, ring_tag>
+{};
-template <typename Geometry>
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+namespace resolve_strategy {
+
+template <typename Strategies>
struct convex_hull
{
- template <typename OutputGeometry, typename Strategy>
+ template <typename Geometry, typename OutputGeometry>
static inline void apply(Geometry const& geometry,
OutputGeometry& out,
- Strategy const& strategy)
+ Strategies const& strategies)
{
- concepts::check_concepts_and_equal_dimensions<
- const Geometry,
- OutputGeometry
- >();
-
- resolve_strategy::convex_hull::apply(geometry, out, strategy);
+ dispatch::convex_hull_out<OutputGeometry>::apply(geometry, out, strategies);
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct convex_hull<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <>
+struct convex_hull<default_strategy>
{
- template <typename OutputGeometry, typename Strategy>
- struct visitor: boost::static_visitor<void>
+ template <typename Geometry, typename OutputGeometry>
+ static inline void apply(Geometry const& geometry,
+ OutputGeometry& out,
+ default_strategy const&)
{
- OutputGeometry& m_out;
- Strategy const& m_strategy;
-
- visitor(OutputGeometry& out, Strategy const& strategy)
- : m_out(out), m_strategy(strategy)
- {}
-
- template <typename Geometry>
- void operator()(Geometry const& geometry) const
- {
- convex_hull<Geometry>::apply(geometry, m_out, m_strategy);
- }
- };
+ using strategy_type = typename detail::convex_hull::default_strategy
+ <
+ Geometry
+ >::type;
- template <typename OutputGeometry, typename Strategy>
- static inline void
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- OutputGeometry& out,
- Strategy const& strategy)
- {
- boost::apply_visitor(visitor<OutputGeometry, Strategy>(out, strategy),
- geometry);
+ dispatch::convex_hull_out<OutputGeometry>::apply(geometry, out, strategy_type());
}
};
-template <typename Geometry>
-struct convex_hull_insert
+
+} // namespace resolve_strategy
+
+
+namespace resolve_dynamic {
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct convex_hull
{
- template <typename OutputIterator, typename Strategy>
- static inline OutputIterator apply(Geometry const& geometry,
- OutputIterator& out,
- Strategy const& strategy)
+ template <typename OutputGeometry, typename Strategy>
+ static inline void apply(Geometry const& geometry,
+ OutputGeometry& out,
+ Strategy const& strategy)
{
- // Concept: output point type = point type of input geometry
- concepts::check<Geometry const>();
- concepts::check<typename point_type<Geometry>::type>();
+ concepts::check_concepts_and_equal_dimensions<
+ const Geometry,
+ OutputGeometry
+ >();
- return resolve_strategy::convex_hull_insert::apply(geometry, out, strategy);
+ resolve_strategy::convex_hull<Strategy>::apply(geometry, out, strategy);
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct convex_hull_insert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct convex_hull<Geometry, dynamic_geometry_tag>
{
- template <typename OutputIterator, typename Strategy>
- struct visitor: boost::static_visitor<OutputIterator>
+ template <typename OutputGeometry, typename Strategy>
+ static inline void apply(Geometry const& geometry,
+ OutputGeometry& out,
+ Strategy const& strategy)
{
- OutputIterator& m_out;
- Strategy const& m_strategy;
-
- visitor(OutputIterator& out, Strategy const& strategy)
- : m_out(out), m_strategy(strategy)
- {}
-
- template <typename Geometry>
- OutputIterator operator()(Geometry const& geometry) const
+ traits::visit<Geometry>::apply([&](auto const& g)
{
- return convex_hull_insert<Geometry>::apply(geometry, m_out, m_strategy);
- }
- };
-
- template <typename OutputIterator, typename Strategy>
- static inline OutputIterator
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- OutputIterator& out,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<OutputIterator, Strategy>(out, strategy), geometry);
+ convex_hull<util::remove_cref_t<decltype(g)>>::apply(g, out, strategy);
+ }, geometry);
}
};
-} // namespace resolve_variant
+
+} // namespace resolve_dynamic
/*!
@@ -330,8 +581,7 @@ struct convex_hull_insert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
\qbk{[include reference/algorithms/convex_hull.qbk]}
*/
template<typename Geometry, typename OutputGeometry, typename Strategy>
-inline void convex_hull(Geometry const& geometry,
- OutputGeometry& out, Strategy const& strategy)
+inline void convex_hull(Geometry const& geometry, OutputGeometry& out, Strategy const& strategy)
{
if (geometry::is_empty(geometry))
{
@@ -339,7 +589,7 @@ inline void convex_hull(Geometry const& geometry,
return;
}
- resolve_variant::convex_hull<Geometry>::apply(geometry, out, strategy);
+ resolve_dynamic::convex_hull<Geometry>::apply(geometry, out, strategy);
}
@@ -355,52 +605,11 @@ inline void convex_hull(Geometry const& geometry,
\qbk{[include reference/algorithms/convex_hull.qbk]}
*/
template<typename Geometry, typename OutputGeometry>
-inline void convex_hull(Geometry const& geometry,
- OutputGeometry& hull)
+inline void convex_hull(Geometry const& geometry, OutputGeometry& hull)
{
geometry::convex_hull(geometry, hull, default_strategy());
}
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail { namespace convex_hull
-{
-
-
-template<typename Geometry, typename OutputIterator, typename Strategy>
-inline OutputIterator convex_hull_insert(Geometry const& geometry,
- OutputIterator out, Strategy const& strategy)
-{
- return resolve_variant::convex_hull_insert
- <
- Geometry
- >::apply(geometry, out, strategy);
-}
-
-
-/*!
-\brief Calculate the convex hull of a geometry, output-iterator version
-\ingroup convex_hull
-\tparam Geometry the input geometry type
-\tparam OutputIterator: an output-iterator
-\param geometry the geometry to calculate convex hull from
-\param out an output iterator outputing points of the convex hull
-\note This overloaded version outputs to an output iterator.
-In this case, nothing is known about its point-type or
- about its clockwise order. Therefore, the input point-type
- and order are copied
-
- */
-template<typename Geometry, typename OutputIterator>
-inline OutputIterator convex_hull_insert(Geometry const& geometry,
- OutputIterator out)
-{
- return convex_hull_insert(geometry, out, default_strategy());
-}
-
-
-}} // namespace detail::convex_hull
-#endif // DOXYGEN_NO_DETAIL
-
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/counting.hpp b/boost/geometry/algorithms/detail/counting.hpp
index 3580740b31..0199ec0b9a 100644
--- a/boost/geometry/algorithms/detail/counting.hpp
+++ b/boost/geometry/algorithms/detail/counting.hpp
@@ -30,8 +30,6 @@
#include <boost/geometry/util/range.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
-
namespace boost { namespace geometry
{
@@ -67,10 +65,8 @@ struct polygon_count
{
std::size_t n = RangeCount::apply(exterior_ring(poly));
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(poly);
- for (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ auto const& rings = interior_rings(poly);
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
n += RangeCount::apply(*it);
}
@@ -84,13 +80,10 @@ template <typename SingleCount>
struct multi_count
{
template <typename MultiGeometry>
- static inline std::size_t apply(MultiGeometry const& geometry)
+ static inline std::size_t apply(MultiGeometry const& multi)
{
std::size_t n = 0;
- for (typename boost::range_iterator<MultiGeometry const>::type
- it = boost::begin(geometry);
- it != boost::end(geometry);
- ++it)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
n += SingleCount::apply(*it);
}
diff --git a/boost/geometry/algorithms/detail/covered_by/implementation.hpp b/boost/geometry/algorithms/detail/covered_by/implementation.hpp
index ca4e557caa..13626871aa 100644
--- a/boost/geometry/algorithms/detail/covered_by/implementation.hpp
+++ b/boost/geometry/algorithms/detail/covered_by/implementation.hpp
@@ -4,9 +4,10 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2013-2021.
-// Modifications copyright (c) 2013-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 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
@@ -37,7 +38,8 @@ namespace detail { namespace covered_by {
struct use_point_in_geometry
{
template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
{
return detail::within::covered_by_point_geometry(geometry1, geometry2, strategy);
}
@@ -46,44 +48,41 @@ struct use_point_in_geometry
struct use_relate
{
template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- typedef typename detail::de9im::static_mask_covered_by_type
+ return detail::relate::relate_impl
<
- Geometry1, Geometry2
- >::type covered_by_mask;
- return geometry::relate(geometry1, geometry2, covered_by_mask(), strategy);
+ detail::de9im::static_mask_covered_by_type,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
}
};
-}} // namespace detail::covered_by
-#endif // DOXYGEN_NO_DETAIL
-
-#ifndef DOXYGEN_NO_DISPATCH
-namespace dispatch
-{
-
-template <typename Point, typename Box>
-struct covered_by<Point, Box, point_tag, box_tag>
+struct geometry_covered_by_box
{
- template <typename Strategy>
- static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
+ template <typename Geometry, typename Box, typename Strategy>
+ static inline bool apply(Geometry const& geometry, Box const& box, Strategy const& strategy)
{
- return strategy.covered_by(point, box).apply(point, box);
+ using point_type = typename point_type<Geometry>::type;
+ using mutable_point_type = typename helper_geometry<point_type>::type;
+ using box_type = model::box<mutable_point_type>;
+
+ // TODO: this is not optimal since the process should be able to terminate if a point is found
+ // outside of the box without computing the whole envelope
+ box_type box_areal;
+ geometry::envelope(geometry, box_areal, strategy);
+ return strategy.covered_by(box_areal, box).apply(box_areal, box);
}
};
-template <typename Box1, typename Box2>
-struct covered_by<Box1, Box2, box_tag, box_tag>
-{
- template <typename Strategy>
- static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
- {
- assert_dimension_equal<Box1, Box2>();
- return strategy.covered_by(box1, box2).apply(box1, box2);
- }
-};
+}} // namespace detail::covered_by
+#endif // DOXYGEN_NO_DETAIL
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
// P/P
@@ -272,6 +271,76 @@ struct covered_by<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon
: public detail::covered_by::use_relate
{};
+// B/A
+
+template <typename Box, typename Polygon>
+struct covered_by<Box, Polygon, box_tag, ring_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename Box, typename Polygon>
+struct covered_by<Box, Polygon, box_tag, polygon_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename Box, typename Polygon>
+struct covered_by<Box, Polygon, box_tag, multi_polygon_tag>
+ : public detail::covered_by::use_relate
+{};
+
+// Geometry/Box
+
+template <typename Point, typename Box>
+struct covered_by<Point, Box, point_tag, box_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
+ {
+ return strategy.covered_by(point, box).apply(point, box);
+ }
+};
+
+template <typename MultiPoint, typename Box>
+struct covered_by<MultiPoint, Box, multi_point_tag, box_tag>
+ : public detail::covered_by::geometry_covered_by_box
+{};
+
+template <typename Linestring, typename Box>
+struct covered_by<Linestring, Box, linestring_tag, box_tag>
+ : public detail::covered_by::geometry_covered_by_box
+{};
+
+template <typename MultiLinestring, typename Box>
+struct covered_by<MultiLinestring, Box, multi_linestring_tag, box_tag>
+ : public detail::covered_by::geometry_covered_by_box
+{};
+
+template <typename Ring, typename Box>
+struct covered_by<Ring, Box, ring_tag, box_tag>
+ : public detail::covered_by::geometry_covered_by_box
+{};
+
+template <typename Polygon, typename Box>
+struct covered_by<Polygon, Box, polygon_tag, box_tag>
+ : public detail::covered_by::geometry_covered_by_box
+{};
+
+template <typename MultiPolygon, typename Box>
+struct covered_by<MultiPolygon, Box, multi_polygon_tag, box_tag>
+ : public detail::covered_by::geometry_covered_by_box
+{};
+
+template <typename Box1, typename Box2>
+struct covered_by<Box1, Box2, box_tag, box_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
+ {
+ assert_dimension_equal<Box1, Box2>();
+ return strategy.covered_by(box1, box2).apply(box1, box2);
+ }
+};
+
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
diff --git a/boost/geometry/algorithms/detail/covered_by/implementation_gc.hpp b/boost/geometry/algorithms/detail/covered_by/implementation_gc.hpp
new file mode 100644
index 0000000000..cd0a44bc8f
--- /dev/null
+++ b/boost/geometry/algorithms/detail/covered_by/implementation_gc.hpp
@@ -0,0 +1,46 @@
+// Boost.Geometry
+
+// Copyright (c) 2022 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_GC_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_GC_HPP
+
+
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
+#include <boost/geometry/algorithms/detail/relate/implementation_gc.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+template <typename Geometry1, typename Geometry2>
+struct covered_by<Geometry1, Geometry2, geometry_collection_tag, geometry_collection_tag>
+ : detail::covered_by::use_relate
+{};
+
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct covered_by<Geometry1, Geometry2, Tag1, geometry_collection_tag>
+ : detail::covered_by::use_relate
+{};
+
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct covered_by<Geometry1, Geometry2, geometry_collection_tag, Tag2>
+ : detail::covered_by::use_relate
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_GC_HPP
diff --git a/boost/geometry/algorithms/detail/covered_by/interface.hpp b/boost/geometry/algorithms/detail/covered_by/interface.hpp
index 20b22ff600..0488034381 100644
--- a/boost/geometry/algorithms/detail/covered_by/interface.hpp
+++ b/boost/geometry/algorithms/detail/covered_by/interface.hpp
@@ -19,10 +19,6 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_INTERFACE_HPP
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
#include <boost/geometry/algorithms/detail/within/interface.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
@@ -121,9 +117,14 @@ struct covered_by<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant {
+namespace resolve_dynamic {
-template <typename Geometry1, typename Geometry2>
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct covered_by
{
template <typename Strategy>
@@ -131,107 +132,74 @@ struct covered_by
Geometry2 const& geometry2,
Strategy const& strategy)
{
- return resolve_strategy::covered_by<Strategy>
- ::apply(geometry1, geometry2, strategy);
+ return resolve_strategy::covered_by
+ <
+ Strategy
+ >::apply(geometry1, geometry2, strategy);
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct covered_by<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct covered_by<Geometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2, Strategy const& strategy)
- : m_geometry2(geometry2), m_strategy(strategy) {}
-
- template <typename Geometry1>
- bool operator()(Geometry1 const& geometry1) const
+ bool result = false;
+ traits::visit<Geometry1>::apply([&](auto const& g1)
{
- return covered_by<Geometry1, Geometry2>
- ::apply(geometry1, m_geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
+ result = resolve_strategy::covered_by
+ <
+ Strategy
+ >::apply(g1, geometry2, strategy);
+ }, geometry1);
+ return result;
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct covered_by<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct covered_by<Geometry1, Geometry2, Tag1, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1, Strategy const& strategy)
- : m_geometry1(geometry1), m_strategy(strategy) {}
-
- template <typename Geometry2>
- bool operator()(Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry2>::apply([&](auto const& g2)
{
- return covered_by<Geometry1, Geometry2>
- ::apply(m_geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool
- apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
+ result = resolve_strategy::covered_by
+ <
+ Strategy
+ >::apply(geometry1, g2, strategy);
+ }, geometry2);
+ return result;
}
};
-template <
- BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)
->
-struct covered_by<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
->
+template <typename Geometry1, typename Geometry2>
+struct covered_by<Geometry1, Geometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy): m_strategy(strategy) {}
-
- template <typename Geometry1, typename Geometry2>
- bool operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry1, Geometry2>::apply([&](auto const& g1, auto const& g2)
{
- return covered_by<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
+ result = resolve_strategy::covered_by
+ <
+ Strategy
+ >::apply(g1, g2, strategy);
+ }, geometry1, geometry2);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
@@ -256,8 +224,10 @@ struct covered_by<
template<typename Geometry1, typename Geometry2>
inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
- return resolve_variant::covered_by<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, default_strategy());
+ return resolve_dynamic::covered_by
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, default_strategy());
}
/*!
@@ -280,8 +250,10 @@ template<typename Geometry1, typename Geometry2, typename Strategy>
inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2,
Strategy const& strategy)
{
- return resolve_variant::covered_by<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, strategy);
+ return resolve_dynamic::covered_by
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy);
}
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/direction_code.hpp b/boost/geometry/algorithms/detail/direction_code.hpp
index 269e9b476f..ece34f15b4 100644
--- a/boost/geometry/algorithms/detail/direction_code.hpp
+++ b/boost/geometry/algorithms/detail/direction_code.hpp
@@ -46,16 +46,16 @@ struct direction_code_impl
template <>
struct direction_code_impl<cartesian_tag>
{
- template <typename Point1, typename Point2>
- static inline int apply(Point1 const& segment_a, Point1 const& segment_b,
+ template <typename PointSegmentA, typename PointSegmentB, typename Point2>
+ static inline int apply(PointSegmentA const& segment_a, PointSegmentB const& segment_b,
Point2 const& point)
{
- typedef typename geometry::select_coordinate_type
+ using calc_t = typename geometry::select_coordinate_type
<
- Point1, Point2
- >::type calc_t;
+ PointSegmentA, PointSegmentB, Point2
+ >::type;
- typedef model::infinite_line<calc_t> line_type;
+ using line_type = model::infinite_line<calc_t>;
// Situation and construction of perpendicular line
//
@@ -79,49 +79,67 @@ struct direction_code_impl<cartesian_tag>
}
calc_t const sv = arithmetic::side_value(line, point);
- return sv == 0 ? 0 : sv > 0 ? 1 : -1;
+ static calc_t const zero = 0;
+ return sv == zero ? 0 : sv > zero ? 1 : -1;
}
};
template <>
struct direction_code_impl<spherical_equatorial_tag>
{
- template <typename Point1, typename Point2>
- static inline int apply(Point1 const& segment_a, Point1 const& segment_b,
+ template <typename PointSegmentA, typename PointSegmentB, typename Point2>
+ static inline int apply(PointSegmentA const& segment_a, PointSegmentB const& segment_b,
Point2 const& p)
{
- typedef typename coordinate_type<Point1>::type coord1_t;
- typedef typename coordinate_type<Point2>::type coord2_t;
- typedef typename cs_angular_units<Point1>::type units_t;
- typedef typename cs_angular_units<Point2>::type units2_t;
- BOOST_GEOMETRY_STATIC_ASSERT(
- (std::is_same<units_t, units2_t>::value),
- "Not implemented for different units.",
- units_t, units2_t);
-
- typedef typename geometry::select_coordinate_type <Point1, Point2>::type calc_t;
- typedef math::detail::constants_on_spheroid<coord1_t, units_t> constants1;
- typedef math::detail::constants_on_spheroid<coord2_t, units_t> constants2;
- static coord1_t const pi_half1 = constants1::max_latitude();
- static coord2_t const pi_half2 = constants2::max_latitude();
+ {
+ using units_sa_t = typename cs_angular_units<PointSegmentA>::type;
+ using units_sb_t = typename cs_angular_units<PointSegmentB>::type;
+ using units_p_t = typename cs_angular_units<Point2>::type;
+ BOOST_GEOMETRY_STATIC_ASSERT(
+ (std::is_same<units_sa_t, units_sb_t>::value),
+ "Not implemented for different units.",
+ units_sa_t, units_sb_t);
+ BOOST_GEOMETRY_STATIC_ASSERT(
+ (std::is_same<units_sa_t, units_p_t>::value),
+ "Not implemented for different units.",
+ units_sa_t, units_p_t);
+ }
+
+ using coor_sa_t = typename coordinate_type<PointSegmentA>::type;
+ using coor_sb_t = typename coordinate_type<PointSegmentB>::type;
+ using coor_p_t = typename coordinate_type<Point2>::type;
+
+ // Declare unit type (equal for all types) and calc type (coerced to most precise)
+ using units_t = typename cs_angular_units<Point2>::type;
+ using calc_t = typename geometry::select_coordinate_type
+ <
+ PointSegmentA, PointSegmentB, Point2
+ >::type;
+ using constants_sa_t = math::detail::constants_on_spheroid<coor_sa_t, units_t>;
+ using constants_sb_t = math::detail::constants_on_spheroid<coor_sb_t, units_t>;
+ using constants_p_t = math::detail::constants_on_spheroid<coor_p_t, units_t>;
+
+ static coor_sa_t const pi_half_sa = constants_sa_t::max_latitude();
+ static coor_sb_t const pi_half_sb = constants_sb_t::max_latitude();
+ static coor_p_t const pi_half_p = constants_p_t::max_latitude();
static calc_t const c0 = 0;
- coord1_t const a0 = geometry::get<0>(segment_a);
- coord1_t const a1 = geometry::get<1>(segment_a);
- coord1_t const b0 = geometry::get<0>(segment_b);
- coord1_t const b1 = geometry::get<1>(segment_b);
- coord2_t const p0 = geometry::get<0>(p);
- coord2_t const p1 = geometry::get<1>(p);
-
+ coor_sa_t const a0 = geometry::get<0>(segment_a);
+ coor_sa_t const a1 = geometry::get<1>(segment_a);
+ coor_sb_t const b0 = geometry::get<0>(segment_b);
+ coor_sb_t const b1 = geometry::get<1>(segment_b);
+ coor_p_t const p0 = geometry::get<0>(p);
+ coor_p_t const p1 = geometry::get<1>(p);
+
if ( (math::equals(b0, a0) && math::equals(b1, a1))
|| (math::equals(b0, p0) && math::equals(b1, p1)) )
{
return 0;
}
- bool const is_a_pole = math::equals(pi_half1, math::abs(a1));
- bool const is_b_pole = math::equals(pi_half1, math::abs(b1));
- bool const is_p_pole = math::equals(pi_half2, math::abs(p1));
+ bool const is_a_pole = math::equals(pi_half_sa, math::abs(a1));
+ bool const is_b_pole = math::equals(pi_half_sb, math::abs(b1));
+ bool const is_p_pole = math::equals(pi_half_p, math::abs(p1));
if ( is_b_pole && ((is_a_pole && math::sign(b1) == math::sign(a1))
|| (is_p_pole && math::sign(b1) == math::sign(p1))) )
@@ -139,12 +157,12 @@ struct direction_code_impl<spherical_equatorial_tag>
calc_t const dlat1 = latitude_distance_signed<units_t, calc_t>(b1, a1, dlon1, is_antilon1);
calc_t const dlat2 = latitude_distance_signed<units_t, calc_t>(b1, p1, dlon2, is_antilon2);
- calc_t mx = is_a_pole || is_b_pole || is_p_pole ?
- c0 :
- (std::min)(is_antilon1 ? c0 : math::abs(dlon1),
- is_antilon2 ? c0 : math::abs(dlon2));
- calc_t my = (std::min)(math::abs(dlat1),
- math::abs(dlat2));
+ calc_t const mx = is_a_pole || is_b_pole || is_p_pole
+ ? c0
+ : (std::min)(is_antilon1 ? c0 : math::abs(dlon1),
+ is_antilon2 ? c0 : math::abs(dlon2));
+ calc_t const my = (std::min)(math::abs(dlat1),
+ math::abs(dlat2));
int s1 = 0, s2 = 0;
if (mx >= my)
@@ -164,7 +182,7 @@ struct direction_code_impl<spherical_equatorial_tag>
template <typename Units, typename T>
static inline T latitude_distance_signed(T const& lat1, T const& lat2, T const& lon_ds, bool & is_antilon)
{
- typedef math::detail::constants_on_spheroid<T, Units> constants;
+ using constants = math::detail::constants_on_spheroid<T, Units>;
static T const pi = constants::half_period();
static T const c0 = 0;
@@ -187,27 +205,27 @@ struct direction_code_impl<spherical_equatorial_tag>
template <>
struct direction_code_impl<spherical_polar_tag>
{
- template <typename Point1, typename Point2>
- static inline int apply(Point1 segment_a, Point1 segment_b,
+ template <typename PointSegmentA, typename PointSegmentB, typename Point2>
+ static inline int apply(PointSegmentA segment_a, PointSegmentB segment_b,
Point2 p)
{
- typedef math::detail::constants_on_spheroid
+ using constants_sa_t = math::detail::constants_on_spheroid
<
- typename coordinate_type<Point1>::type,
- typename cs_angular_units<Point1>::type
- > constants1;
- typedef math::detail::constants_on_spheroid
+ typename coordinate_type<PointSegmentA>::type,
+ typename cs_angular_units<PointSegmentA>::type
+ >;
+ using constants_p_t = math::detail::constants_on_spheroid
<
typename coordinate_type<Point2>::type,
typename cs_angular_units<Point2>::type
- > constants2;
+ >;
geometry::set<1>(segment_a,
- constants1::max_latitude() - geometry::get<1>(segment_a));
+ constants_sa_t::max_latitude() - geometry::get<1>(segment_a));
geometry::set<1>(segment_b,
- constants1::max_latitude() - geometry::get<1>(segment_b));
+ constants_sa_t::max_latitude() - geometry::get<1>(segment_b));
geometry::set<1>(p,
- constants2::max_latitude() - geometry::get<1>(p));
+ constants_p_t::max_latitude() - geometry::get<1>(p));
return direction_code_impl
<
@@ -216,13 +234,13 @@ struct direction_code_impl<spherical_polar_tag>
}
};
-// if spherical_tag is passed then pick cs_tag based on Point1 type
+// if spherical_tag is passed then pick cs_tag based on PointSegmentA type
// with spherical_equatorial_tag as the default
template <>
struct direction_code_impl<spherical_tag>
{
- template <typename Point1, typename Point2>
- static inline int apply(Point1 segment_a, Point1 segment_b,
+ template <typename PointSegmentA, typename PointSegmentB, typename Point2>
+ static inline int apply(PointSegmentA segment_a, PointSegmentB segment_b,
Point2 p)
{
return direction_code_impl
@@ -231,7 +249,7 @@ struct direction_code_impl<spherical_tag>
<
std::is_same
<
- typename geometry::cs_tag<Point1>::type,
+ typename geometry::cs_tag<PointSegmentA>::type,
spherical_polar_tag
>::value,
spherical_polar_tag,
@@ -251,8 +269,10 @@ struct direction_code_impl<geographic_tag>
// Returns 1 if p goes forward, so extends (a,b)
// Returns 0 if p is equal with b, or if (a,b) is degenerate
// Note that it does not do any collinearity test, that should be done before
-template <typename CSTag, typename Point1, typename Point2>
-inline int direction_code(Point1 const& segment_a, Point1 const& segment_b,
+// In some cases the "segment" consists of different source points, and therefore
+// their types might differ.
+template <typename CSTag, typename PointSegmentA, typename PointSegmentB, typename Point2>
+inline int direction_code(PointSegmentA const& segment_a, PointSegmentB const& segment_b,
Point2 const& p)
{
return direction_code_impl<CSTag>::apply(segment_a, segment_b, p);
diff --git a/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp b/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp
index 934f90c875..880e503785 100644
--- a/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2020.
-// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -23,13 +23,15 @@
#include <boost/geometry/core/point_type.hpp>
-#include <boost/geometry/algorithms/covered_by.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
+#include <boost/geometry/geometries/helper_geometry.hpp>
+
#include <boost/geometry/algorithms/for_each.hpp>
@@ -46,7 +48,8 @@ inline bool point_on_border_covered_by(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
- typename geometry::point_type<Geometry1>::type pt;
+ using point_type = typename geometry::point_type<Geometry1>::type;
+ typename helper_geometry<point_type>::type pt;
return geometry::point_on_border(pt, geometry1)
&& geometry::covered_by(pt, geometry2, strategy);
}
diff --git a/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp b/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp
index 0a1513fbed..8d71dd2e34 100644
--- a/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp
@@ -5,11 +5,12 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2021.
-// Modifications copyright (c) 2013-2021, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022, Oracle and/or its affiliates.
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, 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
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -36,11 +37,10 @@
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
-#include <boost/geometry/algorithms/covered_by.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
@@ -51,6 +51,7 @@
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
+#include <boost/geometry/geometries/helper_geometry.hpp>
namespace boost { namespace geometry
{
@@ -70,8 +71,8 @@ struct disjoint_no_intersections_policy
template <typename Strategy>
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
- typedef typename point_type<Geometry1>::type point1_type;
- point1_type p;
+ using point_type = typename point_type<Geometry1>::type;
+ typename helper_geometry<point_type>::type p;
geometry::point_on_border(p, g1);
return ! geometry::covered_by(p, g2, strategy);
@@ -88,12 +89,11 @@ struct disjoint_no_intersections_policy<Geometry1, Geometry2, Tag1, multi_tag>
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
// TODO: use partition or rtree on g2
- typedef typename boost::range_iterator<Geometry1 const>::type iterator;
- for ( iterator it = boost::begin(g1) ; it != boost::end(g1) ; ++it )
+ for (auto it = boost::begin(g1); it != boost::end(g1); ++it)
{
typedef typename boost::range_value<Geometry1 const>::type value_type;
- if ( ! disjoint_no_intersections_policy<value_type const, Geometry2>
- ::apply(*it, g2, strategy) )
+ if (! disjoint_no_intersections_policy<value_type const, Geometry2>
+ ::apply(*it, g2, strategy))
{
return false;
}
@@ -141,28 +141,25 @@ struct disjoint_segment_areal
template <typename Segment, typename Polygon>
class disjoint_segment_areal<Segment, Polygon, polygon_tag>
{
-private:
+
template <typename InteriorRings, typename Strategy>
static inline
bool check_interior_rings(InteriorRings const& interior_rings,
Segment const& segment,
Strategy const& strategy)
{
- typedef typename boost::range_value<InteriorRings>::type ring_type;
+ using ring_type = typename boost::range_value<InteriorRings>::type;
- typedef unary_disjoint_geometry_to_query_geometry
+ using unary_predicate_type = unary_disjoint_geometry_to_query_geometry
<
Segment,
Strategy,
disjoint_range_segment_or_box<ring_type, Segment>
- > unary_predicate_type;
-
- return check_iterator_range
- <
- unary_predicate_type
- >::apply(boost::begin(interior_rings),
- boost::end(interior_rings),
- unary_predicate_type(segment, strategy));
+ >;
+
+ return std::all_of(boost::begin(interior_rings),
+ boost::end(interior_rings),
+ unary_predicate_type(segment, strategy));
}
diff --git a/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp b/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp
index fc8e6a3511..00a6bff82d 100644
--- a/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp
@@ -33,6 +33,8 @@
#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
#include <boost/geometry/algorithms/detail/overlay/segment_as_subrange.hpp>
+#include <boost/geometry/geometries/helper_geometry.hpp>
+
#include <boost/geometry/policies/disjoint_interrupt_policy.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
@@ -91,20 +93,21 @@ struct disjoint_linear
Geometry2 const& geometry2,
Strategy const& strategy)
{
- typedef typename geometry::point_type<Geometry1>::type point_type;
- typedef geometry::segment_ratio
+ using point_type = typename geometry::point_type<Geometry1>::type;
+ using mutable_point_type = typename helper_geometry<point_type>::type;
+ using ratio_type = geometry::segment_ratio
<
typename coordinate_type<point_type>::type
- > ratio_type;
- typedef overlay::turn_info
+ > ;
+ using turn_info_type = overlay::turn_info
<
- point_type,
+ mutable_point_type,
ratio_type,
typename detail::get_turns::turn_operation_type
<
- Geometry1, Geometry2, ratio_type
+ Geometry1, Geometry2, mutable_point_type, ratio_type
>::type
- > turn_info_type;
+ >;
std::deque<turn_info_type> turns;
diff --git a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
index 9e3a57a29e..535c9006b5 100644
--- a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
@@ -2,7 +2,9 @@
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -31,7 +33,6 @@
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/expand.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
@@ -62,25 +63,25 @@ namespace detail { namespace disjoint
class multipoint_multipoint
{
private:
- template <typename Iterator, typename CSTag>
- class unary_disjoint_predicate
- : geometry::less<void, -1, CSTag>
+ template <typename Iterator, typename Strategy>
+ class unary_not_disjoint_predicate
+ : geometry::less<void, -1, Strategy>
{
private:
- typedef geometry::less<void, -1, CSTag> base_type;
+ using less_type = geometry::less<void, -1, Strategy>;
public:
- unary_disjoint_predicate(Iterator first, Iterator last)
- : base_type(), m_first(first), m_last(last)
+ unary_not_disjoint_predicate(Iterator first, Iterator last)
+ : less_type(), m_first(first), m_last(last)
{}
template <typename Point>
- inline bool apply(Point const& point) const
+ inline bool operator()(Point const& point) const
{
- return !std::binary_search(m_first,
- m_last,
- point,
- static_cast<base_type const&>(*this));
+ return std::binary_search(m_first,
+ m_last,
+ point,
+ static_cast<less_type const&>(*this));
}
private:
@@ -93,30 +94,25 @@ public:
MultiPoint2 const& multipoint2,
Strategy const&)
{
- typedef typename Strategy::cs_tag cs_tag;
- typedef geometry::less<void, -1, cs_tag> less_type;
-
BOOST_GEOMETRY_ASSERT( boost::size(multipoint1) <= boost::size(multipoint2) );
- typedef typename boost::range_value<MultiPoint1>::type point1_type;
+ using less_type = geometry::less<void, -1, Strategy>;
+ using point1_type = typename boost::range_value<MultiPoint1>::type;
std::vector<point1_type> points1(boost::begin(multipoint1),
boost::end(multipoint1));
std::sort(points1.begin(), points1.end(), less_type());
- typedef unary_disjoint_predicate
+ using predicate_type = unary_not_disjoint_predicate
<
typename std::vector<point1_type>::const_iterator,
- cs_tag
- > predicate_type;
+ Strategy
+ >;
- return check_iterator_range
- <
- predicate_type
- >::apply(boost::begin(multipoint2),
- boost::end(multipoint2),
- predicate_type(points1.begin(), points1.end()));
+ return none_of(boost::begin(multipoint2),
+ boost::end(multipoint2),
+ predicate_type(points1.begin(), points1.end()));
}
};
@@ -289,13 +285,12 @@ public:
typedef typename point_type<MultiPoint>::type point1_type;
typedef typename point_type<SingleGeometry>::type point2_type;
typedef model::box<point2_type> box2_type;
-
+
box2_type box2;
geometry::envelope(single_geometry, box2, strategy);
geometry::detail::expand_by_epsilon(box2);
- typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
- for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
+ for (auto it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it)
{
// The default strategy is enough for Point/Box
if (! detail::disjoint::disjoint_point_box(*it, box2, strategy)
@@ -434,7 +429,7 @@ public:
typedef model::box<point1_type> box1_type;
typedef model::box<point2_type> box2_type;
typedef std::pair<box2_type, std::size_t> box_pair_type;
-
+
std::size_t count2 = boost::size(multi_geometry);
std::vector<box_pair_type> boxes(count2);
for (std::size_t i = 0 ; i < count2 ; ++i)
@@ -533,7 +528,7 @@ struct disjoint
{
return detail::disjoint::multipoint_multipoint
::apply(multipoint2, multipoint1, strategy);
- }
+ }
return detail::disjoint::multipoint_multipoint
::apply(multipoint1, multipoint2, strategy);
diff --git a/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp
index 51945551bb..2dccbae934 100644
--- a/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -11,12 +12,12 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP
+#include <algorithm>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/value_type.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
@@ -34,13 +35,13 @@ class unary_disjoint_geometry_to_query_geometry
{
public:
unary_disjoint_geometry_to_query_geometry(Geometry const& geometry,
- Strategy const& strategy)
+ Strategy const& strategy)
: m_geometry(geometry)
, m_strategy(strategy)
{}
template <typename QueryGeometry>
- inline bool apply(QueryGeometry const& query_geometry) const
+ inline bool operator()(QueryGeometry const& query_geometry) const
{
return BinaryPredicate::apply(query_geometry, m_geometry, m_strategy);
}
@@ -59,7 +60,7 @@ struct multirange_constant_size_geometry
ConstantSizeGeometry const& constant_size_geometry,
Strategy const& strategy)
{
- typedef unary_disjoint_geometry_to_query_geometry
+ using disjoint = unary_disjoint_geometry_to_query_geometry
<
ConstantSizeGeometry,
Strategy,
@@ -68,13 +69,11 @@ struct multirange_constant_size_geometry
typename boost::range_value<MultiRange>::type,
ConstantSizeGeometry
>
- > unary_predicate_type;
+ >;
- return detail::check_iterator_range
- <
- unary_predicate_type
- >::apply(boost::begin(multirange), boost::end(multirange),
- unary_predicate_type(constant_size_geometry, strategy));
+ return std::all_of(boost::begin(multirange),
+ boost::end(multirange),
+ disjoint(constant_size_geometry, strategy));
}
template <typename Strategy>
diff --git a/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp
index 66bd7c26ce..4e22ac3a00 100644
--- a/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -21,7 +21,7 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_GEOMETRY_HPP
-#include <boost/geometry/algorithms/covered_by.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
diff --git a/boost/geometry/algorithms/detail/disjoint/segment_box.hpp b/boost/geometry/algorithms/detail/disjoint/segment_box.hpp
index f6ba272690..1f2d669e53 100644
--- a/boost/geometry/algorithms/detail/disjoint/segment_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/segment_box.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2020.
-// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2021.
+// Modifications copyright (c) 2013-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -33,7 +33,6 @@
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
-#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/formulas/vertex_longitude.hpp>
diff --git a/boost/geometry/algorithms/detail/distance/geometry_collection.hpp b/boost/geometry/algorithms/detail/distance/geometry_collection.hpp
new file mode 100644
index 0000000000..f230958437
--- /dev/null
+++ b/boost/geometry/algorithms/detail/distance/geometry_collection.hpp
@@ -0,0 +1,237 @@
+// Boost.Geometry
+
+// Copyright (c) 2021 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_COLLECTION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_COLLECTION_HPP
+
+
+#include <vector>
+
+#include <boost/geometry/algorithms/dispatch/distance.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
+#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/index/rtree.hpp>
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/distance_result.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace distance
+{
+
+
+template <typename Geometry, typename GeometryCollection, typename Strategies>
+inline auto geometry_to_collection(Geometry const& geometry,
+ GeometryCollection const& collection,
+ Strategies const& strategies)
+{
+ using result_t = typename geometry::distance_result<Geometry, GeometryCollection, Strategies>::type;
+ result_t result = 0;
+ bool is_first = true;
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ result_t r = dispatch::distance
+ <
+ Geometry, util::remove_cref_t<decltype(g)>, Strategies
+ >::apply(geometry, g, strategies);
+ if (is_first)
+ {
+ result = r;
+ is_first = false;
+ }
+ else if (r < result)
+ {
+ result = r;
+ }
+ return result > result_t(0);
+ }, collection);
+
+ return result;
+}
+
+template <typename GeometryCollection1, typename GeometryCollection2, typename Strategies>
+inline auto collection_to_collection(GeometryCollection1 const& collection1,
+ GeometryCollection2 const& collection2,
+ Strategies const& strategies)
+{
+ using result_t = typename geometry::distance_result<GeometryCollection1, GeometryCollection2, Strategies>::type;
+
+ using point1_t = typename geometry::point_type<GeometryCollection1>::type;
+ using box1_t = model::box<point1_t>;
+ using point2_t = typename geometry::point_type<GeometryCollection2>::type;
+ using box2_t = model::box<point2_t>;
+
+ using rtree_value_t = std::pair<box1_t, typename boost::range_iterator<GeometryCollection1 const>::type>;
+ using rtree_params_t = index::parameters<index::rstar<4>, Strategies>;
+ using rtree_t = index::rtree<rtree_value_t, rtree_params_t>;
+
+ rtree_params_t rtree_params(index::rstar<4>(), strategies);
+ rtree_t rtree(rtree_params);
+
+ // Build rtree of boxes and iterators of elements of GC1
+ // TODO: replace this with visit_breadth_first_iterator to avoid creating an unnecessary container?
+ {
+ std::vector<rtree_value_t> values;
+ visit_breadth_first_impl<true>::apply([&](auto & g1, auto it)
+ {
+ box1_t b1 = geometry::return_envelope<box1_t>(g1, strategies);
+ geometry::detail::expand_by_epsilon(b1);
+ values.emplace_back(b1, it);
+ return true;
+ }, collection1);
+ rtree_t rt(values.begin(), values.end(), rtree_params);
+ rtree = std::move(rt);
+ }
+
+ result_t const zero = 0;
+ auto const rtree_qend = rtree.qend();
+
+ result_t result = 0;
+ bool is_first = true;
+ visit_breadth_first([&](auto const& g2)
+ {
+ box2_t b2 = geometry::return_envelope<box2_t>(g2, strategies);
+ geometry::detail::expand_by_epsilon(b2);
+
+ for (auto it = rtree.qbegin(index::nearest(b2, rtree.size())) ; it != rtree_qend ; ++it)
+ {
+ // If the distance between boxes is greater than or equal to previously found
+ // distance between geometries then stop processing the current b2 because no
+ // closer b1 will be found
+ if (! is_first)
+ {
+ result_t const bd = dispatch::distance
+ <
+ box1_t, box2_t, Strategies
+ >::apply(it->first, b2, strategies);
+ if (bd >= result)
+ {
+ break;
+ }
+ }
+
+ // Boxes are closer than the previously found distance (or it's the first time),
+ // calculate the new distance between geometries and check if it's closer (or assign it).
+ traits::iter_visit<GeometryCollection1>::apply([&](auto const& g1)
+ {
+ result_t const d = dispatch::distance
+ <
+ util::remove_cref_t<decltype(g1)>, util::remove_cref_t<decltype(g2)>,
+ Strategies
+ >::apply(g1, g2, strategies);
+ if (is_first)
+ {
+ result = d;
+ is_first = false;
+ }
+ else if (d < result)
+ {
+ result = d;
+ }
+ }, it->second);
+
+ // The smallest possible distance found, end searching.
+ if (! is_first && result <= zero)
+ {
+ return false;
+ }
+ }
+
+ // Just in case
+ return is_first || result > zero;
+ }, collection2);
+
+ return result;
+}
+
+
+}} // namespace detail::distance
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Geometry, typename GeometryCollection, typename Strategies, typename Tag1
+>
+struct distance
+ <
+ Geometry, GeometryCollection, Strategies,
+ Tag1, geometry_collection_tag, void, false
+ >
+{
+ static inline auto apply(Geometry const& geometry,
+ GeometryCollection const& collection,
+ Strategies const& strategies)
+ {
+ assert_dimension_equal<Geometry, GeometryCollection>();
+
+ return detail::distance::geometry_to_collection(geometry, collection, strategies);
+ }
+};
+
+template
+<
+ typename GeometryCollection, typename Geometry, typename Strategies, typename Tag2
+>
+struct distance
+ <
+ GeometryCollection, Geometry, Strategies,
+ geometry_collection_tag, Tag2, void, false
+ >
+{
+ static inline auto apply(GeometryCollection const& collection,
+ Geometry const& geometry,
+ Strategies const& strategies)
+ {
+ assert_dimension_equal<Geometry, GeometryCollection>();
+
+ return detail::distance::geometry_to_collection(geometry, collection, strategies);
+ }
+};
+
+template
+<
+ typename GeometryCollection1, typename GeometryCollection2, typename Strategies
+>
+struct distance
+ <
+ GeometryCollection1, GeometryCollection2, Strategies,
+ geometry_collection_tag, geometry_collection_tag, void, false
+ >
+{
+ static inline auto apply(GeometryCollection1 const& collection1,
+ GeometryCollection2 const& collection2,
+ Strategies const& strategies)
+ {
+ assert_dimension_equal<GeometryCollection1, GeometryCollection2>();
+
+ // Build the rtree for the smaller GC (ignoring recursive GCs)
+ return boost::size(collection1) <= boost::size(collection2)
+ ? detail::distance::collection_to_collection(collection1, collection2, strategies)
+ : detail::distance::collection_to_collection(collection2, collection1, strategies);
+ }
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
diff --git a/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp b/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp
index 6a852ec43f..5af854f901 100644
--- a/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp
+++ b/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp
@@ -54,7 +54,7 @@ template
>
struct segment_or_box_point_range_closure
: not_implemented<SegmentOrBox>
-{};
+{};
template <typename Segment>
struct segment_or_box_point_range_closure<Segment, segment_tag>
@@ -163,17 +163,11 @@ public:
Strategies const& strategies,
bool check_intersection = true)
{
- typedef geometry::point_iterator<Geometry const> point_iterator_type;
typedef geometry::segment_iterator
<
Geometry const
> segment_iterator_type;
- typedef typename boost::range_const_iterator
- <
- std::vector<segment_or_box_point>
- >::type seg_or_box_const_iterator;
-
typedef assign_new_min_iterator<SegmentOrBox> assign_new_value;
@@ -196,32 +190,27 @@ public:
assign_segment_or_box_points
<
- SegmentOrBox,
+ SegmentOrBox,
std::vector<segment_or_box_point>
>::apply(segment_or_box, seg_or_box_points);
// consider all distances of the points in the geometry to the
// segment or box
comparable_return_type cd_min1(0);
- point_iterator_type pit_min;
- seg_or_box_const_iterator it_min1 = boost::const_begin(seg_or_box_points);
- seg_or_box_const_iterator it_min2 = it_min1;
- ++it_min2;
+ auto pit_min = points_begin(geometry);
+ auto it_min1 = boost::const_begin(seg_or_box_points);
+ auto it_min2 = it_min1 + 1;
bool first = true;
- for (point_iterator_type pit = points_begin(geometry);
+ for (auto pit = pit_min;
pit != points_end(geometry); ++pit, first = false)
{
comparable_return_type cd;
- std::pair
- <
- seg_or_box_const_iterator, seg_or_box_const_iterator
- > it_pair
- = point_to_point_range::apply(*pit,
- boost::const_begin(seg_or_box_points),
- boost::const_end(seg_or_box_points),
- cstrategy,
- cd);
+ auto it_pair = point_to_point_range::apply(*pit,
+ boost::const_begin(seg_or_box_points),
+ boost::const_end(seg_or_box_points),
+ cstrategy,
+ cd);
if (first || cd < cd_min1)
{
@@ -236,10 +225,10 @@ public:
// segments of the geometry
comparable_return_type cd_min2(0);
segment_iterator_type sit_min;
- seg_or_box_const_iterator it_min;
+ auto it_min = boost::const_begin(seg_or_box_points);
first = true;
- for (seg_or_box_const_iterator it = boost::const_begin(seg_or_box_points);
+ for (auto it = boost::const_begin(seg_or_box_points);
it != boost::const_end(seg_or_box_points); ++it, first = false)
{
comparable_return_type cd;
@@ -282,7 +271,7 @@ public:
}
- static inline return_type apply(SegmentOrBox const& segment_or_box, Geometry const& geometry,
+ static inline return_type apply(SegmentOrBox const& segment_or_box, Geometry const& geometry,
Strategies const& strategies, bool check_intersection = true)
{
return apply(geometry, segment_or_box, strategies, check_intersection);
@@ -299,14 +288,7 @@ class geometry_to_segment_or_box
{
private:
typedef detail::closest_feature::geometry_to_range base_type;
-
- typedef typename boost::range_iterator
- <
- MultiPoint const
- >::type iterator_type;
-
typedef detail::closest_feature::geometry_to_range geometry_to_range;
-
typedef distance::strategy_t<MultiPoint, SegmentOrBox, Strategies> strategy_type;
public:
@@ -318,7 +300,7 @@ public:
{
distance::creturn_t<MultiPoint, SegmentOrBox, Strategies> cd_min;
- iterator_type it_min
+ auto const it_min
= geometry_to_range::apply(segment_or_box,
boost::begin(multipoint),
boost::end(multipoint),
diff --git a/boost/geometry/algorithms/detail/distance/implementation.hpp b/boost/geometry/algorithms/detail/distance/implementation.hpp
index 91b1d817b3..8dfe4fec7e 100644
--- a/boost/geometry/algorithms/detail/distance/implementation.hpp
+++ b/boost/geometry/algorithms/detail/distance/implementation.hpp
@@ -7,9 +7,9 @@
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
-
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, 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
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -27,6 +27,7 @@
#include <boost/geometry/algorithms/detail/distance/linear_to_linear.hpp>
#include <boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp>
#include <boost/geometry/algorithms/detail/distance/linear_to_box.hpp>
+#include <boost/geometry/algorithms/detail/distance/geometry_collection.hpp>
#include <boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp>
#include <boost/geometry/algorithms/detail/distance/segment_to_segment.hpp>
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
diff --git a/boost/geometry/algorithms/detail/distance/interface.hpp b/boost/geometry/algorithms/detail/distance/interface.hpp
index f39f505544..5fdb66beaf 100644
--- a/boost/geometry/algorithms/detail/distance/interface.hpp
+++ b/boost/geometry/algorithms/detail/distance/interface.hpp
@@ -8,7 +8,6 @@
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
-
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -28,6 +27,7 @@
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/core/point_type.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>
@@ -92,10 +92,9 @@ template
struct distance
{
template <typename Geometry1, typename Geometry2>
- static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
- apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
+ static inline auto apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
return dispatch::distance
<
@@ -123,11 +122,9 @@ struct distance<Strategy, false>
typename Geometry1, typename Geometry2, typename S,
std::enable_if_t<is_strategy_converter_specialized<S>::value, int> = 0
>
- static inline
- typename distance_result<Geometry1, Geometry2, S>::type
- apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- S const& strategy)
+ static inline auto apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ S const& strategy)
{
typedef strategies::distance::services::strategy_converter<Strategy> converter;
typedef decltype(converter::get(strategy)) strategy_type;
@@ -143,11 +140,9 @@ struct distance<Strategy, false>
typename Geometry1, typename Geometry2, typename S,
std::enable_if_t<! is_strategy_converter_specialized<S>::value, int> = 0
>
- static inline
- typename distance_result<Geometry1, Geometry2, S>::type
- apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- S const& strategy)
+ static inline auto apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ S const& strategy)
{
typedef strategies::distance::services::custom_strategy_converter
<
@@ -166,11 +161,9 @@ template <>
struct distance<default_strategy, false>
{
template <typename Geometry1, typename Geometry2>
- static inline
- typename distance_result<Geometry1, Geometry2, default_strategy>::type
- apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- default_strategy)
+ static inline auto apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ default_strategy)
{
typedef typename strategies::distance::services::default_strategy
<
@@ -187,18 +180,22 @@ struct distance<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant
+namespace resolve_dynamic
{
-template <typename Geometry1, typename Geometry2>
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct distance
{
template <typename Strategy>
- static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
- apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
+ static inline auto apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
return resolve_strategy::distance
<
@@ -208,174 +205,72 @@ struct distance
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct distance<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
+struct distance<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Strategy>
- struct visitor: static_visitor
- <
- typename distance_result
- <
- variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
- Geometry2,
- Strategy
- >::type
- >
+ static inline auto apply(DynamicGeometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2,
- Strategy const& strategy)
- : m_geometry2(geometry2),
- m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- typename distance_result<Geometry1, Geometry2, Strategy>::type
- operator()(Geometry1 const& geometry1) const
+ using result_t = typename geometry::distance_result<DynamicGeometry1, Geometry2, Strategy>::type;
+ result_t result = 0;
+ traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
{
- return distance
- <
- Geometry1,
- Geometry2
- >::template apply
- <
- Strategy
- >(geometry1, m_geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline typename distance_result
- <
- variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
- Geometry2,
- Strategy
- >::type
- apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
+ result = resolve_strategy::distance
+ <
+ Strategy
+ >::apply(g1, geometry2, strategy);
+ }, geometry1);
+ return result;
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct distance<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
+struct distance<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: static_visitor
- <
- typename distance_result
- <
- Geometry1,
- variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
- Strategy
- >::type
- >
+ static inline auto apply(Geometry1 const& geometry1,
+ DynamicGeometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1,
- Strategy const& strategy)
- : m_geometry1(geometry1),
- m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- typename distance_result<Geometry1, Geometry2, Strategy>::type
- operator()(Geometry2 const& geometry2) const
+ using result_t = typename geometry::distance_result<Geometry1, DynamicGeometry2, Strategy>::type;
+ result_t result = 0;
+ traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
{
- return distance
- <
- Geometry1,
- Geometry2
- >::template apply
- <
- Strategy
- >(m_geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline typename distance_result
- <
- Geometry1,
- variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
- Strategy
- >::type
- apply(
- Geometry1 const& geometry1,
- const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
+ result = resolve_strategy::distance
+ <
+ Strategy
+ >::apply(geometry1, g2, strategy);
+ }, geometry2);
+ return result;
}
};
-template
-<
- BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)
->
-struct distance
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
- >
+template <typename DynamicGeometry1, typename DynamicGeometry2>
+struct distance<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: static_visitor
- <
- typename distance_result
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
- Strategy
- >::type
- >
+ static inline auto apply(DynamicGeometry1 const& geometry1,
+ DynamicGeometry2 const& geometry2,
+ Strategy const& strategy)
{
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy)
- : m_strategy(strategy)
- {}
-
- template <typename Geometry1, typename Geometry2>
- typename distance_result<Geometry1, Geometry2, Strategy>::type
- operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const
+ using result_t = typename geometry::distance_result<DynamicGeometry1, DynamicGeometry2, Strategy>::type;
+ result_t result = 0;
+ traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
{
- return distance
- <
- Geometry1,
- Geometry2
- >::template apply
- <
- Strategy
- >(geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline typename distance_result
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
- Strategy
- >::type
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
+ result = resolve_strategy::distance
+ <
+ Strategy
+ >::apply(g1, g2, strategy);
+ }, geometry1, geometry2);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
@@ -415,10 +310,9 @@ for distance, it is probably so that there is no specialization
for return_type<...> for your strategy.
*/
template <typename Geometry1, typename Geometry2, typename Strategy>
-inline typename distance_result<Geometry1, Geometry2, Strategy>::type
-distance(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
+inline auto distance(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
@@ -426,7 +320,7 @@ distance(Geometry1 const& geometry1,
detail::throw_on_empty_input(geometry1);
detail::throw_on_empty_input(geometry2);
- return resolve_variant::distance
+ return resolve_dynamic::distance
<
Geometry1,
Geometry2
@@ -448,13 +342,9 @@ distance(Geometry1 const& geometry1,
\qbk{[include reference/algorithms/distance.qbk]}
*/
template <typename Geometry1, typename Geometry2>
-inline typename default_distance_result<Geometry1, Geometry2>::type
-distance(Geometry1 const& geometry1,
- Geometry2 const& geometry2)
+inline auto distance(Geometry1 const& geometry1,
+ Geometry2 const& geometry2)
{
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
-
return geometry::distance(geometry1, geometry2, default_strategy());
}
diff --git a/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp b/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp
index e4cb41a358..dc1f4786b5 100644
--- a/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp
+++ b/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp
@@ -91,7 +91,7 @@ template <typename Linear, typename Areal, typename Strategy>
struct distance
<
Linear, Areal, Strategy,
- linear_tag, areal_tag,
+ linear_tag, areal_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::linear_to_areal
@@ -104,7 +104,7 @@ template <typename Areal, typename Linear, typename Strategy>
struct distance
<
Areal, Linear, Strategy,
- areal_tag, linear_tag,
+ areal_tag, linear_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::linear_to_areal
@@ -118,7 +118,7 @@ template <typename Areal1, typename Areal2, typename Strategy>
struct distance
<
Areal1, Areal2, Strategy,
- areal_tag, areal_tag,
+ areal_tag, areal_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::areal_to_areal
diff --git a/boost/geometry/algorithms/detail/distance/linear_to_linear.hpp b/boost/geometry/algorithms/detail/distance/linear_to_linear.hpp
index eb81133f61..0c3e68051b 100644
--- a/boost/geometry/algorithms/detail/distance/linear_to_linear.hpp
+++ b/boost/geometry/algorithms/detail/distance/linear_to_linear.hpp
@@ -102,7 +102,7 @@ template <typename Linear1, typename Linear2, typename Strategy, typename Strate
struct distance
<
Linear1, Linear2, Strategy,
- linear_tag, linear_tag,
+ linear_tag, linear_tag,
StrategyTag, false
> : detail::distance::linear_to_linear
<
diff --git a/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp b/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp
index eabc9528db..58a9d5b283 100644
--- a/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp
+++ b/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2021 Oracle and/or its affiliates.
+// Copyright (c) 2014-2021, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -16,7 +17,6 @@
#include <boost/range/size.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp>
#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
@@ -46,7 +46,6 @@ struct multipoint_to_multipoint
Strategies const& strategies)
{
if (boost::size(multipoint2) < boost::size(multipoint1))
-
{
return point_or_segment_range_to_geometry_rtree
<
@@ -103,16 +102,16 @@ template <typename MultiPoint, typename Areal, typename Strategies>
class multipoint_to_areal
{
private:
- struct not_covered_by_areal
+ struct covered_by_areal
{
- not_covered_by_areal(Areal const& areal, Strategies const& strategy)
+ covered_by_areal(Areal const& areal, Strategies const& strategy)
: m_areal(areal), m_strategy(strategy)
{}
template <typename Point>
- inline bool apply(Point const& point) const
+ inline bool operator()(Point const& point) const
{
- return !geometry::covered_by(point, m_areal, m_strategy);
+ return geometry::covered_by(point, m_areal, m_strategy);
}
Areal const& m_areal;
@@ -126,14 +125,10 @@ public:
Areal const& areal,
Strategies const& strategies)
{
- not_covered_by_areal predicate(areal, strategies);
+ covered_by_areal predicate(areal, strategies);
- if (check_iterator_range
- <
- not_covered_by_areal, false
- >::apply(boost::begin(multipoint),
- boost::end(multipoint),
- predicate))
+ if (! boost::empty(multipoint) &&
+ std::none_of(boost::begin(multipoint), boost::end(multipoint), predicate))
{
return detail::distance::point_or_segment_range_to_geometry_rtree
<
diff --git a/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp b/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp
index b76955cb63..cd7c46ce71 100644
--- a/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp
+++ b/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp
@@ -95,7 +95,7 @@ public:
:
dispatch::distance
<
- point_or_segment_type,
+ point_or_segment_type,
typename std::iterator_traits
<
typename selector_type::iterator_type
diff --git a/boost/geometry/algorithms/detail/distance/segment_to_box.hpp b/boost/geometry/algorithms/detail/distance/segment_to_box.hpp
index 354d42bd01..09f3cc4f61 100644
--- a/boost/geometry/algorithms/detail/distance/segment_to_box.hpp
+++ b/boost/geometry/algorithms/detail/distance/segment_to_box.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2021 Oracle and/or its affiliates.
+// Copyright (c) 2014-2023 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -91,7 +91,7 @@ private:
std::vector<box_point>,
open
> point_to_point_range;
-
+
public:
// TODO: Or should the return type be defined by sb_strategy_type?
typedef distance::return_t<box_point, Segment, Strategies> return_type;
@@ -114,7 +114,7 @@ public:
// get box points
std::vector<box_point> box_points(4);
detail::assign_box_corners_oriented<true>(box, box_points);
-
+
ps_strategy_type const strategy = strategies.distance(dummy_point(), dummy_segment());
auto const cstrategy = strategy::distance::services::get_comparable
@@ -192,7 +192,7 @@ private:
public:
// TODO: Or should the return type be defined by sb_strategy_type?
typedef distance::return_t<box_point, Segment, Strategies> return_type;
-
+
static inline return_type apply(Segment const& segment,
Box const& box,
Strategies const& strategies,
@@ -658,7 +658,7 @@ public:
BoxPoint const& bottom_right,
Strategies const& strategies)
{
- BOOST_GEOMETRY_ASSERT( (geometry::less<SegmentPoint, -1, typename Strategies::cs_tag>()(p0, p1))
+ BOOST_GEOMETRY_ASSERT( (geometry::less<SegmentPoint, -1, Strategies>()(p0, p1))
|| geometry::has_nan_coordinate(p0)
|| geometry::has_nan_coordinate(p1) );
@@ -753,7 +753,7 @@ public:
bottom_left, bottom_right,
top_left, top_right);
- typedef geometry::less<segment_point, -1, typename Strategies::cs_tag> less_type;
+ typedef geometry::less<segment_point, -1, Strategies> less_type;
if (less_type()(p[0], p[1]))
{
return segment_to_box_2D
diff --git a/boost/geometry/algorithms/detail/envelope/areal.hpp b/boost/geometry/algorithms/detail/envelope/areal.hpp
index 3c9b5c576c..ece4d3d144 100644
--- a/boost/geometry/algorithms/detail/envelope/areal.hpp
+++ b/boost/geometry/algorithms/detail/envelope/areal.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2018 Oracle and/or its affiliates.
+// Copyright (c) 2018-2021 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
@@ -22,6 +22,8 @@
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
+#include <boost/geometry/views/reversible_view.hpp>
+
namespace boost { namespace geometry
{
@@ -29,6 +31,24 @@ namespace boost { namespace geometry
namespace detail { namespace envelope
{
+
+struct envelope_hole
+{
+ template <typename Range, typename Box, typename Strategies>
+ static inline void apply(Range const& range, Box& mbr, Strategies const& strategies)
+ {
+ // Reverse holes to avoid calculating the envelope for the outside
+ // in spherical and geographic coordinate systems
+ detail::clockwise_view
+ <
+ Range const,
+ geometry::point_order<Range>::value == counterclockwise
+ ? clockwise : counterclockwise
+ > view(range);
+ strategies.envelope(range, mbr).apply(view, mbr);
+ }
+};
+
struct envelope_polygon
{
template <typename Polygon, typename Box, typename Strategy>
@@ -39,11 +59,14 @@ struct envelope_polygon
if (geometry::is_empty(ext_ring))
{
+ // use dummy multi polygon to get the strategy because there is no multi ring concept
+ using strategy_t = decltype(strategy.envelope(detail::dummy_multi_polygon(),
+ detail::dummy_box()));
// if the exterior ring is empty, consider the interior rings
envelope_multi_range
<
- envelope_range
- >::apply(interior_rings(polygon), mbr, strategy);
+ envelope_hole
+ >::template apply<strategy_t>(interior_rings(polygon), mbr, strategy);
}
else
{
diff --git a/boost/geometry/algorithms/detail/envelope/geometry_collection.hpp b/boost/geometry/algorithms/detail/envelope/geometry_collection.hpp
new file mode 100644
index 0000000000..979513da7e
--- /dev/null
+++ b/boost/geometry/algorithms/detail/envelope/geometry_collection.hpp
@@ -0,0 +1,62 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_GEOMETRY_COLLECTION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_GEOMETRY_COLLECTION_HPP
+
+
+#include <boost/geometry/algorithms/detail/visit.hpp>
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>
+#include <boost/geometry/algorithms/is_empty.hpp>
+
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Collection>
+struct envelope<Collection, geometry_collection_tag>
+{
+ template <typename Geometry, typename Box, typename Strategies>
+ static inline void apply(Geometry const& geometry,
+ Box& mbr,
+ Strategies const& strategies)
+ {
+ using strategy_t = decltype(strategies.envelope(geometry, mbr));
+
+ typename strategy_t::template state<Box> state;
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ if (! geometry::is_empty(g))
+ {
+ Box b;
+ envelope<util::remove_cref_t<decltype(g)>>::apply(g, b, strategies);
+ strategy_t::apply(state, b);
+ }
+ return true;
+ }, geometry);
+ strategy_t::result(state, mbr);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_GEOMETRY_COLLECTION_HPP
diff --git a/boost/geometry/algorithms/detail/envelope/implementation.hpp b/boost/geometry/algorithms/detail/envelope/implementation.hpp
index 569c77b036..cb4108d163 100644
--- a/boost/geometry/algorithms/detail/envelope/implementation.hpp
+++ b/boost/geometry/algorithms/detail/envelope/implementation.hpp
@@ -6,9 +6,9 @@
// This file was modified by Oracle on 2015-2021.
// Modifications copyright (c) 2015-2021, Oracle and/or its affiliates.
-
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, 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
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -28,6 +28,7 @@
#include <boost/geometry/algorithms/detail/envelope/areal.hpp>
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
+#include <boost/geometry/algorithms/detail/envelope/geometry_collection.hpp>
#include <boost/geometry/algorithms/detail/envelope/linear.hpp>
#include <boost/geometry/algorithms/detail/envelope/multipoint.hpp>
#include <boost/geometry/algorithms/detail/envelope/point.hpp>
diff --git a/boost/geometry/algorithms/detail/envelope/interface.hpp b/boost/geometry/algorithms/detail/envelope/interface.hpp
index 3f6dece384..70679dd918 100644
--- a/boost/geometry/algorithms/detail/envelope/interface.hpp
+++ b/boost/geometry/algorithms/detail/envelope/interface.hpp
@@ -22,16 +22,14 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tag.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/strategies/default_strategy.hpp>
@@ -39,6 +37,7 @@
#include <boost/geometry/strategies/envelope/services.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
+#include <boost/geometry/util/type_traits_std.hpp>
namespace boost { namespace geometry
@@ -98,10 +97,10 @@ struct envelope<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant
+namespace resolve_dynamic
{
-template <typename Geometry>
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct envelope
{
template <typename Box, typename Strategy>
@@ -117,38 +116,22 @@ struct envelope
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct envelope<Geometry, dynamic_geometry_tag>
{
template <typename Box, typename Strategy>
- struct visitor: boost::static_visitor<void>
+ static inline void apply(Geometry const& geometry,
+ Box& box,
+ Strategy const& strategy)
{
- Box& m_box;
- Strategy const& m_strategy;
-
- visitor(Box& box, Strategy const& strategy)
- : m_box(box)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry>
- void operator()(Geometry const& geometry) const
+ traits::visit<Geometry>::apply([&](auto const& g)
{
- envelope<Geometry>::apply(geometry, m_box, m_strategy);
- }
- };
-
- template <typename Box, typename Strategy>
- static inline void
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- Box& box,
- Strategy const& strategy)
- {
- boost::apply_visitor(visitor<Box, Strategy>(box, strategy), geometry);
+ envelope<util::remove_cref_t<decltype(g)>>::apply(g, box, strategy);
+ }, geometry);
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
@@ -172,7 +155,7 @@ struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template<typename Geometry, typename Box, typename Strategy>
inline void envelope(Geometry const& geometry, Box& mbr, Strategy const& strategy)
{
- resolve_variant::envelope<Geometry>::apply(geometry, mbr, strategy);
+ resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, strategy);
}
/*!
@@ -193,7 +176,7 @@ inline void envelope(Geometry const& geometry, Box& mbr, Strategy const& strateg
template<typename Geometry, typename Box>
inline void envelope(Geometry const& geometry, Box& mbr)
{
- resolve_variant::envelope<Geometry>::apply(geometry, mbr, default_strategy());
+ resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, default_strategy());
}
@@ -219,7 +202,7 @@ template<typename Box, typename Geometry, typename Strategy>
inline Box return_envelope(Geometry const& geometry, Strategy const& strategy)
{
Box mbr;
- resolve_variant::envelope<Geometry>::apply(geometry, mbr, strategy);
+ resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, strategy);
return mbr;
}
@@ -242,7 +225,7 @@ template<typename Box, typename Geometry>
inline Box return_envelope(Geometry const& geometry)
{
Box mbr;
- resolve_variant::envelope<Geometry>::apply(geometry, mbr, default_strategy());
+ resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, default_strategy());
return mbr;
}
diff --git a/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp b/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp
index 47937bf740..05127e0d23 100644
--- a/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp
+++ b/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp
@@ -19,7 +19,7 @@
#include <boost/geometry/algorithms/detail/normalize.hpp>
-namespace boost { namespace geometry
+namespace boost { namespace geometry
{
namespace detail { namespace envelope
@@ -38,7 +38,7 @@ struct intersects_antimeridian
<
CoordinateType, Units
> constants;
-
+
return
math::equals(math::abs(lat1), constants::max_latitude())
||
diff --git a/boost/geometry/algorithms/detail/envelope/range.hpp b/boost/geometry/algorithms/detail/envelope/range.hpp
index 068685b0ef..4692341e06 100644
--- a/boost/geometry/algorithms/detail/envelope/range.hpp
+++ b/boost/geometry/algorithms/detail/envelope/range.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2015-2020.
-// Modifications copyright (c) 2015-2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015-2021.
+// Modifications copyright (c) 2015-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -28,7 +28,7 @@
#include <boost/range/end.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
-
+#include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
#include <boost/geometry/algorithms/detail/expand/box.hpp>
#include <boost/geometry/algorithms/detail/expand/point.hpp>
@@ -47,42 +47,10 @@ namespace detail { namespace envelope
// implementation for simple ranges
struct envelope_range
{
- template <typename Iterator, typename Box, typename Strategy>
- static inline void apply(Iterator it,
- Iterator last,
- Box& mbr,
- Strategy const& strategy)
- {
- typedef typename std::iterator_traits<Iterator>::value_type value_type;
-
- // initialize MBR
- initialize<Box, 0, dimension<Box>::value>::apply(mbr);
-
- if (it != last)
- {
- // initialize box with first element in range
- dispatch::envelope
- <
- value_type
- >::apply(*it, mbr, strategy);
-
- // consider now the remaining elements in the range (if any)
- for (++it; it != last; ++it)
- {
- dispatch::expand
- <
- Box, value_type
- >::apply(mbr, *it, strategy);
- }
- }
- }
-
- template <typename Range, typename Box, typename Strategy>
- static inline void apply(Range const& range, Box& mbr, Strategy const& strategy)
+ template <typename Range, typename Box, typename Strategies>
+ static inline void apply(Range const& range, Box& mbr, Strategies const& strategies)
{
- using strategy_t = decltype(strategy.envelope(range, mbr));
- return apply(strategy_t::begin(range), strategy_t::end(range),
- mbr, strategy);
+ strategies.envelope(range, mbr).apply(range, mbr);
}
};
@@ -91,35 +59,32 @@ struct envelope_range
template <typename EnvelopePolicy>
struct envelope_multi_range
{
- template <typename MultiRange, typename Box, typename Strategy>
+ template <typename MultiRange, typename Box, typename Strategies>
static inline void apply(MultiRange const& multirange,
Box& mbr,
- Strategy const& strategy)
+ Strategies const& strategies)
{
- using range_t = typename boost::range_value<MultiRange>::type;
- using strategy_t = decltype(strategy.envelope(std::declval<range_t>(), mbr));
- using state_t = typename strategy_t::template multi_state<Box>;
- apply<state_t>(boost::begin(multirange), boost::end(multirange), mbr, strategy);
+ using strategy_t = decltype(strategies.envelope(multirange, mbr));
+ apply<strategy_t>(multirange, mbr, strategies);
}
-private:
- template <typename State, typename Iter, typename Box, typename Strategy>
- static inline void apply(Iter it,
- Iter last,
+ template <typename Strategy, typename MultiRange, typename Box, typename Strategies>
+ static inline void apply(MultiRange const& multirange,
Box& mbr,
- Strategy const& strategy)
+ Strategies const& strategies)
{
- State state;
- for (; it != last; ++it)
+ typename Strategy::template state<Box> state;
+ auto const end = boost::end(multirange);
+ for (auto it = boost::begin(multirange); it != end; ++it)
{
if (! geometry::is_empty(*it))
{
Box helper_mbr;
- EnvelopePolicy::apply(*it, helper_mbr, strategy);
- state.apply(helper_mbr);
+ EnvelopePolicy::apply(*it, helper_mbr, strategies);
+ Strategy::apply(state, helper_mbr);
}
}
- state.result(mbr);
+ Strategy::result(state, mbr);
}
};
diff --git a/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp b/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp
index c55be03435..04032c6237 100644
--- a/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp
+++ b/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp
@@ -59,7 +59,7 @@ public:
longitude_interval(T const& left, T const& right)
{
m_end[0] = left;
- m_end[1] = right;
+ m_end[1] = right;
}
template <std::size_t Index>
@@ -162,11 +162,6 @@ struct envelope_range_of_boxes_by_expansion
{
typedef typename boost::range_value<RangeOfBoxes>::type box_type;
- typedef typename boost::range_iterator
- <
- RangeOfBoxes const
- >::type iterator_type;
-
// first initialize MBR
detail::indexed_point_view<Box, min_corner> mbr_min(mbr);
detail::indexed_point_view<Box, max_corner> mbr_max(mbr);
@@ -194,7 +189,7 @@ struct envelope_range_of_boxes_by_expansion
>::apply(first_box_max, mbr_max);
// now expand using the remaining boxes
- iterator_type it = boost::begin(range_of_boxes);
+ auto it = boost::begin(range_of_boxes);
for (++it; it != boost::end(range_of_boxes); ++it)
{
detail::expand::indexed_loop
@@ -237,10 +232,6 @@ struct envelope_range_of_boxes
typedef typename boost::range_value<RangeOfBoxes>::type box_type;
typedef typename coordinate_type<box_type>::type coordinate_type;
typedef typename detail::cs_angular_units<box_type>::type units_type;
- typedef typename boost::range_iterator
- <
- RangeOfBoxes const
- >::type iterator_type;
static const bool is_equatorial = ! std::is_same
<
@@ -258,39 +249,40 @@ struct envelope_range_of_boxes
BOOST_GEOMETRY_ASSERT(! boost::empty(range_of_boxes));
- iterator_type it_min = std::min_element(boost::begin(range_of_boxes),
- boost::end(range_of_boxes),
- latitude_less<min_corner>());
- iterator_type it_max = std::max_element(boost::begin(range_of_boxes),
- boost::end(range_of_boxes),
- latitude_less<max_corner>());
+ auto const it_min = std::min_element(boost::begin(range_of_boxes),
+ boost::end(range_of_boxes),
+ latitude_less<min_corner>());
+ auto const it_max = std::max_element(boost::begin(range_of_boxes),
+ boost::end(range_of_boxes),
+ latitude_less<max_corner>());
coordinate_type const min_longitude = constants::min_longitude();
coordinate_type const max_longitude = constants::max_longitude();
coordinate_type const period = constants::period();
interval_range_type intervals;
- for (iterator_type it = boost::begin(range_of_boxes);
+ for (auto it = boost::begin(range_of_boxes);
it != boost::end(range_of_boxes);
++it)
{
- if (is_inverse_spheroidal_coordinates(*it))
+ auto const& box = *it;
+ if (is_inverse_spheroidal_coordinates(box))
{
continue;
}
- coordinate_type lat_min = geometry::get<min_corner, 1>(*it);
- coordinate_type lat_max = geometry::get<max_corner, 1>(*it);
+ coordinate_type lat_min = geometry::get<min_corner, 1>(box);
+ coordinate_type lat_max = geometry::get<max_corner, 1>(box);
if (math::equals(lat_min, constants::max_latitude())
|| math::equals(lat_max, constants::min_latitude()))
{
// if the box degenerates to the south or north pole
// just ignore it
continue;
- }
+ }
- coordinate_type lon_left = geometry::get<min_corner, 0>(*it);
- coordinate_type lon_right = geometry::get<max_corner, 0>(*it);
+ coordinate_type lon_left = geometry::get<min_corner, 0>(box);
+ coordinate_type lon_right = geometry::get<max_corner, 0>(box);
if (math::larger(lon_right, max_longitude))
{
diff --git a/boost/geometry/algorithms/detail/equals/collect_vectors.hpp b/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
index f2e1c7eb49..b908c3e535 100644
--- a/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
+++ b/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
@@ -22,7 +22,6 @@
#include <boost/numeric/conversion/cast.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
@@ -39,7 +38,6 @@
#include <boost/geometry/views/detail/closed_clockwise_view.hpp>
-#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
#include <boost/geometry/strategies/normalize.hpp>
@@ -47,34 +45,17 @@
namespace boost { namespace geometry
{
-// Since these vectors (though ray would be a better name) are used in the
-// implementation of equals() for Areal geometries the internal representation
-// should be consistent with the side strategy.
-template
-<
- typename T,
- typename Geometry,
- typename SideStrategy,
- typename CSTag = typename cs_tag<Geometry>::type
->
-struct collected_vector
- : nyi::not_implemented_tag
-{};
-// compatible with side_by_triangle cartesian strategy
-template <typename T, typename Geometry, typename CT, typename CSTag>
-struct collected_vector
- <
- T, Geometry, strategy::side::side_by_triangle<CT>, CSTag
- >
+template <typename T>
+struct collected_vector_cartesian
{
typedef T type;
-
- inline collected_vector()
+
+ inline collected_vector_cartesian()
{}
- inline collected_vector(T const& px, T const& py,
- T const& pdx, T const& pdy)
+ inline collected_vector_cartesian(T const& px, T const& py,
+ T const& pdx, T const& pdy)
: x(px)
, y(py)
, dx(pdx)
@@ -84,7 +65,7 @@ struct collected_vector
{}
template <typename Point>
- inline collected_vector(Point const& p1, Point const& p2)
+ inline collected_vector_cartesian(Point const& p1, Point const& p2)
: x(get<0>(p1))
, y(get<1>(p1))
, dx(get<0>(p2) - x)
@@ -95,8 +76,7 @@ struct collected_vector
bool normalize()
{
- T magnitude = math::sqrt(
- boost::numeric_cast<T>(dx * dx + dy * dy));
+ T magnitude = math::sqrt(boost::numeric_cast<T>(dx * dx + dy * dy));
// NOTE: shouldn't here math::equals() be called?
if (magnitude > 0)
@@ -110,7 +90,7 @@ struct collected_vector
}
// For sorting
- inline bool operator<(collected_vector const& other) const
+ inline bool operator<(collected_vector_cartesian const& other) const
{
if (math::equals(x, other.x))
{
@@ -127,13 +107,13 @@ struct collected_vector
return x < other.x;
}
- inline bool next_is_collinear(collected_vector const& other) const
+ inline bool next_is_collinear(collected_vector_cartesian const& other) const
{
return same_direction(other);
}
// For std::equals
- inline bool operator==(collected_vector const& other) const
+ inline bool operator==(collected_vector_cartesian const& other) const
{
return math::equals(x, other.x)
&& math::equals(y, other.y)
@@ -141,7 +121,7 @@ struct collected_vector
}
private:
- inline bool same_direction(collected_vector const& other) const
+ inline bool same_direction(collected_vector_cartesian const& other) const
{
// For high precision arithmetic, we have to be
// more relaxed then using ==
@@ -159,38 +139,32 @@ private:
// Compatible with spherical_side_formula which currently
// is the default spherical_equatorial and geographic strategy
// so CSTag is spherical_equatorial_tag or geographic_tag
-template <typename T, typename Geometry, typename CT, typename CSTag>
-struct collected_vector
- <
- T, Geometry, strategy::side::spherical_side_formula<CT>, CSTag
- >
+template <typename T, typename Point>
+struct collected_vector_spherical
{
typedef T type;
-
- typedef typename geometry::detail::cs_angular_units<Geometry>::type units_type;
- typedef model::point<T, 2, cs::spherical_equatorial<units_type> > point_type;
+
typedef model::point<T, 3, cs::cartesian> vector_type;
- collected_vector()
+ collected_vector_spherical()
{}
- template <typename Point>
- collected_vector(Point const& p1, Point const& p2)
+ collected_vector_spherical(Point const& p1, Point const& p2)
: origin(get<0>(p1), get<1>(p1))
{
- origin = detail::return_normalized<point_type>(
+ origin = detail::return_normalized<Point>(
origin,
strategy::normalize::spherical_point());
using namespace geometry::formula;
prev = sph_to_cart3d<vector_type>(p1);
next = sph_to_cart3d<vector_type>(p2);
- direction = cross_product(prev, next);
+ cross = direction = cross_product(prev, next);
}
bool normalize()
{
- T magnitude_sqr = dot_product(direction, direction);
+ T const magnitude_sqr = dot_product(direction, direction);
// NOTE: shouldn't here math::equals() be called?
if (magnitude_sqr > 0)
@@ -202,7 +176,7 @@ struct collected_vector
return false;
}
- bool operator<(collected_vector const& other) const
+ bool operator<(collected_vector_spherical const& other) const
{
if (math::equals(get<0>(origin), get<0>(other.origin)))
{
@@ -226,13 +200,13 @@ struct collected_vector
// For consistency with side and intersection strategies used by relops
// IMPORTANT: this method should be called for previous vector
// and next vector should be passed as parameter
- bool next_is_collinear(collected_vector const& other) const
+ bool next_is_collinear(collected_vector_spherical const& other) const
{
- return formula::sph_side_value(direction, other.next) == 0;
+ return formula::sph_side_value(cross, other.next) == 0;
}
// For std::equals
- bool operator==(collected_vector const& other) const
+ bool operator==(collected_vector_spherical const& other) const
{
return math::equals(get<0>(origin), get<0>(other.origin))
&& math::equals(get<1>(origin), get<1>(other.origin))
@@ -241,76 +215,57 @@ struct collected_vector
private:
// For consistency with side and intersection strategies used by relops
- bool is_collinear(collected_vector const& other) const
+ // NOTE: alternative would be to equal-compare direction's coordinates
+ // or to check if dot product of directions is equal to 1.
+ bool is_collinear(collected_vector_spherical const& other) const
{
- return formula::sph_side_value(direction, other.prev) == 0
- && formula::sph_side_value(direction, other.next) == 0;
+ return formula::sph_side_value(cross, other.prev) == 0
+ && formula::sph_side_value(cross, other.next) == 0;
}
-
- /*bool same_direction(collected_vector const& other) const
- {
- return math::equals_with_epsilon(get<0>(direction), get<0>(other.direction))
- && math::equals_with_epsilon(get<1>(direction), get<1>(other.direction))
- && math::equals_with_epsilon(get<2>(direction), get<2>(other.direction));
- }*/
- point_type origin; // used for sorting and equality check
+ Point origin; // used for sorting and equality check
vector_type direction; // used for sorting, only in operator<
+ vector_type cross; // used for sorting, used for collinearity check
vector_type prev; // used for collinearity check, only in operator==
vector_type next; // used for collinearity check
};
-// Specialization for spherical polar
-template <typename T, typename Geometry, typename CT>
-struct collected_vector
- <
- T, Geometry,
- strategy::side::spherical_side_formula<CT>,
- spherical_polar_tag
- >
- : public collected_vector
- <
- T, Geometry,
- strategy::side::spherical_side_formula<CT>,
- spherical_equatorial_tag
- >
+// Version for spherical polar
+template <typename T, typename Point>
+struct collected_vector_polar
+ : public collected_vector_spherical<T, Point>
{
- typedef collected_vector
- <
- T, Geometry,
- strategy::side::spherical_side_formula<CT>,
- spherical_equatorial_tag
- > base_type;
+ using type = T;
+ using base_point_type
+ = model::point<T, 2, cs::spherical_equatorial<geometry::degree>>;
+ using base_type = collected_vector_spherical<T, base_point_type>;
- collected_vector() {}
+ collected_vector_polar() {}
- template <typename Point>
- collected_vector(Point const& p1, Point const& p2)
+ collected_vector_polar(Point const& p1, Point const& p2)
: base_type(to_equatorial(p1), to_equatorial(p2))
{}
private:
- template <typename Point>
- Point to_equatorial(Point const& p)
+ static base_point_type to_equatorial(Point const& p)
{
- typedef typename coordinate_type<Point>::type coord_type;
-
- typedef math::detail::constants_on_spheroid
+ using coord_type = typename coordinate_type<Point>::type;
+ using constants = math::detail::constants_on_spheroid
<
coord_type,
typename coordinate_system<Point>::type::units
- > constants;
+ > ;
- coord_type const pi_2 = constants::half_period() / 2;
+ constexpr coord_type pi_2 = constants::half_period() / 2;
- Point res = p;
+ base_point_type res;
+ set<0>(res, get<0>(p));
set<1>(res, pi_2 - get<1>(p));
return res;
}
};
-
-// TODO: specialize collected_vector for geographic_tag
+// TODO: implement collected_vector type for geographic
#ifndef DOXYGEN_NO_DETAIL
@@ -339,15 +294,11 @@ private:
return;
}
- typedef typename boost::range_size<Collection>::type collection_size_t;
- collection_size_t c_old_size = boost::size(collection);
-
- typedef typename boost::range_iterator<ClosedClockwiseRange const>::type iterator;
-
+ auto c_old_size = boost::size(collection);
bool is_first = true;
- iterator it = boost::begin(range);
+ auto it = boost::begin(range);
- for (iterator prev = it++; it != boost::end(range); prev = it++)
+ for (auto prev = it++; it != boost::end(range); prev = it++)
{
typename boost::range_value<Collection>::type v(*prev, *it);
@@ -366,13 +317,10 @@ private:
}
// If first one has same direction as last one, remove first one
- collection_size_t collected_count = boost::size(collection) - c_old_size;
- if ( collected_count > 1 )
+ if (boost::size(collection) > c_old_size + 1)
{
- typedef typename boost::range_iterator<Collection>::type c_iterator;
- c_iterator first = range::pos(collection, c_old_size);
-
- if (collection.back().next_is_collinear(*first) )
+ auto first = range::pos(collection, c_old_size);
+ if (collection.back().next_is_collinear(*first))
{
//collection.erase(first);
// O(1) instead of O(N)
@@ -451,10 +399,8 @@ struct polygon_collect_vectors
typedef range_collect_vectors<ring_type, Collection> per_range;
per_range::apply(collection, exterior_ring(polygon));
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(polygon);
- for (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ auto const& rings = interior_rings(polygon);
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
per_range::apply(collection, *it);
}
@@ -467,10 +413,7 @@ struct multi_collect_vectors
{
static inline void apply(Collection& collection, MultiGeometry const& multi)
{
- for (typename boost::range_iterator<MultiGeometry const>::type
- it = boost::begin(multi);
- it != boost::end(multi);
- ++it)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
SinglePolicy::apply(collection, *it);
}
diff --git a/boost/geometry/algorithms/detail/equals/implementation.hpp b/boost/geometry/algorithms/detail/equals/implementation.hpp
index e66a8a77ac..2f803f3658 100644
--- a/boost/geometry/algorithms/detail/equals/implementation.hpp
+++ b/boost/geometry/algorithms/detail/equals/implementation.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -36,8 +36,8 @@
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/detail/equals/collect_vectors.hpp>
#include <boost/geometry/algorithms/detail/equals/interface.hpp>
+#include <boost/geometry/algorithms/detail/relate/implementation.hpp>
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
-#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/strategies/relate/cartesian.hpp>
#include <boost/geometry/strategies/relate/geographic.hpp>
@@ -160,26 +160,32 @@ struct length_check
*/
-template <typename Geometry1, typename Geometry2, typename Strategy>
-struct collected_vector
+// Small helper structure do decide to use collect_vectors, or not
+template <typename Strategy, typename CsTag>
+struct use_collect_vectors
{
- typedef typename geometry::select_most_precise
- <
- typename select_coordinate_type
- <
- Geometry1, Geometry2
- >::type,
- double
- >::type calculation_type;
+ static constexpr bool value = false;
+};
- typedef geometry::collected_vector
- <
- calculation_type,
- Geometry1,
- decltype(std::declval<Strategy>().side())
- > type;
+template <typename Strategy>
+struct use_collect_vectors<Strategy, cartesian_tag>
+{
+ static constexpr bool value = true;
+
+ template <typename T, typename Point>
+ using type = collected_vector_cartesian<T>;
};
+template <typename CV>
+struct use_collect_vectors<strategy::side::spherical_side_formula<CV>, spherical_tag>
+{
+ static constexpr bool value = true;
+
+ template <typename T, typename Point>
+ using type = collected_vector_spherical<T, Point>;
+};
+
+
template <typename TrivialCheck>
struct equals_by_collection
{
@@ -193,10 +199,24 @@ struct equals_by_collection
return false;
}
- typedef typename collected_vector
+ using calculation_type = typename geometry::select_most_precise
+ <
+ typename select_coordinate_type
+ <
+ Geometry1, Geometry2
+ >::type,
+ double
+ >::type;
+
+ using collected_vector_type = typename use_collect_vectors
<
- Geometry1, Geometry2, Strategy
- >::type collected_vector_type;
+ decltype(std::declval<Strategy>().side()),
+ typename Strategy::cs_tag
+ >::template type
+ <
+ calculation_type,
+ typename geometry::point_type<Geometry1>::type
+ >;
std::vector<collected_vector_type> c1, c2;
@@ -211,7 +231,7 @@ struct equals_by_collection
std::sort(c1.begin(), c1.end());
std::sort(c2.begin(), c2.end());
- // Just check if these vectors are equal.
+ // Check if these vectors are equal.
return std::equal(c1.begin(), c1.end(), c2.begin());
}
};
@@ -226,47 +246,40 @@ struct equals_by_relate
>
{};
-// If collect_vectors which is a SideStrategy-dispatched optimization
-// is implemented in a way consistent with the Intersection/Side Strategy
-// then collect_vectors is used, otherwise relate is used.
+// Use either collect_vectors or relate
// NOTE: the result could be conceptually different for invalid
// geometries in different coordinate systems because collect_vectors
// and relate treat invalid geometries differently.
template<typename TrivialCheck>
struct equals_by_collection_or_relate
{
- template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- typedef std::is_base_of
- <
- nyi::not_implemented_tag,
- typename collected_vector
- <
- Geometry1, Geometry2, Strategy
- >::type
- > enable_relate_type;
-
- return apply(geometry1, geometry2, strategy, enable_relate_type());
- }
+ template <typename Strategy>
+ using use_vectors = use_collect_vectors
+ <
+ decltype(std::declval<Strategy>().side()),
+ typename Strategy::cs_tag
+ >;
-private:
- template <typename Geometry1, typename Geometry2, typename Strategy>
+ template
+ <
+ typename Geometry1, typename Geometry2, typename Strategy,
+ std::enable_if_t<use_vectors<Strategy>::value, int> = 0
+ >
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
- Strategy const& strategy,
- std::false_type /*enable_relate*/)
+ Strategy const& strategy)
{
return equals_by_collection<TrivialCheck>::apply(geometry1, geometry2, strategy);
}
- template <typename Geometry1, typename Geometry2, typename Strategy>
+ template
+ <
+ typename Geometry1, typename Geometry2, typename Strategy,
+ std::enable_if_t<! use_vectors<Strategy>::value, int> = 0
+ >
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
- Strategy const& strategy,
- std::true_type /*enable_relate*/)
+ Strategy const& strategy)
{
return equals_by_relate<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
}
@@ -376,7 +389,7 @@ struct equals
<
MultiPolygon1, MultiPolygon2,
multi_polygon_tag, multi_polygon_tag,
- areal_tag, areal_tag,
+ areal_tag, areal_tag,
2,
Reverse
>
@@ -389,7 +402,7 @@ struct equals
<
Polygon, MultiPolygon,
polygon_tag, multi_polygon_tag,
- areal_tag, areal_tag,
+ areal_tag, areal_tag,
2,
Reverse
>
@@ -401,7 +414,7 @@ struct equals
<
MultiPolygon, Ring,
multi_polygon_tag, ring_tag,
- areal_tag, areal_tag,
+ areal_tag, areal_tag,
2,
Reverse
>
diff --git a/boost/geometry/algorithms/detail/equals/implementation_gc.hpp b/boost/geometry/algorithms/detail/equals/implementation_gc.hpp
new file mode 100644
index 0000000000..81424e0468
--- /dev/null
+++ b/boost/geometry/algorithms/detail/equals/implementation_gc.hpp
@@ -0,0 +1,114 @@
+// Boost.Geometry
+
+// Copyright (c) 2022 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_GC_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_GC_HPP
+
+
+#include <boost/geometry/algorithms/detail/equals/implementation.hpp>
+#include <boost/geometry/algorithms/detail/relate/implementation_gc.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Geometry1, typename Geometry2, std::size_t DimensionCount>
+struct equals
+ <
+ Geometry1, Geometry2,
+ geometry_collection_tag, geometry_collection_tag,
+ geometry_collection_tag, geometry_collection_tag,
+ DimensionCount, false
+ >
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ return detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_equals_type,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
+ }
+};
+
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1, typename CastedTag1,
+ std::size_t DimensionCount
+>
+struct equals
+ <
+ Geometry1, Geometry2,
+ Tag1, geometry_collection_tag,
+ CastedTag1, geometry_collection_tag,
+ DimensionCount, false
+ >
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ using gc1_view_t = detail::geometry_collection_view<Geometry1>;
+ return equals
+ <
+ gc1_view_t, Geometry2
+ >::apply(gc1_view_t(geometry1), geometry2, strategy);
+ }
+};
+
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag2, typename CastedTag2,
+ std::size_t DimensionCount
+>
+struct equals
+ <
+ Geometry1, Geometry2,
+ geometry_collection_tag, Tag2,
+ geometry_collection_tag, CastedTag2,
+ DimensionCount, false
+ >
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ using gc2_view_t = detail::geometry_collection_view<Geometry2>;
+ return equals
+ <
+ Geometry1, gc2_view_t
+ >::apply(geometry1, gc2_view_t(geometry2), strategy);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_GC_HPP
diff --git a/boost/geometry/algorithms/detail/equals/interface.hpp b/boost/geometry/algorithms/detail/equals/interface.hpp
index bd31e8c2c4..f0c4438430 100644
--- a/boost/geometry/algorithms/detail/equals/interface.hpp
+++ b/boost/geometry/algorithms/detail/equals/interface.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -23,15 +23,12 @@
#include <cstddef>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tag_cast.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
@@ -157,9 +154,14 @@ struct equals<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant {
+namespace resolve_dynamic {
-template <typename Geometry1, typename Geometry2>
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct equals
{
template <typename Strategy>
@@ -180,114 +182,67 @@ struct equals
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct equals<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct equals<Geometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Strategy>
- struct visitor: static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2, Strategy const& strategy)
- : m_geometry2(geometry2)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- inline bool operator()(Geometry1 const& geometry1) const
+ bool result = false;
+ traits::visit<Geometry1>::apply([&](auto const& g1)
{
- return equals<Geometry1, Geometry2>
- ::apply(geometry1, m_geometry2, m_strategy);
- }
-
- };
-
- template <typename Strategy>
- static inline bool apply(
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy
- )
- {
- return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
+ result = equals
+ <
+ util::remove_cref_t<decltype(g1)>,
+ Geometry2
+ >::apply(g1, geometry2, strategy);
+ }, geometry1);
+ return result;
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct equals<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct equals<Geometry1, Geometry2, Tag1, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1, Strategy const& strategy)
- : m_geometry1(geometry1)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- inline bool operator()(Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry2>::apply([&](auto const& g2)
{
- return equals<Geometry1, Geometry2>
- ::apply(m_geometry1, geometry2, m_strategy);
- }
-
- };
-
- template <typename Strategy>
- static inline bool apply(
- Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Strategy const& strategy
- )
- {
- return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
+ result = equals
+ <
+ Geometry1,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(geometry1, g2, strategy);
+ }, geometry2);
+ return result;
}
};
-template <
- BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)
->
-struct equals<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
->
+template <typename Geometry1, typename Geometry2>
+struct equals<Geometry1, Geometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy)
- : m_strategy(strategy)
- {}
-
- template <typename Geometry1, typename Geometry2>
- inline bool operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry1, Geometry2>::apply([&](auto const& g1, auto const& g2)
{
- return equals<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, m_strategy);
- }
-
- };
-
- template <typename Strategy>
- static inline bool apply(
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy
- )
- {
- return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
+ result = equals
+ <
+ util::remove_cref_t<decltype(g1)>,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(g1, g2, strategy);
+ }, geometry1, geometry2);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
@@ -314,10 +269,10 @@ inline bool equals(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
- return resolve_variant::equals
- <
- Geometry1, Geometry2
- >::apply(geometry1, geometry2, strategy);
+ return resolve_dynamic::equals
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy);
}
@@ -340,8 +295,10 @@ inline bool equals(Geometry1 const& geometry1,
template <typename Geometry1, typename Geometry2>
inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
- return resolve_variant::equals<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, default_strategy());
+ return resolve_dynamic::equals
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, default_strategy());
}
diff --git a/boost/geometry/algorithms/detail/expand/indexed.hpp b/boost/geometry/algorithms/detail/expand/indexed.hpp
index 08463689de..92d701d16e 100644
--- a/boost/geometry/algorithms/detail/expand/indexed.hpp
+++ b/boost/geometry/algorithms/detail/expand/indexed.hpp
@@ -61,7 +61,7 @@ struct indexed_loop
std::less<coordinate_type> less;
std::greater<coordinate_type> greater;
-
+
if (less(coord, get<min_corner, Dimension>(box)))
{
set<min_corner, Dimension>(box, coord);
diff --git a/boost/geometry/algorithms/detail/expand/interface.hpp b/boost/geometry/algorithms/detail/expand/interface.hpp
index 442a4e011f..6552c266e4 100644
--- a/boost/geometry/algorithms/detail/expand/interface.hpp
+++ b/boost/geometry/algorithms/detail/expand/interface.hpp
@@ -22,22 +22,23 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/dispatch/expand.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tag.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/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/expand/services.hpp>
+#include <boost/geometry/util/type_traits_std.hpp>
+
namespace boost { namespace geometry
{
@@ -97,10 +98,10 @@ struct expand<default_strategy, false>
} //namespace resolve_strategy
-namespace resolve_variant
+namespace resolve_dynamic
{
-
-template <typename Geometry>
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct expand
{
template <typename Box, typename Strategy>
@@ -111,72 +112,28 @@ struct expand
concepts::check<Box>();
concepts::check<Geometry const>();
concepts::check_concepts_and_equal_dimensions<Box, Geometry const>();
-
+
resolve_strategy::expand<Strategy>::apply(box, geometry, strategy);
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct expand<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct expand<Geometry, dynamic_geometry_tag>
{
- template <typename Box, typename Strategy>
- struct visitor: boost::static_visitor<void>
- {
- Box& m_box;
- Strategy const& m_strategy;
-
- visitor(Box& box, Strategy const& strategy)
- : m_box(box)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry>
- void operator()(Geometry const& geometry) const
- {
- return expand<Geometry>::apply(m_box, geometry, m_strategy);
- }
- };
-
template <class Box, typename Strategy>
- static inline void
- apply(Box& box,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- Strategy const& strategy)
+ static inline void apply(Box& box,
+ Geometry const& geometry,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<Box, Strategy>(box, strategy),
- geometry);
+ traits::visit<Geometry>::apply([&](auto const& g)
+ {
+ expand<util::remove_cref_t<decltype(g)>>::apply(box, g, strategy);
+ }, geometry);
}
};
-
-} // namespace resolve_variant
-
-
-/***
-*!
-\brief Expands a box using the extend (envelope) of another geometry (box, point)
-\ingroup expand
-\tparam Box type of the box
-\tparam Geometry of second geometry, to be expanded with the box
-\param box box to expand another geometry with, might be changed
-\param geometry other geometry
-\param strategy_less
-\param strategy_greater
-\note Strategy is currently ignored
- *
-template
-<
- typename Box, typename Geometry,
- typename StrategyLess, typename StrategyGreater
->
-inline void expand(Box& box, Geometry const& geometry,
- StrategyLess const& strategy_less,
- StrategyGreater const& strategy_greater)
-{
- concepts::check_concepts_and_equal_dimensions<Box, Geometry const>();
- dispatch::expand<Box, Geometry>::apply(box, geometry);
-}
-***/
+} // namespace resolve_dynamic
+
/*!
\brief Expands (with strategy)
@@ -195,7 +152,7 @@ will be added to the box
template <typename Box, typename Geometry, typename Strategy>
inline void expand(Box& box, Geometry const& geometry, Strategy const& strategy)
{
- resolve_variant::expand<Geometry>::apply(box, geometry, strategy);
+ resolve_dynamic::expand<Geometry>::apply(box, geometry, strategy);
}
/*!
@@ -213,7 +170,7 @@ added to the box
template <typename Box, typename Geometry>
inline void expand(Box& box, Geometry const& geometry)
{
- resolve_variant::expand<Geometry>::apply(box, geometry, default_strategy());
+ resolve_dynamic::expand<Geometry>::apply(box, geometry, default_strategy());
}
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/expand_by_epsilon.hpp b/boost/geometry/algorithms/detail/expand_by_epsilon.hpp
index 3e41b71ff9..ae07f5bb0a 100644
--- a/boost/geometry/algorithms/detail/expand_by_epsilon.hpp
+++ b/boost/geometry/algorithms/detail/expand_by_epsilon.hpp
@@ -44,7 +44,7 @@ struct corner_by_epsilon
typedef typename coordinate_type<Point>::type coord_type;
coord_type const coord = get<I>(point);
coord_type const seps = math::scaled_epsilon(coord);
-
+
set<I>(point, PlusOrMinus<coord_type>()(coord, seps));
corner_by_epsilon<Point, PlusOrMinus, I+1>::apply(point);
diff --git a/boost/geometry/algorithms/detail/extreme_points.hpp b/boost/geometry/algorithms/detail/extreme_points.hpp
index a6605fd45d..2ac13fc1ed 100644
--- a/boost/geometry/algorithms/detail/extreme_points.hpp
+++ b/boost/geometry/algorithms/detail/extreme_points.hpp
@@ -26,7 +26,6 @@
#include <boost/range/value_type.hpp>
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
@@ -124,7 +123,6 @@ struct extreme_points_on_ring
{
typedef typename geometry::coordinate_type<Ring>::type coordinate_type;
- typedef typename boost::range_iterator<Ring const>::type range_iterator;
typedef typename geometry::point_type<Ring>::type point_type;
template <typename CirclingIterator, typename Points>
@@ -288,8 +286,7 @@ struct extreme_points_on_ring
template <typename Iterator, typename SideStrategy>
static inline bool right_turn(Ring const& ring, Iterator it, SideStrategy const& strategy)
{
- typename std::iterator_traits<Iterator>::difference_type const index
- = std::distance(boost::begin(ring), it);
+ auto const index = std::distance(boost::begin(ring), it);
geometry::ever_circling_range_iterator<Ring const> left(ring);
geometry::ever_circling_range_iterator<Ring const> right(ring);
left += index;
@@ -326,9 +323,9 @@ struct extreme_points_on_ring
// Get all maxima, usually one. In case of self-tangencies, or self-crossings,
// the max might be is not valid. A valid max should make a right turn
- range_iterator max_it = boost::begin(ring);
+ auto max_it = boost::begin(ring);
compare<Dimension> smaller;
- for (range_iterator it = max_it + 1; it != boost::end(ring); ++it)
+ for (auto it = max_it + 1; it != boost::end(ring); ++it)
{
if (smaller(*max_it, *it) && right_turn(ring, it, strategy))
{
@@ -341,8 +338,7 @@ struct extreme_points_on_ring
return false;
}
- typename std::iterator_traits<range_iterator>::difference_type const
- index = std::distance(boost::begin(ring), max_it);
+ auto const index = std::distance(boost::begin(ring), max_it);
//std::cout << "Extreme point lies at " << index << " having " << geometry::wkt(*max_it) << std::endl;
geometry::ever_circling_range_iterator<Ring const> left(ring);
@@ -429,10 +425,8 @@ struct extreme_points<Polygon, Dimension, polygon_tag>
}
// For a polygon, its interior rings can contain intruders
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(polygon);
- for (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ auto const& rings = interior_rings(polygon);
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
ring_implementation::get_intruders(*it, extremes, intruders, strategy);
}
diff --git a/boost/geometry/algorithms/detail/gc_group_elements.hpp b/boost/geometry/algorithms/detail/gc_group_elements.hpp
new file mode 100644
index 0000000000..c1c26ec9c6
--- /dev/null
+++ b/boost/geometry/algorithms/detail/gc_group_elements.hpp
@@ -0,0 +1,196 @@
+// Boost.Geometry
+
+// Copyright (c) 2022, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_GROUP_ELEMENTS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_GROUP_ELEMENTS_HPP
+
+
+#include <array>
+#include <deque>
+#include <map>
+#include <set>
+#include <vector>
+
+#include <boost/range/begin.hpp>
+#include <boost/range/size.hpp>
+
+#include <boost/geometry/algorithms/detail/gc_make_rtree.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
+#include <boost/geometry/algorithms/is_empty.hpp>
+#include <boost/geometry/core/topological_dimension.hpp>
+#include <boost/geometry/views/detail/random_access_view.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+struct gc_element_id
+{
+ gc_element_id(unsigned int source_id_, std::size_t gc_id_)
+ : source_id(source_id_), gc_id(gc_id_)
+ {}
+
+ unsigned int source_id;
+ std::size_t gc_id;
+
+ friend bool operator<(gc_element_id const& left, gc_element_id const& right)
+ {
+ return left.source_id < right.source_id
+ || (left.source_id == right.source_id && left.gc_id < right.gc_id);
+ }
+};
+
+template <typename GC1View, typename GC2View, typename Strategy, typename IntersectingFun, typename DisjointFun>
+inline void gc_group_elements(GC1View const& gc1_view, GC2View const& gc2_view, Strategy const& strategy,
+ IntersectingFun&& intersecting_fun,
+ DisjointFun&& disjoint_fun,
+ bool const group_self = false)
+{
+ // NOTE: gc_make_rtree_indexes() already checks for random-access,
+ // non-recursive geometry collections.
+
+ // NOTE: could be replaced with unordered_map and unordered_set
+ std::map<gc_element_id, std::set<gc_element_id>> adjacent;
+
+ // Create adjacency list based on intersecting envelopes of GC elements
+ auto const rtree2 = gc_make_rtree_indexes(gc2_view, strategy);
+ if (! group_self) // group only elements from the other GC?
+ {
+ for (std::size_t i = 0; i < boost::size(gc1_view); ++i)
+ {
+ traits::iter_visit<GC1View>::apply([&](auto const& g1)
+ {
+ using g1_t = util::remove_cref_t<decltype(g1)>;
+ using box1_t = gc_make_rtree_box_t<g1_t>;
+ box1_t b1 = geometry::return_envelope<box1_t>(g1, strategy);
+ detail::expand_by_epsilon(b1);
+
+ gc_element_id id1 = {0, i};
+ for (auto qit = rtree2.qbegin(index::intersects(b1)); qit != rtree2.qend(); ++qit)
+ {
+ gc_element_id id2 = {1, qit->second};
+ adjacent[id1].insert(id2);
+ adjacent[id2].insert(id1);
+ }
+ }, boost::begin(gc1_view) + i);
+ }
+ }
+ else // group elements from the same GCs and the other GC
+ {
+ auto const rtree1 = gc_make_rtree_indexes(gc1_view, strategy);
+ for (auto it1 = rtree1.begin() ; it1 != rtree1.end() ; ++it1)
+ {
+ auto const b1 = it1->first;
+ gc_element_id id1 = {0, it1->second};
+ for (auto qit2 = rtree2.qbegin(index::intersects(b1)); qit2 != rtree2.qend(); ++qit2)
+ {
+ gc_element_id id2 = {1, qit2->second};
+ adjacent[id1].insert(id2);
+ adjacent[id2].insert(id1);
+ }
+ for (auto qit1 = rtree1.qbegin(index::intersects(b1)); qit1 != rtree1.qend(); ++qit1)
+ {
+ if (id1.gc_id != qit1->second)
+ {
+ gc_element_id id11 = {0, qit1->second};
+ adjacent[id1].insert(id11);
+ adjacent[id11].insert(id1);
+ }
+ }
+ }
+ for (auto it2 = rtree2.begin(); it2 != rtree2.end(); ++it2)
+ {
+ auto const b2 = it2->first;
+ gc_element_id id2 = {1, it2->second};
+ for (auto qit2 = rtree2.qbegin(index::intersects(b2)); qit2 != rtree2.qend(); ++qit2)
+ {
+ if (id2.gc_id != qit2->second)
+ {
+ gc_element_id id22 = {1, qit2->second};
+ adjacent[id2].insert(id22);
+ adjacent[id22].insert(id2);
+ }
+ }
+ }
+ }
+
+ // Traverse the graph and build connected groups i.e. groups of intersecting envelopes
+ std::deque<gc_element_id> queue;
+ std::array<std::vector<bool>, 2> visited = {
+ std::vector<bool>(boost::size(gc1_view), false),
+ std::vector<bool>(boost::size(gc2_view), false)
+ };
+ for (auto const& elem : adjacent)
+ {
+ std::vector<gc_element_id> group;
+ if (! visited[elem.first.source_id][elem.first.gc_id])
+ {
+ queue.push_back(elem.first);
+ visited[elem.first.source_id][elem.first.gc_id] = true;
+ group.push_back(elem.first);
+ while (! queue.empty())
+ {
+ gc_element_id e = queue.front();
+ queue.pop_front();
+ for (auto const& n : adjacent[e])
+ {
+ if (! visited[n.source_id][n.gc_id])
+ {
+ queue.push_back(n);
+ visited[n.source_id][n.gc_id] = true;
+ group.push_back(n);
+ }
+ }
+ }
+ }
+ if (! group.empty())
+ {
+ if (! intersecting_fun(group))
+ {
+ return;
+ }
+ }
+ }
+
+ {
+ std::vector<gc_element_id> group;
+ for (std::size_t i = 0; i < visited[0].size(); ++i)
+ {
+ if (! visited[0][i])
+ {
+ group.emplace_back(0, i);
+ }
+ }
+ for (std::size_t i = 0; i < visited[1].size(); ++i)
+ {
+ if (! visited[1][i])
+ {
+ group.emplace_back(1, i);
+ }
+ }
+ if (! group.empty())
+ {
+ disjoint_fun(group);
+ }
+ }
+}
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_GROUP_ELEMENTS_HPP
diff --git a/boost/geometry/algorithms/detail/gc_make_rtree.hpp b/boost/geometry/algorithms/detail/gc_make_rtree.hpp
new file mode 100644
index 0000000000..c1c00d4692
--- /dev/null
+++ b/boost/geometry/algorithms/detail/gc_make_rtree.hpp
@@ -0,0 +1,118 @@
+// Boost.Geometry
+
+// Copyright (c) 2022, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_MAKE_RTREE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_MAKE_RTREE_HPP
+
+#include <vector>
+
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/size.hpp>
+
+#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
+#include <boost/geometry/algorithms/envelope.hpp>
+#include <boost/geometry/index/rtree.hpp>
+#include <boost/geometry/strategies/index/services.hpp>
+#include <boost/geometry/views/detail/random_access_view.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+template <typename GC>
+using gc_make_rtree_box_t = geometry::model::box
+ <
+ geometry::model::point
+ <
+ typename geometry::coordinate_type<GC>::type,
+ geometry::dimension<GC>::value,
+ typename geometry::coordinate_system<GC>::type
+ >
+ >;
+
+
+template <typename GC, typename Strategy>
+inline auto gc_make_rtree_iterators(GC& gc, Strategy const& strategy)
+{
+ using box_t = gc_make_rtree_box_t<GC>;
+ using iter_t = typename boost::range_iterator<GC>::type;
+
+ using rtree_param_t = index::rstar<4>;
+ using rtree_parameters_t = index::parameters<rtree_param_t, Strategy>;
+ using value_t = std::pair<box_t, iter_t>;
+ using rtree_t = index::rtree<value_t, rtree_parameters_t>;
+
+ // TODO: get rid of the temporary vector
+ auto const size = boost::size(gc);
+ std::vector<value_t> values;
+ values.reserve(size);
+
+ visit_breadth_first_impl<true>::apply([&](auto const& g, auto iter)
+ {
+ box_t b = geometry::return_envelope<box_t>(g, strategy);
+ detail::expand_by_epsilon(b);
+ values.emplace_back(b, iter);
+ return true;
+ }, gc);
+
+ return rtree_t(values.begin(), values.end(), rtree_parameters_t(rtree_param_t(), strategy));
+}
+
+
+template <typename GCView, typename Strategy>
+inline auto gc_make_rtree_indexes(GCView const& gc, Strategy const& strategy)
+{
+ // Alternatively only take random_access_view<GC>
+ static const bool is_random_access = is_random_access_range<GCView>::value;
+ static const bool is_not_recursive = ! is_geometry_collection_recursive<GCView>::value;
+ BOOST_GEOMETRY_STATIC_ASSERT((is_random_access && is_not_recursive),
+ "This algorithm requires random-access, non-recursive geometry collection or view.",
+ GCView);
+
+ using box_t = gc_make_rtree_box_t<GCView>;
+
+ using rtree_param_t = index::rstar<4>;
+ using rtree_parameters_t = index::parameters<rtree_param_t, Strategy>;
+ using value_t = std::pair<box_t, std::size_t>;
+ using rtree_t = index::rtree<value_t, rtree_parameters_t>;
+
+ // TODO: get rid of the temporary vector
+ std::size_t const size = boost::size(gc);
+ std::vector<value_t> values;
+ values.reserve(size);
+
+ auto const begin = boost::begin(gc);
+ for (std::size_t i = 0; i < size; ++i)
+ {
+ traits::iter_visit<GCView>::apply([&](auto const& g)
+ {
+ box_t b = geometry::return_envelope<box_t>(g, strategy);
+ detail::expand_by_epsilon(b);
+ values.emplace_back(b, i);
+ }, begin + i);
+ }
+
+ return rtree_t(values.begin(), values.end(), rtree_parameters_t(rtree_param_t(), strategy));
+}
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_MAKE_RTREE_HPP
diff --git a/boost/geometry/algorithms/detail/gc_topological_dimension.hpp b/boost/geometry/algorithms/detail/gc_topological_dimension.hpp
new file mode 100644
index 0000000000..49f017945c
--- /dev/null
+++ b/boost/geometry/algorithms/detail/gc_topological_dimension.hpp
@@ -0,0 +1,51 @@
+// Boost.Geometry
+
+// Copyright (c) 2022, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_TOPOLOGICAL_DIMENSION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_TOPOLOGICAL_DIMENSION_HPP
+
+
+#include <algorithm>
+
+#include <boost/geometry/algorithms/detail/visit.hpp>
+#include <boost/geometry/algorithms/is_empty.hpp>
+#include <boost/geometry/core/topological_dimension.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+template <typename GeometryCollection>
+inline int gc_topological_dimension(GeometryCollection const& geometry)
+{
+ int result = -1;
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ if (! geometry::is_empty(g))
+ {
+ static const int d = geometry::topological_dimension<decltype(g)>::value;
+ result = (std::max)(result, d);
+ }
+ return result >= 2;
+ }, geometry);
+ return result;
+}
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_TOPOLOGICAL_DIMENSION_HPP
diff --git a/boost/geometry/algorithms/detail/has_self_intersections.hpp b/boost/geometry/algorithms/detail/has_self_intersections.hpp
index 805ab6754a..0b13eb7bda 100644
--- a/boost/geometry/algorithms/detail/has_self_intersections.hpp
+++ b/boost/geometry/algorithms/detail/has_self_intersections.hpp
@@ -91,10 +91,8 @@ inline bool has_self_intersections(Geometry const& geometry,
#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS
bool first = true;
#endif
- for(typename std::deque<turn_info>::const_iterator it = boost::begin(turns);
- it != boost::end(turns); ++it)
+ for (auto const& info : turns)
{
- turn_info const& info = *it;
bool const both_union_turn =
info.operations[0].operation == detail::overlay::operation_union
&& info.operations[1].operation == detail::overlay::operation_union;
diff --git a/boost/geometry/algorithms/detail/interior_iterator.hpp b/boost/geometry/algorithms/detail/interior_iterator.hpp
index 3582773c3d..1a9d4f1922 100644
--- a/boost/geometry/algorithms/detail/interior_iterator.hpp
+++ b/boost/geometry/algorithms/detail/interior_iterator.hpp
@@ -31,7 +31,7 @@ struct interior_iterator
{
typedef typename boost::range_iterator
<
- typename geometry::interior_type<Geometry>::type
+ typename geometry::interior_type<Geometry>::type
>::type type;
};
diff --git a/boost/geometry/algorithms/detail/intersection/areal_areal.hpp b/boost/geometry/algorithms/detail/intersection/areal_areal.hpp
index 9faa1df55c..e657f825f2 100644
--- a/boost/geometry/algorithms/detail/intersection/areal_areal.hpp
+++ b/boost/geometry/algorithms/detail/intersection/areal_areal.hpp
@@ -155,7 +155,7 @@ struct intersection_areal_areal_<TupledOut, tupled_output_tag>
pointlike::get(geometry_out),
strategy);
}
-
+
return;
}
diff --git a/boost/geometry/algorithms/detail/intersection/gc.hpp b/boost/geometry/algorithms/detail/intersection/gc.hpp
new file mode 100644
index 0000000000..fa492c0f34
--- /dev/null
+++ b/boost/geometry/algorithms/detail/intersection/gc.hpp
@@ -0,0 +1,329 @@
+// Boost.Geometry
+
+// Copyright (c) 2022, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_GC_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_GC_HPP
+
+
+#include <tuple>
+
+#include <boost/geometry/algorithms/detail/gc_make_rtree.hpp>
+#include <boost/geometry/algorithms/detail/intersection/interface.hpp>
+#include <boost/geometry/views/detail/geometry_collection_view.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intersection
+{
+
+
+template <typename GC, typename Multi>
+struct gc_can_move_element
+{
+ template <typename G>
+ using is_same_as_single = std::is_same<G, typename boost::range_value<Multi>::type>;
+ using gc_types = typename traits::geometry_types<GC>::type;
+ using found_type = typename util::sequence_find_if<gc_types, is_same_as_single>::type;
+ static const bool value = ! std::is_void<found_type>::value;
+};
+
+template <typename GC, typename Multi>
+struct gc_can_convert_element
+{
+ template <typename G>
+ using has_same_tag_as_single = std::is_same
+ <
+ typename geometry::tag<G>::type,
+ typename geometry::tag<typename boost::range_value<Multi>::type>::type
+ >;
+ using gc_types = typename traits::geometry_types<GC>::type;
+ using found_type = typename util::sequence_find_if<gc_types, has_same_tag_as_single>::type;
+ static const bool value = ! std::is_void<found_type>::value;
+};
+
+template
+<
+ typename GC, typename Multi,
+ std::enable_if_t<gc_can_move_element<GC, Multi>::value, int> = 0
+>
+inline void gc_move_one_elem_multi_back(GC& gc, Multi&& multi)
+{
+ range::emplace_back(gc, std::move(*boost::begin(multi)));
+}
+
+template
+<
+ typename GC, typename Multi,
+ std::enable_if_t<! gc_can_move_element<GC, Multi>::value && gc_can_convert_element<GC, Multi>::value, int> = 0
+>
+inline void gc_move_one_elem_multi_back(GC& gc, Multi&& multi)
+{
+ typename gc_can_convert_element<GC, Multi>::found_type single_out;
+ geometry::convert(*boost::begin(multi), single_out);
+ range::emplace_back(gc, std::move(single_out));
+}
+
+template
+<
+ typename GC, typename Multi,
+ std::enable_if_t<! gc_can_move_element<GC, Multi>::value && ! gc_can_convert_element<GC, Multi>::value, int> = 0
+>
+inline void gc_move_one_elem_multi_back(GC& gc, Multi&& multi)
+{
+ range::emplace_back(gc, std::move(multi));
+}
+
+template <typename GC, typename Multi>
+inline void gc_move_multi_back(GC& gc, Multi&& multi)
+{
+ if (! boost::empty(multi))
+ {
+ if (boost::size(multi) == 1)
+ {
+ gc_move_one_elem_multi_back(gc, std::move(multi));
+ }
+ else
+ {
+ range::emplace_back(gc, std::move(multi));
+ }
+ }
+}
+
+
+}} // namespace detail::intersection
+#endif // DOXYGEN_NO_DETAIL
+
+
+namespace resolve_collection
+{
+
+
+template
+<
+ typename Geometry1, typename Geometry2, typename GeometryOut
+>
+struct intersection
+ <
+ Geometry1, Geometry2, GeometryOut,
+ geometry_collection_tag, geometry_collection_tag, geometry_collection_tag
+ >
+{
+ // NOTE: for now require all of the possible output types
+ // technically only a subset could be needed.
+ using multi_point_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<GeometryOut>::type,
+ util::is_multi_point
+ >::type;
+ using multi_linestring_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<GeometryOut>::type,
+ util::is_multi_linestring
+ >::type;
+ using multi_polygon_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<GeometryOut>::type,
+ util::is_multi_polygon
+ >::type;
+ using tuple_out_t = boost::tuple<multi_point_t, multi_linestring_t, multi_polygon_t>;
+
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
+ {
+ bool result = false;
+ tuple_out_t out;
+
+ auto const rtree2 = detail::gc_make_rtree_iterators(geometry2, strategy);
+ detail::visit_breadth_first([&](auto const& g1)
+ {
+ bool r = g1_prod_gc2(g1, rtree2, out, strategy);
+ result = result || r;
+ return true;
+ }, geometry1);
+
+ detail::intersection::gc_move_multi_back(geometry_out, boost::get<0>(out));
+ detail::intersection::gc_move_multi_back(geometry_out, boost::get<1>(out));
+ detail::intersection::gc_move_multi_back(geometry_out, boost::get<2>(out));
+
+ return result;
+ }
+
+private:
+ // Implemented as separate function because msvc is unable to do nested lambda capture
+ template <typename G1, typename Rtree2, typename TupleOut, typename Strategy>
+ static bool g1_prod_gc2(G1 const& g1, Rtree2 const& rtree2, TupleOut& out, Strategy const& strategy)
+ {
+ bool result = false;
+
+ using box1_t = detail::gc_make_rtree_box_t<G1>;
+ box1_t b1 = geometry::return_envelope<box1_t>(g1, strategy);
+ detail::expand_by_epsilon(b1);
+
+ for (auto qit = rtree2.qbegin(index::intersects(b1)); qit != rtree2.qend(); ++qit)
+ {
+ traits::iter_visit<Geometry2>::apply([&](auto const& g2)
+ {
+ TupleOut inters_result;
+ using g2_t = util::remove_cref_t<decltype(g2)>;
+ intersection<G1, g2_t, TupleOut>::apply(g1, g2, inters_result, strategy);
+
+ // TODO: If possible merge based on adjacency lists, i.e. merge
+ // only the intersections of elements that intersect each other
+ // as subgroups. So the result could contain merged intersections
+ // of several groups, not only one.
+ // TODO: It'd probably be better to gather all of the parts first
+ // and then merge them with merge_elements.
+ // NOTE: template explicitly called because gcc-6 doesn't compile it
+ // otherwise.
+ bool const r0 = intersection::template merge_result<0>(inters_result, out, strategy);
+ bool const r1 = intersection::template merge_result<1>(inters_result, out, strategy);
+ bool const r2 = intersection::template merge_result<2>(inters_result, out, strategy);
+ result = result || r0 || r1 || r2;
+ }, qit->second);
+ }
+
+ return result;
+ }
+
+ template <std::size_t Index, typename Out, typename Strategy>
+ static bool merge_result(Out const& inters_result, Out& out, Strategy const& strategy)
+ {
+ auto const& multi_result = boost::get<Index>(inters_result);
+ auto& multi_out = boost::get<Index>(out);
+ if (! boost::empty(multi_result))
+ {
+ std::remove_reference_t<decltype(multi_out)> temp_result;
+ merge_two(multi_out, multi_result, temp_result, strategy);
+ multi_out = std::move(temp_result);
+ return true;
+ }
+ return false;
+ }
+
+ template <typename Out, typename Strategy, std::enable_if_t<! util::is_pointlike<Out>::value, int> = 0>
+ static void merge_two(Out const& g1, Out const& g2, Out& out, Strategy const& strategy)
+ {
+ using rescale_policy_type = typename geometry::rescale_overlay_policy_type
+ <
+ Out, Out, typename Strategy::cs_tag
+ >::type;
+
+ rescale_policy_type robust_policy
+ = geometry::get_rescale_policy<rescale_policy_type>(
+ g1, g2, strategy);
+
+ geometry::dispatch::intersection_insert
+ <
+ Out, Out, typename boost::range_value<Out>::type,
+ overlay_union
+ >::apply(g1,
+ g2,
+ robust_policy,
+ geometry::range::back_inserter(out),
+ strategy);
+ }
+
+ template <typename Out, typename Strategy, std::enable_if_t<util::is_pointlike<Out>::value, int> = 0>
+ static void merge_two(Out const& g1, Out const& g2, Out& out, Strategy const& strategy)
+ {
+ detail::overlay::union_pointlike_pointlike_point
+ <
+ Out, Out, typename boost::range_value<Out>::type
+ >::apply(g1,
+ g2,
+ 0, // dummy robust policy
+ geometry::range::back_inserter(out),
+ strategy);
+ }
+};
+
+template
+<
+ typename Geometry1, typename Geometry2, typename GeometryOut, typename Tag1
+>
+struct intersection
+ <
+ Geometry1, Geometry2, GeometryOut,
+ Tag1, geometry_collection_tag, geometry_collection_tag
+ >
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
+ {
+ using gc_view_t = geometry::detail::geometry_collection_view<Geometry1>;
+ return intersection
+ <
+ gc_view_t, Geometry2, GeometryOut
+ >::apply(gc_view_t(geometry1), geometry2, geometry_out, strategy);
+ }
+};
+
+template
+<
+ typename Geometry1, typename Geometry2, typename GeometryOut, typename Tag2
+>
+struct intersection
+ <
+ Geometry1, Geometry2, GeometryOut,
+ geometry_collection_tag, Tag2, geometry_collection_tag
+ >
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
+ {
+ using gc_view_t = geometry::detail::geometry_collection_view<Geometry2>;
+ return intersection
+ <
+ Geometry1, gc_view_t, GeometryOut
+ >::apply(geometry1, gc_view_t(geometry2), geometry_out, strategy);
+ }
+};
+
+template
+<
+ typename Geometry1, typename Geometry2, typename GeometryOut, typename Tag1, typename Tag2
+>
+struct intersection
+ <
+ Geometry1, Geometry2, GeometryOut,
+ Tag1, Tag2, geometry_collection_tag
+ >
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
+ {
+ using gc1_view_t = geometry::detail::geometry_collection_view<Geometry1>;
+ using gc2_view_t = geometry::detail::geometry_collection_view<Geometry2>;
+ return intersection
+ <
+ gc1_view_t, gc2_view_t, GeometryOut
+ >::apply(gc1_view_t(geometry1), gc2_view_t(geometry2), geometry_out, strategy);
+ }
+};
+
+
+} // namespace resolve_collection
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_GC_HPP
diff --git a/boost/geometry/algorithms/detail/intersection/implementation.hpp b/boost/geometry/algorithms/detail/intersection/implementation.hpp
index eee3f25f91..199a05d015 100644
--- a/boost/geometry/algorithms/detail/intersection/implementation.hpp
+++ b/boost/geometry/algorithms/detail/intersection/implementation.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -17,6 +17,7 @@
#include <boost/geometry/algorithms/detail/intersection/areal_areal.hpp>
#include <boost/geometry/algorithms/detail/intersection/box_box.hpp>
+#include <boost/geometry/algorithms/detail/intersection/gc.hpp>
#include <boost/geometry/algorithms/detail/intersection/multi.hpp>
#include <boost/geometry/strategies/relate/cartesian.hpp>
diff --git a/boost/geometry/algorithms/detail/intersection/interface.hpp b/boost/geometry/algorithms/detail/intersection/interface.hpp
index fcd7e959e7..84a9a57cc1 100644
--- a/boost/geometry/algorithms/detail/intersection/interface.hpp
+++ b/boost/geometry/algorithms/detail/intersection/interface.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014-2020.
-// Modifications copyright (c) 2014-2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -14,17 +14,15 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
#include <boost/geometry/algorithms/detail/tupled_output.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
#include <boost/geometry/util/range.hpp>
+#include <boost/geometry/util/type_traits_std.hpp>
namespace boost { namespace geometry
@@ -107,25 +105,21 @@ struct intersection
#endif // DOXYGEN_NO_DISPATCH
-namespace resolve_strategy {
+namespace resolve_collection
+{
template
<
- typename Strategy,
- bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
+ typename Geometry1, typename Geometry2, typename GeometryOut,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type,
+ typename TagOut = typename geometry::tag<GeometryOut>::type
>
struct intersection
{
- template
- <
- typename Geometry1,
- typename Geometry2,
- typename GeometryOut
- >
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- GeometryOut & geometry_out,
- Strategy const& strategy)
+ template <typename Strategy>
+ static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ GeometryOut & geometry_out, Strategy const& strategy)
{
typedef typename geometry::rescale_overlay_policy_type
<
@@ -133,7 +127,7 @@ struct intersection
Geometry2,
typename Strategy::cs_tag
>::type rescale_policy_type;
-
+
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(
geometry1, geometry2, strategy);
@@ -147,6 +141,36 @@ struct intersection
}
};
+} // namespace resolve_collection
+
+
+namespace resolve_strategy {
+
+template
+<
+ typename Strategy,
+ bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
+>
+struct intersection
+{
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename GeometryOut
+ >
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut & geometry_out,
+ Strategy const& strategy)
+ {
+ return resolve_collection::intersection
+ <
+ Geometry1, Geometry2, GeometryOut
+ >::apply(geometry1, geometry2, geometry_out, strategy);
+ }
+};
+
template <typename Strategy>
struct intersection<Strategy, false>
{
@@ -199,21 +223,24 @@ struct intersection<default_strategy, false>
} // resolve_strategy
-namespace resolve_variant
+namespace resolve_dynamic
{
-
-template <typename Geometry1, typename Geometry2>
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct intersection
{
template <typename GeometryOut, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- GeometryOut& geometry_out,
- Strategy const& strategy)
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ GeometryOut& geometry_out, Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
-
+
return resolve_strategy::intersection
<
Strategy
@@ -222,135 +249,70 @@ struct intersection
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
+struct intersection<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename GeometryOut, typename Strategy>
- struct visitor: static_visitor<bool>
+ static inline bool apply(DynamicGeometry1 const& geometry1, Geometry2 const& geometry2,
+ GeometryOut& geometry_out, Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- GeometryOut& m_geometry_out;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2,
- GeometryOut& geometry_out,
- Strategy const& strategy)
- : m_geometry2(geometry2)
- , m_geometry_out(geometry_out)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- bool operator()(Geometry1 const& geometry1) const
+ bool result = false;
+ traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
{
- return intersection
+ result = intersection
<
- Geometry1,
+ util::remove_cref_t<decltype(g1)>,
Geometry2
- >::apply(geometry1, m_geometry2, m_geometry_out, m_strategy);
- }
- };
-
- template <typename GeometryOut, typename Strategy>
- static inline bool
- apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- GeometryOut& geometry_out,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry2,
- geometry_out,
- strategy),
- geometry1);
+ >::apply(g1, geometry2, geometry_out, strategy);
+ }, geometry1);
+ return result;
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
+struct intersection<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
{
template <typename GeometryOut, typename Strategy>
- struct visitor: static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1, DynamicGeometry2 const& geometry2,
+ GeometryOut& geometry_out, Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- GeometryOut& m_geometry_out;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1,
- GeometryOut& geometry_out,
- Strategy const& strategy)
- : m_geometry1(geometry1)
- , m_geometry_out(geometry_out)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- bool operator()(Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
{
- return intersection
+ result = intersection
<
Geometry1,
- Geometry2
- >::apply(m_geometry1, geometry2, m_geometry_out, m_strategy);
- }
- };
-
- template <typename GeometryOut, typename Strategy>
- static inline bool
- apply(Geometry1 const& geometry1,
- variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- GeometryOut& geometry_out,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry1,
- geometry_out,
- strategy),
- geometry2);
+ util::remove_cref_t<decltype(g2)>
+ >::apply(geometry1, g2, geometry_out, strategy);
+ }, geometry2);
+ return result;
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
-struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
+template <typename DynamicGeometry1, typename DynamicGeometry2>
+struct intersection<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename GeometryOut, typename Strategy>
- struct visitor: static_visitor<bool>
+ static inline bool apply(DynamicGeometry1 const& geometry1, DynamicGeometry2 const& geometry2,
+ GeometryOut& geometry_out, Strategy const& strategy)
{
- GeometryOut& m_geometry_out;
- Strategy const& m_strategy;
-
- visitor(GeometryOut& geometry_out, Strategy const& strategy)
- : m_geometry_out(geometry_out)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1, typename Geometry2>
- bool operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
{
- return intersection
+ result = intersection
<
- Geometry1,
- Geometry2
- >::apply(geometry1, geometry2, m_geometry_out, m_strategy);
- }
- };
-
- template <typename GeometryOut, typename Strategy>
- static inline bool
- apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- GeometryOut& geometry_out,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry_out,
- strategy),
- geometry1, geometry2);
+ util::remove_cref_t<decltype(g1)>,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(g1, g2, geometry_out, strategy);
+ }, geometry1, geometry2);
+ return result;
}
};
-
-} // namespace resolve_variant
-
+
+} // namespace resolve_dynamic
+
/*!
\brief \brief_calc2{intersection}
@@ -382,7 +344,7 @@ inline bool intersection(Geometry1 const& geometry1,
GeometryOut& geometry_out,
Strategy const& strategy)
{
- return resolve_variant::intersection
+ return resolve_dynamic::intersection
<
Geometry1,
Geometry2
@@ -415,7 +377,7 @@ inline bool intersection(Geometry1 const& geometry1,
Geometry2 const& geometry2,
GeometryOut& geometry_out)
{
- return resolve_variant::intersection
+ return resolve_dynamic::intersection
<
Geometry1,
Geometry2
diff --git a/boost/geometry/algorithms/detail/intersection/multi.hpp b/boost/geometry/algorithms/detail/intersection/multi.hpp
index 42b9997fd0..7810abab50 100644
--- a/boost/geometry/algorithms/detail/intersection/multi.hpp
+++ b/boost/geometry/algorithms/detail/intersection/multi.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2020.
-// Modifications copyright (c) 2014-2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -22,6 +22,8 @@
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
+
// TODO: those headers probably may be removed
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
@@ -33,7 +35,6 @@
#include <boost/geometry/algorithms/detail/intersection/interface.hpp>
-#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
@@ -63,19 +64,9 @@ struct intersection_multi_linestring_multi_linestring_point
{
// Note, this loop is quadratic w.r.t. number of linestrings per input.
// Future Enhancement: first do the sections of each, then intersect.
- for (typename boost::range_iterator
- <
- MultiLinestring1 const
- >::type it1 = boost::begin(ml1);
- it1 != boost::end(ml1);
- ++it1)
+ for (auto it1 = boost::begin(ml1); it1 != boost::end(ml1); ++it1)
{
- for (typename boost::range_iterator
- <
- MultiLinestring2 const
- >::type it2 = boost::begin(ml2);
- it2 != boost::end(ml2);
- ++it2)
+ for (auto it2 = boost::begin(ml2); it2 != boost::end(ml2); ++it2)
{
out = intersection_linestring_linestring_point<PointOut>
::apply(*it1, *it2, robust_policy, out, strategy);
@@ -102,12 +93,7 @@ struct intersection_linestring_multi_linestring_point
OutputIterator out,
Strategy const& strategy)
{
- for (typename boost::range_iterator
- <
- MultiLinestring const
- >::type it = boost::begin(ml);
- it != boost::end(ml);
- ++it)
+ for (auto it = boost::begin(ml); it != boost::end(ml); ++it)
{
out = intersection_linestring_linestring_point<PointOut>
::apply(linestring, *it, robust_policy, out, strategy);
@@ -140,12 +126,7 @@ struct intersection_of_multi_linestring_with_areal
OutputIterator out,
Strategy const& strategy)
{
- for (typename boost::range_iterator
- <
- MultiLinestring const
- >::type it = boost::begin(ml);
- it != boost::end(ml);
- ++it)
+ for (auto it = boost::begin(ml); it != boost::end(ml); ++it)
{
out = intersection_of_linestring_with_areal
<
@@ -204,9 +185,7 @@ struct clip_multi_linestring
{
typedef typename point_type<LinestringOut>::type point_type;
strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
- for (typename boost::range_iterator<MultiLinestring const>::type it
- = boost::begin(multi_linestring);
- it != boost::end(multi_linestring); ++it)
+ for (auto it = boost::begin(multi_linestring); it != boost::end(multi_linestring); ++it)
{
out = detail::intersection::clip_range_with_box
<LinestringOut>(box, *it, robust_policy, out, lb_strategy);
@@ -537,6 +516,40 @@ struct intersection_insert
template
<
+ typename Linestring, typename MultiPolygon,
+ typename TupledOut,
+ overlay_type OverlayType,
+ bool ReverseMultiLinestring, bool ReverseMultiPolygon
+>
+struct intersection_insert
+ <
+ Linestring, MultiPolygon,
+ TupledOut,
+ OverlayType,
+ ReverseMultiLinestring, ReverseMultiPolygon,
+ linestring_tag, multi_polygon_tag, detail::tupled_output_tag,
+ linear_tag, areal_tag, detail::tupled_output_tag
+ > : detail::intersection::intersection_of_linestring_with_areal
+ <
+ ReverseMultiPolygon, TupledOut, OverlayType, true
+ >
+ , detail::expect_output
+ <
+ Linestring, MultiPolygon, TupledOut,
+ // NOTE: points can be the result only in case of intersection.
+ // TODO: union should require L and A
+ std::conditional_t
+ <
+ (OverlayType == overlay_intersection),
+ point_tag,
+ void
+ >,
+ linestring_tag
+ >
+{};
+
+template
+<
typename MultiLinestring, typename MultiPolygon,
typename TupledOut,
overlay_type OverlayType,
diff --git a/boost/geometry/algorithms/detail/is_simple/areal.hpp b/boost/geometry/algorithms/detail/is_simple/areal.hpp
index 4fc3fa26e5..952aa4e549 100644
--- a/boost/geometry/algorithms/detail/is_simple/areal.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/areal.hpp
@@ -49,12 +49,12 @@ template <typename InteriorRings, typename Strategy>
inline bool are_simple_interior_rings(InteriorRings const& interior_rings,
Strategy const& strategy)
{
- auto const end = boost::end(interior_rings);
- return std::find_if(boost::begin(interior_rings), end,
- [&](auto const& r)
- {
- return ! is_simple_ring(r, strategy);
- }) == end; // non-simple ring not found
+ return std::all_of(boost::begin(interior_rings),
+ boost::end(interior_rings),
+ [&](auto const& r)
+ {
+ return is_simple_ring(r, strategy);
+ }); // non-simple ring not found
// allow empty ring
}
@@ -116,12 +116,11 @@ struct is_simple<MultiPolygon, multi_polygon_tag>
template <typename Strategy>
static inline bool apply(MultiPolygon const& multipolygon, Strategy const& strategy)
{
- auto const end = boost::end(multipolygon);
- return std::find_if(boost::begin(multipolygon), end,
- [&](auto const& po) {
- return ! detail::is_simple::is_simple_polygon(po, strategy);
- }) == end; // non-simple polygon not found
- // allow empty multi-polygon
+ return std::none_of(boost::begin(multipolygon), boost::end(multipolygon),
+ [&](auto const& po) {
+ return ! detail::is_simple::is_simple_polygon(po, strategy);
+ }); // non-simple polygon not found
+ // allow empty multi-polygon
}
};
diff --git a/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp b/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp
index b336d44f67..7136e5167e 100644
--- a/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp
@@ -69,9 +69,7 @@ struct debug_boundary_points_printer<MultiLinestring, multi_linestring_tag>
typedef std::vector<point_type> point_vector;
point_vector boundary_points;
- for (typename boost::range_iterator<MultiLinestring const>::type it
- = boost::begin(multilinestring);
- it != boost::end(multilinestring); ++it)
+ for (auto it = boost::begin(multilinestring); it != boost::end(multilinestring); ++it)
{
if ( boost::size(*it) > 1
&& !geometry::equals(range::front(*it), range::back(*it)) )
@@ -85,11 +83,9 @@ struct debug_boundary_points_printer<MultiLinestring, multi_linestring_tag>
geometry::less<point_type>());
std::cout << "boundary points: ";
- for (typename point_vector::const_iterator
- pit = boundary_points.begin();
- pit != boundary_points.end(); ++pit)
+ for (auto const& p : boundary_points)
{
- std::cout << " " << geometry::dsv(*pit);
+ std::cout << " " << geometry::dsv(p);
}
std::cout << std::endl << std::endl;
}
diff --git a/boost/geometry/algorithms/detail/is_simple/linear.hpp b/boost/geometry/algorithms/detail/is_simple/linear.hpp
index 090824c25e..e2ac77ad56 100644
--- a/boost/geometry/algorithms/detail/is_simple/linear.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/linear.hpp
@@ -2,6 +2,7 @@
// Copyright (c) 2014-2021, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -36,7 +37,6 @@
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
@@ -158,7 +158,7 @@ public:
inline bool apply(Turn const& turn) const
{
typedef typename boost::range_value<MultiLinestring>::type linestring_type;
-
+
linestring_type const& ls1 =
range::at(m_multilinestring, turn.operations[0].seg_id.multi_index);
@@ -261,16 +261,16 @@ struct is_simple_multilinestring
{
private:
template <typename Strategy>
- struct per_linestring
+ struct not_simple
{
- per_linestring(Strategy const& strategy)
+ not_simple(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Linestring>
- inline bool apply(Linestring const& linestring) const
+ inline bool operator()(Linestring const& linestring) const
{
- return detail::is_simple::is_simple_linestring
+ return ! detail::is_simple::is_simple_linestring
<
Linestring,
false // do not compute self-intersections
@@ -285,19 +285,16 @@ public:
static inline bool apply(MultiLinestring const& multilinestring,
Strategy const& strategy)
{
- typedef per_linestring<Strategy> per_ls;
-
// check each of the linestrings for simplicity
// but do not compute self-intersections yet; these will be
// computed for the entire multilinestring
- if ( ! detail::check_iterator_range
- <
- per_ls, // do not compute self-intersections
- true // allow empty multilinestring
- >::apply(boost::begin(multilinestring),
- boost::end(multilinestring),
- per_ls(strategy))
- )
+ // return true for empty multilinestring
+
+ using not_simple = not_simple<Strategy>; // do not compute self-intersections
+
+ if (std::any_of(boost::begin(multilinestring),
+ boost::end(multilinestring),
+ not_simple(strategy)))
{
return false;
}
diff --git a/boost/geometry/algorithms/detail/is_simple/multipoint.hpp b/boost/geometry/algorithms/detail/is_simple/multipoint.hpp
index 2d2e52130f..2eba68f97e 100644
--- a/boost/geometry/algorithms/detail/is_simple/multipoint.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/multipoint.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2021, Oracle and/or its affiliates.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -44,12 +45,11 @@ struct is_simple_multipoint
template <typename Strategy>
static inline bool apply(MultiPoint const& multipoint, Strategy const& strategy)
{
- typedef typename Strategy::cs_tag cs_tag;
typedef geometry::less
<
typename point_type<MultiPoint>::type,
-1,
- cs_tag
+ Strategy
> less_type;
if (boost::empty(multipoint))
diff --git a/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp b/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp
index 67a94f1016..9a51d30eb4 100644
--- a/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, 2018, 2019, Oracle and/or its affiliates.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -32,7 +33,7 @@ namespace detail { namespace is_valid
{
-template <typename TurnPoint, typename CSTag>
+template <typename TurnPoint, typename Strategy>
class complement_graph_vertex
{
public:
@@ -55,7 +56,7 @@ public:
{
return geometry::less
<
- TurnPoint, -1, CSTag
+ TurnPoint, -1, Strategy
>()(*m_turn_point, *other.m_turn_point);
}
if ( m_turn_point == NULL && other.m_turn_point == NULL )
@@ -77,11 +78,11 @@ private:
-template <typename TurnPoint, typename CSTag>
+template <typename TurnPoint, typename Strategy>
class complement_graph
{
private:
- typedef complement_graph_vertex<TurnPoint, CSTag> vertex;
+ typedef complement_graph_vertex<TurnPoint, Strategy> vertex;
typedef std::set<vertex> vertex_container;
public:
@@ -224,9 +225,10 @@ public:
}
#ifdef BOOST_GEOMETRY_TEST_DEBUG
- template <typename OStream, typename TP>
+ template <typename OutputStream>
friend inline
- void debug_print_complement_graph(OStream&, complement_graph<TP> const&);
+ void debug_print_complement_graph(OutputStream&,
+ complement_graph<TurnPoint, Strategy> const&);
#endif // BOOST_GEOMETRY_TEST_DEBUG
private:
diff --git a/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp b/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp
index 5d16e2ea3c..4e4b978b53 100644
--- a/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, 2018, 2019, Oracle and/or its affiliates.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -25,12 +26,12 @@ namespace detail { namespace is_valid
#ifdef BOOST_GEOMETRY_TEST_DEBUG
-template <typename OutputStream, typename TurnPoint, typename CSTag>
+template <typename OutputStream, typename TurnPoint, typename Strategy>
inline void
debug_print_complement_graph(OutputStream& os,
- complement_graph<TurnPoint, CSTag> const& graph)
+ complement_graph<TurnPoint, Strategy> const& graph)
{
- typedef typename complement_graph<TurnPoint>::vertex_handle vertex_handle;
+ typedef typename complement_graph<TurnPoint, Strategy>::vertex_handle vertex_handle;
os << "num rings: " << graph.m_num_rings << std::endl;
os << "vertex ids: {";
@@ -39,7 +40,7 @@ debug_print_complement_graph(OutputStream& os,
{
os << " " << it->id();
}
- os << " }" << std::endl;
+ os << " }" << std::endl;
for (vertex_handle it = graph.m_vertices.begin();
it != graph.m_vertices.end(); ++it)
@@ -47,20 +48,20 @@ debug_print_complement_graph(OutputStream& os,
os << "neighbors of " << it->id() << ": {";
for (typename complement_graph
<
- TurnPoint
+ TurnPoint, Strategy
>::neighbor_container::const_iterator
nit = graph.m_neighbors[it->id()].begin();
nit != graph.m_neighbors[it->id()].end(); ++nit)
{
os << " " << (*nit)->id();
}
- os << "}" << std::endl;
+ os << "}" << std::endl;
}
}
#else
-template <typename OutputStream, typename TurnPoint, typename CSTag>
+template <typename OutputStream, typename TurnPoint, typename Strategy>
inline void debug_print_complement_graph(OutputStream&,
- complement_graph<TurnPoint, CSTag> const&)
+ complement_graph<TurnPoint, Strategy> const&)
{
}
#endif
diff --git a/boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp b/boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp
index ce0853d20c..82a1f5f4cd 100644
--- a/boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-2021, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -14,7 +15,6 @@
#include <cstddef>
#include <type_traits>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/validity_failure_type.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
@@ -28,7 +28,7 @@
namespace boost { namespace geometry
{
-
+
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace is_valid
{
@@ -80,26 +80,19 @@ struct indexed_has_invalid_coordinate
struct range_has_invalid_coordinate
{
- struct point_has_valid_coordinates
- {
- template <typename Point>
- static inline bool apply(Point const& point)
- {
- return ! point_has_invalid_coordinate::apply(point);
- }
- };
-
template <typename Geometry, typename VisitPolicy>
static inline bool apply(Geometry const& geometry, VisitPolicy& visitor)
{
boost::ignore_unused(visitor);
- bool const has_valid_coordinates = detail::check_iterator_range
- <
- point_has_valid_coordinates,
- true // do not consider an empty range as problematic
- >::apply(geometry::points_begin(geometry),
- geometry::points_end(geometry));
+ auto const points_end = geometry::points_end(geometry);
+ bool const has_valid_coordinates = std::none_of
+ (
+ geometry::points_begin(geometry), points_end,
+ []( auto const& point ){
+ return point_has_invalid_coordinate::apply(point);
+ }
+ );
return has_valid_coordinates
?
diff --git a/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp b/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp
index 6dbaa49bc7..08e9ab43d2 100644
--- a/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp
@@ -56,7 +56,9 @@ struct has_spikes
Strategy const& strategy)
{
if (first == last)
+ {
return last;
+ }
auto const& front = *first;
++first;
return std::find_if(first, last, [&](auto const& pt) {
@@ -71,18 +73,12 @@ struct has_spikes
{
boost::ignore_unused(visitor);
- typedef typename boost::range_iterator<View const>::type iterator;
+ auto cur = boost::begin(view);
+ auto prev = find_different_from_first(boost::rbegin(view),
+ boost::rend(view),
+ strategy);
- iterator cur = boost::begin(view);
- typename boost::range_reverse_iterator
- <
- View const
- >::type prev = find_different_from_first(boost::rbegin(view),
- boost::rend(view),
- strategy);
-
- iterator next = find_different_from_first(cur, boost::end(view),
- strategy);
+ auto next = find_different_from_first(cur, boost::end(view), strategy);
if (detail::is_spike_or_equal(*next, *cur, *prev, strategy.side()))
{
return ! visitor.template apply<failure_spikes>(is_linear, *cur);
@@ -131,8 +127,7 @@ struct has_spikes
// also in geographic cases going over the pole
if (detail::is_spike_or_equal(*next, *cur, *prev, strategy.side()))
{
- return
- ! visitor.template apply<failure_spikes>(is_linestring, *cur);
+ return ! visitor.template apply<failure_spikes>(is_linestring, *cur);
}
prev = cur;
cur = next;
diff --git a/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp b/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp
index 6c33961b3b..b12c42c8e9 100644
--- a/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -54,11 +54,6 @@ private:
CSTag
>::type rescale_policy_type;
- typedef detail::overlay::get_turn_info
- <
- detail::overlay::assign_null_policy
- > turn_policy;
-
public:
typedef detail::overlay::turn_info
<
@@ -88,12 +83,11 @@ public:
> interrupt_policy;
// Calculate self-turns, skipping adjacent segments
- detail::self_get_turn_points::self_turns<false, turn_policy>(geometry,
- strategy,
- robust_policy,
- turns,
- interrupt_policy,
- 0, true);
+ detail::self_get_turn_points::self_turns
+ <
+ false, detail::overlay::assign_null_policy
+ >(geometry, strategy, robust_policy, turns, interrupt_policy,
+ 0, true);
if (interrupt_policy.has_intersections)
{
diff --git a/boost/geometry/algorithms/detail/is_valid/interface.hpp b/boost/geometry/algorithms/detail/is_valid/interface.hpp
index 4f8d1f5435..53576d20cb 100644
--- a/boost/geometry/algorithms/detail/is_valid/interface.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/interface.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -14,12 +14,11 @@
#include <sstream>
#include <string>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
+#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/algorithms/dispatch/is_valid.hpp>
#include <boost/geometry/core/cs.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/policies/is_valid/default_policy.hpp>
#include <boost/geometry/policies/is_valid/failing_reason_policy.hpp>
@@ -31,7 +30,7 @@
namespace boost { namespace geometry
{
-
+
namespace resolve_strategy
{
@@ -90,10 +89,10 @@ struct is_valid<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant
+namespace resolve_dynamic
{
-template <typename Geometry>
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct is_valid
{
template <typename VisitPolicy, typename Strategy>
@@ -110,39 +109,42 @@ struct is_valid
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct is_valid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct is_valid<Geometry, dynamic_geometry_tag>
{
template <typename VisitPolicy, typename Strategy>
- struct visitor : boost::static_visitor<bool>
+ static inline bool apply(Geometry const& geometry,
+ VisitPolicy& policy_visitor,
+ Strategy const& strategy)
{
- visitor(VisitPolicy& policy, Strategy const& strategy)
- : m_policy(policy)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry>
- bool operator()(Geometry const& geometry) const
+ bool result = true;
+ traits::visit<Geometry>::apply([&](auto const& g)
{
- return is_valid<Geometry>::apply(geometry, m_policy, m_strategy);
- }
-
- VisitPolicy& m_policy;
- Strategy const& m_strategy;
- };
+ result = is_valid<util::remove_cref_t<decltype(g)>>::apply(g, policy_visitor, strategy);
+ }, geometry);
+ return result;
+ }
+};
+template <typename Geometry>
+struct is_valid<Geometry, geometry_collection_tag>
+{
template <typename VisitPolicy, typename Strategy>
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- VisitPolicy& policy_visitor,
- Strategy const& strategy)
+ static inline bool apply(Geometry const& geometry,
+ VisitPolicy& policy_visitor,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<VisitPolicy, Strategy>(policy_visitor, strategy),
- geometry);
+ bool result = true;
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ result = is_valid<util::remove_cref_t<decltype(g)>>::apply(g, policy_visitor, strategy);
+ return result;
+ }, geometry);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
// Undocumented for now
@@ -151,7 +153,7 @@ inline bool is_valid(Geometry const& geometry,
VisitPolicy& visitor,
Strategy const& strategy)
{
- return resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
+ return resolve_dynamic::is_valid<Geometry>::apply(geometry, visitor, strategy);
}
@@ -175,7 +177,7 @@ template <typename Geometry, typename Strategy>
inline bool is_valid(Geometry const& geometry, Strategy const& strategy)
{
is_valid_default_policy<> visitor;
- return resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
+ return resolve_dynamic::is_valid<Geometry>::apply(geometry, visitor, strategy);
}
/*!
@@ -220,7 +222,7 @@ template <typename Geometry, typename Strategy>
inline bool is_valid(Geometry const& geometry, validity_failure_type& failure, Strategy const& strategy)
{
failure_type_policy<> visitor;
- bool result = resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
+ bool result = resolve_dynamic::is_valid<Geometry>::apply(geometry, visitor, strategy);
failure = visitor.failure();
return result;
}
@@ -271,7 +273,7 @@ inline bool is_valid(Geometry const& geometry, std::string& message, Strategy co
{
std::ostringstream stream;
failing_reason_policy<> visitor(stream);
- bool result = resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
+ bool result = resolve_dynamic::is_valid<Geometry>::apply(geometry, visitor, strategy);
message = stream.str();
return result;
}
diff --git a/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp b/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp
index 9ca82b1071..4aad18881d 100644
--- a/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp
@@ -151,7 +151,7 @@ public:
|| turn.method == method_touch_interior)
&& turn.touch_only;
}
-};
+};
}} // namespace detail::is_valid
diff --git a/boost/geometry/algorithms/detail/is_valid/linear.hpp b/boost/geometry/algorithms/detail/is_valid/linear.hpp
index 69cb76e5d5..3753c87a42 100644
--- a/boost/geometry/algorithms/detail/is_valid/linear.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/linear.hpp
@@ -1,7 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2021, Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2014-2021, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -20,7 +22,6 @@
#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/algorithms/validity_failure_type.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp>
#include <boost/geometry/algorithms/detail/is_valid/has_spikes.hpp>
#include <boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp>
@@ -31,7 +32,7 @@
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
-#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/constexpr.hpp>
namespace boost { namespace geometry
@@ -105,7 +106,7 @@ namespace dispatch
// A curve is simple if it does not pass through the same point twice,
// with the possible exception of its two endpoints
//
-// There is an option here as to whether spikes are allowed for linestrings;
+// There is an option here as to whether spikes are allowed for linestrings;
// here we pass this as an additional template parameter: allow_spikes
// If allow_spikes is set to true, spikes are allowed, false otherwise.
// By default, spikes are disallowed
@@ -131,7 +132,6 @@ class is_valid
MultiLinestring, multi_linestring_tag, AllowEmptyMultiGeometries
>
{
-private:
template <typename VisitPolicy, typename Strategy>
struct per_linestring
{
@@ -141,7 +141,7 @@ private:
{}
template <typename Linestring>
- inline bool apply(Linestring const& linestring) const
+ inline bool operator()(Linestring const& linestring) const
{
return detail::is_valid::is_valid_linestring
<
@@ -159,21 +159,19 @@ public:
VisitPolicy& visitor,
Strategy const& strategy)
{
- if (BOOST_GEOMETRY_CONDITION(
- AllowEmptyMultiGeometries && boost::empty(multilinestring)))
+ if BOOST_GEOMETRY_CONSTEXPR (AllowEmptyMultiGeometries)
{
- return visitor.template apply<no_failure>();
+ if (boost::empty(multilinestring))
+ {
+ return visitor.template apply<no_failure>();
+ }
}
- typedef per_linestring<VisitPolicy, Strategy> per_ls;
+ using per_ls = per_linestring<VisitPolicy, Strategy>;
- return detail::check_iterator_range
- <
- per_ls,
- false // do not check for empty multilinestring (done above)
- >::apply(boost::begin(multilinestring),
- boost::end(multilinestring),
- per_ls(visitor, strategy));
+ return std::all_of(boost::begin(multilinestring),
+ boost::end(multilinestring),
+ per_ls(visitor, strategy));
}
};
diff --git a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
index 0b3b4c4a74..5af933de85 100644
--- a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
@@ -1,7 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2014-2021, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -26,7 +28,7 @@
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tags.hpp>
-#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/constexpr.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/geometries/box.hpp>
@@ -34,7 +36,6 @@
#include <boost/geometry/algorithms/validity_failure_type.hpp>
#include <boost/geometry/algorithms/within.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
#include <boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp>
@@ -257,55 +258,56 @@ private:
template <typename VisitPolicy, typename Strategy>
- struct per_polygon
+ struct is_invalid_polygon
{
- per_polygon(VisitPolicy& policy, Strategy const& strategy)
+ is_invalid_polygon(VisitPolicy& policy, Strategy const& strategy)
: m_policy(policy)
, m_strategy(strategy)
{}
template <typename Polygon>
- inline bool apply(Polygon const& polygon) const
+ inline bool operator()(Polygon const& polygon) const
{
- return base::apply(polygon, m_policy, m_strategy);
+ return ! base::apply(polygon, m_policy, m_strategy);
}
VisitPolicy& m_policy;
Strategy const& m_strategy;
};
+
public:
template <typename VisitPolicy, typename Strategy>
static inline bool apply(MultiPolygon const& multipolygon,
VisitPolicy& visitor,
Strategy const& strategy)
{
- typedef debug_validity_phase<MultiPolygon> debug_phase;
+ using debug_phase = debug_validity_phase<MultiPolygon>;
- if (BOOST_GEOMETRY_CONDITION(AllowEmptyMultiGeometries)
- && boost::empty(multipolygon))
+ if BOOST_GEOMETRY_CONSTEXPR (AllowEmptyMultiGeometries)
{
- return visitor.template apply<no_failure>();
+ if (boost::empty(multipolygon))
+ {
+ return visitor.template apply<no_failure>();
+ }
}
// check validity of all polygons ring
debug_phase::apply(1);
- if (! detail::check_iterator_range
- <
- per_polygon<VisitPolicy, Strategy>,
- false // do not check for empty multipolygon (done above)
- >::apply(boost::begin(multipolygon),
- boost::end(multipolygon),
- per_polygon<VisitPolicy, Strategy>(visitor, strategy)))
+ if (std::any_of(boost::begin(multipolygon), boost::end(multipolygon),
+ is_invalid_polygon<VisitPolicy, Strategy>(visitor, strategy)))
{
return false;
}
-
// compute turns and check if all are acceptable
debug_phase::apply(2);
- typedef has_valid_self_turns<MultiPolygon, typename Strategy::cs_tag> has_valid_turns;
+ using has_valid_turns = has_valid_self_turns
+ <
+ MultiPolygon,
+ typename Strategy::cs_tag
+ >;
std::deque<typename has_valid_turns::turn_type> turns;
bool has_invalid_turns =
diff --git a/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/boost/geometry/algorithms/detail/is_valid/polygon.hpp
index 72ae593f8e..39512ad154 100644
--- a/boost/geometry/algorithms/detail/is_valid/polygon.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/polygon.hpp
@@ -1,9 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2017-2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -34,7 +34,7 @@
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tags.hpp>
-#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/constexpr.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/util/sequence.hpp>
@@ -50,7 +50,6 @@
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/within.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
#include <boost/geometry/algorithms/detail/is_valid/complement_graph.hpp>
@@ -86,17 +85,17 @@ class is_valid_polygon
protected:
template <typename VisitPolicy, typename Strategy>
- struct per_ring
+ struct is_invalid_ring
{
- per_ring(VisitPolicy& policy, Strategy const& strategy)
+ is_invalid_ring(VisitPolicy& policy, Strategy const& strategy)
: m_policy(policy)
, m_strategy(strategy)
{}
template <typename Ring>
- inline bool apply(Ring const& ring) const
+ inline bool operator()(Ring const& ring) const
{
- return detail::is_valid::is_valid_ring
+ return ! detail::is_valid::is_valid_ring
<
Ring, false, true
>::apply(ring, m_policy, m_strategy);
@@ -111,14 +110,9 @@ protected:
VisitPolicy& visitor,
Strategy const& strategy)
{
- return
- detail::check_iterator_range
- <
- per_ring<VisitPolicy, Strategy>,
- true // allow for empty interior ring range
- >::apply(boost::begin(interior_rings),
- boost::end(interior_rings),
- per_ring<VisitPolicy, Strategy>(visitor, strategy));
+ return std::none_of(boost::begin(interior_rings),
+ boost::end(interior_rings),
+ is_invalid_ring<VisitPolicy, Strategy>(visitor, strategy));
}
struct has_valid_rings
@@ -372,7 +366,7 @@ protected:
}
struct has_holes_inside
- {
+ {
template <typename TurnIterator, typename VisitPolicy, typename Strategy>
static inline bool apply(Polygon const& polygon,
TurnIterator first,
@@ -410,7 +404,7 @@ protected:
typedef complement_graph
<
typename turn_type::point_type,
- typename Strategy::cs_tag
+ Strategy
> graph;
graph g(geometry::num_interior_rings(polygon) + 1);
@@ -452,7 +446,7 @@ public:
return false;
}
- if (BOOST_GEOMETRY_CONDITION(CheckRingValidityOnly))
+ if BOOST_GEOMETRY_CONSTEXPR (CheckRingValidityOnly)
{
return true;
}
diff --git a/boost/geometry/algorithms/detail/make/make.hpp b/boost/geometry/algorithms/detail/make/make.hpp
index 566936b86a..45aa6ed473 100644
--- a/boost/geometry/algorithms/detail/make/make.hpp
+++ b/boost/geometry/algorithms/detail/make/make.hpp
@@ -19,10 +19,10 @@ namespace boost { namespace geometry
namespace detail { namespace make
{
-template <typename Type, typename Coordinate>
+template <typename Type, typename Coordinate1, typename Coordinate2>
inline
-model::infinite_line<Type> make_infinite_line(Coordinate const& x1,
- Coordinate const& y1, Coordinate const& x2, Coordinate const& y2)
+model::infinite_line<Type> make_infinite_line(Coordinate1 const& x1,
+ Coordinate1 const& y1, Coordinate2 const& x2, Coordinate2 const& y2)
{
model::infinite_line<Type> result;
result.a = y1 - y2;
@@ -31,9 +31,9 @@ model::infinite_line<Type> make_infinite_line(Coordinate const& x1,
return result;
}
-template <typename Type, typename Point>
+template <typename Type, typename PointA, typename PointB>
inline
-model::infinite_line<Type> make_infinite_line(Point const& a, Point const& b)
+model::infinite_line<Type> make_infinite_line(PointA const& a, PointB const& b)
{
return make_infinite_line<Type>(geometry::get<0>(a), geometry::get<1>(a),
geometry::get<0>(b), geometry::get<1>(b));
@@ -49,9 +49,9 @@ model::infinite_line<Type> make_infinite_line(Segment const& segment)
geometry::get<1, 1>(segment));
}
-template <typename Type, typename Point>
+template <typename Type, typename PointA, typename PointB, typename PointC>
inline
-model::infinite_line<Type> make_perpendicular_line(Point const& a, Point const& b, Point const& c)
+model::infinite_line<Type> make_perpendicular_line(PointA const& a, PointB const& b, PointC const& c)
{
// https://www.math-only-math.com/equation-of-a-line-perpendicular-to-a-line.html
model::infinite_line<Type> const line = make_infinite_line<Type>(a, b);
diff --git a/boost/geometry/algorithms/detail/max_interval_gap.hpp b/boost/geometry/algorithms/detail/max_interval_gap.hpp
index f71efc9aa6..905491ef36 100644
--- a/boost/geometry/algorithms/detail/max_interval_gap.hpp
+++ b/boost/geometry/algorithms/detail/max_interval_gap.hpp
@@ -225,7 +225,7 @@ maximum_gap(RangeOfIntervals const& range_of_intervals,
std::priority_queue
<
event_type,
- std::vector<event_type>,
+ std::vector<event_type>,
detail::max_interval_gap::event_greater<event_type>
> queue;
diff --git a/boost/geometry/algorithms/detail/multi_modify.hpp b/boost/geometry/algorithms/detail/multi_modify.hpp
index 9c2f180067..58597ed6f3 100644
--- a/boost/geometry/algorithms/detail/multi_modify.hpp
+++ b/boost/geometry/algorithms/detail/multi_modify.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// 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-2021.
+// Modifications copyright (c) 2017-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -32,27 +32,24 @@ namespace detail
{
-template <typename MultiGeometry, typename Policy>
+template <typename Policy>
struct multi_modify
{
+ template <typename MultiGeometry>
static inline void apply(MultiGeometry& multi)
{
- typedef typename boost::range_iterator<MultiGeometry>::type iterator_type;
- for (iterator_type it = boost::begin(multi);
- it != boost::end(multi);
- ++it)
+ auto const end = boost::end(multi);
+ for (auto it = boost::begin(multi); it != end; ++it)
{
Policy::apply(*it);
}
}
- template <typename Strategy>
+ template <typename MultiGeometry, typename Strategy>
static inline void apply(MultiGeometry& multi, Strategy const& strategy)
{
- typedef typename boost::range_iterator<MultiGeometry>::type iterator_type;
- for (iterator_type it = boost::begin(multi);
- it != boost::end(multi);
- ++it)
+ auto const end = boost::end(multi);
+ for (auto it = boost::begin(multi); it != end; ++it)
{
Policy::apply(*it, strategy);
}
diff --git a/boost/geometry/algorithms/detail/multi_modify_with_predicate.hpp b/boost/geometry/algorithms/detail/multi_modify_with_predicate.hpp
index 4dcc919e98..8d0ec2cb51 100644
--- a/boost/geometry/algorithms/detail/multi_modify_with_predicate.hpp
+++ b/boost/geometry/algorithms/detail/multi_modify_with_predicate.hpp
@@ -36,10 +36,7 @@ struct multi_modify_with_predicate
{
static inline void apply(MultiGeometry& multi, Predicate const& predicate)
{
- typedef typename boost::range_iterator<MultiGeometry>::type iterator_type;
- for (iterator_type it = boost::begin(multi);
- it != boost::end(multi);
- ++it)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
Policy::apply(*it, predicate);
}
diff --git a/boost/geometry/algorithms/detail/multi_sum.hpp b/boost/geometry/algorithms/detail/multi_sum.hpp
index d41a3689fd..1c5ad6bf51 100644
--- a/boost/geometry/algorithms/detail/multi_sum.hpp
+++ b/boost/geometry/algorithms/detail/multi_sum.hpp
@@ -31,15 +31,10 @@ namespace detail
struct multi_sum
{
template <typename ReturnType, typename Policy, typename MultiGeometry, typename Strategy>
- static inline ReturnType apply(MultiGeometry const& geometry, Strategy const& strategy)
+ static inline ReturnType apply(MultiGeometry const& multi, Strategy const& strategy)
{
ReturnType sum = ReturnType();
- for (typename boost::range_iterator
- <
- MultiGeometry const
- >::type it = boost::begin(geometry);
- it != boost::end(geometry);
- ++it)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
sum += Policy::apply(*it, strategy);
}
diff --git a/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp b/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp
index 5acc531d32..4b94ed4c4f 100644
--- a/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp
+++ b/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -19,6 +20,8 @@
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
+
namespace boost { namespace geometry
{
@@ -48,8 +51,6 @@ struct num_distinct_consecutive_points
template <typename Strategy>
static inline std::size_t apply(Range const& range, Strategy const& strategy)
{
- typedef typename boost::range_iterator<Range const>::type iterator;
-
std::size_t const size = boost::size(range);
if ( size < 2u )
@@ -57,13 +58,13 @@ struct num_distinct_consecutive_points
return (size < MaximumNumber) ? size : MaximumNumber;
}
- iterator current = boost::begin(range);
- iterator const end = boost::end(range);
+ auto current = boost::begin(range);
+ auto const end = boost::end(range);
std::size_t counter(0);
do
{
++counter;
- iterator next = std::find_if(current, end, [&](auto const& pt) {
+ auto next = std::find_if(current, end, [&](auto const& pt) {
return ! equals::equals_point_point(pt, *current, strategy);
});
current = next;
diff --git a/boost/geometry/algorithms/detail/overlaps/implementation.hpp b/boost/geometry/algorithms/detail/overlaps/implementation.hpp
index e056cbbdaf..5ab1b6ba7b 100644
--- a/boost/geometry/algorithms/detail/overlaps/implementation.hpp
+++ b/boost/geometry/algorithms/detail/overlaps/implementation.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -24,9 +24,11 @@
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/algorithms/detail/gc_topological_dimension.hpp>
#include <boost/geometry/algorithms/detail/overlaps/interface.hpp>
+#include <boost/geometry/algorithms/detail/relate/implementation.hpp>
+#include <boost/geometry/algorithms/detail/relate/implementation_gc.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
-#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
@@ -34,6 +36,8 @@
#include <boost/geometry/strategies/relate/geographic.hpp>
#include <boost/geometry/strategies/relate/spherical.hpp>
+#include <boost/geometry/views/detail/geometry_collection_view.hpp>
+
namespace boost { namespace geometry
{
@@ -150,6 +154,74 @@ struct overlaps<Box1, Box2, box_tag, box_tag>
: detail::overlaps::box_box
{};
+
+template <typename Geometry1, typename Geometry2>
+struct overlaps<Geometry1, Geometry2, geometry_collection_tag, geometry_collection_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ int dimension1 = detail::gc_topological_dimension(geometry1);
+ int dimension2 = detail::gc_topological_dimension(geometry2);
+
+ if (dimension1 >= 0 && dimension2 >= 0)
+ {
+ if (dimension1 == 1 && dimension2 == 1)
+ {
+ return detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_overlaps_d1_1_d2_1_type,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
+ }
+ else if (dimension1 == dimension2)
+ {
+ return detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_overlaps_d1_eq_d2_type,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
+ }
+ }
+
+ return false;
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct overlaps<Geometry1, Geometry2, Tag1, geometry_collection_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ using gc1_view_t = detail::geometry_collection_view<Geometry1>;
+ return overlaps
+ <
+ gc1_view_t, Geometry2
+ >::apply(gc1_view_t(geometry1), geometry2, strategy);
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct overlaps<Geometry1, Geometry2, geometry_collection_tag, Tag2>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ using gc2_view_t = detail::geometry_collection_view<Geometry2>;
+ return overlaps
+ <
+ Geometry1, gc2_view_t
+ >::apply(geometry1, gc2_view_t(geometry2), strategy);
+ }
+};
+
+
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
diff --git a/boost/geometry/algorithms/detail/overlaps/interface.hpp b/boost/geometry/algorithms/detail/overlaps/interface.hpp
index fbe0ffdae8..bc2cfb517b 100644
--- a/boost/geometry/algorithms/detail/overlaps/interface.hpp
+++ b/boost/geometry/algorithms/detail/overlaps/interface.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -24,6 +24,7 @@
#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
@@ -124,6 +125,96 @@ struct overlaps<default_strategy, false>
} // namespace resolve_strategy
+namespace resolve_dynamic
+{
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
+struct overlaps
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ return resolve_strategy::overlaps
+ <
+ Strategy
+ >::apply(geometry1, geometry2, strategy);
+ }
+};
+
+
+template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
+struct overlaps<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
+{
+ template <typename Strategy>
+ static inline bool apply(DynamicGeometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ bool result = false;
+ traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
+ {
+ result = resolve_strategy::overlaps
+ <
+ Strategy
+ >::apply(g1, geometry2, strategy);
+ }, geometry1);
+ return result;
+ }
+};
+
+
+template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
+struct overlaps<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ DynamicGeometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ bool result = false;
+ traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
+ {
+ result = resolve_strategy::overlaps
+ <
+ Strategy
+ >::apply(geometry1, g2, strategy);
+ }, geometry2);
+ return result;
+ }
+};
+
+
+template <typename DynamicGeometry1, typename DynamicGeometry2>
+struct overlaps<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(DynamicGeometry1 const& geometry1,
+ DynamicGeometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ bool result = false;
+ traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
+ {
+ result = resolve_strategy::overlaps
+ <
+ Strategy
+ >::apply(g1, g2, strategy);
+ }, geometry1, geometry2);
+ return result;
+ }
+};
+
+
+} // namespace resolve_dynamic
+
+
/*!
\brief \brief_check2{overlap}
\ingroup overlaps
@@ -146,9 +237,9 @@ inline bool overlaps(Geometry1 const& geometry1,
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
- return resolve_strategy::overlaps
+ return resolve_dynamic::overlaps
<
- Strategy
+ Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
}
@@ -174,9 +265,9 @@ inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2)
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
- return resolve_strategy::overlaps
+ return resolve_dynamic::overlaps
<
- default_strategy
+ Geometry1, Geometry2
>::apply(geometry1, geometry2, default_strategy());
}
diff --git a/boost/geometry/algorithms/detail/overlay/add_rings.hpp b/boost/geometry/algorithms/detail/overlay/add_rings.hpp
index 45f2e7f12f..026906b496 100644
--- a/boost/geometry/algorithms/detail/overlay/add_rings.hpp
+++ b/boost/geometry/algorithms/detail/overlay/add_rings.hpp
@@ -96,8 +96,6 @@ inline OutputIterator add_rings(SelectionMap const& map,
Strategy const& strategy,
add_rings_error_handling error_handling = add_rings_ignore_unordered)
{
- typedef typename SelectionMap::const_iterator iterator;
-
std::size_t const min_num_points = core_detail::closure::minimum_ring_size
<
geometry::closure
@@ -110,29 +108,23 @@ inline OutputIterator add_rings(SelectionMap const& map,
>::value;
- for (iterator it = boost::begin(map);
- it != boost::end(map);
- ++it)
+ for (auto const& pair : map)
{
- if (! it->second.discarded
- && it->second.parent.source_index == -1)
+ if (! pair.second.discarded
+ && pair.second.parent.source_index == -1)
{
GeometryOut result;
convert_and_add(result, geometry1, geometry2, collection,
- it->first, it->second.reversed, false);
+ pair.first, pair.second.reversed, false);
// Add children
- for (typename std::vector<ring_identifier>::const_iterator child_it
- = it->second.children.begin();
- child_it != it->second.children.end();
- ++child_it)
+ for (auto const& child : pair.second.children)
{
- iterator mit = map.find(*child_it);
- if (mit != map.end()
- && ! mit->second.discarded)
+ auto mit = map.find(child);
+ if (mit != map.end() && ! mit->second.discarded)
{
convert_and_add(result, geometry1, geometry2, collection,
- *child_it, mit->second.reversed, true);
+ child, mit->second.reversed, true);
}
}
diff --git a/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp b/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp
index f304600c00..a21ee9832b 100644
--- a/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp
+++ b/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp
@@ -23,6 +23,7 @@
#include <boost/static_assert.hpp>
#include <boost/geometry/algorithms/append.hpp>
+#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
@@ -99,7 +100,16 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point,
return;
}
- traits::push_back<Range>::apply(range, point);
+ auto append = [](auto& r, const auto& p)
+ {
+ using point_t = typename boost::range_value<Range>::type;
+ point_t rp;
+ geometry::detail::conversion::convert_point_to_point(p, rp);
+ traits::push_back<Range>::apply(r, std::move(rp));
+ };
+
+ append(range, point);
+
// If a point is equal, or forming a spike, remove the pen-ultimate point
// because this one caused the spike.
@@ -115,7 +125,7 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point,
{
// Use the Concept/traits, so resize and append again
traits::resize<Range>::apply(range, boost::size(range) - 2);
- traits::push_back<Range>::apply(range, point);
+ append(range, point);
}
}
@@ -174,7 +184,6 @@ inline void clean_closing_dups_and_spikes(Range& range,
return;
}
- typedef typename boost::range_iterator<Range>::type iterator_type;
static bool const closed = geometry::closure<Range>::value == geometry::closed;
// TODO: the following algorithm could be rewritten to first look for spikes
@@ -184,9 +193,9 @@ inline void clean_closing_dups_and_spikes(Range& range,
do
{
found = false;
- iterator_type first = boost::begin(range);
- iterator_type second = first + 1;
- iterator_type ultimate = boost::end(range) - 1;
+ auto first = boost::begin(range);
+ auto second = first + 1;
+ auto ultimate = boost::end(range) - 1;
if (BOOST_GEOMETRY_CONDITION(closed))
{
ultimate--;
diff --git a/boost/geometry/algorithms/detail/overlay/approximately_equals.hpp b/boost/geometry/algorithms/detail/overlay/approximately_equals.hpp
index d28a04ee8f..1f41085dc1 100644
--- a/boost/geometry/algorithms/detail/overlay/approximately_equals.hpp
+++ b/boost/geometry/algorithms/detail/overlay/approximately_equals.hpp
@@ -23,7 +23,7 @@ namespace detail { namespace overlay
template <typename Point1, typename Point2, typename E>
inline bool approximately_equals(Point1 const& a, Point2 const& b,
- E const& multiplier)
+ E const& epsilon_multiplier)
{
using coor_t = typename select_coordinate_type<Point1, Point2>::type;
using calc_t = typename geometry::select_most_precise<coor_t, E>::type;
@@ -34,7 +34,7 @@ inline bool approximately_equals(Point1 const& a, Point2 const& b,
calc_t const& b1 = geometry::get<1>(b);
math::detail::equals_factor_policy<calc_t> policy(a0, b0, a1, b1);
- policy.factor *= multiplier;
+ policy.multiply_epsilon(epsilon_multiplier);
return math::detail::equals_by_policy(a0, b0, policy)
&& math::detail::equals_by_policy(a1, b1, policy);
diff --git a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
index a4cfac4dc1..fb3ee1bef2 100644
--- a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
+++ b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
@@ -3,8 +3,9 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 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
// Use, modification and distribution is subject to the Boost Software License,
@@ -18,15 +19,19 @@
#include <boost/range/end.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
+
+#include <boost/geometry/algorithms/area_result.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/expand.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
#include <boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp>
-#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/geometries/box.hpp>
+#include <boost/geometry/util/for_each_with_index.hpp>
+
namespace boost { namespace geometry
{
@@ -260,38 +265,31 @@ inline void assign_parents(Geometry1 const& geometry1,
point_type, Strategy // TODO: point_type is technically incorrect
>::type area_result_type;
- typedef typename RingMap::iterator map_iterator_type;
-
{
- typedef ring_info_helper<point_type, area_result_type> helper;
- typedef std::vector<helper> vector_type;
- typedef typename boost::range_iterator<vector_type const>::type vector_iterator_type;
-
std::size_t count_total = ring_map.size();
std::size_t count_positive = 0;
std::size_t index_positive = 0; // only used if count_positive>0
- std::size_t index = 0;
- // Copy to vector (with new approach this might be obsolete as well, using the map directly)
- vector_type vector(count_total);
+ // Copy to vector (this might be obsolete, using the map directly)
+ using helper = ring_info_helper<point_type, area_result_type>;
+ std::vector<helper> vector(count_total);
- for (map_iterator_type it = boost::begin(ring_map);
- it != boost::end(ring_map); ++it, ++index)
+ for_each_with_index(ring_map, [&](std::size_t index, auto const& pair)
{
- vector[index] = helper(it->first, it->second.get_area());
+ vector[index] = helper(pair.first, pair.second.get_area());
helper& item = vector[index];
- switch(it->first.source_index)
+ switch(pair.first.source_index)
{
case 0 :
- geometry::envelope(get_ring<tag1>::apply(it->first, geometry1),
+ geometry::envelope(get_ring<tag1>::apply(pair.first, geometry1),
item.envelope, strategy);
break;
case 1 :
- geometry::envelope(get_ring<tag2>::apply(it->first, geometry2),
+ geometry::envelope(get_ring<tag2>::apply(pair.first, geometry2),
item.envelope, strategy);
break;
case 2 :
- geometry::envelope(get_ring<void>::apply(it->first, collection),
+ geometry::envelope(get_ring<void>::apply(pair.first, collection),
item.envelope, strategy);
break;
}
@@ -304,7 +302,7 @@ inline void assign_parents(Geometry1 const& geometry1,
count_positive++;
index_positive = index;
}
- }
+ });
if (! check_for_orientation)
{
@@ -325,17 +323,15 @@ inline void assign_parents(Geometry1 const& geometry1,
// located outside the outer ring, this cannot be done
ring_identifier id_of_positive = vector[index_positive].id;
ring_info_type& outer = ring_map[id_of_positive];
- index = 0;
- for (vector_iterator_type it = boost::begin(vector);
- it != boost::end(vector); ++it, ++index)
+ for_each_with_index(vector, [&](std::size_t index, auto const& item)
{
if (index != index_positive)
{
- ring_info_type& inner = ring_map[it->id];
+ ring_info_type& inner = ring_map[item.id];
inner.parent = id_of_positive;
- outer.children.push_back(it->id);
+ outer.children.push_back(item.id);
}
- }
+ });
return;
}
}
@@ -357,10 +353,9 @@ inline void assign_parents(Geometry1 const& geometry1,
if (check_for_orientation)
{
- for (map_iterator_type it = boost::begin(ring_map);
- it != boost::end(ring_map); ++it)
+ for (auto& pair : ring_map)
{
- ring_info_type& info = it->second;
+ ring_info_type& info = pair.second;
if (geometry::math::equals(info.get_area(), 0))
{
info.discarded = true;
@@ -397,12 +392,11 @@ inline void assign_parents(Geometry1 const& geometry1,
}
// Assign childlist
- for (map_iterator_type it = boost::begin(ring_map);
- it != boost::end(ring_map); ++it)
+ for (auto& pair : ring_map)
{
- if (it->second.parent.source_index >= 0)
+ if (pair.second.parent.source_index >= 0)
{
- ring_map[it->second.parent].children.push_back(it->first);
+ ring_map[pair.second.parent].children.push_back(pair.first);
}
}
}
diff --git a/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp b/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp
index 14be63a554..49d190bd0c 100644
--- a/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp
+++ b/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp
@@ -38,21 +38,11 @@ namespace detail { namespace overlay
template <typename Turns>
inline void clear_visit_info(Turns& turns)
{
- typedef typename boost::range_value<Turns>::type tp_type;
-
- for (typename boost::range_iterator<Turns>::type
- it = boost::begin(turns);
- it != boost::end(turns);
- ++it)
+ for (auto& turn : turns)
{
- for (typename boost::range_iterator
- <
- typename tp_type::container_type
- >::type op_it = boost::begin(it->operations);
- op_it != boost::end(it->operations);
- ++op_it)
+ for (auto& op : turn.operations)
{
- op_it->visited.clear();
+ op.visited.clear();
}
}
}
diff --git a/boost/geometry/algorithms/detail/overlay/check_enrich.hpp b/boost/geometry/algorithms/detail/overlay/check_enrich.hpp
index 843e120a18..ad3bd6bda9 100644
--- a/boost/geometry/algorithms/detail/overlay/check_enrich.hpp
+++ b/boost/geometry/algorithms/detail/overlay/check_enrich.hpp
@@ -127,37 +127,30 @@ inline bool check_graph(TurnPoints& turn_points, operation_type for_operation)
typedef typename boost::range_value<TurnPoints>::type turn_point_type;
bool error = false;
- int index = 0;
std::vector<meta_turn<turn_point_type> > meta_turns;
- for (typename boost::range_iterator<TurnPoints const>::type
- it = boost::begin(turn_points);
- it != boost::end(turn_points);
- ++it, ++index)
+ for_each_with_index(turn_points, [&](std::size_t index, auto const& point)
{
- meta_turns.push_back(meta_turn<turn_point_type>(index, *it));
- }
+ meta_turns.push_back(meta_turn<turn_point_type>(index, point));
+ });
int cycle = 0;
- for (typename boost::range_iterator<std::vector<meta_turn<turn_point_type> > > ::type
- it = boost::begin(meta_turns);
- it != boost::end(meta_turns);
- ++it)
+ for (auto& meta_turn : meta_turns)
{
- if (! (it->turn->blocked() || it->turn->discarded))
+ if (! (meta_turn.turn->blocked() || meta_turn.turn->discarded))
{
for (int i = 0 ; i < 2; i++)
{
- if (! it->handled[i]
- && it->turn->operations[i].operation == for_operation)
+ if (! meta_turn.handled[i]
+ && meta_turn.turn->operations[i].operation == for_operation)
{
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
std::cout << "CYCLE " << cycle << std::endl;
#endif
- it->handled[i] = true;
- check_detailed(meta_turns, *it, i, cycle++, it->index, for_operation, error);
+ meta_turn.handled[i] = true;
+ check_detailed(meta_turns, meta_turn, i, cycle++, meta_turn.index, for_operation, error);
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
- std::cout <<" END CYCLE " << it->index << std::endl;
+ std::cout <<" END CYCLE " << meta_turn.index << std::endl;
#endif
}
}
diff --git a/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp b/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp
index f99140dcd0..2eb70aa7d8 100644
--- a/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp
+++ b/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp
@@ -197,9 +197,8 @@ OutputIterator clip_range_with_box(Box const& b, Range const& range,
OutputLinestring line_out;
- typedef typename boost::range_iterator<Range const>::type iterator_type;
- iterator_type vertex = boost::begin(range);
- for(iterator_type previous = vertex++;
+ auto vertex = boost::begin(range);
+ for (auto previous = vertex++;
vertex != boost::end(range);
++previous, ++vertex)
{
diff --git a/boost/geometry/algorithms/detail/overlay/cluster_exits.hpp b/boost/geometry/algorithms/detail/overlay/cluster_exits.hpp
index c4d01b1c14..8c4f4c7f31 100644
--- a/boost/geometry/algorithms/detail/overlay/cluster_exits.hpp
+++ b/boost/geometry/algorithms/detail/overlay/cluster_exits.hpp
@@ -2,8 +2,9 @@
// Copyright (c) 2020 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2020.
-// Modifications copyright (c) 2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2023.
+// Modifications copyright (c) 2020-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
// Use, modification and distribution is subject to the Boost Software License,
@@ -22,6 +23,7 @@
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
+#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/util/condition.hpp>
@@ -67,16 +69,11 @@ private :
signed_size_type rank_index;
};
- typedef typename std::vector<linked_turn_op_info>::const_iterator const_it_type;
- typedef typename std::vector<linked_turn_op_info>::iterator it_type;
- typedef typename std::set<signed_size_type>::const_iterator sit_type;
-
inline signed_size_type get_rank(Sbs const& sbs,
linked_turn_op_info const& info) const
{
- for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
+ for (auto const& rp : sbs.m_ranked_points)
{
- typename Sbs::rp const& rp = sbs.m_ranked_points[i];
if (rp.turn_index == info.turn_index
&& rp.operation_index == info.op_index
&& rp.direction == sort_by_side::dir_to)
@@ -95,9 +92,8 @@ private :
bool collect(Turns const& turns)
{
- for (sit_type it = m_ids.begin(); it != m_ids.end(); ++it)
+ for (auto cluster_turn_index : m_ids)
{
- signed_size_type cluster_turn_index = *it;
turn_type const& cluster_turn = turns[cluster_turn_index];
if (cluster_turn.discarded)
{
@@ -148,23 +144,19 @@ private :
return true;
}
- for (it_type it = possibilities.begin(); it != possibilities.end(); ++it)
+ for (auto& info : possibilities)
{
- linked_turn_op_info& info = *it;
info.rank_index = get_rank(sbs, info);
}
- for (it_type it = blocked.begin(); it != blocked.end(); ++it)
+ for (auto& info : blocked)
{
- linked_turn_op_info& info = *it;
info.rank_index = get_rank(sbs, info);
}
- for (const_it_type it = possibilities.begin(); it != possibilities.end(); ++it)
+ for (auto const& lti : possibilities)
{
- linked_turn_op_info const& lti = *it;
- for (const_it_type bit = blocked.begin(); bit != blocked.end(); ++bit)
+ for (auto const& blti : blocked)
{
- linked_turn_op_info const& blti = *bit;
if (blti.next_turn_index == lti.next_turn_index
&& blti.rank_index == lti.rank_index)
{
@@ -198,10 +190,8 @@ public :
// If there is one (and only one) possibility pointing outside
// the cluster, take that one.
linked_turn_op_info target;
- for (const_it_type it = possibilities.begin();
- it != possibilities.end(); ++it)
+ for (auto const& lti : possibilities)
{
- linked_turn_op_info const& lti = *it;
if (m_ids.count(lti.next_turn_index) == 0)
{
if (target.turn_index >= 0
diff --git a/boost/geometry/algorithms/detail/overlay/colocate_clusters.hpp b/boost/geometry/algorithms/detail/overlay/colocate_clusters.hpp
new file mode 100644
index 0000000000..06d6e7bd61
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/colocate_clusters.hpp
@@ -0,0 +1,107 @@
+// Boost.Geometry
+
+// Copyright (c) 2023 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COLOCATE_CLUSTERS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COLOCATE_CLUSTERS_HPP
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+// Default implementation, using the first point for all turns in the cluster.
+template
+<
+ typename Point,
+ typename CoordinateType = typename geometry::coordinate_type<Point>::type,
+ typename CsTag = typename geometry::cs_tag<Point>::type,
+ bool IsIntegral = std::is_integral<CoordinateType>::value
+>
+struct cluster_colocator
+{
+ template <typename TurnIndices, typename Turns>
+ static inline void apply(TurnIndices const& indices, Turns& turns)
+ {
+ // This approach works for all but one testcase (rt_p13)
+ // The problem is fill_sbs, which uses sides and these sides might change slightly
+ // depending on the exact location of the cluster.
+ // Using the centroid is, on the average, a safer choice for sides.
+ // Alternatively fill_sbs could be revised, but that requires a lot of work
+ // and is outside current scope.
+ // Integer coordinates are always colocated already and do not need centroid calculation.
+ // Geographic/spherical coordinates might (in extremely rare cases) cross the date line
+ // and therefore the first point is taken for them as well.
+ auto it = indices.begin();
+ auto const& first_point = turns[*it].point;
+ for (++it; it != indices.end(); ++it)
+ {
+ turns[*it].point = first_point;
+ }
+ }
+};
+
+// Specialization for non-integral cartesian coordinates, calculating
+// the centroid of the points of the turns in the cluster.
+template <typename Point, typename CoordinateType>
+struct cluster_colocator<Point, CoordinateType, geometry::cartesian_tag, false>
+{
+ template <typename TurnIndices, typename Turns>
+ static inline void apply(TurnIndices const& indices, Turns& turns)
+ {
+ CoordinateType centroid_0 = 0;
+ CoordinateType centroid_1 = 0;
+ for (const auto& index : indices)
+ {
+ centroid_0 += geometry::get<0>(turns[index].point);
+ centroid_1 += geometry::get<1>(turns[index].point);
+ }
+ centroid_0 /= indices.size();
+ centroid_1 /= indices.size();
+ for (const auto& index : indices)
+ {
+ geometry::set<0>(turns[index].point, centroid_0);
+ geometry::set<1>(turns[index].point, centroid_1);
+ }
+ }
+};
+
+// Moves intersection points per cluster such that they are identical.
+// Because clusters are intersection close together, and
+// handled as one location. Then they should also have one location.
+// It is necessary to avoid artefacts and invalidities.
+template <typename Clusters, typename Turns>
+inline void colocate_clusters(Clusters const& clusters, Turns& turns)
+{
+ for (auto const& pair : clusters)
+ {
+ auto const& indices = pair.second.turn_indices;
+ if (indices.size() < 2)
+ {
+ // Defensive check
+ continue;
+ }
+ using point_t = decltype(turns[*indices.begin()].point);
+ cluster_colocator<point_t>::apply(indices, turns);
+ }
+}
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COLOCATE_CLUSTERS_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/convert_ring.hpp b/boost/geometry/algorithms/detail/overlay/convert_ring.hpp
index becaaafc37..c7c1cf7030 100644
--- a/boost/geometry/algorithms/detail/overlay/convert_ring.hpp
+++ b/boost/geometry/algorithms/detail/overlay/convert_ring.hpp
@@ -86,6 +86,7 @@ struct convert_ring<polygon_tag>
if (geometry::num_points(source) >= min_num_points)
{
+ // TODO: resize and .size() and .back() should not be called here
interior_rings(destination).resize(
interior_rings(destination).size() + 1);
geometry::convert(source, interior_rings(destination).back());
diff --git a/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
index 30a0a25095..8280a25018 100644
--- a/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
+++ b/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2020-2021.
// Modifications copyright (c) 2020-2021, Oracle and/or its affiliates.
@@ -14,7 +15,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP
-#include <boost/array.hpp>
+#include <array>
+
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
@@ -113,7 +115,7 @@ struct copy_segment_point_box
SegmentIdentifier const& seg_id, signed_size_type offset,
PointOut& point)
{
- boost::array<typename point_type<Box>::type, 4> bp;
+ std::array<typename point_type<Box>::type, 4> bp;
assign_box_corners_oriented<Reverse>(box, bp);
signed_size_type const target = circular_offset(4, seg_id.segment_index, offset);
diff --git a/boost/geometry/algorithms/detail/overlay/copy_segments.hpp b/boost/geometry/algorithms/detail/overlay/copy_segments.hpp
index 8af9ea4c1f..545bdc0314 100644
--- a/boost/geometry/algorithms/detail/overlay/copy_segments.hpp
+++ b/boost/geometry/algorithms/detail/overlay/copy_segments.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
@@ -15,10 +16,10 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP
+#include <array>
#include <type_traits>
#include <vector>
-#include <boost/array.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
@@ -167,10 +168,7 @@ public:
}
signed_size_type const count = to_index - from_index + 1;
-
- typename boost::range_iterator<LineString const>::type
- it = boost::begin(ls) + from_index;
-
+ auto it = boost::begin(ls) + from_index;
for (signed_size_type i = 0; i < count; ++i, ++it)
{
append_to_output(current_output, *it, strategy, robust_policy,
@@ -238,7 +236,7 @@ struct copy_segments_box
: 5 - index + to_index + 1;
// Create array of points, the fifth one closes it
- boost::array<typename point_type<Box>::type, 5> bp;
+ std::array<typename point_type<Box>::type, 5> bp;
assign_box_corners_oriented<Reverse>(box, bp);
bp[4] = bp[0];
diff --git a/boost/geometry/algorithms/detail/overlay/discard_duplicate_turns.hpp b/boost/geometry/algorithms/detail/overlay/discard_duplicate_turns.hpp
index f5a4a82656..258a815f09 100644
--- a/boost/geometry/algorithms/detail/overlay/discard_duplicate_turns.hpp
+++ b/boost/geometry/algorithms/detail/overlay/discard_duplicate_turns.hpp
@@ -2,6 +2,10 @@
// Copyright (c) 2021 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2023.
+// Modifications copyright (c) 2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -9,6 +13,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DISCARD_DUPLICATE_TURNS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DISCARD_DUPLICATE_TURNS_HPP
+#include <map>
+
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
diff --git a/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
index 58ab4fcdda..b94bba6c5a 100644
--- a/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
+++ b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
@@ -3,9 +3,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017-2020.
+// This file was modified by Oracle on 2017-2021.
// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates.
-
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -42,6 +41,7 @@
#include <boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
#include <boost/geometry/policies/robustness/robust_type.hpp>
+#include <boost/geometry/util/for_each_with_index.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
# include <boost/geometry/algorithms/detail/overlay/check_enrich.hpp>
@@ -83,24 +83,24 @@ template
typename Turns,
typename Geometry1, typename Geometry2,
typename RobustPolicy,
- typename SideStrategy
+ typename Strategy
>
inline void enrich_sort(Operations& operations,
Turns const& turns,
Geometry1 const& geometry1,
Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
- SideStrategy const& strategy)
+ Strategy const& strategy)
{
- std::sort(boost::begin(operations),
- boost::end(operations),
- less_by_segment_ratio
+ std::sort(std::begin(operations),
+ std::end(operations),
+ less_by_segment_ratio
<
Turns,
typename boost::range_value<Operations>::type,
Geometry1, Geometry2,
RobustPolicy,
- SideStrategy,
+ Strategy,
Reverse1, Reverse2
>(turns, geometry1, geometry2, robust_policy, strategy));
}
@@ -110,93 +110,83 @@ template <typename Operations, typename Turns>
inline void enrich_assign(Operations& operations, Turns& turns,
bool check_turns)
{
- typedef typename boost::range_value<Turns>::type turn_type;
- typedef typename turn_type::turn_operation_type op_type;
- typedef typename boost::range_iterator<Operations>::type iterator_type;
+ if (operations.empty())
+ {
+ return;
+ }
+ // Assign travel-to-vertex/ip index for each turning point.
+ // Iterator "next" is circular
- if (operations.size() > 0)
- {
- // Assign travel-to-vertex/ip index for each turning point.
- // Iterator "next" is circular
+ geometry::ever_circling_range_iterator<Operations const> next(operations);
+ ++next;
- geometry::ever_circling_range_iterator<Operations const> next(operations);
- ++next;
+ for (auto const& indexed : operations)
+ {
+ auto& turn = turns[indexed.turn_index];
+ auto& op = turn.operations[indexed.operation_index];
- for (iterator_type it = boost::begin(operations);
- it != boost::end(operations); ++it)
+ if (check_turns && indexed.turn_index == next->turn_index)
{
- turn_type& turn = turns[it->turn_index];
- op_type& op = turn.operations[it->operation_index];
-
- if (check_turns && it->turn_index == next->turn_index)
- {
- // Normal behaviour: next points at next turn, increase next.
- // For dissolve this should not be done, turn_index is often
- // the same for two consecutive operations
- ++next;
- }
+ // Normal behaviour: next points at next turn, increase next.
+ // For dissolve this should not be done, turn_index is often
+ // the same for two consecutive operations
+ ++next;
+ }
- // Cluster behaviour: next should point after cluster, unless
- // their seg_ids are not the same
- // (For dissolve, this is still to be examined - TODO)
- while (turn.is_clustered()
- && it->turn_index != next->turn_index
- && turn.cluster_id == turns[next->turn_index].cluster_id
- && op.seg_id == turns[next->turn_index].operations[next->operation_index].seg_id)
- {
- ++next;
- }
+ // Cluster behaviour: next should point after cluster, unless
+ // their seg_ids are not the same
+ // (For dissolve, this is still to be examined - TODO)
+ while (turn.is_clustered()
+ && indexed.turn_index != next->turn_index
+ && turn.cluster_id == turns[next->turn_index].cluster_id
+ && op.seg_id == turns[next->turn_index].operations[next->operation_index].seg_id)
+ {
+ ++next;
+ }
- turn_type const& next_turn = turns[next->turn_index];
- op_type const& next_op = next_turn.operations[next->operation_index];
+ auto const& next_turn = turns[next->turn_index];
+ auto const& next_op = next_turn.operations[next->operation_index];
- op.enriched.travels_to_ip_index
- = static_cast<signed_size_type>(next->turn_index);
- op.enriched.travels_to_vertex_index
- = next->subject->seg_id.segment_index;
+ op.enriched.travels_to_ip_index
+ = static_cast<signed_size_type>(next->turn_index);
+ op.enriched.travels_to_vertex_index
+ = next->subject->seg_id.segment_index;
- if (op.seg_id.segment_index == next_op.seg_id.segment_index
- && op.fraction < next_op.fraction)
- {
- // Next turn is located further on same segment
- // assign next_ip_index
- // (this is one not circular therefore fraction is considered)
- op.enriched.next_ip_index = static_cast<signed_size_type>(next->turn_index);
- }
+ if (op.seg_id.segment_index == next_op.seg_id.segment_index
+ && op.fraction < next_op.fraction)
+ {
+ // Next turn is located further on same segment
+ // assign next_ip_index
+ // (this is one not circular therefore fraction is considered)
+ op.enriched.next_ip_index = static_cast<signed_size_type>(next->turn_index);
+ }
- if (! check_turns)
- {
- ++next;
- }
+ if (! check_turns)
+ {
+ ++next;
}
}
// DEBUG
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+ for (auto const& indexed_op : operations)
{
- for (iterator_type it = boost::begin(operations);
- it != boost::end(operations);
- ++it)
- {
- op_type const& op = turns[it->turn_index]
- .operations[it->operation_index];
-
- std::cout << it->turn_index
- << " cl=" << turns[it->turn_index].cluster_id
- << " meth=" << method_char(turns[it->turn_index].method)
- << " seg=" << op.seg_id
- << " dst=" << op.fraction // needs define
- << " op=" << operation_char(turns[it->turn_index].operations[0].operation)
- << operation_char(turns[it->turn_index].operations[1].operation)
- << " (" << operation_char(op.operation) << ")"
- << " nxt=" << op.enriched.next_ip_index
- << " / " << op.enriched.travels_to_ip_index
- << " [vx " << op.enriched.travels_to_vertex_index << "]"
- << (turns[it->turn_index].discarded ? " discarded" : "")
- << std::endl;
- ;
- }
+ auto const& op = turns[indexed_op.turn_index].operations[indexed_op.operation_index];
+
+ std::cout << indexed_op.turn_index
+ << " cl=" << turns[indexed_op.turn_index].cluster_id
+ << " meth=" << method_char(turns[indexed_op.turn_index].method)
+ << " seg=" << op.seg_id
+ << " dst=" << op.fraction // needs define
+ << " op=" << operation_char(turns[indexed_op.turn_index].operations[0].operation)
+ << operation_char(turns[indexed_op.turn_index].operations[1].operation)
+ << " (" << operation_char(op.operation) << ")"
+ << " nxt=" << op.enriched.next_ip_index
+ << " / " << op.enriched.travels_to_ip_index
+ << " [vx " << op.enriched.travels_to_vertex_index << "]"
+ << (turns[indexed_op.turn_index].discarded ? " discarded" : "")
+ << std::endl;
}
#endif
// END DEBUG
@@ -206,47 +196,37 @@ inline void enrich_assign(Operations& operations, Turns& turns,
template <typename Operations, typename Turns>
inline void enrich_adapt(Operations& operations, Turns& turns)
{
- typedef typename boost::range_value<Turns>::type turn_type;
- typedef typename turn_type::turn_operation_type op_type;
- typedef typename boost::range_value<Operations>::type indexed_turn_type;
-
+ // Operations is a vector of indexed_turn_operation<>
+ // If it is empty, or contains one or two items, it makes no sense
if (operations.size() < 3)
{
- // If it is empty, or contains one or two turns, it makes no sense
return;
}
- // Operations is a vector of indexed_turn_operation<>
-
- // Last index:
- std::size_t const x = operations.size() - 1;
bool next_phase = false;
+ std::size_t previous_index = operations.size() - 1;
- for (std::size_t i = 0; i < operations.size(); i++)
+ for_each_with_index(operations, [&](std::size_t index, auto const& indexed)
{
- indexed_turn_type const& indexed = operations[i];
-
- turn_type& turn = turns[indexed.turn_index];
- op_type& op = turn.operations[indexed.operation_index];
-
- // Previous/next index
- std::size_t const p = i > 0 ? i - 1 : x;
- std::size_t const n = i < x ? i + 1 : 0;
+ auto& turn = turns[indexed.turn_index];
+ auto& op = turn.operations[indexed.operation_index];
- turn_type const& next_turn = turns[operations[n].turn_index];
- op_type const& next_op = next_turn.operations[operations[n].operation_index];
+ std::size_t const next_index = index + 1 < operations.size() ? index + 1 : 0;
+ auto const& next_turn = turns[operations[next_index].turn_index];
+ auto const& next_op = next_turn.operations[operations[next_index].operation_index];
if (op.seg_id.segment_index == next_op.seg_id.segment_index)
{
- turn_type const& prev_turn = turns[operations[p].turn_index];
- op_type const& prev_op = prev_turn.operations[operations[p].operation_index];
+ auto const& prev_turn = turns[operations[previous_index].turn_index];
+ auto const& prev_op = prev_turn.operations[operations[previous_index].operation_index];
if (op.seg_id.segment_index == prev_op.seg_id.segment_index)
{
op.enriched.startable = false;
next_phase = true;
}
}
- }
+ previous_index = index;
+ });
if (! next_phase)
{
@@ -255,12 +235,8 @@ inline void enrich_adapt(Operations& operations, Turns& turns)
// Discard turns which are both non-startable
next_phase = false;
- for (typename boost::range_iterator<Turns>::type
- it = boost::begin(turns);
- it != boost::end(turns);
- ++it)
+ for (auto& turn : turns)
{
- turn_type& turn = *it;
if (! turn.operations[0].enriched.startable
&& ! turn.operations[1].enriched.startable)
{
@@ -276,8 +252,8 @@ inline void enrich_adapt(Operations& operations, Turns& turns)
// Remove discarded turns from operations to avoid having them as next turn
discarded_indexed_turn<Turns> const predicate(turns);
- operations.erase(std::remove_if(boost::begin(operations),
- boost::end(operations), predicate), boost::end(operations));
+ operations.erase(std::remove_if(std::begin(operations),
+ std::end(operations), predicate), std::end(operations));
}
struct enriched_map_default_include_policy
@@ -290,52 +266,35 @@ struct enriched_map_default_include_policy
}
};
+// Add all (non discarded) operations on this ring
+// Blocked operations or uu on clusters (for intersection)
+// should be included, to block potential paths in clusters
template <typename Turns, typename MappedVector, typename IncludePolicy>
inline void create_map(Turns const& turns, MappedVector& mapped_vector,
IncludePolicy const& include_policy)
{
- typedef typename boost::range_value<Turns>::type turn_type;
- typedef typename turn_type::container_type container_type;
- typedef typename MappedVector::mapped_type mapped_type;
- typedef typename boost::range_value<mapped_type>::type indexed_type;
-
- std::size_t index = 0;
- for (typename boost::range_iterator<Turns const>::type
- it = boost::begin(turns);
- it != boost::end(turns);
- ++it, ++index)
+ for_each_with_index(turns, [&](std::size_t index, auto const& turn)
{
- // Add all (non discarded) operations on this ring
- // Blocked operations or uu on clusters (for intersection)
- // should be included, to block potential paths in clusters
- turn_type const& turn = *it;
- if (turn.discarded)
- {
- continue;
- }
-
- std::size_t op_index = 0;
- for (typename boost::range_iterator<container_type const>::type
- op_it = boost::begin(turn.operations);
- op_it != boost::end(turn.operations);
- ++op_it, ++op_index)
+ if (! turn.discarded)
{
- if (include_policy.include(op_it->operation))
+ for_each_with_index(turn.operations, [&](std::size_t op_index, auto const& op)
{
- ring_identifier const ring_id
- (
- op_it->seg_id.source_index,
- op_it->seg_id.multi_index,
- op_it->seg_id.ring_index
- );
- mapped_vector[ring_id].push_back
- (
- indexed_type(index, op_index, *op_it,
- it->operations[1 - op_index].seg_id)
- );
- }
+ if (include_policy.include(op.operation))
+ {
+ ring_identifier const ring_id
+ (
+ op.seg_id.source_index,
+ op.seg_id.multi_index,
+ op.seg_id.ring_index
+ );
+ mapped_vector[ring_id].emplace_back
+ (
+ index, op_index, op, turn.operations[1 - op_index].seg_id
+ );
+ }
+ });
}
- }
+ });
}
template <typename Point1, typename Point2>
@@ -344,7 +303,7 @@ inline typename geometry::coordinate_type<Point1>::type
{
// TODO: use comparable distance for point-point instead - but that
// causes currently cycling include problems
- typedef typename geometry::coordinate_type<Point1>::type ctype;
+ using ctype = typename geometry::coordinate_type<Point1>::type;
ctype const dx = get<0>(a) - get<0>(b);
ctype const dy = get<1>(a) - get<1>(b);
return dx * dx + dy * dy;
@@ -353,30 +312,24 @@ inline typename geometry::coordinate_type<Point1>::type
template <typename Turns>
inline void calculate_remaining_distance(Turns& turns)
{
- typedef typename boost::range_value<Turns>::type turn_type;
- typedef typename turn_type::turn_operation_type op_type;
-
- for (typename boost::range_iterator<Turns>::type
- it = boost::begin(turns);
- it != boost::end(turns);
- ++it)
+ for (auto& turn : turns)
{
- turn_type& turn = *it;
+ auto& op0 = turn.operations[0];
+ auto& op1 = turn.operations[1];
- op_type& op0 = turn.operations[0];
- op_type& op1 = turn.operations[1];
+ static decltype(op0.remaining_distance) const zero_distance = 0;
- if (op0.remaining_distance != 0
- || op1.remaining_distance != 0)
+ if (op0.remaining_distance != zero_distance
+ || op1.remaining_distance != zero_distance)
{
continue;
}
- signed_size_type const to_index0 = op0.enriched.get_next_turn_index();
- signed_size_type const to_index1 = op1.enriched.get_next_turn_index();
+ auto const to_index0 = op0.enriched.get_next_turn_index();
+ auto const to_index1 = op1.enriched.get_next_turn_index();
if (to_index0 >= 0
- && to_index1 >= 0
- && to_index0 != to_index1)
+ && to_index1 >= 0
+ && to_index0 != to_index1)
{
op0.remaining_distance = distance_measure(turn.point, turns[to_index0].point);
op1.remaining_distance = distance_measure(turn.point, turns[to_index1].point);
@@ -422,29 +375,28 @@ inline void enrich_intersection_points(Turns& turns,
RobustPolicy const& robust_policy,
IntersectionStrategy const& strategy)
{
- static const detail::overlay::operation_type target_operation
+ constexpr detail::overlay::operation_type target_operation
= detail::overlay::operation_from_overlay<OverlayType>::value;
- static const detail::overlay::operation_type opposite_operation
+ constexpr detail::overlay::operation_type opposite_operation
= target_operation == detail::overlay::operation_union
? detail::overlay::operation_intersection
: detail::overlay::operation_union;
- static const bool is_dissolve = OverlayType == overlay_dissolve;
+ constexpr bool is_dissolve = OverlayType == overlay_dissolve;
- typedef typename boost::range_value<Turns>::type turn_type;
- typedef typename turn_type::turn_operation_type op_type;
- typedef detail::overlay::indexed_turn_operation
+ using turn_type = typename boost::range_value<Turns>::type;
+ using indexed_turn_operation = detail::overlay::indexed_turn_operation
<
- op_type
- > indexed_turn_operation;
+ typename turn_type::turn_operation_type
+ > ;
- typedef std::map
+ using mapped_vector_type = std::map
<
ring_identifier,
std::vector<indexed_turn_operation>
- > mapped_vector_type;
+ >;
// From here on, turn indexes are used (in clusters, next_index, etc)
- // and may not be DELETED - they may only be flagged as discarded
+ // and turns may not be DELETED - they may only be flagged as discarded
discard_duplicate_start_turns(turns, geometry1, geometry2);
bool has_cc = false;
@@ -455,13 +407,8 @@ inline void enrich_intersection_points(Turns& turns,
>(turns, clusters, robust_policy);
// Discard turns not part of target overlay
- for (typename boost::range_iterator<Turns>::type
- it = boost::begin(turns);
- it != boost::end(turns);
- ++it)
+ for (auto& turn : turns)
{
- turn_type& turn = *it;
-
if (turn.both(detail::overlay::operation_none)
|| turn.both(opposite_operation)
|| turn.both(detail::overlay::operation_blocked)
@@ -514,20 +461,15 @@ inline void enrich_intersection_points(Turns& turns,
detail::overlay::create_map(turns, mapped_vector,
detail::overlay::enriched_map_default_include_policy());
- // No const-iterator; contents of mapped copy is temporary,
- // and changed by enrich
- for (typename mapped_vector_type::iterator mit
- = mapped_vector.begin();
- mit != mapped_vector.end();
- ++mit)
+ for (auto& pair : mapped_vector)
{
detail::overlay::enrich_sort<Reverse1, Reverse2>(
- mit->second, turns,
+ pair.second, turns,
geometry1, geometry2,
- robust_policy, strategy.side()); // TODO: pass strategy
+ robust_policy, strategy);
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
- std::cout << "ENRICH-sort Ring " << mit->first << std::endl;
- for (auto const& op : mit->second)
+ std::cout << "ENRICH-sort Ring " << pair.first << std::endl;
+ for (auto const& op : pair.second)
{
std::cout << op.turn_index << " " << op.operation_index << std::endl;
}
@@ -551,20 +493,17 @@ inline void enrich_intersection_points(Turns& turns,
// After cleaning up clusters assign the next turns
- for (typename mapped_vector_type::iterator mit
- = mapped_vector.begin();
- mit != mapped_vector.end();
- ++mit)
+ for (auto& pair : mapped_vector)
{
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
- std::cout << "ENRICH-assign Ring " << mit->first << std::endl;
+ std::cout << "ENRICH-assign Ring " << pair.first << std::endl;
#endif
if (is_dissolve)
{
- detail::overlay::enrich_adapt(mit->second, turns);
+ detail::overlay::enrich_adapt(pair.second, turns);
}
- detail::overlay::enrich_assign(mit->second, turns, ! is_dissolve);
+ detail::overlay::enrich_assign(pair.second, turns, ! is_dissolve);
}
if (has_cc)
diff --git a/boost/geometry/algorithms/detail/overlay/follow.hpp b/boost/geometry/algorithms/detail/overlay/follow.hpp
index afcd2bd82e..d945605413 100644
--- a/boost/geometry/algorithms/detail/overlay/follow.hpp
+++ b/boost/geometry/algorithms/detail/overlay/follow.hpp
@@ -3,8 +3,8 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014-2020.
-// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -23,8 +23,8 @@
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
-#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
#include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp>
#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
@@ -422,13 +422,6 @@ public :
OutputIterator out,
Strategy const& strategy)
{
- typedef typename boost::range_iterator<Turns>::type turn_iterator;
- typedef typename boost::range_value<Turns>::type turn_type;
- typedef typename boost::range_iterator
- <
- typename turn_type::container_type
- >::type turn_operation_iterator_type;
-
typedef following::action_selector<OverlayType, RemoveSpikes> action;
// Sort intersection points on segments-along-linestring, and distance
@@ -438,8 +431,7 @@ public :
// for different ring id: c, i, u, x
typedef relate::turns::less
<
- 0, relate::turns::less_op_linear_areal_single<0>,
- typename Strategy::cs_tag
+ 0, relate::turns::less_op_linear_areal_single<0>, Strategy
> turn_less;
std::sort(boost::begin(turns), boost::end(turns), turn_less());
@@ -449,51 +441,51 @@ public :
// Iterate through all intersection points (they are ordered along the line)
bool entered = false;
bool first = true;
- for (turn_iterator it = boost::begin(turns); it != boost::end(turns); ++it)
+ for (auto const& turn : turns)
{
- turn_operation_iterator_type iit = boost::begin(it->operations);
+ auto const& op = turn.operations[0];
- if (following::was_entered(*it, *iit, first, linestring, polygon, strategy))
+ if (following::was_entered(turn, op, first, linestring, polygon, strategy))
{
- debug_traverse(*it, *iit, "-> Was entered");
+ debug_traverse(turn, op, "-> Was entered");
entered = true;
}
- if (following::is_staying_inside(*it, *iit, entered, first, linestring, polygon, strategy))
+ if (following::is_staying_inside(turn, op, entered, first, linestring, polygon, strategy))
{
- debug_traverse(*it, *iit, "-> Staying inside");
+ debug_traverse(turn, op, "-> Staying inside");
entered = true;
}
- else if (following::is_entering(*it, *iit))
+ else if (following::is_entering(turn, op))
{
- debug_traverse(*it, *iit, "-> Entering");
+ debug_traverse(turn, op, "-> Entering");
entered = true;
action::enter(current_piece, linestring, current_segment_id,
- iit->seg_id.segment_index, it->point, *iit,
+ op.seg_id.segment_index, turn.point, op,
strategy, robust_policy,
linear::get(out));
}
- else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon, strategy))
+ else if (following::is_leaving(turn, op, entered, first, linestring, polygon, strategy))
{
- debug_traverse(*it, *iit, "-> Leaving");
+ debug_traverse(turn, op, "-> Leaving");
entered = false;
action::leave(current_piece, linestring, current_segment_id,
- iit->seg_id.segment_index, it->point, *iit,
+ op.seg_id.segment_index, turn.point, op,
strategy, robust_policy,
linear::get(out));
}
else if (BOOST_GEOMETRY_CONDITION(FollowIsolatedPoints)
- && following::is_touching(*it, *iit, entered))
+ && following::is_touching(turn, op, entered))
{
- debug_traverse(*it, *iit, "-> Isolated point");
+ debug_traverse(turn, op, "-> Isolated point");
action::template isolated_point
<
typename pointlike::type
- >(it->point, pointlike::get(out));
+ >(turn.point, pointlike::get(out));
}
first = false;
diff --git a/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
index a3ad620162..5d1577c481 100644
--- a/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
@@ -74,7 +74,7 @@ static inline bool is_entering(Turn const& turn,
template <typename Turn, typename Operation>
static inline bool is_staying_inside(Turn const& turn,
- Operation const& operation,
+ Operation const& operation,
bool entered)
{
if ( !entered )
@@ -327,21 +327,17 @@ public:
for (TurnIterator it = first; it != beyond; ++it)
{
oit = process_turn(it, boost::begin(it->operations),
- entered, enter_count,
+ entered, enter_count,
linestring,
current_piece, current_segment_id,
oit,
strategy);
}
-#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
if (enter_count != 0)
{
- BOOST_THROW_EXCEPTION(inconsistent_turns_exception());
+ return oit;
}
-#else
- BOOST_GEOMETRY_ASSERT(enter_count == 0);
-#endif
return process_end(entered, linestring,
current_segment_id, current_piece,
diff --git a/boost/geometry/algorithms/detail/overlay/get_clusters.hpp b/boost/geometry/algorithms/detail/overlay/get_clusters.hpp
index 1e612d6577..2747fa68ba 100644
--- a/boost/geometry/algorithms/detail/overlay/get_clusters.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_clusters.hpp
@@ -35,19 +35,29 @@ namespace detail { namespace overlay
template <typename Tag = no_rescale_policy_tag, bool Integral = false>
struct sweep_equal_policy
{
+private:
+ template <typename T>
+ static inline T threshold()
+ {
+ // Points within some epsilons are considered as equal.
+ return T(100);
+ }
+public:
+ // Returns true if point are considered equal (within an epsilon)
template <typename P>
static inline bool equals(P const& p1, P const& p2)
{
- // Points within a kilo epsilon are considered as equal
- return approximately_equals(p1, p2, 1000.0);
+ using coor_t = typename coordinate_type<P>::type;
+ return approximately_equals(p1, p2, threshold<coor_t>());
}
template <typename T>
static inline bool exceeds(T value)
{
// This threshold is an arbitrary value
- // as long as it is than the used kilo-epsilon
- return value > 1.0e-3;
+ // as long as it is bigger than the used value above
+ T const limit = T(1) / threshold<T>();
+ return value > limit;
}
};
diff --git a/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp b/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp
index 82ab3d5d04..d462bb524d 100644
--- a/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp
@@ -1,6 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2019 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2019-2021 Barend Gehrels, Amsterdam, the Netherlands.
+
+// This file was modified by Oracle on 2022.
+// Modifications copyright (c) 2022 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -61,53 +65,48 @@ namespace detail_dispatch
template <typename CalculationType, typename CsTag>
struct get_distance_measure
- : not_implemented<CsTag>
+ : not_implemented<CsTag>
{};
template <typename CalculationType>
-struct get_distance_measure<CalculationType, cartesian_tag>
+struct get_distance_measure<CalculationType, spherical_tag>
{
- typedef detail::distance_measure<CalculationType> result_type;
+ // By default the distance measure is zero, no side difference
+ using result_type = detail::distance_measure<CalculationType>;
template <typename SegmentPoint, typename Point>
- static result_type apply(SegmentPoint const& p1, SegmentPoint const& p2,
- Point const& p)
+ static result_type apply(SegmentPoint const& , SegmentPoint const& ,
+ Point const& )
{
- // Get the distance measure / side value
- // It is not a real distance and purpose is
- // to detect small differences in collinearity
-
- typedef model::infinite_line<CalculationType> line_type;
- line_type const line = detail::make::make_infinite_line<CalculationType>(p1, p2);
- result_type result;
- result.measure = arithmetic::side_value(line, p);
+ const result_type result;
return result;
}
};
template <typename CalculationType>
-struct get_distance_measure<CalculationType, spherical_tag>
+struct get_distance_measure<CalculationType, geographic_tag>
+ : get_distance_measure<CalculationType, spherical_tag>
+{};
+
+template <typename CalculationType>
+struct get_distance_measure<CalculationType, cartesian_tag>
{
- typedef detail::distance_measure<CalculationType> result_type;
+ using result_type = detail::distance_measure<CalculationType>;
template <typename SegmentPoint, typename Point>
- static result_type apply(SegmentPoint const& , SegmentPoint const& ,
- Point const& )
+ static result_type apply(SegmentPoint const& p1, SegmentPoint const& p2,
+ Point const& p)
{
- // TODO, optional
+ // Get the distance measure / side value
+ // It is not a real distance and purpose is
+ // to detect small differences in collinearity
+ auto const line = detail::make::make_infinite_line<CalculationType>(p1, p2);
result_type result;
+ result.measure = arithmetic::side_value(line, p);
return result;
}
};
-template <typename CalculationType>
-struct get_distance_measure<CalculationType, geographic_tag>
- : get_distance_measure<CalculationType, spherical_tag> {};
-
-template <typename CalculationType>
-struct get_distance_measure<CalculationType, spherical_equatorial_tag>
- : get_distance_measure<CalculationType, spherical_tag> {};
-
} // namespace detail_dispatch
namespace detail
@@ -117,18 +116,32 @@ namespace detail
// 0 (absolutely 0, not even an epsilon) means collinear. Like side,
// a negative means that p is to the right of p1-p2. And a positive value
// means that p is to the left of p1-p2.
-
-template <typename SegmentPoint, typename Point>
-static distance_measure<typename select_coordinate_type<SegmentPoint, Point>::type>
-get_distance_measure(SegmentPoint const& p1, SegmentPoint const& p2, Point const& p)
+template <typename SegmentPoint, typename Point, typename Strategies>
+inline auto get_distance_measure(SegmentPoint const& p1, SegmentPoint const& p2, Point const& p,
+ Strategies const&)
{
- typedef typename geometry::cs_tag<Point>::type cs_tag;
- return detail_dispatch::get_distance_measure
- <
- typename select_coordinate_type<SegmentPoint, Point>::type,
- cs_tag
- >::apply(p1, p2, p);
+ using calc_t = typename select_coordinate_type<SegmentPoint, Point>::type;
+
+ // Verify equality, without using a tolerance
+ // (so don't use equals or equals_point_point)
+ // because it is about very tiny differences.
+ auto identical = [](const auto& point1, const auto& point2)
+ {
+ return geometry::get<0>(point1) == geometry::get<0>(point2)
+ && geometry::get<1>(point1) == geometry::get<1>(point2);
+ };
+ if (identical(p1, p) || identical(p2, p))
+ {
+ detail::distance_measure<calc_t> const result;
+ return result;
+ }
+
+ return detail_dispatch::get_distance_measure
+ <
+ calc_t,
+ typename Strategies::cs_tag
+ >::apply(p1, p2, p);
}
} // namespace detail
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
index fcd3635fd6..4e10c07bde 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
@@ -1,11 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2007-2021 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2015-2020.
-// Modifications copyright (c) 2015-2020 Oracle and/or its affiliates.
-
+// This file was modified by Oracle on 2015-2022.
+// Modifications copyright (c) 2015-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -26,14 +25,9 @@
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
-
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp>
-// Silence warning C4127: conditional expression is constant
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4127)
-#endif
+#include <boost/geometry/util/condition.hpp>
namespace boost { namespace geometry
@@ -66,6 +60,36 @@ public:
namespace detail { namespace overlay
{
+
+struct policy_verify_nothing
+{
+ static bool const use_side_verification = false;
+ static bool const use_start_turn = false;
+ static bool const use_handle_as_touch = false;
+ static bool const use_handle_as_equal = false;
+ static bool const use_handle_imperfect_touch = false;
+};
+
+struct policy_verify_all
+{
+ static bool const use_side_verification = true;
+ static bool const use_start_turn = true;
+ static bool const use_handle_as_touch = true;
+ static bool const use_handle_as_equal = true;
+ static bool const use_handle_imperfect_touch = true;
+};
+
+
+#if defined(BOOST_GEOMETRY_USE_RESCALING)
+using verify_policy_aa = policy_verify_nothing;
+#else
+using verify_policy_aa = policy_verify_all;
+#endif
+
+using verify_policy_ll = policy_verify_nothing;
+using verify_policy_la = policy_verify_nothing;
+
+
struct base_turn_handler
{
// Returns true if both sides are opposite
@@ -107,52 +131,6 @@ struct base_turn_handler
both(ti, condition ? operation_union : operation_intersection);
}
-
-#if ! defined(BOOST_GEOMETRY_USE_RESCALING)
- template
- <
- typename UniqueSubRange1,
- typename UniqueSubRange2
- >
- static inline int side_with_distance_measure(UniqueSubRange1 const& range_p,
- UniqueSubRange2 const& range_q,
- int range_index, int point_index)
- {
- if (range_index >= 1 && range_p.is_last_segment())
- {
- return 0;
- }
- if (point_index >= 2 && range_q.is_last_segment())
- {
- return 0;
- }
-
- auto const dm = get_distance_measure(range_p.at(range_index), range_p.at(range_index + 1), range_q.at(point_index));
- return dm.measure == 0 ? 0 : dm.measure > 0 ? 1 : -1;
- }
-
- template
- <
- typename UniqueSubRange1,
- typename UniqueSubRange2
- >
- static inline int verified_side(int side,
- UniqueSubRange1 const& range_p,
- UniqueSubRange2 const& range_q,
- int range_index,
- int point_index)
- {
- return side == 0 ? side_with_distance_measure(range_p, range_q, range_index, point_index) : side;
- }
-#else
- template <typename T1, typename T2>
- static inline int verified_side(int side, T1 const& , T2 const& , int , int)
- {
- return side;
- }
-#endif
-
-
template <typename TurnInfo, typename IntersectionInfo>
static inline void assign_point(TurnInfo& ti,
method_type method,
@@ -208,14 +186,22 @@ struct base_turn_handler
? 1 : 0;
}
+};
+
+template<typename VerifyPolicy>
+struct turn_info_verification_functions
+{
template <typename Point1, typename Point2>
- static inline typename geometry::coordinate_type<Point1>::type
- distance_measure(Point1 const& a, Point2 const& b)
+ static inline
+ typename select_coordinate_type<Point1, Point2>::type
+ distance_measure(Point1 const& a, Point2 const& b)
{
- // TODO: use comparable distance for point-point instead - but that
- // causes currently cycling include problems
- auto const dx = get<0>(a) - get<0>(b);
- auto const dy = get<1>(a) - get<1>(b);
+ // TODO: revise this using comparable distance for various
+ // coordinate systems
+ using coor_t = typename select_coordinate_type<Point1, Point2>::type;
+
+ coor_t const dx = get<0>(a) - get<0>(b);
+ coor_t const dy = get<1>(a) - get<1>(b);
return dx * dx + dy * dy;
}
@@ -228,50 +214,127 @@ struct base_turn_handler
typename UmbrellaStrategy,
typename TurnInfo
>
- static inline void both_collinear(
+ static inline void set_both_verified(
UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
- UmbrellaStrategy const&,
+ UmbrellaStrategy const& umbrella_strategy,
std::size_t index_p, std::size_t index_q,
TurnInfo& ti)
{
- boost::ignore_unused(range_p, range_q);
BOOST_GEOMETRY_ASSERT(IndexP + IndexQ == 1);
BOOST_GEOMETRY_ASSERT(index_p > 0 && index_p <= 2);
BOOST_GEOMETRY_ASSERT(index_q > 0 && index_q <= 2);
-#if ! defined(BOOST_GEOMETRY_USE_RESCALING)
- ti.operations[IndexP].remaining_distance = distance_measure(ti.point, range_p.at(index_p));
- ti.operations[IndexQ].remaining_distance = distance_measure(ti.point, range_q.at(index_q));
-
- // pk/q2 is considered as collinear, but there might be
- // a tiny measurable difference. If so, use that.
- // Calculate pk // qj-qk
- bool const p_closer =
- ti.operations[IndexP].remaining_distance
- < ti.operations[IndexQ].remaining_distance;
- auto const dm
+ using distance_measure_result_type = typename geometry::coordinate_type<decltype(ti.point)>::type;
+
+ bool const p_in_range = index_p < range_p.size();
+ bool const q_in_range = index_q < range_q.size();
+ ti.operations[IndexP].remaining_distance
+ = p_in_range
+ ? distance_measure(ti.point, range_p.at(index_p))
+ : distance_measure_result_type{0};
+ ti.operations[IndexQ].remaining_distance
+ = q_in_range
+ ? distance_measure(ti.point, range_q.at(index_q))
+ : distance_measure_result_type{0};
+
+ if (p_in_range && q_in_range)
+ {
+ // pk/q2 is considered as collinear, but there might be
+ // a tiny measurable difference. If so, use that.
+ // Calculate pk // qj-qk
+ bool const p_closer
+ = ti.operations[IndexP].remaining_distance
+ < ti.operations[IndexQ].remaining_distance;
+ auto const dm
= p_closer
? get_distance_measure(range_q.at(index_q - 1),
- range_q.at(index_q), range_p.at(index_p))
+ range_q.at(index_q), range_p.at(index_p),
+ umbrella_strategy)
: get_distance_measure(range_p.at(index_p - 1),
- range_p.at(index_p), range_q.at(index_q));
+ range_p.at(index_p), range_q.at(index_q),
+ umbrella_strategy);
+
+ if (! dm.is_zero())
+ {
+ // Not truely collinear, distinguish for union/intersection
+ // If p goes left (positive), take that for a union
+ bool const p_left
+ = p_closer ? dm.is_positive() : dm.is_negative();
+
+ ti.operations[IndexP].operation = p_left
+ ? operation_union : operation_intersection;
+ ti.operations[IndexQ].operation = p_left
+ ? operation_intersection : operation_union;
+ return;
+ }
+ }
+
+ base_turn_handler::both(ti, operation_continue);
+ }
- if (! dm.is_zero())
+ template
+ <
+ std::size_t IndexP,
+ std::size_t IndexQ,
+ typename UniqueSubRange1,
+ typename UniqueSubRange2,
+ typename UmbrellaStrategy,
+ typename TurnInfo
+ >
+ static inline void both_collinear(
+ UniqueSubRange1 const& range_p,
+ UniqueSubRange2 const& range_q,
+ UmbrellaStrategy const& umbrella_strategy,
+ std::size_t index_p, std::size_t index_q,
+ TurnInfo& ti)
+ {
+ if (BOOST_GEOMETRY_CONDITION(VerifyPolicy::use_side_verification))
{
- // Not truely collinear, distinguish for union/intersection
- // If p goes left (positive), take that for a union
- bool const p_left = p_closer ? dm.is_positive() : dm.is_negative();
-
- ti.operations[IndexP].operation = p_left
- ? operation_union : operation_intersection;
- ti.operations[IndexQ].operation = p_left
- ? operation_intersection : operation_union;
- return;
+ set_both_verified<IndexP, IndexQ>(range_p, range_q, umbrella_strategy,
+ index_p, index_q, ti);
}
-#endif
+ else
+ {
+ base_turn_handler::both(ti, operation_continue);
+ }
+ }
- both(ti, operation_continue);
+ template
+ <
+ typename UniqueSubRange1,
+ typename UniqueSubRange2,
+ typename UmbrellaStrategy
+ >
+ static inline int verified_side(int side,
+ UniqueSubRange1 const& range_p,
+ UniqueSubRange2 const& range_q,
+ UmbrellaStrategy const& umbrella_strategy,
+ int index_p, int index_q)
+ {
+ if (side == 0
+ && BOOST_GEOMETRY_CONDITION(VerifyPolicy::use_side_verification))
+ {
+ if (index_p >= 1 && range_p.is_last_segment())
+ {
+ return 0;
+ }
+ if (index_q >= 2 && range_q.is_last_segment())
+ {
+ return 0;
+ }
+
+ auto const dm = get_distance_measure(range_p.at(index_p),
+ range_p.at(index_p + 1),
+ range_q.at(index_q),
+ umbrella_strategy);
+ static decltype(dm.measure) const zero = 0;
+ return dm.measure == zero ? 0 : dm.measure > zero ? 1 : -1;
+ }
+ else
+ {
+ return side;
+ }
}
};
@@ -279,10 +342,12 @@ struct base_turn_handler
template
<
- typename TurnInfo
+ typename TurnInfo,
+ typename VerifyPolicy
>
struct touch_interior : public base_turn_handler
{
+ using fun = turn_info_verification_functions<VerifyPolicy>;
template
<
@@ -292,9 +357,11 @@ struct touch_interior : public base_turn_handler
static bool handle_as_touch(IntersectionInfo const& info,
UniqueSubRange const& non_touching_range)
{
-#if defined(BOOST_GEOMETRY_USE_RESCALING)
- return false;
-#endif
+ if (! BOOST_GEOMETRY_CONDITION(VerifyPolicy::use_handle_as_touch))
+ {
+ return false;
+ }
+
//
//
// ^ Q(i) ^ P(i)
@@ -325,7 +392,7 @@ struct touch_interior : public base_turn_handler
// Therefore handle it as a normal touch (two segments arrive at the
// intersection point). It currently checks for zero, but even a
// distance a little bit larger would do.
- auto const dm = distance_measure(info.intersections[0], non_touching_range.at(1));
+ auto const dm = fun::distance_measure(info.intersections[0], non_touching_range.at(1));
decltype(dm) const zero = 0;
bool const result = math::equals(dm, zero);
return result;
@@ -448,7 +515,8 @@ struct touch_interior : public base_turn_handler
// Q intersects on interior of P and continues collinearly
if (side_qk_q == side_qi_p)
{
- both_collinear<index_p, index_q>(range_p, range_q, umbrella_strategy, 1, 2, ti);
+ fun::template both_collinear<index_p, index_q>(range_p, range_q, umbrella_strategy,
+ 1, 2, ti);
}
else
{
@@ -472,24 +540,35 @@ struct touch_interior : public base_turn_handler
template
<
- typename TurnInfo
+ typename TurnInfo,
+ typename VerifyPolicy
>
struct touch : public base_turn_handler
{
+ using fun = turn_info_verification_functions<VerifyPolicy>;
+
static inline bool between(int side1, int side2, int turn)
{
return side1 == side2 && ! opposite(side1, turn);
}
-#if ! defined(BOOST_GEOMETRY_USE_RESCALING)
template
<
typename UniqueSubRange1,
- typename UniqueSubRange2
+ typename UniqueSubRange2,
+ typename UmbrellaStrategy
>
static inline bool handle_imperfect_touch(UniqueSubRange1 const& range_p,
- UniqueSubRange2 const& range_q, TurnInfo& ti)
+ UniqueSubRange2 const& range_q,
+ int side_pk_q2,
+ UmbrellaStrategy const& umbrella_strategy,
+ TurnInfo& ti)
{
+ if (! BOOST_GEOMETRY_CONDITION(VerifyPolicy::use_handle_imperfect_touch))
+ {
+ return false;
+ }
+
// Q
// ^
// ||
@@ -513,13 +592,18 @@ struct touch : public base_turn_handler
// >----->P qj is LEFT of P1 and pi is LEFT of Q2
// (the other way round is also possible)
- auto const dm_qj_p1 = get_distance_measure(range_p.at(0), range_p.at(1), range_q.at(1));
- auto const dm_pi_q2 = get_distance_measure(range_q.at(1), range_q.at(2), range_p.at(0));
+ auto has_distance = [&](const auto& r1, const auto& r2) -> bool
+ {
+ auto const d1 = get_distance_measure(r1.at(0), r1.at(1), r2.at(1), umbrella_strategy);
+ auto const d2 = get_distance_measure(r2.at(1), r2.at(2), r1.at(0), umbrella_strategy);
+ return d1.measure > 0 && d2.measure > 0;
+ };
- if (dm_qj_p1.measure > 0 && dm_pi_q2.measure > 0)
+ if (side_pk_q2 == -1 && has_distance(range_p, range_q))
{
// Even though there is a touch, Q(j) is left of P1
// and P(i) is still left from Q2.
+ // Q continues to the right.
// It can continue.
ti.operations[0].operation = operation_blocked;
// Q turns right -> union (both independent),
@@ -529,24 +613,17 @@ struct touch : public base_turn_handler
return true;
}
- auto const dm_pj_q1 = get_distance_measure(range_q.at(0), range_q.at(1), range_p.at(1));
- auto const dm_qi_p2 = get_distance_measure(range_p.at(1), range_p.at(2), range_q.at(0));
-
- if (dm_pj_q1.measure > 0 && dm_qi_p2.measure > 0)
+ if (side_pk_q2 == 1 && has_distance(range_q, range_p))
{
- // Even though there is a touch, Q(j) is left of P1
- // and P(i) is still left from Q2.
- // It can continue.
+ // Similarly, but the other way round.
+ // Q continues to the left.
ti.operations[0].operation = operation_union;
- // Q turns right -> union (both independent),
- // Q turns left -> intersection
ti.operations[1].operation = operation_blocked;
ti.touch_only = true;
return true;
}
return false;
}
-#endif
template
<
@@ -572,8 +649,12 @@ struct touch : public base_turn_handler
int const side_pk_q1 = has_pk ? side.pk_wrt_q1() : 0;
- int const side_qi_p1 = verified_side(dir_info.sides.template get<1, 0>(), range_p, range_q, 0, 0);
- int const side_qk_p1 = has_qk ? verified_side(side.qk_wrt_p1(), range_p, range_q, 0, 2) : 0;
+ int const side_qi_p1 = fun::verified_side(dir_info.sides.template get<1, 0>(),
+ range_p, range_q, umbrella_strategy, 0, 0);
+ int const side_qk_p1 = has_qk
+ ? fun::verified_side(side.qk_wrt_p1(), range_p, range_q,
+ umbrella_strategy, 0, 2)
+ : 0;
// If Qi and Qk are both at same side of Pi-Pj,
// or collinear (so: not opposite sides)
@@ -596,21 +677,20 @@ struct touch : public base_turn_handler
|| side_pk_p == side_qk_p1
|| (side_qi_p1 == 0 && side_qk_p1 == 0 && side_pk_p != -1))
{
-#if ! defined(BOOST_GEOMETRY_USE_RESCALING)
if (side_qk_p1 == 0 && side_pk_q1 == 0
- && has_qk && has_qk
- && handle_imperfect_touch(range_p, range_q, ti))
+ && has_pk && has_qk
+ && handle_imperfect_touch(range_p, range_q, side_pk_q2, umbrella_strategy, ti))
{
// If q continues collinearly (opposite) with p, it should be blocked
// but (FP) not if there is just a tiny space in between
return;
}
-#endif
// Collinear -> lines join, continue
// (#BRL2)
if (side_pk_q2 == 0 && ! block_q)
{
- both_collinear<0, 1>(range_p, range_q, umbrella_strategy, 2, 2, ti);
+ fun::template both_collinear<0, 1>(range_p, range_q, umbrella_strategy,
+ 2, 2, ti);
return;
}
@@ -687,7 +767,10 @@ struct touch : public base_turn_handler
{
// The qi/qk are opposite to each other, w.r.t. p1
// From left to right or from right to left
- int const side_pk_p = has_pk ? verified_side(side.pk_wrt_p1(), range_p, range_p, 0, 2) : 0;
+ int const side_pk_p = has_pk
+ ? fun::verified_side(side.pk_wrt_p1(), range_p, range_p,
+ umbrella_strategy, 0, 2)
+ : 0;
bool const right_to_left = side_qk_p1 == 1;
// If p turns into direction of qi (1,2)
@@ -738,10 +821,13 @@ struct touch : public base_turn_handler
template
<
- typename TurnInfo
+ typename TurnInfo,
+ typename VerifyPolicy
>
struct equal : public base_turn_handler
{
+ using fun = turn_info_verification_functions<VerifyPolicy>;
+
template
<
typename UniqueSubRange1,
@@ -769,17 +855,18 @@ struct equal : public base_turn_handler
int const side_pk_p = has_pk ? side.pk_wrt_p1() : 0;
int const side_qk_p = has_qk ? side.qk_wrt_p1() : 0;
-#if ! defined(BOOST_GEOMETRY_USE_RESCALING)
-
- if (has_pk && has_qk && side_pk_p == side_qk_p)
+ if (BOOST_GEOMETRY_CONDITION(VerifyPolicy::use_side_verification)
+ && has_pk && has_qk && side_pk_p == side_qk_p)
{
// They turn to the same side, or continue both collinearly
// Without rescaling, to check for union/intersection,
// try to check side values (without any thresholds)
auto const dm_pk_q2
- = get_distance_measure(range_q.at(1), range_q.at(2), range_p.at(2));
+ = get_distance_measure(range_q.at(1), range_q.at(2), range_p.at(2),
+ umbrella_strategy);
auto const dm_qk_p2
- = get_distance_measure(range_p.at(1), range_p.at(2), range_q.at(2));
+ = get_distance_measure(range_p.at(1), range_p.at(2), range_q.at(2),
+ umbrella_strategy);
if (dm_qk_p2.measure != dm_pk_q2.measure)
{
@@ -789,7 +876,6 @@ struct equal : public base_turn_handler
return;
}
}
-#endif
// If pk is collinear with qj-qk, they continue collinearly.
// This can be on either side of p1 (== q1), or collinear
@@ -797,7 +883,7 @@ struct equal : public base_turn_handler
// oppositely
if (side_pk_q2 == 0 && side_pk_p == side_qk_p)
{
- both_collinear<0, 1>(range_p, range_q, umbrella_strategy, 2, 2, ti);
+ fun::template both_collinear<0, 1>(range_p, range_q, umbrella_strategy, 2, 2, ti);
return;
}
@@ -819,7 +905,8 @@ struct equal : public base_turn_handler
template
<
- typename TurnInfo
+ typename TurnInfo,
+ typename VerifyPolicy
>
struct start : public base_turn_handler
{
@@ -840,10 +927,10 @@ struct start : public base_turn_handler
SideCalculator const& side,
UmbrellaStrategy const& )
{
-#if defined(BOOST_GEOMETRY_USE_RESCALING)
- // With rescaling, start turns are not needed.
- return false;
-#endif
+ if (! BOOST_GEOMETRY_CONDITION(VerifyPolicy::use_start_turn))
+ {
+ return false;
+ }
// Start turns have either how_a = -1, or how_b = -1 (either p leaves or q leaves)
BOOST_GEOMETRY_ASSERT(dir_info.how_a != dir_info.how_b);
@@ -898,7 +985,7 @@ struct equal_opposite : public base_turn_handler
IntersectionInfo const& intersection_info)
{
// For equal-opposite segments, normally don't do anything.
- if (AssignPolicy::include_opposite)
+ if (BOOST_GEOMETRY_CONDITION(AssignPolicy::include_opposite))
{
tp.method = method_equal;
for (unsigned int i = 0; i < 2; i++)
@@ -916,10 +1003,13 @@ struct equal_opposite : public base_turn_handler
template
<
- typename TurnInfo
+ typename TurnInfo,
+ typename VerifyPolicy
>
struct collinear : public base_turn_handler
{
+ using fun = turn_info_verification_functions<VerifyPolicy>;
+
template
<
typename IntersectionInfo,
@@ -932,9 +1022,11 @@ struct collinear : public base_turn_handler
UniqueSubRange2 const& range_q,
DirInfo const& dir_info)
{
-#if defined(BOOST_GEOMETRY_USE_RESCALING)
- return false;
-#endif
+ if (! BOOST_GEOMETRY_CONDITION(VerifyPolicy::use_handle_as_equal))
+ {
+ return false;
+ }
+
int const arrival_p = dir_info.arrival[0];
int const arrival_q = dir_info.arrival[1];
if (arrival_p * arrival_q != -1 || info.count != 2)
@@ -943,8 +1035,9 @@ struct collinear : public base_turn_handler
return false;
}
- auto const dm = distance_measure(info.intersections[1],
- arrival_p == 1 ? range_q.at(1) : range_p.at(1));
+ auto const dm = arrival_p == 1
+ ? fun::distance_measure(info.intersections[1], range_q.at(1))
+ : fun::distance_measure(info.intersections[1], range_p.at(1));
decltype(dm) const zero = 0;
return math::equals(dm, zero);
}
@@ -1046,12 +1139,12 @@ struct collinear : public base_turn_handler
// measured until the end of the next segment
ti.operations[0].remaining_distance
= side_p == 0 && has_pk
- ? distance_measure(ti.point, range_p.at(2))
- : distance_measure(ti.point, range_p.at(1));
+ ? fun::distance_measure(ti.point, range_p.at(2))
+ : fun::distance_measure(ti.point, range_p.at(1));
ti.operations[1].remaining_distance
= side_q == 0 && has_qk
- ? distance_measure(ti.point, range_q.at(2))
- : distance_measure(ti.point, range_q.at(1));
+ ? fun::distance_measure(ti.point, range_q.at(2))
+ : fun::distance_measure(ti.point, range_q.at(1));
}
};
@@ -1110,7 +1203,7 @@ private :
// two operations blocked, so the whole point does not need
// to be generated.
// So return false to indicate nothing is to be done.
- if (AssignPolicy::include_opposite)
+ if (BOOST_GEOMETRY_CONDITION(AssignPolicy::include_opposite))
{
tp.operations[Index].operation = operation_opposite;
blocked = operation_opposite;
@@ -1204,7 +1297,7 @@ public:
*out++ = tp;
}
- if (AssignPolicy::include_opposite)
+ if (BOOST_GEOMETRY_CONDITION(AssignPolicy::include_opposite))
{
// Handle cases not yet handled above
if ((arrival_q == -1 && arrival_p == 0)
@@ -1352,8 +1445,11 @@ struct get_turn_info
if (handle_as_start)
{
// It is in some cases necessary to handle a start turn
- if (AssignPolicy::include_start_turn
- && start<TurnInfo>::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides(), umbrella_strategy))
+ using handler = start<TurnInfo, verify_policy_aa>;
+ if (BOOST_GEOMETRY_CONDITION(AssignPolicy::include_start_turn)
+ && handler::apply(range_p, range_q, tp,
+ inters.i_info(), inters.d_info(), inters.sides(),
+ umbrella_strategy))
{
*out++ = tp;
}
@@ -1365,7 +1461,7 @@ struct get_turn_info
if (handle_as_touch_interior)
{
- typedef touch_interior<TurnInfo> handler;
+ using handler = touch_interior<TurnInfo, verify_policy_aa>;
if ( inters.d_info().arrival[1] == 1 )
{
@@ -1406,7 +1502,9 @@ struct get_turn_info
if (handle_as_touch)
{
// Touch: both segments arrive at the intersection point
- touch<TurnInfo>::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides(), umbrella_strategy);
+ using handler = touch<TurnInfo, verify_policy_aa>;
+ handler::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides(),
+ umbrella_strategy);
*out++ = tp;
}
@@ -1415,16 +1513,17 @@ struct get_turn_info
// Collinear
if ( ! inters.d_info().opposite )
{
+ using handler = collinear<TurnInfo, verify_policy_aa>;
if (inters.d_info().arrival[0] == 0
- || collinear<TurnInfo>::handle_as_equal(inters.i_info(), range_p, range_q, inters.d_info()))
+ || handler::handle_as_equal(inters.i_info(), range_p, range_q, inters.d_info()))
{
// Both segments arrive at the second intersection point
handle_as_equal = true;
}
else
{
- collinear<TurnInfo>::apply(range_p, range_q, tp,
- inters.i_info(), inters.d_info(), inters.sides());
+ handler::apply(range_p, range_q, tp, inters.i_info(),
+ inters.d_info(), inters.sides());
*out++ = tp;
}
}
@@ -1445,7 +1544,8 @@ struct get_turn_info
{
// Both equal
// or collinear-and-ending at intersection point
- equal<TurnInfo>::apply(range_p, range_q, tp,
+ using handler = equal<TurnInfo, verify_policy_aa>;
+ handler::apply(range_p, range_q, tp,
inters.i_info(), inters.d_info(), inters.sides(),
umbrella_strategy);
if (handle_as_collinear)
@@ -1467,8 +1567,10 @@ struct get_turn_info
}
}
- if ((handle_as_degenerate && AssignPolicy::include_degenerate)
- || (do_only_convert && AssignPolicy::include_no_turn))
+ if ((handle_as_degenerate
+ && BOOST_GEOMETRY_CONDITION(AssignPolicy::include_degenerate))
+ || (do_only_convert
+ && BOOST_GEOMETRY_CONDITION(AssignPolicy::include_no_turn)))
{
if (inters.i_info().count > 0)
{
@@ -1489,8 +1591,4 @@ struct get_turn_info
}} // namespace boost::geometry
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif
-
#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp
index 2b56d7dd57..007ada0f2f 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp
@@ -201,7 +201,7 @@ public:
BOOST_STATIC_ASSERT(I < 2);
return ips[I];
}
-
+
private:
// only if collinear (same_dirs)
@@ -287,7 +287,7 @@ struct get_turn_info_for_endpoint
if ( intersections.template get<1>().p_operation == operation_none )
return result_ignore_ip0;
-
+
bool append1_last
= analyse_segment_and_assign_ip(range_p, range_q,
intersections.template get<1>(),
@@ -436,7 +436,7 @@ struct get_turn_info_for_endpoint
if ( operations_both(operations, operation_continue) )
{
- if ( op1 != operation_union
+ if ( op1 != operation_union
|| op2 != operation_union
|| ! ( G1Index == 0 ? inters.is_spike_q() : inters.is_spike_p() ) )
{
@@ -544,7 +544,7 @@ struct get_turn_info_for_endpoint
OutputIterator out)
{
TurnInfo tp = tp_model;
-
+
//geometry::convert(ip, tp.point);
//tp.method = method;
base_turn_handler::assign_point(tp, method, result.intersection_points, ip_index);
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
index b82528fa4d..00a6004f2d 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
@@ -50,8 +50,6 @@ template
>
struct side_calculator
{
- typedef typename UniqueSubRange1::point_type point1_type;
- typedef typename UniqueSubRange2::point_type point2_type;
typedef decltype(std::declval<Strategy>().side()) side_strategy_type;
inline side_calculator(UniqueSubRange1 const& range_p,
@@ -76,13 +74,13 @@ struct side_calculator
inline int pj_wrt_q1() const { return m_side_strategy.apply(get_qi(), get_qj(), get_pj()); }
inline int pj_wrt_q2() const { return m_side_strategy.apply(get_qj(), get_qk(), get_pj()); }
- inline point1_type const& get_pi() const { return m_range_p.at(0); }
- inline point1_type const& get_pj() const { return m_range_p.at(1); }
- inline point1_type const& get_pk() const { return m_range_p.at(2); }
+ inline auto const& get_pi() const { return m_range_p.at(0); }
+ inline auto const& get_pj() const { return m_range_p.at(1); }
+ inline auto const& get_pk() const { return m_range_p.at(2); }
- inline point2_type const& get_qi() const { return m_range_q.at(0); }
- inline point2_type const& get_qj() const { return m_range_q.at(1); }
- inline point2_type const& get_qk() const { return m_range_q.at(2); }
+ inline auto const& get_qi() const { return m_range_q.at(0); }
+ inline auto const& get_qj() const { return m_range_q.at(1); }
+ inline auto const& get_qk() const { return m_range_q.at(2); }
// Used side-strategy, owned by the calculator
side_strategy_type m_side_strategy;
@@ -338,9 +336,6 @@ public:
typedef typename intersection_policy_type::return_type result_type;
- typedef typename UniqueSubRange1::point_type point1_type;
- typedef typename UniqueSubRange2::point_type point2_type;
-
typedef side_calculator
<
UniqueSubRange1, UniqueSubRange2, UmbrellaStrategy
@@ -350,7 +345,7 @@ public:
<
UniqueSubRange2, UniqueSubRange1, UmbrellaStrategy
> swapped_side_calculator_type;
-
+
intersection_info_base(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
UmbrellaStrategy const& umbrella_strategy,
@@ -366,13 +361,13 @@ public:
inline bool p_is_last_segment() const { return m_range_p.is_last_segment(); }
inline bool q_is_last_segment() const { return m_range_q.is_last_segment(); }
- inline point1_type const& rpi() const { return m_side_calc.get_pi(); }
- inline point1_type const& rpj() const { return m_side_calc.get_pj(); }
- inline point1_type const& rpk() const { return m_side_calc.get_pk(); }
+ inline auto const& rpi() const { return m_side_calc.get_pi(); }
+ inline auto const& rpj() const { return m_side_calc.get_pj(); }
+ inline auto const& rpk() const { return m_side_calc.get_pk(); }
- inline point2_type const& rqi() const { return m_side_calc.get_qi(); }
- inline point2_type const& rqj() const { return m_side_calc.get_qj(); }
- inline point2_type const& rqk() const { return m_side_calc.get_qk(); }
+ inline auto const& rqi() const { return m_side_calc.get_qi(); }
+ inline auto const& rqj() const { return m_side_calc.get_qj(); }
+ inline auto const& rqk() const { return m_side_calc.get_qk(); }
inline side_calculator_type const& sides() const { return m_side_calc; }
inline swapped_side_calculator_type const& swapped_sides() const
@@ -410,14 +405,11 @@ class intersection_info
public:
- typedef typename UniqueSubRange1::point_type point1_type;
- typedef typename UniqueSubRange2::point_type point2_type;
-
typedef typename UmbrellaStrategy::cs_tag cs_tag;
typedef typename base::side_calculator_type side_calculator_type;
typedef typename base::result_type result_type;
-
+
typedef typename result_type::intersection_points_type i_info_type;
typedef typename result_type::direction_type d_info_type;
@@ -470,7 +462,7 @@ public:
return true;
}
}
-
+
return false;
}
@@ -493,18 +485,18 @@ public:
bool const has_pk = ! base::p_is_last_segment();
int const pk_q1 = has_pk ? base::sides().pk_wrt_q1() : 0;
int const pk_q2 = has_pk ? base::sides().pk_wrt_q2() : 0;
-
+
if (pk_q1 == -pk_q2)
{
if (pk_q1 == 0)
{
return direction_code<cs_tag>(base::rqi(), base::rqj(), base::rqk()) == -1;
}
-
+
return true;
}
}
-
+
return false;
}
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp
index 20aaa6a434..76d7faf6de 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp
@@ -95,7 +95,7 @@ struct get_turn_info_linear_areal
}
else
{
- typedef touch_interior<TurnInfo> handler;
+ using handler = touch_interior<TurnInfo, verify_policy_la>;
// If Q (1) arrives (1)
if ( inters.d_info().arrival[1] == 1 )
@@ -120,12 +120,12 @@ struct get_turn_info_linear_areal
replace_method_and_operations_tm(tp.method,
tp.operations[0].operation,
tp.operations[1].operation);
-
+
// this function assumes that 'u' must be set for a spike
calculate_spike_operation(tp.operations[0].operation,
inters,
umbrella_strategy);
-
+
*out++ = tp;
}
}
@@ -148,9 +148,10 @@ struct get_turn_info_linear_areal
{
// do nothing
}
- else
+ else
{
- touch<TurnInfo>::apply(range_p, range_q, tp,
+ using handler = touch<TurnInfo, verify_policy_la>;
+ handler::apply(range_p, range_q, tp,
inters.i_info(), inters.d_info(), inters.sides(),
umbrella_strategy);
@@ -177,7 +178,7 @@ struct get_turn_info_linear_areal
}
else
{
- tp.operations[0].operation = operation_union;
+ tp.operations[0].operation = operation_union;
}
}
}
@@ -246,7 +247,8 @@ struct get_turn_info_linear_areal
{
// Both equal
// or collinear-and-ending at intersection point
- equal<TurnInfo>::apply(range_p, range_q, tp,
+ using handler = equal<TurnInfo, verify_policy_la>;
+ handler::apply(range_p, range_q, tp,
inters.i_info(), inters.d_info(), inters.sides(),
umbrella_strategy);
@@ -295,7 +297,8 @@ struct get_turn_info_linear_areal
if ( inters.d_info().arrival[0] == 0 )
{
// Collinear, but similar thus handled as equal
- equal<TurnInfo>::apply(range_p, range_q, tp,
+ using handler = equal<TurnInfo, verify_policy_la>;
+ handler::apply(range_p, range_q, tp,
inters.i_info(), inters.d_info(), inters.sides(),
umbrella_strategy);
@@ -304,8 +307,9 @@ struct get_turn_info_linear_areal
}
else
{
- collinear<TurnInfo>::apply(range_p, range_q, tp,
- inters.i_info(), inters.d_info(), inters.sides());
+ using handler = collinear<TurnInfo, verify_policy_la>;
+ handler::apply(range_p, range_q, tp, inters.i_info(),
+ inters.d_info(), inters.sides());
//method_replace = method_touch_interior;
//version = append_collinear;
@@ -403,7 +407,7 @@ struct get_turn_info_linear_areal
if ( is_p_spike )
{
int const pk_q1 = inters.sides().pk_wrt_q1();
-
+
bool going_in = pk_q1 < 0; // Pk on the right
bool going_out = pk_q1 > 0; // Pk on the left
@@ -411,7 +415,7 @@ struct get_turn_info_linear_areal
// special cases
if ( qk_q1 < 0 ) // Q turning R
- {
+ {
// spike on the edge point
// if it's already known that the spike is going out this musn't be checked
if ( ! going_out
@@ -524,7 +528,7 @@ struct get_turn_info_linear_areal
|| tp.operations[0].operation == operation_intersection ) : // i ???
true )
&& inters.is_spike_p();
-
+
// TODO: throw an exception for spike in Areal?
/*bool is_q_spike = ( ( Version == append_touches
&& tp.operations[1].operation == operation_continue )
@@ -671,7 +675,7 @@ struct get_turn_info_linear_areal
// possible to define a spike on an endpoint. Areal geometries must
// NOT have spikes at all. One thing that could be done is to throw
// an exception when spike is detected in Areal geometry.
-
+
template <bool EnableFirst,
bool EnableLast,
typename UniqueSubRange1,
@@ -797,7 +801,7 @@ struct get_turn_info_linear_areal
&& ( ip_count > 1 ? (ip1.is_pj && !ip1.is_qi) : (ip0.is_pj && !ip0.is_qi) ) ) // prevents duplication
{
TurnInfo tp = tp_model;
-
+
if ( inters.i_info().count > 1 )
{
//BOOST_GEOMETRY_ASSERT( result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0 );
@@ -823,7 +827,7 @@ struct get_turn_info_linear_areal
{
side_pi_y = sides.apply(range_q.at(1), range_q.at(2), range_p.at(0)); // pi wrt q2
side_pi_x = sides.apply(range_q.at(0), range_q.at(1), range_p.at(0)); // pi wrt q1
- side_qz_x = sides.apply(range_q.at(0), range_q.at(1), range_q.at(2)); // qk wrt q1
+ side_qz_x = sides.apply(range_q.at(0), range_q.at(1), range_q.at(2)); // qk wrt q1
}
// 2. ip0 or pj in the middle of q1
else
@@ -849,7 +853,7 @@ struct get_turn_info_linear_areal
tp.operations[0].operation = operation_blocked;
tp.operations[0].position = position_back;
tp.operations[1].position = position_middle;
-
+
// equals<> or collinear<> will assign the second point,
// we'd like to assign the first one
unsigned int ip_index = ip_count > 1 ? 1 : 0;
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp
index ccb5e668ae..6dbd6d682c 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp
@@ -83,6 +83,8 @@ struct get_turn_info_linear_linear
case 'm' :
{
+ using handler = touch_interior<TurnInfo, verify_policy_ll>;
+
if ( get_turn_info_for_endpoint<false, true>
::apply(range_p, range_q,
tp_model, inters, method_touch_interior, out,
@@ -92,15 +94,10 @@ struct get_turn_info_linear_linear
}
else
{
- typedef touch_interior
- <
- TurnInfo
- > policy;
-
// If Q (1) arrives (1)
if ( inters.d_info().arrival[1] == 1)
{
- policy::template apply<0>(range_p, range_q, tp,
+ handler::template apply<0>(range_p, range_q, tp,
inters.i_info(), inters.d_info(),
inters.sides(),
umbrella_strategy);
@@ -108,12 +105,12 @@ struct get_turn_info_linear_linear
else
{
// Swap p/q
- policy::template apply<1>(range_q, range_p, tp,
+ handler::template apply<1>(range_q, range_p, tp,
inters.i_info(), inters.d_info(),
inters.swapped_sides(),
umbrella_strategy);
}
-
+
if ( tp.operations[0].operation == operation_blocked )
{
tp.operations[1].is_collinear = true;
@@ -126,7 +123,7 @@ struct get_turn_info_linear_linear
replace_method_and_operations_tm(tp.method,
tp.operations[0].operation,
tp.operations[1].operation);
-
+
*out++ = tp;
}
}
@@ -142,6 +139,8 @@ struct get_turn_info_linear_linear
break;
case 't' :
{
+ using handler = touch<TurnInfo, verify_policy_ll>;
+
// Both touch (both arrive there)
if ( get_turn_info_for_endpoint<false, true>
::apply(range_p, range_q,
@@ -150,12 +149,12 @@ struct get_turn_info_linear_linear
{
// do nothing
}
- else
+ else
{
- touch<TurnInfo>::apply(range_p, range_q, tp,
- inters.i_info(), inters.d_info(),
- inters.sides(),
- umbrella_strategy);
+ handler::apply(range_p, range_q, tp,
+ inters.i_info(), inters.d_info(),
+ inters.sides(),
+ umbrella_strategy);
// workarounds for touch<> not taking spikes into account starts here
// those was discovered empirically
@@ -170,7 +169,7 @@ struct get_turn_info_linear_linear
if ( inters.is_spike_p() && inters.is_spike_q() )
{
tp.operations[0].operation = operation_union;
- tp.operations[1].operation = operation_union;
+ tp.operations[1].operation = operation_union;
}
else
{
@@ -189,7 +188,7 @@ struct get_turn_info_linear_linear
}
else
{
- tp.operations[0].operation = operation_union;
+ tp.operations[0].operation = operation_union;
}
}
else
@@ -208,7 +207,7 @@ struct get_turn_info_linear_linear
}
else
{
- tp.operations[1].operation = operation_union;
+ tp.operations[1].operation = operation_union;
}
}
else
@@ -224,7 +223,7 @@ struct get_turn_info_linear_linear
&& inters.is_spike_p() )
{
tp.operations[0].operation = operation_union;
- tp.operations[1].operation = operation_union;
+ tp.operations[1].operation = operation_union;
}
}
else if ( tp.operations[0].operation == operation_none
@@ -275,6 +274,8 @@ struct get_turn_info_linear_linear
break;
case 'e':
{
+ using handler = equal<TurnInfo, verify_policy_ll>;
+
if ( get_turn_info_for_endpoint<true, true>
::apply(range_p, range_q,
tp_model, inters, method_equal, out,
@@ -291,7 +292,7 @@ struct get_turn_info_linear_linear
{
// Both equal
// or collinear-and-ending at intersection point
- equal<TurnInfo>::apply(range_p, range_q, tp,
+ handler::apply(range_p, range_q, tp,
inters.i_info(), inters.d_info(), inters.sides(),
umbrella_strategy);
@@ -351,7 +352,9 @@ struct get_turn_info_linear_linear
if ( inters.d_info().arrival[0] == 0 )
{
// Collinear, but similar thus handled as equal
- equal<TurnInfo>::apply(range_p, range_q, tp,
+ using handler = equal<TurnInfo, verify_policy_ll>;
+
+ handler::apply(range_p, range_q, tp,
inters.i_info(), inters.d_info(), inters.sides(),
umbrella_strategy);
@@ -364,8 +367,10 @@ struct get_turn_info_linear_linear
}
else
{
- collinear<TurnInfo>::apply(range_p, range_q,
- tp, inters.i_info(), inters.d_info(), inters.sides());
+ using handler = collinear<TurnInfo, verify_policy_ll>;
+ handler::apply(range_p, range_q, tp,
+ inters.i_info(), inters.d_info(),
+ inters.sides());
//method_replace = method_touch_interior;
//spike_op = operation_continue;
@@ -374,7 +379,7 @@ struct get_turn_info_linear_linear
// transform turn
turn_transformer_ec transformer(method_replace);
transformer(tp);
-
+
// conditionally handle spikes
if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes)
|| ! append_collinear_spikes(tp, inters,
@@ -519,7 +524,7 @@ struct get_turn_info_linear_linear
return true;
}
-
+
return false;
}
@@ -562,9 +567,9 @@ struct get_turn_info_linear_linear
{
tp.operations[0].is_collinear = true;
tp.operations[1].is_collinear = false;
-
+
BOOST_GEOMETRY_ASSERT(inters.i_info().count > 1);
-
+
base_turn_handler::assign_point(tp, method_touch_interior,
inters.i_info(), 1);
}
@@ -593,7 +598,7 @@ struct get_turn_info_linear_linear
{
tp.operations[0].is_collinear = false;
tp.operations[1].is_collinear = true;
-
+
BOOST_GEOMETRY_ASSERT(inters.i_info().count > 0);
base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 0);
@@ -608,7 +613,7 @@ struct get_turn_info_linear_linear
res = true;
}
-
+
return res;
}
diff --git a/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/boost/geometry/algorithms/detail/overlay/get_turns.hpp
index 35ca5157de..326c883b39 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turns.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turns.hpp
@@ -1,11 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2014-2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
-
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -16,10 +15,10 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP
+#include <array>
#include <cstddef>
#include <map>
-#include <boost/array.hpp>
#include <boost/concept_check.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/range/begin.hpp>
@@ -29,7 +28,6 @@
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp>
@@ -111,7 +109,7 @@ template
>
struct unique_sub_range_from_section
{
- typedef Point point_type;
+ using point_type = Point;
unique_sub_range_from_section(Section const& section, signed_size_type index,
CircularIterator circular_iterator,
@@ -123,7 +121,7 @@ struct unique_sub_range_from_section
, m_previous_point(previous)
, m_current_point(current)
, m_circular_iterator(circular_iterator)
- , m_point_retrieved(false)
+ , m_next_point_retrieved(false)
, m_strategy(strategy)
, m_robust_policy(robust_policy)
{}
@@ -158,18 +156,18 @@ struct unique_sub_range_from_section
private :
inline Point const& get_next_point() const
{
- if (! m_point_retrieved)
+ if (! m_next_point_retrieved)
{
advance_to_non_duplicate_next(m_current_point, m_circular_iterator);
- m_point = *m_circular_iterator;
- m_point_retrieved = true;
+ m_next_point_retrieved = true;
}
- return m_point;
+ return *m_circular_iterator;
}
inline void advance_to_non_duplicate_next(Point const& current, CircularIterator& circular_iterator) const
{
- typedef typename robust_point_type<Point, RobustPolicy>::type robust_point_type;
+ using box_point_type = typename geometry::point_type<typename Section::box_type>::type;
+ using robust_point_type = typename robust_point_type<box_point_type, RobustPolicy>::type;
robust_point_type current_robust_point;
robust_point_type next_robust_point;
geometry::recalculate(current_robust_point, current, m_robust_policy);
@@ -199,8 +197,7 @@ private :
Point const& m_previous_point;
Point const& m_current_point;
mutable CircularIterator m_circular_iterator;
- mutable Point m_point;
- mutable bool m_point_retrieved;
+ mutable bool m_next_point_retrieved;
Strategy m_strategy;
RobustPolicy m_robust_policy;
};
@@ -571,7 +568,7 @@ struct get_turns_cs
{
typedef typename geometry::point_type<Range>::type range_point_type;
typedef typename geometry::point_type<Box>::type box_point_type;
- typedef boost::array<box_point_type, 4> box_array;
+ typedef std::array<box_point_type, 4> box_array;
using view_type = detail::closed_clockwise_view
<
@@ -843,10 +840,8 @@ struct get_turns_polygon_cs
signed_size_type i = 0;
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(polygon);
- for (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it, ++i)
+ auto const& rings = interior_rings(polygon);
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it, ++i)
{
intersector_type::apply(
source_id1, *it,
@@ -878,15 +873,8 @@ struct get_turns_multi_polygon_cs
Turns& turns,
InterruptPolicy& interrupt_policy)
{
- typedef typename boost::range_iterator
- <
- Multi const
- >::type iterator_type;
-
signed_size_type i = 0;
- for (iterator_type it = boost::begin(multi);
- it != boost::end(multi);
- ++it, ++i)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it, ++i)
{
// Call its single version
get_turns_polygon_cs
@@ -927,24 +915,24 @@ struct get_turn_info_type<Geometry1, Geometry2, AssignPolicy, Tag1, Tag2, linear
: overlay::get_turn_info_linear_areal<AssignPolicy>
{};
-template <typename Geometry1, typename Geometry2, typename SegmentRatio,
+template <typename Geometry1, typename Geometry2, typename Point, typename SegmentRatio,
typename Tag1 = typename tag<Geometry1>::type, typename Tag2 = typename tag<Geometry2>::type,
typename TagBase1 = typename topological_tag_base<Geometry1>::type, typename TagBase2 = typename topological_tag_base<Geometry2>::type>
struct turn_operation_type
{
- typedef overlay::turn_operation<typename point_type<Geometry1>::type, SegmentRatio> type;
+ using type = overlay::turn_operation<Point, SegmentRatio>;
};
-template <typename Geometry1, typename Geometry2, typename SegmentRatio, typename Tag1, typename Tag2>
-struct turn_operation_type<Geometry1, Geometry2, SegmentRatio, Tag1, Tag2, linear_tag, linear_tag>
+template <typename Geometry1, typename Geometry2, typename Point, typename SegmentRatio, typename Tag1, typename Tag2>
+struct turn_operation_type<Geometry1, Geometry2, Point, SegmentRatio, Tag1, Tag2, linear_tag, linear_tag>
{
- typedef overlay::turn_operation_linear<typename point_type<Geometry1>::type, SegmentRatio> type;
+ using type = overlay::turn_operation_linear<Point, SegmentRatio>;
};
-template <typename Geometry1, typename Geometry2, typename SegmentRatio, typename Tag1, typename Tag2>
-struct turn_operation_type<Geometry1, Geometry2, SegmentRatio, Tag1, Tag2, linear_tag, areal_tag>
+template <typename Geometry1, typename Geometry2, typename Point, typename SegmentRatio, typename Tag1, typename Tag2>
+struct turn_operation_type<Geometry1, Geometry2, Point, SegmentRatio, Tag1, Tag2, linear_tag, areal_tag>
{
- typedef overlay::turn_operation_linear<typename point_type<Geometry1>::type, SegmentRatio> type;
+ using type = overlay::turn_operation_linear<Point, SegmentRatio>;
};
}} // namespace detail::get_turns
diff --git a/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp b/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
index 9afea24c2b..aaabb4a4df 100644
--- a/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
+++ b/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
@@ -29,6 +29,7 @@
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
+#include <boost/geometry/algorithms/detail/overlay/colocate_clusters.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_clusters.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
#include <boost/geometry/algorithms/detail/overlay/is_self_turn.hpp>
@@ -52,22 +53,22 @@ namespace boost { namespace geometry
namespace detail { namespace overlay
{
+// Removes clusters which have only one point left, or are empty.
template <typename Turns, typename Clusters>
inline void remove_clusters(Turns& turns, Clusters& clusters)
{
- typename Clusters::iterator it = clusters.begin();
+ auto it = clusters.begin();
while (it != clusters.end())
{
// Hold iterator and increase. We can erase cit, this keeps the
// iterator valid (cf The standard associative-container erase idiom)
- typename Clusters::iterator current_it = it;
+ auto current_it = it;
++it;
- std::set<signed_size_type> const& turn_indices
- = current_it->second.turn_indices;
+ auto const& turn_indices = current_it->second.turn_indices;
if (turn_indices.size() == 1)
{
- signed_size_type const turn_index = *turn_indices.begin();
+ auto const turn_index = *turn_indices.begin();
turns[turn_index].cluster_id = -1;
clusters.erase(current_it);
}
@@ -78,36 +79,35 @@ template <typename Turns, typename Clusters>
inline void cleanup_clusters(Turns& turns, Clusters& clusters)
{
// Removes discarded turns from clusters
- for (typename Clusters::iterator mit = clusters.begin();
- mit != clusters.end(); ++mit)
+ for (auto& pair : clusters)
{
- cluster_info& cinfo = mit->second;
- std::set<signed_size_type>& ids = cinfo.turn_indices;
- for (std::set<signed_size_type>::iterator sit = ids.begin();
- sit != ids.end(); /* no increment */)
+ auto& cinfo = pair.second;
+ auto& indices = cinfo.turn_indices;
+ for (auto sit = indices.begin(); sit != indices.end(); /* no increment */)
{
- std::set<signed_size_type>::iterator current_it = sit;
+ auto current_it = sit;
++sit;
- signed_size_type const turn_index = *current_it;
+ auto const turn_index = *current_it;
if (turns[turn_index].discarded)
{
- ids.erase(current_it);
+ indices.erase(current_it);
}
}
}
remove_clusters(turns, clusters);
+ colocate_clusters(clusters, turns);
}
-template <typename Turn, typename IdSet>
-inline void discard_colocated_turn(Turn& turn, IdSet& ids, signed_size_type id)
+template <typename Turn, typename IndexSet>
+inline void discard_colocated_turn(Turn& turn, IndexSet& indices, signed_size_type index)
{
turn.discarded = true;
// Set cluster id to -1, but don't clear colocated flags
turn.cluster_id = -1;
// To remove it later from clusters
- ids.insert(id);
+ indices.insert(index);
}
template <bool Reverse>
@@ -167,22 +167,17 @@ template
>
inline void discard_interior_exterior_turns(Turns& turns, Clusters& clusters)
{
- typedef std::set<signed_size_type>::const_iterator set_iterator;
- typedef typename boost::range_value<Turns>::type turn_type;
-
- std::set<signed_size_type> ids_to_remove;
+ std::set<signed_size_type> indices_to_remove;
- for (typename Clusters::iterator cit = clusters.begin();
- cit != clusters.end(); ++cit)
+ for (auto& pair : clusters)
{
- cluster_info& cinfo = cit->second;
- std::set<signed_size_type>& ids = cinfo.turn_indices;
+ cluster_info& cinfo = pair.second;
- ids_to_remove.clear();
+ indices_to_remove.clear();
- for (set_iterator it = ids.begin(); it != ids.end(); ++it)
+ for (auto index : cinfo.turn_indices)
{
- turn_type& turn = turns[*it];
+ auto& turn = turns[index];
segment_identifier const& seg_0 = turn.operations[0].seg_id;
segment_identifier const& seg_1 = turn.operations[1].seg_id;
@@ -193,34 +188,33 @@ inline void discard_interior_exterior_turns(Turns& turns, Clusters& clusters)
continue;
}
- for (set_iterator int_it = ids.begin(); int_it != ids.end(); ++int_it)
+ for (auto interior_index : cinfo.turn_indices)
{
- if (*it == *int_it)
+ if (index == interior_index)
{
continue;
}
// Turn with, possibly, an interior ring involved
- turn_type& int_turn = turns[*int_it];
- segment_identifier const& int_seg_0 = int_turn.operations[0].seg_id;
- segment_identifier const& int_seg_1 = int_turn.operations[1].seg_id;
+ auto& interior_turn = turns[interior_index];
+ segment_identifier const& int_seg_0 = interior_turn.operations[0].seg_id;
+ segment_identifier const& int_seg_1 = interior_turn.operations[1].seg_id;
if (is_ie_turn<Reverse0, Reverse1>(seg_0, seg_1, int_seg_0, int_seg_1))
{
- discard_colocated_turn(int_turn, ids_to_remove, *int_it);
+ discard_colocated_turn(interior_turn, indices_to_remove, interior_index);
}
if (is_ie_turn<Reverse1, Reverse0>(seg_1, seg_0, int_seg_1, int_seg_0))
{
- discard_colocated_turn(int_turn, ids_to_remove, *int_it);
+ discard_colocated_turn(interior_turn, indices_to_remove, interior_index);
}
}
}
- // Erase from the ids (which cannot be done above)
- for (set_iterator sit = ids_to_remove.begin();
- sit != ids_to_remove.end(); ++sit)
+ // Erase from the indices (which cannot be done above)
+ for (auto index : indices_to_remove)
{
- ids.erase(*sit);
+ cinfo.turn_indices.erase(index);
}
}
}
@@ -233,19 +227,14 @@ template
>
inline void set_colocation(Turns& turns, Clusters const& clusters)
{
- typedef std::set<signed_size_type>::const_iterator set_iterator;
- typedef typename boost::range_value<Turns>::type turn_type;
-
- for (typename Clusters::const_iterator cit = clusters.begin();
- cit != clusters.end(); ++cit)
+ for (auto const& pair : clusters)
{
- cluster_info const& cinfo = cit->second;
- std::set<signed_size_type> const& ids = cinfo.turn_indices;
+ cluster_info const& cinfo = pair.second;
bool both_target = false;
- for (set_iterator it = ids.begin(); it != ids.end(); ++it)
+ for (auto index : cinfo.turn_indices)
{
- turn_type const& turn = turns[*it];
+ auto const& turn = turns[index];
if (turn.both(operation_from_overlay<OverlayType>::value))
{
both_target = true;
@@ -255,9 +244,9 @@ inline void set_colocation(Turns& turns, Clusters const& clusters)
if (both_target)
{
- for (set_iterator it = ids.begin(); it != ids.end(); ++it)
+ for (auto index : cinfo.turn_indices)
{
- turn_type& turn = turns[*it];
+ auto& turn = turns[index];
turn.has_colocated_both = true;
}
}
@@ -276,7 +265,7 @@ inline void check_colocation(bool& has_blocked,
has_blocked = false;
- typename Clusters::const_iterator mit = clusters.find(cluster_id);
+ auto mit = clusters.find(cluster_id);
if (mit == clusters.end())
{
return;
@@ -284,11 +273,9 @@ inline void check_colocation(bool& has_blocked,
cluster_info const& cinfo = mit->second;
- for (std::set<signed_size_type>::const_iterator it
- = cinfo.turn_indices.begin();
- it != cinfo.turn_indices.end(); ++it)
+ for (auto index : cinfo.turn_indices)
{
- turn_type const& turn = turns[*it];
+ turn_type const& turn = turns[index];
if (turn.any_blocked())
{
has_blocked = true;
@@ -410,21 +397,15 @@ inline bool fill_sbs(Sbs& sbs, Point& turn_point,
Turns const& turns,
Geometry1 const& geometry1, Geometry2 const& geometry2)
{
- typedef typename boost::range_value<Turns>::type turn_type;
-
- std::set<signed_size_type> const& ids = cinfo.turn_indices;
-
- if (ids.empty())
+ if (cinfo.turn_indices.empty())
{
return false;
}
bool first = true;
- for (std::set<signed_size_type>::const_iterator sit = ids.begin();
- sit != ids.end(); ++sit)
+ for (auto turn_index : cinfo.turn_indices)
{
- signed_size_type turn_index = *sit;
- turn_type const& turn = turns[turn_index];
+ auto const& turn = turns[turn_index];
if (first)
{
turn_point = turn.point;
@@ -464,10 +445,9 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
Reverse1, Reverse2, OverlayType, point_type, SideStrategy, std::less<int>
> sbs_type;
- for (typename Clusters::iterator mit = clusters.begin();
- mit != clusters.end(); ++mit)
+ for (auto& pair : clusters)
{
- cluster_info& cinfo = mit->second;
+ cluster_info& cinfo = pair.second;
sbs_type sbs(strategy);
point_type turn_point; // should be all the same for all turns in cluster
@@ -515,10 +495,10 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
continue;
}
- if (BOOST_GEOMETRY_CONDITION(OverlayType != overlay_difference)
+ if (BOOST_GEOMETRY_CONDITION(OverlayType == overlay_difference)
&& is_self_turn<OverlayType>(turn))
{
- // Difference needs the self-turns, TODO: investigate
+ // TODO: investigate
continue;
}
diff --git a/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp b/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp
index aec43548d4..435a80c272 100644
--- a/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp
+++ b/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp
@@ -1,10 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2017 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2017-2023 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2019-2020.
-// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2022.
+// Modifications copyright (c) 2019-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -19,11 +19,11 @@
#include <boost/range/end.hpp>
#include <boost/range/value_type.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
#include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/is_self_turn.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
-#include <boost/geometry/algorithms/covered_by.hpp>
-#include <boost/geometry/algorithms/within.hpp>
+#include <boost/geometry/algorithms/detail/within/implementation.hpp>
namespace boost { namespace geometry
{
@@ -106,15 +106,8 @@ struct discard_closed_turns<overlay_union, operation_union>
Geometry0 const& geometry0, Geometry1 const& geometry1,
Strategy const& strategy)
{
- typedef typename boost::range_value<Turns>::type turn_type;
-
- for (typename boost::range_iterator<Turns>::type
- it = boost::begin(turns);
- it != boost::end(turns);
- ++it)
+ for (auto& turn : turns)
{
- turn_type& turn = *it;
-
if (! turn.discarded
&& is_self_turn<overlay_union>(turn)
&& check_within<overlay_union>::apply(turn, geometry0,
@@ -137,18 +130,16 @@ private :
bool is_self_cluster(signed_size_type cluster_id,
const Turns& turns, Clusters const& clusters)
{
- typename Clusters::const_iterator cit = clusters.find(cluster_id);
+ auto cit = clusters.find(cluster_id);
if (cit == clusters.end())
{
return false;
}
cluster_info const& cinfo = cit->second;
- for (std::set<signed_size_type>::const_iterator it
- = cinfo.turn_indices.begin();
- it != cinfo.turn_indices.end(); ++it)
+ for (auto index : cinfo.turn_indices)
{
- if (! is_self_turn<OverlayType>(turns[*it]))
+ if (! is_self_turn<OverlayType>(turns[index]))
{
return false;
}
@@ -164,28 +155,25 @@ private :
Geometry0 const& geometry0, Geometry1 const& geometry1,
Strategy const& strategy)
{
- for (typename Clusters::const_iterator cit = clusters.begin();
- cit != clusters.end(); ++cit)
+ for (auto const& pair : clusters)
{
- signed_size_type const cluster_id = cit->first;
+ signed_size_type const cluster_id = pair.first;
+ cluster_info const& cinfo = pair.second;
// If there are only self-turns in the cluster, the cluster should
// be located within the other geometry, for intersection
- if (! cit->second.turn_indices.empty()
+ if (! cinfo.turn_indices.empty()
&& is_self_cluster(cluster_id, turns, clusters))
{
- cluster_info const& cinfo = cit->second;
- signed_size_type const index = *cinfo.turn_indices.begin();
- if (! check_within<OverlayType>::apply(turns[index],
+ signed_size_type const first_index = *cinfo.turn_indices.begin();
+ if (! check_within<OverlayType>::apply(turns[first_index],
geometry0, geometry1,
strategy))
{
// Discard all turns in cluster
- for (std::set<signed_size_type>::const_iterator sit
- = cinfo.turn_indices.begin();
- sit != cinfo.turn_indices.end(); ++sit)
+ for (auto index : cinfo.turn_indices)
{
- turns[*sit].discarded = true;
+ turns[index].discarded = true;
}
}
}
@@ -203,15 +191,8 @@ public :
{
discard_clusters(turns, clusters, geometry0, geometry1, strategy);
- typedef typename boost::range_value<Turns>::type turn_type;
-
- for (typename boost::range_iterator<Turns>::type
- it = boost::begin(turns);
- it != boost::end(turns);
- ++it)
+ for (auto& turn : turns)
{
- turn_type& turn = *it;
-
// It is a ii self-turn
// Check if it is within the other geometry
if (! turn.discarded
diff --git a/boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp b/boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp
index c62b7d2834..31db94dd95 100644
--- a/boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp
+++ b/boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp
@@ -63,7 +63,7 @@ struct intersection_box_box
// Set dimensions of output coordinate
set<min_corner, Dimension>(box_out, min1 < min2 ? min2 : min1);
set<max_corner, Dimension>(box_out, max1 > max2 ? max2 : max1);
-
+
return intersection_box_box<Dimension + 1, DimensionCount>
::apply(box1, box2, robust_policy, box_out, strategy);
}
diff --git a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
index 153fb1cf4b..df3b70a456 100644
--- a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
+++ b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
@@ -2,9 +2,10 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014-2020.
-// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2021.
+// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -25,7 +26,6 @@
#include <boost/range/size.hpp>
#include <boost/geometry/algorithms/convert.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/detail/overlay/clip_linestring.hpp>
#include <boost/geometry/algorithms/detail/overlay/follow.hpp>
@@ -59,6 +59,7 @@
#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
+#include <boost/geometry/util/for_each_with_index.hpp>
#endif
namespace boost { namespace geometry
@@ -145,11 +146,10 @@ struct intersection_linestring_linestring_point
geometry::get_intersection_points(linestring1, linestring2,
robust_policy, turns, strategy);
- for (typename boost::range_iterator<std::deque<turn_info> const>::type
- it = boost::begin(turns); it != boost::end(turns); ++it)
+ for (auto const& turn : turns)
{
PointOut p;
- geometry::convert(it->point, p);
+ geometry::convert(turn.point, p);
*out++ = p;
}
return out;
@@ -212,11 +212,10 @@ struct intersection_of_linestring_with_areal
bool found_union = false;
bool found_front = false;
- for (typename Turns::const_iterator it = turns.begin();
- it != turns.end(); ++it)
+ for (auto const& turn : turns)
{
- method_type const method = it->method;
- operation_type const op = it->operations[0].operation;
+ method_type const method = turn.method;
+ operation_type const op = turn.operations[0].operation;
if (method == method_crosses)
{
@@ -240,7 +239,7 @@ struct intersection_of_linestring_with_areal
return false;
}
- if (it->operations[0].position == position_front)
+ if (turn.operations[0].position == position_front)
{
found_front = true;
}
@@ -378,14 +377,12 @@ struct intersection_of_linestring_with_areal
return out;
}
-
+
#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
- int index = 0;
- for(typename std::deque<turn_info>::const_iterator
- it = turns.begin(); it != turns.end(); ++it)
+ for_each_with_index(turns, [](auto index, auto const& turn)
{
- debug_follow(*it, it->operations[0], index++);
- }
+ debug_follow(turn, turn.operations[0], index);
+ });
#endif
return follower::apply
@@ -402,10 +399,9 @@ template <typename Turns, typename OutputIterator>
inline OutputIterator intersection_output_turn_points(Turns const& turns,
OutputIterator out)
{
- for (typename Turns::const_iterator
- it = turns.begin(); it != turns.end(); ++it)
+ for (auto const& turn : turns)
{
- *out++ = it->point;
+ *out++ = turn.point;
}
return out;
@@ -1543,7 +1539,7 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1,
<
Geometry1, Geometry2
>::type strategy_type;
-
+
return intersection_insert<GeometryOut>(geometry1, geometry2, out,
strategy_type());
}
diff --git a/boost/geometry/algorithms/detail/overlay/is_self_turn.hpp b/boost/geometry/algorithms/detail/overlay/is_self_turn.hpp
index 448c04404f..1606c31e90 100644
--- a/boost/geometry/algorithms/detail/overlay/is_self_turn.hpp
+++ b/boost/geometry/algorithms/detail/overlay/is_self_turn.hpp
@@ -26,8 +26,7 @@ struct is_self_turn_check
template <typename Turn>
static inline bool apply(Turn const& turn)
{
- return turn.operations[0].seg_id.source_index
- == turn.operations[1].seg_id.source_index;
+ return turn.is_self();
}
};
diff --git a/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp b/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp
index 06ce0a7f0d..1ce97d261e 100644
--- a/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp
+++ b/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp
@@ -66,7 +66,7 @@ template
typename Indexed,
typename Geometry1, typename Geometry2,
typename RobustPolicy,
- typename SideStrategy,
+ typename Strategy,
bool Reverse1, bool Reverse2
>
struct less_by_segment_ratio
@@ -75,7 +75,7 @@ struct less_by_segment_ratio
, Geometry1 const& geometry1
, Geometry2 const& geometry2
, RobustPolicy const& robust_policy
- , SideStrategy const& strategy)
+ , Strategy const& strategy)
: m_turns(turns)
, m_geometry1(geometry1)
, m_geometry2(geometry2)
@@ -90,7 +90,7 @@ private :
Geometry1 const& m_geometry1;
Geometry2 const& m_geometry2;
RobustPolicy const& m_robust_policy;
- SideStrategy const& m_strategy;
+ Strategy const& m_strategy;
typedef typename geometry::point_type<Geometry1>::type point_type;
@@ -115,8 +115,9 @@ private :
*right.other_seg_id,
si, sj);
- int const side_rj_p = m_strategy.apply(pi, pj, rj);
- int const side_sj_p = m_strategy.apply(pi, pj, sj);
+ auto side_strategy = m_strategy.side();
+ int const side_rj_p = side_strategy.apply(pi, pj, rj);
+ int const side_sj_p = side_strategy.apply(pi, pj, sj);
// Put the one turning left (1; right == -1) as last
if (side_rj_p != side_sj_p)
@@ -124,8 +125,8 @@ private :
return side_rj_p < side_sj_p;
}
- int const side_sj_r = m_strategy.apply(ri, rj, sj);
- int const side_rj_s = m_strategy.apply(si, sj, rj);
+ int const side_sj_r = side_strategy.apply(ri, rj, sj);
+ int const side_rj_s = side_strategy.apply(si, sj, rj);
// If they both turn left: the most left as last
// If they both turn right: this is not relevant, but take also here most left
@@ -156,10 +157,8 @@ public :
return left.subject->fraction < right.subject->fraction;
}
-
- typedef typename boost::range_value<Turns>::type turn_type;
- turn_type const& left_turn = m_turns[left.turn_index];
- turn_type const& right_turn = m_turns[right.turn_index];
+ auto const& left_turn = m_turns[left.turn_index];
+ auto const& right_turn = m_turns[right.turn_index];
// First check "real" intersection (crosses)
// -> distance zero due to precision, solve it by sorting
diff --git a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
index f5d5f7bf4d..f67a06b0bb 100644
--- a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -30,7 +30,7 @@
#include <boost/geometry/algorithms/convert.hpp>
-
+#include <boost/geometry/geometries/helper_geometry.hpp>
namespace boost { namespace geometry
{
@@ -82,9 +82,7 @@ struct linear_linear_no_intersections
static inline OutputIterator apply(MultiLineString const& multilinestring,
OutputIterator oit)
{
- for (typename boost::range_iterator<MultiLineString const>::type
- it = boost::begin(multilinestring);
- it != boost::end(multilinestring); ++it)
+ for (auto it = boost::begin(multilinestring); it != boost::end(multilinestring); ++it)
{
LineStringOut ls_out;
geometry::convert(*it, ls_out);
@@ -206,7 +204,7 @@ protected:
turns::remove_duplicate_turns
<
Turns, EnableRemoveDuplicateTurns
- >::apply(turns);
+ >::apply(turns, strategy);
return detail::overlay::following::linear::follow
<
diff --git a/boost/geometry/algorithms/detail/overlay/overlay.hpp b/boost/geometry/algorithms/detail/overlay/overlay.hpp
index 7d960987d4..e0451f9dd6 100644
--- a/boost/geometry/algorithms/detail/overlay/overlay.hpp
+++ b/boost/geometry/algorithms/detail/overlay/overlay.hpp
@@ -103,10 +103,6 @@ template
>
inline void get_ring_turn_info(TurnInfoMap& turn_info_map, Turns const& turns, Clusters const& clusters)
{
- typedef typename boost::range_value<Turns>::type turn_type;
- typedef typename turn_type::turn_operation_type turn_operation_type;
- typedef typename turn_type::container_type container_type;
-
static const operation_type target_operation
= operation_from_overlay<OverlayType>::value;
static const operation_type opposite_operation
@@ -114,13 +110,8 @@ inline void get_ring_turn_info(TurnInfoMap& turn_info_map, Turns const& turns, C
? operation_intersection
: operation_union;
- for (typename boost::range_iterator<Turns const>::type
- it = boost::begin(turns);
- it != boost::end(turns);
- ++it)
+ for (auto const& turn : turns)
{
- turn_type const& turn = *it;
-
bool cluster_checked = false;
bool has_blocked = false;
@@ -130,12 +121,8 @@ inline void get_ring_turn_info(TurnInfoMap& turn_info_map, Turns const& turns, C
continue;
}
- for (typename boost::range_iterator<container_type const>::type
- op_it = boost::begin(turn.operations);
- op_it != boost::end(turn.operations);
- ++op_it)
+ for (auto const& op : turn.operations)
{
- turn_operation_type const& op = *op_it;
ring_identifier const ring_id = ring_id_by_seg_id(op.seg_id);
if (! is_self_turn<OverlayType>(turn)
@@ -369,12 +356,9 @@ std::cout << "traverse" << std::endl;
// Add rings created during traversal
{
ring_identifier id(2, 0, -1);
- for (typename boost::range_iterator<ring_container_type>::type
- it = boost::begin(rings);
- it != boost::end(rings);
- ++it)
+ for (auto const& ring : rings)
{
- selected_ring_properties[id] = properties(*it, strategy);
+ selected_ring_properties[id] = properties(ring, strategy);
selected_ring_properties[id].reversed = ReverseOut;
id.multi_index++;
}
@@ -392,15 +376,18 @@ std::cout << "traverse" << std::endl;
// it can be returned or an exception can be thrown.
return add_rings<GeometryOut>(selected_ring_properties, geometry1, geometry2, rings, out,
strategy,
- OverlayType == overlay_union ?
#if defined(BOOST_GEOMETRY_UNION_THROW_INVALID_OUTPUT_EXCEPTION)
+ OverlayType == overlay_union ?
add_rings_throw_if_reversed
+ : add_rings_ignore_unordered
#elif defined(BOOST_GEOMETRY_UNION_RETURN_INVALID)
+ OverlayType == overlay_union ?
add_rings_add_unordered
+ : add_rings_ignore_unordered
#else
add_rings_ignore_unordered
#endif
- : add_rings_ignore_unordered);
+ );
}
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
diff --git a/boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp b/boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp
index 8b62b0752b..503d656478 100644
--- a/boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp
+++ b/boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp
@@ -157,7 +157,7 @@ private:
private:
MultiPolygon const& m_multipolygon;
- OutputIterator& m_oit;
+ OutputIterator& m_oit;
Strategy const& m_strategy;
};
diff --git a/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp b/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
index bbf62b3633..19045b250a 100644
--- a/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
@@ -98,10 +98,7 @@ struct multipoint_single_point
OutputIterator oit,
Strategy const& strategy)
{
- for (typename boost::range_iterator<MultiPoint const>::type
- it = boost::begin(multipoint);
- it != boost::end(multipoint);
- ++it)
+ for (auto it = boost::begin(multipoint); it != boost::end(multipoint); ++it)
{
action_selector_pl
<
diff --git a/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp b/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp
index a46fc8b5f7..4ad311277a 100644
--- a/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp
+++ b/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp
@@ -1,7 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -33,6 +36,8 @@
#include <boost/geometry/policies/compare.hpp>
+#include <boost/geometry/util/condition.hpp>
+
namespace boost { namespace geometry
{
@@ -75,9 +80,7 @@ struct copy_points<PointOut, MultiPointIn, multi_point_tag>
static inline void apply(MultiPointIn const& multi_point_in,
OutputIterator& oit)
{
- for (typename boost::range_iterator<MultiPointIn const>::type
- it = boost::begin(multi_point_in);
- it != boost::end(multi_point_in); ++it)
+ for (auto it = boost::begin(multi_point_in); it != boost::end(multi_point_in); ++it)
{
PointOut point_out;
geometry::convert(*it, point_out);
@@ -189,9 +192,7 @@ struct multipoint_point_point
{
BOOST_GEOMETRY_ASSERT( OverlayType == overlay_difference );
- for (typename boost::range_iterator<MultiPoint const>::type
- it = boost::begin(multipoint);
- it != boost::end(multipoint); ++it)
+ for (auto it = boost::begin(multipoint); it != boost::end(multipoint); ++it)
{
action_selector_pl
<
@@ -225,9 +226,7 @@ struct point_multipoint_point
{
typedef action_selector_pl<PointOut, OverlayType> action;
- for (typename boost::range_iterator<MultiPoint const>::type
- it = boost::begin(multipoint);
- it != boost::end(multipoint); ++it)
+ for (auto it = boost::begin(multipoint); it != boost::end(multipoint); ++it)
{
if ( detail::equals::equals_point_point(*it, point, strategy) )
{
@@ -260,10 +259,10 @@ struct multipoint_multipoint_point
OutputIterator oit,
Strategy const& strategy)
{
- typedef geometry::less<void, -1, typename Strategy::cs_tag> less_type;
+ typedef geometry::less<void, -1, Strategy> less_type;
- if ( OverlayType != overlay_difference
- && boost::size(multipoint1) > boost::size(multipoint2) )
+ if (BOOST_GEOMETRY_CONDITION(OverlayType != overlay_difference)
+ && boost::size(multipoint1) > boost::size(multipoint2))
{
return multipoint_multipoint_point
<
@@ -279,9 +278,7 @@ struct multipoint_multipoint_point
less_type const less = less_type();
std::sort(points2.begin(), points2.end(), less);
- for (typename boost::range_iterator<MultiPoint1 const>::type
- it1 = boost::begin(multipoint1);
- it1 != boost::end(multipoint1); ++it1)
+ for (auto it1 = boost::begin(multipoint1); it1 != boost::end(multipoint1); ++it1)
{
bool found = std::binary_search(points2.begin(), points2.end(),
*it1, less);
diff --git a/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp b/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp
index 6f49f5168d..e41ee8238c 100644
--- a/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp
+++ b/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2017-2020 Oracle and/or its affiliates.
+// Copyright (c) 2017-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -12,7 +12,7 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RANGE_IN_GEOMETRY_HPP
-#include <boost/geometry/algorithms/covered_by.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/iterators/point_iterator.hpp>
@@ -154,7 +154,7 @@ inline int range_in_geometry(Point1 const& first_point1,
// check points of geometry1 until point inside/outside is found
// NOTE: skip first point because it should be already tested above
result = range_in_geometry(geometry1, geometry2, strategy, true);
- }
+ }
return result;
}
diff --git a/boost/geometry/algorithms/detail/overlay/ring_properties.hpp b/boost/geometry/algorithms/detail/overlay/ring_properties.hpp
index c5341832bc..4039891f74 100644
--- a/boost/geometry/algorithms/detail/overlay/ring_properties.hpp
+++ b/boost/geometry/algorithms/detail/overlay/ring_properties.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2017.
-// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2022.
+// Modifications copyright (c) 2017-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,8 +15,8 @@
#include <boost/geometry/algorithms/area.hpp>
-#include <boost/geometry/algorithms/within.hpp>
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
+#include <boost/geometry/algorithms/detail/within/implementation.hpp>
namespace boost { namespace geometry
diff --git a/boost/geometry/algorithms/detail/overlay/select_rings.hpp b/boost/geometry/algorithms/detail/overlay/select_rings.hpp
index 1f43133367..58371606e2 100644
--- a/boost/geometry/algorithms/detail/overlay/select_rings.hpp
+++ b/boost/geometry/algorithms/detail/overlay/select_rings.hpp
@@ -3,8 +3,8 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017-2021.
-// Modifications copyright (c) 2017-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2022.
+// Modifications copyright (c) 2017-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -23,12 +23,11 @@
#include <boost/geometry/core/tags.hpp>
-#include <boost/geometry/algorithms/covered_by.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
-#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
#include <boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp>
#include <boost/geometry/algorithms/detail/overlay/ring_properties.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
namespace boost { namespace geometry
@@ -119,10 +118,8 @@ namespace dispatch
per_ring::apply(exterior_ring(polygon), geometry, id, ring_properties, strategy);
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(polygon);
- for (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ auto const& rings = interior_rings(polygon);
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
id.ring_index++;
per_ring::apply(*it, geometry, id, ring_properties, strategy);
@@ -139,10 +136,8 @@ namespace dispatch
per_ring::apply(exterior_ring(polygon), id, ring_properties, strategy);
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(polygon);
- for (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ auto const& rings = interior_rings(polygon);
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
id.ring_index++;
per_ring::apply(*it, id, ring_properties, strategy);
@@ -158,15 +153,10 @@ namespace dispatch
ring_identifier id, RingPropertyMap& ring_properties,
Strategy const& strategy)
{
- typedef typename boost::range_iterator
- <
- Multi const
- >::type iterator_type;
-
typedef select_rings<polygon_tag, typename boost::range_value<Multi>::type> per_polygon;
id.multi_index = 0;
- for (iterator_type it = boost::begin(multi); it != boost::end(multi); ++it)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
id.ring_index = -1;
per_polygon::apply(*it, geometry, id, ring_properties, strategy);
@@ -254,15 +244,13 @@ inline void update_ring_selection(Geometry1 const& geometry1,
{
selected_ring_properties.clear();
- for (typename RingPropertyMap::const_iterator it = boost::begin(all_ring_properties);
- it != boost::end(all_ring_properties);
- ++it)
+ for (auto const& pair : all_ring_properties)
{
- ring_identifier const& id = it->first;
+ ring_identifier const& id = pair.first;
ring_turn_info info;
- typename TurnInfoMap::const_iterator tcit = turn_info_map.find(id);
+ auto tcit = turn_info_map.find(id);
if (tcit != turn_info_map.end())
{
info = tcit->second; // Copy by value
@@ -281,12 +269,12 @@ inline void update_ring_selection(Geometry1 const& geometry1,
{
// within
case 0 :
- info.within_other = range_in_geometry(it->second.point,
+ info.within_other = range_in_geometry(pair.second.point,
geometry1, geometry2,
strategy) > 0;
break;
case 1 :
- info.within_other = range_in_geometry(it->second.point,
+ info.within_other = range_in_geometry(pair.second.point,
geometry2, geometry1,
strategy) > 0;
break;
@@ -294,7 +282,7 @@ inline void update_ring_selection(Geometry1 const& geometry1,
if (decide<OverlayType>::include(id, info))
{
- typename RingPropertyMap::mapped_type properties = it->second; // Copy by value
+ auto properties = pair.second; // Copy by value
properties.reversed = decide<OverlayType>::reversed(id, info);
selected_ring_properties[id] = properties;
}
@@ -321,7 +309,7 @@ inline void select_rings(Geometry1 const& geometry1, Geometry2 const& geometry2,
{
typedef typename geometry::tag<Geometry1>::type tag1;
typedef typename geometry::tag<Geometry2>::type tag2;
-
+
RingPropertyMap all_ring_properties;
dispatch::select_rings<tag1, Geometry1>::apply(geometry1, geometry2,
ring_identifier(0, -1, -1), all_ring_properties,
diff --git a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
index 0845390a90..20369fa95a 100644
--- a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
+++ b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
@@ -3,9 +3,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 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-2021.
+// Modifications copyright (c) 2017-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -33,6 +32,9 @@
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/strategies/detail.hpp>
+#include <boost/geometry/strategies/relate/services.hpp>
+
#include <boost/geometry/util/condition.hpp>
@@ -271,24 +273,103 @@ struct self_get_turn_points
#endif // DOXYGEN_NO_DISPATCH
+namespace resolve_strategy
+{
+
+template
+<
+ bool Reverse,
+ typename AssignPolicy,
+ typename Strategies,
+ bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
+>
+struct self_get_turn_points
+{
+ template
+ <
+ typename Geometry,
+ typename RobustPolicy,
+ typename Turns,
+ typename InterruptPolicy
+ >
+ static inline void apply(Geometry const& geometry,
+ Strategies const& strategies,
+ RobustPolicy const& robust_policy,
+ Turns& turns,
+ InterruptPolicy& interrupt_policy,
+ int source_index,
+ bool skip_adjacent)
+ {
+ using turn_policy = detail::overlay::get_turn_info<AssignPolicy>;
+
+ dispatch::self_get_turn_points
+ <
+ Reverse,
+ typename tag<Geometry>::type,
+ Geometry,
+ turn_policy
+ >::apply(geometry, strategies, robust_policy, turns, interrupt_policy,
+ source_index, skip_adjacent);
+ }
+};
+
+template <bool Reverse, typename AssignPolicy, typename Strategy>
+struct self_get_turn_points<Reverse, AssignPolicy, Strategy, false>
+{
+ template
+ <
+ typename Geometry,
+ typename RobustPolicy,
+ typename Turns,
+ typename InterruptPolicy
+ >
+ static inline void apply(Geometry const& geometry,
+ Strategy const& strategy,
+ RobustPolicy const& robust_policy,
+ Turns& turns,
+ InterruptPolicy& interrupt_policy,
+ int source_index,
+ bool skip_adjacent)
+ {
+ using strategies::relate::services::strategy_converter;
+
+ self_get_turn_points
+ <
+ Reverse,
+ AssignPolicy,
+ decltype(strategy_converter<Strategy>::get(strategy))
+ >::apply(geometry,
+ strategy_converter<Strategy>::get(strategy),
+ robust_policy,
+ turns,
+ interrupt_policy,
+ source_index,
+ skip_adjacent);
+ }
+};
+
+
+} // namespace resolve_strategy
+
+
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace self_get_turn_points
{
-// Version where Reverse can be specified manually. TODO:
+// Version where Reverse can be specified manually. TODO:
// can most probably be merged with self_get_turn_points::get_turn
template
<
bool Reverse,
typename AssignPolicy,
typename Geometry,
- typename IntersectionStrategy,
+ typename Strategy,
typename RobustPolicy,
typename Turns,
typename InterruptPolicy
>
inline void self_turns(Geometry const& geometry,
- IntersectionStrategy const& strategy,
+ Strategy const& strategy,
RobustPolicy const& robust_policy,
Turns& turns,
InterruptPolicy& interrupt_policy,
@@ -297,14 +378,9 @@ inline void self_turns(Geometry const& geometry,
{
concepts::check<Geometry const>();
- typedef detail::overlay::get_turn_info<detail::overlay::assign_null_policy> turn_policy;
-
- dispatch::self_get_turn_points
+ resolve_strategy::self_get_turn_points
<
- Reverse,
- typename tag<Geometry>::type,
- Geometry,
- turn_policy
+ Reverse, AssignPolicy, Strategy
>::apply(geometry, strategy, robust_policy, turns, interrupt_policy,
source_index, skip_adjacent);
}
@@ -351,12 +427,11 @@ inline void self_turns(Geometry const& geometry,
geometry::point_order<Geometry>::value
>::value;
- detail::self_get_turn_points::self_turns
+ resolve_strategy::self_get_turn_points
<
- reverse,
- AssignPolicy
- >(geometry, strategy, robust_policy, turns, interrupt_policy,
- source_index, skip_adjacent);
+ reverse, AssignPolicy, Strategy
+ >::apply(geometry, strategy, robust_policy, turns, interrupt_policy,
+ source_index, skip_adjacent);
}
diff --git a/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp b/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp
index 49e6761860..503b36720a 100644
--- a/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp
+++ b/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp
@@ -3,9 +3,10 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017, 2019.
-// Modifications copyright (c) 2017, 2019 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
// Use, modification and distribution is subject to the Boost Software License,
@@ -17,6 +18,7 @@
#include <algorithm>
#include <map>
+#include <set>
#include <vector>
#include <boost/geometry/algorithms/detail/overlay/approximately_equals.hpp>
@@ -127,10 +129,10 @@ struct less_false
}
};
-template <typename Point, typename SideStrategy, typename LessOnSame, typename Compare>
+template <typename PointOrigin, typename PointTurn, typename SideStrategy, typename LessOnSame, typename Compare>
struct less_by_side
{
- less_by_side(const Point& p1, const Point& p2, SideStrategy const& strategy)
+ less_by_side(const PointOrigin& p1, const PointTurn& p2, SideStrategy const& strategy)
: m_origin(p1)
, m_turn_point(p2)
, m_strategy(strategy)
@@ -209,8 +211,8 @@ struct less_by_side
}
private :
- Point const& m_origin;
- Point const& m_turn_point;
+ PointOrigin const& m_origin;
+ PointTurn const& m_turn_point;
SideStrategy const& m_strategy;
};
@@ -316,7 +318,15 @@ public :
// then take a point (or more) further back.
// The limit of offset avoids theoretical infinite loops.
// In practice it currently walks max 1 point back in all cases.
- double const tolerance = 1.0e9;
+ // Use the coordinate type, but if it is too small (e.g. std::int16), use a double
+ using ct_type = typename geometry::select_most_precise
+ <
+ typename geometry::coordinate_type<Point>::type,
+ double
+ >::type;
+
+ ct_type const tolerance = 1000000000;
+
int offset = 0;
while (approximately_equals(point_from, turn.point, tolerance)
&& offset > -10)
@@ -371,7 +381,8 @@ public :
}
}
- void apply(Point const& turn_point)
+ template <typename PointTurn>
+ void apply(PointTurn const& turn_point)
{
// We need three compare functors:
// 1) to order clockwise (union) or counter clockwise (intersection)
@@ -380,8 +391,8 @@ public :
// to give colinear points
// Sort by side and assign rank
- less_by_side<Point, SideStrategy, less_by_index, Compare> less_unique(m_origin, turn_point, m_strategy);
- less_by_side<Point, SideStrategy, less_false, Compare> less_non_unique(m_origin, turn_point, m_strategy);
+ less_by_side<Point, PointTurn, SideStrategy, less_by_index, Compare> less_unique(m_origin, turn_point, m_strategy);
+ less_by_side<Point, PointTurn, SideStrategy, less_false, Compare> less_non_unique(m_origin, turn_point, m_strategy);
std::sort(m_ranked_points.begin(), m_ranked_points.end(), less_unique);
@@ -467,7 +478,7 @@ public :
// Move iterator after rank==0
bool has_first = false;
- typename container_type::iterator it = m_ranked_points.begin() + 1;
+ auto it = m_ranked_points.begin() + 1;
for (; it != m_ranked_points.end() && it->rank == 0; ++it)
{
has_first = true;
@@ -478,8 +489,7 @@ public :
// Reverse first part (having rank == 0), if any,
// but skip the very first row
std::reverse(m_ranked_points.begin() + 1, it);
- for (typename container_type::iterator fit = m_ranked_points.begin();
- fit != it; ++fit)
+ for (auto fit = m_ranked_points.begin(); fit != it; ++fit)
{
BOOST_ASSERT(fit->rank == 0);
}
diff --git a/boost/geometry/algorithms/detail/overlay/traversal.hpp b/boost/geometry/algorithms/detail/overlay/traversal.hpp
index a0149789c6..22ae1a2de8 100644
--- a/boost/geometry/algorithms/detail/overlay/traversal.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traversal.hpp
@@ -123,12 +123,8 @@ public :
template <typename TurnInfoMap>
inline void finalize_visit_info(TurnInfoMap& turn_info_map)
{
- for (typename boost::range_iterator<Turns>::type
- it = boost::begin(m_turns);
- it != boost::end(m_turns);
- ++it)
+ for (auto& turn : m_turns)
{
- turn_type& turn = *it;
for (int i = 0; i < 2; i++)
{
turn_operation_type& op = turn.operations[i];
@@ -158,23 +154,18 @@ public :
inline void set_visited_in_cluster(signed_size_type cluster_id,
signed_size_type rank)
{
- typename Clusters::const_iterator mit = m_clusters.find(cluster_id);
+ auto mit = m_clusters.find(cluster_id);
BOOST_ASSERT(mit != m_clusters.end());
cluster_info const& cinfo = mit->second;
- std::set<signed_size_type> const& ids = cinfo.turn_indices;
- for (typename std::set<signed_size_type>::const_iterator it = ids.begin();
- it != ids.end(); ++it)
+ for (auto turn_index : cinfo.turn_indices)
{
- signed_size_type const turn_index = *it;
turn_type& turn = m_turns[turn_index];
- for (int i = 0; i < 2; i++)
+ for (auto& op : turn.operations)
{
- turn_operation_type& op = turn.operations[i];
- if (op.visited.none()
- && op.enriched.rank == rank)
+ if (op.visited.none() && op.enriched.rank == rank)
{
op.visited.set_visited();
}
@@ -621,31 +612,32 @@ public :
return m_turns[rp.turn_index].operations[rp.operation_index];
}
- inline sort_by_side::rank_type select_rank(sbs_type const& sbs,
- bool skip_isolated) const
+ inline sort_by_side::rank_type select_rank(sbs_type const& sbs) const
{
+ static bool const is_intersection
+ = target_operation == operation_intersection;
+
// Take the first outgoing rank corresponding to incoming region,
// or take another region if it is not isolated
- turn_operation_type const& incoming_op
- = operation_from_rank(sbs.m_ranked_points.front());
+ auto const& in_op = operation_from_rank(sbs.m_ranked_points.front());
for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
{
- typename sbs_type::rp const& rp = sbs.m_ranked_points[i];
+ auto const& rp = sbs.m_ranked_points[i];
if (rp.rank == 0 || rp.direction == sort_by_side::dir_from)
{
continue;
}
- turn_operation_type const& op = operation_from_rank(rp);
+ auto const& out_op = operation_from_rank(rp);
- if (op.operation != target_operation
- && op.operation != operation_continue)
+ if (out_op.operation != target_operation
+ && out_op.operation != operation_continue)
{
continue;
}
- if (op.enriched.region_id == incoming_op.enriched.region_id
- || (skip_isolated && ! op.enriched.isolated))
+ if (in_op.enriched.region_id == out_op.enriched.region_id
+ || (is_intersection && ! out_op.enriched.isolated))
{
// Region corresponds to incoming region, or (for intersection)
// there is a non-isolated other region which should be taken
@@ -660,7 +652,7 @@ public :
int& op_index, sbs_type const& sbs,
signed_size_type start_turn_index, int start_op_index) const
{
- sort_by_side::rank_type const selected_rank = select_rank(sbs, false);
+ sort_by_side::rank_type const selected_rank = select_rank(sbs);
int current_priority = 0;
for (std::size_t i = 1; i < sbs.m_ranked_points.size(); i++)
@@ -688,49 +680,59 @@ public :
inline bool analyze_cluster_intersection(signed_size_type& turn_index,
int& op_index, sbs_type const& sbs) const
{
- sort_by_side::rank_type const selected_rank = select_rank(sbs, true);
+ // Select the rank based on regions and isolation
+ sort_by_side::rank_type const selected_rank = select_rank(sbs);
- if (selected_rank > 0)
+ if (selected_rank <= 0)
{
- typename turn_operation_type::comparable_distance_type
- min_remaining_distance = 0;
+ return false;
+ }
- std::size_t selected_index = sbs.m_ranked_points.size();
- for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
+ // From these ranks, select the index: the first, or the one with
+ // the smallest remaining distance
+ typename turn_operation_type::comparable_distance_type
+ min_remaining_distance = 0;
+
+ std::size_t selected_index = sbs.m_ranked_points.size();
+ for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
+ {
+ auto const& ranked_point = sbs.m_ranked_points[i];
+
+ if (ranked_point.rank > selected_rank)
{
- typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[i];
+ break;
+ }
+ else if (ranked_point.rank == selected_rank)
+ {
+ auto const& op = operation_from_rank(ranked_point);
- if (ranked_point.rank == selected_rank)
+ if (op.visited.finalized())
{
- turn_operation_type const& op = operation_from_rank(ranked_point);
-
- if (op.visited.finalized())
- {
- // This direction is already traveled before, the same
- // cannot be traveled again
- continue;
- }
-
- // Take turn with the smallest remaining distance
- if (selected_index == sbs.m_ranked_points.size()
- || op.remaining_distance < min_remaining_distance)
- {
- selected_index = i;
- min_remaining_distance = op.remaining_distance;
- }
+ // This direction is already traveled,
+ // it cannot be traveled again
+ continue;
}
- }
- if (selected_index < sbs.m_ranked_points.size())
- {
- typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[selected_index];
- turn_index = ranked_point.turn_index;
- op_index = ranked_point.operation_index;
- return true;
+ if (selected_index == sbs.m_ranked_points.size()
+ || op.remaining_distance < min_remaining_distance)
+ {
+ // It was unassigned or it is better
+ selected_index = i;
+ min_remaining_distance = op.remaining_distance;
+ }
}
}
- return false;
+ if (selected_index == sbs.m_ranked_points.size())
+ {
+ // Should not happen, there must be points with the selected rank
+ return false;
+ }
+
+ auto const& ranked_point = sbs.m_ranked_points[selected_index];
+ turn_index = ranked_point.turn_index;
+ op_index = ranked_point.operation_index;
+ return true;
}
inline bool fill_sbs(sbs_type& sbs,
@@ -778,21 +780,19 @@ public :
turn_type const& turn = m_turns[turn_index];
BOOST_ASSERT(turn.is_clustered());
- typename Clusters::const_iterator mit = m_clusters.find(turn.cluster_id);
+ auto mit = m_clusters.find(turn.cluster_id);
BOOST_ASSERT(mit != m_clusters.end());
cluster_info const& cinfo = mit->second;
- std::set<signed_size_type> const& cluster_indices = cinfo.turn_indices;
sbs_type sbs(m_strategy);
-
- if (! fill_sbs(sbs, turn_index, cluster_indices, previous_seg_id))
+ if (! fill_sbs(sbs, turn_index, cinfo.turn_indices, previous_seg_id))
{
return false;
}
- cluster_exits<OverlayType, Turns, sbs_type> exits(m_turns, cluster_indices, sbs);
+ cluster_exits<OverlayType, Turns, sbs_type> exits(m_turns, cinfo.turn_indices, sbs);
if (exits.apply(turn_index, op_index))
{
@@ -803,7 +803,7 @@ public :
if (is_union)
{
- result = select_from_cluster_union(turn_index, cluster_indices,
+ result = select_from_cluster_union(turn_index, cinfo.turn_indices,
op_index, sbs,
start_turn_index, start_op_index);
if (! result)
@@ -819,6 +819,7 @@ public :
return result;
}
+ // Analyzes a non-clustered "ii" intersection, as if it is clustered.
inline bool analyze_ii_intersection(signed_size_type& turn_index, int& op_index,
turn_type const& current_turn,
segment_identifier const& previous_seg_id)
@@ -956,31 +957,43 @@ public :
{
turn_type const& current_turn = m_turns[turn_index];
+ bool const back_at_start_cluster
+ = has_points
+ && current_turn.is_clustered()
+ && m_turns[start_turn_index].cluster_id == current_turn.cluster_id;
if (BOOST_GEOMETRY_CONDITION(target_operation == operation_intersection))
{
- if (has_points)
- {
- bool const back_at_start_cluster
- = current_turn.is_clustered()
- && m_turns[start_turn_index].cluster_id == current_turn.cluster_id;
+ // Intersection or difference
- if (turn_index == start_turn_index || back_at_start_cluster)
- {
- // Intersection can always be finished if returning
- turn_index = start_turn_index;
- op_index = start_op_index;
- return true;
- }
+ if (has_points && (turn_index == start_turn_index || back_at_start_cluster))
+ {
+ // Intersection can always be finished if returning
+ turn_index = start_turn_index;
+ op_index = start_op_index;
+ return true;
}
if (! current_turn.is_clustered()
- && current_turn.both(operation_intersection))
- {
- if (analyze_ii_intersection(turn_index, op_index,
+ && current_turn.both(operation_intersection)
+ && analyze_ii_intersection(turn_index, op_index,
current_turn, previous_seg_id))
- {
- return true;
- }
+ {
+ return true;
+ }
+ }
+ else if (turn_index == start_turn_index || back_at_start_cluster)
+ {
+ // Union or buffer: cannot return immediately to starting turn, because it then
+ // might miss a formed multi polygon with a touching point.
+ auto const& current_op = current_turn.operations[op_index];
+ signed_size_type const next_turn_index = current_op.enriched.get_next_turn_index();
+ bool const to_other_turn = next_turn_index >= 0 && m_turns[next_turn_index].cluster_id != current_turn.cluster_id;
+ if (! to_other_turn)
+ {
+ // Return to starting point
+ turn_index = start_turn_index;
+ op_index = start_op_index;
+ return true;
}
}
diff --git a/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp b/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp
index ad248826dd..be0f2bcd87 100644
--- a/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp
@@ -89,7 +89,6 @@ struct traversal_switch_detector
enum isolation_type
{
- isolation_unknown = -1,
isolation_no = 0,
isolation_yes = 1,
isolation_multiple = 2
@@ -121,7 +120,7 @@ struct traversal_switch_detector
struct region_properties
{
signed_size_type region_id = -1;
- isolation_type isolated = isolation_unknown;
+ isolation_type isolated = isolation_no;
set_type unique_turn_ids;
connection_map connected_region_counts;
};
@@ -374,7 +373,7 @@ struct traversal_switch_detector
{
region_properties& properties = key_val.second;
- if (properties.isolated == isolation_unknown
+ if (properties.isolated == isolation_no
&& has_only_isolated_children(properties))
{
properties.isolated = isolation_yes;
@@ -388,13 +387,36 @@ struct traversal_switch_detector
{
for (turn_type& turn : m_turns)
{
+ // For difference, for the input walked through in reverse,
+ // the meaning is reversed: what is isolated is actually not,
+ // and vice versa.
+ bool const reverseMeaningInTurn
+ = (Reverse1 || Reverse2)
+ && ! turn.is_self()
+ && ! turn.is_clustered()
+ && uu_or_ii(turn)
+ && turn.operations[0].enriched.region_id
+ != turn.operations[1].enriched.region_id;
+
for (auto& op : turn.operations)
{
auto mit = m_connected_regions.find(op.enriched.region_id);
if (mit != m_connected_regions.end())
{
+ bool const reverseMeaningInOp
+ = reverseMeaningInTurn
+ && ((op.seg_id.source_index == 0 && Reverse1)
+ || (op.seg_id.source_index == 1 && Reverse2));
+
+ // It is assigned to isolated if it's property is "Yes",
+ // (one connected interior, or chained).
+ // "Multiple" doesn't count for isolation,
+ // neither for intersection, neither for difference.
region_properties const& prop = mit->second;
- op.enriched.isolated = prop.isolated == isolation_yes;
+ op.enriched.isolated
+ = reverseMeaningInOp
+ ? false
+ : prop.isolated == isolation_yes;
}
}
}
@@ -478,8 +500,12 @@ struct traversal_switch_detector
// Discarded turns don't connect rings to the same region
// Also xx are not relevant
// (otherwise discarded colocated uu turn could make a connection)
- return ! turn.discarded
- && ! turn.both(operation_blocked);
+ return ! turn.discarded && ! turn.both(operation_blocked);
+ }
+
+ inline bool uu_or_ii(turn_type const& turn) const
+ {
+ return turn.both(operation_union) || turn.both(operation_intersection);
}
inline bool connects_same_region(turn_type const& turn) const
@@ -492,7 +518,7 @@ struct traversal_switch_detector
if (! turn.is_clustered())
{
// If it is a uu/ii-turn (non clustered), it is never same region
- return ! (turn.both(operation_union) || turn.both(operation_intersection));
+ return ! uu_or_ii(turn);
}
if (BOOST_GEOMETRY_CONDITION(target_operation == operation_union))
@@ -565,10 +591,83 @@ struct traversal_switch_detector
}
}
+#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)
+ void debug_show_results()
+ {
+ auto isolation_to_string = [](isolation_type const& iso) -> std::string
+ {
+ switch(iso)
+ {
+ case isolation_no : return "no";
+ case isolation_yes : return "yes";
+ case isolation_multiple : return "multiple";
+ }
+ return "error";
+ };
+ auto set_to_string = [](auto const& s) -> std::string
+ {
+ std::ostringstream result;
+ for (auto item : s) { result << " " << item; }
+ return result.str();
+ };
+
+ for (auto const& kv : m_connected_regions)
+ {
+ auto const& prop = kv.second;
+
+ std::ostringstream sub;
+ sub << "[turns" << set_to_string(prop.unique_turn_ids)
+ << "] regions";
+ for (auto const& kvs : prop.connected_region_counts)
+ {
+ sub << " { " << kvs.first
+ << " : via [" << set_to_string(kvs.second.unique_turn_ids)
+ << " ] }";
+ }
+
+ std::cout << "REGION " << prop.region_id
+ << " " << isolation_to_string(prop.isolated)
+ << " " << sub.str()
+ << std::endl;
+ }
+
+ for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index)
+ {
+ turn_type const& turn = m_turns[turn_index];
+
+ if (uu_or_ii(turn) && ! turn.is_clustered())
+ {
+ std::cout << (turn.both(operation_union) ? "UU" : "II")
+ << " " << turn_index
+ << " (" << geometry::get<0>(turn.point)
+ << ", " << geometry::get<1>(turn.point) << ")"
+ << " -> " << std::boolalpha
+ << " [" << turn.operations[0].seg_id.source_index
+ << "/" << turn.operations[1].seg_id.source_index << "] "
+ << "(" << turn.operations[0].enriched.region_id
+ << " " << turn.operations[0].enriched.isolated
+ << ") / (" << turn.operations[1].enriched.region_id
+ << " " << turn.operations[1].enriched.isolated << ")"
+ << std::endl;
+ }
+ }
+
+ for (auto const& key_val : m_clusters)
+ {
+ cluster_info const& cinfo = key_val.second;
+ std::cout << "CL RESULT " << key_val.first
+ << " -> " << cinfo.open_count << std::endl;
+ }
+ }
+#endif
+
void iterate()
{
#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)
- std::cout << "BEGIN SWITCH DETECTOR (region_ids and isolation)" << std::endl;
+ std::cout << "BEGIN SWITCH DETECTOR (region_ids and isolation)"
+ << (Reverse1 ? " REVERSE_1" : "")
+ << (Reverse2 ? " REVERSE_2" : "")
+ << std::endl;
#endif
// Collect turns per ring
@@ -608,33 +707,7 @@ struct traversal_switch_detector
#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)
std::cout << "END SWITCH DETECTOR" << std::endl;
-
- for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index)
- {
- turn_type const& turn = m_turns[turn_index];
-
- if ((turn.both(operation_union) || turn.both(operation_intersection))
- && ! turn.is_clustered())
- {
- std::cout << (turn.both(operation_union) ? "UU" : "II")
- << " " << turn_index
- << " (" << geometry::get<0>(turn.point)
- << ", " << geometry::get<1>(turn.point) << ")"
- << " -> " << std::boolalpha
- << "(" << turn.operations[0].enriched.region_id
- << " " << turn.operations[0].enriched.isolated
- << ") / (" << turn.operations[1].enriched.region_id
- << " " << turn.operations[1].enriched.isolated << ")"
- << std::endl;
- }
- }
-
- for (auto const& key_val : m_clusters)
- {
- cluster_info const& cinfo = key_val.second;
- std::cout << "CL RESULT " << key_val.first
- << " -> " << cinfo.open_count << std::endl;
- }
+ debug_show_results();
#endif
}
diff --git a/boost/geometry/algorithms/detail/overlay/traverse.hpp b/boost/geometry/algorithms/detail/overlay/traverse.hpp
index b9cbea3127..710cea09e9 100644
--- a/boost/geometry/algorithms/detail/overlay/traverse.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traverse.hpp
@@ -42,14 +42,11 @@ class traverse
template <typename Turns>
static void reset_visits(Turns& turns)
{
- for (typename boost::range_iterator<Turns>::type
- it = boost::begin(turns);
- it != boost::end(turns);
- ++it)
+ for (auto& turn : turns)
{
- for (int i = 0; i < 2; i++)
+ for (auto& op : turn.operations)
{
- it->operations[i].visited.reset();
+ op.visited.reset();
}
}
}
diff --git a/boost/geometry/algorithms/detail/overlay/turn_info.hpp b/boost/geometry/algorithms/detail/overlay/turn_info.hpp
index 7dcbf4c8ef..8f1d22c8c0 100644
--- a/boost/geometry/algorithms/detail/overlay/turn_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/turn_info.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -10,7 +11,7 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TURN_INFO_HPP
-#include <boost/array.hpp>
+#include <array>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
@@ -80,7 +81,7 @@ template
typename Point,
typename SegmentRatio = geometry::segment_ratio<typename coordinate_type<Point>::type>,
typename Operation = turn_operation<Point, SegmentRatio>,
- typename Container = boost::array<Operation, 2>
+ typename Container = std::array<Operation, 2>
>
struct turn_info
{
@@ -138,6 +139,11 @@ struct turn_info
{
return cluster_id > 0;
}
+ inline bool is_self() const
+ {
+ return operations[0].seg_id.source_index
+ == operations[1].seg_id.source_index;
+ }
private :
inline bool has12(operation_type type1, operation_type type2) const
diff --git a/boost/geometry/algorithms/detail/partition.hpp b/boost/geometry/algorithms/detail/partition.hpp
index 2a47eb2b64..e3c4208e3e 100644
--- a/boost/geometry/algorithms/detail/partition.hpp
+++ b/boost/geometry/algorithms/detail/partition.hpp
@@ -52,20 +52,39 @@ struct divide_interval<T, true>
{
static inline T apply(T const& mi, T const& ma)
{
- // avoid overflow
+ // Avoid overflow
return mi / 2 + ma / 2 + (mi % 2 + ma % 2) / 2;
}
};
-template <int Dimension, typename Box>
+struct visit_no_policy
+{
+ template <typename Box>
+ static inline void apply(Box const&, std::size_t )
+ {}
+};
+
+struct include_all_policy
+{
+ template <typename Item>
+ static inline bool apply(Item const&)
+ {
+ return true;
+ }
+};
+
+
+template <std::size_t Dimension, typename Box>
inline void divide_box(Box const& box, Box& lower_box, Box& upper_box)
{
- typedef typename coordinate_type<Box>::type ctype;
+ using coor_t = typename coordinate_type<Box>::type;
- // Divide input box into two parts, e.g. left/right
- ctype mid = divide_interval<ctype>::apply(
- geometry::get<min_corner, Dimension>(box),
- geometry::get<max_corner, Dimension>(box));
+ // Divide input box into two halves
+ // either left/right (Dimension 0)
+ // or top/bottom (Dimension 1)
+ coor_t const mid
+ = divide_interval<coor_t>::apply(geometry::get<min_corner, Dimension>(box),
+ geometry::get<max_corner, Dimension>(box));
lower_box = box;
upper_box = box;
@@ -85,12 +104,7 @@ inline void divide_into_subsets(Box const& lower_box,
IteratorVector& exceeding,
OverlapsPolicy const& overlaps_policy)
{
- typedef typename boost::range_iterator
- <
- IteratorVector const
- >::type it_type;
-
- for(it_type it = boost::begin(input); it != boost::end(input); ++it)
+ for (auto it = boost::begin(input); it != boost::end(input); ++it)
{
bool const lower_overlapping = overlaps_policy.apply(lower_box, **it);
bool const upper_overlapping = overlaps_policy.apply(upper_box, **it);
@@ -124,10 +138,9 @@ template
inline void expand_with_elements(Box& total, IteratorVector const& input,
ExpandPolicy const& expand_policy)
{
- typedef typename boost::range_iterator<IteratorVector const>::type it_type;
- for(it_type it = boost::begin(input); it != boost::end(input); ++it)
+ for (auto const& it : input)
{
- expand_policy.apply(total, **it);
+ expand_policy.apply(total, *it);
}
}
@@ -141,17 +154,15 @@ inline bool handle_one(IteratorVector const& input, VisitPolicy& visitor)
return true;
}
- typedef typename boost::range_iterator<IteratorVector const>::type it_type;
-
// Quadratic behaviour at lowest level (lowest quad, or all exceeding)
- for (it_type it1 = boost::begin(input); it1 != boost::end(input); ++it1)
+ for (auto it1 = boost::begin(input); it1 != boost::end(input); ++it1)
{
- it_type it2 = it1;
+ auto it2 = it1;
for (++it2; it2 != boost::end(input); ++it2)
{
if (! visitor.apply(**it1, **it2))
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
}
@@ -170,32 +181,19 @@ inline bool handle_two(IteratorVector1 const& input1,
IteratorVector2 const& input2,
VisitPolicy& visitor)
{
- typedef typename boost::range_iterator
- <
- IteratorVector1 const
- >::type iterator_type1;
-
- typedef typename boost::range_iterator
- <
- IteratorVector2 const
- >::type iterator_type2;
if (boost::empty(input1) || boost::empty(input2))
{
return true;
}
- for(iterator_type1 it1 = boost::begin(input1);
- it1 != boost::end(input1);
- ++it1)
+ for (auto const& it1 : input1)
{
- for(iterator_type2 it2 = boost::begin(input2);
- it2 != boost::end(input2);
- ++it2)
+ for (auto const& it2 : input2)
{
- if (! visitor.apply(**it1, **it2))
+ if (! visitor.apply(*it1, *it2))
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
}
@@ -236,11 +234,11 @@ inline bool recurse_ok(IteratorVector1 const& input1,
}
-template <int Dimension, typename Box>
+template <std::size_t Dimension, typename Box>
class partition_two_ranges;
-template <int Dimension, typename Box>
+template <std::size_t Dimension, typename Box>
class partition_one_range
{
template <typename IteratorVector, typename ExpandPolicy>
@@ -349,10 +347,10 @@ public :
if (! boost::empty(exceeding))
{
// Get the box of exceeding-only
- Box exceeding_box = get_new_box(exceeding, expand_policy);
+ Box const exceeding_box = get_new_box(exceeding, expand_policy);
- // Recursively do exceeding elements only, in next dimension they
- // will probably be less exceeding within the new box
+ // Recursively do exceeding elements only, in next dimension they
+ // will probably be less exceeding within the new box
if (! (next_level(exceeding_box, exceeding, level, min_elements,
visitor, expand_policy, overlaps_policy, box_policy)
// Switch to two forward ranges, combine exceeding with
@@ -362,7 +360,7 @@ public :
&& next_level2(exceeding_box, exceeding, upper, level, min_elements,
visitor, expand_policy, overlaps_policy, box_policy)) )
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
@@ -376,7 +374,7 @@ public :
template
<
- int Dimension,
+ std::size_t Dimension,
typename Box
>
class partition_two_ranges
@@ -480,20 +478,20 @@ public :
if (recurse_ok(exceeding1, exceeding2, min_elements, level))
{
- Box exceeding_box = get_new_box(exceeding1, exceeding2,
- expand_policy1, expand_policy2);
+ Box const exceeding_box = get_new_box(exceeding1, exceeding2,
+ expand_policy1, expand_policy2);
if (! next_level(exceeding_box, exceeding1, exceeding2, level,
min_elements, visitor, expand_policy1, overlaps_policy1,
expand_policy2, overlaps_policy2, box_policy))
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
else
{
if (! handle_two(exceeding1, exceeding2, visitor))
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
@@ -503,7 +501,7 @@ public :
// the same combinations again and again)
if (recurse_ok(lower2, upper2, exceeding1, min_elements, level))
{
- Box exceeding_box = get_new_box(exceeding1, expand_policy1);
+ Box const exceeding_box = get_new_box(exceeding1, expand_policy1);
if (! (next_level(exceeding_box, exceeding1, lower2, level,
min_elements, visitor, expand_policy1, overlaps_policy1,
expand_policy2, overlaps_policy2, box_policy)
@@ -511,7 +509,7 @@ public :
min_elements, visitor, expand_policy1, overlaps_policy1,
expand_policy2, overlaps_policy2, box_policy)) )
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
else
@@ -519,7 +517,7 @@ public :
if (! (handle_two(exceeding1, lower2, visitor)
&& handle_two(exceeding1, upper2, visitor)) )
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
}
@@ -529,7 +527,7 @@ public :
// All exceeding from 2 with lower and upper of 1:
if (recurse_ok(lower1, upper1, exceeding2, min_elements, level))
{
- Box exceeding_box = get_new_box(exceeding2, expand_policy2);
+ Box const exceeding_box = get_new_box(exceeding2, expand_policy2);
if (! (next_level(exceeding_box, lower1, exceeding2, level,
min_elements, visitor, expand_policy1, overlaps_policy1,
expand_policy2, overlaps_policy2, box_policy)
@@ -537,7 +535,7 @@ public :
min_elements, visitor, expand_policy1, overlaps_policy1,
expand_policy2, overlaps_policy2, box_policy)) )
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
else
@@ -545,7 +543,7 @@ public :
if (! (handle_two(lower1, exceeding2, visitor)
&& handle_two(upper1, exceeding2, visitor)) )
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
}
@@ -556,14 +554,14 @@ public :
min_elements, visitor, expand_policy1, overlaps_policy1,
expand_policy2, overlaps_policy2, box_policy) )
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
else
{
if (! handle_two(lower1, lower2, visitor))
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
@@ -573,14 +571,14 @@ public :
min_elements, visitor, expand_policy1, overlaps_policy1,
expand_policy2, overlaps_policy2, box_policy) )
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
else
{
if (! handle_two(upper1, upper2, visitor))
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
@@ -588,22 +586,6 @@ public :
}
};
-struct visit_no_policy
-{
- template <typename Box>
- static inline void apply(Box const&, std::size_t )
- {}
-};
-
-struct include_all_policy
-{
- template <typename Item>
- static inline bool apply(Item const&)
- {
- return true;
- }
-};
-
}} // namespace detail::partition
@@ -629,10 +611,7 @@ class partition
IteratorVector& iterator_vector,
ExpandPolicy const& expand_policy)
{
- for(typename boost::range_iterator<ForwardRange const>::type
- it = boost::begin(forward_range);
- it != boost::end(forward_range);
- ++it)
+ for (auto it = boost::begin(forward_range); it != boost::end(forward_range); ++it)
{
if (IncludePolicy::apply(*it))
{
@@ -691,14 +670,14 @@ public:
std::size_t min_elements,
VisitBoxPolicy box_visitor)
{
- typedef typename boost::range_iterator
+ using iterator_t = typename boost::range_iterator
<
ForwardRange const
- >::type iterator_type;
+ >::type;
if (std::size_t(boost::size(forward_range)) > min_elements)
{
- std::vector<iterator_type> iterator_vector;
+ std::vector<iterator_t> iterator_vector;
Box total;
assign_inverse(total);
expand_to_range<IncludePolicy1>(forward_range, total,
@@ -712,16 +691,16 @@ public:
}
else
{
- for(iterator_type it1 = boost::begin(forward_range);
+ for (auto it1 = boost::begin(forward_range);
it1 != boost::end(forward_range);
++it1)
{
- iterator_type it2 = it1;
- for(++it2; it2 != boost::end(forward_range); ++it2)
+ auto it2 = it1;
+ for (++it2; it2 != boost::end(forward_range); ++it2)
{
if (! visitor.apply(*it1, *it2))
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
}
@@ -817,21 +796,21 @@ public:
std::size_t min_elements,
VisitBoxPolicy box_visitor)
{
- typedef typename boost::range_iterator
+ using iterator1_t = typename boost::range_iterator
<
ForwardRange1 const
- >::type iterator_type1;
+ >::type;
- typedef typename boost::range_iterator
+ using iterator2_t = typename boost::range_iterator
<
ForwardRange2 const
- >::type iterator_type2;
+ >::type;
if (std::size_t(boost::size(forward_range1)) > min_elements
&& std::size_t(boost::size(forward_range2)) > min_elements)
{
- std::vector<iterator_type1> iterator_vector1;
- std::vector<iterator_type2> iterator_vector2;
+ std::vector<iterator1_t> iterator_vector1;
+ std::vector<iterator2_t> iterator_vector2;
Box total;
assign_inverse(total);
expand_to_range<IncludePolicy1>(forward_range1, total,
@@ -849,17 +828,17 @@ public:
}
else
{
- for(iterator_type1 it1 = boost::begin(forward_range1);
+ for (auto it1 = boost::begin(forward_range1);
it1 != boost::end(forward_range1);
++it1)
{
- for(iterator_type2 it2 = boost::begin(forward_range2);
+ for (auto it2 = boost::begin(forward_range2);
it2 != boost::end(forward_range2);
++it2)
{
if (! visitor.apply(*it1, *it2))
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
}
diff --git a/boost/geometry/algorithms/detail/point_on_border.hpp b/boost/geometry/algorithms/detail/point_on_border.hpp
index 3969939b4e..8b3a20a16f 100644
--- a/boost/geometry/algorithms/detail/point_on_border.hpp
+++ b/boost/geometry/algorithms/detail/point_on_border.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// 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-2022.
+// Modifications copyright (c) 2017-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -25,17 +25,15 @@
#include <boost/range/end.hpp>
#include <boost/static_assert.hpp>
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/ring_type.hpp>
-
#include <boost/geometry/geometries/concepts/check.hpp>
-
-#include <boost/geometry/algorithms/assign.hpp>
-#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
-#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
-
#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/views/detail/indexed_point_view.hpp>
namespace boost { namespace geometry
@@ -49,10 +47,10 @@ namespace detail { namespace point_on_border
struct get_point
{
- template <typename Point>
- static inline bool apply(Point& destination, Point const& source)
+ template <typename Destination, typename Source>
+ static inline bool apply(Destination& destination, Source const& source)
{
- destination = source;
+ detail::conversion::convert_point_to_point(source, destination);
return true;
}
};
@@ -69,7 +67,7 @@ struct point_on_range
return false;
}
- geometry::detail::conversion::convert_point_to_point(*begin, point);
+ detail::conversion::convert_point_to_point(*begin, point);
return true;
}
@@ -92,12 +90,13 @@ struct point_on_polygon
};
-struct point_on_box
+struct point_on_segment_or_box
{
- template<typename Point, typename Box>
- static inline bool apply(Point& point, Box const& box)
+ template<typename Point, typename SegmentOrBox>
+ static inline bool apply(Point& point, SegmentOrBox const& segment_or_box)
{
- detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, point);
+ detail::indexed_point_view<SegmentOrBox const, 0> view(segment_or_box);
+ detail::conversion::convert_point_to_point(view, point);
return true;
}
};
@@ -111,12 +110,7 @@ struct point_on_multi
{
// Take a point on the first multi-geometry
// (i.e. the first that is not empty)
- for (typename boost::range_iterator
- <
- MultiGeometry const
- >::type it = boost::begin(multi);
- it != boost::end(multi);
- ++it)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
if (Policy::apply(point, *it))
{
@@ -147,6 +141,11 @@ struct point_on_border<point_tag>
{};
template <>
+struct point_on_border<segment_tag>
+ : detail::point_on_border::point_on_segment_or_box
+{};
+
+template <>
struct point_on_border<linestring_tag>
: detail::point_on_border::point_on_range
{};
@@ -163,11 +162,16 @@ struct point_on_border<polygon_tag>
template <>
struct point_on_border<box_tag>
- : detail::point_on_border::point_on_box
+ : detail::point_on_border::point_on_segment_or_box
{};
template <>
+struct point_on_border<multi_point_tag>
+ : detail::point_on_border::point_on_range
+{};
+
+template <>
struct point_on_border<multi_polygon_tag>
: detail::point_on_border::point_on_multi
<
@@ -189,6 +193,9 @@ struct point_on_border<multi_linestring_tag>
#endif // DOXYGEN_NO_DISPATCH
+// TODO: We should probably rename this utility because it can return point
+// which is in the interior of a geometry (for PointLike and LinearRings).
+
/*!
\brief Take point on a border
\ingroup overlay
diff --git a/boost/geometry/algorithms/detail/recalculate.hpp b/boost/geometry/algorithms/detail/recalculate.hpp
index 688d49237d..eb633c9c2f 100644
--- a/boost/geometry/algorithms/detail/recalculate.hpp
+++ b/boost/geometry/algorithms/detail/recalculate.hpp
@@ -106,13 +106,10 @@ struct range_to_range
typedef recalculate_point<geometry::dimension<point_type>::value> per_point;
geometry::clear(destination);
- for (typename boost::range_iterator<Range2 const>::type it
- = boost::begin(source);
- it != boost::end(source);
- ++it)
+ for (auto const& source_point : source)
{
point_type p;
- per_point::apply(p, *it, strategy);
+ per_point::apply(p, source_point, strategy);
geometry::append(destination, p);
}
}
diff --git a/boost/geometry/algorithms/detail/relate/areal_areal.hpp b/boost/geometry/algorithms/detail/relate/areal_areal.hpp
index 99df598da8..41366e3167 100644
--- a/boost/geometry/algorithms/detail/relate/areal_areal.hpp
+++ b/boost/geometry/algorithms/detail/relate/areal_areal.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018, 2019.
-// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -29,12 +29,14 @@
#include <boost/geometry/algorithms/detail/relate/boundary_checker.hpp>
#include <boost/geometry/algorithms/detail/relate/follow_helpers.hpp>
+#include <boost/geometry/geometries/helper_geometry.hpp>
+
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace relate {
-
+
// WARNING!
// TODO: In the worst case calling this Pred in a loop for MultiPolygon/MultiPolygon may take O(NM)
// Use the rtree in this case!
@@ -85,9 +87,9 @@ public:
return false;
}
- typedef typename geometry::point_type<Areal>::type point_type;
- point_type pt;
- bool const ok = boost::geometry::point_on_border(pt, areal);
+ using point_type = typename geometry::point_type<Areal>::type;
+ typename helper_geometry<point_type>::type pt;
+ bool const ok = geometry::point_on_border(pt, areal);
// TODO: for now ignore, later throw an exception?
if ( !ok )
@@ -102,7 +104,7 @@ public:
m_other_areal,
m_point_in_areal_strategy);
//BOOST_GEOMETRY_ASSERT( pig != 0 );
-
+
// inside
if ( pig > 0 )
{
@@ -185,7 +187,7 @@ public:
}
}
}
-
+
return m_flags != 3 && !m_result.interrupt;
}
@@ -206,9 +208,6 @@ struct areal_areal
static const bool interruption_enabled = true;
- typedef typename geometry::point_type<Geometry1>::type point1_type;
- typedef typename geometry::point_type<Geometry2>::type point2_type;
-
template <typename Result, typename Strategy>
static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
Result & result,
@@ -216,17 +215,16 @@ struct areal_areal
{
// TODO: If Areal geometry may have infinite size, change the following line:
- // The result should be FFFFFFFFF
- relate::set<exterior, exterior, result_dimension<Geometry2>::value>(result);// FFFFFFFFd, d in [1,9] or T
+ update<exterior, exterior, result_dimension<Geometry2>::value>(result);// FFFFFFFFd, d in [1,9] or T
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
// get and analyse turns
- typedef typename turns::get_turns
+ using turn_type = typename turns::get_turns
<
Geometry1, Geometry2
- >::template turn_info_type<Strategy>::type turn_type;
+ >::template turn_info_type<Strategy>::type;
std::vector<turn_type> turns;
interrupt_policy_areal_areal<Result> interrupt_policy(geometry1, geometry2, result);
@@ -235,8 +233,6 @@ struct areal_areal
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
- typedef typename Strategy::cs_tag cs_tag;
-
no_turns_aa_pred<Geometry2, Result, Strategy, false>
pred1(geometry2, result, strategy);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
@@ -248,7 +244,7 @@ struct areal_areal
for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2);
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
-
+
if ( turns.empty() )
return;
@@ -259,8 +255,8 @@ struct areal_areal
|| may_update<exterior, interior, '2'>(result) )
{
// sort turns
- typedef turns::less<0, turns::less_op_areal_areal<0>, cs_tag> less;
- std::sort(turns.begin(), turns.end(), less());
+ using less_t = turns::less<0, turns::less_op_areal_areal<0>, Strategy>;
+ std::sort(turns.begin(), turns.end(), less_t());
/*if ( may_update<interior, exterior, '2'>(result)
|| may_update<boundary, exterior, '1'>(result)
@@ -299,8 +295,8 @@ struct areal_areal
|| may_update<exterior, interior, '2', true>(result) )
{
// sort turns
- typedef turns::less<1, turns::less_op_areal_areal<1>, cs_tag> less;
- std::sort(turns.begin(), turns.end(), less());
+ using less_t = turns::less<1, turns::less_op_areal_areal<1>, Strategy>;
+ std::sort(turns.begin(), turns.end(), less_t());
/*if ( may_update<interior, exterior, '2', true>(result)
|| may_update<boundary, exterior, '1', true>(result)
@@ -352,9 +348,7 @@ struct areal_areal
template <typename Range>
inline bool apply(Range const& turns)
{
- typedef typename boost::range_iterator<Range const>::type iterator;
-
- for (iterator it = boost::begin(turns) ; it != boost::end(turns) ; ++it)
+ for (auto it = boost::begin(turns) ; it != boost::end(turns) ; ++it)
{
per_turn<0>(*it);
per_turn<1>(*it);
@@ -469,7 +463,7 @@ struct areal_areal
{
m_exit_detected = false;
}
- }
+ }
/*else*/
if ( m_enter_detected /*m_previous_operation == overlay::operation_intersection*/ )
{
@@ -652,15 +646,14 @@ struct areal_areal
return;
}
- typename detail::sub_range_return_type<Geometry const>::type
- range_ref = detail::sub_range(geometry, seg_id);
+ auto const& sub_range = detail::sub_range(geometry, seg_id);
- if ( boost::empty(range_ref) )
+ if ( boost::empty(sub_range) )
{
// TODO: throw an exception?
return; // ignore
}
-
+
// TODO: possible optimization
// if the range is an interior ring we may use other IPs generated for this single geometry
// to know which other single geometries should be checked
@@ -668,7 +661,7 @@ struct areal_areal
// TODO: optimize! e.g. use spatial index
// O(N) - running it in a loop gives O(NM)
using detail::within::point_in_geometry;
- int const pig = point_in_geometry(range::front(range_ref),
+ int const pig = point_in_geometry(range::front(sub_range),
other_geometry,
m_point_in_areal_strategy);
@@ -713,12 +706,12 @@ struct areal_areal
for ( TurnIt it = first ; it != last ; ++it )
{
- if ( it->operations[0].operation == overlay::operation_intersection
+ if ( it->operations[0].operation == overlay::operation_intersection
&& it->operations[1].operation == overlay::operation_intersection )
{
found_ii = true;
}
- else if ( it->operations[0].operation == overlay::operation_union
+ else if ( it->operations[0].operation == overlay::operation_union
&& it->operations[1].operation == overlay::operation_union )
{
found_uu = true;
@@ -735,7 +728,7 @@ struct areal_areal
update<interior, interior, '2', transpose_result>(m_result);
m_flags |= 1;
- //update<boundary, boundary, '0', transpose_result>(m_result);
+ //update<boundary, boundary, '0', transpose_result>(m_result);
update<boundary, interior, '1', transpose_result>(m_result);
update<exterior, interior, '2', transpose_result>(m_result);
@@ -846,7 +839,7 @@ struct areal_areal
count = boost::numeric_cast<signed_size_type>(
geometry::num_interior_rings(
detail::single_geometry(analyser.geometry, seg_id)));
-
+
for_no_turns_rings(analyser, turn, seg_id.ring_index + 1, count);
}
diff --git a/boost/geometry/algorithms/detail/relate/boundary_checker.hpp b/boost/geometry/algorithms/detail/relate/boundary_checker.hpp
index 487c706e9f..0d95aabac1 100644
--- a/boost/geometry/algorithms/detail/relate/boundary_checker.hpp
+++ b/boost/geometry/algorithms/detail/relate/boundary_checker.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020 Oracle and/or its affiliates.
+// Copyright (c) 2014-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
// Use, modification and distribution is subject to the Boost Software License,
@@ -17,8 +18,14 @@
#include <boost/geometry/algorithms/detail/sub_range.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
+#include <boost/geometry/geometries/helper_geometry.hpp>
+
#include <boost/geometry/policies/compare.hpp>
+#include <boost/geometry/strategies/relate/cartesian.hpp>
+#include <boost/geometry/strategies/relate/geographic.hpp>
+#include <boost/geometry/strategies/relate/spherical.hpp>
+
#include <boost/geometry/util/has_nan_coordinate.hpp>
#include <boost/geometry/util/range.hpp>
@@ -26,9 +33,9 @@ namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
-namespace detail { namespace relate {
+namespace detail { namespace relate
+{
-enum boundary_query { boundary_front, boundary_back, boundary_any };
template
<
@@ -41,30 +48,26 @@ class boundary_checker {};
template <typename Geometry, typename Strategy>
class boundary_checker<Geometry, Strategy, linestring_tag>
{
- typedef typename point_type<Geometry>::type point_type;
-
public:
boundary_checker(Geometry const& g, Strategy const& s)
- : m_has_boundary( boost::size(g) >= 2
- && ! detail::equals::equals_point_point(range::front(g),
- range::back(g),
- s) )
+ : m_has_boundary(
+ boost::size(g) >= 2
+ && ! detail::equals::equals_point_point(range::front(g), range::back(g), s))
#ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER
, m_geometry(g)
#endif
, m_strategy(s)
{}
- template <boundary_query BoundaryQuery>
- bool is_endpoint_boundary(point_type const& pt) const
+ template <typename Point>
+ bool is_endpoint_boundary(Point const& pt) const
{
boost::ignore_unused(pt);
#ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER
// may give false positives for INT
- BOOST_GEOMETRY_ASSERT( (BoundaryQuery == boundary_front || BoundaryQuery == boundary_any)
- && detail::equals::equals_point_point(pt, range::front(m_geometry), m_strategy)
- || (BoundaryQuery == boundary_back || BoundaryQuery == boundary_any)
- && detail::equals::equals_point_point(pt, range::back(m_geometry), m_strategy) );
+ BOOST_GEOMETRY_ASSERT(
+ detail::equals::equals_point_point(pt, range::front(m_geometry), m_strategy)
+ || detail::equals::equals_point_point(pt, range::back(m_geometry), m_strategy));
#endif
return m_has_boundary;
}
@@ -82,10 +85,72 @@ private:
Strategy const& m_strategy;
};
+
+template <typename Point, typename Strategy, typename Out>
+inline void copy_boundary_points(Point const& front_pt, Point const& back_pt,
+ Strategy const& strategy, Out & boundary_points)
+{
+ using mutable_point_type = typename Out::value_type;
+ // linear ring or point - no boundary
+ if (! equals::equals_point_point(front_pt, back_pt, strategy))
+ {
+ // do not add points containing NaN coordinates
+ // because they cannot be reasonably compared, e.g. with MSVC
+ // an assertion failure is reported in std::equal_range()
+ if (! geometry::has_nan_coordinate(front_pt))
+ {
+ mutable_point_type pt;
+ geometry::convert(front_pt, pt);
+ boundary_points.push_back(pt);
+ }
+ if (! geometry::has_nan_coordinate(back_pt))
+ {
+ mutable_point_type pt;
+ geometry::convert(back_pt, pt);
+ boundary_points.push_back(pt);
+ }
+ }
+}
+
+template <typename Segment, typename Strategy, typename Out>
+inline void copy_boundary_points_of_seg(Segment const& seg, Strategy const& strategy,
+ Out & boundary_points)
+{
+ typename Out::value_type front_pt, back_pt;
+ assign_point_from_index<0>(seg, front_pt);
+ assign_point_from_index<1>(seg, back_pt);
+ copy_boundary_points(front_pt, back_pt, strategy, boundary_points);
+}
+
+template <typename Linestring, typename Strategy, typename Out>
+inline void copy_boundary_points_of_ls(Linestring const& ls, Strategy const& strategy,
+ Out & boundary_points)
+{
+ // empty or point - no boundary
+ if (boost::size(ls) >= 2)
+ {
+ auto const& front_pt = range::front(ls);
+ auto const& back_pt = range::back(ls);
+ copy_boundary_points(front_pt, back_pt, strategy, boundary_points);
+ }
+}
+
+template <typename MultiLinestring, typename Strategy, typename Out>
+inline void copy_boundary_points_of_mls(MultiLinestring const& mls, Strategy const& strategy,
+ Out & boundary_points)
+{
+ for (auto it = boost::begin(mls); it != boost::end(mls); ++it)
+ {
+ copy_boundary_points_of_ls(*it, strategy, boundary_points);
+ }
+}
+
+
template <typename Geometry, typename Strategy>
class boundary_checker<Geometry, Strategy, multi_linestring_tag>
{
- typedef typename point_type<Geometry>::type point_type;
+ using point_type = typename point_type<Geometry>::type;
+ using mutable_point_type = typename helper_geometry<point_type>::type;
public:
boundary_checker(Geometry const& g, Strategy const& s)
@@ -94,75 +159,38 @@ public:
// First call O(NlogN)
// Each next call O(logN)
- template <boundary_query BoundaryQuery>
- bool is_endpoint_boundary(point_type const& pt) const
+ template <typename Point>
+ bool is_endpoint_boundary(Point const& pt) const
{
- typedef geometry::less<point_type, -1, typename Strategy::cs_tag> less_type;
+ using less_type = geometry::less<mutable_point_type, -1, Strategy>;
- typedef typename boost::range_size<Geometry>::type size_type;
- size_type multi_count = boost::size(m_geometry);
+ auto const multi_count = boost::size(m_geometry);
- if ( multi_count < 1 )
+ if (multi_count < 1)
+ {
return false;
+ }
- if ( ! m_is_filled )
+ if (! m_is_filled)
{
//boundary_points.clear();
m_boundary_points.reserve(multi_count * 2);
- typedef typename boost::range_iterator<Geometry const>::type multi_iterator;
- for ( multi_iterator it = boost::begin(m_geometry) ;
- it != boost::end(m_geometry) ; ++ it )
- {
- typename boost::range_reference<Geometry const>::type
- ls = *it;
-
- // empty or point - no boundary
- if (boost::size(ls) < 2)
- {
- continue;
- }
-
- typedef typename boost::range_reference
- <
- typename boost::range_value<Geometry const>::type const
- >::type point_reference;
-
- point_reference front_pt = range::front(ls);
- point_reference back_pt = range::back(ls);
-
- // linear ring or point - no boundary
- if (! equals::equals_point_point(front_pt, back_pt, m_strategy))
- {
- // do not add points containing NaN coordinates
- // because they cannot be reasonably compared, e.g. with MSVC
- // an assertion failure is reported in std::equal_range()
- if (! geometry::has_nan_coordinate(front_pt))
- {
- m_boundary_points.push_back(front_pt);
- }
- if (! geometry::has_nan_coordinate(back_pt))
- {
- m_boundary_points.push_back(back_pt);
- }
- }
- }
-
- std::sort(m_boundary_points.begin(),
- m_boundary_points.end(),
- less_type());
+ copy_boundary_points_of_mls(m_geometry, m_strategy, m_boundary_points);
+
+ std::sort(m_boundary_points.begin(), m_boundary_points.end(), less_type());
m_is_filled = true;
}
- std::size_t equal_points_count
- = boost::size(
- std::equal_range(m_boundary_points.begin(),
- m_boundary_points.end(),
- pt,
- less_type())
- );
+ mutable_point_type mpt;
+ geometry::convert(pt, mpt);
+ auto const equal_range = std::equal_range(m_boundary_points.begin(),
+ m_boundary_points.end(),
+ mpt,
+ less_type());
+ std::size_t const equal_points_count = boost::size(equal_range);
return equal_points_count % 2 != 0;// && equal_points_count > 0; // the number is odd and > 0
}
@@ -173,13 +201,14 @@ public:
private:
mutable bool m_is_filled;
- // TODO: store references/pointers instead of points?
- mutable std::vector<point_type> m_boundary_points;
+ // TODO: store references/pointers instead of converted points?
+ mutable std::vector<mutable_point_type> m_boundary_points;
Geometry const& m_geometry;
Strategy const& m_strategy;
};
+
}} // namespace detail::relate
#endif // DOXYGEN_NO_DETAIL
diff --git a/boost/geometry/algorithms/detail/relate/box_areal.hpp b/boost/geometry/algorithms/detail/relate/box_areal.hpp
new file mode 100644
index 0000000000..a9e749fdb2
--- /dev/null
+++ b/boost/geometry/algorithms/detail/relate/box_areal.hpp
@@ -0,0 +1,70 @@
+// Boost.Geometry
+
+// Copyright (c) 2022, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOX_AREAL_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOX_AREAL_HPP
+
+#include <boost/geometry/algorithms/detail/relate/areal_areal.hpp>
+#include <boost/geometry/views/box_view.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace relate {
+
+
+// The implementation of an algorithm calculating relate() for B/A
+template <typename Box, typename Areal>
+struct box_areal
+{
+ static const bool interruption_enabled = true;
+
+ template <typename Result, typename Strategy>
+ static inline void apply(Box const& box, Areal const& areal,
+ Result& result,
+ Strategy const& strategy)
+ {
+ using is_cartesian = std::is_same
+ <
+ typename Strategy::cs_tag,
+ cartesian_tag
+ >;
+ apply(box, areal, result, strategy, is_cartesian());
+ }
+
+ template <typename Result, typename Strategy>
+ static inline void apply(Box const& box, Areal const& areal,
+ Result& result,
+ Strategy const& strategy,
+ std::true_type /*is_cartesian*/)
+ {
+ using box_view = boost::geometry::box_view<Box>;
+ box_view view(box);
+ areal_areal<box_view, Areal>::apply(view, areal, result, strategy);
+ }
+
+ template <typename Result, typename Strategy>
+ static inline void apply(Box const& box, Areal const& areal,
+ Result& result,
+ Strategy const& strategy,
+ std::false_type /*is_cartesian*/)
+ {
+ BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
+ "Not implemented for this coordinate system.",
+ typename Strategy::cs_tag());
+ }
+};
+
+}} // namespace detail::relate
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOX_AREAL_HPP
diff --git a/boost/geometry/algorithms/detail/relate/de9im.hpp b/boost/geometry/algorithms/detail/relate/de9im.hpp
index a89d46100a..a9d6ea5792 100644
--- a/boost/geometry/algorithms/detail/relate/de9im.hpp
+++ b/boost/geometry/algorithms/detail/relate/de9im.hpp
@@ -1,9 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2022 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2020.
-// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -25,7 +26,7 @@
namespace boost { namespace geometry
{
-
+
namespace de9im
{
@@ -103,7 +104,7 @@ public:
inline explicit mask(const char* code)
: base_type(code)
{}
-
+
/*!
\brief The constructor.
\param code The mask pattern.
@@ -275,6 +276,11 @@ struct static_mask_touches_impl<Geometry1, Geometry2, 0, 0>
};
template <typename Geometry1, typename Geometry2>
+struct static_mask_touches_not_pp_type
+ : static_mask_touches_impl<Geometry1, Geometry2, 2, 2> // dummy dimensions
+{};
+
+template <typename Geometry1, typename Geometry2>
struct static_mask_touches_type
: static_mask_touches_impl<Geometry1, Geometry2>
{};
@@ -344,6 +350,21 @@ struct static_mask_crosses_type
: static_mask_crosses_impl<Geometry1, Geometry2>
{};
+template <typename Geometry1, typename Geometry2>
+struct static_mask_crosses_d1_le_d2_type // specific dimensions are not important here
+ : static_mask_crosses_impl<Geometry1, Geometry2, 0, 1>
+{};
+
+template <typename Geometry1, typename Geometry2>
+struct static_mask_crosses_d2_le_d1_type // specific dimensions are not important here
+ : static_mask_crosses_impl<Geometry1, Geometry2, 1, 0>
+{};
+
+template <typename Geometry1, typename Geometry2>
+struct static_mask_crosses_d1_1_d2_1_type
+ : static_mask_crosses_impl<Geometry1, Geometry2, 1, 1>
+{};
+
// OVERLAPS
// dim(G1) != dim(G2) - NOT P/P, L/L, A/A
@@ -376,6 +397,16 @@ struct static_mask_overlaps_type
: static_mask_overlaps_impl<Geometry1, Geometry2>
{};
+template <typename Geometry1, typename Geometry2>
+struct static_mask_overlaps_d1_eq_d2_type
+ : static_mask_overlaps_impl<Geometry1, Geometry2, 2, 2>
+{};
+
+template <typename Geometry1, typename Geometry2>
+struct static_mask_overlaps_d1_1_d2_1_type
+ : static_mask_overlaps_impl<Geometry1, Geometry2, 1, 1>
+{};
+
}} // namespace detail::de9im
#endif // DOXYGEN_NO_DETAIL
diff --git a/boost/geometry/algorithms/detail/relate/follow_helpers.hpp b/boost/geometry/algorithms/detail/relate/follow_helpers.hpp
index d584e81e5c..cb1f0f40c9 100644
--- a/boost/geometry/algorithms/detail/relate/follow_helpers.hpp
+++ b/boost/geometry/algorithms/detail/relate/follow_helpers.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2018.
-// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -30,6 +30,8 @@
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
+#include <type_traits>
+
namespace boost { namespace geometry
{
@@ -42,7 +44,7 @@ namespace detail { namespace relate {
template <std::size_t OpId,
typename Geometry,
typename Tag = typename geometry::tag<Geometry>::type,
- bool IsMulti = boost::is_base_of<multi_tag, Tag>::value
+ bool IsMulti = std::is_base_of<multi_tag, Tag>::value
>
struct for_each_disjoint_geometry_if
: public not_implemented<Tag>
@@ -52,14 +54,12 @@ template <std::size_t OpId, typename Geometry, typename Tag>
struct for_each_disjoint_geometry_if<OpId, Geometry, Tag, false>
{
template <typename TurnIt, typename Pred>
- static inline bool apply(TurnIt first, TurnIt last,
- Geometry const& geometry,
- Pred & pred)
+ static void apply(TurnIt first, TurnIt last, Geometry const& geometry, Pred & pred)
{
- if ( first != last )
- return false;
- pred(geometry);
- return true;
+ if (first == last)
+ {
+ pred(geometry);
+ }
}
};
@@ -67,49 +67,43 @@ template <std::size_t OpId, typename Geometry, typename Tag>
struct for_each_disjoint_geometry_if<OpId, Geometry, Tag, true>
{
template <typename TurnIt, typename Pred>
- static inline bool apply(TurnIt first, TurnIt last,
- Geometry const& geometry,
- Pred & pred)
+ static void apply(TurnIt first, TurnIt last, Geometry const& geometry, Pred & pred)
{
- if ( first != last )
- return for_turns(first, last, geometry, pred);
+ if (first == last)
+ {
+ for_empty(geometry, pred);
+ }
else
- return for_empty(geometry, pred);
+ {
+ for_turns(first, last, geometry, pred);
+ }
}
template <typename Pred>
- static inline bool for_empty(Geometry const& geometry,
- Pred & pred)
+ static void for_empty(Geometry const& geometry, Pred & pred)
{
- typedef typename boost::range_iterator<Geometry const>::type iterator;
-
// O(N)
// check predicate for each contained geometry without generated turn
- for ( iterator it = boost::begin(geometry) ;
- it != boost::end(geometry) ; ++it )
+ for (auto it = boost::begin(geometry); it != boost::end(geometry) ; ++it)
{
- bool cont = pred(*it);
- if ( !cont )
+ if (! pred(*it))
+ {
break;
+ }
}
-
- return !boost::empty(geometry);
}
template <typename TurnIt, typename Pred>
- static inline bool for_turns(TurnIt first, TurnIt last,
- Geometry const& geometry,
- Pred & pred)
+ static void for_turns(TurnIt first, TurnIt last, Geometry const& geometry, Pred & pred)
{
BOOST_GEOMETRY_ASSERT(first != last);
const std::size_t count = boost::size(geometry);
- boost::ignore_unused(count);
// O(I)
// gather info about turns generated for contained geometries
std::vector<bool> detected_intersections(count, false);
- for ( TurnIt it = first ; it != last ; ++it )
+ for (TurnIt it = first; it != last; ++it)
{
signed_size_type multi_index = it->operations[OpId].seg_id.multi_index;
BOOST_GEOMETRY_ASSERT(multi_index >= 0);
@@ -118,28 +112,23 @@ struct for_each_disjoint_geometry_if<OpId, Geometry, Tag, true>
detected_intersections[index] = true;
}
- bool found = false;
-
// O(N)
// check predicate for each contained geometry without generated turn
- for ( std::vector<bool>::iterator it = detected_intersections.begin() ;
- it != detected_intersections.end() ; ++it )
+ for (std::size_t index = 0; index < detected_intersections.size(); ++index)
{
// if there were no intersections for this multi_index
- if ( *it == false )
+ if (detected_intersections[index] == false)
{
- found = true;
- std::size_t const index = std::size_t(std::distance(detected_intersections.begin(), it));
- bool cont = pred(range::at(geometry, index));
- if ( !cont )
+ if (! pred(range::at(geometry, index)))
+ {
break;
+ }
}
}
-
- return found;
}
};
+
// WARNING! This class stores pointers!
// Passing a reference to local variable will result in undefined behavior!
template <typename Point>
@@ -184,7 +173,7 @@ public:
bool operator()(segment_identifier const& sid) const
{
- return sid.multi_index == sid_ptr->multi_index;
+ return sid.multi_index == sid_ptr->multi_index;
}
template <typename Point>
@@ -267,11 +256,10 @@ public:
segment_identifier const& other_id = turn.operations[other_op_id].seg_id;
overlay::operation_type exit_op = turn.operations[op_id].operation;
- typedef typename std::vector<point_info>::iterator point_iterator;
// search for the entry point in the same range of other geometry
- point_iterator entry_it = std::find_if(m_other_entry_points.begin(),
- m_other_entry_points.end(),
- same_single(other_id));
+ auto entry_it = std::find_if(m_other_entry_points.begin(),
+ m_other_entry_points.end(),
+ same_single(other_id));
// this end point has corresponding entry point
if ( entry_it != m_other_entry_points.end() )
@@ -298,11 +286,10 @@ public:
bool is_outside(TurnInfo const& turn) const
{
return m_other_entry_points.empty()
- || std::find_if(m_other_entry_points.begin(),
+ || std::none_of(m_other_entry_points.begin(),
m_other_entry_points.end(),
same_single(
- turn.operations[other_op_id].seg_id))
- == m_other_entry_points.end();
+ turn.operations[other_op_id].seg_id));
}
overlay::operation_type get_exit_operation() const
@@ -366,44 +353,17 @@ inline bool turn_on_the_same_ip(Turn const& prev_turn, Turn const& curr_turn,
return detail::equals::equals_point_point(prev_turn.point, curr_turn.point, strategy);
}
-template <boundary_query BoundaryQuery,
- typename Point,
- typename BoundaryChecker>
-static inline bool is_endpoint_on_boundary(Point const& pt,
- BoundaryChecker & boundary_checker)
-{
- return boundary_checker.template is_endpoint_boundary<BoundaryQuery>(pt);
-}
-
-template <boundary_query BoundaryQuery,
- typename IntersectionPoint,
- typename OperationInfo,
- typename BoundaryChecker>
+template <typename IntersectionPoint, typename OperationInfo, typename BoundaryChecker>
static inline bool is_ip_on_boundary(IntersectionPoint const& ip,
OperationInfo const& operation_info,
- BoundaryChecker & boundary_checker,
- segment_identifier const& seg_id)
+ BoundaryChecker const& boundary_checker)
{
- boost::ignore_unused(seg_id);
-
- bool res = false;
-
- // IP on the last point of the linestring
- if ( BOOST_GEOMETRY_CONDITION(BoundaryQuery == boundary_back || BoundaryQuery == boundary_any)
- && operation_info.position == overlay::position_back )
- {
- // check if this point is a boundary
- res = boundary_checker.template is_endpoint_boundary<boundary_back>(ip);
- }
- // IP on the last point of the linestring
- else if ( BOOST_GEOMETRY_CONDITION(BoundaryQuery == boundary_front || BoundaryQuery == boundary_any)
- && operation_info.position == overlay::position_front )
- {
- // check if this point is a boundary
- res = boundary_checker.template is_endpoint_boundary<boundary_front>(ip);
- }
-
- return res;
+ // IP on the first or the last point of the linestring
+ return (operation_info.position == overlay::position_back
+ || operation_info.position == overlay::position_front)
+ // check if this point is a boundary
+ ? boundary_checker.is_endpoint_boundary(ip)
+ : false;
}
diff --git a/boost/geometry/algorithms/detail/relate/implementation.hpp b/boost/geometry/algorithms/detail/relate/implementation.hpp
index 190a5e3d6b..458bfdba3f 100644
--- a/boost/geometry/algorithms/detail/relate/implementation.hpp
+++ b/boost/geometry/algorithms/detail/relate/implementation.hpp
@@ -2,9 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013-2021.
-// Modifications copyright (c) 2013-2021 Oracle and/or its affiliates.
-
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,16 +14,16 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_HPP
-#include <boost/geometry/core/tags.hpp>
-
+#include <boost/geometry/algorithms/detail/relate/areal_areal.hpp>
+#include <boost/geometry/algorithms/detail/relate/box_areal.hpp>
#include <boost/geometry/algorithms/detail/relate/interface.hpp>
-
-#include <boost/geometry/algorithms/detail/relate/point_point.hpp>
-#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp>
-#include <boost/geometry/algorithms/detail/relate/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/relate/linear_areal.hpp>
+#include <boost/geometry/algorithms/detail/relate/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp>
-#include <boost/geometry/algorithms/detail/relate/areal_areal.hpp>
+#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp>
+#include <boost/geometry/algorithms/detail/relate/point_point.hpp>
+
+#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/relate/cartesian.hpp>
#include <boost/geometry/strategies/relate/geographic.hpp>
@@ -116,6 +115,23 @@ struct relate<Areal1, Areal2, Tag1, Tag2, 2, 2, true>
: detail::relate::areal_areal<Areal1, Areal2>
{};
+
+template <typename Box, typename Ring>
+struct relate<Box, Ring, box_tag, ring_tag, 2, 2, false>
+ : detail::relate::box_areal<Box, Ring>
+{};
+
+template <typename Box, typename Polygon>
+struct relate<Box, Polygon, box_tag, polygon_tag, 2, 2, false>
+ : detail::relate::box_areal<Box, Polygon>
+{};
+
+template <typename Box, typename MultiPolygon>
+struct relate<Box, MultiPolygon, box_tag, multi_polygon_tag, 2, 2, false>
+ : detail::relate::box_areal<Box, MultiPolygon>
+{};
+
+
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
diff --git a/boost/geometry/algorithms/detail/relate/implementation_gc.hpp b/boost/geometry/algorithms/detail/relate/implementation_gc.hpp
new file mode 100644
index 0000000000..f0fa11d2af
--- /dev/null
+++ b/boost/geometry/algorithms/detail/relate/implementation_gc.hpp
@@ -0,0 +1,696 @@
+// Boost.Geometry
+
+// Copyright (c) 2022-2023 Adam Wulkiewicz, Lodz, Poland.
+
+// Copyright (c) 2022 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_GC_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_GC_HPP
+
+
+#include <boost/geometry/algorithms/detail/relate/boundary_checker.hpp>
+#include <boost/geometry/algorithms/detail/relate/interface.hpp>
+#include <boost/geometry/algorithms/difference.hpp>
+#include <boost/geometry/algorithms/intersection.hpp>
+#include <boost/geometry/algorithms/is_empty.hpp>
+#include <boost/geometry/algorithms/union.hpp>
+#include <boost/geometry/geometries/linestring.hpp>
+#include <boost/geometry/geometries/multi_linestring.hpp>
+#include <boost/geometry/geometries/multi_point.hpp>
+#include <boost/geometry/geometries/multi_polygon.hpp>
+#include <boost/geometry/geometries/polygon.hpp>
+#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/views/detail/geometry_collection_view.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace relate
+{
+
+// For fields II IE and EI this handler behaves like matrix_handler.
+// It has to be created at the beginning of processing because it relies on the
+// fact that all of the fields are set to F and no geometry was handled yet.
+// This way it can check which fields are required for any mask and matrix
+// without accessing the internals.
+// An alternative would be to remove this wrapper and always set the matrix
+// in static_mask_handler even if this is not required.
+template <typename Handler>
+struct aa_handler_wrapper
+{
+ bool interrupt = false;
+
+ explicit aa_handler_wrapper(Handler& handler)
+ : m_handler(handler)
+ , m_overwrite_ii(! handler.template may_update<interior, interior, '2'>())
+ , m_overwrite_ie(! handler.template may_update<interior, exterior, '2'>())
+ , m_overwrite_ei(! handler.template may_update<exterior, interior, '2'>())
+ {}
+
+ template <field F1, field F2, char D>
+ inline bool may_update() const
+ {
+ if ((BOOST_GEOMETRY_CONDITION(F1 == interior && F2 == interior) && m_overwrite_ii)
+ || (BOOST_GEOMETRY_CONDITION(F1 == interior && F2 == exterior) && m_overwrite_ie)
+ || (BOOST_GEOMETRY_CONDITION(F1 == exterior && F2 == interior) && m_overwrite_ei))
+ {
+ char const c = m_handler.template get<F1, F2>();
+ return D > c || c > '9';
+ }
+ else
+ {
+ return m_handler.template may_update<F1, F2, D>();
+ }
+ }
+
+ template <field F1, field F2, char V>
+ inline void update()
+ {
+ if ((BOOST_GEOMETRY_CONDITION(F1 == interior && F2 == interior) && m_overwrite_ii)
+ || (BOOST_GEOMETRY_CONDITION(F1 == interior && F2 == exterior) && m_overwrite_ie)
+ || (BOOST_GEOMETRY_CONDITION(F1 == exterior && F2 == interior) && m_overwrite_ei))
+ {
+ // NOTE: Other handlers first check for potential interruption
+ // and only after that checks update condition.
+ char const c = m_handler.template get<F1, F2>();
+ // If c == T and V == T it will be set anyway but that's fine.
+ if (V > c || c > '9')
+ {
+ // set may set interrupt flag
+ m_handler.template set<F1, F2, V>();
+ }
+ }
+ else
+ {
+ m_handler.template update<F1, F2, V>();
+ }
+ interrupt = interrupt || m_handler.interrupt;
+ }
+
+private:
+ Handler & m_handler;
+ bool const m_overwrite_ii;
+ bool const m_overwrite_ie;
+ bool const m_overwrite_ei;
+};
+
+
+template <typename Geometry1, typename Geometry2>
+struct gc_gc
+{
+ static const bool interruption_enabled = true;
+
+ using mpt1_found_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Geometry1>::type,
+ util::is_multi_point
+ >::type;
+ using mls1_found_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Geometry1>::type,
+ util::is_multi_linestring
+ >::type;
+ using mpo1_found_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Geometry1>::type,
+ util::is_multi_polygon
+ >::type;
+ using pt1_t = typename geometry::point_type<Geometry1>::type;
+ using mpt1_t = std::conditional_t
+ <
+ std::is_void<mpt1_found_t>::value,
+ geometry::model::multi_point<pt1_t>,
+ mpt1_found_t
+ >;
+ using mls1_t = std::conditional_t
+ <
+ std::is_void<mls1_found_t>::value,
+ geometry::model::multi_linestring<geometry::model::linestring<pt1_t>>,
+ mls1_found_t
+ >;
+ using mpo1_t = std::conditional_t
+ <
+ std::is_void<mpo1_found_t>::value,
+ geometry::model::multi_polygon<geometry::model::polygon<pt1_t>>,
+ mpo1_found_t
+ >;
+ using tuple1_t = boost::tuple<mpt1_t, mls1_t, mpo1_t>;
+
+ using mpt2_found_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Geometry2>::type,
+ util::is_multi_point
+ >::type;
+ using mls2_found_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Geometry2>::type,
+ util::is_multi_linestring
+ >::type;
+ using mpo2_found_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Geometry2>::type,
+ util::is_multi_polygon
+ >::type;
+ using pt2_t = typename geometry::point_type<Geometry2>::type;
+ using mpt2_t = std::conditional_t
+ <
+ std::is_void<mpt2_found_t>::value,
+ geometry::model::multi_point<pt2_t>,
+ mpt2_found_t
+ >;
+ using mls2_t = std::conditional_t
+ <
+ std::is_void<mls2_found_t>::value,
+ geometry::model::multi_linestring<geometry::model::linestring<pt2_t>>,
+ mls2_found_t
+ >;
+ using mpo2_t = std::conditional_t
+ <
+ std::is_void<mpo2_found_t>::value,
+ geometry::model::multi_polygon<geometry::model::polygon<pt2_t>>,
+ mpo2_found_t
+ >;
+ using tuple2_t = boost::tuple<mpt2_t, mls2_t, mpo2_t>;
+
+ template <typename Geometry>
+ using kind_id = util::index_constant
+ <
+ util::is_areal<Geometry>::value ? 2
+ : util::is_linear<Geometry>::value ? 1
+ : 0
+ >;
+
+ template <typename Result, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Result & result,
+ Strategy const& strategy)
+ {
+ using gc1_view_t = random_access_view<Geometry1 const>;
+ using gc2_view_t = random_access_view<Geometry2 const>;
+ gc1_view_t const gc1_view(geometry1);
+ gc2_view_t const gc2_view(geometry2);
+
+ bool inters_found[2][3] = {{false, false, false}, {false, false, false}};
+ bool disjoint_found[2][3] = {{false, false, false}, {false, false, false}};
+ bool disjoint_linear_boundary_found[2] = {false, false};
+ bool has_disjoint = false;
+
+ gc_group_elements(gc1_view, gc2_view, strategy,
+ [&](auto const& inters_group)
+ {
+ tuple1_t tuple1;
+ tuple2_t tuple2;
+
+ // Create MPts, MLss and MPos containing all gc elements from this group
+ // They may potentially intersect each other
+ for (auto const& id : inters_group)
+ {
+ BOOST_GEOMETRY_ASSERT(id.source_id == 0 || id.source_id == 1);
+ if (id.source_id == 0)
+ {
+ traits::iter_visit<gc1_view_t>::apply([&](auto const& g1)
+ {
+ merge_geometry(tuple1, g1, strategy);
+ }, boost::begin(gc1_view) + id.gc_id);
+ }
+ else
+ {
+ traits::iter_visit<gc2_view_t>::apply([&](auto const& g2)
+ {
+ merge_geometry(tuple2, g2, strategy);
+ }, boost::begin(gc2_view) + id.gc_id);
+ }
+ }
+
+ // Subtract higher topo-dim elements from elements of lower topo-dim
+ // MPts do not intersect other geometries, MLss and MPos may touch
+ subtract_elements(tuple1, strategy);
+ subtract_elements(tuple2, strategy);
+
+ // Helpers
+ auto const& mpt1 = boost::get<0>(tuple1);
+ auto const& mls1 = boost::get<1>(tuple1);
+ auto const& mpo1 = boost::get<2>(tuple1);
+ auto const& mpt2 = boost::get<0>(tuple2);
+ auto const& mls2 = boost::get<1>(tuple2);
+ auto const& mpo2 = boost::get<2>(tuple2);
+
+ // A/A
+ if (! geometry::is_empty(mpo1) && ! geometry::is_empty(mpo2))
+ {
+ inters_found[0][2] = true;
+ inters_found[1][2] = true;
+ aa_handler_wrapper<Result> wrapper(result);
+ call_relate(mpo1, mpo2, wrapper, strategy);
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(result.interrupt))
+ {
+ return false;
+ }
+
+ bool is_aa_ii = result.template get<interior, interior>() != 'F';
+ bool is_aa_ie = result.template get<interior, exterior>() != 'F';
+ bool is_aa_ei = result.template get<exterior, interior>() != 'F';
+ // is_aa_ii implies is_aa_checked and non-empty Areal geometries
+ bool are_aa_equal = is_aa_ii && ! is_aa_ie && ! is_aa_ei;
+
+ // Boundary checkers are internally initialized lazily later if a point has to be checked
+ boundary_checker<mls1_t, Strategy> mls1_boundary(mls1, strategy);
+ boundary_checker<mls2_t, Strategy> mls2_boundary(mls2, strategy);
+
+ // If needed divide MLss into two parts:
+ // - inside Areal of other GC
+ // - outside of other GC Areal to check WRT Linear of other GC
+ mls2_t mls2_diff_mpo1, mls2_inters_mpo1;
+ bool is_mls2_divided = false;
+ mls1_t mls1_diff_mpo2, mls1_inters_mpo2;
+ bool is_mls1_divided = false;
+ // If Areal are equal then Linear are outside of both so there is no need to divide
+ if (! are_aa_equal && ! geometry::is_empty(mls1) && ! geometry::is_empty(mls2))
+ {
+ // LA/L
+ if (! geometry::is_empty(mpo1))
+ {
+ geometry::difference(mls2, mpo1, mls2_diff_mpo1);
+ geometry::intersection(mls2, mpo1, mls2_inters_mpo1);
+ is_mls2_divided = true;
+ }
+ // L/LA
+ if (! geometry::is_empty(mpo2))
+ {
+ geometry::difference(mls1, mpo2, mls1_diff_mpo2);
+ geometry::intersection(mls1, mpo2, mls1_inters_mpo2);
+ is_mls1_divided = true;
+ }
+ }
+
+ // A/L
+ if (! geometry::is_empty(mpo1) && ! geometry::is_empty(mls2))
+ {
+ inters_found[0][2] = true;
+ inters_found[1][1] = true;
+ if (is_aa_ii && ! is_aa_ie && ! is_aa_ei && ! geometry::is_empty(mls1))
+ {
+ // Equal Areal and both Linear non-empty, calculate only L/L below
+ }
+ else if (is_aa_ii && ! is_aa_ie && geometry::is_empty(mls1))
+ {
+ // An alternative would be to calculate L/L with one empty below
+ mpo1_t empty;
+ call_relate_al(empty, mls2, mls2_boundary, result, strategy);
+ }
+ else
+ {
+ if (is_mls2_divided)
+ {
+ if (! geometry::is_empty(mls2_inters_mpo1))
+ {
+ call_relate_al(mpo1, mls2_inters_mpo1, mls2_boundary, result, strategy);
+ }
+ }
+ else
+ {
+ call_relate_al(mpo1, mls2, mls2_boundary, result, strategy);
+ }
+ }
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(result.interrupt))
+ {
+ return false;
+ }
+
+ // L/A
+ if (! geometry::is_empty(mls1) && ! geometry::is_empty(mpo2))
+ {
+ inters_found[0][1] = true;
+ inters_found[1][2] = true;
+ if (is_aa_ii && ! is_aa_ei && ! is_aa_ie && ! geometry::is_empty(mls2))
+ {
+ // Equal Areal and both Linear non-empty, calculate only L/L below
+ }
+ else if (is_aa_ii && ! is_aa_ei && geometry::is_empty(mls2))
+ {
+ // An alternative would be to calculate L/L with one empty below
+ mpo2_t empty;
+ call_relate_la(mls1, empty, mls1_boundary, result, strategy);
+ }
+ else
+ {
+ if (is_mls1_divided)
+ {
+ if (! geometry::is_empty(mls1_inters_mpo2))
+ {
+ call_relate_la(mls1_inters_mpo2, mpo2, mls1_boundary, result, strategy);
+ }
+ }
+ else
+ {
+ call_relate_la(mls1, mpo2, mls1_boundary, result, strategy);
+ }
+ }
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(result.interrupt))
+ {
+ return false;
+ }
+
+ // L/L
+ if (! geometry::is_empty(mls1) && ! geometry::is_empty(mls2))
+ {
+ inters_found[0][1] = true;
+ inters_found[1][1] = true;
+ if (is_mls1_divided && is_mls2_divided)
+ {
+ if (! geometry::is_empty(mls1_diff_mpo2) && ! geometry::is_empty(mls2_diff_mpo1))
+ {
+ call_relate_ll(mls1_diff_mpo2, mls2_diff_mpo1, mls1_boundary, mls2_boundary, result, strategy);
+ }
+ }
+ else if (is_mls1_divided)
+ {
+ if (! geometry::is_empty(mls1_diff_mpo2))
+ {
+ call_relate_ll(mls1_diff_mpo2, mls2, mls1_boundary, mls2_boundary, result, strategy);
+ }
+ }
+ else if (is_mls2_divided)
+ {
+ if (! geometry::is_empty(mls2_diff_mpo1))
+ {
+ call_relate_ll(mls1, mls2_diff_mpo1, mls1_boundary, mls2_boundary, result, strategy);
+ }
+ }
+ else
+ {
+ call_relate_ll(mls1, mls2, mls1_boundary, mls2_boundary, result, strategy);
+ }
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(result.interrupt))
+ {
+ return false;
+ }
+
+ // A/P
+ if (! geometry::is_empty(mpo1) && ! geometry::is_empty(mpt2))
+ {
+ inters_found[0][2] = true;
+ inters_found[1][0] = true;
+ call_relate(mpo1, mpt2, result, strategy);
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(result.interrupt))
+ {
+ return false;
+ }
+
+ // P/A
+ if (! geometry::is_empty(mpt1) && ! geometry::is_empty(mpo2))
+ {
+ inters_found[0][0] = true;
+ inters_found[1][2] = true;
+ call_relate(mpt1, mpo2, result, strategy);
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(result.interrupt))
+ {
+ return false;
+ }
+
+ // L/P
+ if (! geometry::is_empty(mls1) && ! geometry::is_empty(mpt2))
+ {
+ inters_found[0][1] = true;
+ inters_found[1][0] = true;
+ call_relate(mls1, mpt2, result, strategy);
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(result.interrupt))
+ {
+ return false;
+ }
+
+ // P/L
+ if (! geometry::is_empty(mpt1) && ! geometry::is_empty(mls2))
+ {
+ inters_found[0][0] = true;
+ inters_found[1][1] = true;
+ call_relate(mpt1, mls2, result, strategy);
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(result.interrupt))
+ {
+ return false;
+ }
+
+ // P/P
+ if (! geometry::is_empty(mpt1) && ! geometry::is_empty(mpt2))
+ {
+ inters_found[0][0] = true;
+ inters_found[1][0] = true;
+ call_relate(mpt1, mpt2, result, strategy);
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(result.interrupt))
+ {
+ return false;
+ }
+
+ return true;
+ },
+ [&](auto const& disjoint_group)
+ {
+ for (auto const& id : disjoint_group)
+ {
+ BOOST_GEOMETRY_ASSERT(id.source_id == 0 || id.source_id == 1);
+ if (id.source_id == 0)
+ {
+ traits::iter_visit<gc1_view_t>::apply([&](auto const& g1)
+ {
+ if (! geometry::is_empty(g1))
+ {
+ static const std::size_t index = kind_id<util::remove_cref_t<decltype(g1)>>::value;
+ disjoint_found[0][index] = true;
+ disjoint_linear_boundary_found[0] = has_linear_boundary(g1, strategy);
+ has_disjoint = true;
+ }
+ }, boost::begin(gc1_view) + id.gc_id);
+ }
+ else
+ {
+ traits::iter_visit<gc2_view_t>::apply([&](auto const& g2)
+ {
+ if (! geometry::is_empty(g2))
+ {
+ static const std::size_t index = kind_id<util::remove_cref_t<decltype(g2)>>::value;
+ disjoint_found[1][index] = true;
+ disjoint_linear_boundary_found[1] = has_linear_boundary(g2, strategy);
+ has_disjoint = true;
+ }
+ }, boost::begin(gc2_view) + id.gc_id);
+ }
+ }
+ }, true);
+
+ // Based on found disjoint geometries as well as those intersecting set exteriors
+ if (has_disjoint)
+ {
+ if (disjoint_found[0][2] == true)
+ {
+ update<interior, exterior, '2'>(result);
+ update<boundary, exterior, '1'>(result);
+ }
+ else if (disjoint_found[0][1] == true)
+ {
+ update<interior, exterior, '1'>(result);
+ if (disjoint_linear_boundary_found[0])
+ {
+ update<boundary, exterior, '0'>(result);
+ }
+ }
+ else if (disjoint_found[0][0] == true)
+ {
+ update<interior, exterior, '0'>(result);
+ }
+
+ if (disjoint_found[1][2] == true)
+ {
+ update<exterior, interior, '2'>(result);
+ update<exterior, boundary, '1'>(result);
+ }
+ else if (disjoint_found[1][1] == true)
+ {
+ update<exterior, interior, '1'>(result);
+ if (disjoint_linear_boundary_found[1])
+ {
+ update<exterior, boundary, '0'>(result);
+ }
+ }
+ else if (disjoint_found[1][0] == true)
+ {
+ update<exterior, interior, '0'>(result);
+ }
+ }
+ }
+
+private:
+ template <typename Tuple, typename Geometry, typename Strategy>
+ static inline void merge_geometry(Tuple& tuple, Geometry const& geometry, Strategy const& strategy)
+ {
+ static const std::size_t index = kind_id<Geometry>::value;
+ typename boost::tuples::element<index, Tuple>::type temp_out;
+ geometry::union_(boost::get<index>(tuple), geometry, temp_out, strategy);
+ boost::get<index>(tuple) = std::move(temp_out);
+ }
+
+ template <typename Tuple, typename Strategy>
+ static inline void subtract_elements(Tuple& tuple, Strategy const& strategy)
+ {
+ if (! geometry::is_empty(boost::get<1>(tuple)))
+ {
+ if (! geometry::is_empty(boost::get<2>(tuple)))
+ {
+ typename boost::tuples::element<1, Tuple>::type mls;
+ geometry::difference(boost::get<1>(tuple), boost::get<2>(tuple), mls, strategy);
+ boost::get<1>(tuple) = std::move(mls);
+ }
+ }
+ if (! geometry::is_empty(boost::get<0>(tuple)))
+ {
+ if (! geometry::is_empty(boost::get<2>(tuple)))
+ {
+ typename boost::tuples::element<0, Tuple>::type mpt;
+ geometry::difference(boost::get<0>(tuple), boost::get<2>(tuple), mpt, strategy);
+ boost::get<0>(tuple) = std::move(mpt);
+ }
+ if (! geometry::is_empty(boost::get<1>(tuple)))
+ {
+ typename boost::tuples::element<0, Tuple>::type mpt;
+ geometry::difference(boost::get<0>(tuple), boost::get<1>(tuple), mpt, strategy);
+ boost::get<0>(tuple) = std::move(mpt);
+ }
+ }
+ }
+
+ template
+ <
+ typename Geometry, typename Strategy,
+ std::enable_if_t<util::is_linear<Geometry>::value, int> = 0
+ >
+ static inline bool has_linear_boundary(Geometry const& geometry, Strategy const& strategy)
+ {
+ topology_check<Geometry, Strategy> tc(geometry, strategy);
+ return tc.has_boundary();
+ }
+
+ template
+ <
+ typename Geometry, typename Strategy,
+ std::enable_if_t<! util::is_linear<Geometry>::value, int> = 0
+ >
+ static inline bool has_linear_boundary(Geometry const& , Strategy const& )
+ {
+ return false;
+ }
+
+
+ template <typename Multi1, typename Multi2, typename Result, typename Strategy>
+ static inline void call_relate(Multi1 const& multi1, Multi2 const& multi2,
+ Result& result, Strategy const& strategy)
+ {
+ dispatch::relate
+ <
+ Multi1, Multi2
+ >::apply(multi1, multi2, result, strategy);
+ }
+
+ template <typename MLs, typename MPo, typename MLsBoundary, typename Result, typename Strategy>
+ static inline void call_relate_la(MLs const& mls, MPo const& mpo,
+ MLsBoundary const& mls_boundary,
+ Result& result, Strategy const& strategy)
+ {
+ linear_areal<MLs, MPo>::apply(mls, mpo, mls_boundary, result, strategy);
+ }
+
+ template <typename MPo, typename MLs, typename MLsBoundary, typename Result, typename Strategy>
+ static inline void call_relate_al(MPo const& mls, MLs const& mpo,
+ MLsBoundary const& mls_boundary,
+ Result& result, Strategy const& strategy)
+ {
+ areal_linear<MPo, MLs>::apply(mls, mpo, mls_boundary, result, strategy);
+ }
+
+ template <typename MLs1, typename MLs2, typename MLs1Boundary, typename MLs2Boundary, typename Result, typename Strategy>
+ static inline void call_relate_ll(MLs1 const& mls1, MLs2 const& mls2,
+ MLs1Boundary const& mls1_boundary,
+ MLs2Boundary const& mls2_boundary,
+ Result& result, Strategy const& strategy)
+ {
+ linear_linear<MLs1, MLs2>::apply(mls1, mls2, mls1_boundary, mls2_boundary,
+ result, strategy);
+ }
+
+
+};
+
+
+}} // namespace detail::relate
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+template <typename Geometry1, typename Geometry2>
+struct relate<Geometry1, Geometry2, geometry_collection_tag, geometry_collection_tag, -1, -1, false>
+ : detail::relate::gc_gc<Geometry1, Geometry2>
+{};
+
+
+template <typename Geometry1, typename Geometry2, typename Tag1, int TopDim1>
+struct relate<Geometry1, Geometry2, Tag1, geometry_collection_tag, TopDim1, -1, false>
+{
+ static const bool interruption_enabled = true;
+
+ template <typename Result, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Result & result,
+ Strategy const& strategy)
+ {
+ using gc1_view_t = detail::geometry_collection_view<Geometry1>;
+ relate<gc1_view_t, Geometry2>::apply(gc1_view_t(geometry1), geometry2, result, strategy);
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Tag2, int TopDim2>
+struct relate<Geometry1, Geometry2, geometry_collection_tag, Tag2, -1, TopDim2, false>
+{
+ static const bool interruption_enabled = true;
+
+ template <typename Result, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Result & result,
+ Strategy const& strategy)
+ {
+ using gc2_view_t = detail::geometry_collection_view<Geometry2>;
+ relate<Geometry1, gc2_view_t>::apply(geometry1, gc2_view_t(geometry2), result, strategy);
+ }
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_HPP
diff --git a/boost/geometry/algorithms/detail/relate/interface.hpp b/boost/geometry/algorithms/detail/relate/interface.hpp
index 801ad21db1..19568a870e 100644
--- a/boost/geometry/algorithms/detail/relate/interface.hpp
+++ b/boost/geometry/algorithms/detail/relate/interface.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013-2020.
-// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -17,16 +17,13 @@
#include <tuple>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
#include <boost/geometry/algorithms/detail/relate/de9im.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/topological_dimension.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
@@ -160,8 +157,8 @@ struct result_handler_type<Geometry1, Geometry2, util::type_sequence<StaticMasks
}} // namespace detail::relate
#endif // DOXYGEN_NO_DETAIL
-namespace resolve_strategy {
-
+namespace resolve_strategy
+{
template
<
@@ -217,7 +214,7 @@ struct relate<default_strategy, false>
Geometry1,
Geometry2
>::type strategy_type;
-
+
dispatch::relate
<
Geometry1,
@@ -228,9 +225,15 @@ struct relate<default_strategy, false>
} // resolve_strategy
-namespace resolve_variant {
+namespace resolve_dynamic
+{
-template <typename Geometry1, typename Geometry2>
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct relate
{
template <typename Mask, typename Strategy>
@@ -256,109 +259,73 @@ struct relate
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct relate<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct relate<Geometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Mask, typename Strategy>
- struct visitor : boost::static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Mask const& mask,
+ Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Mask const& m_mask;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2, Mask const& mask, Strategy const& strategy)
- : m_geometry2(geometry2), m_mask(mask), m_strategy(strategy) {}
-
- template <typename Geometry1>
- bool operator()(Geometry1 const& geometry1) const
+ bool result = false;
+ traits::visit<Geometry1>::apply([&](auto const& g1)
{
- return relate<Geometry1, Geometry2>
- ::apply(geometry1, m_geometry2, m_mask, m_strategy);
- }
- };
-
- template <typename Mask, typename Strategy>
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Mask const& mask,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Mask, Strategy>(geometry2, mask, strategy), geometry1);
+ result = relate
+ <
+ util::remove_cref_t<decltype(g1)>,
+ Geometry2
+ >::apply(g1, geometry2, mask, strategy);
+ }, geometry1);
+ return result;
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct relate<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct relate<Geometry1, Geometry2, Tag1, dynamic_geometry_tag>
{
template <typename Mask, typename Strategy>
- struct visitor : boost::static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Mask const& mask,
+ Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Mask const& m_mask;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1, Mask const& mask, Strategy const& strategy)
- : m_geometry1(geometry1), m_mask(mask), m_strategy(strategy) {}
-
- template <typename Geometry2>
- bool operator()(Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry2>::apply([&](auto const& g2)
{
- return relate<Geometry1, Geometry2>
- ::apply(m_geometry1, geometry2, m_mask, m_strategy);
- }
- };
-
- template <typename Mask, typename Strategy>
- static inline bool
- apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Mask const& mask,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Mask, Strategy>(geometry1, mask, strategy), geometry2);
+ result = relate
+ <
+ Geometry1,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(geometry1, g2, mask, strategy);
+ }, geometry2);
+ return result;
}
};
-template <
- BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)
->
-struct relate<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
->
+template <typename Geometry1, typename Geometry2>
+struct relate<Geometry1, Geometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Mask, typename Strategy>
- struct visitor : boost::static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Mask const& mask,
+ Strategy const& strategy)
{
- Mask const& m_mask;
- Strategy const& m_strategy;
-
- visitor(Mask const& mask, Strategy const& strategy)
- : m_mask(mask), m_strategy(strategy) {}
-
- template <typename Geometry1, typename Geometry2>
- bool operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry1, Geometry2>::apply([&](auto const& g1, auto const& g2)
{
- return relate<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, m_mask, m_strategy);
- }
- };
-
- template <typename Mask, typename Strategy>
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Mask const& mask,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Mask, Strategy>(mask, strategy), geometry1, geometry2);
+ result = relate
+ <
+ util::remove_cref_t<decltype(g1)>,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(g1, g2, mask, strategy);
+ }, geometry1, geometry2);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
\brief Checks relation between a pair of geometries defined by a mask.
@@ -382,7 +349,7 @@ inline bool relate(Geometry1 const& geometry1,
Mask const& mask,
Strategy const& strategy)
{
- return resolve_variant::relate
+ return resolve_dynamic::relate
<
Geometry1,
Geometry2
@@ -407,7 +374,7 @@ inline bool relate(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Mask const& mask)
{
- return resolve_variant::relate
+ return resolve_dynamic::relate
<
Geometry1,
Geometry2
diff --git a/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/boost/geometry/algorithms/detail/relate/linear_areal.hpp
index e32c4afcba..1e35e64fc5 100644
--- a/boost/geometry/algorithms/detail/relate/linear_areal.hpp
+++ b/boost/geometry/algorithms/detail/relate/linear_areal.hpp
@@ -1,10 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2021.
-// Modifications copyright (c) 2013-2021 Oracle and/or its affiliates.
-
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -34,6 +34,8 @@
#include <boost/geometry/algorithms/detail/relate/boundary_checker.hpp>
#include <boost/geometry/algorithms/detail/relate/follow_helpers.hpp>
+#include <boost/geometry/geometries/helper_geometry.hpp>
+
#include <boost/geometry/views/detail/closed_clockwise_view.hpp>
namespace boost { namespace geometry
@@ -51,7 +53,7 @@ template
<
typename Geometry2,
typename Result,
- typename PointInArealStrategy,
+ typename Strategy,
typename BoundaryChecker,
bool TransposeResult
>
@@ -60,11 +62,11 @@ class no_turns_la_linestring_pred
public:
no_turns_la_linestring_pred(Geometry2 const& geometry2,
Result & res,
- PointInArealStrategy const& point_in_areal_strategy,
+ Strategy const& strategy,
BoundaryChecker const& boundary_checker)
: m_geometry2(geometry2)
, m_result(res)
- , m_point_in_areal_strategy(point_in_areal_strategy)
+ , m_strategy(strategy)
, m_boundary_checker(boundary_checker)
, m_interrupt_flags(0)
{
@@ -93,7 +95,7 @@ public:
bool operator()(Linestring const& linestring)
{
std::size_t const count = boost::size(linestring);
-
+
// invalid input
if ( count < 2 )
{
@@ -110,7 +112,7 @@ public:
int const pig = detail::within::point_in_geometry(range::front(linestring),
m_geometry2,
- m_point_in_areal_strategy);
+ m_strategy);
//BOOST_GEOMETRY_ASSERT_MSG(pig != 0, "There should be no IPs");
if ( pig > 0 )
@@ -125,11 +127,9 @@ public:
}
// check if there is a boundary
- if ( ( m_interrupt_flags & 0xC ) != 0xC // if wasn't already set
- && ( m_boundary_checker.template
- is_endpoint_boundary<boundary_front>(range::front(linestring))
- || m_boundary_checker.template
- is_endpoint_boundary<boundary_back>(range::back(linestring)) ) )
+ if ((m_interrupt_flags & 0xC) != 0xC // if wasn't already set
+ && (m_boundary_checker.is_endpoint_boundary(range::front(linestring))
+ || m_boundary_checker.is_endpoint_boundary(range::back(linestring))))
{
if ( pig > 0 )
{
@@ -150,7 +150,7 @@ public:
private:
Geometry2 const& m_geometry2;
Result & m_result;
- PointInArealStrategy const& m_point_in_areal_strategy;
+ Strategy const& m_strategy;
BoundaryChecker const& m_boundary_checker;
unsigned m_interrupt_flags;
};
@@ -177,9 +177,9 @@ public:
// TODO:
// handle empty/invalid geometries in a different way than below?
- typedef typename geometry::point_type<Areal>::type point_type;
- point_type dummy;
- bool const ok = boost::geometry::point_on_border(dummy, areal);
+ using point_type = typename geometry::point_type<Areal>::type;
+ typename helper_geometry<point_type>::type pt;
+ bool const ok = geometry::point_on_border(pt, areal);
// TODO: for now ignore, later throw an exception?
if ( !ok )
@@ -189,7 +189,7 @@ public:
update<interior, exterior, '2', TransposeResult>(m_result);
update<boundary, exterior, '1', TransposeResult>(m_result);
-
+
return false;
}
@@ -198,6 +198,129 @@ private:
bool const interrupt;
};
+
+template <typename It, typename Strategy>
+inline It find_next_non_duplicated(It first, It current, It last, Strategy const& strategy)
+{
+ BOOST_GEOMETRY_ASSERT(current != last);
+
+ It it = current;
+ for (++it ; it != last ; ++it)
+ {
+ if (! equals::equals_point_point(*current, *it, strategy))
+ {
+ return it;
+ }
+ }
+
+ // if not found start from the beginning
+ for (it = first ; it != current ; ++it)
+ {
+ if (! equals::equals_point_point(*current, *it, strategy))
+ {
+ return it;
+ }
+ }
+
+ return current;
+}
+
+// calculate inside or outside based on side_calc
+// this is simplified version of a check from equal<>
+template
+<
+ typename Pi, typename Pj, typename Pk,
+ typename Qi, typename Qj, typename Qk,
+ typename Strategy
+>
+inline bool calculate_from_inside_sides(Pi const& pi, Pj const& pj, Pk const& pk,
+ Qi const& , Qj const& qj, Qk const& qk,
+ Strategy const& strategy)
+{
+ auto const side_strategy = strategy.side();
+
+ int const side_pk_p = side_strategy.apply(pi, pj, pk);
+ int const side_qk_p = side_strategy.apply(pi, pj, qk);
+ // If they turn to same side (not opposite sides)
+ if (! overlay::base_turn_handler::opposite(side_pk_p, side_qk_p))
+ {
+ int const side_pk_q2 = side_strategy.apply(qj, qk, pk);
+ return side_pk_q2 == -1;
+ }
+ else
+ {
+ return side_pk_p == -1;
+ }
+}
+
+// check if the passed turn's segment of Linear geometry arrived
+// from the inside or the outside of the Areal geometry
+template
+<
+ std::size_t OpId,
+ typename Geometry1, typename Geometry2,
+ typename Turn, typename Strategy
+>
+inline bool calculate_from_inside(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Turn const& turn,
+ Strategy const& strategy)
+{
+ static const std::size_t op_id = OpId;
+ static const std::size_t other_op_id = (OpId + 1) % 2;
+
+ if (turn.operations[op_id].position == overlay::position_front)
+ {
+ return false;
+ }
+
+ auto const& range1 = sub_range(geometry1, turn.operations[op_id].seg_id);
+
+ using range2_view = detail::closed_clockwise_view<typename ring_type<Geometry2>::type const>;
+ range2_view const range2(sub_range(geometry2, turn.operations[other_op_id].seg_id));
+
+ BOOST_GEOMETRY_ASSERT(boost::size(range1));
+ std::size_t const s2 = boost::size(range2);
+ BOOST_GEOMETRY_ASSERT(s2 > 2);
+ std::size_t const seg_count2 = s2 - 1;
+
+ std::size_t const p_seg_ij = static_cast<std::size_t>(turn.operations[op_id].seg_id.segment_index);
+ std::size_t const q_seg_ij = static_cast<std::size_t>(turn.operations[other_op_id].seg_id.segment_index);
+
+ BOOST_GEOMETRY_ASSERT(p_seg_ij + 1 < boost::size(range1));
+ BOOST_GEOMETRY_ASSERT(q_seg_ij + 1 < s2);
+
+ auto const& pi = range::at(range1, p_seg_ij);
+ auto const& qi = range::at(range2, q_seg_ij);
+ auto const& qj = range::at(range2, q_seg_ij + 1);
+
+ bool const is_ip_qj = equals::equals_point_point(turn.point, qj, strategy);
+ // TODO: test this!
+ // BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, pi));
+ // BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, qi));
+
+ if (is_ip_qj)
+ {
+ std::size_t const q_seg_jk = (q_seg_ij + 1) % seg_count2;
+ // TODO: the following function should return immediately, however the worst case complexity is O(N)
+ // It would be good to replace it with some O(1) mechanism
+ auto qk_it = find_next_non_duplicated(boost::begin(range2),
+ range::pos(range2, q_seg_jk),
+ boost::end(range2),
+ strategy);
+
+ // Calculate sides in a different point order for P and Q
+ // Will this sequence of points be always correct?
+ return calculate_from_inside_sides(qi, turn.point, pi, qi, qj, *qk_it, strategy);
+ }
+ else
+ {
+ // Calculate sides with different points for P and Q
+ return calculate_from_inside_sides(qi, turn.point, pi, qi, turn.point, qj, strategy);
+ }
+}
+
+
// The implementation of an algorithm calculating relate() for L/A
template <typename Geometry1, typename Geometry2, bool TransposeResult = false>
struct linear_areal
@@ -208,9 +331,6 @@ struct linear_areal
static const bool interruption_enabled = true;
- typedef typename geometry::point_type<Geometry1>::type point1_type;
- typedef typename geometry::point_type<Geometry2>::type point2_type;
-
template <typename Geom1, typename Geom2, typename Strategy>
struct multi_turn_info
: turns::get_turns<Geom1, Geom2>::template turn_info_type<Strategy>::type
@@ -228,45 +348,49 @@ struct linear_areal
typename turns::get_turns<Geom1, Geom2>::template turn_info_type<Strategy>::type
>
{};
-
+
template <typename Result, typename Strategy>
static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
Result & result,
Strategy const& strategy)
{
-// TODO: If Areal geometry may have infinite size, change the following line:
+ boundary_checker<Geometry1, Strategy> boundary_checker1(geometry1, strategy);
+ apply(geometry1, geometry2, boundary_checker1, result, strategy);
+ }
+
+ template <typename BoundaryChecker1, typename Result, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ BoundaryChecker1 const& boundary_checker1,
+ Result & result,
+ Strategy const& strategy)
+ {
+ // TODO: If Areal geometry may have infinite size, change the following line:
- // The result should be FFFFFFFFF
- relate::set<exterior, exterior, result_dimension<Geometry2>::value, TransposeResult>(result);// FFFFFFFFd, d in [1,9] or T
+ update<exterior, exterior, result_dimension<Geometry2>::value, TransposeResult>(result);// FFFFFFFFd, d in [1,9] or T
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
+ {
return;
+ }
// get and analyse turns
- typedef typename turn_info_type<Geometry1, Geometry2, Strategy>::type turn_type;
+ using turn_type = typename turn_info_type<Geometry1, Geometry2, Strategy>::type;
std::vector<turn_type> turns;
interrupt_policy_linear_areal<Geometry2, Result> interrupt_policy(geometry2, result);
turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy, strategy);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
+ {
return;
-
- typedef typename Strategy::cs_tag cs_tag;
-
- typedef boundary_checker
- <
- Geometry1,
- Strategy
- > boundary_checker1_type;
- boundary_checker1_type boundary_checker1(geometry1, strategy);
+ }
no_turns_la_linestring_pred
<
Geometry2,
Result,
Strategy,
- boundary_checker1_type,
+ BoundaryChecker1,
TransposeResult
> pred1(geometry2,
result,
@@ -274,24 +398,32 @@ struct linear_areal
boundary_checker1);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
+ {
return;
+ }
no_turns_la_areal_pred<Result, !TransposeResult> pred2(result);
for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
+ {
return;
-
+ }
+
if ( turns.empty() )
+ {
return;
+ }
// This is set here because in the case if empty Areal geometry were passed
// those shouldn't be set
- relate::set<exterior, interior, '2', TransposeResult>(result);// FFFFFF2Fd
+ update<exterior, interior, '2', TransposeResult>(result);// FFFFFF2Fd
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
+ {
return;
+ }
{
- sort_dispatch<cs_tag>(turns.begin(), turns.end(), util::is_multi<Geometry2>());
+ sort_dispatch(turns.begin(), turns.end(), strategy, util::is_multi<Geometry2>());
turns_analyser<turn_type> analyser;
analyse_each_turn(result, analyser,
@@ -301,13 +433,15 @@ struct linear_areal
strategy);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
+ {
return;
+ }
}
// If 'c' (insersection_boundary) was not found we know that any Ls isn't equal to one of the Rings
if ( !interrupt_policy.is_boundary_found )
{
- relate::set<exterior, boundary, '1', TransposeResult>(result);
+ update<exterior, boundary, '1', TransposeResult>(result);
}
// Don't calculate it if it's required
else if ( may_update<exterior, boundary, '1', TransposeResult>(result) )
@@ -323,12 +457,9 @@ struct linear_areal
// sort by multi_index and rind_index
std::sort(turns.begin(), turns.end(), less_ring());
- typedef typename std::vector<turn_type>::iterator turn_iterator;
-
- turn_iterator it = turns.begin();
segment_identifier * prev_seg_id_ptr = NULL;
// for each ring
- for ( ; it != turns.end() ; )
+ for (auto it = turns.begin() ; it != turns.end() ; )
{
// it's the next single geometry
if ( prev_seg_id_ptr == NULL
@@ -338,7 +469,7 @@ struct linear_areal
if ( it->operations[1].seg_id.ring_index > -1 )
{
// we can be sure that the exterior overlaps the boundary
- relate::set<exterior, boundary, '1', TransposeResult>(result);
+ update<exterior, boundary, '1', TransposeResult>(result);
break;
}
// if there was some previous ring
@@ -346,14 +477,14 @@ struct linear_areal
{
signed_size_type const next_ring_index = prev_seg_id_ptr->ring_index + 1;
BOOST_GEOMETRY_ASSERT(next_ring_index >= 0);
-
+
// if one of the last rings of previous single geometry was ommited
if ( static_cast<std::size_t>(next_ring_index)
< geometry::num_interior_rings(
single_geometry(geometry2, *prev_seg_id_ptr)) )
{
// we can be sure that the exterior overlaps the boundary
- relate::set<exterior, boundary, '1', TransposeResult>(result);
+ update<exterior, boundary, '1', TransposeResult>(result);
break;
}
}
@@ -366,7 +497,7 @@ struct linear_areal
&& prev_seg_id_ptr->ring_index + 1 < it->operations[1].seg_id.ring_index )
{
// we can be sure that the exterior overlaps the boundary
- relate::set<exterior, boundary, '1', TransposeResult>(result);
+ update<exterior, boundary, '1', TransposeResult>(result);
break;
}
}
@@ -375,25 +506,25 @@ struct linear_areal
// find the next ring first iterator and check if the analysis should be performed
has_boundary_intersection has_boundary_inters;
- turn_iterator next = find_next_ring(it, turns.end(), has_boundary_inters);
+ auto next = find_next_ring(it, turns.end(), has_boundary_inters);
// if there is no 1d overlap with the boundary
if ( !has_boundary_inters.result )
{
// we can be sure that the exterior overlaps the boundary
- relate::set<exterior, boundary, '1', TransposeResult>(result);
+ update<exterior, boundary, '1', TransposeResult>(result);
break;
}
// else there is 1d overlap with the boundary so we must analyse the boundary
else
{
// u, c
- typedef turns::less<1, turns::less_op_areal_linear<1>, cs_tag> less;
- std::sort(it, next, less());
+ using less_t = turns::less<1, turns::less_op_areal_linear<1>, Strategy>;
+ std::sort(it, next, less_t());
// analyse
areal_boundary_analyser<turn_type> analyser;
- for ( turn_iterator rit = it ; rit != next ; ++rit )
+ for (auto rit = it ; rit != next ; ++rit)
{
// if the analyser requests, break the search
if ( !analyser.apply(it, rit, next, strategy) )
@@ -404,7 +535,7 @@ struct linear_areal
if ( analyser.is_union_detected )
{
// we can be sure that the boundary of Areal overlaps the exterior of Linear
- relate::set<exterior, boundary, '1', TransposeResult>(result);
+ update<exterior, boundary, '1', TransposeResult>(result);
break;
}
}
@@ -424,7 +555,7 @@ struct linear_areal
single_geometry(geometry2, *prev_seg_id_ptr)) )
{
// we can be sure that the exterior overlaps the boundary
- relate::set<exterior, boundary, '1', TransposeResult>(result);
+ update<exterior, boundary, '1', TransposeResult>(result);
}
}
}
@@ -434,7 +565,9 @@ struct linear_areal
static void for_each_equal_range(It first, It last, Pred pred, Comp comp)
{
if ( first == last )
+ {
return;
+ }
It first_equal = first;
It prev = first;
@@ -445,9 +578,11 @@ struct linear_areal
pred(first_equal, first);
first_equal = first;
}
-
+
if ( first == last )
+ {
break;
+ }
}
}
@@ -516,12 +651,13 @@ struct linear_areal
}
};
- template <typename CSTag, typename TurnIt>
- static void sort_dispatch(TurnIt first, TurnIt last, std::true_type const& /*is_multi*/)
+ template <typename TurnIt, typename Strategy>
+ static void sort_dispatch(TurnIt first, TurnIt last, Strategy const& ,
+ std::true_type const& /*is_multi*/)
{
// sort turns by Linear seg_id, then by fraction, then by other multi_index
- typedef turns::less<0, turns::less_other_multi_index<0>, CSTag> less;
- std::sort(first, last, less());
+ using less_t = turns::less<0, turns::less_other_multi_index<0>, Strategy>;
+ std::sort(first, last, less_t());
// For the same IP and multi_index - the same other's single geometry
// set priorities as the least operation found for the whole single geometry
@@ -534,22 +670,23 @@ struct linear_areal
// When priorities for single geometries are set now sort turns for the same IP
// if multi_index is the same sort them according to the single-less
// else use priority of the whole single-geometry set earlier
- typedef turns::less<0, turns::less_op_linear_areal_single<0>, CSTag> single_less;
+ using single_less_t = turns::less<0, turns::less_op_linear_areal_single<0>, Strategy>;
for_each_equal_range(first, last,
- sort_turns_group<single_less>(),
+ sort_turns_group<single_less_t>(),
same_ip());
}
- template <typename CSTag, typename TurnIt>
- static void sort_dispatch(TurnIt first, TurnIt last, std::false_type const& /*is_multi*/)
+ template <typename TurnIt, typename Strategy>
+ static void sort_dispatch(TurnIt first, TurnIt last, Strategy const& ,
+ std::false_type const& /*is_multi*/)
{
// sort turns by Linear seg_id, then by fraction, then
// for same ring id: x, u, i, c
// for different ring id: c, i, u, x
- typedef turns::less<0, turns::less_op_linear_areal_single<0>, CSTag> less;
- std::sort(first, last, less());
+ using less_t = turns::less<0, turns::less_op_linear_areal_single<0>, Strategy>;
+ std::sort(first, last, less_t());
}
-
+
// interrupt policy which may be passed to get_turns to interrupt the analysis
// based on the info in the passed result/mask
@@ -569,9 +706,7 @@ struct linear_areal
template <typename Range>
inline bool apply(Range const& turns)
{
- typedef typename boost::range_iterator<Range const>::type iterator;
-
- for (iterator it = boost::begin(turns) ; it != boost::end(turns) ; ++it)
+ for (auto it = boost::begin(turns) ; it != boost::end(turns) ; ++it)
{
if ( it->operations[0].operation == overlay::operation_intersection )
{
@@ -619,39 +754,6 @@ struct linear_areal
static const std::size_t op_id = 0;
static const std::size_t other_op_id = 1;
- template <typename TurnPointCSTag, typename PointP, typename PointQ,
- typename Strategy,
- typename Pi = PointP, typename Pj = PointP, typename Pk = PointP,
- typename Qi = PointQ, typename Qj = PointQ, typename Qk = PointQ
- >
- struct la_side_calculator
- {
- typedef decltype(std::declval<Strategy>().side()) side_strategy_type;
-
- inline la_side_calculator(Pi const& pi, Pj const& pj, Pk const& pk,
- Qi const& qi, Qj const& qj, Qk const& qk,
- Strategy const& strategy)
- : m_pi(pi), m_pj(pj), m_pk(pk)
- , m_qi(qi), m_qj(qj), m_qk(qk)
- , m_side_strategy(strategy.side())
- {}
-
- inline int pk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_pk); }
- inline int qk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_qk); }
- inline int pk_wrt_q2() const { return m_side_strategy.apply(m_qj, m_qk, m_pk); }
-
- private :
- Pi const& m_pi;
- Pj const& m_pj;
- Pk const& m_pk;
- Qi const& m_qi;
- Qj const& m_qj;
- Qk const& m_qk;
-
- side_strategy_type m_side_strategy;
- };
-
-
public:
turns_analyser()
: m_previous_turn_ptr(NULL)
@@ -705,7 +807,7 @@ struct linear_areal
strategy) )
{
m_exit_watcher.reset_detected_exit();
-
+
update<interior, exterior, '1', TransposeResult>(res);
// next single geometry
@@ -714,9 +816,8 @@ struct linear_areal
// NOTE: similar code is in the post-last-ip-apply()
segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
- bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(
- range::back(sub_range(geometry, prev_seg_id)),
- boundary_checker);
+ bool const prev_back_b = boundary_checker.is_endpoint_boundary(
+ range::back(sub_range(geometry, prev_seg_id)));
// if there is a boundary on the last point
if ( prev_back_b )
@@ -790,7 +891,7 @@ struct linear_areal
// TODO: THIS IS POTENTIALLY ERROREOUS!
// THIS ALGORITHM DEPENDS ON SOME SPECIFIC SEQUENCE OF OPERATIONS
// IT WOULD GIVE WRONG RESULTS E.G.
-// IN THE CASE OF SELF-TOUCHING POINT WHEN 'i' WOULD BE BEFORE 'u'
+// IN THE CASE OF SELF-TOUCHING POINT WHEN 'i' WOULD BE BEFORE 'u'
// handle the interior overlap
if ( m_interior_detected )
@@ -809,9 +910,8 @@ struct linear_areal
{
segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
- bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(
- range::back(sub_range(geometry, prev_seg_id)),
- boundary_checker);
+ bool const prev_back_b = boundary_checker.is_endpoint_boundary(
+ range::back(sub_range(geometry, prev_seg_id)));
// if there is a boundary on the last point
if ( prev_back_b )
@@ -890,11 +990,8 @@ struct linear_areal
update<interior, boundary, '1', TransposeResult>(res);
}
- bool const this_b
- = is_ip_on_boundary<boundary_front>(it->point,
- it->operations[op_id],
- boundary_checker,
- seg_id);
+ bool const this_b = is_ip_on_boundary(it->point, it->operations[op_id],
+ boundary_checker);
// going inside on boundary point
if ( this_b )
{
@@ -911,11 +1008,11 @@ struct linear_areal
&& it->operations[op_id].position != overlay::position_front )
{
// TODO: calculate_from_inside() is only needed if the current Linestring is not closed
- bool const from_inside = first_point
- && calculate_from_inside(geometry,
- other_geometry,
- *it,
- strategy);
+ bool const from_inside =
+ first_point && calculate_from_inside<op_id>(geometry,
+ other_geometry,
+ *it,
+ strategy);
if ( from_inside )
update<interior, interior, '1', TransposeResult>(res);
@@ -925,9 +1022,8 @@ struct linear_areal
// if it's the first IP then the first point is outside
if ( first_point )
{
- bool const front_b = is_endpoint_on_boundary<boundary_front>(
- range::front(sub_range(geometry, seg_id)),
- boundary_checker);
+ bool const front_b = boundary_checker.is_endpoint_boundary(
+ range::front(sub_range(geometry, seg_id)));
// if there is a boundary on the first point
if ( front_b )
@@ -955,7 +1051,7 @@ struct linear_areal
// TODO: is this condition ok?
// TODO: move it into the exit_watcher?
&& m_exit_watcher.get_exit_operation() == overlay::operation_none;
-
+
if ( op == overlay::operation_union )
{
if ( m_boundary_counter > 0 && it->operations[op_id].is_collinear )
@@ -974,7 +1070,7 @@ struct linear_areal
{
// check if this is indeed the boundary point
// NOTE: is_ip_on_boundary<>() should be called here but the result will be the same
- if ( is_endpoint_on_boundary<boundary_back>(it->point, boundary_checker) )
+ if (boundary_checker.is_endpoint_boundary(it->point))
{
update<boundary, boundary, '0', TransposeResult>(res);
}
@@ -989,10 +1085,8 @@ struct linear_areal
// we're outside or inside and this is the first turn
else
{
- bool const this_b = is_ip_on_boundary<boundary_any>(it->point,
- it->operations[op_id],
- boundary_checker,
- seg_id);
+ bool const this_b = is_ip_on_boundary(it->point, it->operations[op_id],
+ boundary_checker);
// if current IP is on boundary of the geometry
if ( this_b )
{
@@ -1012,11 +1106,11 @@ struct linear_areal
// For LS/MultiPolygon multiple x/u turns may be generated
// the first checked Polygon may be the one which LS is outside for.
bool const first_point = first_in_range || m_first_from_unknown;
- bool const first_from_inside = first_point
- && calculate_from_inside(geometry,
- other_geometry,
- *it,
- strategy);
+ bool const first_from_inside =
+ first_point && calculate_from_inside<op_id>(geometry,
+ other_geometry,
+ *it,
+ strategy);
if ( first_from_inside )
{
update<interior, interior, '1', TransposeResult>(res);
@@ -1044,9 +1138,8 @@ struct linear_areal
// first IP on the last segment point - this means that the first point is outside or inside
if ( first_point && ( !this_b || op_blocked ) )
{
- bool const front_b = is_endpoint_on_boundary<boundary_front>(
- range::front(sub_range(geometry, seg_id)),
- boundary_checker);
+ bool const front_b = boundary_checker.is_endpoint_boundary(
+ range::front(sub_range(geometry, seg_id)));
// if there is a boundary on the first point
if ( front_b )
@@ -1135,9 +1228,8 @@ struct linear_areal
segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
- bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(
- range::back(sub_range(geometry, prev_seg_id)),
- boundary_checker);
+ bool const prev_back_b = boundary_checker.is_endpoint_boundary(
+ range::back(sub_range(geometry, prev_seg_id)));
// if there is a boundary on the last point
if ( prev_back_b )
@@ -1158,9 +1250,8 @@ struct linear_areal
segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
- bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(
- range::back(sub_range(geometry, prev_seg_id)),
- boundary_checker);
+ bool const prev_back_b = boundary_checker.is_endpoint_boundary(
+ range::back(sub_range(geometry, prev_seg_id)));
// if there is a boundary on the last point
if ( prev_back_b )
@@ -1184,9 +1275,8 @@ struct linear_areal
segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
- bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(
- range::back(sub_range(geometry, prev_seg_id)),
- boundary_checker);
+ bool const prev_back_b = boundary_checker.is_endpoint_boundary(
+ range::back(sub_range(geometry, prev_seg_id)));
// if there is a boundary on the last point
if ( prev_back_b )
@@ -1202,120 +1292,6 @@ struct linear_areal
m_first_from_unknown_boundary_detected = false;
}
- // check if the passed turn's segment of Linear geometry arrived
- // from the inside or the outside of the Areal geometry
- template <typename Turn, typename Strategy>
- static inline bool calculate_from_inside(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Turn const& turn,
- Strategy const& strategy)
- {
- typedef typename cs_tag<typename Turn::point_type>::type cs_tag;
-
- if ( turn.operations[op_id].position == overlay::position_front )
- return false;
-
- typename sub_range_return_type<Geometry1 const>::type
- range1 = sub_range(geometry1, turn.operations[op_id].seg_id);
-
- using range2_view = detail::closed_clockwise_view<typename ring_type<Geometry2>::type const>;
- using range2_iterator = typename boost::range_iterator<range2_view const>::type;
- range2_view const range2(sub_range(geometry2, turn.operations[other_op_id].seg_id));
-
- BOOST_GEOMETRY_ASSERT(boost::size(range1));
- std::size_t const s2 = boost::size(range2);
- BOOST_GEOMETRY_ASSERT(s2 > 2);
- std::size_t const seg_count2 = s2 - 1;
-
- std::size_t const p_seg_ij = static_cast<std::size_t>(turn.operations[op_id].seg_id.segment_index);
- std::size_t const q_seg_ij = static_cast<std::size_t>(turn.operations[other_op_id].seg_id.segment_index);
-
- BOOST_GEOMETRY_ASSERT(p_seg_ij + 1 < boost::size(range1));
- BOOST_GEOMETRY_ASSERT(q_seg_ij + 1 < s2);
-
- point1_type const& pi = range::at(range1, p_seg_ij);
- point2_type const& qi = range::at(range2, q_seg_ij);
- point2_type const& qj = range::at(range2, q_seg_ij + 1);
- point1_type qi_conv;
- geometry::convert(qi, qi_conv);
- bool const is_ip_qj = equals::equals_point_point(turn.point, qj, strategy);
-// TODO: test this!
-// BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, pi));
-// BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, qi));
- point1_type new_pj;
- geometry::convert(turn.point, new_pj);
-
- if ( is_ip_qj )
- {
- std::size_t const q_seg_jk = (q_seg_ij + 1) % seg_count2;
-// TODO: the following function should return immediately, however the worst case complexity is O(N)
-// It would be good to replace it with some O(1) mechanism
- range2_iterator qk_it = find_next_non_duplicated(boost::begin(range2),
- range::pos(range2, q_seg_jk),
- boost::end(range2),
- strategy);
-
- // Will this sequence of points be always correct?
- la_side_calculator<cs_tag, point1_type, point2_type, Strategy>
- side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it, strategy);
-
- return calculate_from_inside_sides(side_calc);
- }
- else
- {
- point2_type new_qj;
- geometry::convert(turn.point, new_qj);
-
- la_side_calculator<cs_tag, point1_type, point2_type, Strategy>
- side_calc(qi_conv, new_pj, pi, qi, new_qj, qj, strategy);
-
- return calculate_from_inside_sides(side_calc);
- }
- }
-
- template <typename It, typename Strategy>
- static inline It find_next_non_duplicated(It first, It current, It last,
- Strategy const& strategy)
- {
- BOOST_GEOMETRY_ASSERT( current != last );
-
- It it = current;
-
- for ( ++it ; it != last ; ++it )
- {
- if ( !equals::equals_point_point(*current, *it, strategy) )
- return it;
- }
-
- // if not found start from the beginning
- for ( it = first ; it != current ; ++it )
- {
- if ( !equals::equals_point_point(*current, *it, strategy) )
- return it;
- }
-
- return current;
- }
-
- // calculate inside or outside based on side_calc
- // this is simplified version of a check from equal<>
- template <typename SideCalc>
- static inline bool calculate_from_inside_sides(SideCalc const& side_calc)
- {
- int const side_pk_p = side_calc.pk_wrt_p1();
- int const side_qk_p = side_calc.qk_wrt_p1();
- // If they turn to same side (not opposite sides)
- if (! overlay::base_turn_handler::opposite(side_pk_p, side_qk_p))
- {
- int const side_pk_q2 = side_calc.pk_wrt_q2();
- return side_pk_q2 == -1;
- }
- else
- {
- return side_pk_p == -1;
- }
- }
-
private:
exit_watcher<TurnInfo, op_id> m_exit_watcher;
segment_watcher<same_single> m_seg_watcher;
@@ -1346,7 +1322,9 @@ struct linear_areal
Strategy const& strategy)
{
if ( first == last )
+ {
return;
+ }
for ( TurnIt it = first ; it != last ; ++it )
{
@@ -1356,7 +1334,9 @@ struct linear_areal
strategy);
if ( BOOST_GEOMETRY_CONDITION( res.interrupt ) )
+ {
return;
+ }
}
analyser.apply(res, first, last,
@@ -1472,7 +1452,7 @@ struct linear_areal
else
{
return false;
- }
+ }
}
bool is_union_detected;
@@ -1496,6 +1476,15 @@ struct areal_linear
{
linear_areal_type::apply(geometry2, geometry1, result, strategy);
}
+
+ template <typename BoundaryChecker2, typename Result, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ BoundaryChecker2 const& boundary_checker2,
+ Result & result,
+ Strategy const& strategy)
+ {
+ linear_areal_type::apply(geometry2, geometry1, boundary_checker2, result, strategy);
+ }
};
}} // namespace detail::relate
diff --git a/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/boost/geometry/algorithms/detail/relate/linear_linear.hpp
index fa46db2459..8a326265af 100644
--- a/boost/geometry/algorithms/detail/relate/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/relate/linear_linear.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018, 2019.
-// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -33,6 +33,8 @@
#include <boost/geometry/algorithms/detail/relate/boundary_checker.hpp>
#include <boost/geometry/algorithms/detail/relate/follow_helpers.hpp>
+#include <boost/geometry/geometries/helper_geometry.hpp>
+
namespace boost { namespace geometry
{
@@ -68,7 +70,7 @@ public:
}
std::size_t const count = boost::size(linestring);
-
+
// invalid input
if ( count < 2 )
{
@@ -91,11 +93,9 @@ public:
m_flags |= 1;
// check if there is a boundary
- if ( m_flags < 2
- && ( m_boundary_checker.template
- is_endpoint_boundary<boundary_front>(range::front(linestring))
- || m_boundary_checker.template
- is_endpoint_boundary<boundary_back>(range::back(linestring)) ) )
+ if (m_flags < 2
+ && (m_boundary_checker.is_endpoint_boundary(range::front(linestring))
+ || m_boundary_checker.is_endpoint_boundary(range::back(linestring))))
{
update<boundary, exterior, '0', TransposeResult>(m_result);
m_flags |= 2;
@@ -117,26 +117,33 @@ struct linear_linear
{
static const bool interruption_enabled = true;
- typedef typename geometry::point_type<Geometry1>::type point1_type;
- typedef typename geometry::point_type<Geometry2>::type point2_type;
-
template <typename Result, typename Strategy>
static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
Result & result,
Strategy const& strategy)
{
- typedef typename Strategy::cs_tag cs_tag;
+ boundary_checker<Geometry1, Strategy> boundary_checker1(geometry1, strategy);
+ boundary_checker<Geometry2, Strategy> boundary_checker2(geometry2, strategy);
+ apply(geometry1, geometry2, boundary_checker1, boundary_checker2, result, strategy);
+ }
+ template <typename BoundaryChecker1, typename BoundaryChecker2, typename Result, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ BoundaryChecker1 const& boundary_checker1,
+ BoundaryChecker2 const& boundary_checker2,
+ Result & result,
+ Strategy const& strategy)
+ {
// The result should be FFFFFFFFF
- relate::set<exterior, exterior, result_dimension<Geometry1>::value>(result);// FFFFFFFFd, d in [1,9] or T
+ update<exterior, exterior, result_dimension<Geometry1>::value>(result);// FFFFFFFFd, d in [1,9] or T
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
// get and analyse turns
- typedef typename turns::get_turns
+ using turn_type = typename turns::get_turns
<
Geometry1, Geometry2
- >::template turn_info_type<Strategy>::type turn_type;
+ >::template turn_info_type<Strategy>::type;
std::vector<turn_type> turns;
interrupt_policy_linear_linear<Result> interrupt_policy(result);
@@ -151,20 +158,16 @@ struct linear_linear
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
- typedef boundary_checker<Geometry1, Strategy> boundary_checker1_type;
- boundary_checker1_type boundary_checker1(geometry1, strategy);
- disjoint_linestring_pred<Result, boundary_checker1_type, false> pred1(result, boundary_checker1);
+ disjoint_linestring_pred<Result, BoundaryChecker1, false> pred1(result, boundary_checker1);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
- typedef boundary_checker<Geometry2, Strategy> boundary_checker2_type;
- boundary_checker2_type boundary_checker2(geometry2, strategy);
- disjoint_linestring_pred<Result, boundary_checker2_type, true> pred2(result, boundary_checker2);
+ disjoint_linestring_pred<Result, BoundaryChecker2, true> pred2(result, boundary_checker2);
for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
-
+
if ( turns.empty() )
return;
@@ -178,8 +181,8 @@ struct linear_linear
|| may_update<boundary, boundary, '0'>(result)
|| may_update<boundary, exterior, '0'>(result) )
{
- typedef turns::less<0, turns::less_op_linear_linear<0>, cs_tag> less;
- std::sort(turns.begin(), turns.end(), less());
+ using less_t = turns::less<0, turns::less_op_linear_linear<0>, Strategy>;
+ std::sort(turns.begin(), turns.end(), less_t());
turns_analyser<turn_type, 0> analyser;
analyse_each_turn(result, analyser,
@@ -190,7 +193,7 @@ struct linear_linear
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
-
+
if ( may_update<interior, interior, '1', true>(result)
|| may_update<interior, boundary, '0', true>(result)
|| may_update<interior, exterior, '1', true>(result)
@@ -198,8 +201,8 @@ struct linear_linear
|| may_update<boundary, boundary, '0', true>(result)
|| may_update<boundary, exterior, '0', true>(result) )
{
- typedef turns::less<1, turns::less_op_linear_linear<1>, cs_tag> less;
- std::sort(turns.begin(), turns.end(), less());
+ using less_t = turns::less<1, turns::less_op_linear_linear<1>, Strategy>;
+ std::sort(turns.begin(), turns.end(), less_t());
turns_analyser<turn_type, 1> analyser;
analyse_each_turn(result, analyser,
@@ -224,9 +227,7 @@ struct linear_linear
template <typename Range>
inline bool apply(Range const& turns)
{
- typedef typename boost::range_iterator<Range const>::type iterator;
-
- for (iterator it = boost::begin(turns) ; it != boost::end(turns) ; ++it)
+ for (auto it = boost::begin(turns) ; it != boost::end(turns) ; ++it)
{
if ( it->operations[0].operation == overlay::operation_intersection
|| it->operations[1].operation == overlay::operation_intersection )
@@ -285,7 +286,6 @@ struct linear_linear
overlay::operation_type const op = it->operations[op_id].operation;
segment_identifier const& seg_id = it->operations[op_id].seg_id;
- segment_identifier const& other_id = it->operations[other_op_id].seg_id;
bool const first_in_range = m_seg_watcher.update(seg_id);
@@ -296,8 +296,8 @@ struct linear_linear
// degenerated turn
if ( op == overlay::operation_continue
&& it->method == overlay::method_none
- && m_exit_watcher.is_outside(*it)
- /*&& ( m_exit_watcher.get_exit_operation() == overlay::operation_none
+ && m_exit_watcher.is_outside(*it)
+ /*&& ( m_exit_watcher.get_exit_operation() == overlay::operation_none
|| ! turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it) )*/ )
{
// TODO: rewrite the above condition
@@ -336,7 +336,7 @@ struct linear_linear
boundary_checker.strategy()) )
{
m_exit_watcher.reset_detected_exit();
-
+
// not the last IP
update<interior, exterior, '1', transpose_result>(res);
}
@@ -374,20 +374,16 @@ struct linear_linear
update<interior, interior, '1', transpose_result>(res);
bool const this_b = it->operations[op_id].position == overlay::position_front // ignore spikes!
- && is_ip_on_boundary<boundary_front>(it->point,
- it->operations[op_id],
- boundary_checker,
- seg_id);
+ && is_ip_on_boundary(it->point, it->operations[op_id],
+ boundary_checker);
// going inside on boundary point
// may be front only
if ( this_b )
{
// may be front and back
- bool const other_b = is_ip_on_boundary<boundary_any>(it->point,
- it->operations[other_op_id],
- other_boundary_checker,
- other_id);
+ bool const other_b = is_ip_on_boundary(it->point, it->operations[other_op_id],
+ other_boundary_checker);
// it's also the boundary of the other geometry
if ( other_b )
@@ -413,9 +409,8 @@ struct linear_linear
// if it's the first IP then the first point is outside
if ( first_in_range )
{
- bool const front_b = is_endpoint_on_boundary<boundary_front>(
- range::front(sub_range(geometry, seg_id)),
- boundary_checker);
+ bool const front_b = boundary_checker.is_endpoint_boundary(
+ range::front(sub_range(geometry, seg_id)));
// if there is a boundary on the first point
if ( front_b )
@@ -461,13 +456,12 @@ struct linear_linear
{
// check if this is indeed the boundary point
// NOTE: is_ip_on_boundary<>() should be called here but the result will be the same
- if ( is_endpoint_on_boundary<boundary_back>(it->point, boundary_checker) )
+ if (boundary_checker.is_endpoint_boundary(it->point))
{
// may be front and back
- bool const other_b = is_ip_on_boundary<boundary_any>(it->point,
- it->operations[other_op_id],
- other_boundary_checker,
- other_id);
+ bool const other_b = is_ip_on_boundary(it->point,
+ it->operations[other_op_id],
+ other_boundary_checker);
// it's also the boundary of the other geometry
if ( other_b )
{
@@ -501,9 +495,8 @@ struct linear_linear
// it's the first point in range
if ( first_in_range )
{
- bool const front_b = is_endpoint_on_boundary<boundary_front>(
- range::front(sub_range(geometry, seg_id)),
- boundary_checker);
+ bool const front_b = boundary_checker.is_endpoint_boundary(
+ range::front(sub_range(geometry, seg_id)));
// if there is a boundary on the first point
if ( front_b )
@@ -515,16 +508,14 @@ struct linear_linear
// method other than crosses, check more conditions
else
{
- bool const this_b = is_ip_on_boundary<boundary_any>(it->point,
- it->operations[op_id],
- boundary_checker,
- seg_id);
-
- bool const other_b = is_ip_on_boundary<boundary_any>(it->point,
- it->operations[other_op_id],
- other_boundary_checker,
- other_id);
-
+ bool const this_b = is_ip_on_boundary(it->point,
+ it->operations[op_id],
+ boundary_checker);
+
+ bool const other_b = is_ip_on_boundary(it->point,
+ it->operations[other_op_id],
+ other_boundary_checker);
+
// if current IP is on boundary of the geometry
if ( this_b )
{
@@ -560,9 +551,8 @@ struct linear_linear
&& ! m_collinear_spike_exit
/*&& !is_collinear*/ )
{
- bool const front_b = is_endpoint_on_boundary<boundary_front>(
- range::front(sub_range(geometry, seg_id)),
- boundary_checker);
+ bool const front_b = boundary_checker.is_endpoint_boundary(
+ range::front(sub_range(geometry, seg_id)));
// if there is a boundary on the first point
if ( front_b )
@@ -570,7 +560,7 @@ struct linear_linear
update<boundary, exterior, '0', transpose_result>(res);
}
}
-
+
}
}
}
@@ -613,15 +603,14 @@ struct linear_linear
turn_ptr = m_degenerated_turn_ptr;
else if ( m_previous_turn_ptr )
turn_ptr = m_previous_turn_ptr;
-
+
if ( turn_ptr )
{
segment_identifier const& prev_seg_id = turn_ptr->operations[op_id].seg_id;
//BOOST_GEOMETRY_ASSERT(!boost::empty(sub_range(geometry, prev_seg_id)));
- bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(
- range::back(sub_range(geometry, prev_seg_id)),
- boundary_checker);
+ bool const prev_back_b = boundary_checker.is_endpoint_boundary(
+ range::back(sub_range(geometry, prev_seg_id)));
// if there is a boundary on the last point
if ( prev_back_b )
@@ -659,19 +648,17 @@ struct linear_linear
OtherBoundaryChecker const& other_boundary_checker,
bool first_in_range)
{
- typename detail::single_geometry_return_type<Geometry const>::type
- ls1_ref = detail::single_geometry(geometry, turn.operations[op_id].seg_id);
- typename detail::single_geometry_return_type<OtherGeometry const>::type
- ls2_ref = detail::single_geometry(other_geometry, turn.operations[other_op_id].seg_id);
+ auto const& ls1 = detail::single_geometry(geometry, turn.operations[op_id].seg_id);
+ auto const& ls2 = detail::single_geometry(other_geometry, turn.operations[other_op_id].seg_id);
// only one of those should be true:
if ( turn.operations[op_id].position == overlay::position_front )
{
// valid, point-sized
- if ( boost::size(ls2_ref) == 2 )
+ if ( boost::size(ls2) == 2 )
{
- bool const front_b = is_endpoint_on_boundary<boundary_front>(turn.point, boundary_checker);
+ bool const front_b = boundary_checker.is_endpoint_boundary(turn.point);
if ( front_b )
{
@@ -691,11 +678,11 @@ struct linear_linear
else if ( turn.operations[op_id].position == overlay::position_back )
{
// valid, point-sized
- if ( boost::size(ls2_ref) == 2 )
+ if ( boost::size(ls2) == 2 )
{
update<interior, exterior, '1', transpose_result>(res);
- bool const back_b = is_endpoint_on_boundary<boundary_back>(turn.point, boundary_checker);
+ bool const back_b = boundary_checker.is_endpoint_boundary(turn.point);
if ( back_b )
{
@@ -708,9 +695,9 @@ struct linear_linear
if ( first_in_range )
{
- //BOOST_GEOMETRY_ASSERT(!boost::empty(ls1_ref));
- bool const front_b = is_endpoint_on_boundary<boundary_front>(
- range::front(ls1_ref), boundary_checker);
+ //BOOST_GEOMETRY_ASSERT(!boost::empty(ls1));
+ bool const front_b = boundary_checker.is_endpoint_boundary(
+ range::front(ls1));
if ( front_b )
{
update<boundary, exterior, '0', transpose_result>(res);
@@ -725,13 +712,13 @@ struct linear_linear
// here we don't know which one is degenerated
- bool const is_point1 = boost::size(ls1_ref) == 2
- && equals::equals_point_point(range::front(ls1_ref),
- range::back(ls1_ref),
+ bool const is_point1 = boost::size(ls1) == 2
+ && equals::equals_point_point(range::front(ls1),
+ range::back(ls1),
boundary_checker.strategy());
- bool const is_point2 = boost::size(ls2_ref) == 2
- && equals::equals_point_point(range::front(ls2_ref),
- range::back(ls2_ref),
+ bool const is_point2 = boost::size(ls2) == 2
+ && equals::equals_point_point(range::front(ls2),
+ range::back(ls2),
other_boundary_checker.strategy());
// if the second one is degenerated
@@ -741,9 +728,9 @@ struct linear_linear
if ( first_in_range )
{
- //BOOST_GEOMETRY_ASSERT(!boost::empty(ls1_ref));
- bool const front_b = is_endpoint_on_boundary<boundary_front>(
- range::front(ls1_ref), boundary_checker);
+ //BOOST_GEOMETRY_ASSERT(!boost::empty(ls1));
+ bool const front_b = boundary_checker.is_endpoint_boundary(
+ range::front(ls1));
if ( front_b )
{
update<boundary, exterior, '0', transpose_result>(res);
diff --git a/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp b/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp
index 7da7f2be5e..204a4fe22d 100644
--- a/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp
+++ b/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry
-// Copyright (c) 2017-2020 Oracle and/or its affiliates.
+// Copyright (c) 2014-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
// Use, modification and distribution is subject to the Boost Software License,
@@ -94,9 +95,8 @@ struct multi_point_geometry_eb<Geometry, linestring_tag>
template <typename Point, typename Strategy>
bool apply(Point const& boundary_point, Strategy const& strategy)
{
- if ( std::find_if(m_points.begin(), m_points.end(),
- find_pred<Point, Strategy>(boundary_point, strategy))
- == m_points.end() )
+ if ( std::none_of(m_points.begin(), m_points.end(),
+ find_pred<Point, Strategy>(boundary_point, strategy)))
{
m_boundary_found = true;
return false;
@@ -135,7 +135,7 @@ struct multi_point_geometry_eb<Geometry, multi_linestring_tag>
template <typename Point, typename Strategy>
bool apply(Point const& boundary_point, Strategy const&)
{
- typedef geometry::less<void, -1, typename Strategy::cs_tag> less_type;
+ typedef geometry::less<void, -1, Strategy> less_type;
if (! std::binary_search(m_points.begin(), m_points.end(),
boundary_point, less_type()) )
@@ -159,9 +159,9 @@ struct multi_point_geometry_eb<Geometry, multi_linestring_tag>
{
typedef typename boost::range_value<MultiPoint>::type point_type;
typedef std::vector<point_type> points_type;
- typedef geometry::less<void, -1, typename Strategy::cs_tag> less_type;
+ typedef geometry::less<void, -1, Strategy> less_type;
- points_type points(boost::begin(multi_point), boost::end(multi_point));
+ points_type points(boost::begin(multi_point), boost::end(multi_point));
std::sort(points.begin(), points.end(), less_type());
boundary_visitor<points_type> visitor(points);
@@ -184,13 +184,12 @@ struct multi_point_single_geometry
{
typedef typename point_type<SingleGeometry>::type point2_type;
typedef model::box<point2_type> box2_type;
-
+
box2_type box2;
geometry::envelope(single_geometry, box2, strategy);
geometry::detail::expand_by_epsilon(box2);
- typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
- for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
+ for (auto it = boost::begin(multi_point); it != boost::end(multi_point); ++it)
{
if (! (relate::may_update<interior, interior, '0', Transpose>(result)
|| relate::may_update<interior, boundary, '0', Transpose>(result)
@@ -202,7 +201,7 @@ struct multi_point_single_geometry
// The default strategy is enough for Point/Box
if (detail::disjoint::disjoint_point_box(*it, box2, strategy))
{
- relate::set<interior, exterior, '0', Transpose>(result);
+ update<interior, exterior, '0', Transpose>(result);
}
else
{
@@ -210,15 +209,15 @@ struct multi_point_single_geometry
if (in_val > 0) // within
{
- relate::set<interior, interior, '0', Transpose>(result);
+ update<interior, interior, '0', Transpose>(result);
}
else if (in_val == 0)
{
- relate::set<interior, boundary, '0', Transpose>(result);
+ update<interior, boundary, '0', Transpose>(result);
}
else // in_val < 0 - not within
{
- relate::set<interior, exterior, '0', Transpose>(result);
+ update<interior, exterior, '0', Transpose>(result);
}
}
@@ -240,7 +239,7 @@ struct multi_point_single_geometry
{
// TODO: this is not true if a linestring is degenerated to a point
// then the interior has topological dimension = 0, not 1
- relate::set<exterior, interior, tc_t::interior, Transpose>(result);
+ update<exterior, interior, tc_t::interior, Transpose>(result);
}
if ( relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result)
@@ -248,12 +247,12 @@ struct multi_point_single_geometry
{
if (multi_point_geometry_eb<SingleGeometry>::apply(multi_point, tc))
{
- relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
+ update<exterior, boundary, tc_t::boundary, Transpose>(result);
}
}
}
- relate::set<exterior, exterior, result_dimension<MultiPoint>::value, Transpose>(result);
+ update<exterior, exterior, result_dimension<MultiPoint>::value, Transpose>(result);
}
};
@@ -365,14 +364,18 @@ class multi_point_multi_geometry_ii_ib
if (in_val > 0) // within
{
- relate::set<interior, interior, '0', Transpose>(m_result);
+ update<interior, interior, '0', Transpose>(m_result);
}
else if (in_val == 0)
{
if (m_tc.check_boundary_point(point))
- relate::set<interior, boundary, '0', Transpose>(m_result);
+ {
+ update<interior, boundary, '0', Transpose>(m_result);
+ }
else
- relate::set<interior, interior, '0', Transpose>(m_result);
+ {
+ update<interior, interior, '0', Transpose>(m_result);
+ }
}
}
@@ -442,7 +445,6 @@ struct multi_point_multi_geometry_ii_ib_ie
typedef model::box<point2_type> box2_type;
typedef std::pair<box2_type, std::size_t> box_pair_type;
typedef std::vector<box_pair_type> boxes_type;
- typedef typename boxes_type::const_iterator boxes_iterator;
template <typename Result, typename Strategy>
static inline void apply(MultiPoint const& multi_point,
@@ -463,8 +465,7 @@ struct multi_point_multi_geometry_ii_ib_ie
rtree(boxes.begin(), boxes.end(),
index_parameters_type(index::rstar<4>(), strategy));
- typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
- for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
+ for (auto it = boost::begin(multi_point); it != boost::end(multi_point); ++it)
{
if (! (relate::may_update<interior, interior, '0', Transpose>(result)
|| relate::may_update<interior, boundary, '0', Transpose>(result)
@@ -479,24 +480,28 @@ struct multi_point_multi_geometry_ii_ib_ie
rtree.query(index::intersects(point), std::back_inserter(boxes_found));
bool found_ii_or_ib = false;
- for (boxes_iterator bi = boxes_found.begin() ; bi != boxes_found.end() ; ++bi)
+ for (auto const& box_found : boxes_found)
{
typename boost::range_value<MultiGeometry>::type const&
- single = range::at(multi_geometry, bi->second);
+ single = range::at(multi_geometry, box_found.second);
int in_val = detail::within::point_in_geometry(point, single, strategy);
if (in_val > 0) // within
{
- relate::set<interior, interior, '0', Transpose>(result);
+ update<interior, interior, '0', Transpose>(result);
found_ii_or_ib = true;
}
else if (in_val == 0) // on boundary of single
{
if (tc.check_boundary_point(point))
- relate::set<interior, boundary, '0', Transpose>(result);
+ {
+ update<interior, boundary, '0', Transpose>(result);
+ }
else
- relate::set<interior, interior, '0', Transpose>(result);
+ {
+ update<interior, interior, '0', Transpose>(result);
+ }
found_ii_or_ib = true;
}
}
@@ -504,7 +509,7 @@ struct multi_point_multi_geometry_ii_ib_ie
// neither interior nor boundary found -> exterior
if (found_ii_or_ib == false)
{
- relate::set<interior, exterior, '0', Transpose>(result);
+ update<interior, exterior, '0', Transpose>(result);
}
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
@@ -573,7 +578,7 @@ struct multi_point_multi_geometry
{
// TODO: this is not true if a linestring is degenerated to a point
// then the interior has topological dimension = 0, not 1
- relate::set<exterior, interior, tc_t::interior, Transpose>(result);
+ update<exterior, interior, tc_t::interior, Transpose>(result);
}
if ( relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result)
@@ -581,12 +586,12 @@ struct multi_point_multi_geometry
{
if (multi_point_geometry_eb<MultiGeometry>::apply(multi_point, tc))
{
- relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
+ update<exterior, boundary, tc_t::boundary, Transpose>(result);
}
}
}
- relate::set<exterior, exterior, result_dimension<MultiPoint>::value, Transpose>(result);
+ update<exterior, exterior, result_dimension<MultiPoint>::value, Transpose>(result);
}
};
diff --git a/boost/geometry/algorithms/detail/relate/point_geometry.hpp b/boost/geometry/algorithms/detail/relate/point_geometry.hpp
index 501c5f3dd6..e570a7209b 100644
--- a/boost/geometry/algorithms/detail/relate/point_geometry.hpp
+++ b/boost/geometry/algorithms/detail/relate/point_geometry.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013-2020.
-// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -14,12 +14,9 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_GEOMETRY_HPP
-#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
-//#include <boost/geometry/algorithms/within.hpp>
-//#include <boost/geometry/algorithms/covered_by.hpp>
-
#include <boost/geometry/algorithms/detail/relate/result.hpp>
#include <boost/geometry/algorithms/detail/relate/topology_check.hpp>
+#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
#include <boost/geometry/util/condition.hpp>
@@ -44,18 +41,18 @@ struct point_geometry
if ( pig > 0 ) // within
{
- relate::set<interior, interior, '0', Transpose>(result);
+ update<interior, interior, '0', Transpose>(result);
}
else if ( pig == 0 )
{
- relate::set<interior, boundary, '0', Transpose>(result);
+ update<interior, boundary, '0', Transpose>(result);
}
else // pig < 0 - not within
{
- relate::set<interior, exterior, '0', Transpose>(result);
+ update<interior, exterior, '0', Transpose>(result);
}
- relate::set<exterior, exterior, result_dimension<Point>::value, Transpose>(result);
+ update<exterior, exterior, result_dimension<Point>::value, Transpose>(result);
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
@@ -70,17 +67,21 @@ struct point_geometry
{
// NOTE: even for MLs, if there is at least one boundary point,
// somewhere there must be another one
- relate::set<exterior, interior, tc_t::interior, Transpose>(result);
- relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
+ update<exterior, interior, tc_t::interior, Transpose>(result);
+ update<exterior, boundary, tc_t::boundary, Transpose>(result);
}
else
{
// check if there is a boundary in Geometry
tc_t tc(geometry, strategy);
if ( tc.has_interior() )
- relate::set<exterior, interior, tc_t::interior, Transpose>(result);
+ {
+ update<exterior, interior, tc_t::interior, Transpose>(result);
+ }
if ( tc.has_boundary() )
- relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
+ {
+ update<exterior, boundary, tc_t::boundary, Transpose>(result);
+ }
}
}
}
@@ -168,7 +169,7 @@ struct geometry_point
// //}
// return result("F0FFFF**T");
// }
-// else
+// else
// {
// /*if ( box_has_interior<Box>::apply(box) )
// {
@@ -194,7 +195,7 @@ struct geometry_point
// return result("0FTFFTFFT");
// else if ( geometry::covered_by(point, box) )
// return result("FF*0F*FFT");
-// else
+// else
// return result("FF*FFT0FT");
// }
//};
diff --git a/boost/geometry/algorithms/detail/relate/point_point.hpp b/boost/geometry/algorithms/detail/relate/point_point.hpp
index 7103e2dc92..c987bb44cb 100644
--- a/boost/geometry/algorithms/detail/relate/point_point.hpp
+++ b/boost/geometry/algorithms/detail/relate/point_point.hpp
@@ -2,9 +2,10 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2017, 2018.
-// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-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
// Use, modification and distribution is subject to the Boost Software License,
@@ -44,15 +45,15 @@ struct point_point
bool equal = detail::equals::equals_point_point(point1, point2, strategy);
if ( equal )
{
- relate::set<interior, interior, '0'>(result);
+ update<interior, interior, '0'>(result);
}
else
{
- relate::set<interior, exterior, '0'>(result);
- relate::set<exterior, interior, '0'>(result);
+ update<interior, exterior, '0'>(result);
+ update<exterior, interior, '0'>(result);
}
- relate::set<exterior, exterior, result_dimension<Point1>::value>(result);
+ update<exterior, exterior, result_dimension<Point1>::value>(result);
}
};
@@ -67,20 +68,25 @@ std::pair<bool, bool> point_multipoint_check(Point const& point,
// point_in_geometry could be used here but why iterate over MultiPoint twice?
// we must search for a point in the exterior because all points in MultiPoint can be equal
- typedef typename boost::range_iterator<MultiPoint const>::type iterator;
- iterator it = boost::begin(multi_point);
- iterator last = boost::end(multi_point);
- for ( ; it != last ; ++it )
+
+ auto const end = boost::end(multi_point);
+ for (auto it = boost::begin(multi_point); it != end; ++it)
{
bool ii = detail::equals::equals_point_point(point, *it, strategy);
- if ( ii )
+ if (ii)
+ {
found_inside = true;
+ }
else
+ {
found_outside = true;
+ }
- if ( found_inside && found_outside )
+ if (found_inside && found_outside)
+ {
break;
+ }
}
return std::make_pair(found_inside, found_outside);
@@ -99,7 +105,7 @@ struct point_multipoint
if ( boost::empty(multi_point) )
{
// TODO: throw on empty input?
- relate::set<interior, exterior, '0', Transpose>(result);
+ update<interior, exterior, '0', Transpose>(result);
return;
}
@@ -107,20 +113,20 @@ struct point_multipoint
if ( rel.first ) // some point of MP is equal to P
{
- relate::set<interior, interior, '0', Transpose>(result);
+ update<interior, interior, '0', Transpose>(result);
if ( rel.second ) // a point of MP was found outside P
{
- relate::set<exterior, interior, '0', Transpose>(result);
+ update<exterior, interior, '0', Transpose>(result);
}
}
else
{
- relate::set<interior, exterior, '0', Transpose>(result);
- relate::set<exterior, interior, '0', Transpose>(result);
+ update<interior, exterior, '0', Transpose>(result);
+ update<exterior, interior, '0', Transpose>(result);
}
- relate::set<exterior, exterior, result_dimension<Point>::value, Transpose>(result);
+ update<exterior, exterior, result_dimension<Point>::value, Transpose>(result);
}
};
@@ -148,8 +154,6 @@ struct multipoint_multipoint
Result & result,
Strategy const& /*strategy*/)
{
- typedef typename Strategy::cs_tag cs_tag;
-
{
// TODO: throw on empty input?
bool empty1 = boost::empty(multi_point1);
@@ -160,12 +164,12 @@ struct multipoint_multipoint
}
else if ( empty1 )
{
- relate::set<exterior, interior, '0'>(result);
+ update<exterior, interior, '0'>(result);
return;
}
else if ( empty2 )
{
- relate::set<interior, exterior, '0'>(result);
+ update<interior, exterior, '0'>(result);
return;
}
}
@@ -173,17 +177,17 @@ struct multipoint_multipoint
// The geometry containing smaller number of points will be analysed first
if ( boost::size(multi_point1) < boost::size(multi_point2) )
{
- search_both<false, cs_tag>(multi_point1, multi_point2, result);
+ search_both<false, Strategy>(multi_point1, multi_point2, result);
}
else
{
- search_both<true, cs_tag>(multi_point2, multi_point1, result);
+ search_both<true, Strategy>(multi_point2, multi_point1, result);
}
- relate::set<exterior, exterior, result_dimension<MultiPoint1>::value>(result);
+ update<exterior, exterior, result_dimension<MultiPoint1>::value>(result);
}
- template <bool Transpose, typename CSTag, typename MPt1, typename MPt2, typename Result>
+ template <bool Transpose, typename Strategy, typename MPt1, typename MPt2, typename Result>
static inline void search_both(MPt1 const& first_sorted_mpt, MPt2 const& first_iterated_mpt,
Result & result)
{
@@ -192,7 +196,7 @@ struct multipoint_multipoint
|| relate::may_update<exterior, interior, '0'>(result) )
{
// NlogN + MlogN
- bool is_disjoint = search<Transpose, CSTag>(first_sorted_mpt, first_iterated_mpt, result);
+ bool is_disjoint = search<Transpose, Strategy>(first_sorted_mpt, first_iterated_mpt, result);
if ( BOOST_GEOMETRY_CONDITION(is_disjoint || result.interrupt) )
return;
@@ -203,12 +207,12 @@ struct multipoint_multipoint
|| relate::may_update<exterior, interior, '0'>(result) )
{
// MlogM + NlogM
- search<! Transpose, CSTag>(first_iterated_mpt, first_sorted_mpt, result);
+ search<! Transpose, Strategy>(first_iterated_mpt, first_sorted_mpt, result);
}
}
template <bool Transpose,
- typename CSTag,
+ typename Strategy,
typename SortedMultiPoint,
typename IteratedMultiPoint,
typename Result>
@@ -218,7 +222,7 @@ struct multipoint_multipoint
{
// sort points from the 1 MPt
typedef typename geometry::point_type<SortedMultiPoint>::type point_type;
- typedef geometry::less<void, -1, CSTag> less_type;
+ typedef geometry::less<void, -1, Strategy> less_type;
std::vector<point_type> points(boost::begin(sorted_mpt), boost::end(sorted_mpt));
@@ -229,19 +233,22 @@ struct multipoint_multipoint
bool found_outside = false;
// for each point in the second MPt
- typedef typename boost::range_iterator<IteratedMultiPoint const>::type iterator;
- for ( iterator it = boost::begin(iterated_mpt) ;
- it != boost::end(iterated_mpt) ; ++it )
+ for (auto it = boost::begin(iterated_mpt); it != boost::end(iterated_mpt); ++it)
{
- bool ii =
- std::binary_search(points.begin(), points.end(), *it, less);
- if ( ii )
+ bool ii = std::binary_search(points.begin(), points.end(), *it, less);
+ if (ii)
+ {
found_inside = true;
+ }
else
+ {
found_outside = true;
+ }
- if ( found_inside && found_outside )
+ if (found_inside && found_outside)
+ {
break;
+ }
}
if ( found_inside ) // some point of MP2 is equal to some of MP1
@@ -249,17 +256,17 @@ struct multipoint_multipoint
// TODO: if I/I is set for one MPt, this won't be changed when the other one in analysed
// so if e.g. only I/I must be analysed we musn't check the other MPt
- relate::set<interior, interior, '0', Transpose>(result);
+ update<interior, interior, '0', Transpose>(result);
if ( found_outside ) // some point of MP2 was found outside of MP1
{
- relate::set<exterior, interior, '0', Transpose>(result);
+ update<exterior, interior, '0', Transpose>(result);
}
}
else
{
- relate::set<interior, exterior, '0', Transpose>(result);
- relate::set<exterior, interior, '0', Transpose>(result);
+ update<interior, exterior, '0', Transpose>(result);
+ update<exterior, interior, '0', Transpose>(result);
}
// if no point is intersecting the other MPt then we musn't analyse the reversed case
diff --git a/boost/geometry/algorithms/detail/relate/result.hpp b/boost/geometry/algorithms/detail/relate/result.hpp
index c7a83665bd..84c342e636 100644
--- a/boost/geometry/algorithms/detail/relate/result.hpp
+++ b/boost/geometry/algorithms/detail/relate/result.hpp
@@ -1,11 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-
-// This file was modified by Oracle on 2013-2020.
-// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates.
+// Copyright (c) 2017-2023 Adam Wulkiewicz, Lodz, Poland.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -19,10 +18,10 @@
#include <cstddef>
#include <cstring>
#include <string>
+#include <tuple>
#include <type_traits>
#include <boost/throw_exception.hpp>
-#include <boost/tuple/tuple.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
@@ -44,6 +43,13 @@ enum field { interior = 0, boundary = 1, exterior = 2 };
// but for safety reasons (STATIC_ASSERT) we should check if parameter D is valid and set() doesn't do that
// so some additional function could be added, e.g. set_dim()
+
+template <typename MatrixOrMask, field F1, field F2>
+using fields_in_bounds = util::bool_constant
+ <
+ (F1 < MatrixOrMask::static_height && F2 < MatrixOrMask::static_width)
+ >;
+
// --------------- MATRIX ----------------
// matrix
@@ -60,25 +66,31 @@ public:
static const std::size_t static_width = Width;
static const std::size_t static_height = Height;
static const std::size_t static_size = Width * Height;
-
+
inline matrix()
{
- ::memset(m_array, 'F', static_size);
+ std::fill_n(m_array, static_size, 'F');
}
- template <field F1, field F2>
+ template
+ <
+ field F1, field F2,
+ std::enable_if_t<fields_in_bounds<matrix, F1, F2>::value, int> = 0
+ >
inline char get() const
{
- BOOST_STATIC_ASSERT(F1 < Height && F2 < Width);
static const std::size_t index = F1 * Width + F2;
BOOST_STATIC_ASSERT(index < static_size);
return m_array[index];
}
- template <field F1, field F2, char V>
+ template
+ <
+ field F1, field F2, char V,
+ std::enable_if_t<fields_in_bounds<matrix, F1, F2>::value, int> = 0
+ >
inline void set()
{
- BOOST_STATIC_ASSERT(F1 < Height && F2 < Width);
static const std::size_t index = F1 * Width + F2;
BOOST_STATIC_ASSERT(index < static_size);
m_array[index] = V;
@@ -104,7 +116,7 @@ public:
{
return static_size;
}
-
+
inline const char * data() const
{
return m_array;
@@ -151,56 +163,36 @@ public:
inline bool may_update() const
{
BOOST_STATIC_ASSERT('0' <= D && D <= '9');
-
char const c = m_matrix.template get<F1, F2>();
return D > c || c > '9';
}
template <field F1, field F2, char V>
- inline void set()
- {
- static const bool in_bounds = F1 < Matrix::static_height
- && F2 < Matrix::static_width;
- typedef std::integral_constant<bool, in_bounds> in_bounds_t;
- set_dispatch<F1, F2, V>(in_bounds_t());
- }
-
- template <field F1, field F2, char D>
inline void update()
{
- static const bool in_bounds = F1 < Matrix::static_height
- && F2 < Matrix::static_width;
- typedef std::integral_constant<bool, in_bounds> in_bounds_t;
- update_dispatch<F1, F2, D>(in_bounds_t());
+ BOOST_STATIC_ASSERT(('0' <= V && V <= '9') || V == 'T');
+ char const c = m_matrix.template get<F1, F2>();
+ // If c == T and V == T it will be set anyway but that's fine
+ if (V > c || c > '9')
+ {
+ m_matrix.template set<F1, F2, V>();
+ }
}
-private:
template <field F1, field F2, char V>
- inline void set_dispatch(std::true_type)
+ inline void set()
{
- static const std::size_t index = F1 * Matrix::static_width + F2;
- BOOST_STATIC_ASSERT(index < Matrix::static_size);
- BOOST_STATIC_ASSERT(('0' <= V && V <= '9') || V == 'T' || V == 'F');
+ BOOST_STATIC_ASSERT(('0' <= V && V <= '9') || V == 'T');
m_matrix.template set<F1, F2, V>();
}
- template <field F1, field F2, char V>
- inline void set_dispatch(std::false_type)
- {}
- template <field F1, field F2, char D>
- inline void update_dispatch(std::true_type)
+ template <field F1, field F2>
+ inline char get() const
{
- static const std::size_t index = F1 * Matrix::static_width + F2;
- BOOST_STATIC_ASSERT(index < Matrix::static_size);
- BOOST_STATIC_ASSERT('0' <= D && D <= '9');
- char const c = m_matrix.template get<F1, F2>();
- if ( D > c || c > '9')
- m_matrix.template set<F1, F2, D>();
+ return m_matrix.template get<F1, F2>();
}
- template <field F1, field F2, char D>
- inline void update_dispatch(std::false_type)
- {}
+private:
Matrix m_matrix;
};
@@ -228,7 +220,7 @@ public:
}
if ( it != last )
{
- ::memset(it, '*', last - it);
+ std::fill(it, last, '*');
}
}
@@ -241,18 +233,21 @@ public:
if ( count > 0 )
{
std::for_each(s, s + count, check_char);
- ::memcpy(m_array, s, count);
+ std::copy_n(s, count, m_array);
}
if ( count < static_size )
{
- ::memset(m_array + count, '*', static_size - count);
+ std::fill_n(m_array + count, static_size - count, '*');
}
}
- template <field F1, field F2>
+ template
+ <
+ field F1, field F2,
+ std::enable_if_t<fields_in_bounds<mask, F1, F2>::value, int> = 0
+ >
inline char get() const
{
- BOOST_STATIC_ASSERT(F1 < Height && F2 < Width);
static const std::size_t index = F1 * Width + F2;
BOOST_STATIC_ASSERT(index < static_size);
return m_array[index];
@@ -362,7 +357,7 @@ struct may_update_dispatch
BOOST_STATIC_ASSERT('0' <= D && D <= '9');
char const m = mask.template get<F1, F2>();
-
+
if ( m == 'F' )
{
return true;
@@ -575,37 +570,41 @@ public:
template <field F1, field F2, char D>
inline bool may_update() const
{
- return detail::relate::may_update<F1, F2, D>(
- m_mask, base_t::matrix()
- );
+ return detail::relate::may_update<F1, F2, D>(m_mask, base_t::matrix());
}
template <field F1, field F2, char V>
- inline void set()
+ inline void update()
{
- if ( relate::interrupt<F1, F2, V, Interrupt>(m_mask) )
+ if (relate::interrupt<F1, F2, V, Interrupt>(m_mask))
{
interrupt = true;
}
else
{
- base_t::template set<F1, F2, V>();
+ base_t::template update<F1, F2, V>();
}
}
template <field F1, field F2, char V>
- inline void update()
+ inline void set()
{
- if ( relate::interrupt<F1, F2, V, Interrupt>(m_mask) )
+ if (relate::interrupt<F1, F2, V, Interrupt>(m_mask))
{
interrupt = true;
}
else
{
- base_t::template update<F1, F2, V>();
+ base_t::template set<F1, F2, V>();
}
}
+ template <field F1, field F2>
+ inline char get() const
+ {
+ return base_t::template get<F1, F2>();
+ }
+
private:
Mask const& m_mask;
};
@@ -647,7 +646,7 @@ struct static_mask
BOOST_STATIC_ASSERT(
std::size_t(util::sequence_size<Seq>::value) == static_size);
-
+
template <detail::relate::field F1, detail::relate::field F2>
struct static_get
{
@@ -744,7 +743,7 @@ struct static_interrupt_dispatch<StaticMask, V, F1, F2, true, IsSequence>
static const char mask_el = StaticMask::template static_get<F1, F2>::value;
static const bool value
- = ( V >= '0' && V <= '9' ) ?
+ = ( V >= '0' && V <= '9' ) ?
( mask_el == 'F' || ( mask_el < V && mask_el >= '0' && mask_el <= '9' ) ) :
( ( V == 'T' ) ? mask_el == 'F' : false );
};
@@ -930,7 +929,7 @@ struct static_check_dispatch
&& per_one<exterior, boundary>::apply(matrix)
&& per_one<exterior, exterior>::apply(matrix);
}
-
+
template <field F1, field F2>
struct per_one
{
@@ -1067,24 +1066,6 @@ public:
apply(base_type::matrix());
}
- template <field F1, field F2>
- static inline bool expects()
- {
- return static_should_handle_element<StaticMask, F1, F2>::value;
- }
-
- template <field F1, field F2, char V>
- inline void set()
- {
- static const bool interrupt_c = static_interrupt<StaticMask, V, F1, F2, Interrupt>::value;
- static const bool should_handle = static_should_handle_element<StaticMask, F1, F2>::value;
- static const int version = interrupt_c ? 0
- : should_handle ? 1
- : 2;
-
- set_dispatch<F1, F2, V>(integral_constant<int, version>());
- }
-
template <field F1, field F2, char V>
inline void update()
{
@@ -1097,24 +1078,33 @@ public:
update_dispatch<F1, F2, V>(integral_constant<int, version>());
}
-private:
- // Interrupt && interrupt
- template <field F1, field F2, char V>
- inline void set_dispatch(integral_constant<int, 0>)
+ template
+ <
+ field F1, field F2, char V,
+ std::enable_if_t<static_interrupt<StaticMask, V, F1, F2, Interrupt>::value, int> = 0
+ >
+ inline void set()
{
interrupt = true;
}
- // else should_handle
- template <field F1, field F2, char V>
- inline void set_dispatch(integral_constant<int, 1>)
+
+ template
+ <
+ field F1, field F2, char V,
+ std::enable_if_t<! static_interrupt<StaticMask, V, F1, F2, Interrupt>::value, int> = 0
+ >
+ inline void set()
{
base_type::template set<F1, F2, V>();
}
- // else
- template <field F1, field F2, char V>
- inline void set_dispatch(integral_constant<int, 2>)
- {}
+ template <field F1, field F2>
+ inline char get() const
+ {
+ return base_type::template get<F1, F2>();
+ }
+
+private:
// Interrupt && interrupt
template <field F1, field F2, char V>
inline void update_dispatch(integral_constant<int, 0>)
@@ -1135,40 +1125,6 @@ private:
// --------------- UTIL FUNCTIONS ----------------
-// set
-
-template <field F1, field F2, char V, typename Result>
-inline void set(Result & res)
-{
- res.template set<F1, F2, V>();
-}
-
-template <field F1, field F2, char V, bool Transpose>
-struct set_dispatch
-{
- template <typename Result>
- static inline void apply(Result & res)
- {
- res.template set<F1, F2, V>();
- }
-};
-
-template <field F1, field F2, char V>
-struct set_dispatch<F1, F2, V, true>
-{
- template <typename Result>
- static inline void apply(Result & res)
- {
- res.template set<F2, F1, V>();
- }
-};
-
-template <field F1, field F2, char V, bool Transpose, typename Result>
-inline void set(Result & res)
-{
- set_dispatch<F1, F2, V, Transpose>::apply(res);
-}
-
// update
template <field F1, field F2, char D, typename Result>
@@ -1177,30 +1133,24 @@ inline void update(Result & res)
res.template update<F1, F2, D>();
}
-template <field F1, field F2, char D, bool Transpose>
-struct update_result_dispatch
-{
- template <typename Result>
- static inline void apply(Result & res)
- {
- update<F1, F2, D>(res);
- }
-};
-
-template <field F1, field F2, char D>
-struct update_result_dispatch<F1, F2, D, true>
+template
+<
+ field F1, field F2, char D, bool Transpose, typename Result,
+ std::enable_if_t<! Transpose, int> = 0
+>
+inline void update(Result & res)
{
- template <typename Result>
- static inline void apply(Result & res)
- {
- update<F2, F1, D>(res);
- }
-};
+ res.template update<F1, F2, D>();
+}
-template <field F1, field F2, char D, bool Transpose, typename Result>
+template
+<
+ field F1, field F2, char D, bool Transpose, typename Result,
+ std::enable_if_t<Transpose, int> = 0
+>
inline void update(Result & res)
{
- update_result_dispatch<F1, F2, D, Transpose>::apply(res);
+ res.template update<F2, F1, D>();
}
// may_update
@@ -1211,30 +1161,24 @@ inline bool may_update(Result const& res)
return res.template may_update<F1, F2, D>();
}
-template <field F1, field F2, char D, bool Transpose>
-struct may_update_result_dispatch
-{
- template <typename Result>
- static inline bool apply(Result const& res)
- {
- return may_update<F1, F2, D>(res);
- }
-};
-
-template <field F1, field F2, char D>
-struct may_update_result_dispatch<F1, F2, D, true>
+template
+<
+ field F1, field F2, char D, bool Transpose, typename Result,
+ std::enable_if_t<! Transpose, int> = 0
+>
+inline bool may_update(Result const& res)
{
- template <typename Result>
- static inline bool apply(Result const& res)
- {
- return may_update<F2, F1, D>(res);
- }
-};
+ return res.template may_update<F1, F2, D>();
+}
-template <field F1, field F2, char D, bool Transpose, typename Result>
+template
+<
+ field F1, field F2, char D, bool Transpose, typename Result,
+ std::enable_if_t<Transpose, int> = 0
+>
inline bool may_update(Result const& res)
{
- return may_update_result_dispatch<F1, F2, D, Transpose>::apply(res);
+ return res.template may_update<F2, F1, D>();
}
// result_dimension
@@ -1242,11 +1186,9 @@ inline bool may_update(Result const& res)
template <typename Geometry>
struct result_dimension
{
- BOOST_STATIC_ASSERT(geometry::dimension<Geometry>::value >= 0);
- static const char value
- = ( geometry::dimension<Geometry>::value <= 9 ) ?
- ( '0' + geometry::dimension<Geometry>::value ) :
- 'T';
+ static const std::size_t dim = geometry::dimension<Geometry>::value;
+ BOOST_STATIC_ASSERT(dim >= 0);
+ static const char value = (dim <= 9) ? ('0' + dim) : 'T';
};
}} // namespace detail::relate
diff --git a/boost/geometry/algorithms/detail/relate/topology_check.hpp b/boost/geometry/algorithms/detail/relate/topology_check.hpp
index 459c816143..2fc31ab51b 100644
--- a/boost/geometry/algorithms/detail/relate/topology_check.hpp
+++ b/boost/geometry/algorithms/detail/relate/topology_check.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-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
// Use, modification and distribution is subject to the Boost Software License,
@@ -170,22 +171,22 @@ struct topology_check<MultiLinestring, Strategy, multi_linestring_tag>
}
private:
- typedef geometry::less<void, -1, typename Strategy::cs_tag> less_type;
+ typedef geometry::less<void, -1, Strategy> less_type;
void init() const
{
if (m_is_initialized)
+ {
return;
+ }
m_endpoints.reserve(boost::size(m_mls) * 2);
m_has_interior = false;
- typedef typename boost::range_iterator<MultiLinestring const>::type ls_iterator;
- for ( ls_iterator it = boost::begin(m_mls) ; it != boost::end(m_mls) ; ++it )
+ for (auto it = boost::begin(m_mls); it != boost::end(m_mls); ++it)
{
- typename boost::range_reference<MultiLinestring const>::type
- ls = *it;
+ auto const& ls = *it;
std::size_t count = boost::size(ls);
@@ -196,13 +197,8 @@ private:
if (count > 1)
{
- typedef typename boost::range_reference
- <
- typename boost::range_value<MultiLinestring const>::type const
- >::type point_reference;
-
- point_reference front_pt = range::front(ls);
- point_reference back_pt = range::back(ls);
+ auto const& front_pt = range::front(ls);
+ auto const& back_pt = range::back(ls);
// don't store boundaries of linear rings, this doesn't change anything
if (! equals::equals_point_point(front_pt, back_pt, m_strategy))
@@ -226,7 +222,7 @@ private:
m_has_boundary = false;
- if (! m_endpoints.empty() )
+ if (! m_endpoints.empty())
{
std::sort(m_endpoints.begin(), m_endpoints.end(), less_type());
m_has_boundary = find_odd_count(m_endpoints.begin(), m_endpoints.end());
@@ -341,7 +337,7 @@ struct topology_check<MultiPolygon, Strategy, multi_polygon_tag>
: topology_check_areal
{
topology_check(MultiPolygon const&, Strategy const&) {}
-
+
template <typename Point>
static bool check_boundary_point(Point const& ) { return true; }
};
diff --git a/boost/geometry/algorithms/detail/relate/turns.hpp b/boost/geometry/algorithms/detail/relate/turns.hpp
index 7d82887300..d98794e78a 100644
--- a/boost/geometry/algorithms/detail/relate/turns.hpp
+++ b/boost/geometry/algorithms/detail/relate/turns.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013-2020.
-// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -20,6 +20,8 @@
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
+#include <boost/geometry/geometries/helper_geometry.hpp>
+
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
@@ -40,7 +42,7 @@ struct assign_policy
static bool const include_degenerate = IncludeDegenerate;
};
-// GET_TURNS
+// turn retriever, calling get_turns
template
<
@@ -53,7 +55,10 @@ template
>
struct get_turns
{
- typedef typename geometry::point_type<Geometry1>::type point1_type;
+ using turn_point_type = typename helper_geometry
+ <
+ typename geometry::point_type<Geometry1>::type
+ >::type;
template <typename Strategy>
struct robust_policy_type
@@ -72,16 +77,16 @@ struct get_turns
>
struct turn_info_type
{
- typedef typename segment_ratio_type<point1_type, RobustPolicy>::type ratio_type;
- typedef overlay::turn_info
+ using ratio_type = typename segment_ratio_type<turn_point_type, RobustPolicy>::type;
+ using type = overlay::turn_info
<
- point1_type,
+ turn_point_type,
ratio_type,
typename detail::get_turns::turn_operation_type
<
- Geometry1, Geometry2, ratio_type
+ Geometry1, Geometry2, turn_point_type, ratio_type
>::type
- > type;
+ >;
};
template <typename Turns, typename InterruptPolicy, typename Strategy>
@@ -167,7 +172,7 @@ struct less_op_xxx_linear
template <std::size_t OpId>
struct less_op_linear_linear
- : less_op_xxx_linear< OpId, op_to_int<0,2,3,1,4,0> >
+ : less_op_xxx_linear< OpId, op_to_int<0,2,3,1,4,0> > // xuic
{};
template <std::size_t OpId>
@@ -244,7 +249,7 @@ struct less_op_areal_areal
else if ( right_operation.operation == overlay::operation_intersection )
return false;
}
-
+
return op_to_int_iuxc(left_operation) < op_to_int_iuxc(right_operation);
}
}
@@ -270,7 +275,7 @@ struct less_other_multi_index
// sort turns by G1 - source_index == 0 by:
// seg_id -> distance and coordinates -> operation
-template <std::size_t OpId, typename LessOp, typename CSTag>
+template <std::size_t OpId, typename LessOp, typename Strategy>
struct less
{
BOOST_STATIC_ASSERT(OpId < 2);
@@ -278,14 +283,8 @@ struct less
template <typename Turn>
static inline bool use_fraction(Turn const& left, Turn const& right)
{
- typedef typename geometry::strategy::within::services::default_strategy
- <
- typename Turn::point_type, typename Turn::point_type,
- point_tag, point_tag,
- pointlike_tag, pointlike_tag,
- typename tag_cast<CSTag, spherical_tag>::type,
- typename tag_cast<CSTag, spherical_tag>::type
- >::type eq_pp_strategy_type;
+ using eq_pp_strategy_type = decltype(std::declval<Strategy>().relate(
+ detail::dummy_point(), detail::dummy_point()));
static LessOp less_op;
diff --git a/boost/geometry/algorithms/detail/relation/interface.hpp b/boost/geometry/algorithms/detail/relation/interface.hpp
index e9d940c3e9..4c3616ab42 100644
--- a/boost/geometry/algorithms/detail/relation/interface.hpp
+++ b/boost/geometry/algorithms/detail/relation/interface.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013-2020.
-// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -35,10 +35,15 @@ struct result_handler_type<Geometry1, Geometry2, geometry::de9im::matrix>
}} // namespace detail::relate
#endif // DOXYGEN_NO_DETAIL
-namespace resolve_variant
+namespace resolve_dynamic
{
-template <typename Geometry1, typename Geometry2>
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct relation
{
template <typename Matrix, typename Strategy>
@@ -66,105 +71,70 @@ struct relation
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct relation<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct relation<Geometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Matrix, typename Strategy>
- struct visitor : boost::static_visitor<Matrix>
+ static inline Matrix apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2, Strategy const& strategy)
- : m_geometry2(geometry2), m_strategy(strategy) {}
-
- template <typename Geometry1>
- Matrix operator()(Geometry1 const& geometry1) const
+ Matrix result;
+ traits::visit<Geometry1>::apply([&](auto const& g1)
{
- return relation<Geometry1, Geometry2>
- ::template apply<Matrix>(geometry1, m_geometry2, m_strategy);
- }
- };
-
- template <typename Matrix, typename Strategy>
- static inline Matrix
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Matrix, Strategy>(geometry2, strategy), geometry1);
+ result = relation
+ <
+ util::remove_cref_t<decltype(g1)>,
+ Geometry2
+ >::template apply<Matrix>(g1, geometry2, strategy);
+ }, geometry1);
+ return result;
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct relation<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct relation<Geometry1, Geometry2, Tag1, dynamic_geometry_tag>
{
template <typename Matrix, typename Strategy>
- struct visitor : boost::static_visitor<Matrix>
+ static inline Matrix apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1, Strategy const& strategy)
- : m_geometry1(geometry1), m_strategy(strategy) {}
-
- template <typename Geometry2>
- Matrix operator()(Geometry2 const& geometry2) const
+ Matrix result;
+ traits::visit<Geometry2>::apply([&](auto const& g2)
{
- return relation<Geometry1, Geometry2>
- ::template apply<Matrix>(m_geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Matrix, typename Strategy>
- static inline Matrix
- apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Matrix, Strategy>(geometry1, strategy), geometry2);
+ result = relation
+ <
+ Geometry1,
+ util::remove_cref_t<decltype(g2)>
+ >::template apply<Matrix>(geometry1, g2, strategy);
+ }, geometry2);
+ return result;
}
};
-template
-<
- BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)
->
-struct relation
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
- >
+template <typename Geometry1, typename Geometry2>
+struct relation<Geometry1, Geometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Matrix, typename Strategy>
- struct visitor : boost::static_visitor<Matrix>
+ static inline Matrix apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy)
- : m_strategy(strategy) {}
-
- template <typename Geometry1, typename Geometry2>
- Matrix operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ Matrix result;
+ traits::visit<Geometry1, Geometry2>::apply([&](auto const& g1, auto const& g2)
{
- return relation<Geometry1, Geometry2>
- ::template apply<Matrix>(geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Matrix, typename Strategy>
- static inline Matrix
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Matrix, Strategy>(strategy), geometry1, geometry2);
+ result = relation
+ <
+ util::remove_cref_t<decltype(g1)>,
+ util::remove_cref_t<decltype(g2)>
+ >::template apply<Matrix>(g1, g2, strategy);
+ }, geometry1, geometry2);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
@@ -186,7 +156,7 @@ inline de9im::matrix relation(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
- return resolve_variant::relation
+ return resolve_dynamic::relation
<
Geometry1,
Geometry2
@@ -209,7 +179,7 @@ template <typename Geometry1, typename Geometry2>
inline de9im::matrix relation(Geometry1 const& geometry1,
Geometry2 const& geometry2)
{
- return resolve_variant::relation
+ return resolve_dynamic::relation
<
Geometry1,
Geometry2
diff --git a/boost/geometry/algorithms/detail/sections/section_functions.hpp b/boost/geometry/algorithms/detail/sections/section_functions.hpp
index abc6de409c..df4f31025a 100644
--- a/boost/geometry/algorithms/detail/sections/section_functions.hpp
+++ b/boost/geometry/algorithms/detail/sections/section_functions.hpp
@@ -70,7 +70,7 @@ struct preceding_check<0, Geometry, spherical_tag>
calc_t const value = get<0>(point);
calc_t const other_min = get<min_corner, 0>(other_box);
calc_t const other_max = get<max_corner, 0>(other_box);
-
+
bool const pt_covered = strategy::within::detail::covered_by_range
<
Point, 0, spherical_tag
@@ -124,13 +124,14 @@ template
typename Box,
typename RobustPolicy
>
-static inline bool preceding(int dir,
- Point const& point,
- Box const& point_box,
- Box const& other_box,
- RobustPolicy const& robust_policy)
+inline bool preceding(int dir,
+ Point const& point,
+ Box const& point_box,
+ Box const& other_box,
+ RobustPolicy const& robust_policy)
{
- typename geometry::robust_point_type<Point, RobustPolicy>::type robust_point;
+ using box_point_type = typename geometry::point_type<Box>::type;
+ typename geometry::robust_point_type<box_point_type, RobustPolicy>::type robust_point;
geometry::recalculate(robust_point, point, robust_policy);
// After recalculate() to prevent warning: 'robust_point' may be used uninitialized
@@ -148,11 +149,11 @@ template
typename Box,
typename RobustPolicy
>
-static inline bool exceeding(int dir,
- Point const& point,
- Box const& point_box,
- Box const& other_box,
- RobustPolicy const& robust_policy)
+inline bool exceeding(int dir,
+ Point const& point,
+ Box const& point_box,
+ Box const& other_box,
+ RobustPolicy const& robust_policy)
{
return preceding<Dimension>(-dir, point, point_box, other_box, robust_policy);
}
diff --git a/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/boost/geometry/algorithms/detail/sections/sectionalize.hpp
index e98536e3fd..3317ff70a9 100644
--- a/boost/geometry/algorithms/detail/sections/sectionalize.hpp
+++ b/boost/geometry/algorithms/detail/sections/sectionalize.hpp
@@ -38,11 +38,9 @@
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/recalculate.hpp>
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
-#include <boost/geometry/algorithms/detail/buffer/buffer_box.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/closure.hpp>
@@ -87,7 +85,7 @@ template
>
struct section
{
- typedef Box box_type;
+ using box_type = Box;
static std::size_t const dimension_count = DimensionCount;
int directions[DimensionCount];
@@ -134,7 +132,7 @@ struct section
template <typename Box, std::size_t DimensionCount>
struct sections : std::vector<section<Box, DimensionCount> >
{
- typedef Box box_type;
+ using box_type = Box;
static std::size_t const value = DimensionCount;
};
@@ -161,16 +159,14 @@ template
>
struct get_direction_loop
{
- typedef typename util::sequence_element<Index, DimensionVector>::type dimension;
+ using dimension = typename util::sequence_element<Index, DimensionVector>::type;
template <typename Segment>
static inline void apply(Segment const& seg,
int directions[Count])
{
- typedef typename coordinate_type<Segment>::type coordinate_type;
-
- coordinate_type const c0 = geometry::get<0, dimension::value>(seg);
- coordinate_type const c1 = geometry::get<1, dimension::value>(seg);
+ auto const& c0 = geometry::get<0, dimension::value>(seg);
+ auto const& c1 = geometry::get<1, dimension::value>(seg);
directions[Index] = c1 > c0 ? 1 : c1 < c0 ? -1 : 0;
@@ -193,14 +189,14 @@ template
>
struct get_direction_loop<Point, DimensionVector, 0, Count, spherical_tag>
{
- typedef typename util::sequence_element<0, DimensionVector>::type dimension;
+ using dimension = typename util::sequence_element<0, DimensionVector>::type;
template <typename Segment>
static inline void apply(Segment const& seg,
int directions[Count])
{
- typedef typename coordinate_type<Segment>::type coordinate_type;
- typedef typename coordinate_system<Point>::type::units units_t;
+ using coordinate_type = typename coordinate_type<Segment>::type;
+ using units_t = typename coordinate_system<Point>::type::units;
coordinate_type const diff = math::longitude_distance_signed
<
@@ -381,11 +377,7 @@ struct box_next_in_section<cartesian_tag>
};
/// @brief Helper class to create sections of a part of a range, on the fly
-template
-<
- typename Point,
- typename DimensionVector
->
+template<typename DimensionVector>
struct sectionalize_part
{
static const std::size_t dimension_count
@@ -407,18 +399,21 @@ struct sectionalize_part
{
boost::ignore_unused(robust_policy);
- typedef typename boost::range_value<Sections>::type section_type;
+ using section_type = typename boost::range_value<Sections>::type;
+ using box_type = typename section_type::box_type;
+ using point_type = typename geometry::point_type<box_type>::type;
+
BOOST_STATIC_ASSERT
(
section_type::dimension_count
== util::sequence_size<DimensionVector>::value
);
- typedef typename geometry::robust_point_type
+ using robust_point_type = typename geometry::robust_point_type
<
- Point,
+ point_type,
RobustPolicy
- >::type robust_point_type;
+ >::type;
std::size_t const count = std::distance(begin, end);
if (count == 0)
@@ -436,7 +431,7 @@ struct sectionalize_part
Iterator it = begin;
robust_point_type previous_robust_point;
geometry::recalculate(previous_robust_point, *it, robust_policy);
-
+
for(Iterator previous = it++;
it != end;
++previous, ++it, index++)
@@ -449,7 +444,7 @@ struct sectionalize_part
int direction_classes[dimension_count] = {0};
get_direction_loop
<
- Point, DimensionVector, 0, dimension_count
+ point_type, DimensionVector, 0, dimension_count
>::apply(robust_segment, direction_classes);
// if "dir" == 0 for all point-dimensions, it is duplicate.
@@ -463,7 +458,7 @@ struct sectionalize_part
// (dimension_count might be < dimension<P>::value)
if (check_duplicate_loop
<
- 0, geometry::dimension<Point>::type::value
+ 0, geometry::dimension<point_type>::type::value
>::apply(robust_segment)
)
{
@@ -562,7 +557,6 @@ template
<
closure_selector Closure,
bool Reverse,
- typename Point,
typename DimensionVector
>
struct sectionalize_range
@@ -601,7 +595,7 @@ struct sectionalize_range
return;
}
- sectionalize_part<Point, DimensionVector>::apply(sections,
+ sectionalize_part<DimensionVector>::apply(sections,
boost::begin(view), boost::end(view),
robust_policy, strategy,
ring_id, max_count);
@@ -629,23 +623,21 @@ struct sectionalize_polygon
ring_identifier ring_id,
std::size_t max_count)
{
- typedef typename point_type<Polygon>::type point_type;
- typedef sectionalize_range
+ using sectionalizer = sectionalize_range
<
- closure<Polygon>::value, Reverse, point_type, DimensionVector
- > per_range;
+ closure<Polygon>::value, Reverse, DimensionVector
+ >;
ring_id.ring_index = -1;
- per_range::apply(exterior_ring(poly), robust_policy, sections,
+ sectionalizer::apply(exterior_ring(poly), robust_policy, sections,
strategy, ring_id, max_count);
ring_id.ring_index++;
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(poly);
- for (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it, ++ring_id.ring_index)
+ auto const& rings = interior_rings(poly);
+ for (auto it = boost::begin(rings); it != boost::end(rings);
+ ++it, ++ring_id.ring_index)
{
- per_range::apply(*it, robust_policy, sections,
+ sectionalizer::apply(*it, robust_policy, sections,
strategy, ring_id, max_count);
}
}
@@ -667,7 +659,7 @@ struct sectionalize_box
Strategy const& strategy,
ring_identifier const& ring_id, std::size_t max_count)
{
- typedef typename point_type<Box>::type point_type;
+ using point_type = typename point_type<Box>::type;
assert_dimension<Box, 2>();
@@ -693,7 +685,7 @@ struct sectionalize_box
// because edges of a box are not geodesic segments
sectionalize_range
<
- closed, false, point_type, DimensionVector
+ closed, false, DimensionVector
>::apply(points, robust_policy, sections,
strategy, ring_id, max_count);
}
@@ -717,10 +709,7 @@ struct sectionalize_multi
std::size_t max_count)
{
ring_id.multi_index = 0;
- for (typename boost::range_iterator<MultiGeometry const>::type
- it = boost::begin(multi);
- it != boost::end(multi);
- ++it, ++ring_id.multi_index)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it, ++ring_id.multi_index)
{
Policy::apply(*it, robust_policy, sections,
strategy,
@@ -729,77 +718,28 @@ struct sectionalize_multi
}
};
-// TODO: If it depends on CS it should probably be made into strategy.
-// For now implemented here because of ongoing work on robustness
-// the fact that it interferes with detail::buffer::buffer_box
-// and that we probably need a general strategy for defining epsilon in
-// various coordinate systems, e.g. for point comparison, enlargement of
-// bounding boxes, etc.
-template <typename CSTag>
-struct expand_by_epsilon
- : not_implemented<CSTag>
-{};
-
-template <>
-struct expand_by_epsilon<cartesian_tag>
-{
- template <typename Box>
- static inline void apply(Box & box)
- {
- detail::expand_by_epsilon(box);
- }
-};
-
-template <>
-struct expand_by_epsilon<spherical_tag>
-{
- template <typename Box>
- static inline void apply(Box & box)
- {
- typedef typename coordinate_type<Box>::type coord_t;
- static const coord_t eps = std::is_same<coord_t, float>::value
- ? coord_t(1e-6)
- : coord_t(1e-12);
- detail::expand_by_epsilon(box, eps);
- }
-};
-
-// TODO: In geographic CS it should probably also depend on FormulaPolicy.
-template <>
-struct expand_by_epsilon<geographic_tag>
- : expand_by_epsilon<spherical_tag>
-{};
-
template <typename Sections, typename Strategy>
inline void enlarge_sections(Sections& sections, Strategy const&)
{
- // Enlarge sections slightly, this should be consistent with math::equals()
- // and with the tolerances used in general_form intersections.
- // This avoids missing turns.
-
- // Points and Segments are equal-compared WRT machine epsilon, but Boxes aren't
- // Enlarging Boxes ensures that they correspond to the bound objects,
- // Segments in this case, since Sections are collections of Segments.
-
- // It makes section a tiny bit too large, which might cause (a small number)
- // of more comparisons
- for (typename boost::range_iterator<Sections>::type it = boost::begin(sections);
- it != boost::end(sections);
- ++it)
+ // Expand the box to avoid missing any intersection. The amount is
+ // should be larger than epsilon. About the value itself: the smaller
+ // it is, the higher the risk to miss intersections. The larger it is,
+ // the more comparisons are made, which is not harmful for the result
+ // (but it might be for the performance).
+ // So it should be on the high side.
+
+ // Use a compilable and workable epsilon for all types, for example:
+ // - for double :~ 2.22e-13
+ // - for float :~ 1e-4
+ // - for Boost.Multiprecision (50) :~ 5.35e-48
+ // - for Boost.Rational : 0/1
+
+ for (auto& section : sections)
{
-#if defined(BOOST_GEOMETRY_USE_RESCALING)
- detail::sectionalize::expand_by_epsilon
- <
- typename Strategy::cs_tag
- >::apply(it->bounding_box);
-
-#else
- // Expand the box to avoid missing any intersection. The amount is
- // should be larger than epsilon. About the value itself: the smaller
- // it is, the higher the risk to miss intersections. The larger it is,
- // the more comparisons are made. So it should be on the high side.
- detail::buffer::buffer_box(it->bounding_box, 0.001, it->bounding_box);
-#endif
+ using gt = decltype(section.bounding_box);
+ using ct = typename geometry::coordinate_type<gt>::type;
+ static ct const eps = math::scaled_epsilon<ct>(1000);
+ expand_by_epsilon(section.bounding_box, eps);
}
}
@@ -848,12 +788,7 @@ struct sectionalize
false,
DimensionVector
>
- : detail::sectionalize::sectionalize_range
- <
- closed, false,
- typename point_type<LineString>::type,
- DimensionVector
- >
+ : detail::sectionalize::sectionalize_range<closed, false, DimensionVector>
{};
template
@@ -866,7 +801,6 @@ struct sectionalize<ring_tag, Ring, Reverse, DimensionVector>
: detail::sectionalize::sectionalize_range
<
geometry::closure<Ring>::value, Reverse,
- typename point_type<Ring>::type,
DimensionVector
>
{};
@@ -913,12 +847,7 @@ struct sectionalize<multi_linestring_tag, MultiLinestring, Reverse, DimensionVec
: detail::sectionalize::sectionalize_multi
<
DimensionVector,
- detail::sectionalize::sectionalize_range
- <
- closed, false,
- typename point_type<MultiLinestring>::type,
- DimensionVector
- >
+ detail::sectionalize::sectionalize_range<closed, false, DimensionVector>
>
{};
@@ -960,26 +889,6 @@ inline void sectionalize(Geometry const& geometry,
{
concepts::check<Geometry const>();
- typedef typename boost::range_value<Sections>::type section_type;
-
- // Compiletime check for point type of section boxes
- // and point type related to robust policy
- typedef typename geometry::coordinate_type
- <
- typename section_type::box_type
- >::type ctype1;
- typedef typename geometry::coordinate_type
- <
- typename geometry::robust_point_type
- <
- typename geometry::point_type<Geometry>::type,
- RobustPolicy
- >::type
- >::type ctype2;
-
- BOOST_STATIC_ASSERT((std::is_same<ctype1, ctype2>::value));
-
-
sections.clear();
ring_identifier ring_id;
@@ -1013,11 +922,12 @@ inline void sectionalize(Geometry const& geometry,
int source_index = 0,
std::size_t max_count = 10)
{
- typedef typename strategies::envelope::services::default_strategy
+ using box_type = typename Sections::box_type;
+ using strategy_type = typename strategies::envelope::services::default_strategy
<
Geometry,
- model::box<typename point_type<Geometry>::type>
- >::type strategy_type;
+ box_type
+ >::type;
boost::geometry::sectionalize
<
diff --git a/boost/geometry/algorithms/detail/select_geometry_type.hpp b/boost/geometry/algorithms/detail/select_geometry_type.hpp
index 2e94ae73e6..5592fa5c4b 100644
--- a/boost/geometry/algorithms/detail/select_geometry_type.hpp
+++ b/boost/geometry/algorithms/detail/select_geometry_type.hpp
@@ -11,6 +11,9 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SELECT_GEOMETRY_TYPE_HPP
#include <boost/geometry/core/geometry_types.hpp>
+#include <boost/geometry/core/static_assert.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/sequence.hpp>
#include <boost/geometry/util/type_traits.hpp>
@@ -21,29 +24,33 @@ namespace boost { namespace geometry
namespace detail
{
-template
-<
- typename Geometry,
- template <typename, typename> class LessPred,
- bool IsDynamicOrCollection = util::is_dynamic_geometry<Geometry>::value
- || util::is_geometry_collection<Geometry>::value
->
-struct select_geometry_type
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct first_geometry_type
{
using type = Geometry;
};
-template
-<
- typename Geometry,
- template <typename, typename> class LessPred
->
-struct select_geometry_type<Geometry, LessPred, true>
- : util::select_element
+template <typename Geometry>
+struct first_geometry_type<Geometry, geometry_collection_tag>
+{
+ template <typename T>
+ using pred = util::bool_constant
<
- typename traits::geometry_types<std::remove_const_t<Geometry>>::type,
- LessPred
- >
+ ! util::is_dynamic_geometry<T>::value
+ && ! util::is_geometry_collection<T>::value
+ >;
+
+ using type = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Geometry>::type,
+ pred
+ >::type;
+};
+
+template <typename Geometry>
+struct first_geometry_type<Geometry, dynamic_geometry_tag>
+ : first_geometry_type<Geometry, geometry_collection_tag>
{};
@@ -67,6 +74,32 @@ struct geometry_types<Geometry, true>
template
<
+ typename Geometry,
+ template <typename, typename> class LessPred,
+ bool IsDynamicOrCollection = util::is_dynamic_geometry<Geometry>::value
+ || util::is_geometry_collection<Geometry>::value
+>
+struct select_geometry_type
+{
+ using type = Geometry;
+};
+
+template
+<
+ typename Geometry,
+ template <typename, typename> class LessPred
+>
+struct select_geometry_type<Geometry, LessPred, true>
+ : util::sequence_min_element
+ <
+ typename traits::geometry_types<std::remove_const_t<Geometry>>::type,
+ LessPred
+ >
+{};
+
+
+template
+<
typename Geometry1, typename Geometry2,
template <typename, typename> class LessPred,
bool IsDynamicOrCollection = util::is_dynamic_geometry<Geometry1>::value
@@ -89,10 +122,13 @@ template
template <typename, typename> class LessPred
>
struct select_geometry_types<Geometry1, Geometry2, LessPred, true>
- : util::select_combination_element
+ : util::sequence_min_element
<
- typename geometry_types<Geometry1>::type,
- typename geometry_types<Geometry2>::type,
+ typename util::sequence_combine
+ <
+ typename geometry_types<Geometry1>::type,
+ typename geometry_types<Geometry2>::type
+ >::type,
LessPred
>
{};
diff --git a/boost/geometry/algorithms/detail/sweep.hpp b/boost/geometry/algorithms/detail/sweep.hpp
index 3dc78261f2..a8c7f9a91a 100644
--- a/boost/geometry/algorithms/detail/sweep.hpp
+++ b/boost/geometry/algorithms/detail/sweep.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2015, Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2015, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
@@ -10,6 +11,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SWEEP_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SWEEP_HPP
+#include <boost/geometry/util/condition.hpp>
+
#include <boost/core/ignore_unused.hpp>
@@ -56,7 +59,7 @@ inline void sweep(Range const& range, PriorityQueue& queue,
event_type event = queue.top();
queue.pop();
event_visitor.apply(event, queue);
- if (interrupt_policy.enabled && interrupt_policy.apply(event))
+ if (BOOST_GEOMETRY_CONDITION(interrupt_policy.enabled) && interrupt_policy.apply(event))
{
break;
}
diff --git a/boost/geometry/algorithms/detail/touches/implementation.hpp b/boost/geometry/algorithms/detail/touches/implementation.hpp
index b37e7bc7ea..15a899e701 100644
--- a/boost/geometry/algorithms/detail/touches/implementation.hpp
+++ b/boost/geometry/algorithms/detail/touches/implementation.hpp
@@ -3,10 +3,10 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2013-2022 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2020.
-// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -24,15 +24,20 @@
#include <type_traits>
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
+#include <boost/geometry/algorithms/detail/gc_topological_dimension.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
#include <boost/geometry/algorithms/detail/sub_range.hpp>
+#include <boost/geometry/algorithms/detail/relate/implementation.hpp>
+#include <boost/geometry/algorithms/detail/relate/implementation_gc.hpp>
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
#include <boost/geometry/algorithms/detail/touches/interface.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/algorithms/disjoint.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/num_geometries.hpp>
-#include <boost/geometry/algorithms/relate.hpp>
+
+#include <boost/geometry/geometries/helper_geometry.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
@@ -40,6 +45,8 @@
#include <boost/geometry/strategies/relate/geographic.hpp>
#include <boost/geometry/strategies/relate/spherical.hpp>
+#include <boost/geometry/views/detail/geometry_collection_view.hpp>
+
namespace boost { namespace geometry
{
@@ -80,7 +87,7 @@ struct box_box_loop
{
touch = true;
}
-
+
return box_box_loop
<
Dimension + 1,
@@ -150,19 +157,20 @@ struct areal_interrupt_policy
inline bool apply(Range const& range)
{
// if already rejected (temp workaround?)
- if ( found_not_touch )
+ if (found_not_touch)
+ {
return true;
+ }
- typedef typename boost::range_iterator<Range const>::type iterator;
- for ( iterator it = boost::begin(range) ; it != boost::end(range) ; ++it )
+ for (auto it = boost::begin(range); it != boost::end(range); ++it)
{
- if ( it->has(overlay::operation_intersection) )
+ if (it->has(overlay::operation_intersection))
{
found_not_touch = true;
return true;
}
- switch(it->method)
+ switch (it->method)
{
case overlay::method_crosses:
found_not_touch = true;
@@ -211,7 +219,8 @@ inline bool point_on_border_within(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
- typename geometry::point_type<Geometry1>::type pt;
+ using point_type = typename geometry::point_type<Geometry1>::type;
+ typename helper_geometry<point_type>::type pt;
return geometry::point_on_border(pt, geometry1)
&& geometry::within(pt, geometry2, strategy);
}
@@ -235,17 +244,18 @@ struct areal_areal
Geometry2 const& geometry2,
Strategy const& strategy)
{
- typedef typename geometry::point_type<Geometry1>::type point_type;
- typedef detail::overlay::turn_info<point_type> turn_info;
+ using point_type = typename geometry::point_type<Geometry1>::type;
+ using mutable_point_type = typename helper_geometry<point_type>::type;
+ using turn_info = detail::overlay::turn_info<mutable_point_type>;
std::deque<turn_info> turns;
detail::touches::areal_interrupt_policy policy;
- boost::geometry::get_turns
- <
- detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
- detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
- detail::overlay::assign_null_policy
- >(geometry1, geometry2, strategy, detail::no_rescale_policy(), turns, policy);
+ geometry::get_turns
+ <
+ detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
+ detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
+ detail::overlay::assign_null_policy
+ >(geometry1, geometry2, strategy, detail::no_rescale_policy(), turns, policy);
return policy.result()
&& ! geometry::detail::touches::rings_containing(geometry1, geometry2, strategy)
@@ -264,6 +274,55 @@ struct use_point_in_geometry
}
};
+// GC
+
+struct gc_gc
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ int const dimension1 = detail::gc_topological_dimension(geometry1);
+ int const dimension2 = detail::gc_topological_dimension(geometry2);
+
+ if (dimension1 == 0 && dimension2 == 0)
+ {
+ return false;
+ }
+ else
+ {
+ return detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_touches_not_pp_type,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
+ }
+ }
+};
+
+struct notgc_gc
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ using gc1_view_t = detail::geometry_collection_view<Geometry1>;
+ return gc_gc::apply(gc1_view_t(geometry1), geometry2, strategy);
+ }
+};
+
+struct gc_notgc
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ using gc2_view_t = detail::geometry_collection_view<Geometry2>;
+ return gc_gc::apply(geometry1, gc2_view_t(geometry2), strategy);
+ }
+};
+
}}
#endif // DOXYGEN_NO_DETAIL
@@ -396,14 +455,52 @@ struct touches<Areal1, Areal2, ring_tag, ring_tag, areal_tag, areal_tag, false>
: detail::touches::areal_areal<Areal1, Areal2>
{};
+// GC
+
+template <typename Geometry1, typename Geometry2>
+struct touches
+ <
+ Geometry1, Geometry2,
+ geometry_collection_tag, geometry_collection_tag,
+ geometry_collection_tag, geometry_collection_tag,
+ false
+ >
+ : detail::touches::gc_gc
+{};
+
+
+template <typename Geometry1, typename Geometry2, typename Tag1, typename CastedTag1>
+struct touches
+ <
+ Geometry1, Geometry2,
+ Tag1, geometry_collection_tag,
+ CastedTag1, geometry_collection_tag,
+ false
+ >
+ : detail::touches::notgc_gc
+{};
+
+
+template <typename Geometry1, typename Geometry2, typename Tag2, typename CastedTag2>
+struct touches
+ <
+ Geometry1, Geometry2,
+ geometry_collection_tag, Tag2,
+ geometry_collection_tag, CastedTag2,
+ false
+ >
+ : detail::touches::gc_notgc
+{};
+
+
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
-namespace resolve_variant
+namespace resolve_dynamic
{
-template <typename Geometry>
+template <typename Geometry, typename Tag>
struct self_touches
{
static bool apply(Geometry const& geometry)
@@ -436,7 +533,7 @@ struct self_touches
}
};
-}
+} // namespace resolve_dynamic
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/touches/interface.hpp b/boost/geometry/algorithms/detail/touches/interface.hpp
index 39d997463e..271697c5d9 100644
--- a/boost/geometry/algorithms/detail/touches/interface.hpp
+++ b/boost/geometry/algorithms/detail/touches/interface.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2021.
-// Modifications copyright (c) 2013-2021, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -23,15 +23,13 @@
#include <deque>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/visit.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
@@ -146,13 +144,19 @@ struct touches<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant {
+namespace resolve_dynamic {
-template <typename Geometry1, typename Geometry2>
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct touches
{
template <typename Strategy>
- static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
+ static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
@@ -164,120 +168,87 @@ struct touches
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct touches<Geometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2, Strategy const& strategy)
- : m_geometry2(geometry2)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- bool operator()(Geometry1 const& geometry1) const
+ bool result = false;
+ traits::visit<Geometry1>::apply([&](auto const& g1)
{
- return touches<Geometry1, Geometry2>::apply(geometry1, m_geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
+ result = touches
+ <
+ util::remove_cref_t<decltype(g1)>,
+ Geometry2
+ >::apply(g1, geometry2, strategy);
+ }, geometry1);
+ return result;
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct touches<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct touches<Geometry1, Geometry2, Tag1, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1, Strategy const& strategy)
- : m_geometry1(geometry1)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- bool operator()(Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry2>::apply([&](auto const& g2)
{
- return touches<Geometry1, Geometry2>::apply(m_geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
+ result = touches
+ <
+ Geometry1,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(geometry1, g2, strategy);
+ }, geometry2);
+ return result;
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)>
-struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
+template <typename Geometry1, typename Geometry2>
+struct touches<Geometry1, Geometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy)
- : m_strategy(strategy)
- {}
-
- template <typename Geometry1, typename Geometry2>
- bool operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry1, Geometry2>::apply([&](auto const& g1, auto const& g2)
{
- return touches<Geometry1, Geometry2>::apply(geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
+ result = touches
+ <
+ util::remove_cref_t<decltype(g1)>,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(g1, g2, strategy);
+ }, geometry1, geometry2);
+ return result;
}
};
-template <typename Geometry>
+template <typename Geometry, typename Tag = typename geometry::tag<Geometry>::type>
struct self_touches;
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct self_touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct self_touches<Geometry, dynamic_geometry_tag>
{
- struct visitor: boost::static_visitor<bool>
+ static bool apply(Geometry const& geometry)
{
- template <typename Geometry>
- bool operator()(Geometry const& geometry) const
+ bool result = false;
+ traits::visit<Geometry>::apply([&](auto const& g)
{
- return self_touches<Geometry>::apply(geometry);
- }
- };
-
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
- {
- return boost::apply_visitor(visitor(), geometry);
+ result = self_touches
+ <
+ util::remove_cref_t<decltype(g)>
+ >::apply(g);
+ }, geometry);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
@@ -301,7 +272,7 @@ struct self_touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
inline bool touches(Geometry const& geometry)
{
- return resolve_variant::self_touches<Geometry>::apply(geometry);
+ return resolve_dynamic::self_touches<Geometry>::apply(geometry);
}
@@ -325,7 +296,7 @@ inline bool touches(Geometry const& geometry)
template <typename Geometry1, typename Geometry2>
inline bool touches(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
- return resolve_variant::touches
+ return resolve_dynamic::touches
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, default_strategy());
@@ -350,7 +321,7 @@ inline bool touches(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
- return resolve_variant::touches
+ return resolve_dynamic::touches
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
diff --git a/boost/geometry/algorithms/detail/tupled_output.hpp b/boost/geometry/algorithms/detail/tupled_output.hpp
index e0f889745b..8d9652683a 100644
--- a/boost/geometry/algorithms/detail/tupled_output.hpp
+++ b/boost/geometry/algorithms/detail/tupled_output.hpp
@@ -389,7 +389,7 @@ struct output_geometry_access<TupledOut, Tag, DefaultTag, void>
>::value;
typedef typename geometry::tuples::element<index, TupledOut>::type type;
-
+
template <typename Tuple>
static typename geometry::tuples::element<index, Tuple>::type&
get(Tuple & tup)
@@ -593,8 +593,7 @@ struct convert_to_output<Geometry, SingleOut, true>
static OutputIterator apply(Geometry const& geometry,
OutputIterator oit)
{
- typedef typename boost::range_iterator<Geometry const>::type iterator;
- for (iterator it = boost::begin(geometry); it != boost::end(geometry); ++it)
+ for (auto it = boost::begin(geometry); it != boost::end(geometry); ++it)
{
SingleOut single_out;
geometry::convert(*it, single_out);
diff --git a/boost/geometry/algorithms/detail/turns/remove_duplicate_turns.hpp b/boost/geometry/algorithms/detail/turns/remove_duplicate_turns.hpp
index ccb19efb73..7819b5e2e1 100644
--- a/boost/geometry/algorithms/detail/turns/remove_duplicate_turns.hpp
+++ b/boost/geometry/algorithms/detail/turns/remove_duplicate_turns.hpp
@@ -1,18 +1,19 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, Oracle and/or its affiliates.
+// Copyright (c) 2014-2022, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
-// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_REMOVE_DUPLICATE_TURNS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_REMOVE_DUPLICATE_TURNS_HPP
#include <algorithm>
-#include <boost/geometry/algorithms/equals.hpp>
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
namespace boost { namespace geometry
{
@@ -23,33 +24,27 @@ namespace detail { namespace turns
template <typename Turns, bool Enable>
struct remove_duplicate_turns
{
- static inline void apply(Turns&) {}
+ template <typename Strategy>
+ static inline void apply(Turns const&, Strategy const&) {}
};
template <typename Turns>
-class remove_duplicate_turns<Turns, true>
+struct remove_duplicate_turns<Turns, true>
{
-private:
- struct TurnEqualsTo
- {
- template <typename Turn>
- bool operator()(Turn const& t1, Turn const& t2) const
- {
- return geometry::equals(t1.point, t2.point)
- && t1.operations[0].seg_id == t2.operations[0].seg_id
- && t1.operations[1].seg_id == t2.operations[1].seg_id;
- }
- };
-
-public:
- static inline void apply(Turns& turns)
+ template <typename Strategy>
+ static inline void apply(Turns& turns, Strategy const& strategy)
{
- turns.erase( std::unique(turns.begin(), turns.end(),
- TurnEqualsTo()),
- turns.end()
- );
+ turns.erase(
+ std::unique(turns.begin(), turns.end(),
+ [&](auto const& t1, auto const& t2)
+ {
+ return detail::equals::equals_point_point(t1.point, t2.point, strategy)
+ && t1.operations[0].seg_id == t2.operations[0].seg_id
+ && t1.operations[1].seg_id == t2.operations[1].seg_id;
+ }),
+ turns.end());
}
};
diff --git a/boost/geometry/algorithms/detail/visit.hpp b/boost/geometry/algorithms/detail/visit.hpp
index 60958f4b40..7cbf9e2318 100644
--- a/boost/geometry/algorithms/detail/visit.hpp
+++ b/boost/geometry/algorithms/detail/visit.hpp
@@ -181,20 +181,16 @@ struct visit_breadth_first<Geometry, dynamic_geometry_tag>
}
};
-// NOTE: This specialization works partially like std::visit and partially like
-// std::ranges::for_each. If the argument is rvalue reference then the elements
-// are passed into the function as rvalue references as well. This is consistent
-// with std::visit but different than std::ranges::for_each. It's done this way
-// because visit_breadth_first is also specialized for static and dynamic geometries
-// which and references for them has to be propagated like that. If this is not
-// desireable then the support for other kinds of geometries should be dropped and
-// this algorithm should work only for geometry collection.
-// This is not a problem right now because only non-rvalue references are passed
-// but in the future there might be some issues. Consider e.g. passing a temporary
-// mutable proxy range as geometry collection. In such case the elements would be
-// passed as rvalue references which would be incorrect.
-template <typename Geometry>
-struct visit_breadth_first<Geometry, geometry_collection_tag>
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <bool PassIterator = false>
+struct visit_breadth_first_impl
{
template <typename F, typename Geom>
static bool apply(F function, Geom && geom)
@@ -217,7 +213,8 @@ struct visit_breadth_first<Geometry, geometry_collection_tag>
bool result = true;
traits::iter_visit<util::remove_cref_t<Geom>>::apply([&](auto && g)
{
- result = visit_or_enqueue(function, std::forward<decltype(g)>(g), queue, it);
+ result = visit_breadth_first_impl::visit_or_enqueue<PassIterator>(
+ function, std::forward<decltype(g)>(g), queue, it);
}, it);
if (! result)
@@ -235,7 +232,7 @@ struct visit_breadth_first<Geometry, geometry_collection_tag>
// so this call can be avoided.
traits::iter_visit<util::remove_cref_t<Geom>>::apply([&](auto && g)
{
- set_iterators(std::forward<decltype(g)>(g), it, end);
+ visit_breadth_first_impl::set_iterators(std::forward<decltype(g)>(g), it, end);
}, queue.front());
queue.pop_front();
}
@@ -246,7 +243,7 @@ struct visit_breadth_first<Geometry, geometry_collection_tag>
private:
template
<
- typename F, typename Geom, typename Iterator,
+ bool PassIter, typename F, typename Geom, typename Iterator,
std::enable_if_t<util::is_geometry_collection<Geom>::value, int> = 0
>
static bool visit_or_enqueue(F &, Geom &&, std::deque<Iterator> & queue, Iterator iter)
@@ -256,13 +253,22 @@ private:
}
template
<
- typename F, typename Geom, typename Iterator,
- std::enable_if_t<! util::is_geometry_collection<Geom>::value, int> = 0
+ bool PassIter, typename F, typename Geom, typename Iterator,
+ std::enable_if_t<! util::is_geometry_collection<Geom>::value && ! PassIter, int> = 0
>
static bool visit_or_enqueue(F & f, Geom && g, std::deque<Iterator> & , Iterator)
{
return f(std::forward<Geom>(g));
}
+ template
+ <
+ bool PassIter, typename F, typename Geom, typename Iterator,
+ std::enable_if_t<! util::is_geometry_collection<Geom>::value && PassIter, int> = 0
+ >
+ static bool visit_or_enqueue(F & f, Geom && g, std::deque<Iterator> & , Iterator iter)
+ {
+ return f(std::forward<Geom>(g), iter);
+ }
template
<
@@ -283,6 +289,32 @@ private:
{}
};
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+// NOTE: This specialization works partially like std::visit and partially like
+// std::ranges::for_each. If the argument is rvalue reference then the elements
+// are passed into the function as rvalue references as well. This is consistent
+// with std::visit but different than std::ranges::for_each. It's done this way
+// because visit_breadth_first is also specialized for static and dynamic geometries
+// and references for them has to be propagated like that. If this is not
+// desireable then the support for other kinds of geometries should be dropped and
+// this algorithm should work only for geometry collection. Or forwarding of rvalue
+// references should simply be dropped entirely.
+// This is not a problem right now because only non-rvalue references are passed
+// but in the future there might be some issues. Consider e.g. passing a temporary
+// mutable proxy range as geometry collection. In such case the elements would be
+// passed as rvalue references which would be incorrect.
+template <typename Geometry>
+struct visit_breadth_first<Geometry, geometry_collection_tag>
+ : detail::visit_breadth_first_impl<>
+{};
+
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
diff --git a/boost/geometry/algorithms/detail/within/implementation.hpp b/boost/geometry/algorithms/detail/within/implementation.hpp
index 72561cd890..b5300a9934 100644
--- a/boost/geometry/algorithms/detail/within/implementation.hpp
+++ b/boost/geometry/algorithms/detail/within/implementation.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2013-2021.
-// Modifications copyright (c) 2013-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -29,7 +29,8 @@
#include <boost/geometry/algorithms/detail/within/interface.hpp>
#include <boost/geometry/algorithms/detail/within/multi_point.hpp>
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
-#include <boost/geometry/algorithms/relate.hpp>
+#include <boost/geometry/algorithms/detail/relate/implementation.hpp>
+#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/closure.hpp>
@@ -68,11 +69,12 @@ struct use_relate
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
- typedef typename detail::de9im::static_mask_within_type
+ return detail::relate::relate_impl
<
- Geometry1, Geometry2
- >::type within_mask;
- return geometry::relate(geometry1, geometry2, within_mask(), strategy);
+ detail::de9im::static_mask_within_type,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/within/implementation_gc.hpp b/boost/geometry/algorithms/detail/within/implementation_gc.hpp
new file mode 100644
index 0000000000..6f40f318d8
--- /dev/null
+++ b/boost/geometry/algorithms/detail/within/implementation_gc.hpp
@@ -0,0 +1,46 @@
+// Boost.Geometry
+
+// Copyright (c) 2022 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_IMPLEMENTATION_GC_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_IMPLEMENTATION_GC_HPP
+
+
+#include <boost/geometry/algorithms/detail/relate/implementation_gc.hpp>
+#include <boost/geometry/algorithms/detail/within/implementation.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+template <typename Geometry1, typename Geometry2>
+struct within<Geometry1, Geometry2, geometry_collection_tag, geometry_collection_tag>
+ : detail::within::use_relate
+{};
+
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct within<Geometry1, Geometry2, Tag1, geometry_collection_tag>
+ : detail::within::use_relate
+{};
+
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct within<Geometry1, Geometry2, geometry_collection_tag, Tag2>
+ : detail::within::use_relate
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_IMPLEMENTATION_GC_HPP
diff --git a/boost/geometry/algorithms/detail/within/interface.hpp b/boost/geometry/algorithms/detail/within/interface.hpp
index 1a10ca84d8..572e0e5c94 100644
--- a/boost/geometry/algorithms/detail/within/interface.hpp
+++ b/boost/geometry/algorithms/detail/within/interface.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2013-2021.
-// Modifications copyright (c) 2013-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -21,16 +21,14 @@
#include <boost/concept_check.hpp>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tag_cast.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
+
#include <boost/geometry/strategies/concepts/within_concept.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
@@ -126,10 +124,15 @@ struct within<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant
+namespace resolve_dynamic
{
-template <typename Geometry1, typename Geometry2>
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct within
{
template <typename Strategy>
@@ -148,110 +151,66 @@ struct within
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct within<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct within<Geometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2, Strategy const& strategy)
- : m_geometry2(geometry2)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- bool operator()(Geometry1 const& geometry1) const
+ bool result = false;
+ traits::visit<Geometry1>::apply([&](auto const& g1)
{
- return within<Geometry1, Geometry2>::apply(geometry1,
- m_geometry2,
- m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry2, strategy),
- geometry1);
+ result = within
+ <
+ util::remove_cref_t<decltype(g1)>,
+ Geometry2
+ >::apply(g1, geometry2, strategy);
+ }, geometry1);
+ return result;
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct within<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct within<Geometry1, Geometry2, Tag1, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1, Strategy const& strategy)
- : m_geometry1(geometry1)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- bool operator()(Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry2>::apply([&](auto const& g2)
{
- return within<Geometry1, Geometry2>::apply(m_geometry1,
- geometry2,
- m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool
- apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry1, strategy),
- geometry2
- );
+ result = within
+ <
+ Geometry1,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(geometry1, g2, strategy);
+ }, geometry2);
+ return result;
}
};
-template <
- BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)
->
-struct within<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
->
+template <typename Geometry1, typename Geometry2>
+struct within<Geometry1, Geometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy): m_strategy(strategy) {}
-
- template <typename Geometry1, typename Geometry2>
- bool operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry1, Geometry2>::apply([&](auto const& g1, auto const& g2)
{
- return within<Geometry1, Geometry2>::apply(geometry1,
- geometry2,
- m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(strategy),
- geometry1,
- geometry2);
+ result = within
+ <
+ util::remove_cref_t<decltype(g1)>,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(g1, g2, strategy);
+ }, geometry1, geometry2);
+ return result;
}
};
@@ -282,7 +241,7 @@ struct within<
template<typename Geometry1, typename Geometry2>
inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
- return resolve_variant::within
+ return resolve_dynamic::within
<
Geometry1,
Geometry2
@@ -320,7 +279,7 @@ inline bool within(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
- return resolve_variant::within
+ return resolve_dynamic::within
<
Geometry1,
Geometry2
diff --git a/boost/geometry/algorithms/detail/within/multi_point.hpp b/boost/geometry/algorithms/detail/within/multi_point.hpp
index 349ef03026..be984e9364 100644
--- a/boost/geometry/algorithms/detail/within/multi_point.hpp
+++ b/boost/geometry/algorithms/detail/within/multi_point.hpp
@@ -1,6 +1,10 @@
// Boost.Geometry
-// Copyright (c) 2017-2020, Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+
+// 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
// Use, modification and distribution is subject to the Boost Software License,
@@ -38,6 +42,7 @@
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/disjoint.hpp>
+#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/type_traits.hpp>
@@ -55,8 +60,7 @@ struct multi_point_point
{
auto const s = strategy.relate(multi_point, point);
- typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
- for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
+ for (auto it = boost::begin(multi_point); it != boost::end(multi_point); ++it)
{
if (! s.apply(*it, point))
{
@@ -78,8 +82,7 @@ struct multi_point_multi_point
Strategy const& /*strategy*/)
{
typedef typename boost::range_value<MultiPoint2>::type point2_type;
- typedef typename Strategy::cs_tag cs_tag;
- typedef geometry::less<void, -1, cs_tag> less_type;
+ typedef geometry::less<void, -1, Strategy> less_type;
less_type const less = less_type();
@@ -88,8 +91,7 @@ struct multi_point_multi_point
bool result = false;
- typedef typename boost::range_const_iterator<MultiPoint1>::type iterator;
- for ( iterator it = boost::begin(multi_point1) ; it != boost::end(multi_point1) ; ++it )
+ for (auto it = boost::begin(multi_point1); it != boost::end(multi_point1); ++it)
{
if (! std::binary_search(points2.begin(), points2.end(), *it, less))
{
@@ -134,13 +136,12 @@ struct multi_point_single_geometry
// If in the exterior, break
bool result = false;
- typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
- for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
+ for (auto it = boost::begin(multi_point); it != boost::end(multi_point); ++it )
{
typedef decltype(strategy.covered_by(*it, box)) point_in_box_type;
int in_val = 0;
-
+
// exterior of box and of geometry
if (! point_in_box_type::apply(*it, box)
|| (in_val = point_in_geometry(*it, linear_or_areal, strategy)) < 0)
@@ -198,8 +199,7 @@ struct multi_point_multi_geometry
// If a point is in the exterior break
bool result = false;
- typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
- for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
+ for (auto it = boost::begin(multi_point); it != boost::end(multi_point); ++it)
{
// TODO: investigate the possibility of using satisfies
// TODO: investigate the possibility of using iterative queries (optimization below)
@@ -238,7 +238,7 @@ struct multi_point_multi_geometry
if (boundaries > 0)
{
- if (is_linear && boundaries % 2 == 0)
+ if (BOOST_GEOMETRY_CONDITION(is_linear) && boundaries % 2 == 0)
{
found_interior = true;
}
diff --git a/boost/geometry/algorithms/detail/within/point_in_geometry.hpp b/boost/geometry/algorithms/detail/within/point_in_geometry.hpp
index c9b9cbfd81..459e54ec85 100644
--- a/boost/geometry/algorithms/detail/within/point_in_geometry.hpp
+++ b/boost/geometry/algorithms/detail/within/point_in_geometry.hpp
@@ -30,7 +30,6 @@
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/concepts/within_concept.hpp>
@@ -49,13 +48,12 @@ int point_in_range(Point const& point, Range const& range, Strategy const& strat
{
typename Strategy::state_type state;
- typedef typename boost::range_iterator<Range const>::type iterator_type;
- iterator_type it = boost::begin(range);
- iterator_type end = boost::end(range);
+ auto it = boost::begin(range);
+ auto const end = boost::end(range);
- for ( iterator_type previous = it++ ; it != end ; ++previous, ++it )
+ for (auto previous = it++; it != end; ++previous, ++it)
{
- if ( ! strategy.apply(point, *previous, *it, state) )
+ if (! strategy.apply(point, *previous, *it, state))
{
break;
}
@@ -202,13 +200,8 @@ struct point_in_geometry<Polygon, polygon_tag>
if (code == 1)
{
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(polygon);
-
- for (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings);
- it != boost::end(rings);
- ++it)
+ auto const& rings = interior_rings(polygon);
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
int const interior_code = point_in_geometry
<
@@ -235,14 +228,16 @@ struct point_in_geometry<Geometry, multi_point_tag>
int apply(Point const& point, Geometry const& geometry, Strategy const& strategy)
{
typedef typename boost::range_value<Geometry>::type point_type;
- typedef typename boost::range_const_iterator<Geometry>::type iterator;
- for ( iterator it = boost::begin(geometry) ; it != boost::end(geometry) ; ++it )
+ for (auto it = boost::begin(geometry); it != boost::end(geometry); ++it)
{
int pip = point_in_geometry<point_type>::apply(point, *it, strategy);
//BOOST_GEOMETRY_ASSERT(pip != 0);
- if ( pip > 0 ) // inside
+ if (pip > 0)
+ {
+ // inside
return 1;
+ }
}
return -1; // outside
@@ -259,14 +254,13 @@ struct point_in_geometry<Geometry, multi_linestring_tag>
typedef typename boost::range_value<Geometry>::type linestring_type;
typedef typename boost::range_value<linestring_type>::type point_type;
- typedef typename boost::range_iterator<Geometry const>::type iterator;
- iterator it = boost::begin(geometry);
- for ( ; it != boost::end(geometry) ; ++it )
+ auto it = boost::begin(geometry);
+ for ( ; it != boost::end(geometry); ++it)
{
pip = point_in_geometry<linestring_type>::apply(point, *it, strategy);
// inside or on the boundary
- if ( pip >= 0 )
+ if (pip >= 0)
{
++it;
break;
@@ -274,24 +268,30 @@ struct point_in_geometry<Geometry, multi_linestring_tag>
}
// outside
- if ( pip < 0 )
+ if (pip < 0)
+ {
return -1;
+ }
// TODO: the following isn't needed for covered_by()
unsigned boundaries = pip == 0 ? 1 : 0;
- for ( ; it != boost::end(geometry) ; ++it )
+ for (; it != boost::end(geometry); ++it)
{
- if ( boost::size(*it) < 2 )
+ if (boost::size(*it) < 2)
+ {
continue;
+ }
point_type const& front = range::front(*it);
point_type const& back = range::back(*it);
// is closed_ring - no boundary
- if ( detail::equals::equals_point_point(front, back, strategy) )
+ if (detail::equals::equals_point_point(front, back, strategy))
+ {
continue;
+ }
// is point on boundary
if ( detail::equals::equals_point_point(point, front, strategy)
@@ -316,14 +316,15 @@ struct point_in_geometry<Geometry, multi_polygon_tag>
//int res = -1; // outside
typedef typename boost::range_value<Geometry>::type polygon_type;
- typedef typename boost::range_const_iterator<Geometry>::type iterator;
- for ( iterator it = boost::begin(geometry) ; it != boost::end(geometry) ; ++it )
+ for (auto it = boost::begin(geometry); it != boost::end(geometry); ++it)
{
int pip = point_in_geometry<polygon_type>::apply(point, *it, strategy);
// inside or on the boundary
- if ( pip >= 0 )
+ if (pip >= 0)
+ {
return pip;
+ }
// For invalid multi-polygons
//if ( 1 == pip ) // inside polygon
diff --git a/boost/geometry/algorithms/detail/within/within_no_turns.hpp b/boost/geometry/algorithms/detail/within/within_no_turns.hpp
index 8da05e58fd..d6d0417c3b 100644
--- a/boost/geometry/algorithms/detail/within/within_no_turns.hpp
+++ b/boost/geometry/algorithms/detail/within/within_no_turns.hpp
@@ -4,8 +4,9 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2013.
-// Modifications copyright (c) 2013, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2023.
+// Modifications copyright (c) 2013-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -41,8 +42,10 @@ struct within_no_turns
{
typedef typename geometry::point_type<Geometry1>::type point1_type;
point1_type p;
- if ( !geometry::point_on_border(p, geometry1) )
+ if (! geometry::point_on_border(p, geometry1))
+ {
return false;
+ }
return detail::within::point_in_geometry(p, geometry2, strategy) >= 0;
}
@@ -57,25 +60,28 @@ struct within_no_turns<Geometry1, Geometry2, ring_tag, polygon_tag>
typedef typename geometry::point_type<Geometry1>::type point1_type;
typedef typename geometry::point_type<Geometry2>::type point2_type;
point1_type p;
- if ( !geometry::point_on_border(p, geometry1) )
+ if (! geometry::point_on_border(p, geometry1))
+ {
return false;
+ }
// check if one of ring points is outside the polygon
- if ( detail::within::point_in_geometry(p, geometry2, strategy) < 0 )
+ if (detail::within::point_in_geometry(p, geometry2, strategy) < 0)
+ {
return false;
+ }
// Now check if holes of G2 aren't inside G1
- typedef typename boost::range_const_iterator
- <
- typename geometry::interior_type<Geometry2>::type
- >::type iterator;
- for ( iterator it = boost::begin(geometry::interior_rings(geometry2)) ;
- it != boost::end(geometry::interior_rings(geometry2)) ;
- ++it )
+ auto const& rings2 = geometry::interior_rings(geometry2);
+ for (auto it = boost::begin(rings2); it != boost::end(rings2); ++it)
{
point2_type p;
- if ( !geometry::point_on_border(p, *it) )
+ if (! geometry::point_on_border(p, *it))
+ {
return false;
- if ( detail::within::point_in_geometry(p, geometry1, strategy) > 0 )
+ }
+ if (detail::within::point_in_geometry(p, geometry1, strategy) > 0)
+ {
return false;
+ }
}
return true;
}
@@ -90,44 +96,42 @@ struct within_no_turns<Geometry1, Geometry2, polygon_tag, polygon_tag>
typedef typename geometry::point_type<Geometry1>::type point1_type;
typedef typename geometry::point_type<Geometry2>::type point2_type;
point1_type p;
- if ( !geometry::point_on_border(p, geometry1) )
+ if (! geometry::point_on_border(p, geometry1))
+ {
return false;
+ }
// check if one of ring points is outside the polygon
- if ( detail::within::point_in_geometry(p, geometry2, strategy) < 0 )
+ if (detail::within::point_in_geometry(p, geometry2, strategy) < 0)
+ {
return false;
+ }
// Now check if holes of G2 aren't inside G1
- typedef typename boost::range_const_iterator
- <
- typename geometry::interior_type<Geometry2>::type
- >::type iterator2;
- for ( iterator2 it = boost::begin(geometry::interior_rings(geometry2)) ;
- it != boost::end(geometry::interior_rings(geometry2)) ;
- ++it )
+ auto const& rings2 = geometry::interior_rings(geometry2);
+ for (auto it2 = boost::begin(rings2); it2 != boost::end(rings2); ++it2)
{
point2_type p2;
- if ( !geometry::point_on_border(p2, *it) )
+ if (! geometry::point_on_border(p2, *it2))
+ {
return false;
+ }
// if the hole of G2 is inside G1
- if ( detail::within::point_in_geometry(p2, geometry1, strategy) > 0 )
+ if (detail::within::point_in_geometry(p2, geometry1, strategy) > 0)
{
// if it's also inside one of the G1 holes, it's ok
bool ok = false;
- typedef typename boost::range_const_iterator
- <
- typename geometry::interior_type<Geometry1>::type
- >::type iterator1;
- for ( iterator1 it1 = boost::begin(geometry::interior_rings(geometry1)) ;
- it1 != boost::end(geometry::interior_rings(geometry1)) ;
- ++it1 )
+ auto const& rings1 = geometry::interior_rings(geometry1);
+ for (auto it1 = boost::begin(rings1); it1 != boost::end(rings1); ++it1)
{
- if ( detail::within::point_in_geometry(p2, *it1, strategy) < 0 )
+ if (detail::within::point_in_geometry(p2, *it1, strategy) < 0)
{
ok = true;
break;
}
}
- if ( !ok )
+ if (! ok)
+ {
return false;
+ }
}
}
return true;
@@ -157,11 +161,12 @@ struct within_no_turns_multi<Geometry1, Geometry2, Tag1, Tag2, true, false>
{
// All values of G1 must be inside G2
typedef typename boost::range_value<Geometry1>::type subgeometry1;
- typedef typename boost::range_const_iterator<Geometry1>::type iterator;
- for ( iterator it = boost::begin(geometry1) ; it != boost::end(geometry1) ; ++it )
+ for (auto it = boost::begin(geometry1) ; it != boost::end(geometry1) ; ++it )
{
- if ( !within_no_turns<subgeometry1, Geometry2>::apply(*it, geometry2, strategy) )
+ if (! within_no_turns<subgeometry1, Geometry2>::apply(*it, geometry2, strategy))
+ {
return false;
+ }
}
return true;
}
@@ -175,11 +180,12 @@ struct within_no_turns_multi<Geometry1, Geometry2, Tag1, Tag2, false, true>
{
// G1 must be within at least one value of G2
typedef typename boost::range_value<Geometry2>::type subgeometry2;
- typedef typename boost::range_const_iterator<Geometry2>::type iterator;
- for ( iterator it = boost::begin(geometry2) ; it != boost::end(geometry2) ; ++it )
+ for (auto it = boost::begin(geometry2); it != boost::end(geometry2); ++it)
{
- if ( within_no_turns<Geometry1, subgeometry2>::apply(geometry1, *it, strategy) )
+ if (within_no_turns<Geometry1, subgeometry2>::apply(geometry1, *it, strategy))
+ {
return true;
+ }
}
return false;
}
@@ -193,11 +199,12 @@ struct within_no_turns_multi<Geometry1, Geometry2, Tag1, Tag2, true, true>
{
// each value of G1 must be inside at least one value of G2
typedef typename boost::range_value<Geometry1>::type subgeometry1;
- typedef typename boost::range_const_iterator<Geometry1>::type iterator;
- for ( iterator it = boost::begin(geometry1) ; it != boost::end(geometry1) ; ++it )
+ for (auto it = boost::begin(geometry1) ; it != boost::end(geometry1) ; ++it)
{
- if ( !within_no_turns_multi<subgeometry1, Geometry2>::apply(*it, geometry2, strategy) )
+ if (! within_no_turns_multi<subgeometry1, Geometry2>::apply(*it, geometry2, strategy))
+ {
return false;
+ }
}
return true;
}