Search code examples
cgal

How do I iterate through all the faces in a CGAL StraightSkeleton_2 / HalfedgeDS?


My goal is to take a polygon, find the straight skeleton, then turn each face into its own polygon.

I'm using the CGAL Create_straight_skeleton_2.cpp example as a starting point. I'm able to have it compute the skeleton and can iterate through the faces:

SsPtr iss = CGAL::create_interior_straight_skeleton_2(poly);
for( auto face = iss->faces_begin(); face != iss->faces_end(); ++face ) {
  // How do I iterate through the vertexes?
}

But with a HalfedgeDSFace it looks like I can only call halfedge() for a HalfedgeDSHalfedge.

At that point I'm confused how to iterate through the vertexes in the face. Do I just treat it like a circular linked list and follow the next pointer until I get back to face->halfedge()?

Here's my first attempt at treating it like a circular linked list:

SsPtr iss = CGAL::create_interior_straight_skeleton_2(poly);
std::cout << "Faces:" << iss->size_of_faces() << std::endl;
for( auto face = iss->faces_begin(); face != iss->faces_end(); ++face ) {
  std::cout << "Faces:" << iss->size_of_faces() << std::endl;
  std::cout << "----" << std::endl;
  do {
    std::cout << edge->vertex()->point() << std::endl;
    edge = edge->next();
  } while (edge != face->halfedge());
}

But that seems to put an empty vertex in each face:

Faces:4
----
197.401 420.778
0 0
166.95 178.812
----
511.699 374.635
0 0
197.401 420.778
----
428.06 122.923
0 0
511.699 374.635
----
166.95 178.812
0 0
428.06 122.923

Solution

  • So the iteration is much as I'd expected:

    // Each face
    for( auto face = iss->faces_begin(); face != iss->faces_end(); ++face ) {
        Ss::Halfedge_const_handle begin = face->halfedge();
        Ss::Halfedge_const_handle edge = begin;
        // Each vertex
        do {
            std::cout << edge->vertex()->point() << std::endl;
            edge = edge->next();
        } while (edge != begin);
    }
    

    The reason it wasn't working was the contour polygon I was using had a clockwise orientation. Once I reversed the order of the points I started getting valid data out of the faces.

    For reference here's how you'd iterate over the vertexes in the contour:

    // Pick a face and use the opposite edge to get on the contour.
    Ss::Halfedge_const_handle begin = iss->faces_begin()->halfedge()->opposite();
    Ss::Halfedge_const_handle edge = begin;
    do {
        std::cout << edge->vertex()->point() << std::endl;
        // Iterate in the opposite direction.
        edge = edge->prev();
    } while (edge != begin);