BlockCalc.java 9.8 KB

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