Changeset 10520 for trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionTreeChart.cs
- Timestamp:
- 02/28/14 11:56:15 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views/3.4/SymbolicExpressionTreeChart.cs
r10499 r10520 33 33 private Image image; 34 34 private readonly StringFormat stringFormat; 35 private Dictionary<ISymbolicExpressionTreeNode, VisualSymbolicExpressionTreeNode> visualTreeNodes; 36 private Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualSymbolicExpressionTreeNodeConnection> visualLines; 37 private readonly ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode> layoutEngine; 38 private readonly SymbolicExpressionTreeLayoutAdapter layoutAdapter; 35 private Dictionary<ISymbolicExpressionTreeNode, VisualTreeNode<ISymbolicExpressionTreeNode>> visualTreeNodes; 36 private Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualTreeNodeConnection> visualLines; 37 private ILayoutEngine<ISymbolicExpressionTreeNode> layoutEngine; 39 38 40 39 private const int preferredNodeWidth = 70; 41 40 private const int preferredNodeHeight = 46; 42 private const int minHorizontalDistance = 20; 43 private const int minVerticalDistance = 20; 44 41 private const int minHorizontalDistance = 30; 42 private const int minVerticalDistance = 30; 45 43 46 44 public SymbolicExpressionTreeChart() { … … 52 50 this.backgroundColor = Color.White; 53 51 this.textFont = new Font(FontFamily.GenericSansSerif, 12); 54 layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>(); 55 layoutAdapter = new SymbolicExpressionTreeLayoutAdapter(); 52 // layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode> { 53 layoutEngine = new BoxesLayoutEngine<ISymbolicExpressionTreeNode> { 54 NodeWidth = preferredNodeWidth, 55 NodeHeight = preferredNodeHeight, 56 HorizontalSpacing = minHorizontalDistance, 57 VerticalSpacing = minVerticalDistance 58 }; 56 59 } 57 60 58 61 public SymbolicExpressionTreeChart(ISymbolicExpressionTree tree) 59 62 : this() { 60 layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode>();61 layoutAdapter = new SymbolicExpressionTreeLayoutAdapter();62 63 this.Tree = tree; 63 64 } … … 105 106 set { 106 107 tree = value; 107 visualTreeNodes = new Dictionary<ISymbolicExpressionTreeNode, VisualSymbolicExpressionTreeNode>();108 visualLines = new Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualSymbolicExpressionTreeNodeConnection>();109 108 if (tree != null) { 110 IEnumerable<ISymbolicExpressionTreeNode> nodes; 111 if (tree.Root.SubtreeCount == 1) nodes = tree.Root.GetSubtree(0).IterateNodesPrefix(); 112 else nodes = tree.Root.IterateNodesPrefix(); 113 foreach (ISymbolicExpressionTreeNode node in nodes) { 114 visualTreeNodes[node] = new VisualSymbolicExpressionTreeNode(node); 115 if (node.Parent != null) visualLines[Tuple.Create(node.Parent, node)] = new VisualSymbolicExpressionTreeNodeConnection(); 116 } 117 } 118 Repaint(); 109 Repaint(); 110 } 119 111 } 120 112 } … … 160 152 } 161 153 162 public void RepaintNode(Visual SymbolicExpressionTreeNodevisualNode) {154 public void RepaintNode(VisualTreeNode<ISymbolicExpressionTreeNode> visualNode) { 163 155 if (!suspendRepaint) { 164 156 using (var graphics = Graphics.FromImage(image)) { … … 182 174 } 183 175 184 public Visual SymbolicExpressionTreeNodeGetVisualSymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode) {176 public VisualTreeNode<ISymbolicExpressionTreeNode> GetVisualSymbolicExpressionTreeNode(ISymbolicExpressionTreeNode symbolicExpressionTreeNode) { 185 177 if (visualTreeNodes.ContainsKey(symbolicExpressionTreeNode)) 186 178 return visualTreeNodes[symbolicExpressionTreeNode]; … … 188 180 } 189 181 190 public Visual SymbolicExpressionTreeNodeConnection GetVisualSymbolicExpressionTreeNodeConnection(ISymbolicExpressionTreeNode parent, ISymbolicExpressionTreeNode child) {182 public VisualTreeNodeConnection GetVisualSymbolicExpressionTreeNodeConnection(ISymbolicExpressionTreeNode parent, ISymbolicExpressionTreeNode child) { 191 183 if (child.Parent != parent) throw new ArgumentException(); 192 184 var key = Tuple.Create(parent, child); 193 Visual SymbolicExpressionTreeNodeConnection connection = null;185 VisualTreeNodeConnection connection = null; 194 186 visualLines.TryGetValue(key, out connection); 195 187 return connection; … … 205 197 206 198 protected virtual void SymbolicExpressionTreeChart_MouseClick(object sender, MouseEventArgs e) { 207 VisualSymbolicExpressionTreeNodevisualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);199 var visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y); 208 200 if (visualTreeNode != null) { 209 201 OnSymbolicExpressionTreeNodeClicked(visualTreeNode, e); … … 219 211 220 212 protected virtual void SymbolicExpressionTreeChart_MouseDoubleClick(object sender, MouseEventArgs e) { 221 Visual SymbolicExpressionTreeNodevisualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);213 VisualTreeNode<ISymbolicExpressionTreeNode> visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y); 222 214 if (visualTreeNode != null) 223 215 OnSymbolicExpressionTreeNodeDoubleClicked(visualTreeNode, e); … … 231 223 } 232 224 233 private Visual SymbolicExpressionTreeNodedraggedSymbolicExpressionTree;225 private VisualTreeNode<ISymbolicExpressionTreeNode> draggedSymbolicExpressionTree; 234 226 private MouseButtons dragButtons; 235 227 private void SymbolicExpressionTreeChart_MouseDown(object sender, MouseEventArgs e) { … … 243 235 244 236 private void SymbolicExpressionTreeChart_MouseMove(object sender, MouseEventArgs e) { 245 Visual SymbolicExpressionTreeNodevisualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y);237 VisualTreeNode<ISymbolicExpressionTreeNode> visualTreeNode = FindVisualSymbolicExpressionTreeNodeAt(e.X, e.Y); 246 238 if (draggedSymbolicExpressionTree != null && 247 239 draggedSymbolicExpressionTree != visualTreeNode) { … … 258 250 } 259 251 260 public Visual SymbolicExpressionTreeNodeFindVisualSymbolicExpressionTreeNodeAt(int x, int y) {252 public VisualTreeNode<ISymbolicExpressionTreeNode> FindVisualSymbolicExpressionTreeNodeAt(int x, int y) { 261 253 foreach (var visualTreeNode in visualTreeNodes.Values) { 262 254 if (x >= visualTreeNode.X && x <= visualTreeNode.X + visualTreeNode.Width && … … 269 261 270 262 #region methods for painting the symbolic expression tree 271 private void DrawFunctionTree(ISymbolicExpressionTree symbolicExpressionTree, Graphics graphics, int preferredWidth, int preferredHeight, int minHDistance, int minVDistance) { 272 var layoutNodes = layoutAdapter.Convert(symbolicExpressionTree).ToList(); 273 if(symbolicExpressionTree.Root.SubtreeCount==1) layoutNodes.RemoveAt(0); 274 layoutEngine.Reset(); 275 layoutEngine.Root = layoutNodes[0]; 276 layoutEngine.AddNodes(layoutNodes); 277 layoutEngine.MinHorizontalSpacing = (preferredWidth + minHDistance); 278 layoutEngine.MinVerticalSpacing = (preferredHeight + minVDistance); 279 layoutEngine.CalculateLayout(); 280 var bounds = layoutEngine.Bounds(); 281 282 double verticalScalingFactor = 1.0; 283 double layoutHeight = (bounds.Height + preferredHeight); 284 if (this.Height < layoutHeight) 285 verticalScalingFactor = this.Height / layoutHeight; 286 287 double horizontalScalingFactor = 1.0; 288 double layoutWidth = (bounds.Width + preferredWidth); 289 if (this.Width < layoutWidth) 290 horizontalScalingFactor = this.Width / layoutWidth; 291 292 double horizontalOffset; 293 if (this.Width > layoutWidth) 294 horizontalOffset = (this.Width - layoutWidth) / 2.0; 295 else 296 horizontalOffset = preferredWidth / 2.0; 297 298 var levels = layoutNodes.GroupBy(n => n.Level, n => n).ToList(); 299 for (int i = levels.Count - 1; i >= 0; --i) { 300 var nodes = levels[i].ToList(); 301 302 double minSpacing = double.MaxValue; 303 if (nodes.Count > 1) { 304 for (int j = 1; j < nodes.Count() - 1; ++j) { 305 var distance = nodes[j].X - nodes[j - 1].X; // guaranteed to be > 0 306 if (minSpacing > distance) minSpacing = distance; 307 } 308 } 309 minSpacing *= horizontalScalingFactor; 310 311 int minWidth = (int)Math.Round(preferredWidth * horizontalScalingFactor); 312 int width = (int)Math.Min(minSpacing, preferredWidth) - 2; // leave some pixels so that node margins don't overlap 313 314 foreach (var layoutNode in nodes) { 315 var visualNode = visualTreeNodes[layoutNode.Content]; 316 visualNode.Width = width; 317 visualNode.Height = (int)Math.Round(preferredHeight * verticalScalingFactor); 318 visualNode.X = (int)Math.Round((layoutNode.X + horizontalOffset) * horizontalScalingFactor + (minWidth - width) / 2.0); 319 visualNode.Y = (int)Math.Round(layoutNode.Y * verticalScalingFactor); 320 DrawTreeNode(graphics, visualNode); 321 } 322 } 323 // draw node connections 324 foreach (var visualNode in visualTreeNodes.Values) { 325 var node = visualNode.SymbolicExpressionTreeNode; 263 private void DrawFunctionTree(ISymbolicExpressionTree symbExprTree, Graphics graphics, int preferredWidth, int preferredHeight, int minHDistance, int minVDistance) { 264 var root = symbExprTree.Root; 265 var actualRoot = root.SubtreeCount == 1 ? root.GetSubtree(0) : root; 266 layoutEngine.NodeWidth = preferredWidth; 267 layoutEngine.NodeHeight = preferredHeight; 268 layoutEngine.HorizontalSpacing = minHDistance; 269 layoutEngine.VerticalSpacing = minVDistance; 270 layoutEngine.Initialize(actualRoot, n => n.Subtrees, n => n.GetLength(), n => n.GetDepth()); 271 layoutEngine.CalculateLayout(Width, Height); 272 273 var visualNodes = layoutEngine.GetVisualNodes().ToList(); 274 visualTreeNodes = visualNodes.ToDictionary(x => x.Content, x => x); 275 visualLines = new Dictionary<Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>, VisualTreeNodeConnection>(); 276 foreach (var node in visualNodes.Select(n => n.Content)) { 277 foreach (var subtree in node.Subtrees) { 278 visualLines.Add(new Tuple<ISymbolicExpressionTreeNode, ISymbolicExpressionTreeNode>(node, subtree), new VisualTreeNodeConnection()); 279 } 280 } 281 // draw nodes and connections 282 foreach (var visualNode in visualNodes) { 283 DrawTreeNode(visualNode); 284 var node = visualNode.Content; 326 285 foreach (var subtree in node.Subtrees) { 327 286 var visualLine = GetVisualSymbolicExpressionTreeNodeConnection(node, subtree); … … 338 297 } 339 298 340 protected void DrawTreeNode(Visual SymbolicExpressionTreeNodevisualTreeNode) {299 protected void DrawTreeNode(VisualTreeNode<ISymbolicExpressionTreeNode> visualTreeNode) { 341 300 using (var graphics = Graphics.FromImage(image)) { 342 301 graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; … … 346 305 } 347 306 348 protected void DrawTreeNode(Graphics graphics, Visual SymbolicExpressionTreeNodevisualTreeNode) {307 protected void DrawTreeNode(Graphics graphics, VisualTreeNode<ISymbolicExpressionTreeNode> visualTreeNode) { 349 308 graphics.Clip = new Region(new Rectangle(visualTreeNode.X, visualTreeNode.Y, visualTreeNode.Width + 1, visualTreeNode.Height + 1)); 350 309 graphics.Clear(backgroundColor); 351 var node = visualTreeNode. SymbolicExpressionTreeNode;310 var node = visualTreeNode.Content; 352 311 using (var textBrush = new SolidBrush(visualTreeNode.TextColor)) 353 312 using (var nodeLinePen = new Pen(visualTreeNode.LineColor)) … … 408 367 } 409 368 #endregion 369 370 private void reingoldTilfordToolStripMenuItem_Click(object sender, EventArgs e) { 371 layoutEngine = new ReingoldTilfordLayoutEngine<ISymbolicExpressionTreeNode> { 372 NodeWidth = preferredNodeWidth, 373 NodeHeight = preferredNodeHeight, 374 HorizontalSpacing = minHorizontalDistance, 375 VerticalSpacing = minVerticalDistance 376 }; 377 Repaint(); 378 } 379 380 private void boxesToolStripMenuItem_Click(object sender, EventArgs e) { 381 layoutEngine = new BoxesLayoutEngine<ISymbolicExpressionTreeNode> { 382 NodeWidth = preferredNodeWidth, 383 NodeHeight = preferredNodeHeight, 384 HorizontalSpacing = minHorizontalDistance, 385 VerticalSpacing = minVerticalDistance 386 }; 387 Repaint(); 388 } 410 389 } 411 390 }
Note: See TracChangeset
for help on using the changeset viewer.