static inline OutputIterator apply( Geometry1 const& geometry1, Geometry2 const& geometry2, RobustPolicy const& robust_policy, OutputIterator out, Strategy const& ) { if ( geometry::num_points(geometry1) == 0 && geometry::num_points(geometry2) == 0 ) { return out; } if ( geometry::num_points(geometry1) == 0 || geometry::num_points(geometry2) == 0 ) { return return_if_one_input_is_empty < GeometryOut, Direction, ReverseOut >(geometry1, geometry2, out); } 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> container_type; typedef std::deque < typename geometry::ring_type<GeometryOut>::type > ring_container_type; container_type turn_points; #ifdef BOOST_GEOMETRY_TIME_OVERLAY boost::timer timer; #endif #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, robust_policy, turn_points, policy); #ifdef BOOST_GEOMETRY_TIME_OVERLAY std::cout << "get_turns: " << timer.elapsed() << std::endl; #endif #ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE std::cout << "enrich" << std::endl; #endif typename Strategy::side_strategy_type side_strategy; geometry::enrich_intersection_points<Reverse1, Reverse2>(turn_points, Direction == overlay_union ? geometry::detail::overlay::operation_union : geometry::detail::overlay::operation_intersection, geometry1, geometry2, robust_policy, side_strategy); #ifdef BOOST_GEOMETRY_TIME_OVERLAY std::cout << "enrich_intersection_points: " << timer.elapsed() << std::endl; #endif #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>::apply ( geometry1, geometry2, Direction == overlay_union ? geometry::detail::overlay::operation_union : geometry::detail::overlay::operation_intersection, robust_policy, turn_points, rings ); #ifdef BOOST_GEOMETRY_TIME_OVERLAY std::cout << "traverse: " << timer.elapsed() << std::endl; #endif std::map<ring_identifier, int> map; map_turns(map, turn_points); #ifdef BOOST_GEOMETRY_TIME_OVERLAY std::cout << "map_turns: " << timer.elapsed() << std::endl; #endif typedef ring_properties<typename geometry::point_type<GeometryOut>::type> properties; std::map<ring_identifier, properties> selected; select_rings<Direction>(geometry1, geometry2, map, selected, ! turn_points.empty()); #ifdef BOOST_GEOMETRY_TIME_OVERLAY std::cout << "select_rings: " << timer.elapsed() << std::endl; #endif // 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) { selected[id] = properties(*it, true); selected[id].reversed = ReverseOut; id.multi_index++; } } #ifdef BOOST_GEOMETRY_TIME_OVERLAY std::cout << "add traversal rings: " << timer.elapsed() << std::endl; #endif assign_parents(geometry1, geometry2, rings, selected); #ifdef BOOST_GEOMETRY_TIME_OVERLAY std::cout << "assign_parents: " << timer.elapsed() << std::endl; #endif return add_rings<GeometryOut>(selected, geometry1, geometry2, rings, out); }
static inline OutputIterator apply(Geometry const& geometry, OutputIterator out) { // Get the self-intersection points, including turns typedef detail::overlay::traversal_turn_info < typename point_type<Geometry>::type > turn_info; std::vector<turn_info> turns; detail::dissolve::no_interrupt_policy policy; geometry::self_turns < detail::overlay::calculate_distance_policy >(geometry, turns, policy); // The dissolve process is not necessary if there are no turns at all if (boost::size(turns) > 0) { typedef typename ring_type<Geometry>::type ring_type; typedef std::vector<ring_type> out_vector; out_vector rings; // Enrich the turns typedef typename strategy::side::services::default_strategy < typename cs_tag<Geometry>::type >::type side_strategy_type; enrich_intersection_points<false, false>(turns, detail::overlay::operation_union, geometry, geometry, side_strategy_type()); typedef detail::overlay::traverse < false, false, Geometry, Geometry, backtrack_for_dissolve<Geometry> > traverser; // Traverse the polygons twice for union... traverser::apply(geometry, geometry, detail::overlay::operation_union, turns, rings); clear_visit_info(turns); enrich_intersection_points<false, false>(turns, detail::overlay::operation_intersection, geometry, geometry, side_strategy_type()); // ... and for intersection traverser::apply(geometry, geometry, detail::overlay::operation_intersection, turns, rings); std::map<ring_identifier, int> map; map_turns(map, turns); typedef detail::overlay::ring_properties<typename geometry::point_type<Geometry>::type> properties; std::map<ring_identifier, properties> selected; detail::overlay::select_rings<overlay_union>(geometry, map, selected, true); // Add intersected rings { ring_identifier id(2, 0, -1); for (typename boost::range_iterator<std::vector<ring_type> const>::type it = boost::begin(rings); it != boost::end(rings); ++it) { selected[id] = properties(*it, true); id.multi_index++; } } detail::overlay::assign_parents(geometry, rings, selected); return detail::overlay::add_rings<GeometryOut>(selected, geometry, rings, out); } else { GeometryOut g; geometry::convert(geometry, g); *out++ = g; return out; } }