Graph.DegenerateBoundaries

Builds loops from a set of directed edges, turning left at each vertex until a repeated edge is found (i.e., LoopType::CIRCUIT). The loops are further grouped into connected components, where each component consists of one or more loops connected by shared vertices.

This method is used to build polygon meshes from directed or undirected input edges. To convert the output of this method into a mesh, the client must determine how the loops in different components are related to each other: for example, several loops from different components may bound the same region on the sphere, in which case all of those loops are combined into a single polygon. (See s2shapeutil::BuildPolygonBoundaries and s2builderutil::LaxPolygonVectorLayer for details.)

Note that loops may include both edges of a sibling pair. When several such edges are connected in a chain or a spanning tree, they form a zero-area "filament". The entire loop may be a filament (i.e., a degenerate loop with an empty interior), or the loop may have have non-empty interior with several filaments that extend inside it, or the loop may consist of several "holes" connected by filaments. These filaments do not change the interior of any loop, so if you are only interested in point containment then they can safely be removed by setting the "degenerate_boundaries" parameter to DISCARD. (They can't be removed by setting (options.sibling_pairs() == DISCARD) because the two siblings might belong to different polygons of the mesh.) Note that you can prevent multiple copies of sibling pairs by specifying options.duplicate_edges() == MERGE.

Each loop is represented as a sequence of edges. The edge ordering and loop ordering are automatically canonicalized in order to preserve the input ordering as much as possible. Loops are non-crossing provided that the graph contains no crossing edges. If some edges cannot be turned into loops, returns false and sets "error" appropriately.

REQUIRES: options.degenerate_edges() == { DISCARD, DISCARD_EXCESS } (but requires DISCARD if degenerate_boundaries == DISCARD) REQUIRES: options.sibling_pairs() == { REQUIRE, CREATE } [i.e., every edge must have a sibling edge]

Values

ValueMeaning
DISCARD
KEEP

Meta