summaryrefslogtreecommitdiff
path: root/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/algorithms/detail/overlay/handle_colocations.hpp')
-rw-r--r--boost/geometry/algorithms/detail/overlay/handle_colocations.hpp93
1 files changed, 74 insertions, 19 deletions
diff --git a/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp b/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
index f3311b34e9..c634fc450f 100644
--- a/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
+++ b/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
@@ -24,6 +24,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/is_self_turn.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/overlay/turn_info.hpp>
@@ -181,6 +182,7 @@ inline signed_size_type add_turn_to_cluster(Turn const& turn,
if (cid0 == -1 && cid1 == -1)
{
+ // Because of this, first cluster ID will be 1
++cluster_id;
add_cluster_id(turn.operations[0], cluster_per_segment, cluster_id);
add_cluster_id(turn.operations[1], cluster_per_segment, cluster_id);
@@ -314,7 +316,7 @@ inline void assign_cluster_to_turns(Turns& turns,
if (it != cluster_per_segment.end())
{
#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_COLOCATIONS)
- if (turn.cluster_id != -1
+ if (turn.is_clustered()
&& turn.cluster_id != it->second)
{
std::cout << " CONFLICT " << std::endl;
@@ -503,6 +505,7 @@ inline void discard_interior_exterior_turns(Turns& turns, Clusters& clusters)
template
<
+ overlay_type OverlayType,
typename Turns,
typename Clusters
>
@@ -517,38 +520,65 @@ inline void set_colocation(Turns& turns, Clusters const& clusters)
cluster_info const& cinfo = cit->second;
std::set<signed_size_type> const& ids = cinfo.turn_indices;
- bool has_ii = false;
- bool has_uu = false;
+ bool both_target = false;
for (set_iterator it = ids.begin(); it != ids.end(); ++it)
{
turn_type const& turn = turns[*it];
- if (turn.both(operation_intersection))
- {
- has_ii = true;
- }
- if (turn.both(operation_union) || turn.combination(operation_union, operation_blocked))
+ if (turn.both(operation_from_overlay<OverlayType>::value))
{
- has_uu = true;
+ both_target = true;
+ break;
}
}
- if (has_ii || has_uu)
+
+ if (both_target)
{
for (set_iterator it = ids.begin(); it != ids.end(); ++it)
{
turn_type& turn = turns[*it];
- if (has_ii)
- {
- turn.colocated_ii = true;
- }
- if (has_uu)
+
+ if (both_target)
{
- turn.colocated_uu = true;
+ turn.has_colocated_both = true;
}
}
}
}
}
+template
+<
+ typename Turns,
+ typename Clusters
+>
+inline void check_colocation(bool& has_blocked,
+ int cluster_id, Turns const& turns, Clusters const& clusters)
+{
+ typedef typename boost::range_value<Turns>::type turn_type;
+
+ has_blocked = false;
+
+ typename Clusters::const_iterator mit = clusters.find(cluster_id);
+ if (mit == clusters.end())
+ {
+ return;
+ }
+
+ 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)
+ {
+ turn_type const& turn = turns[*it];
+ if (turn.any_blocked())
+ {
+ has_blocked = true;
+ }
+ }
+}
+
+
// Checks colocated turns and flags combinations of uu/other, possibly a
// combination of a ring touching another geometry's interior ring which is
// tangential to the exterior ring
@@ -627,6 +657,10 @@ inline bool handle_colocations(Turns& turns, Clusters& clusters,
> cluster_per_segment_type;
cluster_per_segment_type cluster_per_segment;
+
+ // Assign to zero, because of pre-increment later the cluster_id
+ // effectively starts with 1
+ // (and can later be negated to use uniquely with turn_index)
signed_size_type cluster_id = 0;
for (typename map_type::const_iterator it = map.begin();
@@ -640,7 +674,9 @@ inline bool handle_colocations(Turns& turns, Clusters& clusters,
}
assign_cluster_to_turns(turns, clusters, cluster_per_segment);
- set_colocation(turns, clusters);
+ // Get colocated information here and not later, to keep information
+ // on turns which are discarded afterwards
+ set_colocation<OverlayType>(turns, clusters);
discard_interior_exterior_turns
<
do_reverse<geometry::point_order<Geometry1>::value>::value != Reverse1,
@@ -758,14 +794,21 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
cinfo.open_count = sbs.open_count(for_operation);
- // Unset the startable flag for all 'closed' zones
+ bool const set_startable
+ = OverlayType != overlay_dissolve_union
+ && OverlayType != overlay_dissolve_intersection;
+
+ // Unset the startable flag for all 'closed' zones. This does not
+ // apply for self-turns, because those counts are not from both
+ // polygons
for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
{
const typename sbs_type::rp& ranked = sbs.m_ranked_points[i];
turn_type& turn = turns[ranked.turn_index];
turn_operation_type& op = turn.operations[ranked.operation_index];
- if (for_operation == operation_union && cinfo.open_count == 0)
+ if (set_startable
+ && for_operation == operation_union && cinfo.open_count == 0)
{
op.enriched.startable = false;
}
@@ -780,6 +823,18 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
op.enriched.rank = ranked.rank;
op.enriched.zone = ranked.zone;
+ if (! set_startable)
+ {
+ continue;
+ }
+
+ if (OverlayType != overlay_difference
+ && is_self_turn<OverlayType>(turn))
+ {
+ // Difference needs the self-turns, TODO: investigate
+ continue;
+ }
+
if ((for_operation == operation_union
&& ranked.count_left != 0)
|| (for_operation == operation_intersection