static inline bool apply(Polygon const& polygon, TurnIterator first, TurnIterator beyond) { return are_holes_inside(geometry::interior_rings(polygon), geometry::exterior_ring(polygon), first, beyond); }
static inline bool are_holes_inside(InteriorRings const& interior_rings, ExteriorRing const& exterior_ring, IndexSet const& rings_with_turns) { return are_holes_inside(boost::begin(interior_rings), boost::end(interior_rings), exterior_ring, rings_with_turns); }
static inline bool are_holes_inside(InteriorRings const& interior_rings, ExteriorRing const& exterior_ring, TurnIterator first, TurnIterator beyond) { return are_holes_inside(boost::begin(interior_rings), boost::end(interior_rings), exterior_ring, first, beyond); }
static inline bool apply(Polygon const& polygon) { typedef typename point_type<Polygon>::type point_type; typedef typename ring_type<Polygon>::type ring_type; typedef debug_validity_phase<Polygon> debug_phase; // check validity of exterior ring debug_phase::apply(1); if ( !detail::is_valid::is_valid_ring < ring_type, AllowDuplicates, false // do not check self intersections >::apply(exterior_ring(polygon)) ) { return false; } // check validity of interior rings debug_phase::apply(2); if ( !are_valid_interior_rings(geometry::interior_rings(polygon)) ) { return false; } // compute turns and check if all are acceptable debug_phase::apply(3); typedef typename geometry::rescale_policy_type < point_type >::type rescale_policy_type; typedef detail::overlay::turn_info < point_type, typename geometry::segment_ratio_type < point_type, rescale_policy_type >::type > turn_info; typedef detail::overlay::get_turn_info < detail::overlay::assign_null_policy > turn_policy; rescale_policy_type robust_policy = geometry::get_rescale_policy<rescale_policy_type>(polygon); detail::overlay::stateless_predicate_based_interrupt_policy < is_acceptable_turn > interrupt_policy; std::deque<turn_info> turns; geometry::self_turns<turn_policy>(polygon, robust_policy, turns, interrupt_policy); if ( interrupt_policy.has_intersections ) { return false; } debug_print_turns(turns.begin(), turns.end()); // put the ring id's that are associated with turns in a // container with fast lookup (std::set) std::set<int> rings_with_turns; for (typename std::deque<turn_info>::const_iterator tit = turns.begin(); tit != turns.end(); ++tit) { rings_with_turns.insert(tit->operations[0].seg_id.ring_index); rings_with_turns.insert(tit->operations[0].other_id.ring_index); } // check if all interior rings are inside the exterior ring debug_phase::apply(4); if ( !are_holes_inside(geometry::interior_rings(polygon), geometry::exterior_ring(polygon), rings_with_turns) ) { return false; } // check whether the interior of the polygon is a connected set debug_phase::apply(5); typedef graph_vertex<typename turn_info::point_type> graph_vertex; typedef complement_graph<graph_vertex> graph; graph g(geometry::num_interior_rings(polygon) + 1); for (typename std::deque<turn_info>::const_iterator tit = turns.begin(); tit != turns.end(); ++tit) { typename graph::vertex_handle v1 = g.add_vertex(tit->operations[0].seg_id.ring_index); typename graph::vertex_handle v2 = g.add_vertex(tit->operations[0].other_id.ring_index); typename graph::vertex_handle vip = g.add_vertex(tit->point); g.add_edge(v1, vip); g.add_edge(v2, vip); } debug_print_complement_graph(std::cout, g); return !g.has_cycles(); }