Search code examples
c++computational-geometry

Is there a robust C++ implementation of the Bentley-Ottmann algorithm?


The Bentley-Ottoman algorithm finds all crossings in a set of line segments. For a well known and important algorithm, it seems quite weird that a C++ implementation of Bentley-Ottmann algorithm — the implementation that can handle all the degenerated cases (i.e., no special assumption on the sweeping line and the number of intersection points, and so on) — is simply not available. The only code I can found is here, but it doesn't seem to handle the generalized case.

Is Bentley-Ottmann algorithm already implemented in any well-tested library, such as Boost or LEDA? If yes, may I have the reference to it?


Solution

  • CGAL has something in there with the same complexity as Bentley-Ottmann, O((n + k)*log(n)) where n is the number of segments and k is the number of intersections (not sure which algorithm they used):

    //! \file examples/Arrangement_on_surface_2/sweep_line.cpp
    // Computing intersection points among curves using the sweep line.
    
    #include <CGAL/Cartesian.h>
    #include <CGAL/MP_Float.h>
    #include <CGAL/Quotient.h>
    #include <CGAL/Arr_segment_traits_2.h>
    #include <CGAL/Sweep_line_2_algorithms.h>
    #include <list>
    
    typedef CGAL::Quotient<CGAL::MP_Float>                  NT;
    typedef CGAL::Cartesian<NT>                             Kernel;
    typedef Kernel::Point_2                                 Point_2;
    typedef CGAL::Arr_segment_traits_2<Kernel>              Traits_2;
    typedef Traits_2::Curve_2                               Segment_2;
    
    int main()
    {
      // Construct the input segments.
      Segment_2 segments[] = {Segment_2 (Point_2 (1, 5), Point_2 (8, 5)),
                              Segment_2 (Point_2 (1, 1), Point_2 (8, 8)),
                              Segment_2 (Point_2 (3, 1), Point_2 (3, 8)),
                              Segment_2 (Point_2 (8, 5), Point_2 (8, 8))};
    
      // Compute all intersection points.
      std::list<Point_2>     pts;
    
      CGAL::compute_intersection_points (segments, segments + 4,
                                         std::back_inserter (pts));
    
      // Print the result.
      std::cout << "Found " << pts.size() << " intersection points: " << std::endl; 
      std::copy (pts.begin(), pts.end(),
                 std::ostream_iterator<Point_2>(std::cout, "\n"));
    
      // Compute the non-intersecting sub-segments induced by the input segments.
      std::list<Segment_2>   sub_segs;
    
      CGAL::compute_subcurves(segments, segments + 4, std::back_inserter(sub_segs));
    
      std::cout << "Found " << sub_segs.size()
                << " interior-disjoint sub-segments." << std::endl;
    
      CGAL_assertion (CGAL::do_curves_intersect (segments, segments + 4));
    
      return 0;
    }
    

    http://doc.cgal.org/latest/Sweep_line_2/index.html