Search code examples
sortinglinecomputational-geometrycgal

Sorting lines by slope


Is there a function in any of CGAL packages to sort lines (Line_2) by slope? Or can anyone recommend a sorting algorithm that considers degenerate cases like vertical lines?


Solution

  • There's the CGAL::compare_slopes free function for Line_2 objects, and the corresponding K::Compare_slope_2 functor (which can be extracted from a given instance k of K by k.compare_slope_2_object()).

    You can see it in the following example:

    #include <algorithm>
    #include <iostream>
    #include <vector>
    #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
    
    typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
    typedef typename K::Line_2 Line_2;
    
    struct Slope_comparator {
      // K k;
      // Slope_comparator (const K &k = K()) : k(k) {}
      bool operator() (const Line_2 &l1, const Line_2 &l2) const {
        return (CGAL::compare_slopes (l1, l2) < 0);
        // return (k.compare_slope_2_object()(l1, l2) < 0);
      }
    };
    
    int main () {
      std::vector< Line_2 > l;
      l.push_back (Line_2 (    1.,     1., 0.));
      l.push_back (Line_2 (    1.,    -1., 0.));
      l.push_back (Line_2 (    0.,     1., 0.)); // vertical
      l.push_back (Line_2 (1e-100,     1., 0.)); // almost vertical
      l.push_back (Line_2 (1e-100,    -1., 0.)); // almost vertical
      l.push_back (Line_2 (    0.,    -1., 1.)); // also vertical
      l.push_back (Line_2 (1e-100,     1., 2.)); // also almost vertical
      l.push_back (Line_2 (1e-100,    -1., 3.)); // also almost vertical
      l.push_back (Line_2 (    1.,     0., 0.)); // horizontal
      l.push_back (Line_2 (    1., 1e-100, 0.)); // almost horizontal
      l.push_back (Line_2 (   -1., 1e-100, 0.)); // almost horizontal
      l.push_back (Line_2 (   -1.,     0., 4.)); // also horizontal
      l.push_back (Line_2 (   -1., 1e-100, 5.)); // also almost horizontal
      l.push_back (Line_2 (    1., 1e-100, 6.)); // also almost horizontal
    
      std::cout << "insertion order:" << std::endl;
      for (int i = 0; i < l.size(); ++i)
        std::cout << "    " << l[i] << std::endl;
    
      std::sort (l.begin(), l.end(), Slope_comparator());
      std::cout << "sorted order:" << std::endl;
      for (int i = 0; i < l.size(); ++i)
        std::cout << "    " << l[i] << std::endl;
    }
    

    Note that compare_slopes compares oriented lines, essentially directions; if that's not what you want, you have to normalize your lines (e.g. ensure all y-coordinates positive).