Beispiel #1
0
int  _PopAndUnmarkVerticesAndEdges(graphP theGraph, int Z, int stackBottom)
{
int  V, e;

     // Pop vertex/edge pairs until all have been popped from the stack,
     // and all that's left is what was under the pairs, or until...
     while (sp_GetCurrentSize(theGraph->theStack) > stackBottom)
     {
         sp_Pop(theGraph->theStack, V);

         // If we pop the terminating vertex Z, then put it back and break
         if (V == Z)
         {
             sp_Push(theGraph->theStack, V);
             break;
         }

         // Otherwise, pop the edge part of the vertex/edge pair
         sp_Pop(theGraph->theStack, e);

         // Now unmark the vertex and edge (i.e. revert to "unvisited")
         theGraph->G[V].visited = 0;
         theGraph->G[e].visited = 0;
         theGraph->G[gp_GetTwinArc(theGraph, e)].visited = 0;
     }

     return OK;
}
int _ColorVertices_IdentifyVertices(graphP theGraph, int u, int v, int eBefore)
{
    ColorVerticesContext *context = (ColorVerticesContext *) gp_GetExtension(theGraph, COLORVERTICES_ID);

    if (context != NULL)
    {
    	int e_v_last, e_v_first;

    	// First, identify u and v.  No point in taking v's degree beforehand
    	// because some of its incident edges may indicate neighbors of u. This
    	// causes v to be moved to a lower degree list than deg(v).
        if (context->functions.fpIdentifyVertices(theGraph, u, v, eBefore) != OK)
            return NOTOK;

        // The edges transferred from v to u are indicated on the top of the
        // stack, which looks like this after identifying u and v:
        // ... e_u_succ e_v_last e_v_first e_u_pred u v
		e_v_first = sp_Get(theGraph->theStack, sp_GetCurrentSize(theGraph->theStack)-4);
		e_v_last = sp_Get(theGraph->theStack, sp_GetCurrentSize(theGraph->theStack)-5);

        // We count the number of edges K transferred from v to u after the
        // common edges were hidden
		if (gp_IsArc(theGraph, e_v_first))
		{
			int J, K, degu;

			for (J=e_v_first, K=1; J != e_v_last; J=gp_GetNextArc(theGraph, J))
				K++;

	        // Remove v from the degree list K. During IdentifyVertices(), if v had any
			// common edges with u, they were "hidden", which reduced the degree of v to K.
			_RemoveVertexFromDegList(context, theGraph, v, K);

	        // We move u from degree list deg(u)-K to degree list deg(u)
			degu = gp_GetVertexDegree(theGraph, u);
			_RemoveVertexFromDegList(context, theGraph, u, degu-K);
			_AddVertexToDegList(context, theGraph, u, degu);
		}

        return OK;
    }

    return NOTOK;
}
int _ColorVertices_RestoreVertex(graphP theGraph)
{
    ColorVerticesContext *context = (ColorVerticesContext *) gp_GetExtension(theGraph, COLORVERTICES_ID);

    if (context != NULL)
    {
    	int u, v;

    	// Read the stack to figure out which vertex is being restored
		u = sp_Get(theGraph->theStack, sp_GetCurrentSize(theGraph->theStack)-2);
		v = sp_Get(theGraph->theStack, sp_GetCurrentSize(theGraph->theStack)-1);

    	// Restore the vertex
        if (context->functions.fpRestoreVertex(theGraph) != OK)
            return NOTOK;

        // If the restored vertex v was hidden, then give it a color distinct from its neighbors
        // Note that u is NIL in this case
        if (u == NIL)
        {
        	if (_AssignColorToVertex(context, theGraph, v) != OK)
        		return NOTOK;

        	if (context->color[v] < 0)
        		return NOTOK;
        }

        // Else if the restored vertex v was identified, then give v the same color as the
        // vertex u with which it was identified.
        else
        {
        	context->color[v] = context->color[u];
        }

        return OK;
    }

    return NOTOK;
}
Beispiel #4
0
void _CollectDrawingData(DrawPlanarContext *context, int RootVertex, int W, int WPrevLink)
{
graphP theEmbedding = context->theGraph;
//int ancestorChild = RootVertex - theEmbedding->N;
//int ancestor = theEmbedding->V[ancestorChild].DFSParent;
int K, Parent, BicompRoot, DFSChild, direction, descendant;

    gp_LogLine("\ngraphDrawPlanar.c/_CollectDrawingData() start");
    gp_LogLine(gp_MakeLogStr3("_CollectDrawingData(RootVertex=%d, W=%d, W_in=%d)",
				 RootVertex, W, WPrevLink));

    /* Process all of the merge points to set their drawing flags. */

    for (K = 0; K < sp_GetCurrentSize(theEmbedding->theStack); K += 4)
    {
         /* Get the parent and child that are about to be merged from
            the 4-tuple in the merge stack */
         Parent = theEmbedding->theStack->S[K];
         BicompRoot = theEmbedding->theStack->S[K+2];
         DFSChild = BicompRoot - theEmbedding->N;

         /* We get the active descendant vertex in the child bicomp that
            will be adjacent to the parent along the external face.
            This vertex is guaranteed to be found in one step
            due to external face 'short-circuiting' that was done in
            step 'Parent' of the planarity algorithm.
            We pass theEmbedding->N for the second parameter because
            of this; we use this function to signify need of extFace
            links in the other implementation.*/

         direction = theEmbedding->theStack->S[K+3];
         descendant = _GetNextExternalFaceVertex(theEmbedding, BicompRoot, &direction);

         /* Now we set the tie flag in the DFS child, and mark the
            descendant and parent with non-NIL pointers to the child
            whose tie flag is to be resolved as soon as one of the
            two is connected to by an edge or child bicomp merge. */

         context->V[DFSChild].drawingFlag = DRAWINGFLAG_TIE;

         context->V[descendant].tie[direction] = DFSChild;

         direction = theEmbedding->theStack->S[K+1];
         context->V[Parent].tie[direction] = DFSChild;

         gp_LogLine(gp_MakeLogStr5("V[Parent=%d]=.tie[%d] = V[descendant=%d].tie[%d] = (child=%d)",
					 Parent, direction, descendant, theEmbedding->theStack->S[K+3], DFSChild));
    }

    gp_LogLine("graphDrawPlanar.c/_CollectDrawingData() end\n");
}
Beispiel #5
0
void SaveAsciiGraph(graphP theGraph, char *filename)
{
	int  e, limit;
	FILE *outfile = fopen(filename, "wt");
	fprintf(outfile, "%s\n", filename);

	limit = theGraph->edgeOffset + 2*(theGraph->M + sp_GetCurrentSize(theGraph->edgeHoles));

	for (e = theGraph->edgeOffset; e < limit; e+=2)
	{
		if (theGraph->G[e].v != NIL)
			fprintf(outfile, "%d %d\n", theGraph->G[e].v+1, theGraph->G[e+1].v+1);
	}

	fprintf(outfile, "0 0\n");

	fclose(outfile);
}
Beispiel #6
0
int  _SortVertices(graphP theGraph)
{
int  I, N, M, e, J, srcPos, dstPos;
vertexRec tempV;
graphNode tempG;

#ifdef PROFILE
platform_time start, end;
platform_GetTime(start);
#endif

     if (theGraph == NULL) return NOTOK;
     if (!(theGraph->internalFlags&FLAGS_DFSNUMBERED))
         if (gp_CreateDFSTree(theGraph) != OK)
             return NOTOK;

/* Cache number of vertices and edges into local variables */

     N = theGraph->N;
     M = theGraph->M + sp_GetCurrentSize(theGraph->edgeHoles);

/* Change labels of edges from v to DFI(v)-- or vice versa
        Also, if any links go back to locations 0 to n-1, then they
        need to be changed because we are reordering the vertices */

     for (e=0, J=theGraph->edgeOffset; e < M; e++, J+=2)
     {
    	 if (theGraph->G[J].v != NIL)
    	 {
    		 theGraph->G[J].v = theGraph->G[theGraph->G[J].v].v;
    		 theGraph->G[J+1].v = theGraph->G[theGraph->G[J+1].v].v;
    	 }
     }

/* Convert DFSParent from v to DFI(v) or vice versa */

     for (I=0; I < N; I++)
          if (theGraph->V[I].DFSParent != NIL)
              theGraph->V[I].DFSParent = theGraph->G[theGraph->V[I].DFSParent].v;

/* Sort by 'v using constant time random access. Move each vertex to its
        destination 'v', and store its source location in 'v'. */

     /* First we clear the visitation flags.  We need these to help mark
        visited vertices because we change the 'v' field to be the source
        location, so we cannot use index==v as a test for whether the
        correct vertex is in location 'index'. */

     for (I=0; I < N; I++)
          theGraph->G[I].visited = 0;

     /* We visit each vertex location, skipping those marked as visited since
        we've already moved the correct vertex into that location. The
        inner loop swaps the vertex at location I into the correct position,
        G[I].v, marks that location as visited, then sets its 'v' field to
        be the location from whence we obtained the vertex record. */

     for (I=0; I < N; I++)
     {
          srcPos = I;
          while (!theGraph->G[I].visited)
          {
              dstPos = theGraph->G[I].v;

              tempG = theGraph->G[dstPos];
              tempV = theGraph->V[dstPos];
              theGraph->G[dstPos] = theGraph->G[I];
              theGraph->V[dstPos] = theGraph->V[I];
              theGraph->G[I] = tempG;
              theGraph->V[I] = tempV;

              theGraph->G[dstPos].visited = 1;
              theGraph->G[dstPos].v = srcPos;

              srcPos = dstPos;
          }
     }

/* Invert the bit that records the sort order of the graph */

     if (theGraph->internalFlags & FLAGS_SORTEDBYDFI)
          theGraph->internalFlags &= ~FLAGS_SORTEDBYDFI;
     else theGraph->internalFlags |= FLAGS_SORTEDBYDFI;

#ifdef PROFILE
platform_GetTime(end);
printf("SortVertices in %.3lf seconds.\n", platform_GetDuration(start,end));
#endif

     return OK;
}
Beispiel #7
0
int  _MarkHighestXYPath(graphP theGraph)
{
int J, Z;
int R, X, Y, W;
int stackBottom1, stackBottom2;

/* Initialization */

     R = theGraph->IC.r;
     X = theGraph->IC.x;
     Y = theGraph->IC.y;
     W = theGraph->IC.w;
     theGraph->IC.px = theGraph->IC.py = NIL;

/* Save the stack bottom before we start hiding internal edges, so
   we will know how many edges to restore */

     stackBottom1 = sp_GetCurrentSize(theGraph->theStack);

/* Remove the internal edges incident to vertex R */

     if (_HideInternalEdges(theGraph, R) != OK)
    	 return NOTOK;

/* Now we're going to use the stack to collect the vertices of potential
 * X-Y paths, so we need to store where the hidden internal edges are
 * located because we must, at times, pop the collected vertices if
 * the path being collected doesn't work out. */

     stackBottom2 = sp_GetCurrentSize(theGraph->theStack);

/* Walk the proper face containing R to find and mark the highest
        X-Y path. Note that if W is encountered, then there is no
        intervening X-Y path, so we would return FALSE in that case. */

     Z = R;
     // This setting of J is the arc equivalent of prevLink=1
     // As loop progresses, J indicates the arc used to enter Z, not the exit arc
     J = gp_GetLastArc(theGraph, R);

     while (theGraph->G[Z].type != VERTEX_HIGH_RYW &&
            theGraph->G[Z].type != VERTEX_LOW_RYW)
     {
          /* Advance J and Z along the proper face containing R */

    	  J = gp_GetPrevArcCircular(theGraph, J);
          Z = theGraph->G[J].v;
          J = gp_GetTwinArc(theGraph, J);

          /* If Z is already visited, then pop everything since the last time
                we visited Z because its all part of a separable component. */

          if (theGraph->G[Z].visited)
          {
              if (_PopAndUnmarkVerticesAndEdges(theGraph, Z, stackBottom2) != OK)
            	  return NOTOK;
          }

          /* If we have not visited this vertex before... */

          else
          {
              /* If we find W, then there is no X-Y path. Never happens
                 for Kuratowski subgraph isolator, but this routine is
                 also used to test for certain X-Y paths.
                 So, we clean up and bail out in that case. */

              if (Z == W)
              {
                  if (_PopAndUnmarkVerticesAndEdges(theGraph, NIL, stackBottom2) != OK)
                	  return NOTOK;
                  break;
              }

              /* If we found another vertex along the RXW path, then blow off
                 all the vertices we visited so far because they're not part of
                 the obstructing path */

              if (theGraph->G[Z].type == VERTEX_HIGH_RXW ||
                  theGraph->G[Z].type == VERTEX_LOW_RXW)
              {
                  theGraph->IC.px = Z;
                  if (_PopAndUnmarkVerticesAndEdges(theGraph, NIL, stackBottom2) != OK)
                	  return NOTOK;
              }

              /* Push the current vertex onto the stack of vertices visited
                 since the last RXW vertex was encountered */

              sp_Push(theGraph->theStack, J);
              sp_Push(theGraph->theStack, Z);

              /* Mark the vertex Z as visited as well as its edge of entry
                 (except the entry edge for P_x).*/

              theGraph->G[Z].visited = 1;
              if (Z != theGraph->IC.px)
              {
                  theGraph->G[J].visited = 1;
                  theGraph->G[gp_GetTwinArc(theGraph, J)].visited = 1;
              }

              /* If we found an RYW vertex, then we have successfully finished
                 identifying the highest X-Y path, so we record the point of
                 attachment and break the loop. */

              if (theGraph->G[Z].type == VERTEX_HIGH_RYW ||
                  theGraph->G[Z].type == VERTEX_LOW_RYW)
              {
                 theGraph->IC.py = Z;
                 break;
              }
          }
     }

/* Remove any remaining vertex-edge pairs on the top of the stack, then
    Restore the internal edges incident to R that were previously removed. */

     sp_SetCurrentSize(theGraph->theStack, stackBottom2);

     if (_RestoreInternalEdges(theGraph, stackBottom1) != OK)
    	 return NOTOK;

/* Return the result */

     return theGraph->IC.py==NIL ? FALSE : TRUE;
}
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;
}