Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.3/SymbolicExpressionTreeChart.cs @ 4019

Last change on this file since 4019 was 3915, checked in by mkommend, 14 years ago

implemented InteractiveSymbolicRegressionSolutionSimplifierView and fixed lots of minor bugs in the DataAnalysis and DataAnalysis.Views project (ticket #1010)

File size: 12.1 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.ComponentModel;
25using System.Drawing;
26using System.Data;
27using System.Linq;
28using System.Text;
29using System.Windows.Forms;
30
31namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views {
32  public sealed partial class SymbolicExpressionTreeChart : UserControl {
33    private Image image;
34    private StringFormat stringFormat;
35    private Dictionary<SymbolicExpressionTreeNode, VisualSymbolicExpressionTreeNode> visualTreeNodes;
36
37    public SymbolicExpressionTreeChart() {
38      InitializeComponent();
39      this.image = new Bitmap(Width, Height);
40      this.stringFormat = new StringFormat();
41      this.stringFormat.Alignment = StringAlignment.Center;
42      this.stringFormat.LineAlignment = StringAlignment.Center;
43      this.spacing = 5;
44      this.lineColor = Color.Black;
45      this.backgroundColor = Color.White;
46      this.textFont = new Font("Times New Roman", 8);
47    }
48
49    public SymbolicExpressionTreeChart(SymbolicExpressionTree tree)
50      : this() {
51      this.Tree = tree;
52    }
53
54    private int spacing;
55    public int Spacing {
56      get { return this.spacing; }
57      set {
58        this.spacing = value;
59        this.Repaint();
60      }
61    }
62
63    private Color lineColor;
64    public Color LineColor {
65      get { return this.lineColor; }
66      set {
67        this.lineColor = value;
68        this.Repaint();
69      }
70    }
71
72    private Color backgroundColor;
73    public Color BackgroundColor {
74      get { return this.backgroundColor; }
75      set {
76        this.backgroundColor = value;
77        this.Repaint();
78      }
79    }
80
81    private Font textFont;
82    public Font TextFont {
83      get { return this.textFont; }
84      set {
85        this.textFont = value;
86        this.Repaint();
87      }
88    }
89
90    private SymbolicExpressionTree tree;
91    public SymbolicExpressionTree Tree {
92      get { return this.tree; }
93      set {
94        tree = value;
95        visualTreeNodes = new Dictionary<SymbolicExpressionTreeNode, VisualSymbolicExpressionTreeNode>();
96        if (tree != null) {
97          foreach (SymbolicExpressionTreeNode node in tree.IterateNodesPrefix())
98            visualTreeNodes[node] = new VisualSymbolicExpressionTreeNode(node);
99        }
100        Repaint();
101      }
102    }
103
104    protected override void OnPaint(PaintEventArgs e) {
105      base.OnPaint(e);
106      e.Graphics.DrawImage(image, 0, 0);
107    }
108    protected override void OnResize(EventArgs e) {
109      base.OnResize(e);
110      if (this.Width == 0 || this.Height == 0)
111        this.image = new Bitmap(1, 1);
112      else
113        this.image = new Bitmap(Width, Height);
114      this.Repaint();
115    }
116
117    public void Repaint() {
118      this.GenerateImage();
119      this.Refresh();
120    }
121
122    private void GenerateImage() {
123      using (Graphics graphics = Graphics.FromImage(image)) {
124        graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
125        graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
126        graphics.Clear(backgroundColor);
127        if (tree != null) {
128          int height = this.Height / tree.Height;
129          DrawFunctionTree(tree, graphics, 0, 0, this.Width, height);
130        }
131      }
132    }
133
134    public VisualSymbolicExpressionTreeNode GetVisualSymbolicExpressionTreeNode(SymbolicExpressionTreeNode symbolicExpressionTreeNode) {
135      if (visualTreeNodes.ContainsKey(symbolicExpressionTreeNode))
136        return visualTreeNodes[symbolicExpressionTreeNode];
137      return null;
138    }
139
140    #region events
141    public event MouseEventHandler SymbolicExpressionTreeNodeClicked;
142    private void OnSymbolicExpressionTreeNodeClicked(object sender, MouseEventArgs e) {
143      var clicked = SymbolicExpressionTreeNodeClicked;
144      if (clicked != null)
145        clicked(sender, e);
146    }
147
148    private void SymbolicExpressionTreeChart_MouseClick(object sender, MouseEventArgs e) {
149      VisualSymbolicExpressionTreeNode visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
150      if (visualTreeNode != null)
151        OnSymbolicExpressionTreeNodeClicked(visualTreeNode, e);
152    }
153
154    public event MouseEventHandler SymbolicExpressionTreeNodeDoubleClicked;
155    private void OnSymbolicExpressionTreeNodeDoubleClicked(object sender, MouseEventArgs e) {
156      var doubleClicked = SymbolicExpressionTreeNodeDoubleClicked;
157      if (doubleClicked != null)
158        doubleClicked(sender, e);
159    }
160
161    private void SymbolicExpressionTreeChart_MouseDoubleClick(object sender, MouseEventArgs e) {
162      VisualSymbolicExpressionTreeNode visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
163      if (visualTreeNode != null)
164        OnSymbolicExpressionTreeNodeDoubleClicked(visualTreeNode, e);
165    }
166
167    public event ItemDragEventHandler SymbolicExpressionTreeNodeDrag;
168    private void OnSymbolicExpressionTreeNodeDragDrag(object sender, ItemDragEventArgs e) {
169      var dragged = SymbolicExpressionTreeNodeDrag;
170      if (dragged != null)
171        dragged(sender, e);
172    }
173
174    private VisualSymbolicExpressionTreeNode draggedSymbolicExpressionTree;
175    private MouseButtons dragButtons;
176    private void SymbolicExpressionTreeChart_MouseDown(object sender, MouseEventArgs e) {
177      this.dragButtons = e.Button;
178      this.draggedSymbolicExpressionTree = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
179    }
180    private void SymbolicExpressionTreeChart_MouseUp(object sender, MouseEventArgs e) {
181      this.draggedSymbolicExpressionTree = null;
182      this.dragButtons = MouseButtons.None;
183    }
184
185    private void SymbolicExpressionTreeChart_MouseMove(object sender, MouseEventArgs e) {
186      VisualSymbolicExpressionTreeNode visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);
187      if (draggedSymbolicExpressionTree != null &&
188        draggedSymbolicExpressionTree != visualTreeNode) {
189        OnSymbolicExpressionTreeNodeDragDrag(draggedSymbolicExpressionTree, new ItemDragEventArgs(dragButtons, draggedSymbolicExpressionTree));
190        draggedSymbolicExpressionTree = null;
191      } else if (draggedSymbolicExpressionTree == null &&
192        visualTreeNode != null) {
193        string tooltipText = visualTreeNode.ToolTip;
194        if (this.toolTip.GetToolTip(this) != tooltipText)
195          this.toolTip.SetToolTip(this, tooltipText);
196
197      } else if (visualTreeNode == null)
198        this.toolTip.SetToolTip(this, "");
199    }
200
201    private VisualSymbolicExpressionTreeNode FindVisualSymbolicExpressionTreeNodeAt(int x, int y) {
202      foreach (var visualTreeNode in visualTreeNodes.Values) {
203        if (x >= visualTreeNode.X && x <= visualTreeNode.X + visualTreeNode.Width &&
204            y >= visualTreeNode.Y && y <= visualTreeNode.Y + visualTreeNode.Height)
205          return visualTreeNode;
206      }
207      return null;
208    }
209    #endregion
210
211    #region methods for painting the symbolic expression tree
212    private void DrawFunctionTree(SymbolicExpressionTree tree, Graphics graphics, int x, int y, int width, int height) {
213      DrawFunctionTree(tree.Root, graphics, x, y, width, height, Point.Empty);
214    }
215
216    /// <summary>
217    ///
218    /// </summary>
219    /// <param name="functionTree"> functiontree to draw</param>
220    /// <param name="graphics">graphics object to draw on</param>
221    /// <param name="x">x coordinate of drawing area</param>
222    /// <param name="y">y coordinate of drawing area</param>
223    /// <param name="width">width of drawing area</param>
224    /// <param name="height">height of drawing area</param>
225    private void DrawFunctionTree(SymbolicExpressionTreeNode node, Graphics graphics, int x, int y, int width, int height, Point connectionPoint) {
226      VisualSymbolicExpressionTreeNode visualTreeNode = visualTreeNodes[node];
227      float center_x = x + width / 2;
228      float center_y = y + height / 2;
229      int actualWidth = width - spacing;
230      int actualHeight = height - spacing;
231
232      SolidBrush textBrush = new SolidBrush(visualTreeNode.TextColor);
233      Pen linePen = new Pen(this.lineColor);
234      Pen nodeLinePen = new Pen(visualTreeNode.LineColor);
235      SolidBrush nodeFillBrush = new SolidBrush(visualTreeNode.FillColor);
236
237      //calculate size of node
238      if (actualWidth >= visualTreeNode.PreferredWidth && actualHeight >= visualTreeNode.PreferredHeight) {
239        visualTreeNode.Width = visualTreeNode.PreferredWidth;
240        visualTreeNode.Height = visualTreeNode.PreferredHeight;
241        visualTreeNode.X = (int)center_x - visualTreeNode.Width / 2;
242        visualTreeNode.Y = (int)center_y - visualTreeNode.Height / 2;
243      }
244        //width too small to draw in desired sized
245      else if (actualWidth < visualTreeNode.PreferredWidth && actualHeight >= visualTreeNode.PreferredHeight) {
246        visualTreeNode.Width = actualWidth;
247        visualTreeNode.Height = visualTreeNode.PreferredHeight;
248        visualTreeNode.X = x;
249        visualTreeNode.Y = (int)center_y - visualTreeNode.Height / 2;
250      }
251        //height too small to draw in desired sized
252      else if (actualWidth >= visualTreeNode.PreferredWidth && actualHeight < visualTreeNode.PreferredHeight) {
253        visualTreeNode.Width = visualTreeNode.PreferredWidth;
254        visualTreeNode.Height = actualHeight;
255        visualTreeNode.X = (int)center_x - visualTreeNode.Width / 2;
256        visualTreeNode.Y = y;
257      }
258        //width and height too small to draw in desired size
259      else {
260        visualTreeNode.Width = actualWidth;
261        visualTreeNode.Height = actualHeight;
262        visualTreeNode.X = x;
263        visualTreeNode.Y = y;
264      }
265
266      //draw terminal node
267      if (node.SubTrees.Count == 0) {
268        graphics.FillRectangle(nodeFillBrush, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height);
269        graphics.DrawRectangle(nodeLinePen, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height);
270      } else {
271        graphics.FillEllipse(nodeFillBrush, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height);
272        graphics.DrawEllipse(nodeLinePen, visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height);
273      }
274
275      //draw name of symbol
276      var text = node.ToString();
277      graphics.DrawString(text, textFont, textBrush, new RectangleF(visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width, visualTreeNode.Height), stringFormat);
278
279      //draw connection line to parent node
280      if (!connectionPoint.IsEmpty)
281        graphics.DrawLine(linePen, connectionPoint, new Point(visualTreeNode.X + visualTreeNode.Width / 2, visualTreeNode.Y));
282
283      //calculate areas for the subtrees according to their tree size and call drawFunctionTree
284      Point connectFrom = new Point(visualTreeNode.X + visualTreeNode.Width / 2, visualTreeNode.Y + visualTreeNode.Height);
285      int[] xBoundaries = new int[node.SubTrees.Count + 1];
286      xBoundaries[0] = x;
287      for (int i = 0; i < node.SubTrees.Count; i++) {
288        xBoundaries[i + 1] = (int)(xBoundaries[i] + (width * (double)node.SubTrees[i].GetSize()) / (node.GetSize() - 1));
289        DrawFunctionTree(node.SubTrees[i], graphics, xBoundaries[i], y + height,
290          xBoundaries[i + 1] - xBoundaries[i], height, connectFrom);
291      }
292    }
293    #endregion
294  }
295}
Note: See TracBrowser for help on using the repository browser.