Exemple #1
0
 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);
 }
Exemple #3
0
 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();
    }