Free cookie consent management tool by TermsFeed Policy Generator

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

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

#1772: Small improvements to FragmentGraphView, moved tracking classes to separate folder.

File size: 6.8 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.Root = node.Content.Root;
53        var tileNode = new TileLayoutNode { Tile = tile };
54        tileDictionary.Add(node, tileNode);
55      }
56      foreach (var node in Content.Nodes.Where(n => n.Children.Any())) {
57        var layoutNode = tileDictionary[node];
58        layoutNode.Children = new List<TileLayoutNode>(node.Children.Select(x => tileDictionary[x]));
59      }
60    }
61
62    private void Draw() {
63      var chart = symbolicExpressionChartControl.Chart;
64      var nodes = Content.Nodes.ToList();
65      var root = nodes[0];
66      var fragmentRoot = tileDictionary[root];
67      int maxTileWidth = 0, maxTileHeight = 0;
68      var tiles = nodes.Select(x => tileDictionary[x].Tile).ToList();
69
70      foreach (var tile in tiles) {
71        var size = tile.Size;
72        if (maxTileWidth < size.Width) maxTileWidth = size.Width;
73        if (maxTileHeight < size.Height) maxTileHeight = size.Height;
74      }
75      layoutEngine.NodeWidth = maxTileWidth;
76      layoutEngine.NodeHeight = maxTileHeight;
77      layoutEngine.HorizontalSpacing = PreferredHorizontalSpacing;
78      layoutEngine.VerticalSpacing = PreferredVerticalSpacing;
79
80      var visualNodes = layoutEngine.CalculateLayout(fragmentRoot);
81
82      symbolicExpressionChartControl.UpdateEnabled = false;
83      foreach (var visualNode in visualNodes) {
84        var tile = visualNode.Content.Tile;
85        tile.Position = new Point(visualNode.X, visualNode.Y);
86        symbolicExpressionChartControl.Add(tile);
87      }
88
89      // add connections between the tiles
90      foreach (var node in nodes) {
91        var aTile = tileDictionary[node].Tile;
92        var aSize = aTile.Size;
93        var aPos = aTile.Position;
94
95        // mark swapped fragment
96        if (node.Content.Index != 0) {
97          var subtree = node.Content.Root.NodeAt(node.Content.Index);
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 = new Pen(Color.RoyalBlue);
104              }
105            }
106          }
107        }
108
109        // mark the subtree that was replaced by the fragment
110        if (node.Children.Any() && node.Content.Index != 0) {
111          var child = node.Children.First();
112          {
113            var subtree = child.Content.Root.NodeAt(node.Content.Index);
114            var tile = tileDictionary[child].Tile;
115            foreach (var s in subtree.IterateNodesPrefix()) {
116              var primitive = tile.GetPrimitive(s);
117              if (primitive != null) {
118                var rpb = primitive as RectangularPrimitiveBase;
119                if (rpb != null) {
120                  rpb.Pen = new Pen(Color.DarkOrange);
121                }
122              }
123            }
124          }
125        }
126
127        foreach (var child in node.Children) {
128          var bTile = tileDictionary[child].Tile;
129          var bSize = bTile.Size;
130          var bPos = bTile.Position;
131
132          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));
133          symbolicExpressionChartControl.Add(line);
134
135
136        }
137      }
138      symbolicExpressionChartControl.UpdateEnabled = true;
139      symbolicExpressionChartControl.EnforceUpdate();
140    }
141
142    protected override void DeregisterContentEvents() {
143      // TODO: Deregister your event handlers here
144      base.DeregisterContentEvents();
145    }
146
147    protected override void RegisterContentEvents() {
148      base.RegisterContentEvents();
149      // TODO: Register your event handlers here
150    }
151
152    #region Event Handlers (Content)
153    // TODO: Put event handlers of the content here
154    protected override void OnContentChanged() {
155      base.OnContentChanged();
156      if (Content != null) {
157        MakeTiles();
158        Draw();
159      }
160    }
161    #endregion
162
163    protected override void SetEnabledStateOfControls() {
164      base.SetEnabledStateOfControls();
165      // TODO: Enable or disable controls based on whether the content is null or the view is set readonly
166    }
167
168    #region Event Handlers (child controls)
169
170    // TODO: Put event handlers of child controls here.
171
172    #endregion
173  }
174
175  internal class TileLayoutNode {
176    public SymbolicExpressionTreeTile Tile { get; set; }
177
178    private List<TileLayoutNode> children;
179    public IEnumerable<TileLayoutNode> Children {
180      get { return children ?? Enumerable.Empty<TileLayoutNode>(); }
181      set { children = value.ToList(); }
182    }
183  }
184}
Note: See TracBrowser for help on using the repository browser.