summaryrefslogtreecommitdiff
path: root/boost/geometry/algorithms/detail/overlay/overlay.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/algorithms/detail/overlay/overlay.hpp')
-rw-r--r--boost/geometry/algorithms/detail/overlay/overlay.hpp139
1 files changed, 98 insertions, 41 deletions
diff --git a/boost/geometry/algorithms/detail/overlay/overlay.hpp b/boost/geometry/algorithms/detail/overlay/overlay.hpp
index 6eb0b8864c..c3ecaa0b01 100644
--- a/boost/geometry/algorithms/detail/overlay/overlay.hpp
+++ b/boost/geometry/algorithms/detail/overlay/overlay.hpp
@@ -26,6 +26,7 @@
#include <boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp>
#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
+#include <boost/geometry/algorithms/detail/overlay/handle_touch.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/traverse.hpp>
#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
@@ -59,28 +60,50 @@ namespace detail { namespace overlay
{
-template <typename TurnPoints, typename TurnInfoMap>
-inline void get_ring_turn_info(TurnInfoMap& turn_info_map,
- TurnPoints const& turn_points)
+//! Default visitor for overlay, doing nothing
+struct overlay_null_visitor
{
- typedef typename boost::range_value<TurnPoints>::type turn_point_type;
- typedef typename turn_point_type::container_type container_type;
+ void print(char const* ) {}
- for (typename boost::range_iterator<TurnPoints const>::type
- it = boost::begin(turn_points);
- it != boost::end(turn_points);
+ template <typename Turns>
+ void print(char const* , Turns const& , int) {}
+
+ template <typename Turns>
+ void print(char const* , Turns const& , int , int ) {}
+
+ template <typename Turns>
+ void visit_turns(int , Turns const& ) {}
+
+ template <typename Clusters, typename Turns>
+ void visit_clusters(Clusters const& , Turns const& ) {}
+
+ template <typename Turns, typename Turn, typename Operation>
+ void visit_traverse(Turns const& , Turn const& , Operation const& , char const*)
+ {}
+
+ template <typename Turns, typename Turn, typename Operation>
+ void visit_traverse_reject(Turns const& , Turn const& , Operation const& , traverse_error_type )
+ {}
+};
+
+template <typename Turns, typename TurnInfoMap>
+inline void get_ring_turn_info(TurnInfoMap& turn_info_map, Turns const& turns)
+{
+ typedef typename boost::range_value<Turns>::type turn_type;
+ typedef typename turn_type::container_type container_type;
+
+ for (typename boost::range_iterator<Turns const>::type
+ it = boost::begin(turns);
+ it != boost::end(turns);
++it)
{
- typename boost::range_value<TurnPoints>::type const& turn_info = *it;
- bool both_uu = turn_info.both(operation_union);
- bool skip = (turn_info.discarded || both_uu)
- && ! turn_info.any_blocked()
- && ! turn_info.both(operation_intersection)
- ;
+ typename boost::range_value<Turns>::type const& turn_info = *it;
- if (! both_uu && turn_info.colocated)
+ if (turn_info.discarded
+ && ! turn_info.any_blocked()
+ && ! turn_info.colocated)
{
- skip = true;
+ continue;
}
for (typename boost::range_iterator<container_type const>::type
@@ -88,21 +111,13 @@ inline void get_ring_turn_info(TurnInfoMap& turn_info_map,
op_it != boost::end(turn_info.operations);
++op_it)
{
- ring_identifier ring_id
+ ring_identifier const ring_id
(
op_it->seg_id.source_index,
op_it->seg_id.multi_index,
op_it->seg_id.ring_index
);
-
- if (! skip)
- {
- turn_info_map[ring_id].has_normal_turn = true;
- }
- else if (both_uu)
- {
- turn_info_map[ring_id].has_uu_turn = true;
- }
+ turn_info_map[ring_id].has_normal_turn = true;
}
}
}
@@ -164,12 +179,13 @@ template
>
struct overlay
{
- template <typename RobustPolicy, typename OutputIterator, typename Strategy>
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy, typename Visitor>
static inline OutputIterator apply(
Geometry1 const& geometry1, Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
OutputIterator out,
- Strategy const& )
+ Strategy const& ,
+ Visitor& visitor)
{
bool const is_empty1 = geometry::is_empty(geometry1);
bool const is_empty2 = geometry::is_empty(geometry2);
@@ -193,14 +209,23 @@ struct overlay
point_type,
typename geometry::segment_ratio_type<point_type, RobustPolicy>::type
> turn_info;
- typedef std::deque<turn_info> container_type;
+ typedef std::deque<turn_info> turn_container_type;
typedef std::deque
<
typename geometry::ring_type<GeometryOut>::type
> ring_container_type;
- container_type turn_points;
+ // Define the clusters, mapping cluster_id -> turns
+ typedef std::map
+ <
+ signed_size_type,
+ std::set<signed_size_type>
+ > cluster_type;
+
+ cluster_type clusters;
+
+ turn_container_type turns;
#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "get turns" << std::endl;
@@ -210,20 +235,42 @@ std::cout << "get turns" << std::endl;
<
Reverse1, Reverse2,
detail::overlay::assign_null_policy
- >(geometry1, geometry2, robust_policy, turn_points, policy);
+ >(geometry1, geometry2, robust_policy, turns, policy);
+
+ visitor.visit_turns(1, turns);
+
+ static const operation_type op_type
+ = OverlayType == overlay_union
+ ? geometry::detail::overlay::operation_union
+ : geometry::detail::overlay::operation_intersection;
#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "enrich" << std::endl;
#endif
typename Strategy::side_strategy_type side_strategy;
- geometry::enrich_intersection_points<Reverse1, Reverse2, OverlayType>(turn_points,
- OverlayType == overlay_union
- ? geometry::detail::overlay::operation_union
- : geometry::detail::overlay::operation_intersection,
+ geometry::enrich_intersection_points<Reverse1, Reverse2, OverlayType>(turns,
+ clusters, op_type,
geometry1, geometry2,
robust_policy,
side_strategy);
+ visitor.visit_turns(2, turns);
+
+ visitor.visit_clusters(clusters, turns);
+
+
+#if 0
+ // TODO: does not work always correctly, move to traverse and fix
+ if (op_type == geometry::detail::overlay::operation_union)
+ {
+ #ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+ std::cout << "handle_touch" << std::endl;
+ #endif
+
+ handle_touch(op_type, turns, visitor);
+ }
+#endif
+
#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
std::cout << "traverse" << std::endl;
#endif
@@ -231,18 +278,17 @@ std::cout << "traverse" << std::endl;
// Note that these rings are always in clockwise order, even in CCW polygons,
// and are marked as "to be reversed" below
ring_container_type rings;
- traverse<Reverse1, Reverse2, Geometry1, Geometry2>::apply
+ traverse<Reverse1, Reverse2, Geometry1, Geometry2, op_type>::apply
(
geometry1, geometry2,
- OverlayType == overlay_union
- ? geometry::detail::overlay::operation_union
- : geometry::detail::overlay::operation_intersection,
robust_policy,
- turn_points, rings
+ turns, rings,
+ clusters,
+ visitor
);
std::map<ring_identifier, ring_turn_info> turn_info_per_ring;
- get_ring_turn_info(turn_info_per_ring, turn_points);
+ get_ring_turn_info(turn_info_per_ring, turns);
typedef ring_properties
<
@@ -272,6 +318,17 @@ std::cout << "traverse" << std::endl;
return add_rings<GeometryOut>(selected_ring_properties, geometry1, geometry2, rings, out);
}
+
+ template <typename RobustPolicy, typename OutputIterator, typename Strategy>
+ static inline OutputIterator apply(
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ RobustPolicy const& robust_policy,
+ OutputIterator out,
+ Strategy const& strategy)
+ {
+ overlay_null_visitor visitor;
+ return apply(geometry1, geometry2, robust_policy, out, strategy, visitor);
+ }
};