Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1772: Added default font, pen, and brush for the graphical components (the idea is to save memory by sharing default pens and brushes - not allocating new ones all the time), added support for tracing mutation operations

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