/*
* JFLAP - Formal Languages and Automata Package
*
*
* Susan H. Rodger
* Computer Science Department
* Duke University
* August 27, 2009
* Copyright (c) 2002-2009
* All rights reserved.
* JFLAP is open source software. Please see the LICENSE for terms.
*
*/
package automata.graph.layout;
import java.util.ArrayList;
import automata.graph.Graph;
/**
* Class that orders vertices assigned to it one-dimensionally. The order of the vertices is changed as vertices
* are added in order to minimize the number of edges between non-adjacent vertices.
*
* @author Chris Morgan
*/
public class VertexChain{
/**
* List of vertices in the chain.
*/
ArrayList vertices;
/**
* The graph from which edge information is processed.
*/
Graph graph;
/**
* Constructor.
*
* @param g - The graph from which edge information is processed.
*/
public VertexChain(Graph g)
{
vertices = new ArrayList();
graph = g;
}
/**
* Returns the object held in vertices
in the given index.
*
* @return the object in the given index.
*/
public Object get(int index) {
return vertices.get(index);
}
/**
* Returns the ArrayList containing the vertices in the VertexChain
.
*
* @return the vertices in the chain.
*/
public ArrayList getVertices()
{
return vertices;
}
/**
* Returns the number of elements stored in this chain.
*
* @return the number of elements stored in this chain.
*/
public int size() {
return vertices.size();
}
/**
* Returns whether the given vertex has an edge to a VertexChain
member.
*
* @return whether the given vertex has an edge to a VertexChain
member.
*/
public boolean isEdgeToChainMember(Object vertex)
{
if (getDegreeInChain(vertex) > 0)
return true;
return false;
}
/**
* Returns the degree of a given vertex with respect to current vertices in the VertexChain
.
* The vertex does not need to be in the graph, but is not counted toward the degree if it is.
*
* @return the given vertex's degree with respect to the VertexChain
.
*/
public int getDegreeInChain(Object vertex)
{
int count = 0;
for (int i=0; iVertexChain. The subchain is removed
* from its present position in the VertexChain
and placed next to a given vertex.
*
* @param destIndex
* the index of the vertex in the VertexChain
next to which the subchain will be placed.
* @param matchingIndex
* either the start
or the end
value. Determines the vertex that is
* closest to the destIndex's
vertex in the new VertexChain
ordering. Often
* is the index of a vertex linking to the destIndex's
vertex.
* @param start
* the index in the VertexChain
representing the start of the subchain.
* @param end
* the index in the VertexChain
representing the end of the subchain.
* @param shuffleDirection
* if true, the subchain will be placed to the right of the destIndex's
vertex.
* If false, to the left.
*/
public void orientSubChain(int destIndex, int matchingIndex, int start, int end, boolean shuffleDirection) {
Object[] toMove = new Object[end-start+1];
int dest, chainSize;
chainSize = size();
if (destIndex > 0 && destIndex >= start)
dest = destIndex+start-end-1;
else
dest = destIndex;
for (int i=start; i<=end; i++)
toMove[i-start] = get(i);
for (int i=0; iVertexChain, adjusting the VertexChain's
order to
* minimize the number of edges between non-adjacent vertices.
*
* @param vertex the vertex to be added
*/
public void addVertex(Object vertex)
{
int destIndex, subChainBound;
for (int i=0; ii+2 && graph.hasEdge(get(subChainBound-1),
get(subChainBound)))
subChainBound--;
orientSubChain(destIndex, j, subChainBound, j, (destIndex==i+1));
}
return;
}
return;
}
//Added at end if there are no adjacencies.
vertices.add(vertex);
}
/**
* If there is an edge between a vertex in first
and a vertex in last
, then the two
* vertices are moved in their respective chains to their common border, with subchains in tow behind them. This
* only happens for the first matching pair, and other matching pairs have no effect. The vertex in
* first
will be moved to the end of vertices in its VertexChain
, and the vertex in
* last
will be moved to the beginning of vertices in its VertexChain
.
*
* @param first
* the first VertexChain
to search
* @param next
* the second VertexChain
to search
* @param graph
* the graph used to search for edges
*/
public static void alignTwoChains(VertexChain first, VertexChain next, Graph graph) {
int fstart, fend, nstart, nend;
for (int j=0; j 0 && graph.hasEdge(first.get(fstart), first.get(fstart-1)))
fstart--;
while (fend < first.size()-1 && graph.hasEdge(first.get(fend), first.get(fend+1)))
fend++;
while (nstart > 0 && graph.hasEdge(next.get(nstart), next.get(nstart-1)))
nstart--;
while (nend < next.size()-1 && graph.hasEdge(next.get(nend), next.get(nend+1)))
nend++;
first.orientSubChain(first.size()-1, fstart+fend-j, fstart, fend, true);
next.orientSubChain(0, nstart+nend-k, nstart, nend, false);
return;
}
}
}