Combine.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. package bk;
  2. import java.awt.Color;
  3. import java.util.ArrayList;
  4. import java.util.Collections;
  5. import java.util.List;
  6. import javax.swing.JTree;
  7. import animation.CodeLine;
  8. import animation.ControlFlow;
  9. import animation.Memory;
  10. import animation.Memory.MemoryType;
  11. import animation.Memory.ReadOnlyMemory;
  12. import animation.PseudoCodeNode;
  13. import codelines.DeclareVariable;
  14. import codelines.ForEachLoop;
  15. import codelines.FunctionDefinition;
  16. import codelines.SetVariable;
  17. import graph.LayeredGraphNode;
  18. /**
  19. * The stage of the combination of the four extremal layouts.
  20. * @author kolja
  21. *
  22. */
  23. public class Combine {
  24. public static PseudoCodeNode combine( JTree tree ) {
  25. String[] vars = { "graph", "l", "l_min", "v", "positions" };
  26. @SuppressWarnings("serial")
  27. PseudoCodeNode root = new PseudoCodeNode( "function combine( graph )", vars, tree, new FunctionDefinition( new String[]{ "graph" } ) ){
  28. @Override
  29. public String getDebugOutput( Memory m )
  30. {
  31. if( m.isSomewhereDefined( "v", MemoryType.LOCAL ) )
  32. m.<LayeredGraphNode>read( "v", MemoryType.LOCAL).setSelected( null );
  33. return super.getDebugOutput( m );
  34. }
  35. };
  36. root.add( new PseudoCodeNode( "-- Align all Layouts to the one with the smallest width --", vars, tree, new CodeLine() {
  37. @Override
  38. public ControlFlow runForward(Memory m) {
  39. LayeredGraphNode graph = m.read( "graph", MemoryType.LOCAL );
  40. if( graph.parent() == null )
  41. graph.setColor( Color.BLACK, null );
  42. actions.add( (Memory mem) -> {
  43. if( graph.parent() == null )
  44. graph.setColor( null, null );
  45. });
  46. return new ControlFlow( ControlFlow.STEP_OVER );
  47. }
  48. }));
  49. PseudoCodeNode firstLoop = new PseudoCodeNode( "foreach l in ['DOWN_RIGHT', 'DOWN_LEFT', 'UP_RIGHT', 'UP_LEFT'] do", vars, tree, new ForEachLoop<String>( "l" ) {
  50. @Override
  51. protected List<String> list(ReadOnlyMemory m) {
  52. ArrayList< String > list = new ArrayList<String>();
  53. list.add( "DOWN_RIGHT" );
  54. list.add( "DOWN_LEFT" );
  55. list.add( "UP_RIGHT" );
  56. list.add( "UP_LEFT" );
  57. return list;
  58. }
  59. });
  60. root.add( firstLoop );
  61. firstLoop.add( new PseudoCodeNode( "min[l] = minimum x coordinate in l;", vars, tree, new CodeLine() {
  62. @Override
  63. public ControlFlow runForward(Memory m) {
  64. String layout = m.read( "l", MemoryType.LOCAL );
  65. m.declare( "min[" + layout + "]", calcMinX( m.read( "graph", MemoryType.LOCAL ), LayoutType.fromString( layout ) ), MemoryType.GLOBAL );
  66. actions.add( (Memory mem) -> {
  67. mem.undeclare( "min[" + layout + "]", MemoryType.GLOBAL );
  68. });
  69. return new ControlFlow( ControlFlow.STEP_OVER );
  70. }
  71. }));
  72. firstLoop.add( new PseudoCodeNode( "max[l] = maximum x coordinate in l;", vars, tree, new CodeLine() {
  73. @Override
  74. public ControlFlow runForward(Memory m) {
  75. String layout = m.read( "l", MemoryType.LOCAL );
  76. m.declare( "max[" + layout + "]", calcMaxX( m.read( "graph", MemoryType.LOCAL ), LayoutType.fromString( layout ) ), MemoryType.GLOBAL );
  77. actions.add( (Memory mem) -> {
  78. mem.undeclare( "max[" + layout + "]", MemoryType.GLOBAL );
  79. });
  80. return new ControlFlow( ControlFlow.STEP_OVER );
  81. }
  82. }));
  83. firstLoop.add( new PseudoCodeNode( "width[l] = max[l] - min[l];", vars, tree, new CodeLine() {
  84. @Override
  85. public ControlFlow runForward(Memory m) {
  86. String layout = m.read( "l", MemoryType.LOCAL );
  87. m.declare( "width[" + layout + "]", m.<Integer>read( "max[" + layout + "]", MemoryType.GLOBAL ) - m.<Integer>read( "min[" + layout + "]", MemoryType.GLOBAL ), MemoryType.GLOBAL );
  88. actions.add( (Memory mem) -> {
  89. mem.undeclare( "width[" + layout + "]", MemoryType.GLOBAL );
  90. });
  91. return new ControlFlow( ControlFlow.STEP_OVER );
  92. }
  93. }));
  94. root.add( new PseudoCodeNode( "l_min = l with width[l] == min(width);", vars, tree, new DeclareVariable<String>( "l_min" ) {
  95. @Override
  96. protected String value(ReadOnlyMemory m) {
  97. String min = "DOWN_RIGHT";
  98. int minW = m.read( "width[DOWN_RIGHT]", MemoryType.GLOBAL );
  99. for( String l : new String[]{ "DOWN_LEFT", "UP_RIGHT", "UP_LEFT" } )
  100. {
  101. if( minW > m.<Integer>read( "width[" + l + "]", MemoryType.GLOBAL ) )
  102. {
  103. minW = m.<Integer>read( "width[" + l + "]", MemoryType.GLOBAL );
  104. min = l;
  105. }
  106. }
  107. return min;
  108. }
  109. }));
  110. PseudoCodeNode secondLoop = new PseudoCodeNode( "foreach l in ['DOWN_RIGHT', 'DOWN_LEFT', 'UP_RIGHT', 'UP_LEFT'] do", vars, tree, new ForEachLoop<String>( "l" ) {
  111. @Override
  112. protected List<String> list(ReadOnlyMemory m) {
  113. ArrayList< String > list = new ArrayList<String>();
  114. list.add( "DOWN_RIGHT" );
  115. list.add( "DOWN_LEFT" );
  116. list.add( "UP_RIGHT" );
  117. list.add( "UP_LEFT" );
  118. return list;
  119. }
  120. });
  121. root.add( secondLoop );
  122. secondLoop.add( new PseudoCodeNode( "shift[l] = l.contains('RIGHT') ? min[l_min] - min[l] : max[l_min] - max[l];", vars, tree, new CodeLine() {
  123. @Override
  124. public ControlFlow runForward(Memory m) {
  125. String layout = m.read( "l", MemoryType.LOCAL );
  126. String lMin = m.read( "l_min", MemoryType.LOCAL );
  127. if( layout.contains( "RIGHT" ) )
  128. m.declare( "shift[" + layout + "]", m.<Integer>read( "min[" + lMin + "]", MemoryType.GLOBAL ) - m.<Integer>read( "min[" + layout + "]", MemoryType.GLOBAL ), MemoryType.GLOBAL );
  129. else
  130. m.declare( "shift[" + layout + "]", m.<Integer>read( "max[" + lMin + "]", MemoryType.GLOBAL ) - m.<Integer>read( "max[" + layout + "]", MemoryType.GLOBAL ), MemoryType.GLOBAL );
  131. actions.add( (Memory mem) -> {
  132. mem.undeclare( "shift[" + layout + "]", MemoryType.GLOBAL );
  133. });
  134. return new ControlFlow( ControlFlow.STEP_OVER );
  135. }
  136. }));
  137. PseudoCodeNode thirdLoop = new PseudoCodeNode( "foreach v in graph do", vars, tree, new ForEachLoop<LayeredGraphNode>( "v" ) {
  138. @Override
  139. protected List<LayeredGraphNode> list(ReadOnlyMemory m) {
  140. return m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL ).getContainedNodes();
  141. }
  142. });
  143. root.add( thirdLoop );
  144. thirdLoop.add( new PseudoCodeNode( "positions = [];", vars, tree, new DeclareVariable<ArrayList<Integer>>( "positions") {
  145. @Override
  146. protected ArrayList<Integer> value(ReadOnlyMemory m) {
  147. return new ArrayList<Integer>();
  148. }
  149. }));
  150. PseudoCodeNode innerLoop = new PseudoCodeNode( "foreach l in ['DOWN_RIGHT', 'DOWN_LEFT', 'UP_RIGHT', 'UP_LEFT'] do", vars, tree, new ForEachLoop<String>( "l" ) {
  151. @Override
  152. protected List<String> list(ReadOnlyMemory m) {
  153. ArrayList< String > list = new ArrayList<String>();
  154. list.add( "DOWN_RIGHT" );
  155. list.add( "DOWN_LEFT" );
  156. list.add( "UP_RIGHT" );
  157. list.add( "UP_LEFT" );
  158. return list;
  159. }
  160. });
  161. innerLoop.add( new PseudoCodeNode( "positions.add(x[v] in l);", vars, tree, new CodeLine() {
  162. @Override
  163. public ControlFlow runForward(Memory m) {
  164. String layout = m.read( "l", MemoryType.LOCAL );
  165. ArrayList<Integer> positions = m.read( "positions", MemoryType.LOCAL );
  166. positions.add( (int)m.<LayeredGraphNode>read( "v", MemoryType.LOCAL ).getX( LayoutType.fromString( layout ) ) + m.<Integer>read( "shift[" + layout + "]", MemoryType.GLOBAL ) );
  167. actions.add( (Memory mem) -> {
  168. positions.remove( positions.size() - 1 );
  169. });
  170. return new ControlFlow( ControlFlow.STEP_OVER );
  171. }
  172. }));
  173. thirdLoop.add( innerLoop );
  174. thirdLoop.add( new PseudoCodeNode( "positions = sort( positions );", vars, tree, new SetVariable<ArrayList<Integer>>( "positions" ) {
  175. @Override
  176. public ArrayList<Integer> value(ReadOnlyMemory m) {
  177. ArrayList<Integer> positions = m.read( "positions", MemoryType.LOCAL );
  178. ArrayList<Integer> neu = new ArrayList<Integer>();
  179. for( int p : positions )
  180. neu.add( p );
  181. Collections.sort( neu );
  182. return neu;
  183. }
  184. }));
  185. thirdLoop.add( new PseudoCodeNode( "x[v] = (positions[1]+positions[2]) / 2;", vars, tree, new CodeLine() {
  186. @Override
  187. public ControlFlow runForward(Memory m) {
  188. ArrayList<Integer> positions = m.read( "positions", MemoryType.LOCAL );
  189. LayeredGraphNode v = m.read( "v", MemoryType.LOCAL );
  190. double old = v.getX( LayoutType.COMBINED );
  191. v.setX( (positions.get( 1 ) + positions.get( 2 )) / 2.0, true, LayoutType.COMBINED );
  192. actions.add( (Memory mem) -> {
  193. v.setX( old, false, LayoutType.COMBINED );
  194. });
  195. return new ControlFlow( ControlFlow.STEP_OVER );
  196. }
  197. }));
  198. return root;
  199. }
  200. private static int calcMinX( LayeredGraphNode graph, LayoutType layout )
  201. {
  202. int minX = 0;
  203. if( graph.getContainedNodes().size() > 0 )
  204. minX = (int)graph.getContainedNodes().get( 0 ).getX( layout );
  205. for( LayeredGraphNode n : graph.getContainedNodes() )
  206. minX = Math.min( minX, (int)n.getX( layout ) );
  207. return minX;
  208. }
  209. private static int calcMaxX( LayeredGraphNode graph, LayoutType layout )
  210. {
  211. int maxX = 0;
  212. if( graph.getContainedNodes().size() > 0 )
  213. maxX = (int)graph.getContainedNodes().get( 0 ).getX( layout );
  214. for( LayeredGraphNode n : graph.getContainedNodes() )
  215. maxX = Math.max( maxX, (int)n.getX( layout ) );
  216. return maxX;
  217. }
  218. }