Search code examples
computational-geometrycgal

CGAL arrangement face to polygon


I want to generate a polygon for each face in a CGAL arrangement (reason: see my related question)

As input, i added polyline curves with multiple calls of:

std::list<Point_2> points;
(.. add points ..) 
Polyline_2 pi1 (points.begin(), points.end());
insert (arr, pi1);

However, when I output the face:

std::ofstream ofs ("cgal_output.txt", std::ofstream::out);

template<class Arrangement>
void print_ccb (typename Arrangement::Ccb_halfedge_const_circulator circ)
{
  typename Arrangement::Ccb_halfedge_const_circulator  curr = circ;

  do
  {
    typename Arrangement::Halfedge_const_handle he = curr;
    ofs << he->curve() << std::endl; 

  } while (++curr != circ);

    ofs << "#" << std::endl; // end of face mark
  return;
}

the points of the curves are not traversed in a way, that a consistantly winded polygon outline can be drawn with the coordinates.

How can I fix this?


Solution

  • I think that there is code to do what you want in the Arrangement_2 demo. The method that creates a polygon from an individual face is located at demo/Arrangement_on_surface_2/ArrangementGraphicsItem.h:311 (just note there are some Qt objects being used, which you can replace with std::vector and CGAL::Point_2):

      QVector< QPointF > pts; // holds the points of the polygon
      typename X_monotone_curve_2::const_iterator           pt_itr;
      typename X_monotone_curve_2::const_reverse_iterator   pt_rev_itr;
      X_monotone_curve_2 cv;
    
      /* running with around the outer of the face and generate from it
       * polygon
       */
      Ccb_halfedge_circulator cc = f->outer_ccb();
      do { 
        cv = cc->curve();
        bool curve_has_same_direction =
          ( *(cc->curve().begin()) == cc->source()->point() );
        if ( curve_has_same_direction )
        {    
          for( pt_itr = cv.begin() , ++pt_itr ; pt_itr != cv.end(); ++pt_itr)
          {    
            double x = CGAL::to_double((*pt_itr).x());
            double y = CGAL::to_double((*pt_itr).y());
            QPointF coord_source(x , y);
            pts.push_back(coord_source );
          }    
        }    
        else 
        {    
          for (pt_rev_itr = cv.rbegin() , ++pt_rev_itr; pt_rev_itr != cv.rend();
               ++pt_rev_itr)
          {    
            double x = CGAL::to_double((*pt_rev_itr).x());
            double y = CGAL::to_double((*pt_rev_itr).y());
            QPointF coord_source(x , y);
            pts.push_back(coord_source );
          }    
        }    
        //created from the outer boundary of the face
      } while (++cc != f->outer_ccb());
    
      // make polygon from the outer ccb of the face 'f'
      QPolygonF pgn( pts );
    

    Basically, the additional work you need to do is to check if the line segment in the polyline is reversed, then reverse the points accordingly.