- Timestamp:
- 02/28/14 11:56:15 (11 years ago)
- Location:
- trunk/sources
- Files:
-
- 3 added
- 2 deleted
- 7 edited
- 4 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/Formatters/SymbolicExpressionTreeLatexFormatter.cs
r10500 r10520 28 28 using HeuristicLab.Core; 29 29 30 namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding {30 namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views { 31 31 [Item("LaTeX/PDF Formatter", "Formatter for symbolic expression trees for use with latex package tikz.")] 32 32 public class SymbolicExpressionTreeLatexFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter { … … 37 37 }; 38 38 private readonly ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode> layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>(); 39 private readonly SymbolicExpressionTreeLayoutAdapter layoutAdapter = new SymbolicExpressionTreeLayoutAdapter();40 39 41 40 public SymbolicExpressionTreeLatexFormatter() 42 41 : base("LaTeX/PDF Formatter", "Formatter for symbolic expression trees for use with latex package tikz.") { 43 layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>(); 42 layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode> { 43 HorizontalSpacing = 2, 44 VerticalSpacing = 2, 45 NodeWidth = 8, 46 NodeHeight = 4 47 }; 44 48 } 45 49 … … 54 58 public string Format(ISymbolicExpressionTree symbolicExpressionTree) { 55 59 layoutEngine.Reset(); 56 var layoutNodes = layoutAdapter.Convert(symbolicExpressionTree).ToList();57 layoutEngine.Root = layoutNodes[0];58 layoutEngine. AddNodes(layoutNodes);60 var root = symbolicExpressionTree.Root; 61 var actualRoot = root.SubtreeCount == 0 ? root.GetSubtree(0) : root; 62 layoutEngine.Initialize(actualRoot, x => x.Subtrees); 59 63 layoutEngine.CalculateLayout(); 60 var nodeCoordinates = layoutEngine.Get NodeCoordinates();64 var nodeCoordinates = layoutEngine.GetCoordinates(); 61 65 var sb = new StringBuilder(); 62 66 var nl = Environment.NewLine; -
trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views-3.4.csproj
r8600 r10520 110 110 </ItemGroup> 111 111 <ItemGroup> 112 <Compile Include="Formatters\SymbolicExpressionTreeLatexFormatter.cs" /> 113 <Compile Include="LayoutEngines\BoxesLayoutEngine.cs" /> 114 <Compile Include="LayoutEngines\ILayoutEngine.cs" /> 115 <Compile Include="LayoutEngines\LayoutNode.cs" /> 116 <Compile Include="LayoutEngines\ReingoldTilfordLayoutEngine.cs" /> 112 117 <Compile Include="Plugin.cs" /> 113 118 <Compile Include="SymbolicExpressionGrammarAllowedChildSymbolsControl.cs"> … … 160 165 <DependentUpon>SymbolicExpressionView.cs</DependentUpon> 161 166 </Compile> 162 <Compile Include="Visual SymbolicExpressionTreeNode.cs" />163 <Compile Include="Visual SymbolicExpressionTreeNodeConnection.cs" />167 <Compile Include="VisualTreeNode.cs" /> 168 <Compile Include="VisualTreeNodeConnection.cs" /> 164 169 </ItemGroup> 165 170 <ItemGroup> … … 267 272 </BootstrapperPackage> 268 273 </ItemGroup> 274 <ItemGroup /> 269 275 <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> 270 276 <!-- To modify your build process, add your task inside one of the targets below and uncomment it. … … 276 282 --> 277 283 <PropertyGroup> 278 <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir)284 <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">set Path=%25Path%25;$(ProjectDir);$(SolutionDir) 279 285 set ProjectDir=$(ProjectDir) 280 286 set SolutionDir=$(SolutionDir) … … 283 289 call PreBuildEvent.cmd 284 290 </PreBuildEvent> 285 <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">291 <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' "> 286 292 export ProjectDir=$(ProjectDir) 287 293 export SolutionDir=$(SolutionDir) -
trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/LayoutEngines/LayoutNode.cs
r10471 r10520 24 24 using System.Linq; 25 25 26 namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding { 27 public class LayoutNode<T> where T : class { 26 namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views { 27 public class LayoutNode<T> : object where T : class { 28 public float Width { get; set; } 29 public float Height { get; set; } 30 28 31 public LayoutNode<T> NextLeft { 29 32 get { … … 75 78 } 76 79 } 80 /// <summary> 81 /// Translate the position of the layout node according to the given offsets 82 /// </summary> 83 /// <param name="dx"></param> 84 /// <param name="dy"></param> 85 public void Translate(float dx, float dy) { 86 X += dx; 87 Y += dy; 88 } 89 90 public void ResetCoordinates() { 91 X = 0; 92 Y = 0; 93 } 94 95 /// <summary> 96 /// Reset layout-related parameters 97 /// </summary> 98 public void Reset() { 99 Ancestor = this; 100 Thread = null; 101 Change = 0; 102 Shift = 0; 103 Prelim = 0; 104 Mod = 0; 105 ResetCoordinates(); 106 } 77 107 } 78 108 } -
trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/LayoutEngines/ReingoldTilfordLayoutEngine.cs
r10471 r10520 5 5 using System.Linq; 6 6 7 namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding {8 public class ReingoldTilfordLayoutEngine<T> where T : class {7 namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views { 8 public class ReingoldTilfordLayoutEngine<T> : ILayoutEngine<T> where T : class { 9 9 private readonly Dictionary<T, LayoutNode<T>> nodeMap; // provides a reverse mapping T => LayoutNode 10 public int NodeWidth { get; set; } 11 public int NodeHeight { get; set; } 12 private int minHorizontalSpacing = 5; 13 public int HorizontalSpacing { 14 get { return minHorizontalSpacing; } 15 set { minHorizontalSpacing = value; } 16 } 17 18 private int minVerticalSpacing = 5; 19 public int VerticalSpacing { 20 get { return minVerticalSpacing; } 21 set { minVerticalSpacing = value; } 22 } 23 24 public Func<T, IEnumerable<T>> GetChildren { get; set; } 25 public Func<T, int> GetLength { get; set; } 26 public Func<T, int> GetDepth { get; set; } 27 private LayoutNode<T> layoutRoot; 10 28 11 29 public ReingoldTilfordLayoutEngine() { … … 13 31 } 14 32 15 public Dictionary<T, LayoutNode<T>> NodeMap { get { return nodeMap; } } 33 public ReingoldTilfordLayoutEngine(T root, Func<T, IEnumerable<T>> childrenFunc) 34 : this() { 35 Initialize(root, childrenFunc); 36 } 37 38 public void Initialize(T root, Func<T, IEnumerable<T>> getChildren, Func<T, int> getLength = null, Func<T, int> getDepth = null) { 39 GetChildren = getChildren; 40 Clear(); 41 var node = new LayoutNode<T> { Content = root, Width = NodeWidth, Height = NodeHeight }; 42 node.Ancestor = node; 43 layoutRoot = node; 44 Expand(node); 45 } 46 47 private void Expand(LayoutNode<T> lRoot) { 48 nodeMap.Add(lRoot.Content, lRoot); 49 var children = GetChildren(lRoot.Content).ToList(); 50 if (!children.Any()) return; 51 lRoot.Children = new List<LayoutNode<T>>(children.Count); 52 for (int i = 0; i < children.Count; ++i) { 53 var node = new LayoutNode<T> { 54 Content = children[i], 55 Number = i, 56 Parent = lRoot, 57 Level = lRoot.Level + 1, 58 Width = NodeWidth, 59 Height = NodeHeight 60 }; 61 node.Ancestor = node; 62 lRoot.Children.Add(node); 63 Expand(node); 64 } 65 } 66 67 public IEnumerable<VisualTreeNode<T>> GetVisualNodes() { 68 return nodeMap.Values.Select(x => new VisualTreeNode<T>(x.Content) { 69 Width = (int)Math.Round(x.Width), 70 Height = (int)Math.Round(x.Height), 71 X = (int)Math.Round(x.X), 72 Y = (int)Math.Round(x.Y) 73 }); 74 } 16 75 17 76 public void AddNode(T content) { 18 if (nodeMap.ContainsKey(content)) { 19 throw new ArgumentException("Content already present in the dictionary."); 20 } 77 if (nodeMap.ContainsKey(content)) { throw new ArgumentException("Content already present in the dictionary."); } 21 78 var node = new LayoutNode<T> { Content = content }; 22 79 nodeMap.Add(content, node); … … 25 82 public void AddNode(LayoutNode<T> node) { 26 83 var content = node.Content; 27 if (nodeMap.ContainsKey(content)) { 28 throw new ArgumentException("Content already present in the dictionary."); 29 } 84 if (nodeMap.ContainsKey(content)) { throw new ArgumentException("Content already present in the dictionary."); } 30 85 nodeMap.Add(content, node); 31 86 } … … 42 97 } 43 98 44 private float minHorizontalSpacing = 5;45 public float MinHorizontalSpacing {46 get { return minHorizontalSpacing; }47 set { minHorizontalSpacing = value; }48 }49 50 private float minVerticalSpacing = 5;51 public float MinVerticalSpacing {52 get { return minVerticalSpacing; }53 set { minVerticalSpacing = value; }54 }55 56 private LayoutNode<T> root;57 public LayoutNode<T> Root {58 get { return root; }59 set {60 root = value;61 }62 }63 64 99 public void ResetCoordinates() { 65 100 foreach (var node in nodeMap.Values) { 66 node.X = 0; 67 node.Y = 0; 68 } 101 node.ResetCoordinates(); 102 } 103 } 104 105 public Dictionary<T, PointF> GetCoordinates() { 106 return nodeMap.ToDictionary(x => x.Key, x => new PointF(x.Value.X, x.Value.Y)); 69 107 } 70 108 71 109 /// <summary> 72 /// Transform LayoutNode coordinates so that all coordinates are positive and start from 0.110 /// Transform LayoutNode coordinates so that all coordinates are positive and start from (0,0) 73 111 /// </summary> 74 112 private void NormalizeCoordinates() { 75 var list= nodeMap.Values.ToList();113 var nodes = nodeMap.Values.ToList(); 76 114 float xmin = 0, ymin = 0; 77 for (int i = 0; i < list.Count; ++i) { 78 if (xmin > list[i].X) xmin = list[i].X; 79 if (ymin > list[i].Y) ymin = list[i].Y; 80 } 81 for (int i = 0; i < list.Count; ++i) { 82 list[i].X -= xmin; 83 list[i].Y -= ymin; 84 } 115 foreach (var node in nodes) { 116 if (xmin > node.X) xmin = node.X; 117 if (ymin > node.Y) ymin = node.Y; 118 } 119 foreach (var node in nodes) { 120 node.X -= xmin; 121 node.Y -= ymin; 122 } 123 } 124 125 public void Center(float width, float height) { 126 // center layout on screen 127 var bounds = Bounds(); 128 float dx = 0, dy = 0; 129 if (width > bounds.Width) { dx = (width - bounds.Width) / 2f; } 130 if (height > bounds.Height) { dy = (height - bounds.Height) / 2f; } 131 foreach (var node in nodeMap.Values) { node.Translate(dx, dy); } 132 } 133 134 public void FitToBounds(float width, float height) { 135 var bounds = Bounds(); 136 var myWidth = bounds.Width; 137 var myHeight = bounds.Height; 138 139 if (myWidth <= width && myHeight <= height) return; // no need to fit since we are within bounds 140 141 var layers = nodeMap.Values.GroupBy(node => node.Level, node => node).ToList(); 142 143 if (myWidth > width) { 144 // need to scale horizontally 145 float x = width / myWidth; 146 foreach (var node in layers.SelectMany(g => g)) { 147 node.X *= x; 148 node.Width *= x; 149 } 150 float spacing = minHorizontalSpacing * x; 151 foreach (var layer in layers) { 152 var nodes = layer.ToList(); 153 float minWidth = float.MaxValue; 154 for (int i = 0; i < nodes.Count - 1; ++i) { minWidth = Math.Min(minWidth, nodes[i + 1].X - nodes[i].X); } 155 float w = Math.Min(NodeWidth, minWidth - spacing); 156 foreach (var node in nodes) { 157 node.X += (node.Width - w) / 2f; 158 node.Width = w; 159 //this is a simple solution to ensure that the leftmost and rightmost nodes are not drawn partially offscreen due to scaling and offset 160 //this should work well enough 99.9% of the time with no noticeable visual difference 161 if (node.X < 0) { 162 node.Width += node.X; 163 node.X = 0; 164 } else if (node.X + node.Width > width) { 165 node.Width = width - node.X; 166 } 167 } 168 } 169 } 170 if (myHeight > height) { 171 // need to scale vertically 172 float x = height / myHeight; 173 foreach (var node in layers.SelectMany(g => g)) { 174 node.Y *= x; 175 node.Height *= x; 176 } 177 } 178 } 179 180 public void Clear() { 181 layoutRoot = null; 182 nodeMap.Clear(); 85 183 } 86 184 87 185 public void Reset() { 88 root = null;89 nodeMap.Clear();90 }91 92 public void ResetParameters() {93 186 foreach (var layoutNode in nodeMap.Values) { 94 187 // reset layout-related parameters 95 layoutNode.Ancestor = layoutNode; 96 layoutNode.Thread = null; 97 layoutNode.Change = 0; 98 layoutNode.Shift = 0; 99 layoutNode.Prelim = 0; 100 layoutNode.Mod = 0; 188 layoutNode.Reset(); 101 189 } 102 190 } 103 191 104 192 public void CalculateLayout() { 105 if (root == null) 106 throw new Exception("Root cannot be null."); 107 ResetCoordinates(); // reset node X,Y coordinates 108 ResetParameters(); // reset node parameters like Mod, Shift etc. 109 FirstWalk(root); 110 SecondWalk(root, -root.Prelim); 193 if (layoutRoot == null) throw new Exception("Layout layoutRoot cannot be null."); 194 Reset(); // reset node parameters like Mod, Shift etc. and set coordinates to 0 195 FirstWalk(layoutRoot); 196 SecondWalk(layoutRoot, -layoutRoot.Prelim); 111 197 NormalizeCoordinates(); 112 198 } 113 199 114 /// <summary> 115 /// Returns a map of coordinates for each LayoutNode in the symbolic expression tree. 116 /// </summary> 117 /// <returns></returns> 118 public Dictionary<T, PointF> GetNodeCoordinates() { 119 return nodeMap.ToDictionary(x => x.Key, x => new PointF(x.Value.X, x.Value.Y)); 200 public void CalculateLayout(float width, float height) { 201 CalculateLayout(); 202 FitToBounds(width, height); 203 Center(width, height); 120 204 } 121 205 … … 125 209 /// <returns></returns> 126 210 public RectangleF Bounds() { 127 float xmin , xmax, ymin, ymax; xmin = xmax = ymin =ymax = 0;211 float xmin = 0, xmax = 0, ymin = 0, ymax = 0; 128 212 var list = nodeMap.Values.ToList(); 129 for (int i = 0; i < list.Count; ++i) {130 float x = list[i].X, y = list[i].Y;213 foreach (LayoutNode<T> node in list) { 214 float x = node.X, y = node.Y; 131 215 if (xmin > x) xmin = x; 132 216 if (xmax < x) xmax = x; … … 134 218 if (ymax < y) ymax = y; 135 219 } 136 return new RectangleF(xmin, ymin, xmax + minHorizontalSpacing, ymax + minVerticalSpacing); 137 } 138 220 return new RectangleF(xmin, ymin, xmax + minHorizontalSpacing + NodeWidth, ymax + minVerticalSpacing + NodeHeight); 221 } 222 223 #region methods specific to the reingold-tilford layout algorithm 139 224 private void FirstWalk(LayoutNode<T> v) { 140 225 LayoutNode<T> w; … … 142 227 w = v.LeftSibling; 143 228 if (w != null) { 144 v.Prelim = w.Prelim + minHorizontalSpacing ;229 v.Prelim = w.Prelim + minHorizontalSpacing + NodeWidth; 145 230 } 146 231 } else { … … 157 242 w = v.LeftSibling; 158 243 if (w != null) { 159 v.Prelim = w.Prelim + minHorizontalSpacing ;244 v.Prelim = w.Prelim + minHorizontalSpacing + NodeWidth; 160 245 v.Mod = v.Prelim - midPoint; 161 246 } else { … … 167 252 private void SecondWalk(LayoutNode<T> v, float m) { 168 253 v.X = v.Prelim + m; 169 v.Y = v.Level * minVerticalSpacing;254 v.Y = v.Level * (minVerticalSpacing + NodeHeight); 170 255 if (v.IsLeaf) return; 171 256 foreach (var child in v.Children) { … … 193 278 vop = vop.NextRight; 194 279 vop.Ancestor = v; 195 float shift = (vim.Prelim + sim) - (vip.Prelim + sip) + minHorizontalSpacing ;280 float shift = (vim.Prelim + sim) - (vip.Prelim + sip) + minHorizontalSpacing + NodeWidth; 196 281 if (shift > 0) { 197 282 var ancestor = Ancestor(vim, v) ?? defaultAncestor; … … 244 329 return ancestor.Parent == v.Parent ? ancestor : null; 245 330 } 331 #endregion 246 332 } 247 333 } -
trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionGrammarAllowedChildSymbolsControl.cs
r9456 r10520 29 29 using HeuristicLab.PluginInfrastructure; 30 30 31 using VisualSymbolicExpressionTreeNode = HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views.VisualTreeNode<HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.ISymbolicExpressionTreeNode>; 32 31 33 namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views { 32 34 public sealed partial class SymbolicExpressionGrammarAllowedChildSymbolsControl : UserControl { … … 162 164 163 165 VisualSymbolicExpressionTreeNode clickedNode = (VisualSymbolicExpressionTreeNode)sender; 164 var selectedNode = clickedNode. SymbolicExpressionTreeNode;166 var selectedNode = clickedNode.Content; 165 167 if (selectedNode.SubtreeCount == 0) { 166 168 if (!selectedSymbolicExpressionTreeNodes.Contains(selectedNode)) … … 207 209 var visualNode = symbolicExpressionTreeChart.FindVisualSymbolicExpressionTreeNodeAt(coordinates.X, coordinates.Y); 208 210 if (visualNode != null) { 209 var node = visualNode. SymbolicExpressionTreeNode;211 var node = visualNode.Content; 210 212 var root = symbolicExpressionTreeChart.Tree.Root; 211 213 if (node == root || node.Parent == root) e.Effect = DragDropEffects.Copy; … … 223 225 var symbols = data as IEnumerable<ISymbol>; 224 226 225 if (node. SymbolicExpressionTreeNode== root) {227 if (node.Content == root) { 226 228 if (symbol != null) 227 229 Grammar.AddAllowedChildSymbol(root.Symbol, symbol); … … 229 231 foreach (var s in symbols) Grammar.AddAllowedChildSymbol(root.Symbol, s); 230 232 } else { 231 int argumentIndex = root.IndexOfSubtree(node. SymbolicExpressionTreeNode);233 int argumentIndex = root.IndexOfSubtree(node.Content); 232 234 if (symbol != null) 233 235 Grammar.AddAllowedChildSymbol(root.Symbol, symbol, argumentIndex); -
trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionTreeChart.Designer.cs
r10496 r10520 49 49 this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); 50 50 this.saveImageToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 51 this.exportPgfLaTeXToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 52 this.layoutEngineToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 53 this.reingoldTilfordToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 54 this.boxesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 51 55 this.saveFileDialog = new System.Windows.Forms.SaveFileDialog(); 52 this.exportPgfLaTeXToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();53 56 this.contextMenuStrip.SuspendLayout(); 54 57 this.SuspendLayout(); … … 58 61 this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 59 62 this.saveImageToolStripMenuItem, 60 this.exportPgfLaTeXToolStripMenuItem}); 63 this.exportPgfLaTeXToolStripMenuItem, 64 this.layoutEngineToolStripMenuItem}); 61 65 this.contextMenuStrip.Name = "contextMenuStrip"; 62 66 this.contextMenuStrip.Size = new System.Drawing.Size(166, 70); … … 65 69 // 66 70 this.saveImageToolStripMenuItem.Name = "saveImageToolStripMenuItem"; 67 this.saveImageToolStripMenuItem.Size = new System.Drawing.Size(1 52, 22);71 this.saveImageToolStripMenuItem.Size = new System.Drawing.Size(165, 22); 68 72 this.saveImageToolStripMenuItem.Text = "Save Image"; 69 73 this.saveImageToolStripMenuItem.Click += new System.EventHandler(this.saveImageToolStripMenuItem_Click); 70 //71 // saveFileDialog72 //73 this.saveFileDialog.Filter = "Bitmap (*.bmp)|*.bmp|EMF (*.emf)|*.emf";74 74 // 75 75 // exportPgfLaTeXToolStripMenuItem … … 79 79 this.exportPgfLaTeXToolStripMenuItem.Text = "Export Pgf/LaTeX"; 80 80 this.exportPgfLaTeXToolStripMenuItem.Click += new System.EventHandler(this.exportLatexToolStripMenuItem_Click); 81 // 82 // layoutEngineToolStripMenuItem 83 // 84 this.layoutEngineToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 85 this.reingoldTilfordToolStripMenuItem, 86 this.boxesToolStripMenuItem}); 87 this.layoutEngineToolStripMenuItem.Name = "layoutEngineToolStripMenuItem"; 88 this.layoutEngineToolStripMenuItem.Size = new System.Drawing.Size(165, 22); 89 this.layoutEngineToolStripMenuItem.Text = "Layout Engine:"; 90 // 91 // reingoldTilfordToolStripMenuItem 92 // 93 this.reingoldTilfordToolStripMenuItem.Name = "reingoldTilfordToolStripMenuItem"; 94 this.reingoldTilfordToolStripMenuItem.Size = new System.Drawing.Size(161, 22); 95 this.reingoldTilfordToolStripMenuItem.Text = "Reingold-Tilford"; 96 this.reingoldTilfordToolStripMenuItem.Click += new System.EventHandler(this.reingoldTilfordToolStripMenuItem_Click); 97 // 98 // boxesToolStripMenuItem 99 // 100 this.boxesToolStripMenuItem.Name = "boxesToolStripMenuItem"; 101 this.boxesToolStripMenuItem.Size = new System.Drawing.Size(161, 22); 102 this.boxesToolStripMenuItem.Text = "Boxes"; 103 this.boxesToolStripMenuItem.Click += new System.EventHandler(this.boxesToolStripMenuItem_Click); 104 // 105 // saveFileDialog 106 // 107 this.saveFileDialog.Filter = "Bitmap (*.bmp)|*.bmp|EMF (*.emf)|*.emf"; 81 108 // 82 109 // SymbolicExpressionTreeChart … … 103 130 protected System.Windows.Forms.SaveFileDialog saveFileDialog; 104 131 private System.Windows.Forms.ToolStripMenuItem exportPgfLaTeXToolStripMenuItem; 132 private System.Windows.Forms.ToolStripMenuItem layoutEngineToolStripMenuItem; 133 private System.Windows.Forms.ToolStripMenuItem reingoldTilfordToolStripMenuItem; 134 private System.Windows.Forms.ToolStripMenuItem boxesToolStripMenuItem; 105 135 } 106 136 } -
trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionTreeChart.cs
r10499 r10520 33 33 private Image image; 34 34 private readonly StringFormat stringFormat; 35 private Dictionary<ISymbolicExpressionTreeNode, VisualSymbolicExpressionTreeNode> visualTreeNodes; 36 private Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualSymbolicExpressionTreeNodeConnection> visualLines; 37 private readonly ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode> layoutEngine; 38 private readonly SymbolicExpressionTreeLayoutAdapter layoutAdapter; 35 private Dictionary<ISymbolicExpressionTreeNode, VisualTreeNode<ISymbolicExpressionTreeNode>> visualTreeNodes; 36 private Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualTreeNodeConnection> visualLines; 37 private ILayoutEngine<ISymbolicExpressionTreeNode> layoutEngine; 39 38 40 39 private const int preferredNodeWidth = 70; 41 40 private const int preferredNodeHeight = 46; 42 private const int minHorizontalDistance = 20; 43 private const int minVerticalDistance = 20; 44 41 private const int minHorizontalDistance = 30; 42 private const int minVerticalDistance = 30; 45 43 46 44 public SymbolicExpressionTreeChart() { … … 52 50 this.backgroundColor = Color.White; 53 51 this.textFont = new Font(FontFamily.GenericSansSerif, 12); 54 layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>(); 55 layoutAdapter = new SymbolicExpressionTreeLayoutAdapter(); 52 // layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode> { 53 layoutEngine = new BoxesLayoutEngine<ISymbolicExpressionTreeNode> { 54 NodeWidth = preferredNodeWidth, 55 NodeHeight = preferredNodeHeight, 56 HorizontalSpacing = minHorizontalDistance, 57 VerticalSpacing = minVerticalDistance 58 }; 56 59 } 57 60 58 61 public SymbolicExpressionTreeChart(ISymbolicExpressionTree tree) 59 62 : this() { 60 layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>();61 layoutAdapter = new SymbolicExpressionTreeLayoutAdapter();62 63 this.Tree = tree; 63 64 } … … 105 106 set { 106 107 tree = value; 107 visualTreeNodes = new Dictionary<ISymbolicExpressionTreeNode, VisualSymbolicExpressionTreeNode>();108 visualLines = new Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualSymbolicExpressionTreeNodeConnection>();109 108 if (tree != null) { 110 IEnumerable<ISymbolicExpressionTreeNode> nodes; 111 if (tree.Root.SubtreeCount == 1) nodes = tree.Root.GetSubtree(0).IterateNodesPrefix(); 112 else nodes = tree.Root.IterateNodesPrefix(); 113 foreach (ISymbolicExpressionTreeNode node in nodes) { 114 visualTreeNodes[node] = new VisualSymbolicExpressionTreeNode(node); 115 if (node.Parent != null) visualLines[Tuple.Create(node.Parent, node)] = new VisualSymbolicExpressionTreeNodeConnection(); 116 } 117 } 118 Repaint(); 109 Repaint(); 110 } 119 111 } 120 112 } … … 160 152 } 161 153 162 public void RepaintNode(Visual SymbolicExpressionTreeNodevisualNode) {154 public void RepaintNode(VisualTreeNode<ISymbolicExpressionTreeNode> visualNode) { 163 155 if (!suspendRepaint) { 164 156 using (var graphics = Graphics.FromImage(image)) { … … 182 174 } 183 175 184 public Visual SymbolicExpressionTreeNodeGetVisualSymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode) {176 public VisualTreeNode<ISymbolicExpressionTreeNode> GetVisualSymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode) { 185 177 if (visualTreeNodes.ContainsKey(symbolicExpressionTreeNode)) 186 178 return visualTreeNodes[symbolicExpressionTreeNode]; … … 188 180 } 189 181 190 public Visual SymbolicExpressionTreeNodeConnection GetVisualSymbolicExpressionTreeNodeConnection(ISymbolicExpressionTreeNode parent, ISymbolicExpressionTreeNode child) {182 public VisualTreeNodeConnection GetVisualSymbolicExpressionTreeNodeConnection(ISymbolicExpressionTreeNode parent, ISymbolicExpressionTreeNode child) { 191 183 if (child.Parent != parent) throw new ArgumentException(); 192 184 var key = Tuple.Create(parent, child); 193 Visual SymbolicExpressionTreeNodeConnection connection = null;185 VisualTreeNodeConnection connection = null; 194 186 visualLines.TryGetValue(key, out connection); 195 187 return connection; … … 205 197 206 198 protected virtual void SymbolicExpressionTreeChart_MouseClick(object sender, MouseEventArgs e) { 207 VisualSymbolicExpressionTreeNodevisualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);199 var visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y); 208 200 if (visualTreeNode != null) { 209 201 OnSymbolicExpressionTreeNodeClicked(visualTreeNode, e); … … 219 211 220 212 protected virtual void SymbolicExpressionTreeChart_MouseDoubleClick(object sender, MouseEventArgs e) { 221 Visual SymbolicExpressionTreeNodevisualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);213 VisualTreeNode<ISymbolicExpressionTreeNode> visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y); 222 214 if (visualTreeNode != null) 223 215 OnSymbolicExpressionTreeNodeDoubleClicked(visualTreeNode, e); … … 231 223 } 232 224 233 private Visual SymbolicExpressionTreeNodedraggedSymbolicExpressionTree;225 private VisualTreeNode<ISymbolicExpressionTreeNode> draggedSymbolicExpressionTree; 234 226 private MouseButtons dragButtons; 235 227 private void SymbolicExpressionTreeChart_MouseDown(object sender, MouseEventArgs e) { … … 243 235 244 236 private void SymbolicExpressionTreeChart_MouseMove(object sender, MouseEventArgs e) { 245 Visual SymbolicExpressionTreeNodevisualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);237 VisualTreeNode<ISymbolicExpressionTreeNode> visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y); 246 238 if (draggedSymbolicExpressionTree != null && 247 239 draggedSymbolicExpressionTree != visualTreeNode) { … … 258 250 } 259 251 260 public Visual SymbolicExpressionTreeNodeFindVisualSymbolicExpressionTreeNodeAt(int x, int y) {252 public VisualTreeNode<ISymbolicExpressionTreeNode> FindVisualSymbolicExpressionTreeNodeAt(int x, int y) { 261 253 foreach (var visualTreeNode in visualTreeNodes.Values) { 262 254 if (x >= visualTreeNode.X && x <= visualTreeNode.X + visualTreeNode.Width && … … 269 261 270 262 #region methods for painting the symbolic expression tree 271 private void DrawFunctionTree(ISymbolicExpressionTree symbolicExpressionTree, Graphics graphics, int preferredWidth, int preferredHeight, int minHDistance, int minVDistance) { 272 var layoutNodes = layoutAdapter.Convert(symbolicExpressionTree).ToList(); 273 if(symbolicExpressionTree.Root.SubtreeCount==1) layoutNodes.RemoveAt(0); 274 layoutEngine.Reset(); 275 layoutEngine.Root = layoutNodes[0]; 276 layoutEngine.AddNodes(layoutNodes); 277 layoutEngine.MinHorizontalSpacing = (preferredWidth + minHDistance); 278 layoutEngine.MinVerticalSpacing = (preferredHeight + minVDistance); 279 layoutEngine.CalculateLayout(); 280 var bounds = layoutEngine.Bounds(); 281 282 double verticalScalingFactor = 1.0; 283 double layoutHeight = (bounds.Height + preferredHeight); 284 if (this.Height < layoutHeight) 285 verticalScalingFactor = this.Height / layoutHeight; 286 287 double horizontalScalingFactor = 1.0; 288 double layoutWidth = (bounds.Width + preferredWidth); 289 if (this.Width < layoutWidth) 290 horizontalScalingFactor = this.Width / layoutWidth; 291 292 double horizontalOffset; 293 if (this.Width > layoutWidth) 294 horizontalOffset = (this.Width - layoutWidth) / 2.0; 295 else 296 horizontalOffset = preferredWidth / 2.0; 297 298 var levels = layoutNodes.GroupBy(n => n.Level, n => n).ToList(); 299 for (int i = levels.Count - 1; i >= 0; --i) { 300 var nodes = levels[i].ToList(); 301 302 double minSpacing = double.MaxValue; 303 if (nodes.Count > 1) { 304 for (int j = 1; j < nodes.Count() - 1; ++j) { 305 var distance = nodes[j].X - nodes[j - 1].X; // guaranteed to be > 0 306 if (minSpacing > distance) minSpacing = distance; 307 } 308 } 309 minSpacing *= horizontalScalingFactor; 310 311 int minWidth = (int)Math.Round(preferredWidth * horizontalScalingFactor); 312 int width = (int)Math.Min(minSpacing, preferredWidth) - 2; // leave some pixels so that node margins don't overlap 313 314 foreach (var layoutNode in nodes) { 315 var visualNode = visualTreeNodes[layoutNode.Content]; 316 visualNode.Width = width; 317 visualNode.Height = (int)Math.Round(preferredHeight * verticalScalingFactor); 318 visualNode.X = (int)Math.Round((layoutNode.X + horizontalOffset) * horizontalScalingFactor + (minWidth - width) / 2.0); 319 visualNode.Y = (int)Math.Round(layoutNode.Y * verticalScalingFactor); 320 DrawTreeNode(graphics, visualNode); 321 } 322 } 323 // draw node connections 324 foreach (var visualNode in visualTreeNodes.Values) { 325 var node = visualNode.SymbolicExpressionTreeNode; 263 private void DrawFunctionTree(ISymbolicExpressionTree symbExprTree, Graphics graphics, int preferredWidth, int preferredHeight, int minHDistance, int minVDistance) { 264 var root = symbExprTree.Root; 265 var actualRoot = root.SubtreeCount == 1 ? root.GetSubtree(0) : root; 266 layoutEngine.NodeWidth = preferredWidth; 267 layoutEngine.NodeHeight = preferredHeight; 268 layoutEngine.HorizontalSpacing = minHDistance; 269 layoutEngine.VerticalSpacing = minVDistance; 270 layoutEngine.Initialize(actualRoot, n => n.Subtrees, n => n.GetLength(), n => n.GetDepth()); 271 layoutEngine.CalculateLayout(Width, Height); 272 273 var visualNodes = layoutEngine.GetVisualNodes().ToList(); 274 visualTreeNodes = visualNodes.ToDictionary(x => x.Content, x => x); 275 visualLines = new Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualTreeNodeConnection>(); 276 foreach (var node in visualNodes.Select(n => n.Content)) { 277 foreach (var subtree in node.Subtrees) { 278 visualLines.Add(new Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(node, subtree), new VisualTreeNodeConnection()); 279 } 280 } 281 // draw nodes and connections 282 foreach (var visualNode in visualNodes) { 283 DrawTreeNode(visualNode); 284 var node = visualNode.Content; 326 285 foreach (var subtree in node.Subtrees) { 327 286 var visualLine = GetVisualSymbolicExpressionTreeNodeConnection(node, subtree); … … 338 297 } 339 298 340 protected void DrawTreeNode(Visual SymbolicExpressionTreeNodevisualTreeNode) {299 protected void DrawTreeNode(VisualTreeNode<ISymbolicExpressionTreeNode> visualTreeNode) { 341 300 using (var graphics = Graphics.FromImage(image)) { 342 301 graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; … … 346 305 } 347 306 348 protected void DrawTreeNode(Graphics graphics, Visual SymbolicExpressionTreeNodevisualTreeNode) {307 protected void DrawTreeNode(Graphics graphics, VisualTreeNode<ISymbolicExpressionTreeNode> visualTreeNode) { 349 308 graphics.Clip = new Region(new Rectangle(visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width + 1, visualTreeNode.Height + 1)); 350 309 graphics.Clear(backgroundColor); 351 var node = visualTreeNode. SymbolicExpressionTreeNode;310 var node = visualTreeNode.Content; 352 311 using (var textBrush = new SolidBrush(visualTreeNode.TextColor)) 353 312 using (var nodeLinePen = new Pen(visualTreeNode.LineColor)) … … 408 367 } 409 368 #endregion 369 370 private void reingoldTilfordToolStripMenuItem_Click(object sender, EventArgs e) { 371 layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode> { 372 NodeWidth = preferredNodeWidth, 373 NodeHeight = preferredNodeHeight, 374 HorizontalSpacing = minHorizontalDistance, 375 VerticalSpacing = minVerticalDistance 376 }; 377 Repaint(); 378 } 379 380 private void boxesToolStripMenuItem_Click(object sender, EventArgs e) { 381 layoutEngine = new BoxesLayoutEngine<ISymbolicExpressionTreeNode> { 382 NodeWidth = preferredNodeWidth, 383 NodeHeight = preferredNodeHeight, 384 HorizontalSpacing = minHorizontalDistance, 385 VerticalSpacing = minVerticalDistance 386 }; 387 Repaint(); 388 } 410 389 } 411 390 } -
trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/VisualTreeNode.cs
r10500 r10520 23 23 24 24 namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views { 25 public class Visual SymbolicExpressionTreeNode : object{25 public class VisualTreeNode<T> where T : class { 26 26 private static readonly Color defaultLineColor = Color.Black; 27 27 private static readonly Color defaultTextColor = Color.Black; … … 30 30 private const int defaultPreferredHeight = 46; 31 31 32 public Visual SymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode) :33 this( symbolicExpressionTreeNode, defaultLineColor) {32 public VisualTreeNode(T content) : 33 this(content, defaultLineColor) { 34 34 } 35 35 36 public Visual SymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode, Color lineColor) :37 this( symbolicExpressionTreeNode, lineColor, defaultTextColor) {36 public VisualTreeNode(T content, Color lineColor) : 37 this(content, lineColor, defaultTextColor) { 38 38 } 39 39 40 public Visual SymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode, Color lineColor, Color textColor) :41 this( symbolicExpressionTreeNode, lineColor, textColor, defaultFillColor) {40 public VisualTreeNode(T content, Color lineColor, Color textColor) : 41 this(content, lineColor, textColor, defaultFillColor) { 42 42 } 43 43 44 public Visual SymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode, Color lineColor, Color textColor, Color fillColor) :45 this( symbolicExpressionTreeNode, lineColor, textColor, fillColor, defaultPreferredWidth, defaultPreferredHeight) {44 public VisualTreeNode(T content, Color lineColor, Color textColor, Color fillColor) : 45 this(content, lineColor, textColor, fillColor, defaultPreferredWidth, defaultPreferredHeight) { 46 46 } 47 47 48 public Visual SymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode, Color lineColor, Color textColor, Color fillColor, int width, int height) {49 this. symbolicExpressionTreeNode = symbolicExpressionTreeNode;48 public VisualTreeNode(T content, Color lineColor, Color textColor, Color fillColor, int width, int height) { 49 this.content = content; 50 50 this.lineColor = lineColor; 51 51 this.textColor = textColor; … … 53 53 this.preferredWidth = width; 54 54 this.preferredHeight = height; 55 this.ToolTip = symbolicExpressionTreeNode.ToString();55 this.ToolTip = content.ToString(); 56 56 } 57 57 … … 82 82 #endregion 83 83 84 private ISymbolicExpressionTreeNode symbolicExpressionTreeNode;85 public ISymbolicExpressionTreeNode SymbolicExpressionTreeNode{86 get { return this. symbolicExpressionTreeNode; }84 private T content; 85 public T Content { 86 get { return this.content; } 87 87 set { 88 symbolicExpressionTreeNode= value;89 ToolTip = SymbolicExpressionTreeNode.ToString();88 content = value; 89 ToolTip = Content.ToString(); 90 90 } 91 91 } -
trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/VisualTreeNodeConnection.cs
r10500 r10520 24 24 25 25 namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views { 26 public class Visual SymbolicExpressionTreeNodeConnection : object {26 public class VisualTreeNodeConnection : object { 27 27 private static readonly Color defaultLineColor = Color.Black; 28 28 private static readonly DashStyle defaultDashStyle = DashStyle.Solid; … … 40 40 } 41 41 42 public Visual SymbolicExpressionTreeNodeConnection()42 public VisualTreeNodeConnection() 43 43 : base() { 44 44 lineColor = defaultLineColor; -
trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding-3.4.csproj
r10496 r10520 135 135 <Compile Include="Creators\RampedHalfAndHalfTreeCreator.cs" /> 136 136 <Compile Include="Formatters\SymbolicExpressionTreeGraphvizFormatter.cs" /> 137 <Compile Include="Formatters\SymbolicExpressionTreeLatexFormatter.cs" />138 <Compile Include="Interfaces\ILayoutAdapter.cs" />139 137 <Compile Include="Interfaces\IReadOnlySymbol.cs" /> 140 138 <Compile Include="Interfaces\ISymbolicExpressionGrammar.cs" /> … … 156 154 <Compile Include="Interfaces\ISymbolicExpressionTreeStringFormatter.cs" /> 157 155 <Compile Include="Interfaces\Operators\ISymbolicExpressionTreeSizeConstraintOperator.cs" /> 158 <Compile Include="LayoutEngines\LayoutNode.cs" />159 <Compile Include="LayoutEngines\ReingoldTilfordLayoutEngine.cs" />160 <Compile Include="LayoutEngines\SymbolicExpressionTreeLayoutAdapter.cs" />161 156 <Compile Include="Manipulators\ChangeNodeTypeManipulation.cs" /> 162 157 <Compile Include="Interfaces\Operators\ISymbolicExpressionTreeManipulator.cs" />
Note: See TracChangeset
for help on using the changeset viewer.