void sl_test(vector<Segment>& segments) { cout << "All" << endl; sweep_line(segments.begin(), segments.end(), Debug_visitor()); cout << "No end-end" << endl; sweep_line(segments.begin(), segments.end(), filter_visitor(Debug_visitor(), true, false)); cout << "No end-int" << endl; sweep_line(segments.begin(), segments.end(), filter_visitor(Debug_visitor(), false, true)); }
std::pair<ForwardIt, ForwardIt> find_intersection(ForwardIt first, ForwardIt last) { using event_t = std::pair<bool, ForwardIt>; const size_t set_size = std::distance(first, last); std::vector<event_t> event_queue; event_queue.reserve(set_size); for (auto it = first; it != last; ++it) { event_queue.emplace_back(true, it); event_queue.emplace_back(false, it); } auto segment_less = [&](ForwardIt lhs, ForwardIt rhs) { return *lhs < *rhs; }; std::set<ForwardIt, decltype(segment_less)> sweep_line(segment_less); auto event_less = [&](const event_t &lhs, const event_t &rhs) { auto &lpoint = lhs.first ? lhs.second->a : lhs.second->b; auto &rpoint = rhs.first ? rhs.second->a : rhs.second->b; return (lpoint < rpoint) || (lpoint == rpoint && (lhs.first && !rhs.first)); }; std::sort(event_queue.begin(), event_queue.end(), event_less); for (const auto &event : event_queue) { if (event.first) { // left event auto it = sweep_line.lower_bound(event.second); if (it != sweep_line.end() && intersect(**it, *event.second)) return {event.second, *it}; if (it != sweep_line.begin() && intersect(**std::prev(it), *event.second)) return {event.second, *std::prev(it)}; sweep_line.insert(event.second); } else { // right event auto it = sweep_line.lower_bound(event.second); auto has_neighbours = std::next(it) != sweep_line.end() && it != sweep_line.begin(); if (has_neighbours && intersect(**std::next(it), **std::prev(it))) return {*std::prev(it), *std::next(it)}; sweep_line.erase(it); } } return {last, last}; }