BlockCalc.java 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. package bk;
  2. import java.awt.Color;
  3. import java.util.ArrayList;
  4. import java.util.Collections;
  5. import animation.AlgorithmStage;
  6. import animation.BackwardAction;
  7. import animation.PseudoCodeNode;
  8. import bk.ExtremalLayoutCalc.LayoutType;
  9. import graph.LayeredGraphEdge;
  10. import graph.LayeredGraphNode;
  11. /**
  12. * The stage of the BK node placement algorithm where the blocks are computed.
  13. * @author kolja
  14. *
  15. */
  16. public class BlockCalc implements AlgorithmStage {
  17. private int layerIndex;
  18. private int nodeIndex;
  19. private int r;
  20. private LayeredGraphNode graph;
  21. private ArrayList< ArrayList< ExtremalLayoutCalc > > subgraphAlgs;
  22. private ArrayList< BackwardAction > backwards; // TODO: evtl richtigen "Stack" benutzen
  23. private LayoutType layout;
  24. private PseudoCodeNode loopNode;
  25. int step;
  26. public BlockCalc( LayeredGraphNode graph, LayoutType layout )
  27. {
  28. this.layout = layout;
  29. step = 0;
  30. this.graph = graph;
  31. layerIndex = 0;
  32. nodeIndex = 0;
  33. r = 0;
  34. subgraphAlgs = new ArrayList<>();
  35. for( ArrayList<LayeredGraphNode> l : graph.getContainedLayers() )
  36. {
  37. ArrayList< ExtremalLayoutCalc > algs = new ArrayList<>();
  38. for( int i = 0; i < l.size(); i++ )
  39. algs.add( null );
  40. subgraphAlgs.add( algs );
  41. }
  42. backwards = new ArrayList<>();
  43. }
  44. private int calcLayerIndex()
  45. {
  46. if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.TOP_BOTTOM_RIGHT )
  47. return layerIndex;
  48. if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT )
  49. return graph.getContainedLayers().size() - layerIndex - 1;
  50. return -1;
  51. }
  52. private int calcBeforeLayerIndex()
  53. {
  54. if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.TOP_BOTTOM_RIGHT )
  55. return layerIndex - 1;
  56. if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT )
  57. return graph.getContainedLayers().size() - layerIndex;
  58. return -1;
  59. }
  60. private int calcNodeIndex( int index )
  61. {
  62. if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.BOTTOM_TOP_LEFT )
  63. return index;
  64. if( layout == LayoutType.TOP_BOTTOM_RIGHT || layout == LayoutType.BOTTOM_TOP_RIGHT )
  65. return graph.getContainedLayers().get( calcLayerIndex() ).size() - index - 1;
  66. return index;
  67. }
  68. private int calcBeforeLayerNodeIndex( int index )
  69. {
  70. if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.BOTTOM_TOP_LEFT )
  71. return index;
  72. if( layout == LayoutType.TOP_BOTTOM_RIGHT || layout == LayoutType.BOTTOM_TOP_RIGHT )
  73. return graph.getContainedLayers().get( calcBeforeLayerIndex() ).size() - index - 1;
  74. return index;
  75. }
  76. @Override
  77. public StageStatus forwardStep() {
  78. LayeredGraphNode current = graph.getContainedLayers().get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) );
  79. current.setSelected( layout );
  80. if( current.getContainedNodes().size() > 0 )
  81. {
  82. if( subgraphAlgs.get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) ) == null )
  83. subgraphAlgs.get( calcLayerIndex() ).set( calcNodeIndex( nodeIndex ), new ExtremalLayoutCalc( layout, current ) );
  84. if( subgraphAlgs.get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) ).forwardStep() == StageStatus.UNFINISHED )
  85. return StageStatus.UNFINISHED;
  86. }
  87. ArrayList< LayeredGraphEdge > incommingEdges = null;
  88. if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.TOP_BOTTOM_RIGHT )
  89. incommingEdges = current.getSortedIncomingEdges();
  90. if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT )
  91. incommingEdges = current.getSortedOutgoingEdges();
  92. if( layout == LayoutType.TOP_BOTTOM_RIGHT || layout == LayoutType.BOTTOM_TOP_RIGHT )
  93. Collections.reverse( incommingEdges );
  94. if( incommingEdges.size() == 0 )
  95. {
  96. backwards.add( 0, () -> {
  97. System.out.println( "Performing Empty Backwards Step..." );
  98. });
  99. return calcNextState();
  100. }
  101. int[] ms = {(incommingEdges.size() + 1) / 2, (int)( (incommingEdges.size() + 1) / 2.0 + 0.5 )};
  102. boolean backwardsAdded = false;
  103. for( int m : ms )
  104. {
  105. if( current.getAlignedTo( layout ) == current )
  106. {
  107. LayeredGraphNode u = null;
  108. if( layout == LayoutType.TOP_BOTTOM_LEFT || layout == LayoutType.TOP_BOTTOM_RIGHT )
  109. u = incommingEdges.get( m - 1 ).getSources().get( 0 );
  110. if( layout == LayoutType.BOTTOM_TOP_LEFT || layout == LayoutType.BOTTOM_TOP_RIGHT )
  111. u = incommingEdges.get( m - 1 ).getTargets().get( 0 );
  112. ArrayList<LayeredGraphEdge> conflicts = incommingEdges.get( m - 1 ).calcConflictedEdges();
  113. if( !incommingEdges.get( m - 1 ).isConflicted( layout ) && r < calcBeforeLayerNodeIndex( graph.getContainedLayers().get( calcBeforeLayerIndex() ).indexOf( u ) ) + 1 )
  114. {
  115. System.out.println( "" );
  116. ArrayList< Boolean > oldConflicts = new ArrayList<>();
  117. for( LayeredGraphEdge e : conflicts )
  118. {
  119. oldConflicts.add( e.isConflicted( layout ) );
  120. e.setConflicted( true, layout );
  121. }
  122. LayeredGraphNode oldAlignU = u.getAlignedTo( layout );
  123. Color oldColorCurrent = current.getColor( layout );
  124. LayeredGraphNode oldRootCurrent = current.getRoot( layout );
  125. LayeredGraphNode oldAlignCurrent = current.getAlignedTo( layout );
  126. int oldR = r;
  127. u.setAlignTo( current, layout );
  128. current.setColor( u.getRoot( layout ).getColor( layout ), layout );
  129. current.setRoot( u.getRoot( layout ), layout );
  130. current.setAlignTo( current.getRoot( layout ), layout );
  131. r = calcBeforeLayerNodeIndex( graph.getContainedLayers().get( calcBeforeLayerIndex() ).indexOf( u ) ) + 1;
  132. int oldStep = step++;
  133. final LayeredGraphNode uf = u;
  134. backwards.add( 0, () -> {
  135. System.out.println( "Stepping Backwards... (Step " + oldStep + ")" );
  136. for( int i = 0; i < conflicts.size(); i++ )
  137. conflicts.get( i ).setConflicted( oldConflicts.get( i ), layout );
  138. uf.setAlignTo( oldAlignU, layout );
  139. current.setColor( oldColorCurrent, layout );
  140. current.setRoot( oldRootCurrent, layout );
  141. current.setAlignTo( oldAlignCurrent, layout );
  142. r = oldR;
  143. });
  144. backwardsAdded = true;
  145. }
  146. }
  147. }
  148. if( !backwardsAdded )
  149. {
  150. backwards.add( 0, () -> {
  151. System.out.println( "Performing Empty Backwards Step..." );
  152. });
  153. }
  154. //current.update();
  155. return calcNextState();
  156. }
  157. private StageStatus calcNextState()
  158. {
  159. loopNode.setSelected( true );
  160. if( layerIndex >= graph.getContainedLayers().size() - 1 )
  161. {
  162. if( nodeIndex >= graph.getContainedLayers().get( calcLayerIndex() ).size() -1 )
  163. {
  164. loopNode.setSelected( false );
  165. return StageStatus.FINISHED;
  166. }
  167. }
  168. nodeIndex++;
  169. if( nodeIndex >= graph.getContainedLayers().get( calcLayerIndex() ).size() )
  170. {
  171. layerIndex++;
  172. nodeIndex = 0;
  173. int oldR = r;
  174. r = 0;
  175. backwards.add(0, ()->{
  176. this.r = oldR;
  177. });
  178. }
  179. return StageStatus.UNFINISHED;
  180. }
  181. @Override
  182. public StageStatus backwardStep() {
  183. if( subgraphAlgs.get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) ) != null )
  184. {
  185. if( subgraphAlgs.get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) ).backwardStep() == StageStatus.UNFINISHED )
  186. {
  187. LayeredGraphNode current = graph.getContainedLayers().get( calcLayerIndex() ).get( nodeIndex );
  188. current.setSelected( layout );
  189. //current.update();
  190. return StageStatus.UNFINISHED;
  191. }
  192. }
  193. StageStatus status = calcBeforeState();
  194. if( status == StageStatus.FINISHED )
  195. return status;
  196. LayeredGraphNode current = graph.getContainedLayers().get( calcLayerIndex() ).get( calcNodeIndex( nodeIndex ) );
  197. current.setSelected( layout );
  198. //current.update();
  199. if( !backwards.isEmpty() )
  200. {
  201. backwards.get( 0 ).reverse();
  202. backwards.remove( 0 );
  203. }
  204. return status;
  205. }
  206. private StageStatus calcBeforeState()
  207. {
  208. loopNode.setSelected( true );
  209. if( layerIndex == 0 )
  210. {
  211. if( nodeIndex == 0 )
  212. {
  213. loopNode.setSelected( false );
  214. return StageStatus.FINISHED;
  215. }
  216. }
  217. nodeIndex--;
  218. if( nodeIndex < 0 )
  219. {
  220. layerIndex--;
  221. backwards.get( 0 ).reverse();
  222. backwards.remove( 0 );
  223. nodeIndex = graph.getContainedLayers().get( calcLayerIndex() ).size() - 1;
  224. }
  225. return StageStatus.UNFINISHED;
  226. }
  227. @Override
  228. public PseudoCodeNode createPseudocodeTree() {
  229. PseudoCodeNode root = new PseudoCodeNode( "Vertical alignment" );
  230. loopNode = new PseudoCodeNode( "Loop through all nodes..." );
  231. root.add( loopNode );
  232. return root;
  233. }
  234. @Override
  235. public StageStatus forwardStepOver() {
  236. return forwardStep();
  237. }
  238. @Override
  239. public StageStatus forwardStepOut() {
  240. StageStatus status = StageStatus.UNFINISHED;
  241. while( status != StageStatus.FINISHED )
  242. status = forwardStep();
  243. return status;
  244. }
  245. @Override
  246. public StageStatus backwardStepOver() {
  247. return backwardStep();
  248. }
  249. @Override
  250. public StageStatus backwardStepOut() {
  251. StageStatus status = StageStatus.UNFINISHED;
  252. while( status != StageStatus.FINISHED )
  253. status = backwardStep();
  254. return status;
  255. }
  256. }