Ejemplo n.º 1
0
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));
}
Ejemplo n.º 2
0
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};
}