package Algorithms.Animated.BK; import java.awt.Color; import java.util.ArrayList; import Algorithms.Animated.AlgorithmStage; import Algorithms.Animated.BackwardAction; import Algorithms.Animated.BK.ExtremalLayoutCalc.LayoutType; import Model.LayeredGraphEdge; import Model.LayeredGraphNode; /** * The stage of the BK node placement algorithm where the blocks are computed. * @author kolja * */ public class BlockCalc implements AlgorithmStage { private int layerIndex; private int nodeIndex; private int r; private LayeredGraphNode graph; private ArrayList< ArrayList< BKNodePlacement > > subgraphAlgs; private ArrayList< BackwardAction > backwards; private LayoutType layout; int step; public BlockCalc( LayeredGraphNode graph, LayoutType layout ) { this.layout = layout; step = 0; this.graph = graph; layerIndex = 0; nodeIndex = 0; r = 0; subgraphAlgs = new ArrayList<>(); for( ArrayList 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<>(); } private int calcLayerIndex() { if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.TOP_BOTTOM_RIGHT ) return layerIndex; if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT ) return graph.getContainedLayers().size() - layerIndex - 1; return -1; } private int calcBeforeLayerIndex() { if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.TOP_BOTTOM_RIGHT ) return layerIndex - 1; if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT ) return graph.getContainedLayers().size() - layerIndex; return -1; } @Override public StageStatus forwardStep() { LayeredGraphNode current = graph.getContainedLayers().get( calcLayerIndex() ).get( nodeIndex ); current.setSelected( layout ); if( current.getContainedNodes().size() > 0 ) { if( subgraphAlgs.get( calcLayerIndex() ).get( nodeIndex ) == null ) subgraphAlgs.get( calcLayerIndex() ).set( nodeIndex, new BKNodePlacement( null, current ) ); if( subgraphAlgs.get( calcLayerIndex() ).get( nodeIndex ).forwardStep() == StageStatus.UNFINISHED ) return StageStatus.UNFINISHED; } ArrayList< LayeredGraphEdge > incommingEdges = null; if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.TOP_BOTTOM_RIGHT ) incommingEdges = current.getSortedIncomingEdges(); if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT ) incommingEdges = current.getSortedOutgoingEdges(); if( incommingEdges.size() == 0 ) { backwards.add( 0, () -> { System.out.println( "Performing Empty Backwards Step..." ); }); return calcNextState(); } int[] ms = null; if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.BOTTOM_TOP_LEFT ) ms = new int[]{(incommingEdges.size() + 1) / 2, (int)( (incommingEdges.size() + 1) / 2.0 + 0.5 )}; if( layout == LayoutType.TOP_BOTTOM_RIGHT || layout == LayoutType.BOTTOM_TOP_RIGHT ) ms = new int[]{(int)( (incommingEdges.size() + 1) / 2.0 + 0.5 ), (incommingEdges.size() + 1) / 2}; boolean backwardsAdded = false; for( int m : ms ) { if( current.getAlignedTo( layout ) == current ) { LayeredGraphNode u = null; if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.TOP_BOTTOM_RIGHT ) u = incommingEdges.get( m - 1 ).getSources().get( 0 ); if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT ) u = incommingEdges.get( m - 1 ).getTargets().get( 0 ); ArrayList conflicts = incommingEdges.get( m - 1 ).calcConflictedEdges(); if( !incommingEdges.get( m - 1 ).isConflicted() && r < graph.getContainedLayers().get( calcBeforeLayerIndex() ).indexOf( u ) + 1 ) { System.out.println( "" ); ArrayList< Boolean > oldConflicts = new ArrayList<>(); for( LayeredGraphEdge e : conflicts ) { oldConflicts.add( e.isConflicted() ); e.setConflicted( true ); } LayeredGraphNode oldAlignU = u.getAlignedTo( layout ); Color oldColorCurrent = current.getColor( layout ); LayeredGraphNode oldRootCurrent = current.getRoot( layout ); LayeredGraphNode oldAlignCurrent = current.getAlignedTo( layout ); int oldR = r; u.setAlignTo( current, layout ); current.setColor( u.getRoot( layout ).getColor( layout ), layout ); current.setRoot( u.getRoot( layout ), layout ); current.setAlignTo( current.getRoot( layout ), layout ); r = graph.getContainedLayers().get( calcBeforeLayerIndex() ).indexOf( u ) + 1; int oldStep = step++; final LayeredGraphNode uf = u; backwards.add( 0, () -> { System.out.println( "Stepping Backwards... (Step " + oldStep + ")" ); for( int i = 0; i < conflicts.size(); i++ ) conflicts.get( i ).setConflicted( oldConflicts.get( i ) ); uf.setAlignTo( oldAlignU, layout ); current.setColor( oldColorCurrent, layout ); current.setRoot( oldRootCurrent, layout ); current.setAlignTo( oldAlignCurrent, layout ); r = oldR; }); backwardsAdded = true; } } } if( !backwardsAdded ) { backwards.add( 0, () -> { System.out.println( "Performing Empty Backwards Step..." ); }); } //current.update(); return calcNextState(); } private StageStatus calcNextState() { if( layerIndex >= graph.getContainedLayers().size() - 1 ) { if( nodeIndex >= graph.getContainedLayers().get( calcLayerIndex() ).size() -1 ) return StageStatus.FINISHED; } nodeIndex++; if( nodeIndex >= graph.getContainedLayers().get( calcLayerIndex() ).size() ) { layerIndex++; nodeIndex = 0; int oldR = r; r = 0; backwards.add(0, ()->{ this.r = oldR; }); } return StageStatus.UNFINISHED; } @Override public StageStatus backwardStep() { if( subgraphAlgs.get( calcLayerIndex() ).get( nodeIndex ) != null ) { if( subgraphAlgs.get( calcLayerIndex() ).get( nodeIndex ).backwardStep() == StageStatus.UNFINISHED ) { LayeredGraphNode current = graph.getContainedLayers().get( calcLayerIndex() ).get( nodeIndex ); current.setSelected( layout ); //current.update(); return StageStatus.UNFINISHED; } } StageStatus status = calcBeforeState(); if( status == StageStatus.FINISHED ) return status; LayeredGraphNode current = graph.getContainedLayers().get( calcLayerIndex() ).get( nodeIndex ); current.setSelected( layout ); //current.update(); if( !backwards.isEmpty() ) { backwards.get( 0 ).reverse(); backwards.remove( 0 ); } return status; } private StageStatus calcBeforeState() { if( layerIndex == 0 ) { if( nodeIndex == 0 ) return StageStatus.FINISHED; } nodeIndex--; if( nodeIndex < 0 ) { layerIndex--; backwards.get( 0 ).reverse(); backwards.remove( 0 ); nodeIndex = graph.getContainedLayers().get( calcLayerIndex() ).size() - 1; } return StageStatus.UNFINISHED; } }