Changeset 11205 for branches/HiveStatistics/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionTreeChart.cs
- Timestamp:
- 07/18/14 13:44:53 (10 years ago)
- Location:
- branches/HiveStatistics/sources
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/HiveStatistics/sources
- Property svn:ignore
-
old new 8 8 FxCopResults.txt 9 9 Google.ProtocolBuffers-0.9.1.dll 10 Google.ProtocolBuffers-2.4.1.473.dll 10 11 HeuristicLab 3.3.5.1.ReSharper.user 11 12 HeuristicLab 3.3.6.0.ReSharper.user 12 13 HeuristicLab.4.5.resharper.user 13 14 HeuristicLab.ExtLibs.6.0.ReSharper.user 15 HeuristicLab.Scripting.Development 14 16 HeuristicLab.resharper.user 15 17 ProtoGen.exe … … 17 19 _ReSharper.HeuristicLab 18 20 _ReSharper.HeuristicLab 3.3 21 _ReSharper.HeuristicLab 3.3 Tests 19 22 _ReSharper.HeuristicLab.ExtLibs 20 23 bin 21 24 protoc.exe 22 _ReSharper.HeuristicLab 3.3 Tests23 Google.ProtocolBuffers-2.4.1.473.dll
-
- Property svn:mergeinfo changed
- Property svn:ignore
-
branches/HiveStatistics/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views
- Property svn:mergeinfo changed
-
branches/HiveStatistics/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionTreeChart.cs
r11203 r11205 1 1 #region License Information 2 2 /* HeuristicLab 3 * Copyright (C) 2002-201 2Heuristic and Evolutionary Algorithms Laboratory (HEAL)3 * Copyright (C) 2002-2014 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 4 * 5 5 * This file is part of HeuristicLab. … … 24 24 using System.Drawing; 25 25 using System.Drawing.Imaging; 26 using System.IO; 27 using System.Linq; 26 28 using System.Windows.Forms; 29 27 30 28 31 namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views { 29 32 public partial class SymbolicExpressionTreeChart : UserControl { 30 33 private Image image; 31 private StringFormat stringFormat; 32 private Dictionary<ISymbolicExpressionTreeNode, VisualSymbolicExpressionTreeNode> visualTreeNodes; 33 private Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualSymbolicExpressionTreeNodeConnection> visualLines; 34 private readonly StringFormat stringFormat; 35 private Dictionary<ISymbolicExpressionTreeNode, VisualTreeNode<ISymbolicExpressionTreeNode>> visualTreeNodes; 36 private Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualTreeNodeConnection> visualLines; 37 private ILayoutEngine<ISymbolicExpressionTreeNode> layoutEngine; 38 39 private const int preferredNodeWidth = 70; 40 private const int preferredNodeHeight = 46; 41 private int minHorizontalDistance = 30; 42 private int minVerticalDistance = 30; 34 43 35 44 public SymbolicExpressionTreeChart() { … … 40 49 this.lineColor = Color.Black; 41 50 this.backgroundColor = Color.White; 42 this.textFont = new Font("Times New Roman", 8); 51 this.textFont = new Font(FontFamily.GenericSansSerif, 12); 52 53 visualTreeNodes = new Dictionary<ISymbolicExpressionTreeNode, VisualTreeNode<ISymbolicExpressionTreeNode>>(); 54 visualLines = new Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualTreeNodeConnection>(); 55 56 layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>(n => n.Subtrees) { 57 NodeWidth = preferredNodeWidth, 58 NodeHeight = preferredNodeHeight, 59 HorizontalSpacing = minHorizontalDistance, 60 VerticalSpacing = minVerticalDistance 61 }; 62 reingoldTilfordToolStripMenuItem.Checked = true; 43 63 } 44 64 … … 48 68 } 49 69 70 #region Public properties 50 71 private int spacing; 51 72 public int Spacing { … … 89 110 set { 90 111 tree = value; 91 visualTreeNodes = new Dictionary<ISymbolicExpressionTreeNode, VisualSymbolicExpressionTreeNode>();92 visualLines = new Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualSymbolicExpressionTreeNodeConnection>();93 if (tree != null) {94 foreach (ISymbolicExpressionTreeNode node in tree.IterateNodesPrefix()) {95 visualTreeNodes[node] = new VisualSymbolicExpressionTreeNode(node);96 if (node.Parent != null) visualLines[Tuple.Create(node.Parent, node)] = new VisualSymbolicExpressionTreeNodeConnection();97 }98 }99 112 Repaint(); 100 113 } … … 106 119 set { suspendRepaint = value; } 107 120 } 121 #endregion 108 122 109 123 protected override void OnPaint(PaintEventArgs e) { … … 115 129 if (this.Width <= 1 || this.Height <= 1) 116 130 this.image = new Bitmap(1, 1); 117 else 131 else { 118 132 this.image = new Bitmap(Width, Height); 133 } 119 134 this.Repaint(); 135 } 136 137 public event EventHandler Repainted;//expose this event to notify the parent control that the tree was repainted 138 protected virtual void OnRepaint(object sender, EventArgs e) { 139 var repainted = Repainted; 140 if (repainted != null) { 141 repainted(sender, e); 142 } 120 143 } 121 144 … … 124 147 this.GenerateImage(); 125 148 this.Refresh(); 149 OnRepaint(this, EventArgs.Empty); 126 150 } 127 151 } … … 134 158 foreach (var visualNode in visualTreeNodes.Values) { 135 159 DrawTreeNode(graphics, visualNode); 160 if (visualNode.Content.SubtreeCount > 0) { 161 foreach (var visualSubtree in visualNode.Content.Subtrees.Select(s => visualTreeNodes[s])) { 162 DrawLine(graphics, visualNode, visualSubtree); 163 } 164 } 136 165 } 137 166 } … … 140 169 } 141 170 142 public void RepaintNode(Visual SymbolicExpressionTreeNodevisualNode) {171 public void RepaintNode(VisualTreeNode<ISymbolicExpressionTreeNode> visualNode) { 143 172 if (!suspendRepaint) { 144 173 using (var graphics = Graphics.FromImage(image)) { … … 157 186 graphics.Clear(backgroundColor); 158 187 if (tree != null) { 159 int height = this.Height / tree.Depth; 160 DrawFunctionTree(tree, graphics, 0, 0, this.Width, height); 161 } 162 } 163 } 164 165 public VisualSymbolicExpressionTreeNode GetVisualSymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode) { 188 DrawFunctionTree(graphics, preferredNodeWidth, preferredNodeHeight, minHorizontalDistance, minVerticalDistance); 189 } 190 } 191 } 192 193 public VisualTreeNode<ISymbolicExpressionTreeNode> GetVisualSymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode) { 166 194 if (visualTreeNodes.ContainsKey(symbolicExpressionTreeNode)) 167 195 return visualTreeNodes[symbolicExpressionTreeNode]; … … 169 197 } 170 198 171 public Visual SymbolicExpressionTreeNodeConnection GetVisualSymbolicExpressionTreeNodeConnection(ISymbolicExpressionTreeNode parent, ISymbolicExpressionTreeNode child) {199 public VisualTreeNodeConnection GetVisualSymbolicExpressionTreeNodeConnection(ISymbolicExpressionTreeNode parent, ISymbolicExpressionTreeNode child) { 172 200 if (child.Parent != parent) throw new ArgumentException(); 173 201 var key = Tuple.Create(parent, child); 174 Visual SymbolicExpressionTreeNodeConnection connection = null;202 VisualTreeNodeConnection connection = null; 175 203 visualLines.TryGetValue(key, out connection); 176 204 return connection; … … 186 214 187 215 protected virtual void SymbolicExpressionTreeChart_MouseClick(object sender, MouseEventArgs e) { 188 VisualSymbolicExpressionTreeNodevisualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);216 var visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y); 189 217 if (visualTreeNode != null) { 190 218 OnSymbolicExpressionTreeNodeClicked(visualTreeNode, e); … … 200 228 201 229 protected virtual void SymbolicExpressionTreeChart_MouseDoubleClick(object sender, MouseEventArgs e) { 202 Visual SymbolicExpressionTreeNodevisualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);230 VisualTreeNode<ISymbolicExpressionTreeNode> visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y); 203 231 if (visualTreeNode != null) 204 232 OnSymbolicExpressionTreeNodeDoubleClicked(visualTreeNode, e); … … 212 240 } 213 241 214 private Visual SymbolicExpressionTreeNodedraggedSymbolicExpressionTree;242 private VisualTreeNode<ISymbolicExpressionTreeNode> draggedSymbolicExpressionTree; 215 243 private MouseButtons dragButtons; 216 244 private void SymbolicExpressionTreeChart_MouseDown(object sender, MouseEventArgs e) { … … 224 252 225 253 private void SymbolicExpressionTreeChart_MouseMove(object sender, MouseEventArgs e) { 226 Visual SymbolicExpressionTreeNodevisualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);254 VisualTreeNode<ISymbolicExpressionTreeNode> visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y); 227 255 if (draggedSymbolicExpressionTree != null && 228 256 draggedSymbolicExpressionTree != visualTreeNode) { … … 239 267 } 240 268 241 public Visual SymbolicExpressionTreeNodeFindVisualSymbolicExpressionTreeNodeAt(int x, int y) {269 public VisualTreeNode<ISymbolicExpressionTreeNode> FindVisualSymbolicExpressionTreeNodeAt(int x, int y) { 242 270 foreach (var visualTreeNode in visualTreeNodes.Values) { 243 271 if (x >= visualTreeNode.X && x <= visualTreeNode.X + visualTreeNode.Width && … … 249 277 #endregion 250 278 279 private void CalculateLayout(int preferredWidth, int preferredHeight, int minHDistance, int minVDistance) { 280 layoutEngine.NodeWidth = preferredWidth; 281 layoutEngine.NodeHeight = preferredHeight; 282 layoutEngine.HorizontalSpacing = minHDistance; 283 layoutEngine.VerticalSpacing = minVDistance; 284 285 var actualRoot = tree.Root; 286 if (actualRoot.Symbol is ProgramRootSymbol && actualRoot.SubtreeCount == 1) { 287 actualRoot = tree.Root.GetSubtree(0); 288 } 289 290 var visualNodes = layoutEngine.CalculateLayout(actualRoot, Width, Height).ToList(); 291 visualTreeNodes = visualNodes.ToDictionary(x => x.Content, x => x); 292 visualLines = new Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualTreeNodeConnection>(); 293 foreach (var node in visualNodes.Select(n => n.Content)) { 294 foreach (var subtree in node.Subtrees) { 295 visualLines.Add(new Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(node, subtree), new VisualTreeNodeConnection()); 296 } 297 } 298 } 299 251 300 #region methods for painting the symbolic expression tree 252 private void DrawFunctionTree(ISymbolicExpressionTree tree, Graphics graphics, int x, int y, int width, int height) { 253 DrawFunctionTree(tree.Root, graphics, x, y, width, height, Point.Empty); 254 } 255 256 /// <summary> 257 /// 258 /// </summary> 259 /// <param name="functionTree"> function tree to draw</param> 260 /// <param name="graphics">graphics object to draw on</param> 261 /// <param name="x">x coordinate of drawing area</param> 262 /// <param name="y">y coordinate of drawing area</param> 263 /// <param name="width">width of drawing area</param> 264 /// <param name="height">height of drawing area</param> 265 private void DrawFunctionTree(ISymbolicExpressionTreeNode node, Graphics graphics, int x, int y, int width, int height, Point connectionPoint) { 266 VisualSymbolicExpressionTreeNode visualTreeNode = visualTreeNodes[node]; 267 float center_x = x + width / 2; 268 float center_y = y + height / 2; 269 int actualWidth = width - spacing; 270 int actualHeight = height - spacing; 271 272 using (var textBrush = new SolidBrush(visualTreeNode.TextColor)) 273 using (var nodeLinePen = new Pen(visualTreeNode.LineColor)) 274 using (var nodeFillBrush = new SolidBrush(visualTreeNode.FillColor)) { 275 276 //calculate size of node 277 if (actualWidth >= visualTreeNode.PreferredWidth && actualHeight >= visualTreeNode.PreferredHeight) { 278 visualTreeNode.Width = visualTreeNode.PreferredWidth; 279 visualTreeNode.Height = visualTreeNode.PreferredHeight; 280 visualTreeNode.X = (int)center_x - visualTreeNode.Width / 2; 281 visualTreeNode.Y = (int)center_y - visualTreeNode.Height / 2; 282 } 283 //width too small to draw in desired sized 284 else if (actualWidth < visualTreeNode.PreferredWidth && actualHeight >= visualTreeNode.PreferredHeight) { 285 visualTreeNode.Width = actualWidth; 286 visualTreeNode.Height = visualTreeNode.PreferredHeight; 287 visualTreeNode.X = x; 288 visualTreeNode.Y = (int)center_y - visualTreeNode.Height / 2; 289 } 290 //height too small to draw in desired sized 291 else if (actualWidth >= visualTreeNode.PreferredWidth && actualHeight < visualTreeNode.PreferredHeight) { 292 visualTreeNode.Width = visualTreeNode.PreferredWidth; 293 visualTreeNode.Height = actualHeight; 294 visualTreeNode.X = (int)center_x - visualTreeNode.Width / 2; 295 visualTreeNode.Y = y; 296 } 297 //width and height too small to draw in desired size 298 else { 299 visualTreeNode.Width = actualWidth; 300 visualTreeNode.Height = actualHeight; 301 visualTreeNode.X = x; 302 visualTreeNode.Y = y; 303 } 304 305 //draw terminal node 306 if (node.SubtreeCount == 0) { 307 graphics.FillRectangle(nodeFillBrush, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height); 308 graphics.DrawRectangle(nodeLinePen, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height); 309 } else { 310 graphics.FillEllipse(nodeFillBrush, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height); 311 graphics.DrawEllipse(nodeLinePen, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height); 312 } 313 314 //draw name of symbol 315 var text = node.ToString(); 316 graphics.DrawString(text, textFont, textBrush, new RectangleF(visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height), stringFormat); 317 318 //draw connection line to parent node 319 if (!connectionPoint.IsEmpty && node.Parent != null) { 320 var visualLine = GetVisualSymbolicExpressionTreeNodeConnection(node.Parent, node); 321 using (Pen linePen = new Pen(visualLine.LineColor)) { 301 private void DrawFunctionTree(Graphics graphics, int preferredWidth, int preferredHeight, int minHDistance, int minVDistance) { 302 CalculateLayout(preferredWidth, preferredHeight, minHDistance, minVDistance); 303 var visualNodes = visualTreeNodes.Values; 304 //draw nodes and connections 305 foreach (var visualNode in visualNodes) { 306 DrawTreeNode(graphics, visualNode); 307 var node = visualNode.Content; 308 foreach (var subtree in node.Subtrees) { 309 var visualLine = GetVisualSymbolicExpressionTreeNodeConnection(node, subtree); 310 var visualSubtree = visualTreeNodes[subtree]; 311 var origin = new Point(visualNode.X + visualNode.Width / 2, visualNode.Y + visualNode.Height); 312 var target = new Point(visualSubtree.X + visualSubtree.Width / 2, visualSubtree.Y); 313 graphics.Clip = new Region(new Rectangle(Math.Min(origin.X, target.X), origin.Y, Math.Max(origin.X, target.X), target.Y)); 314 using (var linePen = new Pen(visualLine.LineColor)) { 322 315 linePen.DashStyle = visualLine.DashStyle; 323 graphics.DrawLine(linePen, connectionPoint, new Point(visualTreeNode.X + visualTreeNode.Width / 2, visualTreeNode.Y));316 graphics.DrawLine(linePen, origin, target); 324 317 } 325 318 } 326 327 //calculate areas for the subtrees according to their tree size and call drawFunctionTree 328 Point connectFrom = new Point(visualTreeNode.X + visualTreeNode.Width / 2, visualTreeNode.Y + visualTreeNode.Height); 329 int[] xBoundaries = new int[node.SubtreeCount + 1]; 330 xBoundaries[0] = x; 331 for (int i = 0; i < node.SubtreeCount; i++) { 332 xBoundaries[i + 1] = (int)(xBoundaries[i] + (width * (double)node.GetSubtree(i).GetLength()) / (node.GetLength() - 1)); 333 DrawFunctionTree(node.GetSubtree(i), graphics, xBoundaries[i], y + height, xBoundaries[i + 1] - xBoundaries[i], height, connectFrom); 334 } 335 } 336 } 337 338 protected void DrawTreeNode(VisualSymbolicExpressionTreeNode visualTreeNode) { 339 using (var graphics = Graphics.FromImage(image)) { 340 graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; 341 graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; 342 DrawTreeNode(graphics, visualTreeNode); 343 } 344 } 345 346 protected void DrawTreeNode(Graphics graphics, VisualSymbolicExpressionTreeNode visualTreeNode) { 319 } 320 } 321 322 protected void DrawTreeNode(Graphics graphics, VisualTreeNode<ISymbolicExpressionTreeNode> visualTreeNode) { 347 323 graphics.Clip = new Region(new Rectangle(visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width + 1, visualTreeNode.Height + 1)); 348 324 graphics.Clear(backgroundColor); 349 var node = visualTreeNode. SymbolicExpressionTreeNode;325 var node = visualTreeNode.Content; 350 326 using (var textBrush = new SolidBrush(visualTreeNode.TextColor)) 351 327 using (var nodeLinePen = new Pen(visualTreeNode.LineColor)) … … 364 340 } 365 341 } 342 343 protected void DrawLine(Graphics graphics, VisualTreeNode<ISymbolicExpressionTreeNode> startNode, VisualTreeNode<ISymbolicExpressionTreeNode> endNode) { 344 var origin = new Point(startNode.X + startNode.Width / 2, startNode.Y + startNode.Height); 345 var target = new Point(endNode.X + endNode.Width / 2, endNode.Y); 346 graphics.Clip = new Region(new Rectangle(Math.Min(origin.X, target.X), origin.Y, Math.Max(origin.X, target.X), target.Y)); 347 var visualLine = GetVisualSymbolicExpressionTreeNodeConnection(startNode.Content, endNode.Content); 348 using (var linePen = new Pen(visualLine.LineColor)) { 349 linePen.DashStyle = visualLine.DashStyle; 350 graphics.DrawLine(linePen, origin, target); 351 } 352 } 366 353 #endregion 367 368 354 #region save image 369 355 private void saveImageToolStripMenuItem_Click(object sender, EventArgs e) { … … 376 362 } 377 363 378 p rivatevoid SaveImageAsBitmap(string filename) {364 public void SaveImageAsBitmap(string filename) { 379 365 if (tree == null) return; 380 366 Image image = new Bitmap(Width, Height); 381 367 using (Graphics g = Graphics.FromImage(image)) { 382 int height = this.Height / tree.Depth; 383 DrawFunctionTree(tree, g, 0, 0, Width, height); 368 DrawFunctionTree(g, preferredNodeWidth, preferredNodeHeight, minHorizontalDistance, minVerticalDistance); 384 369 } 385 370 image.Save(filename); 386 371 } 387 372 388 p rivatevoid SaveImageAsEmf(string filename) {373 public void SaveImageAsEmf(string filename) { 389 374 if (tree == null) return; 390 375 using (Graphics g = CreateGraphics()) { 391 376 using (Metafile file = new Metafile(filename, g.GetHdc())) { 392 377 using (Graphics emfFile = Graphics.FromImage(file)) { 393 int height = this.Height / tree.Depth; 394 DrawFunctionTree(tree, emfFile, 0, 0, Width, height); 378 DrawFunctionTree(emfFile, preferredNodeWidth, preferredNodeHeight, minHorizontalDistance, minVerticalDistance); 395 379 } 396 380 } … … 399 383 } 400 384 #endregion 385 #region export pgf/tikz 386 private void exportLatexToolStripMenuItem_Click(object sender, EventArgs e) { 387 var t = Tree; 388 if (t == null) return; 389 using (var dialog = new SaveFileDialog { Filter = "Tex (*.tex)|*.tex" }) { 390 if (dialog.ShowDialog() != DialogResult.OK) return; 391 string filename = dialog.FileName.ToLower(); 392 var formatter = new SymbolicExpressionTreeLatexFormatter(); 393 File.WriteAllText(filename, formatter.Format(t)); 394 } 395 } 396 #endregion 397 398 private void reingoldTilfordToolStripMenuItem_Click(object sender, EventArgs e) { 399 minHorizontalDistance = 30; 400 minVerticalDistance = 30; 401 layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>(n => n.Subtrees) { 402 NodeWidth = preferredNodeWidth, 403 NodeHeight = preferredNodeHeight, 404 HorizontalSpacing = minHorizontalDistance, 405 VerticalSpacing = minVerticalDistance 406 }; 407 reingoldTilfordToolStripMenuItem.Checked = true; 408 boxesToolStripMenuItem.Checked = false; 409 Repaint(); 410 } 411 412 private void boxesToolStripMenuItem_Click(object sender, EventArgs e) { 413 minHorizontalDistance = 5; 414 minVerticalDistance = 5; 415 layoutEngine = new BoxesLayoutEngine<ISymbolicExpressionTreeNode>(n => n.Subtrees, n => n.GetLength(), n => n.GetDepth()) { 416 NodeWidth = preferredNodeWidth, 417 NodeHeight = preferredNodeHeight, 418 HorizontalSpacing = minHorizontalDistance, 419 VerticalSpacing = minVerticalDistance 420 }; 421 reingoldTilfordToolStripMenuItem.Checked = false; 422 boxesToolStripMenuItem.Checked = true; 423 Repaint(); 424 } 401 425 } 402 426 }
Note: See TracChangeset
for help on using the changeset viewer.