static inline void discard_clusters(Turns& turns, Clusters const& clusters, Geometry0 const& geometry0, Geometry1 const& geometry1) { for (typename Clusters::const_iterator cit = clusters.begin(); cit != clusters.end(); ++cit) { signed_size_type cluster_id = cit->first; // If there are only self-turns in the cluster, the cluster should // be located within the other geometry, for intersection if (is_self_cluster(cluster_id, turns, clusters)) { cluster_info const& cinfo = cit->second; if (! within(turns[*cinfo.turn_indices.begin()], geometry0, geometry1)) { // Discard all turns in cluster for (std::set<signed_size_type>::const_iterator sit = cinfo.turn_indices.begin(); sit != cinfo.turn_indices.end(); ++sit) { turns[*sit].discarded = true; } } } } }
void visit_clusters(Clusters const& clusters, Turns const& turns) { typedef typename boost::range_value<Turns>::type turn_type; int index = 0; BOOST_FOREACH(turn_type const& turn, turns) { if (turn.cluster_id >= 0) { std::cout << " TURN: " << index << " part of cluster " << turn.cluster_id << std::endl; } index++; } for (typename Clusters::const_iterator it = clusters.begin(); it != clusters.end(); ++it) { std::cout << " CLUSTER " << it->first << ": "; for (typename std::set<bg::signed_size_type>::const_iterator sit = it->second.turn_indices.begin(); sit != it->second.turn_indices.end(); ++sit) { std::cout << " " << *sit; } std::cout << std::endl; } std::cout << std::endl; }
static inline bool any_blocked(signed_size_type cluster_id, const Turns& turns, Clusters const& clusters) { typename Clusters::const_iterator cit = clusters.find(cluster_id); if (cit == clusters.end()) { return false; } cluster_info const& cinfo = cit->second; for (std::set<signed_size_type>::const_iterator it = cinfo.turn_indices.begin(); it != cinfo.turn_indices.end(); ++it) { typename boost::range_value<Turns>::type const& turn = turns[*it]; if (turn.any_blocked()) { return true; } } return false; }
static inline bool is_self_cluster(signed_size_type cluster_id, const Turns& turns, Clusters const& clusters) { typename Clusters::const_iterator cit = clusters.find(cluster_id); if (cit == clusters.end()) { return false; } cluster_info const& cinfo = cit->second; for (std::set<signed_size_type>::const_iterator it = cinfo.turn_indices.begin(); it != cinfo.turn_indices.end(); ++it) { if (! is_self_turn<overlay_intersection>(turns[*it])) { return false; } } return true; }
inline void get_ring_turn_info(TurnInfoMap& turn_info_map, Turns const& turns, Clusters const& clusters) { typedef typename boost::range_value<Turns>::type turn_type; typedef typename turn_type::container_type container_type; static const operation_type target_operation = operation_from_overlay<OverlayType>::value; static const operation_type opposite_operation = target_operation == operation_union ? operation_intersection : operation_union; signed_size_type turn_index = 0; for (typename boost::range_iterator<Turns const>::type it = boost::begin(turns); it != boost::end(turns); ++it, turn_index++) { typename boost::range_value<Turns>::type const& turn = *it; bool const colocated_target = target_operation == operation_union ? turn.colocated_uu : turn.colocated_ii; bool const colocated_opp = target_operation == operation_union ? turn.colocated_ii : turn.colocated_uu; bool const both_opposite = turn.both(opposite_operation); bool const traversed = turn.operations[0].visited.finalized() || turn.operations[0].visited.rejected() || turn.operations[1].visited.finalized() || turn.operations[1].visited.rejected() || turn.both(operation_blocked) || turn.combination(opposite_operation, operation_blocked); bool is_closed = false; if (turn.cluster_id >= 0 && target_operation == operation_union) { typename Clusters::const_iterator mit = clusters.find(turn.cluster_id); BOOST_ASSERT(mit != clusters.end()); cluster_info const& cinfo = mit->second; is_closed = cinfo.open_count == 0; } for (typename boost::range_iterator<container_type const>::type op_it = boost::begin(turn.operations); op_it != boost::end(turn.operations); ++op_it) { ring_identifier const ring_id ( op_it->seg_id.source_index, op_it->seg_id.multi_index, op_it->seg_id.ring_index ); if (traversed || is_closed || ! op_it->enriched.startable) { turn_info_map[ring_id].has_traversed_turn = true; } else if (both_opposite && colocated_target) { // For union: ii, colocated with a uu // For example, two interior rings touch where two exterior rings also touch. // The interior rings are not yet traversed, and should be taken from the input // For intersection: uu, colocated with an ii // unless it is two interior inner rings colocated with a uu // So don't set has_traversed_turn here } else if (both_opposite && ! is_self_turn<OverlayType>(turn)) { // For union, mark any ring with a ii turn as traversed // For intersection, any uu - but not if it is a self-turn turn_info_map[ring_id].has_traversed_turn = true; } else if (colocated_opp && ! colocated_target) { // For union, a turn colocated with ii and NOT with uu/ux // For intersection v.v. turn_info_map[ring_id].has_traversed_turn = true; } } } }