浏览代码

first nice annimation controlled by the keys (P),(LEFT),(RIGHT)

Kolja Strohm 6 年之前
父节点
当前提交
675662e4d1

+ 7 - 0
src/Algorithms/Animated/Action.java

@@ -0,0 +1,7 @@
+package Algorithms.Animated;
+
+public enum Action {
+
+	FORWARD,
+	BACKWARD
+}

+ 13 - 0
src/Algorithms/Animated/AlgorithmStep.java

@@ -0,0 +1,13 @@
+package Algorithms.Animated;
+
+public interface AlgorithmStep {
+
+	public static enum StepStatus
+	{
+		UNFINISHED,
+		FINISHED
+	}
+	
+	public StepStatus forwardStep();
+	public StepStatus backwardStep();
+}

+ 44 - 0
src/Algorithms/Animated/AnnimatedAlgorithm.java

@@ -0,0 +1,44 @@
+package Algorithms.Animated;
+
+import javax.swing.SwingUtilities;
+
+import Model.LayeredGraphNode;
+
+public abstract class AnnimatedAlgorithm extends Thread implements AlgorithmStep {
+
+	protected AnnimationController ac;
+	protected LayeredGraphNode graph;
+	
+	public AnnimatedAlgorithm( AnnimationController controller, LayeredGraphNode graph )
+	{
+		this.ac = controller;
+		this.graph = graph;
+		if( controller != null )
+			start();
+	}
+	
+	@Override
+	public void run()
+	{
+		while( true )
+		{
+			try {
+				switch( ac.getNextAction() )
+				{
+				case FORWARD:
+					System.out.println( "FORWARD" );
+					forwardStep();
+					break;
+				case BACKWARD:
+					System.out.println( "BACKWARD" );
+					backwardStep();
+					break;
+				}
+			} catch (InterruptedException e) {
+				e.printStackTrace();
+				return;
+			}
+			
+		}
+	}
+}

+ 65 - 0
src/Algorithms/Animated/AnnimationController.java

@@ -0,0 +1,65 @@
+package Algorithms.Animated;
+
+public class AnnimationController {
+
+	
+	private Action next;
+	private boolean continuous;
+	private long lastTime;
+	private long timeBetween;
+	
+	public AnnimationController()
+	{
+		next = null;
+		continuous = false;
+		lastTime = 0;
+		timeBetween = 0;
+	}
+	
+	public Action getNextAction() throws InterruptedException
+	{
+		long old = lastTime;
+		Action ret = null;
+		synchronized( this ) {
+			while( next == null )
+				wait();
+			lastTime = System.currentTimeMillis();
+			ret = next;
+		}
+		if( !continuous )
+			next = null;
+		else
+		{
+			if( lastTime - old < timeBetween )
+			{
+				Thread.sleep( timeBetween - ( lastTime - old ) );
+				System.out.println( "sleep: " + ( timeBetween - ( lastTime - old ) ) );
+				lastTime = System.currentTimeMillis();
+			}
+		}
+		return ret;
+	}
+	
+	public void setContinuous( boolean c )
+	{
+		this.continuous = c;
+	}
+	
+	public void setTimeBetween( long between )
+	{
+		timeBetween = between;
+	}
+	
+	public void setNextAction( Action a )
+	{
+		next = a;
+		synchronized( this ) {
+			notify();
+		}
+	}
+	
+	public boolean isContinuous()
+	{
+		return continuous;
+	}
+}

+ 89 - 0
src/Algorithms/Animated/BK/BKNodePlacement.java

@@ -0,0 +1,89 @@
+package Algorithms.Animated.BK;
+
+import Algorithms.Animated.AlgorithmStep;
+import Algorithms.Animated.AnnimatedAlgorithm;
+import Algorithms.Animated.AnnimationController;
+import Model.LayeredGraphNode;
+
+public class BKNodePlacement extends AnnimatedAlgorithm {
+
+	/*
+	 * Private data structures to store the process of the algorithm
+	 */
+	
+	private enum State
+	{
+		LAYOUT1,
+		LAYOUT2,
+		LAYOUT3,
+		LAYOUT4,
+		COMBINE
+	}
+	
+	private State state;
+	private Layout layouts[];
+	private Combine combine;
+	
+	public BKNodePlacement(AnnimationController controller, LayeredGraphNode graph) {
+		super(controller, graph);
+		state = State.LAYOUT1;
+		layouts = new Layout[ 4 ];
+		layouts[ 0 ] = new Layout( Layout.LayoutType.TOP_BOTTOM_LEFT, graph );
+		layouts[ 1 ] = new Layout( Layout.LayoutType.TOP_BOTTOM_RIGHT, graph );
+		layouts[ 2 ] = new Layout( Layout.LayoutType.BOTTOM_TOP_LEFT, graph );
+		layouts[ 3 ] = new Layout( Layout.LayoutType.BOTTOM_TOP_RIGHT, graph );
+		combine = new Combine();
+	}
+
+	@Override
+	public StepStatus forwardStep() {
+		switch( state )
+		{
+		case LAYOUT1:
+			if( layouts[ 0 ].forwardStep() == AlgorithmStep.StepStatus.FINISHED )
+				state = State.LAYOUT2;
+			break;
+		case LAYOUT2:
+			if( layouts[ 1 ].forwardStep() == AlgorithmStep.StepStatus.FINISHED )
+				state = State.LAYOUT3;
+			break;
+		case LAYOUT3:
+			if( layouts[ 2 ].forwardStep() == AlgorithmStep.StepStatus.FINISHED )
+				state = State.LAYOUT4;
+			break;
+		case LAYOUT4:
+			if( layouts[ 3 ].forwardStep() == AlgorithmStep.StepStatus.FINISHED )
+				state = State.COMBINE;
+			break;
+		case COMBINE:
+			return combine.forwardStep();
+		}
+		return StepStatus.UNFINISHED;
+	}
+
+	@Override
+	public StepStatus backwardStep() {
+		switch( state )
+		{
+		case LAYOUT1:
+			return layouts[ 0 ].backwardStep();
+		case LAYOUT2:
+			if( layouts[ 1 ].backwardStep() == AlgorithmStep.StepStatus.FINISHED )
+				state = State.LAYOUT1;
+			break;
+		case LAYOUT3:
+			if( layouts[ 2 ].backwardStep() == AlgorithmStep.StepStatus.FINISHED )
+				state = State.LAYOUT2;
+			break;
+		case LAYOUT4:
+			if( layouts[ 3 ].backwardStep() == AlgorithmStep.StepStatus.FINISHED )
+				state = State.LAYOUT3;
+			break;
+		case COMBINE:
+			if( combine.backwardStep() == AlgorithmStep.StepStatus.FINISHED )
+				state = State.LAYOUT4;
+			break;
+		}
+		return StepStatus.UNFINISHED;
+	}
+}

+ 121 - 0
src/Algorithms/Animated/BK/BlockCalc.java

@@ -0,0 +1,121 @@
+package Algorithms.Animated.BK;
+
+import java.util.ArrayList;
+
+import Algorithms.Animated.AlgorithmStep;
+import Algorithms.Animated.BackwordAction;
+import Model.LayeredGraphEdge;
+import Model.LayeredGraphNode;
+
+public class BlockCalc implements AlgorithmStep {
+
+	private int layerIndex;
+	private int nodeIndex;
+	private LayeredGraphNode graph;
+	private ArrayList< ArrayList< BKNodePlacement > > subgraphAlgs;
+	private ArrayList< BackwordAction > backwards;
+	
+	public BlockCalc( LayeredGraphNode graph )
+	{
+		this.graph = graph;
+		layerIndex = 0;
+		nodeIndex = 0;
+		subgraphAlgs = new ArrayList<>();
+		for( ArrayList<LayeredGraphNode> l : graph.getContainedLayers() )
+		{
+			ArrayList< BKNodePlacement > algs = new ArrayList<>();
+			for( int i = 0; i < l.size(); i++ )
+				algs.add( null );
+			subgraphAlgs.add( algs );
+		}
+		backwards = new ArrayList<>();
+	}
+	
+	@Override
+	public StepStatus forwardStep() {
+		System.out.println( "test" );
+		LayeredGraphNode current = graph.getContainedLayers().get( layerIndex ).get( nodeIndex );
+		current.setSelected();
+		if( current.getContainedNodes().size() > 0 )
+		{
+			if( subgraphAlgs.get( layerIndex ).get( nodeIndex ) == null )
+				subgraphAlgs.get( layerIndex ).set( nodeIndex, new BKNodePlacement( null, current ) );
+			if( subgraphAlgs.get( layerIndex ).get( nodeIndex ).forwardStep() == StepStatus.UNFINISHED )
+				return StepStatus.UNFINISHED;
+		}
+		ArrayList< LayeredGraphEdge > incommingEdges = current.getIncomingEdges();
+		if( incommingEdges.size() == 0 )
+		{
+			current.update();
+			backwards.add( 0, () -> {
+				System.out.println( "Performing Empty Backwards Step..." );
+			});
+			return calcNextState();
+		}
+		for( LayeredGraphEdge e : incommingEdges )
+		{
+			// TODO
+		}
+		backwards.add( 0, () -> {
+			System.out.println( "Stepping Backwards..." );
+			// TODO
+		});
+		current.update();
+		return calcNextState();
+	}
+	
+	private StepStatus calcNextState()
+	{
+		if( layerIndex >= graph.getContainedLayers().size() - 1 )
+		{
+			if( nodeIndex >= graph.getContainedLayers().get( layerIndex ).size() -1 )
+				return StepStatus.FINISHED;
+		}
+		nodeIndex++;
+		if( nodeIndex >= graph.getContainedLayers().get( layerIndex ).size() )
+		{
+			layerIndex++;
+			nodeIndex = 0;
+		}
+		return StepStatus.UNFINISHED;
+	}
+
+	@Override
+	public StepStatus backwardStep() {
+		if( subgraphAlgs.get( layerIndex ).get( nodeIndex ) != null )
+		{
+			if( subgraphAlgs.get( layerIndex ).get( nodeIndex ).backwardStep() == StepStatus.UNFINISHED )
+			{
+				LayeredGraphNode current = graph.getContainedLayers().get( layerIndex ).get( nodeIndex );
+				current.setSelected();
+				current.update();
+				return StepStatus.UNFINISHED;
+			}
+		}
+		StepStatus status = calcBeforeState();
+		if( status == StepStatus.FINISHED )
+			return status;
+		LayeredGraphNode current = graph.getContainedLayers().get( layerIndex ).get( nodeIndex );
+		current.setSelected();
+		current.update();
+		backwards.get( 0 ).reverse();
+		backwards.remove( 0 );
+		return status;
+	}
+	
+	private StepStatus calcBeforeState()
+	{
+		if( layerIndex == 0 )
+		{
+			if( nodeIndex == 0 )
+				return StepStatus.FINISHED;
+		}
+		nodeIndex--;
+		if( nodeIndex < 0 )
+		{
+			layerIndex--;
+			nodeIndex = graph.getContainedLayers().get( layerIndex ).size() - 1;
+		}
+		return StepStatus.UNFINISHED;
+	}
+}

+ 19 - 0
src/Algorithms/Animated/BK/Combine.java

@@ -0,0 +1,19 @@
+package Algorithms.Animated.BK;
+
+import Algorithms.Animated.AlgorithmStep;
+
+public class Combine implements AlgorithmStep {
+
+	@Override
+	public StepStatus forwardStep() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public StepStatus backwardStep() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+}

+ 35 - 0
src/Algorithms/Animated/BK/Layout.java

@@ -0,0 +1,35 @@
+package Algorithms.Animated.BK;
+
+import Algorithms.Animated.AlgorithmStep;
+import Model.LayeredGraphNode;
+
+public class Layout implements AlgorithmStep {
+
+	public enum LayoutType{
+		TOP_BOTTOM_LEFT,
+		TOP_BOTTOM_RIGHT,
+		BOTTOM_TOP_LEFT,
+		BOTTOM_TOP_RIGHT
+	}
+	
+	private LayoutType typ;
+	BlockCalc bc;
+	
+	public Layout( LayoutType typ, LayeredGraphNode graph )
+	{
+		this.typ = typ;
+		bc = new BlockCalc( graph );
+	}
+	
+	@Override
+	public StepStatus forwardStep() {
+		bc.forwardStep();
+		return StepStatus.UNFINISHED;
+	}
+
+	@Override
+	public StepStatus backwardStep() {
+		return bc.backwardStep();
+	}
+
+}

+ 6 - 0
src/Algorithms/Animated/BackwordAction.java

@@ -0,0 +1,6 @@
+package Algorithms.Animated;
+
+public interface BackwordAction {
+
+	public void reverse();
+}

+ 6 - 4
src/Algorithms/InitializeNodePositions.java

@@ -15,10 +15,12 @@ public class InitializeNodePositions {
 
     public static void placeNodes( LayeredGraphNode graph ) {
         
+    	RandomColorGenerator cGen = new RandomColorGenerator();
         for( LayeredGraphNode n : graph.getContainedNodes() )
         {
-            n.setWidth( 10 );
-            n.setHeight( 10 );
+            n.setWidth( 40 );
+            n.setHeight( 40 );
+            n.setColor( cGen.generateColor() );
             placeNodes( n );
         }
         int curY = 0;
@@ -39,9 +41,9 @@ public class InitializeNodePositions {
             for (LayeredGraphNode node : layer) { // Gehe alle Knoten durch
                 node.setX(curX + maxWidth / 2 - node.getWidth() / 2);
                 node.setY(curY + maxHeight / 2 - node.getHeight() / 2); // Position setzen
-                curX += maxWidth + 10;
+                curX += maxWidth + 25;
             }
-            curY += maxHeight + 10;
+            curY += maxHeight + 25;
         }
     }
 }

+ 22 - 0
src/Algorithms/RandomColorGenerator.java

@@ -0,0 +1,22 @@
+package Algorithms;
+
+import java.awt.Color;
+import java.util.Random;
+
+public class RandomColorGenerator {
+
+	Random rand;
+	
+	public RandomColorGenerator()
+	{
+		rand = new Random();
+	}
+	
+	public Color generateColor()
+	{
+		float r = rand.nextFloat();
+		float g = rand.nextFloat();
+		float b = rand.nextFloat();
+		return new Color( r, g, b );
+	}
+}

+ 1 - 1
src/Algorithms/RandomGraphGenerator.java

@@ -29,7 +29,7 @@ public class RandomGraphGenerator {
         LayeredGraphNode node = new LayeredNode( null, null );
         if( parent != null )
             node = parent.createNode( null );
-        if( Math.random() <= pSubgraph && depth < maxDepth )
+        if( ( Math.random() <= pSubgraph && depth < maxDepth ) || depth == 0 )
         {
             int layer = (int)( Math.random() * ( maxLayer - minLayer ) ) + minLayer;
             for( int i = 0; i < layer; i++ )

+ 128 - 0
src/Algorithms/SweepCrossingMinimizer.java

@@ -0,0 +1,128 @@
+package Algorithms;
+
+import java.util.ArrayList;
+
+import Model.LayeredGraphEdge;
+import Model.LayeredGraphNode;
+
+
+/**
+ * Der aus der Vorlesung bekannte Sweep Algorithmus zur Minnimierung von Kantenkreuzungen
+ * Es wird immer genau ein sweep durchgeführt
+ * @author kolja
+ *
+ */
+public class SweepCrossingMinimizer {
+
+    
+    public void minimizeCrossings( LayeredGraphNode graph ) {
+        ArrayList< ArrayList< LayeredGraphNode > > layers = graph.getContainedLayers();
+        System.out.println( "Number of Detected Crossings before minimization: " + numberOfCrossings( layers ) );
+        for( int i = 1; i < layers.size(); i++ )
+        { // Gehe alle Layer durch
+            ArrayList<LayeredGraphNode> l1 = layers.get( i - 1 );
+            ArrayList<LayeredGraphNode> l2 = layers.get( i );
+            graph.setOrderedLayer( reduceCrossingsBetweenLayers( l1, l2, false ), i ); // minnimiere die Kreuzungen zwischen den letzten beiden Layern
+        }
+        for( int i = layers.size() - 2; i >= 0; i-- )
+        { // Gehe alle Layer rückwärts durch
+            ArrayList<LayeredGraphNode> l1 = layers.get( i + 1 );
+            ArrayList<LayeredGraphNode> l2 = layers.get( i );
+            graph.setOrderedLayer( reduceCrossingsBetweenLayers( l1, l2, true ), i );  // minnimiere die Kreuzungen zwischen den letzten beiden Layern
+        }
+        System.out.println( "Number of Detected Crossings after minimization: " + numberOfCrossings( layers ) );
+    }
+    
+    /**
+     * Minnimiert die Kantenkreuzungen zwischen zwei layern
+     * @param l1 Eine geordnete Liste mit Knoten aus dem ersten Layer
+     * @param l2 Eine geordnete Liste mit Knoten aus dem zweiten Layer
+     * @param rev Gibt an, in welche Richtung die Kanten verlaufen (true, falls von l2 nach l1)
+     * @return Gibt eine Liste mit Gewichten zurück, nach denen die Knoten sortiert werden sollen
+     */
+    private ArrayList<Double> reduceCrossingsBetweenLayers( ArrayList<LayeredGraphNode> l1, ArrayList<LayeredGraphNode> l2, boolean rev)
+    {
+        ArrayList< Double > gewicht = new ArrayList< Double >();
+        for( LayeredGraphNode n : l2 )
+        { // Für jeden Knoten in Layer 2
+            ArrayList< LayeredGraphEdge > edges = null;
+            if( rev )
+                edges = n.getOutgoingEdges();
+            else
+                edges = n.getIncomingEdges(); // Kanten nach Layer 1
+            double g = 0;
+            for( LayeredGraphEdge e : edges )
+            { // Ermittle das Gewicht des Knotens
+                if( rev )
+                    g += l1.indexOf( e.getTargets().get( 0 ) );
+                else
+                    g += l1.indexOf( e.getSources().get( 0 ) );
+            }
+            g /= edges.size(); // Teile das Gewicht durch die Anzahl der Kanten
+            gewicht.add( g );
+        }
+        return gewicht;
+    }
+    
+    /**
+     * Zählt die Anzahl der Kantenkreuzungen in einem Graph
+     * @param layers Eine Liste mit Sortierten Layern
+     * @return Die Anzahl der Kreuzungen
+     */
+    private int numberOfCrossings(ArrayList<ArrayList<LayeredGraphNode>> layers)
+    {
+        ArrayList<LayeredGraphNode> lastLayer = null;
+        int crossings = 0;
+        for( ArrayList<LayeredGraphNode> l : layers )
+        {
+            if( lastLayer != null )
+                crossings += numberOfCrossings( lastLayer, l);
+            lastLayer = l;
+        }
+        return crossings;
+    }
+    
+    /**
+     * Zählt die Anzahl der Kantenkreuzungen zwischen zwei Layern (Es wird angenommen dass alle Kanten von l1 nach l2 verlaufen)
+     * @param l1 Der erste Layer
+     * @param l2 Der zweite Layer
+     * @return Die Anzahl der Kreuzungen
+     */
+    private int numberOfCrossings( ArrayList<LayeredGraphNode> l1, ArrayList<LayeredGraphNode> l2 )
+    {
+        // Algoritmus aus der Vorlesung
+        ArrayList< Integer > serie = new ArrayList<>();
+        for( LayeredGraphNode n : l1 )
+        {
+            ArrayList<LayeredGraphEdge> edges = n.getOutgoingEdges();
+            int i = 0;
+            for( LayeredGraphNode n2 : l2 )
+            {
+                for( LayeredGraphEdge e : edges )
+                {
+                    if( e.getTargets().contains( n2 ) )
+                    {
+                        serie.add( i );
+                        break;
+                    }
+                }
+                i++;
+            }
+        }
+        int crossings = 0;
+        for( int i = 1; i < serie.size(); i++ )
+        {
+            if( serie.get( i ) < serie.get( i - 1 ) )
+            {
+                int j = i - 1;
+                for( ; j > 0 && serie.get( i ) < serie.get( j - 1 ) ; j-- );
+                crossings += i - j;
+                int v = serie.get( i );
+                serie.remove( i );
+                serie.add( j, v);
+                i = Math.max( 1, j );
+            }
+        }
+        return crossings;
+    }
+}

+ 6 - 6
src/Main.java

@@ -1,5 +1,6 @@
 import Algorithms.InitializeNodePositions;
 import Algorithms.RandomGraphGenerator;
+import Algorithms.SweepCrossingMinimizer;
 import IO.Reader;
 import Model.LayeredGraphNode;
 import View.MainView;
@@ -9,12 +10,11 @@ public class Main {
 	public static void main(String[] args) {
 		//Reader r = new Reader( "save.graph" );
 		//LayeredGraphNode graph = r.readInputGraph();
-	    LayeredGraphNode graph = null;
-	    do
-	    {
-    	    RandomGraphGenerator r = new RandomGraphGenerator( 0.1, 0.3, 1, 10, 1, 5, 3 );
-    	    graph = r.createRandomNode( null, 0 );
-	    } while( graph.getContainedNodes().size() == 0 );
+	    RandomGraphGenerator r = new RandomGraphGenerator( 0.1, 0.1, 5, 10, 5, 10, 2 );
+	    LayeredGraphNode graph = r.createRandomNode( null, 0 );
+	    SweepCrossingMinimizer cminzer = new SweepCrossingMinimizer();
+	    for( int i = 0; i < 10; i++ )
+	    	cminzer.minimizeCrossings( graph );
 		InitializeNodePositions.placeNodes( graph );
 		new MainView( graph );
 	}

+ 10 - 0
src/Model/LayeredGraphNode.java

@@ -1,7 +1,10 @@
 package Model;
 
+import java.awt.Color;
 import java.util.ArrayList;
 
+import javax.swing.JPanel;
+
 import org.eclipse.elk.graph.ElkEdge;
 import org.eclipse.elk.graph.ElkNode;
 
@@ -22,6 +25,13 @@ public interface LayeredGraphNode {
     
     public void setName( String n );
     public String getName();
+    public void setColor( Color c );
+    public Color getColor();
+    public void update();
+    public void setSelected();
+    public boolean isSelected();
+    public void setView( JPanel v );
+    
     /**
      * Setzt den Index des Layers, zu dem der Knoten geh�ren soll
      * @param index Der Index mit 0 beginnend

+ 60 - 8
src/Model/LayeredNode.java

@@ -1,10 +1,16 @@
 package Model;
 
+import java.awt.Color;
 import java.util.ArrayList;
 
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
 import org.eclipse.elk.graph.ElkEdge;
 import org.eclipse.elk.graph.ElkNode;
 
+import View.MainView;
+
 /**
  * Die Implementation eines Knotens in einem Layered Graph
  * 
@@ -21,8 +27,11 @@ public class LayeredNode implements LayeredGraphNode {
     double y;
     double w;
     double h;
+    Color color;
     
     String name;
+    JPanel view;
+    boolean selected;
     
     // for subgraph in this node
     private ArrayList< LayeredGraphEdge > edges;
@@ -37,6 +46,53 @@ public class LayeredNode implements LayeredGraphNode {
         edges = new ArrayList<>();
         nodes = new ArrayList<>();
         layers = new ArrayList<>();
+        if( original != null )
+        {
+        	x = original.getX();
+        	y = original.getX();
+        	w = original.getWidth();
+        	h = original.getHeight();
+        }
+        
+    }
+    
+    public void update()
+    {
+    	SwingUtilities.invokeLater(new Runnable() {
+		    public void run() {
+		        System.out.println( "UPDATE" );
+		        MainView.frame.repaint();
+		    }
+		});
+    }
+    
+    public void setSelected()
+    {
+    	selected = true;
+    }
+    
+    public boolean isSelected()
+    {
+    	boolean tmp = selected;
+    	selected = false;
+    	return tmp;
+    }
+    
+    public void setView( JPanel v )
+    {
+    	view = v;
+    }
+    
+    @Override
+    public void setColor( Color c )
+    {
+    	color = c;
+    }
+    
+    @Override
+    public Color getColor()
+    {
+    	return color;
     }
     
     @Override
@@ -101,15 +157,13 @@ public class LayeredNode implements LayeredGraphNode {
 
     @Override
     public double getWidth() {
-        if( original != null )
-            return original.getWidth();
         if( nodes.size() > 0 )
         {
         	double max = 0;
         	for( LayeredGraphNode n : nodes )
         	{
-        		if( max < n.getX() + n.getWidth() + 20 )
-        			max = n.getX() + n.getWidth() + 20;
+        		if( max < n.getX() + n.getWidth() + 50 )
+        			max = n.getX() + n.getWidth() + 50;
         	}
         	return Math.max( max, w );
         }
@@ -118,15 +172,13 @@ public class LayeredNode implements LayeredGraphNode {
 
     @Override
     public double getHeight() {
-        if( original != null )
-            return original.getHeight();
         if( nodes.size() > 0 )
         {
         	double max = 0;
         	for( LayeredGraphNode n : nodes )
         	{
-        		if( max < n.getY() + n.getHeight() + 20 )
-        			max = n.getY() + n.getHeight() + 20;
+        		if( max < n.getY() + n.getHeight() + 50 )
+        			max = n.getY() + n.getHeight() + 50;
         	}
         	return Math.max( max, h );
         }

+ 4 - 2
src/View/EdgeView.java

@@ -1,5 +1,6 @@
 package View;
 
+import java.awt.BasicStroke;
 import java.awt.Color;
 import java.awt.Component;
 import java.awt.Graphics;
@@ -79,12 +80,13 @@ public class EdgeView extends JPanel {
     @Override
     public void paintComponent( Graphics g )
     {
-        System.out.println( "Clipping: x:" + g.getClip().getBounds().getX() + " y:" + g.getClip().getBounds().getY() + " w:" + g.getClip().getBounds().getWidth() + " h:" + g.getClip().getBounds().getHeight() );
+        ((Graphics2D)g).setStroke(new BasicStroke(1));
+        //System.out.println( "Clipping: x:" + g.getClip().getBounds().getX() + " y:" + g.getClip().getBounds().getY() + " w:" + g.getClip().getBounds().getWidth() + " h:" + g.getClip().getBounds().getHeight() );
         g.setColor( Color.GREEN );
         ArrayList<Point> bps = model.getLinePoints();
         for( int i = 1; i < bps.size(); i++ )
         {
-            System.out.println( "Draw a Line from (" + (int)bps.get( i - 1 ).getX() + "," + (int)bps.get( i - 1 ).getY() + ") to (" + (int)bps.get( i ).getX() + "," + (int)bps.get( i ).getY() + ")" );
+          //  System.out.println( "Draw a Line from (" + (int)bps.get( i - 1 ).getX() + "," + (int)bps.get( i - 1 ).getY() + ") to (" + (int)bps.get( i ).getX() + "," + (int)bps.get( i ).getY() + ")" );
             g.drawLine( (int)bps.get( i - 1 ).getX() - getX(), (int)bps.get( i - 1 ).getY() - getY(), (int)bps.get( i ).getX() - getX(), (int)bps.get( i ).getY() - getY() );
         }
         ((Graphics2D)g).fill( RenderHelper.createArrowShape( new Point( bps.get( bps.size() - 2 ).x - getX(), bps.get( bps.size() - 2 ).y - getY() ), new Point( bps.get( bps.size() - 1 ).x - getX(), bps.get( bps.size() - 1 ).y - getY() ) ) );

+ 14 - 1
src/View/MainView.java

@@ -5,16 +5,22 @@ import java.awt.event.KeyListener;
 
 import javax.swing.JFrame;
 
+import Algorithms.Animated.Action;
+import Algorithms.Animated.AnnimationController;
+import Algorithms.Animated.BK.BKNodePlacement;
 import IO.Writer;
 import Model.LayeredGraphEdge;
 import Model.LayeredGraphNode;
 
 public class MainView {
 
-	JFrame frame;
+	public static JFrame frame;
+	AnnimationController controller;
 	
 	public MainView( LayeredGraphNode graph )
 	{
+		controller = new AnnimationController();
+		controller.setTimeBetween( 100 );
 		frame = new JFrame();
         frame.setSize( (int)graph.getWidth() + 200, (int)graph.getHeight() + 200 );
 		frame.setLocation( 100, 100 );
@@ -36,6 +42,12 @@ public class MainView {
                     Writer w = new Writer( "save.graph" );
                     w.writeOutputGraph( graph );
                 }
+                if( e.getKeyCode() == KeyEvent.VK_LEFT )
+                	controller.setNextAction( Action.BACKWARD );
+                if( e.getKeyCode() == KeyEvent.VK_RIGHT )
+                	controller.setNextAction( Action.FORWARD );
+                if( e.getKeyCode() == KeyEvent.VK_P )
+                	controller.setContinuous( !controller.isContinuous() );
             }
 
             @Override
@@ -52,6 +64,7 @@ public class MainView {
 		frame.add( view );
 		
 		frame.repaint();
+		new BKNodePlacement( controller, graph );
 	}
 	
 	private NodeView createNodeView( LayeredGraphNode gNode )

+ 21 - 6
src/View/NodeView.java

@@ -1,8 +1,10 @@
 package View;
 
+import java.awt.BasicStroke;
 import java.awt.Color;
 import java.awt.Component;
 import java.awt.Graphics;
+import java.awt.Graphics2D;
 
 import javax.swing.*;
 
@@ -18,6 +20,7 @@ public class NodeView extends JPanel {
 	
 	public NodeView( LayeredGraphNode model ) {
 		this.model = model;
+		model.setView( this );
 	}
 	
 	@Override
@@ -50,16 +53,28 @@ public class NodeView extends JPanel {
         paintComponent( g );
         for( Component c : getComponents() )
             c.paint( g.create( 
-                    c.getX() + 10, 
-                    c.getY() + 10, 
-                    Math.min( getWidth() - 10, c.getWidth() + c.getX() + 10 ), 
-                    Math.min( getHeight() - 10, c.getHeight() + c.getY() + 10 ) ) );
+                    c.getX() + 25, 
+                    c.getY() + 25, 
+                    Math.min( getWidth() - 25, c.getWidth() + c.getX() + 25 ), 
+                    Math.min( getHeight() - 25, c.getHeight() + c.getY() + 25 ) ) );
     }
 
 	@Override
 	public void paintComponent( Graphics g )
 	{
-		g.setColor( Color.RED );
-		g.drawRect( 0, 0, getWidth()-1, getHeight()-1 );
+		if( model.isSelected() )
+		{
+			g.setColor( Color.GRAY );
+			g.fillRect( 0, 0, getWidth()-1, getHeight()-1 );
+		}
+		else
+		{
+			g.setColor( Color.WHITE );
+			g.fillRect( 0, 0, getWidth()-1, getHeight()-1 );
+		}
+		Graphics2D g2 = (Graphics2D)g;
+		g2.setColor( model.getColor() );
+		g2.setStroke(new BasicStroke(5));
+		g2.drawRect( 0, 0, getWidth()-1, getHeight()-1 );
 	}
 }