stackP sp_New(int capacity) { stackP theStack; theStack = (stackP) malloc(sizeof(stack)); if (theStack != NULL) { theStack->S = (int *) malloc(capacity*sizeof(int)); if (theStack->S == NULL) { free(theStack); theStack = NULL; } } if (theStack != NULL) { theStack->capacity = capacity; sp_ClearStack(theStack); } return theStack; }
int _ComputeVertexPositionsInComponent(DrawPlanarContext *context, int root, int *pIndex) { graphP theEmbedding = context->theGraph; listCollectionP theOrder = LCNew(theEmbedding->N); int W, P, C, V, J; if (theOrder == NULL) return NOTOK; // Determine the vertex order using a depth first search with // pre-order visitation. sp_ClearStack(theEmbedding->theStack); sp_Push(theEmbedding->theStack, root); while (!sp_IsEmpty(theEmbedding->theStack)) { sp_Pop(theEmbedding->theStack, W); P = theEmbedding->V[W].DFSParent; V = context->V[W].ancestor; C = context->V[W].ancestorChild; // For the special case that we just popped the DFS tree root, // we simply add the root to its own position. if (P == NIL) { // Put the DFS root in the list by itself LCAppend(theOrder, NIL, W); // The children of the DFS root have the root as their // ancestorChild and 'beyond' as the drawingFlag, so this // causes the root's children to be placed below the root context->V[W].drawingFlag = DRAWINGFLAG_BELOW; } // Determine vertex W position relative to P else { // An unresolved tie is an error if (context->V[W].drawingFlag == DRAWINGFLAG_TIE) return NOTOK; // If C below V, then P below V, so interpret W between // P and V as W above P, and interpret W beyond P relative // to V as W below P. if (context->V[C].drawingFlag == DRAWINGFLAG_BELOW) { if (context->V[W].drawingFlag == DRAWINGFLAG_BETWEEN) context->V[W].drawingFlag = DRAWINGFLAG_ABOVE; else context->V[W].drawingFlag = DRAWINGFLAG_BELOW; } // If C above V, then P above V, so interpret W between // P and V as W below P, and interpret W beyond P relative // to V as W above P. else { if (context->V[W].drawingFlag == DRAWINGFLAG_BETWEEN) context->V[W].drawingFlag = DRAWINGFLAG_BELOW; else context->V[W].drawingFlag = DRAWINGFLAG_ABOVE; } if (context->V[W].drawingFlag == DRAWINGFLAG_BELOW) LCInsertAfter(theOrder, P, W); else LCInsertBefore(theOrder, P, W); } // Push DFS children J = gp_GetFirstArc(theEmbedding, W); while (gp_IsArc(theEmbedding, J)) { if (theEmbedding->G[J].type == EDGE_DFSCHILD) sp_Push(theEmbedding->theStack, theEmbedding->G[J].v); J = gp_GetNextArc(theEmbedding, J); } } // Use the order to assign vertical positions V = root; while (V != NIL) { context->G[V].pos = *pIndex; (*pIndex)++; V = LCGetNext(theOrder, root, V); } // Clean up and return LCFree(&theOrder); return OK; }
int gp_CreateDFSTree(graphP theGraph) { stackP theStack; int N, DFI = 0, I, uparent, u, e, J; #ifdef PROFILE platform_time start, end; platform_GetTime(start); #endif if (theGraph==NULL) return NOTOK; if (theGraph->internalFlags & FLAGS_DFSNUMBERED) return OK; gp_LogLine("\ngraphPreprocess.c/gp_CreateDFSTree() start"); N = theGraph->N; theStack = theGraph->theStack; /* There are 2M edge records (arcs) and for each we can push 2 integers, so a stack of 2 * arcCapacity integers suffices. This is already in theGraph structure, so we make sure it's empty, then clear all visited flags in prep for the Depth first search. */ if (sp_GetCapacity(theStack) < 2*gp_GetArcCapacity(theGraph)) return NOTOK; sp_ClearStack(theStack); for (I=0; I < N; I++) theGraph->G[I].visited = 0; /* This outer loop causes the connected subgraphs of a disconnected graph to be numbered */ for (I=0; I < N && DFI < N; I++) { if (theGraph->V[I].DFSParent != NIL) continue; sp_Push2(theStack, NIL, NIL); while (sp_NonEmpty(theStack)) { sp_Pop2(theStack, uparent, e); u = uparent == NIL ? I : theGraph->G[e].v; if (!theGraph->G[u].visited) { gp_LogLine(gp_MakeLogStr3("V=%d, DFI=%d, Parent=%d", u, DFI, uparent)); theGraph->G[u].visited = 1; theGraph->G[u].v = DFI++; theGraph->V[u].DFSParent = uparent; if (e != NIL) { theGraph->G[e].type = EDGE_DFSCHILD; theGraph->G[gp_GetTwinArc(theGraph, e)].type = EDGE_DFSPARENT; // We want the child arcs to be at the beginning // of the adjacency list. gp_MoveArcToFirst(theGraph, uparent, e); } /* Push edges to all unvisited neighbors. These will be either tree edges to children or forward arcs of back edges */ J = gp_GetFirstArc(theGraph, u); while (gp_IsArc(theGraph, J)) { if (!theGraph->G[theGraph->G[J].v].visited) sp_Push2(theStack, u, J); J = gp_GetNextArc(theGraph, J); } } else { // If the edge leads to a visited vertex, then it is // the forward arc of a back edge. theGraph->G[e].type = EDGE_FORWARD; theGraph->G[gp_GetTwinArc(theGraph, e)].type = EDGE_BACK; // We want all of the forward edges to descendants to // be at the end of the adjacency list. // The tree edge to the parent and the back edges to ancestors // are in the middle, between the child edges and forward edges. gp_MoveArcToLast(theGraph, uparent, e); } } } gp_LogLine("graphPreprocess.c/gp_CreateDFSTree() end\n"); theGraph->internalFlags |= FLAGS_DFSNUMBERED; #ifdef PROFILE platform_GetTime(end); printf("DFS in %.3lf seconds.\n", platform_GetDuration(start,end)); #endif return OK; }
int gp_LowpointAndLeastAncestor(graphP theGraph) { stackP theStack = theGraph->theStack; int I, u, uneighbor, J, L, leastAncestor; int totalVisited = 0; #ifdef PROFILE platform_time start, end; platform_GetTime(start); #endif sp_ClearStack(theStack); for (I=0; I < theGraph->N; I++) theGraph->G[I].visited = 0; /* This outer loop causes the connected subgraphs of a disconnected graph to be processed */ for (I=0; I < theGraph->N && totalVisited < theGraph->N; I++) { if (theGraph->G[I].visited) continue; sp_Push(theStack, I); while (sp_NonEmpty(theStack)) { sp_Pop(theStack, u); if (!theGraph->G[u].visited) { /* Mark u as visited, then push it back on the stack */ theGraph->G[u].visited = 1; totalVisited++; sp_Push(theStack, u); /* Push DFS children */ J = gp_GetFirstArc(theGraph, u); while (gp_IsArc(theGraph, J)) { if (theGraph->G[J].type == EDGE_DFSCHILD) { sp_Push(theStack, theGraph->G[J].v); } else break; J = gp_GetNextArc(theGraph, J); } } else { /* Start with high values because we are doing a min function */ L = leastAncestor = u; /* Compute L and leastAncestor */ J = gp_GetFirstArc(theGraph, u); while (gp_IsArc(theGraph, J)) { uneighbor = theGraph->G[J].v; if (theGraph->G[J].type == EDGE_DFSCHILD) { if (L > theGraph->V[uneighbor].Lowpoint) L = theGraph->V[uneighbor].Lowpoint; } else if (theGraph->G[J].type == EDGE_BACK) { if (leastAncestor > uneighbor) leastAncestor = uneighbor; } else if (theGraph->G[J].type == EDGE_FORWARD) break; J = gp_GetNextArc(theGraph, J); } /* Assign leastAncestor and Lowpoint to the vertex */ theGraph->V[u].leastAncestor = leastAncestor; theGraph->V[u].Lowpoint = leastAncestor < L ? leastAncestor : L; } } } #ifdef PROFILE platform_GetTime(end); printf("Lowpoint in %.3lf seconds.\n", platform_GetDuration(start,end)); #endif 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; }