int _DeleteUnmarkedVerticesAndEdges(graphP theGraph) { int v, e; /* All of the forward and back arcs of all of the edge records were removed from the adjacency lists in the planarity algorithm preprocessing. We now put them back into the adjacency lists (and we do not mark them), so they can be properly deleted below. */ for (v = gp_GetFirstVertex(theGraph); gp_VertexInRange(theGraph, v); v++) { while (gp_IsArc(e = gp_GetVertexFwdArcList(theGraph, v))) _AddBackEdge(theGraph, v, gp_GetNeighbor(theGraph, e)); } /* Now we delete all unmarked edges. We don't delete vertices from the embedding, but the ones we should delete will become degree zero. */ for (v = gp_GetFirstVertex(theGraph); gp_VertexInRange(theGraph, v); v++) { e = gp_GetFirstArc(theGraph, v); while (gp_IsArc(e)) { if (gp_GetEdgeVisited(theGraph, e)) e = gp_GetNextArc(theGraph, e); else e = gp_DeleteEdge(theGraph, e, 0); } } return OK; }
int _CheckEmbeddingFacialIntegrity(graphP theGraph) { stackP theStack = theGraph->theStack; int EsizeOccupied, v, e, eTwin, eStart, eNext, NumFaces, connectedComponents; if (theGraph == NULL) return NOTOK; /* The stack need only contain 2M entries, one for each edge record. With max M at 3N, this amounts to 6N integers of space. The embedding structure already contains this stack, so we just make sure it starts out empty. */ sp_ClearStack(theStack); /* Push all arcs and set them to unvisited */ EsizeOccupied = gp_EdgeInUseIndexBound(theGraph); for (e = gp_GetFirstEdge(theGraph); e < EsizeOccupied; e+=2) { // Except skip edge holes if (gp_EdgeInUse(theGraph, e)) { sp_Push(theStack, e); gp_ClearEdgeVisited(theGraph, e); eTwin = gp_GetTwinArc(theGraph, e); sp_Push(theStack, eTwin); gp_ClearEdgeVisited(theGraph, eTwin); } } // There are M edges, so we better have pushed 2M arcs just now // i.e. testing that the continue above skipped only edge holes if (sp_GetCurrentSize(theStack) != 2*theGraph->M) return NOTOK; /* Read faces until every arc is used */ NumFaces = 0; while (sp_NonEmpty(theStack)) { /* Get an arc; if it has already been used by a face, then don't use it to traverse a new face */ sp_Pop(theStack, eStart); if (gp_GetEdgeVisited(theGraph, eStart)) continue; e = eStart; do { eNext = gp_GetNextArcCircular(theGraph, gp_GetTwinArc(theGraph, e)); if (gp_GetEdgeVisited(theGraph, eNext)) return NOTOK; gp_SetEdgeVisited(theGraph, eNext); e = eNext; } while (e != eStart); NumFaces++; } /* Count the external face once rather than once per connected component; each connected component is detected by the fact that it has no DFS parent, except in the case of isolated vertices, no face was counted so we do not subtract one. */ connectedComponents = 0; for (v = gp_GetFirstVertex(theGraph); gp_VertexInRange(theGraph, v); v++) { if (gp_IsDFSTreeRoot(theGraph, v)) { if (gp_GetVertexDegree(theGraph, v) > 0) NumFaces--; connectedComponents++; } } NumFaces++; /* Test number of faces using the extended Euler's formula. For connected components, Euler's formula is f=m-n+2, but for disconnected graphs it is extended to f=m-n+1+c where c is the number of connected components.*/ return NumFaces == theGraph->M - theGraph->N + 1 + connectedComponents ? OK : NOTOK; }