static inline OutputIterator apply( Geometry1 const& geometry1, Geometry2 const& geometry2, RobustPolicy const& robust_policy, OutputIterator out, Strategy const& strategy, Visitor& visitor) { bool const is_empty1 = geometry::is_empty(geometry1); bool const is_empty2 = geometry::is_empty(geometry2); if (is_empty1 && is_empty2) { return out; } if (is_empty1 || is_empty2) { return return_if_one_input_is_empty < GeometryOut, OverlayType, ReverseOut >(geometry1, geometry2, out, strategy); } typedef typename geometry::point_type<GeometryOut>::type point_type; typedef detail::overlay::traversal_turn_info < point_type, typename geometry::segment_ratio_type<point_type, RobustPolicy>::type > turn_info; typedef std::deque<turn_info> turn_container_type; typedef std::deque < typename geometry::ring_type<GeometryOut>::type > ring_container_type; // Define the clusters, mapping cluster_id -> turns typedef std::map < signed_size_type, cluster_info > cluster_type; turn_container_type turns; #ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE std::cout << "get turns" << std::endl; #endif detail::get_turns::no_interrupt_policy policy; geometry::get_turns < Reverse1, Reverse2, detail::overlay::assign_null_policy >(geometry1, geometry2, strategy, robust_policy, turns, policy); visitor.visit_turns(1, turns); #ifdef BOOST_GEOMETRY_INCLUDE_SELF_TURNS { self_get_turn_points::self_turns<Reverse1, assign_null_policy>(geometry1, strategy, robust_policy, turns, policy, 0); self_get_turn_points::self_turns<Reverse2, assign_null_policy>(geometry2, strategy, robust_policy, turns, policy, 1); } #endif #ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE std::cout << "enrich" << std::endl; #endif typename Strategy::side_strategy_type side_strategy = strategy.get_side_strategy(); cluster_type clusters; geometry::enrich_intersection_points<Reverse1, Reverse2, OverlayType>(turns, clusters, geometry1, geometry2, robust_policy, side_strategy); visitor.visit_turns(2, turns); visitor.visit_clusters(clusters, turns); #ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE std::cout << "traverse" << std::endl; #endif // Traverse through intersection/turn points and create rings of them. // 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, OverlayType>::apply ( geometry1, geometry2, strategy, robust_policy, turns, rings, clusters, visitor ); std::map<ring_identifier, ring_turn_info> turn_info_per_ring; get_ring_turn_info<OverlayType>(turn_info_per_ring, turns, clusters); typedef typename Strategy::template area_strategy<point_type>::type area_strategy_type; typedef ring_properties < point_type, typename area_strategy_type::return_type > properties; // Select all rings which are NOT touched by any intersection point std::map<ring_identifier, properties> selected_ring_properties; select_rings<OverlayType>(geometry1, geometry2, turn_info_per_ring, selected_ring_properties, strategy); // Add rings created during traversal { area_strategy_type const area_strategy = strategy.template get_area_strategy<point_type>(); ring_identifier id(2, 0, -1); for (typename boost::range_iterator<ring_container_type>::type it = boost::begin(rings); it != boost::end(rings); ++it) { selected_ring_properties[id] = properties(*it, area_strategy); selected_ring_properties[id].reversed = ReverseOut; id.multi_index++; } } assign_parents(geometry1, geometry2, rings, selected_ring_properties, strategy); return add_rings<GeometryOut>(selected_ring_properties, geometry1, geometry2, rings, out); }