Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.EvolutionTracking/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/Tracking/FragmentGraphView.cs @ 10838

Last change on this file since 10838 was 10838, checked in by bburlacu, 10 years ago

#1772: Improved display of trees and fragments in the FragmentGraphView by displaying the whole tree and highlighting the subtree and the fragment inside it. Changed color scheme to look nicer.

File size: 8.2 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Drawing;
4using System.Linq;
5using HeuristicLab.Core.Views;
6using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
7using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views;
8using HeuristicLab.EvolutionTracking;
9using HeuristicLab.MainForm;
10using HeuristicLab.Visualization;
11
12namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views {
13  [View("FragmentGraphView")]
14  [Content(typeof(IGenealogyGraph<IFragment<ISymbolicExpressionTreeNode>>), IsDefaultView = true)]
15  public sealed partial class FragmentGraphView : ItemView {
16    private const int PreferredHorizontalSpacing = 10;
17    private const int PreferredVerticalSpacing = 25;
18
19    private ReingoldTilfordLayoutEngine<TileLayoutNode> layoutEngine;
20    private ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode> symbolicExpressionEngine;
21
22    private Dictionary<IGenealogyGraphNode<IFragment<ISymbolicExpressionTreeNode>>, TileLayoutNode> tileDictionary;
23
24    private SymbolicExpressionTreeTile Root { get; set; }
25
26    public new IGenealogyGraph<IFragment<ISymbolicExpressionTreeNode>> Content {
27      get { return (IGenealogyGraph<IFragment<ISymbolicExpressionTreeNode>>)base.Content; }
28      set { base.Content = value; }
29    }
30
31    public FragmentGraphView() {
32      InitializeComponent();
33
34      layoutEngine = new ReingoldTilfordLayoutEngine<TileLayoutNode>(n => n.Children) {
35        HorizontalSpacing = PreferredHorizontalSpacing,
36        VerticalSpacing = PreferredVerticalSpacing,
37      };
38      symbolicExpressionEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>(n => n.Subtrees) {
39        HorizontalSpacing = PreferredHorizontalSpacing,
40        VerticalSpacing = PreferredVerticalSpacing,
41        NodeWidth = 80,
42        NodeHeight = 40
43      };
44      tileDictionary = new Dictionary<IGenealogyGraphNode<IFragment<ISymbolicExpressionTreeNode>>, TileLayoutNode>();
45    }
46
47    private void MakeTiles() {
48      var chart = symbolicExpressionChartControl.Chart;
49      tileDictionary.Clear();
50      foreach (var node in Content.Nodes) {
51        var tile = new SymbolicExpressionTreeTile(chart);
52        tile.LayoutEngine = symbolicExpressionEngine;
53        tile.Label = "Generation " + node.Rank + Environment.NewLine +
54                     "Quality " + String.Format("{0:0.000}", node.Quality);
55        tile.Root = node.Content.Root;
56        var tileNode = new TileLayoutNode { Tile = tile };
57        tileDictionary.Add(node, tileNode);
58      }
59      foreach (var node in Content.Nodes.Where(n => n.Children.Any())) {
60        var layoutNode = tileDictionary[node];
61        layoutNode.Children = new List<TileLayoutNode>(node.Children.Select(x => tileDictionary[x]));
62      }
63    }
64
65    private void Draw() {
66      var chart = symbolicExpressionChartControl.Chart;
67      var nodes = Content.Nodes.ToList();
68      var root = nodes[0];
69      var fragmentRoot = tileDictionary[root];
70      int maxTileWidth = 0, maxTileHeight = 0;
71      var tiles = nodes.Select(x => tileDictionary[x].Tile).ToList();
72
73      foreach (var tile in tiles) {
74        var size = tile.Size;
75        if (maxTileWidth < size.Width) maxTileWidth = size.Width;
76        if (maxTileHeight < size.Height) maxTileHeight = size.Height;
77      }
78      layoutEngine.NodeWidth = maxTileWidth;
79      layoutEngine.NodeHeight = maxTileHeight;
80      layoutEngine.HorizontalSpacing = PreferredHorizontalSpacing;
81      layoutEngine.VerticalSpacing = PreferredVerticalSpacing;
82
83      var visualNodes = layoutEngine.CalculateLayout(fragmentRoot);
84
85      symbolicExpressionChartControl.UpdateEnabled = false;
86      foreach (var visualNode in visualNodes) {
87        var tile = visualNode.Content.Tile;
88        tile.Position = new Point(visualNode.X, visualNode.Y);
89        symbolicExpressionChartControl.Add(tile);
90      }
91
92      // add connections between the tiles
93      foreach (var node in nodes) {
94        var aTile = tileDictionary[node].Tile;
95        var aSize = aTile.Size;
96        var aPos = aTile.Position;
97
98        var fragment = node.Content;
99        if (fragment.Index1 > 0) {
100          var subtree = fragment.Root.NodeAt(fragment.Index1);
101          foreach (var s in subtree.IterateNodesPrefix()) {
102            var primitive = aTile.GetPrimitive(s);
103            if (primitive != null) {
104              var rpb = primitive as RectangularPrimitiveBase;
105              if (rpb != null) {
106                rpb.Pen = new Pen(Color.Black);
107              }
108            }
109          }
110        }
111        if (fragment.Index2 > 0) {
112          var subtree = fragment.Root.NodeAt(fragment.Index2);
113          foreach (var s in subtree.IterateNodesPrefix()) {
114            var primitive = aTile.GetPrimitive(s);
115            if (primitive != null) {
116              var rpb = primitive as RectangularPrimitiveBase;
117              if (rpb != null) {
118                rpb.Brush = new SolidBrush(Color.LightGray);
119              }
120            }
121          }
122        }
123
124        if (node.Parents.Any() && node == node.Parents.First().Children.First()) {
125          var parent = node.Parents.First();
126          var index = fragment.Index1 + (parent.Content.Index2 - parent.Content.Index1);
127          var subtree = fragment.Root.NodeAt(index);
128          var primitive = aTile.GetPrimitive(subtree);
129          primitive.Brush = new SolidBrush(Color.LightCoral);
130        }
131
132        foreach (var child in node.Children) {
133          var bTile = tileDictionary[child].Tile;
134          var bSize = bTile.Size;
135          var bPos = bTile.Position;
136
137          var line = new Line(chart, new PointD(aPos.X + aSize.Width / 2.0, aPos.Y + aSize.Height), new PointD(bPos.X + bSize.Width / 2.0, bPos.Y)) {
138            Pen = Pens.DimGray
139          };
140          symbolicExpressionChartControl.Add(line);
141
142          //          if (child == node.Children.First()) {
143          //            var subtree = child.Content.Root.NodeAt(fragment.Index2);
144          //            var primitive = bTile.GetPrimitive(subtree);
145          //            if (primitive != null) {
146          //              var rpb = primitive as RectangularPrimitiveBase;
147          //              if (rpb != null) {
148          //                rpb.Pen = new Pen(Color.RoyalBlue);
149          //              }
150          //            }
151          //          }
152        }
153      }
154      // center display on the root of the fragment graph
155      symbolicExpressionChartControl.Chart.Move(tileDictionary[root].Tile.Position.X, tileDictionary[root].Tile.Position.Y);
156      symbolicExpressionChartControl.UpdateEnabled = true;
157      symbolicExpressionChartControl.EnforceUpdate();
158    }
159
160    protected override void DeregisterContentEvents() {
161      // TODO: Deregister your event handlers here
162      base.DeregisterContentEvents();
163    }
164
165    protected override void RegisterContentEvents() {
166      base.RegisterContentEvents();
167      // TODO: Register your event handlers here
168    }
169
170    #region Event Handlers (Content)
171    // TODO: Put event handlers of the content here
172    protected override void OnContentChanged() {
173      base.OnContentChanged();
174      if (Content != null) {
175        MakeTiles();
176        Draw();
177      }
178    }
179    #endregion
180
181    protected override void SetEnabledStateOfControls() {
182      base.SetEnabledStateOfControls();
183      // TODO: Enable or disable controls based on whether the content is null or the view is set readonly
184    }
185
186    #region Event Handlers (child controls)
187
188    // TODO: Put event handlers of child controls here.
189
190    #endregion
191  }
192
193  internal static class Util {
194    internal static ISymbolicExpressionTreeNode NodeAt(this ISymbolicExpressionTree tree, int position) {
195      return NodeAt(tree.Root, position);
196    }
197    internal static ISymbolicExpressionTreeNode NodeAt(this ISymbolicExpressionTreeNode root, int position) {
198      return root.IterateNodesPrefix().ElementAt(position);
199    }
200  }
201
202  internal class TileLayoutNode {
203    public SymbolicExpressionTreeTile Tile { get; set; }
204
205    private List<TileLayoutNode> children;
206    public IEnumerable<TileLayoutNode> Children {
207      get { return children ?? Enumerable.Empty<TileLayoutNode>(); }
208      set { children = value.ToList(); }
209    }
210  }
211}
Note: See TracBrowser for help on using the repository browser.